xref: /freebsd/sys/dev/hwpmc/hwpmc_ppc970.c (revision 685dc743)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2013 Justin Hibbits
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  */
29 
30 #include <sys/cdefs.h>
31 #include <sys/param.h>
32 #include <sys/pmc.h>
33 #include <sys/pmckern.h>
34 #include <sys/systm.h>
35 
36 #include <machine/pmc_mdep.h>
37 #include <machine/spr.h>
38 #include <machine/cpu.h>
39 
40 #include "hwpmc_powerpc.h"
41 
42 #define PPC970_MAX_PMCS		8
43 #define PMC_PPC970_FLAG_PMCS	0x000000ff
44 
45 /* MMCR0, PMC1 is 8 bytes in, PMC2 is 1 byte in. */
46 #define PPC970_SET_MMCR0_PMCSEL(r, x, i) \
47 	((r & ~(0x1f << (7 * (1 - i) + 1))) | (x << (7 * (1 - i) + 1)))
48 /* MMCR1 has 6 PMC*SEL items (PMC3->PMC8), in sequence. */
49 #define PPC970_SET_MMCR1_PMCSEL(r, x, i) \
50 	((r & ~(0x1f << (5 * (7 - i) + 2))) | (x << (5 * (7 - i) + 2)))
51 
52 /* How PMC works on PPC970:
53  *
54  * Any PMC can count a direct event.  Indirect events are handled specially.
55  * Direct events: As published.
56  *
57  * Encoding 00 000 -- Add byte lane bit counters
58  *   MMCR1[24:31] -- select bit matching PMC being an adder.
59  * Bus events:
60  * PMCxSEL: 1x -- select from byte lane: 10 == lower lane (0/1), 11 == upper
61  * lane (2/3).
62  * PMCxSEL[2:4] -- bit in the byte lane selected.
63  *
64  * PMC[1,2,5,6] == lane 0/lane 2
65  * PMC[3,4,7,8] == lane 1,3
66  *
67  *
68  * Lanes:
69  * Lane 0 -- TTM0(FPU,ISU,IFU,VPU)
70  *           TTM1(IDU,ISU,STS)
71  *           LSU0 byte 0
72  *           LSU1 byte 0
73  * Lane 1 -- TTM0
74  *           TTM1
75  *           LSU0 byte 1
76  *           LSU1 byte 1
77  * Lane 2 -- TTM0
78  *           TTM1
79  *           LSU0 byte 2
80  *           LSU1 byte 2 or byte 6
81  * Lane 3 -- TTM0
82  *           TTM1
83  *           LSU0 byte 3
84  *           LSU1 byte 3 or byte 7
85  *
86  * Adders:
87  *  Add byte lane for PMC (above), bit 0+4, 1+5, 2+6, 3+7
88  */
89 
90 static struct pmc_ppc_event ppc970_event_codes[] = {
91 	{PMC_EV_PPC970_INSTR_COMPLETED,
92 	    .pe_flags = PMC_PPC970_FLAG_PMCS,
93 	    .pe_code = 0x09
94 	},
95 	{PMC_EV_PPC970_MARKED_GROUP_DISPATCH,
96 		.pe_flags = PMC_FLAG_PMC1,
97 		.pe_code = 0x2
98 	},
99 	{PMC_EV_PPC970_MARKED_STORE_COMPLETED,
100 		.pe_flags = PMC_FLAG_PMC1,
101 		.pe_code = 0x03
102 	},
103 	{PMC_EV_PPC970_GCT_EMPTY,
104 		.pe_flags = PMC_FLAG_PMC1,
105 		.pe_code = 0x04
106 	},
107 	{PMC_EV_PPC970_RUN_CYCLES,
108 		.pe_flags = PMC_FLAG_PMC1,
109 		.pe_code = 0x05
110 	},
111 	{PMC_EV_PPC970_OVERFLOW,
112 		.pe_flags = PMC_PPC970_FLAG_PMCS,
113 		.pe_code = 0x0a
114 	},
115 	{PMC_EV_PPC970_CYCLES,
116 		.pe_flags = PMC_PPC970_FLAG_PMCS,
117 		.pe_code = 0x0f
118 	},
119 	{PMC_EV_PPC970_THRESHOLD_TIMEOUT,
120 		.pe_flags = PMC_FLAG_PMC2,
121 		.pe_code = 0x3
122 	},
123 	{PMC_EV_PPC970_GROUP_DISPATCH,
124 		.pe_flags = PMC_FLAG_PMC2,
125 		.pe_code = 0x4
126 	},
127 	{PMC_EV_PPC970_BR_MARKED_INSTR_FINISH,
128 		.pe_flags = PMC_FLAG_PMC2,
129 		.pe_code = 0x5
130 	},
131 	{PMC_EV_PPC970_GCT_EMPTY_BY_SRQ_FULL,
132 		.pe_flags = PMC_FLAG_PMC2,
133 		.pe_code = 0xb
134 	},
135 	{PMC_EV_PPC970_STOP_COMPLETION,
136 		.pe_flags = PMC_FLAG_PMC3,
137 		.pe_code = 0x1
138 	},
139 	{PMC_EV_PPC970_LSU_EMPTY,
140 		.pe_flags = PMC_FLAG_PMC3,
141 		.pe_code = 0x2
142 	},
143 	{PMC_EV_PPC970_MARKED_STORE_WITH_INTR,
144 		.pe_flags = PMC_FLAG_PMC3,
145 		.pe_code = 0x3
146 	},
147 	{PMC_EV_PPC970_CYCLES_IN_SUPER,
148 		.pe_flags = PMC_FLAG_PMC3,
149 		.pe_code = 0x4
150 	},
151 	{PMC_EV_PPC970_VPU_MARKED_INSTR_COMPLETED,
152 		.pe_flags = PMC_FLAG_PMC3,
153 		.pe_code = 0x5
154 	},
155 	{PMC_EV_PPC970_FXU0_IDLE_FXU1_BUSY,
156 		.pe_flags = PMC_FLAG_PMC4,
157 		.pe_code = 0x2
158 	},
159 	{PMC_EV_PPC970_SRQ_EMPTY,
160 		.pe_flags = PMC_FLAG_PMC4,
161 		.pe_code = 0x3
162 	},
163 	{PMC_EV_PPC970_MARKED_GROUP_COMPLETED,
164 		.pe_flags = PMC_FLAG_PMC4,
165 		.pe_code = 0x4
166 	},
167 	{PMC_EV_PPC970_CR_MARKED_INSTR_FINISH,
168 		.pe_flags = PMC_FLAG_PMC4,
169 		.pe_code = 0x5
170 	},
171 	{PMC_EV_PPC970_DISPATCH_SUCCESS,
172 		.pe_flags = PMC_FLAG_PMC5,
173 		.pe_code = 0x1
174 	},
175 	{PMC_EV_PPC970_FXU0_IDLE_FXU1_IDLE,
176 		.pe_flags = PMC_FLAG_PMC5,
177 		.pe_code = 0x2
178 	},
179 	{PMC_EV_PPC970_ONE_PLUS_INSTR_COMPLETED,
180 		.pe_flags = PMC_FLAG_PMC5,
181 		.pe_code = 0x3
182 	},
183 	{PMC_EV_PPC970_GROUP_MARKED_IDU,
184 		.pe_flags = PMC_FLAG_PMC5,
185 		.pe_code = 0x4
186 	},
187 	{PMC_EV_PPC970_MARKED_GROUP_COMPLETE_TIMEOUT,
188 		.pe_flags = PMC_FLAG_PMC5,
189 		.pe_code = 0x5
190 	},
191 	{PMC_EV_PPC970_FXU0_BUSY_FXU1_BUSY,
192 		.pe_flags = PMC_FLAG_PMC6,
193 		.pe_code = 0x2
194 	},
195 	{PMC_EV_PPC970_MARKED_STORE_SENT_TO_STS,
196 		.pe_flags = PMC_FLAG_PMC6,
197 		.pe_code = 0x3
198 	},
199 	{PMC_EV_PPC970_FXU_MARKED_INSTR_FINISHED,
200 		.pe_flags = PMC_FLAG_PMC6,
201 		.pe_code = 0x4
202 	},
203 	{PMC_EV_PPC970_MARKED_GROUP_ISSUED,
204 		.pe_flags = PMC_FLAG_PMC6,
205 		.pe_code = 0x5
206 	},
207 	{PMC_EV_PPC970_FXU0_BUSY_FXU1_IDLE,
208 		.pe_flags = PMC_FLAG_PMC7,
209 		.pe_code = 0x2
210 	},
211 	{PMC_EV_PPC970_GROUP_COMPLETED,
212 		.pe_flags = PMC_FLAG_PMC7,
213 		.pe_code = 0x3
214 	},
215 	{PMC_EV_PPC970_FPU_MARKED_INSTR_COMPLETED,
216 		.pe_flags = PMC_FLAG_PMC7,
217 		.pe_code = 0x4
218 	},
219 	{PMC_EV_PPC970_MARKED_INSTR_FINISH_ANY_UNIT,
220 		.pe_flags = PMC_FLAG_PMC7,
221 		.pe_code = 0x5
222 	},
223 	{PMC_EV_PPC970_EXTERNAL_INTERRUPT,
224 		.pe_flags = PMC_FLAG_PMC8,
225 		.pe_code = 0x2
226 	},
227 	{PMC_EV_PPC970_GROUP_DISPATCH_REJECT,
228 		.pe_flags = PMC_FLAG_PMC8,
229 		.pe_code = 0x3
230 	},
231 	{PMC_EV_PPC970_LSU_MARKED_INSTR_FINISH,
232 		.pe_flags = PMC_FLAG_PMC8,
233 		.pe_code = 0x4
234 	},
235 	{PMC_EV_PPC970_TIMEBASE_EVENT,
236 		.pe_flags = PMC_FLAG_PMC8,
237 		.pe_code = 0x5
238 	},
239 #if 0
240 	{PMC_EV_PPC970_LSU_COMPLETION_STALL, },
241 	{PMC_EV_PPC970_FXU_COMPLETION_STALL, },
242 	{PMC_EV_PPC970_DCACHE_MISS_COMPLETION_STALL, },
243 	{PMC_EV_PPC970_FPU_COMPLETION_STALL, },
244 	{PMC_EV_PPC970_FXU_LONG_INSTR_COMPLETION_STALL, },
245 	{PMC_EV_PPC970_REJECT_COMPLETION_STALL, },
246 	{PMC_EV_PPC970_FPU_LONG_INSTR_COMPLETION_STALL, },
247 	{PMC_EV_PPC970_GCT_EMPTY_BY_ICACHE_MISS, },
248 	{PMC_EV_PPC970_REJECT_COMPLETION_STALL_ERAT_MISS, },
249 	{PMC_EV_PPC970_GCT_EMPTY_BY_BRANCH_MISS_PREDICT, },
250 #endif
251 };
252 static size_t ppc970_event_codes_size = nitems(ppc970_event_codes);
253 
254 static void
255 ppc970_set_pmc(int cpu, int ri, int config)
256 {
257 	register_t pmc_mmcr;
258 	int config_mask;
259 
260 	if (config == PMCN_NONE)
261 		config = PMC970N_NONE;
262 
263 	/*
264 	 * The mask is inverted (enable is 1) compared to the flags in MMCR0,
265 	 * which are Freeze flags.
266 	 */
267 	config_mask = ~config & POWERPC_PMC_ENABLE;
268 	config &= ~POWERPC_PMC_ENABLE;
269 
270 	/*
271 	 * Disable the PMCs.
272 	 */
273 	switch (ri) {
274 	case 0:
275 	case 1:
276 		pmc_mmcr = mfspr(SPR_MMCR0);
277 		pmc_mmcr = PPC970_SET_MMCR0_PMCSEL(pmc_mmcr, config, ri);
278 		mtspr(SPR_MMCR0, pmc_mmcr);
279 		break;
280 	case 2:
281 	case 3:
282 	case 4:
283 	case 5:
284 	case 6:
285 	case 7:
286 		pmc_mmcr = mfspr(SPR_MMCR1);
287 		pmc_mmcr = PPC970_SET_MMCR1_PMCSEL(pmc_mmcr, config, ri);
288 		mtspr(SPR_MMCR1, pmc_mmcr);
289 		break;
290 	}
291 
292 	if (config != PMC970N_NONE) {
293 		pmc_mmcr = mfspr(SPR_MMCR0);
294 		pmc_mmcr &= ~SPR_MMCR0_FC;
295 		pmc_mmcr |= config_mask;
296 		mtspr(SPR_MMCR0, pmc_mmcr);
297 	}
298 }
299 
300 static int
301 ppc970_pcpu_init(struct pmc_mdep *md, int cpu)
302 {
303 	powerpc_pcpu_init(md, cpu);
304 
305 	/* Clear the MMCRs, and set FC, to disable all PMCs. */
306 	/* 970 PMC is not counted when set to 0x08 */
307 	mtspr(SPR_MMCR0, SPR_MMCR0_FC | SPR_MMCR0_PMXE |
308 	    SPR_MMCR0_FCECE | SPR_MMCR0_PMC1CE | SPR_MMCR0_PMCNCE |
309 	    SPR_MMCR0_PMC1SEL(0x8) | SPR_MMCR0_PMC2SEL(0x8));
310 	mtspr(SPR_MMCR1, 0x4218420);
311 
312 	return (0);
313 }
314 
315 static int
316 ppc970_pcpu_fini(struct pmc_mdep *md, int cpu)
317 {
318 	register_t mmcr0;
319 
320 	/* Freeze counters, disable interrupts */
321 	mmcr0 = mfspr(SPR_MMCR0);
322 	mmcr0 &= ~SPR_MMCR0_PMXE;
323 	mmcr0 |= SPR_MMCR0_FC;
324 	mtspr(SPR_MMCR0, mmcr0);
325 
326 	return (powerpc_pcpu_fini(md, cpu));
327 }
328 
329 static void
330 ppc970_resume_pmc(bool ie)
331 {
332 	register_t mmcr0;
333 
334 	/* Unfreeze counters and re-enable PERF exceptions if requested. */
335 	mmcr0 = mfspr(SPR_MMCR0);
336 	mmcr0 &= ~(SPR_MMCR0_FC | SPR_MMCR0_PMXE);
337 	if (ie)
338 		mmcr0 |= SPR_MMCR0_PMXE;
339 	mtspr(SPR_MMCR0, mmcr0);
340 }
341 
342 int
343 pmc_ppc970_initialize(struct pmc_mdep *pmc_mdep)
344 {
345 	struct pmc_classdep *pcd;
346 
347 	pmc_mdep->pmd_cputype = PMC_CPU_PPC_970;
348 
349 	pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_POWERPC];
350 	pcd->pcd_caps  = POWERPC_PMC_CAPS;
351 	pcd->pcd_class = PMC_CLASS_PPC970;
352 	pcd->pcd_num   = PPC970_MAX_PMCS;
353 	pcd->pcd_ri    = pmc_mdep->pmd_npmc;
354 	pcd->pcd_width = 32;
355 
356 	pcd->pcd_allocate_pmc   = powerpc_allocate_pmc;
357 	pcd->pcd_config_pmc     = powerpc_config_pmc;
358 	pcd->pcd_pcpu_fini      = ppc970_pcpu_fini;
359 	pcd->pcd_pcpu_init      = ppc970_pcpu_init;
360 	pcd->pcd_describe       = powerpc_describe;
361 	pcd->pcd_get_config     = powerpc_get_config;
362 	pcd->pcd_read_pmc       = powerpc_read_pmc;
363 	pcd->pcd_release_pmc    = powerpc_release_pmc;
364 	pcd->pcd_start_pmc      = powerpc_start_pmc;
365 	pcd->pcd_stop_pmc       = powerpc_stop_pmc;
366 	pcd->pcd_write_pmc      = powerpc_write_pmc;
367 
368 	pmc_mdep->pmd_npmc     += PPC970_MAX_PMCS;
369 	pmc_mdep->pmd_intr      = powerpc_pmc_intr;
370 
371 	ppc_event_codes = ppc970_event_codes;
372 	ppc_event_codes_size = ppc970_event_codes_size;
373 	ppc_event_first = PMC_EV_PPC970_FIRST;
374 	ppc_event_last = PMC_EV_PPC970_LAST;
375 	ppc_max_pmcs = PPC970_MAX_PMCS;
376 	ppc_class = pcd->pcd_class;
377 
378 	powerpc_set_pmc = ppc970_set_pmc;
379 	powerpc_pmcn_read = powerpc_pmcn_read_default;
380 	powerpc_pmcn_write = powerpc_pmcn_write_default;
381 	powerpc_resume_pmc = ppc970_resume_pmc;
382 
383 	return (0);
384 }
385