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