xref: /freebsd/sys/dev/hwpmc/hwpmc_ppc970.c (revision 190cef3d)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
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 __FBSDID("$FreeBSD$");
32 
33 #include <sys/param.h>
34 #include <sys/pmc.h>
35 #include <sys/pmckern.h>
36 #include <sys/systm.h>
37 
38 #include <machine/pmc_mdep.h>
39 #include <machine/spr.h>
40 #include <machine/cpu.h>
41 
42 #include "hwpmc_powerpc.h"
43 
44 #define PPC970_MAX_PMCS	8
45 
46 /* MMCR0, PMC1 is 8 bytes in, PMC2 is 1 byte in. */
47 #define PPC970_SET_MMCR0_PMCSEL(r, x, i) \
48 	((r & ~(0x1f << (7 * (1 - i) + 1))) | (x << (7 * (1 - i) + 1)))
49 /* MMCR1 has 6 PMC*SEL items (PMC3->PMC8), in sequence. */
50 #define PPC970_SET_MMCR1_PMCSEL(r, x, i) \
51 	((r & ~(0x1f << (5 * (7 - i) + 2))) | (x << (5 * (7 - i) + 2)))
52 
53 #define PPC970_PMC_HAS_OVERFLOWED(x) (ppc970_pmcn_read(x) & (0x1 << 31))
54 
55 /* How PMC works on PPC970:
56  *
57  * Any PMC can count a direct event.  Indirect events are handled specially.
58  * Direct events: As published.
59  *
60  * Encoding 00 000 -- Add byte lane bit counters
61  *   MMCR1[24:31] -- select bit matching PMC being an adder.
62  * Bus events:
63  * PMCxSEL: 1x -- select from byte lane: 10 == lower lane (0/1), 11 == upper
64  * lane (2/3).
65  * PMCxSEL[2:4] -- bit in the byte lane selected.
66  *
67  * PMC[1,2,5,6] == lane 0/lane 2
68  * PMC[3,4,7,8] == lane 1,3
69  *
70  *
71  * Lanes:
72  * Lane 0 -- TTM0(FPU,ISU,IFU,VPU)
73  *           TTM1(IDU,ISU,STS)
74  *           LSU0 byte 0
75  *           LSU1 byte 0
76  * Lane 1 -- TTM0
77  *           TTM1
78  *           LSU0 byte 1
79  *           LSU1 byte 1
80  * Lane 2 -- TTM0
81  *           TTM1
82  *           LSU0 byte 2
83  *           LSU1 byte 2 or byte 6
84  * Lane 3 -- TTM0
85  *           TTM1
86  *           LSU0 byte 3
87  *           LSU1 byte 3 or byte 7
88  *
89  * Adders:
90  *  Add byte lane for PMC (above), bit 0+4, 1+5, 2+6, 3+7
91  */
92 
93 struct pmc_ppc970_event {
94 	enum pmc_event pe_event;
95 	uint32_t pe_flags;
96 #define PMC_PPC970_FLAG_PMCS	0x000000ff
97 #define  PMC_PPC970_FLAG_PMC1	0x01
98 #define  PMC_PPC970_FLAG_PMC2	0x02
99 #define  PMC_PPC970_FLAG_PMC3	0x04
100 #define  PMC_PPC970_FLAG_PMC4	0x08
101 #define  PMC_PPC970_FLAG_PMC5	0x10
102 #define  PMC_PPC970_FLAG_PMC6	0x20
103 #define  PMC_PPC970_FLAG_PMC7	0x40
104 #define  PMC_PPC970_FLAG_PMC8	0x80
105 	uint32_t pe_code;
106 };
107 
108 static struct pmc_ppc970_event ppc970_event_codes[] = {
109 	{PMC_EV_PPC970_INSTR_COMPLETED,
110 	    .pe_flags = PMC_PPC970_FLAG_PMCS,
111 	    .pe_code = 0x09
112 	},
113 	{PMC_EV_PPC970_MARKED_GROUP_DISPATCH,
114 		.pe_flags = PMC_PPC970_FLAG_PMC1,
115 		.pe_code = 0x2
116 	},
117 	{PMC_EV_PPC970_MARKED_STORE_COMPLETED,
118 		.pe_flags = PMC_PPC970_FLAG_PMC1,
119 		.pe_code = 0x03
120 	},
121 	{PMC_EV_PPC970_GCT_EMPTY,
122 		.pe_flags = PMC_PPC970_FLAG_PMC1,
123 		.pe_code = 0x04
124 	},
125 	{PMC_EV_PPC970_RUN_CYCLES,
126 		.pe_flags = PMC_PPC970_FLAG_PMC1,
127 		.pe_code = 0x05
128 	},
129 	{PMC_EV_PPC970_OVERFLOW,
130 		.pe_flags = PMC_PPC970_FLAG_PMCS,
131 		.pe_code = 0x0a
132 	},
133 	{PMC_EV_PPC970_CYCLES,
134 		.pe_flags = PMC_PPC970_FLAG_PMCS,
135 		.pe_code = 0x0f
136 	},
137 	{PMC_EV_PPC970_THRESHOLD_TIMEOUT,
138 		.pe_flags = PMC_PPC970_FLAG_PMC2,
139 		.pe_code = 0x3
140 	},
141 	{PMC_EV_PPC970_GROUP_DISPATCH,
142 		.pe_flags = PMC_PPC970_FLAG_PMC2,
143 		.pe_code = 0x4
144 	},
145 	{PMC_EV_PPC970_BR_MARKED_INSTR_FINISH,
146 		.pe_flags = PMC_PPC970_FLAG_PMC2,
147 		.pe_code = 0x5
148 	},
149 	{PMC_EV_PPC970_GCT_EMPTY_BY_SRQ_FULL,
150 		.pe_flags = PMC_PPC970_FLAG_PMC2,
151 		.pe_code = 0xb
152 	},
153 	{PMC_EV_PPC970_STOP_COMPLETION,
154 		.pe_flags = PMC_PPC970_FLAG_PMC3,
155 		.pe_code = 0x1
156 	},
157 	{PMC_EV_PPC970_LSU_EMPTY,
158 		.pe_flags = PMC_PPC970_FLAG_PMC3,
159 		.pe_code = 0x2
160 	},
161 	{PMC_EV_PPC970_MARKED_STORE_WITH_INTR,
162 		.pe_flags = PMC_PPC970_FLAG_PMC3,
163 		.pe_code = 0x3
164 	},
165 	{PMC_EV_PPC970_CYCLES_IN_SUPER,
166 		.pe_flags = PMC_PPC970_FLAG_PMC3,
167 		.pe_code = 0x4
168 	},
169 	{PMC_EV_PPC970_VPU_MARKED_INSTR_COMPLETED,
170 		.pe_flags = PMC_PPC970_FLAG_PMC3,
171 		.pe_code = 0x5
172 	},
173 	{PMC_EV_PPC970_FXU0_IDLE_FXU1_BUSY,
174 		.pe_flags = PMC_PPC970_FLAG_PMC4,
175 		.pe_code = 0x2
176 	},
177 	{PMC_EV_PPC970_SRQ_EMPTY,
178 		.pe_flags = PMC_PPC970_FLAG_PMC4,
179 		.pe_code = 0x3
180 	},
181 	{PMC_EV_PPC970_MARKED_GROUP_COMPLETED,
182 		.pe_flags = PMC_PPC970_FLAG_PMC4,
183 		.pe_code = 0x4
184 	},
185 	{PMC_EV_PPC970_CR_MARKED_INSTR_FINISH,
186 		.pe_flags = PMC_PPC970_FLAG_PMC4,
187 		.pe_code = 0x5
188 	},
189 	{PMC_EV_PPC970_DISPATCH_SUCCESS,
190 		.pe_flags = PMC_PPC970_FLAG_PMC5,
191 		.pe_code = 0x1
192 	},
193 	{PMC_EV_PPC970_FXU0_IDLE_FXU1_IDLE,
194 		.pe_flags = PMC_PPC970_FLAG_PMC5,
195 		.pe_code = 0x2
196 	},
197 	{PMC_EV_PPC970_ONE_PLUS_INSTR_COMPLETED,
198 		.pe_flags = PMC_PPC970_FLAG_PMC5,
199 		.pe_code = 0x3
200 	},
201 	{PMC_EV_PPC970_GROUP_MARKED_IDU,
202 		.pe_flags = PMC_PPC970_FLAG_PMC5,
203 		.pe_code = 0x4
204 	},
205 	{PMC_EV_PPC970_MARKED_GROUP_COMPLETE_TIMEOUT,
206 		.pe_flags = PMC_PPC970_FLAG_PMC5,
207 		.pe_code = 0x5
208 	},
209 	{PMC_EV_PPC970_FXU0_BUSY_FXU1_BUSY,
210 		.pe_flags = PMC_PPC970_FLAG_PMC6,
211 		.pe_code = 0x2
212 	},
213 	{PMC_EV_PPC970_MARKED_STORE_SENT_TO_STS,
214 		.pe_flags = PMC_PPC970_FLAG_PMC6,
215 		.pe_code = 0x3
216 	},
217 	{PMC_EV_PPC970_FXU_MARKED_INSTR_FINISHED,
218 		.pe_flags = PMC_PPC970_FLAG_PMC6,
219 		.pe_code = 0x4
220 	},
221 	{PMC_EV_PPC970_MARKED_GROUP_ISSUED,
222 		.pe_flags = PMC_PPC970_FLAG_PMC6,
223 		.pe_code = 0x5
224 	},
225 	{PMC_EV_PPC970_FXU0_BUSY_FXU1_IDLE,
226 		.pe_flags = PMC_PPC970_FLAG_PMC7,
227 		.pe_code = 0x2
228 	},
229 	{PMC_EV_PPC970_GROUP_COMPLETED,
230 		.pe_flags = PMC_PPC970_FLAG_PMC7,
231 		.pe_code = 0x3
232 	},
233 	{PMC_EV_PPC970_FPU_MARKED_INSTR_COMPLETED,
234 		.pe_flags = PMC_PPC970_FLAG_PMC7,
235 		.pe_code = 0x4
236 	},
237 	{PMC_EV_PPC970_MARKED_INSTR_FINISH_ANY_UNIT,
238 		.pe_flags = PMC_PPC970_FLAG_PMC7,
239 		.pe_code = 0x5
240 	},
241 	{PMC_EV_PPC970_EXTERNAL_INTERRUPT,
242 		.pe_flags = PMC_PPC970_FLAG_PMC8,
243 		.pe_code = 0x2
244 	},
245 	{PMC_EV_PPC970_GROUP_DISPATCH_REJECT,
246 		.pe_flags = PMC_PPC970_FLAG_PMC8,
247 		.pe_code = 0x3
248 	},
249 	{PMC_EV_PPC970_LSU_MARKED_INSTR_FINISH,
250 		.pe_flags = PMC_PPC970_FLAG_PMC8,
251 		.pe_code = 0x4
252 	},
253 	{PMC_EV_PPC970_TIMEBASE_EVENT,
254 		.pe_flags = PMC_PPC970_FLAG_PMC8,
255 		.pe_code = 0x5
256 	},
257 #if 0
258 	{PMC_EV_PPC970_LSU_COMPLETION_STALL, },
259 	{PMC_EV_PPC970_FXU_COMPLETION_STALL, },
260 	{PMC_EV_PPC970_DCACHE_MISS_COMPLETION_STALL, },
261 	{PMC_EV_PPC970_FPU_COMPLETION_STALL, },
262 	{PMC_EV_PPC970_FXU_LONG_INSTR_COMPLETION_STALL, },
263 	{PMC_EV_PPC970_REJECT_COMPLETION_STALL, },
264 	{PMC_EV_PPC970_FPU_LONG_INSTR_COMPLETION_STALL, },
265 	{PMC_EV_PPC970_GCT_EMPTY_BY_ICACHE_MISS, },
266 	{PMC_EV_PPC970_REJECT_COMPLETION_STALL_ERAT_MISS, },
267 	{PMC_EV_PPC970_GCT_EMPTY_BY_BRANCH_MISS_PREDICT, },
268 #endif
269 };
270 static size_t ppc970_event_codes_size = nitems(ppc970_event_codes);
271 
272 static pmc_value_t
273 ppc970_pmcn_read(unsigned int pmc)
274 {
275 	pmc_value_t val;
276 
277 	switch (pmc) {
278 		case 0:
279 			val = mfspr(SPR_970PMC1);
280 			break;
281 		case 1:
282 			val = mfspr(SPR_970PMC2);
283 			break;
284 		case 2:
285 			val = mfspr(SPR_970PMC3);
286 			break;
287 		case 3:
288 			val = mfspr(SPR_970PMC4);
289 			break;
290 		case 4:
291 			val = mfspr(SPR_970PMC5);
292 			break;
293 		case 5:
294 			val = mfspr(SPR_970PMC6);
295 			break;
296 		case 6:
297 			val = mfspr(SPR_970PMC7);
298 			break;
299 		case 7:
300 			val = mfspr(SPR_970PMC8);
301 			break;
302 		default:
303 			panic("Invalid PMC number: %d\n", pmc);
304 	}
305 
306 	return (val);
307 }
308 
309 static void
310 ppc970_pmcn_write(unsigned int pmc, uint32_t val)
311 {
312 	switch (pmc) {
313 		case 0:
314 			mtspr(SPR_970PMC1, val);
315 			break;
316 		case 1:
317 			mtspr(SPR_970PMC2, val);
318 			break;
319 		case 2:
320 			mtspr(SPR_970PMC3, val);
321 			break;
322 		case 3:
323 			mtspr(SPR_970PMC4, val);
324 			break;
325 		case 4:
326 			mtspr(SPR_970PMC5, val);
327 			break;
328 		case 5:
329 			mtspr(SPR_970PMC6, val);
330 			break;
331 		case 6:
332 			mtspr(SPR_970PMC7, val);
333 			break;
334 		case 7:
335 			mtspr(SPR_970PMC8, val);
336 			break;
337 		default:
338 			panic("Invalid PMC number: %d\n", pmc);
339 	}
340 }
341 
342 static int
343 ppc970_config_pmc(int cpu, int ri, struct pmc *pm)
344 {
345 	struct pmc_hw *phw;
346 
347 	PMCDBG3(MDP,CFG,1, "cpu=%d ri=%d pm=%p", cpu, ri, pm);
348 
349 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
350 	    ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu));
351 	KASSERT(ri >= 0 && ri < PPC970_MAX_PMCS,
352 	    ("[powerpc,%d] illegal row-index %d", __LINE__, ri));
353 
354 	phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri];
355 
356 	KASSERT(pm == NULL || phw->phw_pmc == NULL,
357 	    ("[powerpc,%d] pm=%p phw->pm=%p hwpmc not unconfigured",
358 	    __LINE__, pm, phw->phw_pmc));
359 
360 	phw->phw_pmc = pm;
361 
362 	return 0;
363 }
364 
365 static int
366 ppc970_set_pmc(int cpu, int ri, int config)
367 {
368 	struct pmc *pm;
369 	struct pmc_hw *phw;
370 	register_t pmc_mmcr;
371 
372 	phw    = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri];
373 	pm     = phw->phw_pmc;
374 
375 	/*
376 	 * Disable the PMCs.
377 	 */
378 	switch (ri) {
379 	case 0:
380 	case 1:
381 		pmc_mmcr = mfspr(SPR_970MMCR0);
382 		pmc_mmcr = PPC970_SET_MMCR0_PMCSEL(pmc_mmcr, config, ri);
383 		mtspr(SPR_970MMCR0, pmc_mmcr);
384 		break;
385 	case 2:
386 	case 3:
387 	case 4:
388 	case 5:
389 	case 6:
390 	case 7:
391 		pmc_mmcr = mfspr(SPR_970MMCR1);
392 		pmc_mmcr = PPC970_SET_MMCR1_PMCSEL(pmc_mmcr, config, ri);
393 		mtspr(SPR_970MMCR1, pmc_mmcr);
394 		break;
395 	}
396 	return 0;
397 }
398 
399 static int
400 ppc970_start_pmc(int cpu, int ri)
401 {
402 	struct pmc *pm;
403 	struct pmc_hw *phw;
404 	register_t pmc_mmcr;
405 	uint32_t config;
406 	int error;
407 
408 	phw    = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri];
409 	pm     = phw->phw_pmc;
410 	config = pm->pm_md.pm_powerpc.pm_powerpc_evsel & ~POWERPC_PMC_ENABLE;
411 
412 	error = ppc970_set_pmc(cpu, ri, config);
413 
414 	/* The mask is inverted (enable is 1) compared to the flags in MMCR0, which
415 	 * are Freeze flags.
416 	 */
417 	config = ~pm->pm_md.pm_powerpc.pm_powerpc_evsel & POWERPC_PMC_ENABLE;
418 
419 	pmc_mmcr = mfspr(SPR_970MMCR0);
420 	pmc_mmcr &= ~SPR_MMCR0_FC;
421 	pmc_mmcr |= config;
422 	mtspr(SPR_970MMCR0, pmc_mmcr);
423 
424 	return 0;
425 }
426 
427 static int
428 ppc970_stop_pmc(int cpu, int ri)
429 {
430 	return ppc970_set_pmc(cpu, ri, PMC970N_NONE);
431 }
432 
433 static int
434 ppc970_read_pmc(int cpu, int ri, pmc_value_t *v)
435 {
436 	struct pmc *pm;
437 	pmc_value_t tmp;
438 
439 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
440 	    ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu));
441 	KASSERT(ri >= 0 && ri < PPC970_MAX_PMCS,
442 	    ("[powerpc,%d] illegal row index %d", __LINE__, ri));
443 
444 	pm  = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc;
445 	KASSERT(pm,
446 	    ("[core,%d] cpu %d ri %d pmc not configured", __LINE__, cpu,
447 		ri));
448 
449 	tmp = ppc970_pmcn_read(ri);
450 	PMCDBG2(MDP,REA,2,"ppc-read id=%d -> %jd", ri, tmp);
451 	if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
452 		*v = POWERPC_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp);
453 	else
454 		*v = tmp;
455 
456 	return 0;
457 }
458 
459 static int
460 ppc970_write_pmc(int cpu, int ri, pmc_value_t v)
461 {
462 	struct pmc *pm;
463 
464 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
465 	    ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu));
466 	KASSERT(ri >= 0 && ri < PPC970_MAX_PMCS,
467 	    ("[powerpc,%d] illegal row-index %d", __LINE__, ri));
468 
469 	pm  = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc;
470 
471 	if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
472 		v = POWERPC_RELOAD_COUNT_TO_PERFCTR_VALUE(v);
473 
474 	PMCDBG3(MDP,WRI,1,"powerpc-write cpu=%d ri=%d v=%jx", cpu, ri, v);
475 
476 	ppc970_pmcn_write(ri, v);
477 
478 	return 0;
479 }
480 
481 static int
482 ppc970_intr(struct trapframe *tf)
483 {
484 	struct pmc *pm;
485 	struct powerpc_cpu *pac;
486 	uint32_t config;
487 	int i, error, retval, cpu;
488 
489 	cpu = curcpu;
490 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
491 	    ("[powerpc,%d] out of range CPU %d", __LINE__, cpu));
492 
493 	PMCDBG3(MDP,INT,1, "cpu=%d tf=%p um=%d", cpu, (void *) tf,
494 	    TRAPF_USERMODE(tf));
495 
496 	retval = 0;
497 
498 	pac = powerpc_pcpu[cpu];
499 
500 	/*
501 	 * look for all PMCs that have interrupted:
502 	 * - look for a running, sampling PMC which has overflowed
503 	 *   and which has a valid 'struct pmc' association
504 	 *
505 	 * If found, we call a helper to process the interrupt.
506 	 */
507 
508 	config  = mfspr(SPR_970MMCR0) & ~SPR_MMCR0_FC;
509 	for (i = 0; i < PPC970_MAX_PMCS; i++) {
510 		if ((pm = pac->pc_ppcpmcs[i].phw_pmc) == NULL ||
511 		    !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) {
512 			continue;
513 		}
514 
515 		if (!PPC970_PMC_HAS_OVERFLOWED(i))
516 			continue;
517 
518 		retval = 1;	/* Found an interrupting PMC. */
519 
520 		if (pm->pm_state != PMC_STATE_RUNNING)
521 			continue;
522 
523 		error = pmc_process_interrupt(PMC_HR, pm, tf);
524 		if (error != 0)
525 			ppc970_stop_pmc(cpu, i);
526 
527 		/* reload sampling count. */
528 		ppc970_write_pmc(cpu, i, pm->pm_sc.pm_reloadcount);
529 	}
530 
531 	if (retval)
532 		counter_u64_add(pmc_stats.pm_intr_processed, 1);
533 	else
534 		counter_u64_add(pmc_stats.pm_intr_ignored, 1);
535 
536 	/* Re-enable PERF exceptions. */
537 	if (retval)
538 		mtspr(SPR_970MMCR0, config | SPR_MMCR0_PMXE);
539 
540 	return (retval);
541 }
542 
543 static int
544 ppc970_pcpu_init(struct pmc_mdep *md, int cpu)
545 {
546 	struct pmc_cpu *pc;
547 	struct powerpc_cpu *pac;
548 	struct pmc_hw  *phw;
549 	int first_ri, i;
550 
551 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
552 	    ("[powerpc,%d] wrong cpu number %d", __LINE__, cpu));
553 	PMCDBG1(MDP,INI,1,"powerpc-init cpu=%d", cpu);
554 
555 	powerpc_pcpu[cpu] = pac = malloc(sizeof(struct powerpc_cpu), M_PMC,
556 	    M_WAITOK|M_ZERO);
557 	pac->pc_ppcpmcs = malloc(sizeof(struct pmc_hw) * PPC970_MAX_PMCS,
558 	    M_PMC, M_WAITOK|M_ZERO);
559 	pac->pc_class = PMC_CLASS_PPC970;
560 
561 	pc = pmc_pcpu[cpu];
562 	first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_POWERPC].pcd_ri;
563 	KASSERT(pc != NULL, ("[powerpc,%d] NULL per-cpu pointer", __LINE__));
564 
565 	for (i = 0, phw = pac->pc_ppcpmcs; i < PPC970_MAX_PMCS; i++, phw++) {
566 		phw->phw_state    = PMC_PHW_FLAG_IS_ENABLED |
567 		    PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(i);
568 		phw->phw_pmc      = NULL;
569 		pc->pc_hwpmcs[i + first_ri] = phw;
570 	}
571 
572 	/* Clear the MMCRs, and set FC, to disable all PMCs. */
573 	/* 970 PMC is not counted when set to 0x08 */
574 	mtspr(SPR_970MMCR0, SPR_MMCR0_FC | SPR_MMCR0_PMXE |
575 	    SPR_MMCR0_FCECE | SPR_MMCR0_PMC1CE | SPR_MMCR0_PMCNCE |
576 	    SPR_970MMCR0_PMC1SEL(0x8) | SPR_970MMCR0_PMC2SEL(0x8));
577 	mtspr(SPR_970MMCR1, 0x4218420);
578 
579 	return 0;
580 }
581 
582 static int
583 ppc970_pcpu_fini(struct pmc_mdep *md, int cpu)
584 {
585 	register_t mmcr0 = mfspr(SPR_MMCR0);
586 
587 	mmcr0 |= SPR_MMCR0_FC;
588 	mmcr0 &= ~SPR_MMCR0_PMXE;
589 	mtspr(SPR_MMCR0, mmcr0);
590 
591 	free(powerpc_pcpu[cpu]->pc_ppcpmcs, M_PMC);
592 	free(powerpc_pcpu[cpu], M_PMC);
593 
594 	return 0;
595 }
596 
597 static int
598 ppc970_allocate_pmc(int cpu, int ri, struct pmc *pm,
599   const struct pmc_op_pmcallocate *a)
600 {
601 	enum pmc_event pe;
602 	uint32_t caps, config = 0, counter = 0;
603 	int i;
604 
605 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
606 	    ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu));
607 	KASSERT(ri >= 0 && ri < PPC970_MAX_PMCS,
608 	    ("[powerpc,%d] illegal row index %d", __LINE__, ri));
609 
610 	caps = a->pm_caps;
611 
612 	pe = a->pm_ev;
613 
614 	if (pe < PMC_EV_PPC970_FIRST || pe > PMC_EV_PPC970_LAST)
615 		return (EINVAL);
616 
617 	for (i = 0; i < ppc970_event_codes_size; i++) {
618 		if (ppc970_event_codes[i].pe_event == pe) {
619 			config = ppc970_event_codes[i].pe_code;
620 			counter =  ppc970_event_codes[i].pe_flags;
621 			break;
622 		}
623 	}
624 	if (i == ppc970_event_codes_size)
625 		return (EINVAL);
626 
627 	if ((counter & (1 << ri)) == 0)
628 		return (EINVAL);
629 
630 	if (caps & PMC_CAP_SYSTEM)
631 		config |= POWERPC_PMC_KERNEL_ENABLE;
632 	if (caps & PMC_CAP_USER)
633 		config |= POWERPC_PMC_USER_ENABLE;
634 	if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0)
635 		config |= POWERPC_PMC_ENABLE;
636 
637 	pm->pm_md.pm_powerpc.pm_powerpc_evsel = config;
638 
639 	PMCDBG2(MDP,ALL,2,"powerpc-allocate ri=%d -> config=0x%x", ri, config);
640 
641 	return 0;
642 }
643 
644 static int
645 ppc970_release_pmc(int cpu, int ri, struct pmc *pmc)
646 {
647 	struct pmc_hw *phw;
648 
649 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
650 	    ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu));
651 	KASSERT(ri >= 0 && ri < PPC970_MAX_PMCS,
652 	    ("[powerpc,%d] illegal row-index %d", __LINE__, ri));
653 
654 	phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri];
655 	KASSERT(phw->phw_pmc == NULL,
656 	    ("[powerpc,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc));
657 
658 	return 0;
659 }
660 
661 int
662 pmc_ppc970_initialize(struct pmc_mdep *pmc_mdep)
663 {
664 	struct pmc_classdep *pcd;
665 
666 	pmc_mdep->pmd_cputype = PMC_CPU_PPC_970;
667 
668 	pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_POWERPC];
669 	pcd->pcd_caps  = POWERPC_PMC_CAPS;
670 	pcd->pcd_class = PMC_CLASS_PPC970;
671 	pcd->pcd_num   = PPC970_MAX_PMCS;
672 	pcd->pcd_ri    = pmc_mdep->pmd_npmc;
673 	pcd->pcd_width = 32;
674 
675 	pcd->pcd_allocate_pmc   = ppc970_allocate_pmc;
676 	pcd->pcd_config_pmc     = ppc970_config_pmc;
677 	pcd->pcd_pcpu_fini      = ppc970_pcpu_fini;
678 	pcd->pcd_pcpu_init      = ppc970_pcpu_init;
679 	pcd->pcd_describe       = powerpc_describe;
680 	pcd->pcd_get_config     = powerpc_get_config;
681 	pcd->pcd_read_pmc       = ppc970_read_pmc;
682 	pcd->pcd_release_pmc    = ppc970_release_pmc;
683 	pcd->pcd_start_pmc      = ppc970_start_pmc;
684 	pcd->pcd_stop_pmc       = ppc970_stop_pmc;
685  	pcd->pcd_write_pmc      = ppc970_write_pmc;
686 
687 	pmc_mdep->pmd_npmc     += PPC970_MAX_PMCS;
688 	pmc_mdep->pmd_intr      = ppc970_intr;
689 
690 	return (0);
691 }
692