xref: /freebsd/sys/dev/hwpmc/hwpmc_core.c (revision 02e9120893770924227138ba49df1edb3896112a)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2008 Joseph Koshy
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  * Intel Core PMCs.
31  */
32 
33 #include <sys/param.h>
34 #include <sys/bus.h>
35 #include <sys/pmc.h>
36 #include <sys/pmckern.h>
37 #include <sys/smp.h>
38 #include <sys/systm.h>
39 
40 #include <machine/intr_machdep.h>
41 #include <x86/apicvar.h>
42 #include <machine/cpu.h>
43 #include <machine/cpufunc.h>
44 #include <machine/md_var.h>
45 #include <machine/specialreg.h>
46 
47 #define	CORE_CPUID_REQUEST		0xA
48 #define	CORE_CPUID_REQUEST_SIZE		0x4
49 #define	CORE_CPUID_EAX			0x0
50 #define	CORE_CPUID_EBX			0x1
51 #define	CORE_CPUID_ECX			0x2
52 #define	CORE_CPUID_EDX			0x3
53 
54 #define	IAF_PMC_CAPS			\
55 	(PMC_CAP_READ | PMC_CAP_WRITE | PMC_CAP_INTERRUPT | \
56 	 PMC_CAP_USER | PMC_CAP_SYSTEM)
57 #define	IAF_RI_TO_MSR(RI)		((RI) + (1 << 30))
58 
59 #define	IAP_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | PMC_CAP_SYSTEM | \
60     PMC_CAP_EDGE | PMC_CAP_THRESHOLD | PMC_CAP_READ | PMC_CAP_WRITE |	 \
61     PMC_CAP_INVERT | PMC_CAP_QUALIFIER | PMC_CAP_PRECISE)
62 
63 #define	EV_IS_NOTARCH		0
64 #define	EV_IS_ARCH_SUPP		1
65 #define	EV_IS_ARCH_NOTSUPP	-1
66 
67 /*
68  * "Architectural" events defined by Intel.  The values of these
69  * symbols correspond to positions in the bitmask returned by
70  * the CPUID.0AH instruction.
71  */
72 enum core_arch_events {
73 	CORE_AE_BRANCH_INSTRUCTION_RETIRED	= 5,
74 	CORE_AE_BRANCH_MISSES_RETIRED		= 6,
75 	CORE_AE_INSTRUCTION_RETIRED		= 1,
76 	CORE_AE_LLC_MISSES			= 4,
77 	CORE_AE_LLC_REFERENCE			= 3,
78 	CORE_AE_UNHALTED_REFERENCE_CYCLES	= 2,
79 	CORE_AE_UNHALTED_CORE_CYCLES		= 0
80 };
81 
82 static enum pmc_cputype	core_cputype;
83 static int core_version;
84 
85 struct core_cpu {
86 	volatile uint32_t	pc_iafctrl;	/* Fixed function control. */
87 	volatile uint64_t	pc_globalctrl;	/* Global control register. */
88 	struct pmc_hw		pc_corepmcs[];
89 };
90 
91 static struct core_cpu **core_pcpu;
92 
93 static uint32_t core_architectural_events;
94 static uint64_t core_pmcmask;
95 
96 static int core_iaf_ri;		/* relative index of fixed counters */
97 static int core_iaf_width;
98 static int core_iaf_npmc;
99 
100 static int core_iap_width;
101 static int core_iap_npmc;
102 static int core_iap_wroffset;
103 
104 static u_int pmc_alloc_refs;
105 static bool pmc_tsx_force_abort_set;
106 
107 static int
108 core_pcpu_noop(struct pmc_mdep *md, int cpu)
109 {
110 	(void) md;
111 	(void) cpu;
112 	return (0);
113 }
114 
115 static int
116 core_pcpu_init(struct pmc_mdep *md, int cpu)
117 {
118 	struct pmc_cpu *pc;
119 	struct core_cpu *cc;
120 	struct pmc_hw *phw;
121 	int core_ri, n, npmc;
122 
123 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
124 	    ("[iaf,%d] insane cpu number %d", __LINE__, cpu));
125 
126 	PMCDBG1(MDP,INI,1,"core-init cpu=%d", cpu);
127 
128 	core_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP].pcd_ri;
129 	npmc = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP].pcd_num;
130 
131 	if (core_version >= 2)
132 		npmc += md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAF].pcd_num;
133 
134 	cc = malloc(sizeof(struct core_cpu) + npmc * sizeof(struct pmc_hw),
135 	    M_PMC, M_WAITOK | M_ZERO);
136 
137 	core_pcpu[cpu] = cc;
138 	pc = pmc_pcpu[cpu];
139 
140 	KASSERT(pc != NULL && cc != NULL,
141 	    ("[core,%d] NULL per-cpu structures cpu=%d", __LINE__, cpu));
142 
143 	for (n = 0, phw = cc->pc_corepmcs; n < npmc; n++, phw++) {
144 		phw->phw_state 	  = PMC_PHW_FLAG_IS_ENABLED |
145 		    PMC_PHW_CPU_TO_STATE(cpu) |
146 		    PMC_PHW_INDEX_TO_STATE(n + core_ri);
147 		phw->phw_pmc	  = NULL;
148 		pc->pc_hwpmcs[n + core_ri]  = phw;
149 	}
150 
151 	if (core_version >= 2 && vm_guest == VM_GUEST_NO) {
152 		/* Enable Freezing PMCs on PMI. */
153 		wrmsr(MSR_DEBUGCTLMSR, rdmsr(MSR_DEBUGCTLMSR) | 0x1000);
154 	}
155 
156 	return (0);
157 }
158 
159 static int
160 core_pcpu_fini(struct pmc_mdep *md, int cpu)
161 {
162 	int core_ri, n, npmc;
163 	struct pmc_cpu *pc;
164 	struct core_cpu *cc;
165 
166 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
167 	    ("[core,%d] insane cpu number (%d)", __LINE__, cpu));
168 
169 	PMCDBG1(MDP,INI,1,"core-pcpu-fini cpu=%d", cpu);
170 
171 	if ((cc = core_pcpu[cpu]) == NULL)
172 		return (0);
173 
174 	core_pcpu[cpu] = NULL;
175 
176 	pc = pmc_pcpu[cpu];
177 
178 	KASSERT(pc != NULL, ("[core,%d] NULL per-cpu %d state", __LINE__,
179 		cpu));
180 
181 	npmc = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP].pcd_num;
182 	core_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP].pcd_ri;
183 
184 	for (n = 0; n < npmc; n++)
185 		wrmsr(IAP_EVSEL0 + n, 0);
186 
187 	if (core_version >= 2) {
188 		wrmsr(IAF_CTRL, 0);
189 		npmc += md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAF].pcd_num;
190 	}
191 
192 	for (n = 0; n < npmc; n++)
193 		pc->pc_hwpmcs[n + core_ri] = NULL;
194 
195 	free(cc, M_PMC);
196 
197 	return (0);
198 }
199 
200 /*
201  * Fixed function counters.
202  */
203 
204 static pmc_value_t
205 iaf_perfctr_value_to_reload_count(pmc_value_t v)
206 {
207 
208 	/* If the PMC has overflowed, return a reload count of zero. */
209 	if ((v & (1ULL << (core_iaf_width - 1))) == 0)
210 		return (0);
211 	v &= (1ULL << core_iaf_width) - 1;
212 	return (1ULL << core_iaf_width) - v;
213 }
214 
215 static pmc_value_t
216 iaf_reload_count_to_perfctr_value(pmc_value_t rlc)
217 {
218 	return (1ULL << core_iaf_width) - rlc;
219 }
220 
221 static int
222 iaf_allocate_pmc(int cpu, int ri, struct pmc *pm,
223     const struct pmc_op_pmcallocate *a)
224 {
225 	uint8_t ev, umask;
226 	uint32_t caps;
227 	uint64_t config, flags;
228 	const struct pmc_md_iap_op_pmcallocate *iap;
229 
230 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
231 	    ("[core,%d] illegal CPU %d", __LINE__, cpu));
232 
233 	PMCDBG2(MDP,ALL,1, "iaf-allocate ri=%d reqcaps=0x%x", ri, pm->pm_caps);
234 
235 	if (ri < 0 || ri > core_iaf_npmc)
236 		return (EINVAL);
237 
238 	if (a->pm_class != PMC_CLASS_IAF)
239 		return (EINVAL);
240 
241 	if ((a->pm_flags & PMC_F_EV_PMU) == 0)
242 		return (EINVAL);
243 
244 	iap = &a->pm_md.pm_iap;
245 	config = iap->pm_iap_config;
246 	ev = IAP_EVSEL_GET(config);
247 	umask = IAP_UMASK_GET(config);
248 
249 	if (ev == 0x0) {
250 		if (umask != ri + 1)
251 			return (EINVAL);
252 	} else {
253 		switch (ri) {
254 		case 0:	/* INST_RETIRED.ANY */
255 			if (ev != 0xC0 || umask != 0x00)
256 				return (EINVAL);
257 			break;
258 		case 1:	/* CPU_CLK_UNHALTED.THREAD */
259 			if (ev != 0x3C || umask != 0x00)
260 				return (EINVAL);
261 			break;
262 		case 2:	/* CPU_CLK_UNHALTED.REF */
263 			if (ev != 0x3C || umask != 0x01)
264 				return (EINVAL);
265 			break;
266 		case 3:	/* TOPDOWN.SLOTS */
267 			if (ev != 0xA4 || umask != 0x01)
268 				return (EINVAL);
269 			break;
270 		default:
271 			return (EINVAL);
272 		}
273 	}
274 
275 	pmc_alloc_refs++;
276 	if ((cpu_stdext_feature3 & CPUID_STDEXT3_TSXFA) != 0 &&
277 	    !pmc_tsx_force_abort_set) {
278 		pmc_tsx_force_abort_set = true;
279 		x86_msr_op(MSR_TSX_FORCE_ABORT, MSR_OP_RENDEZVOUS_ALL |
280 		    MSR_OP_WRITE, 1, NULL);
281 	}
282 
283 	flags = 0;
284 	if (config & IAP_OS)
285 		flags |= IAF_OS;
286 	if (config & IAP_USR)
287 		flags |= IAF_USR;
288 	if (config & IAP_ANY)
289 		flags |= IAF_ANY;
290 	if (config & IAP_INT)
291 		flags |= IAF_PMI;
292 
293 	caps = a->pm_caps;
294 	if (caps & PMC_CAP_INTERRUPT)
295 		flags |= IAF_PMI;
296 	if (caps & PMC_CAP_SYSTEM)
297 		flags |= IAF_OS;
298 	if (caps & PMC_CAP_USER)
299 		flags |= IAF_USR;
300 	if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0)
301 		flags |= (IAF_OS | IAF_USR);
302 
303 	pm->pm_md.pm_iaf.pm_iaf_ctrl = (flags << (ri * 4));
304 
305 	PMCDBG1(MDP,ALL,2, "iaf-allocate config=0x%jx",
306 	    (uintmax_t) pm->pm_md.pm_iaf.pm_iaf_ctrl);
307 
308 	return (0);
309 }
310 
311 static int
312 iaf_config_pmc(int cpu, int ri, struct pmc *pm)
313 {
314 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
315 	    ("[core,%d] illegal CPU %d", __LINE__, cpu));
316 
317 	KASSERT(ri >= 0 && ri < core_iaf_npmc,
318 	    ("[core,%d] illegal row-index %d", __LINE__, ri));
319 
320 	PMCDBG3(MDP,CFG,1, "iaf-config cpu=%d ri=%d pm=%p", cpu, ri, pm);
321 
322 	KASSERT(core_pcpu[cpu] != NULL, ("[core,%d] null per-cpu %d", __LINE__,
323 	    cpu));
324 
325 	core_pcpu[cpu]->pc_corepmcs[ri + core_iaf_ri].phw_pmc = pm;
326 
327 	return (0);
328 }
329 
330 static int
331 iaf_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc)
332 {
333 	struct pmc_hw *phw;
334 
335 	phw = &core_pcpu[cpu]->pc_corepmcs[ri + core_iaf_ri];
336 
337 	snprintf(pi->pm_name, sizeof(pi->pm_name), "IAF-%d", ri);
338 	pi->pm_class = PMC_CLASS_IAF;
339 
340 	if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) {
341 		pi->pm_enabled = TRUE;
342 		*ppmc          = phw->phw_pmc;
343 	} else {
344 		pi->pm_enabled = FALSE;
345 		*ppmc          = NULL;
346 	}
347 
348 	return (0);
349 }
350 
351 static int
352 iaf_get_config(int cpu, int ri, struct pmc **ppm)
353 {
354 	*ppm = core_pcpu[cpu]->pc_corepmcs[ri + core_iaf_ri].phw_pmc;
355 
356 	return (0);
357 }
358 
359 static int
360 iaf_get_msr(int ri, uint32_t *msr)
361 {
362 	KASSERT(ri >= 0 && ri < core_iaf_npmc,
363 	    ("[iaf,%d] ri %d out of range", __LINE__, ri));
364 
365 	*msr = IAF_RI_TO_MSR(ri);
366 
367 	return (0);
368 }
369 
370 static int
371 iaf_read_pmc(int cpu, int ri, struct pmc *pm, pmc_value_t *v)
372 {
373 	pmc_value_t tmp;
374 
375 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
376 	    ("[core,%d] illegal cpu value %d", __LINE__, cpu));
377 	KASSERT(ri >= 0 && ri < core_iaf_npmc,
378 	    ("[core,%d] illegal row-index %d", __LINE__, ri));
379 
380 	tmp = rdpmc(IAF_RI_TO_MSR(ri));
381 
382 	if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
383 		*v = iaf_perfctr_value_to_reload_count(tmp);
384 	else
385 		*v = tmp & ((1ULL << core_iaf_width) - 1);
386 
387 	PMCDBG4(MDP,REA,1, "iaf-read cpu=%d ri=%d msr=0x%x -> v=%jx", cpu, ri,
388 	    IAF_RI_TO_MSR(ri), *v);
389 
390 	return (0);
391 }
392 
393 static int
394 iaf_release_pmc(int cpu, int ri, struct pmc *pmc)
395 {
396 	PMCDBG3(MDP,REL,1, "iaf-release cpu=%d ri=%d pm=%p", cpu, ri, pmc);
397 
398 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
399 	    ("[core,%d] illegal CPU value %d", __LINE__, cpu));
400 	KASSERT(ri >= 0 && ri < core_iaf_npmc,
401 	    ("[core,%d] illegal row-index %d", __LINE__, ri));
402 
403 	KASSERT(core_pcpu[cpu]->pc_corepmcs[ri + core_iaf_ri].phw_pmc == NULL,
404 	    ("[core,%d] PHW pmc non-NULL", __LINE__));
405 
406 	MPASS(pmc_alloc_refs > 0);
407 	if (pmc_alloc_refs-- == 1 && pmc_tsx_force_abort_set) {
408 		pmc_tsx_force_abort_set = false;
409 		x86_msr_op(MSR_TSX_FORCE_ABORT, MSR_OP_RENDEZVOUS_ALL |
410 		    MSR_OP_WRITE, 0, NULL);
411 	}
412 
413 	return (0);
414 }
415 
416 static int
417 iaf_start_pmc(int cpu, int ri, struct pmc *pm)
418 {
419 	struct core_cpu *cc;
420 
421 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
422 	    ("[core,%d] illegal CPU value %d", __LINE__, cpu));
423 	KASSERT(ri >= 0 && ri < core_iaf_npmc,
424 	    ("[core,%d] illegal row-index %d", __LINE__, ri));
425 
426 	PMCDBG2(MDP,STA,1,"iaf-start cpu=%d ri=%d", cpu, ri);
427 
428 	cc = core_pcpu[cpu];
429 	cc->pc_iafctrl |= pm->pm_md.pm_iaf.pm_iaf_ctrl;
430 	wrmsr(IAF_CTRL, cc->pc_iafctrl);
431 
432 	cc->pc_globalctrl |= (1ULL << (ri + IAF_OFFSET));
433 	wrmsr(IA_GLOBAL_CTRL, cc->pc_globalctrl);
434 
435 	PMCDBG4(MDP,STA,1,"iafctrl=%x(%x) globalctrl=%jx(%jx)",
436 	    cc->pc_iafctrl, (uint32_t) rdmsr(IAF_CTRL),
437 	    cc->pc_globalctrl, rdmsr(IA_GLOBAL_CTRL));
438 
439 	return (0);
440 }
441 
442 static int
443 iaf_stop_pmc(int cpu, int ri, struct pmc *pm)
444 {
445 	struct core_cpu *cc;
446 
447 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
448 	    ("[core,%d] illegal CPU value %d", __LINE__, cpu));
449 	KASSERT(ri >= 0 && ri < core_iaf_npmc,
450 	    ("[core,%d] illegal row-index %d", __LINE__, ri));
451 
452 	PMCDBG2(MDP,STA,1,"iaf-stop cpu=%d ri=%d", cpu, ri);
453 
454 	cc = core_pcpu[cpu];
455 
456 	cc->pc_iafctrl &= ~(IAF_MASK << (ri * 4));
457 	wrmsr(IAF_CTRL, cc->pc_iafctrl);
458 
459 	/* Don't need to write IA_GLOBAL_CTRL, one disable is enough. */
460 
461 	PMCDBG4(MDP,STO,1,"iafctrl=%x(%x) globalctrl=%jx(%jx)",
462 	    cc->pc_iafctrl, (uint32_t) rdmsr(IAF_CTRL),
463 	    cc->pc_globalctrl, rdmsr(IA_GLOBAL_CTRL));
464 
465 	return (0);
466 }
467 
468 static int
469 iaf_write_pmc(int cpu, int ri, struct pmc *pm, pmc_value_t v)
470 {
471 	struct core_cpu *cc;
472 
473 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
474 	    ("[core,%d] illegal cpu value %d", __LINE__, cpu));
475 	KASSERT(ri >= 0 && ri < core_iaf_npmc,
476 	    ("[core,%d] illegal row-index %d", __LINE__, ri));
477 
478 	cc = core_pcpu[cpu];
479 
480 	if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
481 		v = iaf_reload_count_to_perfctr_value(v);
482 
483 	/* Turn off the fixed counter */
484 	wrmsr(IAF_CTRL, cc->pc_iafctrl & ~(IAF_MASK << (ri * 4)));
485 
486 	wrmsr(IAF_CTR0 + ri, v & ((1ULL << core_iaf_width) - 1));
487 
488 	/* Turn on fixed counters */
489 	wrmsr(IAF_CTRL, cc->pc_iafctrl);
490 
491 	PMCDBG6(MDP,WRI,1, "iaf-write cpu=%d ri=%d msr=0x%x v=%jx iafctrl=%jx "
492 	    "pmc=%jx", cpu, ri, IAF_RI_TO_MSR(ri), v,
493 	    (uintmax_t) rdmsr(IAF_CTRL),
494 	    (uintmax_t) rdpmc(IAF_RI_TO_MSR(ri)));
495 
496 	return (0);
497 }
498 
499 
500 static void
501 iaf_initialize(struct pmc_mdep *md, int maxcpu, int npmc, int pmcwidth)
502 {
503 	struct pmc_classdep *pcd;
504 
505 	KASSERT(md != NULL, ("[iaf,%d] md is NULL", __LINE__));
506 
507 	PMCDBG0(MDP,INI,1, "iaf-initialize");
508 
509 	pcd = &md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAF];
510 
511 	pcd->pcd_caps	= IAF_PMC_CAPS;
512 	pcd->pcd_class	= PMC_CLASS_IAF;
513 	pcd->pcd_num	= npmc;
514 	pcd->pcd_ri	= md->pmd_npmc;
515 	pcd->pcd_width	= pmcwidth;
516 
517 	pcd->pcd_allocate_pmc	= iaf_allocate_pmc;
518 	pcd->pcd_config_pmc	= iaf_config_pmc;
519 	pcd->pcd_describe	= iaf_describe;
520 	pcd->pcd_get_config	= iaf_get_config;
521 	pcd->pcd_get_msr	= iaf_get_msr;
522 	pcd->pcd_pcpu_fini	= core_pcpu_noop;
523 	pcd->pcd_pcpu_init	= core_pcpu_noop;
524 	pcd->pcd_read_pmc	= iaf_read_pmc;
525 	pcd->pcd_release_pmc	= iaf_release_pmc;
526 	pcd->pcd_start_pmc	= iaf_start_pmc;
527 	pcd->pcd_stop_pmc	= iaf_stop_pmc;
528 	pcd->pcd_write_pmc	= iaf_write_pmc;
529 
530 	md->pmd_npmc	       += npmc;
531 }
532 
533 /*
534  * Intel programmable PMCs.
535  */
536 
537 /* Sub fields of UMASK that this event supports. */
538 #define	IAP_M_CORE		(1 << 0) /* Core specificity */
539 #define	IAP_M_AGENT		(1 << 1) /* Agent specificity */
540 #define	IAP_M_PREFETCH		(1 << 2) /* Prefetch */
541 #define	IAP_M_MESI		(1 << 3) /* MESI */
542 #define	IAP_M_SNOOPRESPONSE	(1 << 4) /* Snoop response */
543 #define	IAP_M_SNOOPTYPE		(1 << 5) /* Snoop type */
544 #define	IAP_M_TRANSITION	(1 << 6) /* Transition */
545 
546 #define	IAP_F_CORE		(0x3 << 14) /* Core specificity */
547 #define	IAP_F_AGENT		(0x1 << 13) /* Agent specificity */
548 #define	IAP_F_PREFETCH		(0x3 << 12) /* Prefetch */
549 #define	IAP_F_MESI		(0xF <<  8) /* MESI */
550 #define	IAP_F_SNOOPRESPONSE	(0xB <<  8) /* Snoop response */
551 #define	IAP_F_SNOOPTYPE		(0x3 <<  8) /* Snoop type */
552 #define	IAP_F_TRANSITION	(0x1 << 12) /* Transition */
553 
554 #define	IAP_PREFETCH_RESERVED	(0x2 << 12)
555 #define	IAP_CORE_THIS		(0x1 << 14)
556 #define	IAP_CORE_ALL		(0x3 << 14)
557 #define	IAP_F_CMASK		0xFF000000
558 
559 static pmc_value_t
560 iap_perfctr_value_to_reload_count(pmc_value_t v)
561 {
562 
563 	/* If the PMC has overflowed, return a reload count of zero. */
564 	if ((v & (1ULL << (core_iap_width - 1))) == 0)
565 		return (0);
566 	v &= (1ULL << core_iap_width) - 1;
567 	return (1ULL << core_iap_width) - v;
568 }
569 
570 static pmc_value_t
571 iap_reload_count_to_perfctr_value(pmc_value_t rlc)
572 {
573 	return (1ULL << core_iap_width) - rlc;
574 }
575 
576 static int
577 iap_pmc_has_overflowed(int ri)
578 {
579 	uint64_t v;
580 
581 	/*
582 	 * We treat a Core (i.e., Intel architecture v1) PMC as has
583 	 * having overflowed if its MSB is zero.
584 	 */
585 	v = rdpmc(ri);
586 	return ((v & (1ULL << (core_iap_width - 1))) == 0);
587 }
588 
589 static int
590 iap_event_corei7_ok_on_counter(uint8_t evsel, int ri)
591 {
592 	uint32_t mask;
593 
594 	switch (evsel) {
595 	/* Events valid only on counter 0, 1. */
596 	case 0x40:
597 	case 0x41:
598 	case 0x42:
599 	case 0x43:
600 	case 0x4C:
601 	case 0x4E:
602 	case 0x51:
603 	case 0x52:
604 	case 0x53:
605 	case 0x63:
606 		mask = 0x3;
607 		break;
608 	/* Any row index is ok. */
609 	default:
610 		mask = ~0;
611 	}
612 
613 	return (mask & (1 << ri));
614 }
615 
616 static int
617 iap_event_westmere_ok_on_counter(uint8_t evsel, int ri)
618 {
619 	uint32_t mask;
620 
621 	switch (evsel) {
622 	/* Events valid only on counter 0. */
623 	case 0x60:
624 	case 0xB3:
625 		mask = 0x1;
626 		break;
627 
628 	/* Events valid only on counter 0, 1. */
629 	case 0x4C:
630 	case 0x4E:
631 	case 0x51:
632 	case 0x52:
633 	case 0x63:
634 		mask = 0x3;
635 		break;
636 	/* Any row index is ok. */
637 	default:
638 		mask = ~0;
639 	}
640 
641 	return (mask & (1 << ri));
642 }
643 
644 static int
645 iap_event_sb_sbx_ib_ibx_ok_on_counter(uint8_t evsel, int ri)
646 {
647 	uint32_t mask;
648 
649 	switch (evsel) {
650 	/* Events valid only on counter 0. */
651 	case 0xB7:
652 		mask = 0x1;
653 		break;
654 	/* Events valid only on counter 1. */
655 	case 0xC0:
656 		mask = 0x2;
657 		break;
658 	/* Events valid only on counter 2. */
659 	case 0x48:
660 	case 0xA2:
661 	case 0xA3:
662 		mask = 0x4;
663 		break;
664 	/* Events valid only on counter 3. */
665 	case 0xBB:
666 	case 0xCD:
667 		mask = 0x8;
668 		break;
669 	/* Any row index is ok. */
670 	default:
671 		mask = ~0;
672 	}
673 
674 	return (mask & (1 << ri));
675 }
676 
677 static int
678 iap_event_core_ok_on_counter(uint8_t evsel, int ri)
679 {
680 	uint32_t mask;
681 
682 	switch (evsel) {
683 		/*
684 		 * Events valid only on counter 0.
685 		 */
686 	case 0x10:
687 	case 0x14:
688 	case 0x18:
689 	case 0xB3:
690 	case 0xC1:
691 	case 0xCB:
692 		mask = (1 << 0);
693 		break;
694 
695 		/*
696 		 * Events valid only on counter 1.
697 		 */
698 	case 0x11:
699 	case 0x12:
700 	case 0x13:
701 		mask = (1 << 1);
702 		break;
703 
704 	default:
705 		mask = ~0;	/* Any row index is ok. */
706 	}
707 
708 	return (mask & (1 << ri));
709 }
710 
711 static int
712 iap_allocate_pmc(int cpu, int ri, struct pmc *pm,
713     const struct pmc_op_pmcallocate *a)
714 {
715 	uint8_t ev;
716 	const struct pmc_md_iap_op_pmcallocate *iap;
717 
718 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
719 	    ("[core,%d] illegal CPU %d", __LINE__, cpu));
720 	KASSERT(ri >= 0 && ri < core_iap_npmc,
721 	    ("[core,%d] illegal row-index value %d", __LINE__, ri));
722 
723 	if (a->pm_class != PMC_CLASS_IAP)
724 		return (EINVAL);
725 
726 	if ((a->pm_flags & PMC_F_EV_PMU) == 0)
727 		return (EINVAL);
728 
729 	iap = &a->pm_md.pm_iap;
730 	ev = IAP_EVSEL_GET(iap->pm_iap_config);
731 
732 	switch (core_cputype) {
733 	case PMC_CPU_INTEL_CORE:
734 	case PMC_CPU_INTEL_CORE2:
735 	case PMC_CPU_INTEL_CORE2EXTREME:
736 		if (iap_event_core_ok_on_counter(ev, ri) == 0)
737 			return (EINVAL);
738 	case PMC_CPU_INTEL_COREI7:
739 	case PMC_CPU_INTEL_NEHALEM_EX:
740 		if (iap_event_corei7_ok_on_counter(ev, ri) == 0)
741 			return (EINVAL);
742 		break;
743 	case PMC_CPU_INTEL_WESTMERE:
744 	case PMC_CPU_INTEL_WESTMERE_EX:
745 		if (iap_event_westmere_ok_on_counter(ev, ri) == 0)
746 			return (EINVAL);
747 		break;
748 	case PMC_CPU_INTEL_SANDYBRIDGE:
749 	case PMC_CPU_INTEL_SANDYBRIDGE_XEON:
750 	case PMC_CPU_INTEL_IVYBRIDGE:
751 	case PMC_CPU_INTEL_IVYBRIDGE_XEON:
752 	case PMC_CPU_INTEL_HASWELL:
753 	case PMC_CPU_INTEL_HASWELL_XEON:
754 	case PMC_CPU_INTEL_BROADWELL:
755 	case PMC_CPU_INTEL_BROADWELL_XEON:
756 		if (iap_event_sb_sbx_ib_ibx_ok_on_counter(ev, ri) == 0)
757 			return (EINVAL);
758 		break;
759 	case PMC_CPU_INTEL_ATOM:
760 	case PMC_CPU_INTEL_ATOM_SILVERMONT:
761 	case PMC_CPU_INTEL_ATOM_GOLDMONT:
762 	case PMC_CPU_INTEL_ATOM_GOLDMONT_P:
763 	case PMC_CPU_INTEL_ATOM_TREMONT:
764 	case PMC_CPU_INTEL_SKYLAKE:
765 	case PMC_CPU_INTEL_SKYLAKE_XEON:
766 	case PMC_CPU_INTEL_ICELAKE:
767 	case PMC_CPU_INTEL_ICELAKE_XEON:
768 	case PMC_CPU_INTEL_ALDERLAKE:
769 	default:
770 		break;
771 	}
772 
773 	pm->pm_md.pm_iap.pm_iap_evsel = iap->pm_iap_config;
774 	return (0);
775 }
776 
777 static int
778 iap_config_pmc(int cpu, int ri, struct pmc *pm)
779 {
780 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
781 	    ("[core,%d] illegal CPU %d", __LINE__, cpu));
782 
783 	KASSERT(ri >= 0 && ri < core_iap_npmc,
784 	    ("[core,%d] illegal row-index %d", __LINE__, ri));
785 
786 	PMCDBG3(MDP,CFG,1, "iap-config cpu=%d ri=%d pm=%p", cpu, ri, pm);
787 
788 	KASSERT(core_pcpu[cpu] != NULL, ("[core,%d] null per-cpu %d", __LINE__,
789 	    cpu));
790 
791 	core_pcpu[cpu]->pc_corepmcs[ri].phw_pmc = pm;
792 
793 	return (0);
794 }
795 
796 static int
797 iap_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc)
798 {
799 	struct pmc_hw *phw;
800 
801 	phw = &core_pcpu[cpu]->pc_corepmcs[ri];
802 
803 	snprintf(pi->pm_name, sizeof(pi->pm_name), "IAP-%d", ri);
804 	pi->pm_class = PMC_CLASS_IAP;
805 
806 	if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) {
807 		pi->pm_enabled = TRUE;
808 		*ppmc          = phw->phw_pmc;
809 	} else {
810 		pi->pm_enabled = FALSE;
811 		*ppmc          = NULL;
812 	}
813 
814 	return (0);
815 }
816 
817 static int
818 iap_get_config(int cpu, int ri, struct pmc **ppm)
819 {
820 	*ppm = core_pcpu[cpu]->pc_corepmcs[ri].phw_pmc;
821 
822 	return (0);
823 }
824 
825 static int
826 iap_get_msr(int ri, uint32_t *msr)
827 {
828 	KASSERT(ri >= 0 && ri < core_iap_npmc,
829 	    ("[iap,%d] ri %d out of range", __LINE__, ri));
830 
831 	*msr = ri;
832 
833 	return (0);
834 }
835 
836 static int
837 iap_read_pmc(int cpu, int ri, struct pmc *pm, pmc_value_t *v)
838 {
839 	pmc_value_t tmp;
840 
841 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
842 	    ("[core,%d] illegal cpu value %d", __LINE__, cpu));
843 	KASSERT(ri >= 0 && ri < core_iap_npmc,
844 	    ("[core,%d] illegal row-index %d", __LINE__, ri));
845 
846 	tmp = rdpmc(ri);
847 	if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
848 		*v = iap_perfctr_value_to_reload_count(tmp);
849 	else
850 		*v = tmp & ((1ULL << core_iap_width) - 1);
851 
852 	PMCDBG4(MDP,REA,1, "iap-read cpu=%d ri=%d msr=0x%x -> v=%jx", cpu, ri,
853 	    IAP_PMC0 + ri, *v);
854 
855 	return (0);
856 }
857 
858 static int
859 iap_release_pmc(int cpu, int ri, struct pmc *pm)
860 {
861 	(void) pm;
862 
863 	PMCDBG3(MDP,REL,1, "iap-release cpu=%d ri=%d pm=%p", cpu, ri,
864 	    pm);
865 
866 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
867 	    ("[core,%d] illegal CPU value %d", __LINE__, cpu));
868 	KASSERT(ri >= 0 && ri < core_iap_npmc,
869 	    ("[core,%d] illegal row-index %d", __LINE__, ri));
870 
871 	KASSERT(core_pcpu[cpu]->pc_corepmcs[ri].phw_pmc
872 	    == NULL, ("[core,%d] PHW pmc non-NULL", __LINE__));
873 
874 	return (0);
875 }
876 
877 static int
878 iap_start_pmc(int cpu, int ri, struct pmc *pm)
879 {
880 	uint64_t evsel;
881 	struct core_cpu *cc;
882 
883 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
884 	    ("[core,%d] illegal CPU value %d", __LINE__, cpu));
885 	KASSERT(ri >= 0 && ri < core_iap_npmc,
886 	    ("[core,%d] illegal row-index %d", __LINE__, ri));
887 
888 	cc = core_pcpu[cpu];
889 
890 	PMCDBG2(MDP,STA,1, "iap-start cpu=%d ri=%d", cpu, ri);
891 
892 	evsel = pm->pm_md.pm_iap.pm_iap_evsel;
893 
894 	PMCDBG4(MDP,STA,2, "iap-start/2 cpu=%d ri=%d evselmsr=0x%x evsel=0x%x",
895 	    cpu, ri, IAP_EVSEL0 + ri, evsel);
896 
897 	/* Event specific configuration. */
898 
899 	switch (IAP_EVSEL_GET(evsel)) {
900 	case 0xB7:
901 		wrmsr(IA_OFFCORE_RSP0, pm->pm_md.pm_iap.pm_iap_rsp);
902 		break;
903 	case 0xBB:
904 		wrmsr(IA_OFFCORE_RSP1, pm->pm_md.pm_iap.pm_iap_rsp);
905 		break;
906 	default:
907 		break;
908 	}
909 
910 	wrmsr(IAP_EVSEL0 + ri, evsel | IAP_EN);
911 
912 	if (core_version >= 2) {
913 		cc->pc_globalctrl |= (1ULL << ri);
914 		wrmsr(IA_GLOBAL_CTRL, cc->pc_globalctrl);
915 	}
916 
917 	return (0);
918 }
919 
920 static int
921 iap_stop_pmc(int cpu, int ri, struct pmc *pm __unused)
922 {
923 
924 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
925 	    ("[core,%d] illegal cpu value %d", __LINE__, cpu));
926 	KASSERT(ri >= 0 && ri < core_iap_npmc,
927 	    ("[core,%d] illegal row index %d", __LINE__, ri));
928 
929 	PMCDBG2(MDP,STO,1, "iap-stop cpu=%d ri=%d", cpu, ri);
930 
931 	wrmsr(IAP_EVSEL0 + ri, 0);
932 
933 	/* Don't need to write IA_GLOBAL_CTRL, one disable is enough. */
934 
935 	return (0);
936 }
937 
938 static int
939 iap_write_pmc(int cpu, int ri, struct pmc *pm, pmc_value_t v)
940 {
941 
942 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
943 	    ("[core,%d] illegal cpu value %d", __LINE__, cpu));
944 	KASSERT(ri >= 0 && ri < core_iap_npmc,
945 	    ("[core,%d] illegal row index %d", __LINE__, ri));
946 
947 	if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
948 		v = iap_reload_count_to_perfctr_value(v);
949 
950 	v &= (1ULL << core_iap_width) - 1;
951 
952 	PMCDBG4(MDP,WRI,1, "iap-write cpu=%d ri=%d msr=0x%x v=%jx", cpu, ri,
953 	    IAP_PMC0 + ri, v);
954 
955 	/*
956 	 * Write the new value to the counter (or it's alias).  The
957 	 * counter will be in a stopped state when the pcd_write()
958 	 * entry point is called.
959 	 */
960 	wrmsr(core_iap_wroffset + IAP_PMC0 + ri, v);
961 	return (0);
962 }
963 
964 
965 static void
966 iap_initialize(struct pmc_mdep *md, int maxcpu, int npmc, int pmcwidth,
967     int flags)
968 {
969 	struct pmc_classdep *pcd;
970 
971 	KASSERT(md != NULL, ("[iap,%d] md is NULL", __LINE__));
972 
973 	PMCDBG0(MDP,INI,1, "iap-initialize");
974 
975 	/* Remember the set of architectural events supported. */
976 	core_architectural_events = ~flags;
977 
978 	pcd = &md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IAP];
979 
980 	pcd->pcd_caps	= IAP_PMC_CAPS;
981 	pcd->pcd_class	= PMC_CLASS_IAP;
982 	pcd->pcd_num	= npmc;
983 	pcd->pcd_ri	= md->pmd_npmc;
984 	pcd->pcd_width	= pmcwidth;
985 
986 	pcd->pcd_allocate_pmc	= iap_allocate_pmc;
987 	pcd->pcd_config_pmc	= iap_config_pmc;
988 	pcd->pcd_describe	= iap_describe;
989 	pcd->pcd_get_config	= iap_get_config;
990 	pcd->pcd_get_msr	= iap_get_msr;
991 	pcd->pcd_pcpu_fini	= core_pcpu_fini;
992 	pcd->pcd_pcpu_init	= core_pcpu_init;
993 	pcd->pcd_read_pmc	= iap_read_pmc;
994 	pcd->pcd_release_pmc	= iap_release_pmc;
995 	pcd->pcd_start_pmc	= iap_start_pmc;
996 	pcd->pcd_stop_pmc	= iap_stop_pmc;
997 	pcd->pcd_write_pmc	= iap_write_pmc;
998 
999 	md->pmd_npmc	       += npmc;
1000 }
1001 
1002 static int
1003 core_intr(struct trapframe *tf)
1004 {
1005 	pmc_value_t v;
1006 	struct pmc *pm;
1007 	struct core_cpu *cc;
1008 	int error, found_interrupt, ri;
1009 
1010 	PMCDBG3(MDP,INT, 1, "cpu=%d tf=%p um=%d", curcpu, (void *) tf,
1011 	    TRAPF_USERMODE(tf));
1012 
1013 	found_interrupt = 0;
1014 	cc = core_pcpu[curcpu];
1015 
1016 	for (ri = 0; ri < core_iap_npmc; ri++) {
1017 
1018 		if ((pm = cc->pc_corepmcs[ri].phw_pmc) == NULL ||
1019 		    !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
1020 			continue;
1021 
1022 		if (!iap_pmc_has_overflowed(ri))
1023 			continue;
1024 
1025 		found_interrupt = 1;
1026 
1027 		if (pm->pm_state != PMC_STATE_RUNNING)
1028 			continue;
1029 
1030 		error = pmc_process_interrupt(PMC_HR, pm, tf);
1031 
1032 		v = pm->pm_sc.pm_reloadcount;
1033 		v = iap_reload_count_to_perfctr_value(v);
1034 
1035 		/*
1036 		 * Stop the counter, reload it but only restart it if
1037 		 * the PMC is not stalled.
1038 		 */
1039 		wrmsr(IAP_EVSEL0 + ri, pm->pm_md.pm_iap.pm_iap_evsel);
1040 		wrmsr(core_iap_wroffset + IAP_PMC0 + ri, v);
1041 
1042 		if (__predict_false(error))
1043 			continue;
1044 
1045 		wrmsr(IAP_EVSEL0 + ri, pm->pm_md.pm_iap.pm_iap_evsel | IAP_EN);
1046 	}
1047 
1048 	if (found_interrupt)
1049 		counter_u64_add(pmc_stats.pm_intr_processed, 1);
1050 	else
1051 		counter_u64_add(pmc_stats.pm_intr_ignored, 1);
1052 
1053 	if (found_interrupt)
1054 		lapic_reenable_pmc();
1055 
1056 	return (found_interrupt);
1057 }
1058 
1059 static int
1060 core2_intr(struct trapframe *tf)
1061 {
1062 	int error, found_interrupt = 0, n, cpu;
1063 	uint64_t flag, intrstatus, intrdisable = 0;
1064 	struct pmc *pm;
1065 	struct core_cpu *cc;
1066 	pmc_value_t v;
1067 
1068 	cpu = curcpu;
1069 	PMCDBG3(MDP,INT, 1, "cpu=%d tf=0x%p um=%d", cpu, (void *) tf,
1070 	    TRAPF_USERMODE(tf));
1071 
1072 	/*
1073 	 * The IA_GLOBAL_STATUS (MSR 0x38E) register indicates which
1074 	 * PMCs have a pending PMI interrupt.  We take a 'snapshot' of
1075 	 * the current set of interrupting PMCs and process these
1076 	 * after stopping them.
1077 	 */
1078 	intrstatus = rdmsr(IA_GLOBAL_STATUS);
1079 	PMCDBG2(MDP,INT, 1, "cpu=%d intrstatus=%jx", cpu,
1080 	    (uintmax_t) intrstatus);
1081 
1082 	/*
1083 	 * Stop PMCs unless hardware already done it.
1084 	 */
1085 	if ((intrstatus & IA_GLOBAL_STATUS_FLAG_CTR_FRZ) == 0)
1086 		wrmsr(IA_GLOBAL_CTRL, 0);
1087 
1088 	cc = core_pcpu[cpu];
1089 	KASSERT(cc != NULL, ("[core,%d] null pcpu", __LINE__));
1090 
1091 	/*
1092 	 * Look for interrupts from fixed function PMCs.
1093 	 */
1094 	for (n = 0, flag = (1ULL << IAF_OFFSET); n < core_iaf_npmc;
1095 	     n++, flag <<= 1) {
1096 
1097 		if ((intrstatus & flag) == 0)
1098 			continue;
1099 
1100 		found_interrupt = 1;
1101 
1102 		pm = cc->pc_corepmcs[n + core_iaf_ri].phw_pmc;
1103 		if (pm == NULL || pm->pm_state != PMC_STATE_RUNNING ||
1104 		    !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
1105 			continue;
1106 
1107 		error = pmc_process_interrupt(PMC_HR, pm, tf);
1108 		if (__predict_false(error))
1109 			intrdisable |= flag;
1110 
1111 		v = iaf_reload_count_to_perfctr_value(pm->pm_sc.pm_reloadcount);
1112 
1113 		/* Reload sampling count. */
1114 		wrmsr(IAF_CTR0 + n, v);
1115 
1116 		PMCDBG4(MDP,INT, 1, "iaf-intr cpu=%d error=%d v=%jx(%jx)", curcpu,
1117 		    error, (uintmax_t) v, (uintmax_t) rdpmc(IAF_RI_TO_MSR(n)));
1118 	}
1119 
1120 	/*
1121 	 * Process interrupts from the programmable counters.
1122 	 */
1123 	for (n = 0, flag = 1; n < core_iap_npmc; n++, flag <<= 1) {
1124 		if ((intrstatus & flag) == 0)
1125 			continue;
1126 
1127 		found_interrupt = 1;
1128 
1129 		pm = cc->pc_corepmcs[n].phw_pmc;
1130 		if (pm == NULL || pm->pm_state != PMC_STATE_RUNNING ||
1131 		    !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
1132 			continue;
1133 
1134 		error = pmc_process_interrupt(PMC_HR, pm, tf);
1135 		if (__predict_false(error))
1136 			intrdisable |= flag;
1137 
1138 		v = iap_reload_count_to_perfctr_value(pm->pm_sc.pm_reloadcount);
1139 
1140 		PMCDBG3(MDP,INT, 1, "iap-intr cpu=%d error=%d v=%jx", cpu, error,
1141 		    (uintmax_t) v);
1142 
1143 		/* Reload sampling count. */
1144 		wrmsr(core_iap_wroffset + IAP_PMC0 + n, v);
1145 	}
1146 
1147 	if (found_interrupt)
1148 		counter_u64_add(pmc_stats.pm_intr_processed, 1);
1149 	else
1150 		counter_u64_add(pmc_stats.pm_intr_ignored, 1);
1151 
1152 	if (found_interrupt)
1153 		lapic_reenable_pmc();
1154 
1155 	/*
1156 	 * Reenable all non-stalled PMCs.
1157 	 */
1158 	if ((intrstatus & IA_GLOBAL_STATUS_FLAG_CTR_FRZ) == 0) {
1159 		wrmsr(IA_GLOBAL_OVF_CTRL, intrstatus);
1160 		cc->pc_globalctrl &= ~intrdisable;
1161 		wrmsr(IA_GLOBAL_CTRL, cc->pc_globalctrl);
1162 	} else {
1163 		if (__predict_false(intrdisable)) {
1164 			cc->pc_globalctrl &= ~intrdisable;
1165 			wrmsr(IA_GLOBAL_CTRL, cc->pc_globalctrl);
1166 		}
1167 		wrmsr(IA_GLOBAL_OVF_CTRL, intrstatus);
1168 	}
1169 
1170 	PMCDBG4(MDP, INT, 1, "cpu=%d fixedctrl=%jx globalctrl=%jx status=%jx",
1171 	    cpu, (uintmax_t) rdmsr(IAF_CTRL),
1172 	    (uintmax_t) rdmsr(IA_GLOBAL_CTRL),
1173 	    (uintmax_t) rdmsr(IA_GLOBAL_STATUS));
1174 
1175 	return (found_interrupt);
1176 }
1177 
1178 int
1179 pmc_core_initialize(struct pmc_mdep *md, int maxcpu, int version_override)
1180 {
1181 	int cpuid[CORE_CPUID_REQUEST_SIZE];
1182 	int flags, nflags;
1183 
1184 	do_cpuid(CORE_CPUID_REQUEST, cpuid);
1185 
1186 	core_cputype = md->pmd_cputype;
1187 	core_version = (version_override > 0) ? version_override :
1188 	    cpuid[CORE_CPUID_EAX] & 0xFF;
1189 
1190 	PMCDBG3(MDP,INI,1,"core-init cputype=%d ncpu=%d version=%d",
1191 	    core_cputype, maxcpu, core_version);
1192 
1193 	if (core_version < 1 || core_version > 5 ||
1194 	    (core_cputype != PMC_CPU_INTEL_CORE && core_version == 1)) {
1195 		/* Unknown PMC architecture. */
1196 		printf("hwpmc_core: unknown PMC architecture: %d\n",
1197 		    core_version);
1198 		return (EPROGMISMATCH);
1199 	}
1200 
1201 	core_iap_wroffset = 0;
1202 	if (cpu_feature2 & CPUID2_PDCM) {
1203 		if (rdmsr(IA32_PERF_CAPABILITIES) & PERFCAP_FW_WRITE) {
1204 			PMCDBG0(MDP, INI, 1,
1205 			    "core-init full-width write supported");
1206 			core_iap_wroffset = IAP_A_PMC0 - IAP_PMC0;
1207 		} else
1208 			PMCDBG0(MDP, INI, 1,
1209 			    "core-init full-width write NOT supported");
1210 	} else
1211 		PMCDBG0(MDP, INI, 1, "core-init pdcm not supported");
1212 
1213 	core_pmcmask = 0;
1214 
1215 	/*
1216 	 * Initialize programmable counters.
1217 	 */
1218 	core_iap_npmc = (cpuid[CORE_CPUID_EAX] >> 8) & 0xFF;
1219 	core_iap_width = (cpuid[CORE_CPUID_EAX] >> 16) & 0xFF;
1220 
1221 	core_pmcmask |= ((1ULL << core_iap_npmc) - 1);
1222 
1223 	nflags = (cpuid[CORE_CPUID_EAX] >> 24) & 0xFF;
1224 	flags = cpuid[CORE_CPUID_EBX] & ((1 << nflags) - 1);
1225 
1226 	iap_initialize(md, maxcpu, core_iap_npmc, core_iap_width, flags);
1227 
1228 	/*
1229 	 * Initialize fixed function counters, if present.
1230 	 */
1231 	if (core_version >= 2) {
1232 		core_iaf_ri = core_iap_npmc;
1233 		core_iaf_npmc = cpuid[CORE_CPUID_EDX] & 0x1F;
1234 		core_iaf_width = (cpuid[CORE_CPUID_EDX] >> 5) & 0xFF;
1235 
1236 		iaf_initialize(md, maxcpu, core_iaf_npmc, core_iaf_width);
1237 		core_pmcmask |= ((1ULL << core_iaf_npmc) - 1) << IAF_OFFSET;
1238 	}
1239 
1240 	PMCDBG2(MDP,INI,1,"core-init pmcmask=0x%jx iafri=%d", core_pmcmask,
1241 	    core_iaf_ri);
1242 
1243 	core_pcpu = malloc(sizeof(*core_pcpu) * maxcpu, M_PMC,
1244 	    M_ZERO | M_WAITOK);
1245 
1246 	/*
1247 	 * Choose the appropriate interrupt handler.
1248 	 */
1249 	if (core_version >= 2)
1250 		md->pmd_intr = core2_intr;
1251 	else
1252 		md->pmd_intr = core_intr;
1253 
1254 	return (0);
1255 }
1256 
1257 void
1258 pmc_core_finalize(struct pmc_mdep *md)
1259 {
1260 	PMCDBG0(MDP,INI,1, "core-finalize");
1261 
1262 	for (int i = 0; i < pmc_cpu_max(); i++)
1263 		KASSERT(core_pcpu[i] == NULL,
1264 		    ("[core,%d] non-null pcpu cpu %d", __LINE__, i));
1265 
1266 	free(core_pcpu, M_PMC);
1267 	core_pcpu = NULL;
1268 }
1269