xref: /freebsd/lib/libpmc/libpmc.c (revision e6bfd18d21b225af6a0ed67ceeaf1293b7b9eba5)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2003-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 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/module.h>
35 #include <sys/pmc.h>
36 #include <sys/syscall.h>
37 
38 #include <ctype.h>
39 #include <errno.h>
40 #include <err.h>
41 #include <fcntl.h>
42 #include <pmc.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <strings.h>
47 #include <sysexits.h>
48 #include <unistd.h>
49 
50 #include "libpmcinternal.h"
51 
52 /* Function prototypes */
53 #if defined(__amd64__) || defined(__i386__)
54 static int k8_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
55     struct pmc_op_pmcallocate *_pmc_config);
56 #endif
57 #if defined(__amd64__) || defined(__i386__)
58 static int tsc_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
59     struct pmc_op_pmcallocate *_pmc_config);
60 #endif
61 #if defined(__arm__)
62 static int armv7_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
63     struct pmc_op_pmcallocate *_pmc_config);
64 #endif
65 #if defined(__aarch64__)
66 static int arm64_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
67     struct pmc_op_pmcallocate *_pmc_config);
68 static int cmn600_pmu_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
69     struct pmc_op_pmcallocate *_pmc_config);
70 static int dmc620_pmu_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
71     struct pmc_op_pmcallocate *_pmc_config);
72 #endif
73 static int soft_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
74     struct pmc_op_pmcallocate *_pmc_config);
75 
76 #if defined(__powerpc__)
77 static int powerpc_allocate_pmc(enum pmc_event _pe, char* ctrspec,
78 			     struct pmc_op_pmcallocate *_pmc_config);
79 #endif /* __powerpc__ */
80 
81 #define PMC_CALL(op, params)	syscall(pmc_syscall, (op), (params))
82 
83 /*
84  * Event aliases provide a way for the user to ask for generic events
85  * like "cache-misses", or "instructions-retired".  These aliases are
86  * mapped to the appropriate canonical event descriptions using a
87  * lookup table.
88  */
89 struct pmc_event_alias {
90 	const char	*pm_alias;
91 	const char	*pm_spec;
92 };
93 
94 static const struct pmc_event_alias *pmc_mdep_event_aliases;
95 
96 /*
97  * The pmc_event_descr structure maps symbolic names known to the user
98  * to integer codes used by the PMC KLD.
99  */
100 struct pmc_event_descr {
101 	const char	*pm_ev_name;
102 	enum pmc_event	pm_ev_code;
103 };
104 
105 /*
106  * The pmc_class_descr structure maps class name prefixes for
107  * event names to event tables and other PMC class data.
108  */
109 struct pmc_class_descr {
110 	const char	*pm_evc_name;
111 	size_t		pm_evc_name_size;
112 	enum pmc_class	pm_evc_class;
113 	const struct pmc_event_descr *pm_evc_event_table;
114 	size_t		pm_evc_event_table_size;
115 	int		(*pm_evc_allocate_pmc)(enum pmc_event _pe,
116 			    char *_ctrspec, struct pmc_op_pmcallocate *_pa);
117 };
118 
119 #define	PMC_TABLE_SIZE(N)	(sizeof(N)/sizeof(N[0]))
120 #define	PMC_EVENT_TABLE_SIZE(N)	PMC_TABLE_SIZE(N##_event_table)
121 
122 #undef	__PMC_EV
123 #define	__PMC_EV(C,N) { #N, PMC_EV_ ## C ## _ ## N },
124 
125 /*
126  * PMC_CLASSDEP_TABLE(NAME, CLASS)
127  *
128  * Define a table mapping event names and aliases to HWPMC event IDs.
129  */
130 #define	PMC_CLASSDEP_TABLE(N, C)				\
131 	static const struct pmc_event_descr N##_event_table[] =	\
132 	{							\
133 		__PMC_EV_##C()					\
134 	}
135 
136 PMC_CLASSDEP_TABLE(iaf, IAF);
137 PMC_CLASSDEP_TABLE(k8, K8);
138 PMC_CLASSDEP_TABLE(armv7, ARMV7);
139 PMC_CLASSDEP_TABLE(armv8, ARMV8);
140 PMC_CLASSDEP_TABLE(cmn600_pmu, CMN600_PMU);
141 PMC_CLASSDEP_TABLE(dmc620_pmu_cd2, DMC620_PMU_CD2);
142 PMC_CLASSDEP_TABLE(dmc620_pmu_c, DMC620_PMU_C);
143 PMC_CLASSDEP_TABLE(ppc7450, PPC7450);
144 PMC_CLASSDEP_TABLE(ppc970, PPC970);
145 PMC_CLASSDEP_TABLE(e500, E500);
146 
147 static struct pmc_event_descr soft_event_table[PMC_EV_DYN_COUNT];
148 
149 #undef	__PMC_EV_ALIAS
150 #define	__PMC_EV_ALIAS(N,CODE) 	{ N, PMC_EV_##CODE },
151 
152 /*
153  * TODO: Factor out the __PMC_EV_ARMV7/8 list into a single separate table
154  * rather than duplicating for each core.
155  */
156 
157 static const struct pmc_event_descr cortex_a8_event_table[] =
158 {
159 	__PMC_EV_ALIAS_ARMV7_CORTEX_A8()
160 	__PMC_EV_ARMV7()
161 };
162 
163 static const struct pmc_event_descr cortex_a9_event_table[] =
164 {
165 	__PMC_EV_ALIAS_ARMV7_CORTEX_A9()
166 	__PMC_EV_ARMV7()
167 };
168 
169 static const struct pmc_event_descr cortex_a53_event_table[] =
170 {
171 	__PMC_EV_ALIAS_ARMV8_CORTEX_A53()
172 	__PMC_EV_ARMV8()
173 };
174 
175 static const struct pmc_event_descr cortex_a57_event_table[] =
176 {
177 	__PMC_EV_ALIAS_ARMV8_CORTEX_A57()
178 	__PMC_EV_ARMV8()
179 };
180 
181 static const struct pmc_event_descr cortex_a76_event_table[] =
182 {
183 	__PMC_EV_ALIAS_ARMV8_CORTEX_A76()
184 	__PMC_EV_ARMV8()
185 };
186 
187 static const struct pmc_event_descr tsc_event_table[] =
188 {
189 	__PMC_EV_ALIAS_TSC()
190 };
191 
192 #undef	PMC_CLASS_TABLE_DESC
193 #define	PMC_CLASS_TABLE_DESC(NAME, CLASS, EVENTS, ALLOCATOR)	\
194 static const struct pmc_class_descr NAME##_class_table_descr =	\
195 	{							\
196 		.pm_evc_name  = #CLASS "-",			\
197 		.pm_evc_name_size = sizeof(#CLASS "-") - 1,	\
198 		.pm_evc_class = PMC_CLASS_##CLASS ,		\
199 		.pm_evc_event_table = EVENTS##_event_table ,	\
200 		.pm_evc_event_table_size = 			\
201 			PMC_EVENT_TABLE_SIZE(EVENTS),		\
202 		.pm_evc_allocate_pmc = ALLOCATOR##_allocate_pmc	\
203 	}
204 
205 #if	defined(__i386__) || defined(__amd64__)
206 PMC_CLASS_TABLE_DESC(k8, K8, k8, k8);
207 #endif
208 #if	defined(__i386__) || defined(__amd64__)
209 PMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc);
210 #endif
211 #if	defined(__arm__)
212 PMC_CLASS_TABLE_DESC(cortex_a8, ARMV7, cortex_a8, armv7);
213 PMC_CLASS_TABLE_DESC(cortex_a9, ARMV7, cortex_a9, armv7);
214 #endif
215 #if	defined(__aarch64__)
216 PMC_CLASS_TABLE_DESC(cortex_a53, ARMV8, cortex_a53, arm64);
217 PMC_CLASS_TABLE_DESC(cortex_a57, ARMV8, cortex_a57, arm64);
218 PMC_CLASS_TABLE_DESC(cortex_a76, ARMV8, cortex_a76, arm64);
219 PMC_CLASS_TABLE_DESC(cmn600_pmu, CMN600_PMU, cmn600_pmu, cmn600_pmu);
220 PMC_CLASS_TABLE_DESC(dmc620_pmu_cd2, DMC620_PMU_CD2, dmc620_pmu_cd2, dmc620_pmu);
221 PMC_CLASS_TABLE_DESC(dmc620_pmu_c, DMC620_PMU_C, dmc620_pmu_c, dmc620_pmu);
222 #endif
223 #if defined(__powerpc__)
224 PMC_CLASS_TABLE_DESC(ppc7450, PPC7450, ppc7450, powerpc);
225 PMC_CLASS_TABLE_DESC(ppc970, PPC970, ppc970, powerpc);
226 PMC_CLASS_TABLE_DESC(e500, E500, e500, powerpc);
227 #endif
228 
229 static struct pmc_class_descr soft_class_table_descr =
230 {
231 	.pm_evc_name  = "SOFT-",
232 	.pm_evc_name_size = sizeof("SOFT-") - 1,
233 	.pm_evc_class = PMC_CLASS_SOFT,
234 	.pm_evc_event_table = NULL,
235 	.pm_evc_event_table_size = 0,
236 	.pm_evc_allocate_pmc = soft_allocate_pmc
237 };
238 
239 #undef	PMC_CLASS_TABLE_DESC
240 
241 static const struct pmc_class_descr **pmc_class_table;
242 #define	PMC_CLASS_TABLE_SIZE	cpu_info.pm_nclass
243 
244 /*
245  * Mapping tables, mapping enumeration values to human readable
246  * strings.
247  */
248 
249 static const char * pmc_capability_names[] = {
250 #undef	__PMC_CAP
251 #define	__PMC_CAP(N,V,D)	#N ,
252 	__PMC_CAPS()
253 };
254 
255 struct pmc_class_map {
256 	enum pmc_class	pm_class;
257 	const char	*pm_name;
258 };
259 
260 static const struct pmc_class_map pmc_class_names[] = {
261 #undef	__PMC_CLASS
262 #define __PMC_CLASS(S,V,D) { .pm_class = PMC_CLASS_##S, .pm_name = #S } ,
263 	__PMC_CLASSES()
264 };
265 
266 struct pmc_cputype_map {
267 	enum pmc_cputype pm_cputype;
268 	const char	*pm_name;
269 };
270 
271 static const struct pmc_cputype_map pmc_cputype_names[] = {
272 #undef	__PMC_CPU
273 #define	__PMC_CPU(S, V, D) { .pm_cputype = PMC_CPU_##S, .pm_name = #S } ,
274 	__PMC_CPUS()
275 };
276 
277 static const char * pmc_disposition_names[] = {
278 #undef	__PMC_DISP
279 #define	__PMC_DISP(D)	#D ,
280 	__PMC_DISPOSITIONS()
281 };
282 
283 static const char * pmc_mode_names[] = {
284 #undef  __PMC_MODE
285 #define __PMC_MODE(M,N)	#M ,
286 	__PMC_MODES()
287 };
288 
289 static const char * pmc_state_names[] = {
290 #undef  __PMC_STATE
291 #define __PMC_STATE(S) #S ,
292 	__PMC_STATES()
293 };
294 
295 /*
296  * Filled in by pmc_init().
297  */
298 static int pmc_syscall = -1;
299 static struct pmc_cpuinfo cpu_info;
300 static struct pmc_op_getdyneventinfo soft_event_info;
301 
302 /* Event masks for events */
303 struct pmc_masks {
304 	const char	*pm_name;
305 	const uint64_t	pm_value;
306 };
307 #define	PMCMASK(N,V)	{ .pm_name = #N, .pm_value = (V) }
308 #define	NULLMASK	{ .pm_name = NULL }
309 
310 #if defined(__amd64__) || defined(__i386__)
311 static int
312 pmc_parse_mask(const struct pmc_masks *pmask, char *p, uint64_t *evmask)
313 {
314 	const struct pmc_masks *pm;
315 	char *q, *r;
316 	int c;
317 
318 	if (pmask == NULL)	/* no mask keywords */
319 		return (-1);
320 	q = strchr(p, '=');	/* skip '=' */
321 	if (*++q == '\0')	/* no more data */
322 		return (-1);
323 	c = 0;			/* count of mask keywords seen */
324 	while ((r = strsep(&q, "+")) != NULL) {
325 		for (pm = pmask; pm->pm_name && strcasecmp(r, pm->pm_name);
326 		    pm++)
327 			;
328 		if (pm->pm_name == NULL) /* not found */
329 			return (-1);
330 		*evmask |= pm->pm_value;
331 		c++;
332 	}
333 	return (c);
334 }
335 #endif
336 
337 #define	KWMATCH(p,kw)		(strcasecmp((p), (kw)) == 0)
338 #define	KWPREFIXMATCH(p,kw)	(strncasecmp((p), (kw), sizeof((kw)) - 1) == 0)
339 #define	EV_ALIAS(N,S)		{ .pm_alias = N, .pm_spec = S }
340 
341 #if defined(__amd64__) || defined(__i386__)
342 /*
343  * AMD K8 PMCs.
344  *
345  */
346 
347 static struct pmc_event_alias k8_aliases[] = {
348 	EV_ALIAS("branches",		"k8-fr-retired-taken-branches"),
349 	EV_ALIAS("branch-mispredicts",
350 	    "k8-fr-retired-taken-branches-mispredicted"),
351 	EV_ALIAS("cycles",		"tsc"),
352 	EV_ALIAS("dc-misses",		"k8-dc-miss"),
353 	EV_ALIAS("ic-misses",		"k8-ic-miss"),
354 	EV_ALIAS("instructions",	"k8-fr-retired-x86-instructions"),
355 	EV_ALIAS("interrupts",		"k8-fr-taken-hardware-interrupts"),
356 	EV_ALIAS("unhalted-cycles",	"k8-bu-cpu-clk-unhalted"),
357 	EV_ALIAS(NULL, NULL)
358 };
359 
360 #define	__K8MASK(N,V) PMCMASK(N,(1 << (V)))
361 
362 /*
363  * Parsing tables
364  */
365 
366 /* fp dispatched fpu ops */
367 static const struct pmc_masks k8_mask_fdfo[] = {
368 	__K8MASK(add-pipe-excluding-junk-ops,	0),
369 	__K8MASK(multiply-pipe-excluding-junk-ops,	1),
370 	__K8MASK(store-pipe-excluding-junk-ops,	2),
371 	__K8MASK(add-pipe-junk-ops,		3),
372 	__K8MASK(multiply-pipe-junk-ops,	4),
373 	__K8MASK(store-pipe-junk-ops,		5),
374 	NULLMASK
375 };
376 
377 /* ls segment register loads */
378 static const struct pmc_masks k8_mask_lsrl[] = {
379 	__K8MASK(es,	0),
380 	__K8MASK(cs,	1),
381 	__K8MASK(ss,	2),
382 	__K8MASK(ds,	3),
383 	__K8MASK(fs,	4),
384 	__K8MASK(gs,	5),
385 	__K8MASK(hs,	6),
386 	NULLMASK
387 };
388 
389 /* ls locked operation */
390 static const struct pmc_masks k8_mask_llo[] = {
391 	__K8MASK(locked-instructions,	0),
392 	__K8MASK(cycles-in-request,	1),
393 	__K8MASK(cycles-to-complete,	2),
394 	NULLMASK
395 };
396 
397 /* dc refill from {l2,system} and dc copyback */
398 static const struct pmc_masks k8_mask_dc[] = {
399 	__K8MASK(invalid,	0),
400 	__K8MASK(shared,	1),
401 	__K8MASK(exclusive,	2),
402 	__K8MASK(owner,		3),
403 	__K8MASK(modified,	4),
404 	NULLMASK
405 };
406 
407 /* dc one bit ecc error */
408 static const struct pmc_masks k8_mask_dobee[] = {
409 	__K8MASK(scrubber,	0),
410 	__K8MASK(piggyback,	1),
411 	NULLMASK
412 };
413 
414 /* dc dispatched prefetch instructions */
415 static const struct pmc_masks k8_mask_ddpi[] = {
416 	__K8MASK(load,	0),
417 	__K8MASK(store,	1),
418 	__K8MASK(nta,	2),
419 	NULLMASK
420 };
421 
422 /* dc dcache accesses by locks */
423 static const struct pmc_masks k8_mask_dabl[] = {
424 	__K8MASK(accesses,	0),
425 	__K8MASK(misses,	1),
426 	NULLMASK
427 };
428 
429 /* bu internal l2 request */
430 static const struct pmc_masks k8_mask_bilr[] = {
431 	__K8MASK(ic-fill,	0),
432 	__K8MASK(dc-fill,	1),
433 	__K8MASK(tlb-reload,	2),
434 	__K8MASK(tag-snoop,	3),
435 	__K8MASK(cancelled,	4),
436 	NULLMASK
437 };
438 
439 /* bu fill request l2 miss */
440 static const struct pmc_masks k8_mask_bfrlm[] = {
441 	__K8MASK(ic-fill,	0),
442 	__K8MASK(dc-fill,	1),
443 	__K8MASK(tlb-reload,	2),
444 	NULLMASK
445 };
446 
447 /* bu fill into l2 */
448 static const struct pmc_masks k8_mask_bfil[] = {
449 	__K8MASK(dirty-l2-victim,	0),
450 	__K8MASK(victim-from-l2,	1),
451 	NULLMASK
452 };
453 
454 /* fr retired fpu instructions */
455 static const struct pmc_masks k8_mask_frfi[] = {
456 	__K8MASK(x87,			0),
457 	__K8MASK(mmx-3dnow,		1),
458 	__K8MASK(packed-sse-sse2,	2),
459 	__K8MASK(scalar-sse-sse2,	3),
460 	NULLMASK
461 };
462 
463 /* fr retired fastpath double op instructions */
464 static const struct pmc_masks k8_mask_frfdoi[] = {
465 	__K8MASK(low-op-pos-0,		0),
466 	__K8MASK(low-op-pos-1,		1),
467 	__K8MASK(low-op-pos-2,		2),
468 	NULLMASK
469 };
470 
471 /* fr fpu exceptions */
472 static const struct pmc_masks k8_mask_ffe[] = {
473 	__K8MASK(x87-reclass-microfaults,	0),
474 	__K8MASK(sse-retype-microfaults,	1),
475 	__K8MASK(sse-reclass-microfaults,	2),
476 	__K8MASK(sse-and-x87-microtraps,	3),
477 	NULLMASK
478 };
479 
480 /* nb memory controller page access event */
481 static const struct pmc_masks k8_mask_nmcpae[] = {
482 	__K8MASK(page-hit,	0),
483 	__K8MASK(page-miss,	1),
484 	__K8MASK(page-conflict,	2),
485 	NULLMASK
486 };
487 
488 /* nb memory controller turnaround */
489 static const struct pmc_masks k8_mask_nmct[] = {
490 	__K8MASK(dimm-turnaround,		0),
491 	__K8MASK(read-to-write-turnaround,	1),
492 	__K8MASK(write-to-read-turnaround,	2),
493 	NULLMASK
494 };
495 
496 /* nb memory controller bypass saturation */
497 static const struct pmc_masks k8_mask_nmcbs[] = {
498 	__K8MASK(memory-controller-hi-pri-bypass,	0),
499 	__K8MASK(memory-controller-lo-pri-bypass,	1),
500 	__K8MASK(dram-controller-interface-bypass,	2),
501 	__K8MASK(dram-controller-queue-bypass,		3),
502 	NULLMASK
503 };
504 
505 /* nb sized commands */
506 static const struct pmc_masks k8_mask_nsc[] = {
507 	__K8MASK(nonpostwrszbyte,	0),
508 	__K8MASK(nonpostwrszdword,	1),
509 	__K8MASK(postwrszbyte,		2),
510 	__K8MASK(postwrszdword,		3),
511 	__K8MASK(rdszbyte,		4),
512 	__K8MASK(rdszdword,		5),
513 	__K8MASK(rdmodwr,		6),
514 	NULLMASK
515 };
516 
517 /* nb probe result */
518 static const struct pmc_masks k8_mask_npr[] = {
519 	__K8MASK(probe-miss,		0),
520 	__K8MASK(probe-hit,		1),
521 	__K8MASK(probe-hit-dirty-no-memory-cancel, 2),
522 	__K8MASK(probe-hit-dirty-with-memory-cancel, 3),
523 	NULLMASK
524 };
525 
526 /* nb hypertransport bus bandwidth */
527 static const struct pmc_masks k8_mask_nhbb[] = { /* HT bus bandwidth */
528 	__K8MASK(command,	0),
529 	__K8MASK(data,	1),
530 	__K8MASK(buffer-release, 2),
531 	__K8MASK(nop,	3),
532 	NULLMASK
533 };
534 
535 #undef	__K8MASK
536 
537 #define	K8_KW_COUNT	"count"
538 #define	K8_KW_EDGE	"edge"
539 #define	K8_KW_INV	"inv"
540 #define	K8_KW_MASK	"mask"
541 #define	K8_KW_OS	"os"
542 #define	K8_KW_USR	"usr"
543 
544 static int
545 k8_allocate_pmc(enum pmc_event pe, char *ctrspec,
546     struct pmc_op_pmcallocate *pmc_config)
547 {
548 	char		*e, *p, *q;
549 	int		n;
550 	uint32_t	count;
551 	uint64_t	evmask;
552 	const struct pmc_masks	*pm, *pmask;
553 
554 	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
555 	pmc_config->pm_md.pm_amd.pm_amd_config = 0;
556 
557 	pmask = NULL;
558 	evmask = 0;
559 
560 #define	__K8SETMASK(M) pmask = k8_mask_##M
561 
562 	/* setup parsing tables */
563 	switch (pe) {
564 	case PMC_EV_K8_FP_DISPATCHED_FPU_OPS:
565 		__K8SETMASK(fdfo);
566 		break;
567 	case PMC_EV_K8_LS_SEGMENT_REGISTER_LOAD:
568 		__K8SETMASK(lsrl);
569 		break;
570 	case PMC_EV_K8_LS_LOCKED_OPERATION:
571 		__K8SETMASK(llo);
572 		break;
573 	case PMC_EV_K8_DC_REFILL_FROM_L2:
574 	case PMC_EV_K8_DC_REFILL_FROM_SYSTEM:
575 	case PMC_EV_K8_DC_COPYBACK:
576 		__K8SETMASK(dc);
577 		break;
578 	case PMC_EV_K8_DC_ONE_BIT_ECC_ERROR:
579 		__K8SETMASK(dobee);
580 		break;
581 	case PMC_EV_K8_DC_DISPATCHED_PREFETCH_INSTRUCTIONS:
582 		__K8SETMASK(ddpi);
583 		break;
584 	case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS:
585 		__K8SETMASK(dabl);
586 		break;
587 	case PMC_EV_K8_BU_INTERNAL_L2_REQUEST:
588 		__K8SETMASK(bilr);
589 		break;
590 	case PMC_EV_K8_BU_FILL_REQUEST_L2_MISS:
591 		__K8SETMASK(bfrlm);
592 		break;
593 	case PMC_EV_K8_BU_FILL_INTO_L2:
594 		__K8SETMASK(bfil);
595 		break;
596 	case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS:
597 		__K8SETMASK(frfi);
598 		break;
599 	case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS:
600 		__K8SETMASK(frfdoi);
601 		break;
602 	case PMC_EV_K8_FR_FPU_EXCEPTIONS:
603 		__K8SETMASK(ffe);
604 		break;
605 	case PMC_EV_K8_NB_MEMORY_CONTROLLER_PAGE_ACCESS_EVENT:
606 		__K8SETMASK(nmcpae);
607 		break;
608 	case PMC_EV_K8_NB_MEMORY_CONTROLLER_TURNAROUND:
609 		__K8SETMASK(nmct);
610 		break;
611 	case PMC_EV_K8_NB_MEMORY_CONTROLLER_BYPASS_SATURATION:
612 		__K8SETMASK(nmcbs);
613 		break;
614 	case PMC_EV_K8_NB_SIZED_COMMANDS:
615 		__K8SETMASK(nsc);
616 		break;
617 	case PMC_EV_K8_NB_PROBE_RESULT:
618 		__K8SETMASK(npr);
619 		break;
620 	case PMC_EV_K8_NB_HT_BUS0_BANDWIDTH:
621 	case PMC_EV_K8_NB_HT_BUS1_BANDWIDTH:
622 	case PMC_EV_K8_NB_HT_BUS2_BANDWIDTH:
623 		__K8SETMASK(nhbb);
624 		break;
625 
626 	default:
627 		break;		/* no options defined */
628 	}
629 
630 	while ((p = strsep(&ctrspec, ",")) != NULL) {
631 		if (KWPREFIXMATCH(p, K8_KW_COUNT "=")) {
632 			q = strchr(p, '=');
633 			if (*++q == '\0') /* skip '=' */
634 				return (-1);
635 
636 			count = strtol(q, &e, 0);
637 			if (e == q || *e != '\0')
638 				return (-1);
639 
640 			pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
641 			pmc_config->pm_md.pm_amd.pm_amd_config |=
642 			    AMD_PMC_TO_COUNTER(count);
643 
644 		} else if (KWMATCH(p, K8_KW_EDGE)) {
645 			pmc_config->pm_caps |= PMC_CAP_EDGE;
646 		} else if (KWMATCH(p, K8_KW_INV)) {
647 			pmc_config->pm_caps |= PMC_CAP_INVERT;
648 		} else if (KWPREFIXMATCH(p, K8_KW_MASK "=")) {
649 			if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0)
650 				return (-1);
651 			pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
652 		} else if (KWMATCH(p, K8_KW_OS)) {
653 			pmc_config->pm_caps |= PMC_CAP_SYSTEM;
654 		} else if (KWMATCH(p, K8_KW_USR)) {
655 			pmc_config->pm_caps |= PMC_CAP_USER;
656 		} else
657 			return (-1);
658 	}
659 
660 	/* other post processing */
661 	switch (pe) {
662 	case PMC_EV_K8_FP_DISPATCHED_FPU_OPS:
663 	case PMC_EV_K8_FP_CYCLES_WITH_NO_FPU_OPS_RETIRED:
664 	case PMC_EV_K8_FP_DISPATCHED_FPU_FAST_FLAG_OPS:
665 	case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS:
666 	case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS:
667 	case PMC_EV_K8_FR_FPU_EXCEPTIONS:
668 		/* XXX only available in rev B and later */
669 		break;
670 	case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS:
671 		/* XXX only available in rev C and later */
672 		break;
673 	case PMC_EV_K8_LS_LOCKED_OPERATION:
674 		/* XXX CPU Rev A,B evmask is to be zero */
675 		if (evmask & (evmask - 1)) /* > 1 bit set */
676 			return (-1);
677 		if (evmask == 0) {
678 			evmask = 0x01; /* Rev C and later: #instrs */
679 			pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
680 		}
681 		break;
682 	default:
683 		if (evmask == 0 && pmask != NULL) {
684 			for (pm = pmask; pm->pm_name; pm++)
685 				evmask |= pm->pm_value;
686 			pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
687 		}
688 	}
689 
690 	if (pmc_config->pm_caps & PMC_CAP_QUALIFIER)
691 		pmc_config->pm_md.pm_amd.pm_amd_config =
692 		    AMD_PMC_TO_UNITMASK(evmask);
693 
694 	return (0);
695 }
696 
697 #endif
698 
699 #if	defined(__i386__) || defined(__amd64__)
700 static int
701 tsc_allocate_pmc(enum pmc_event pe, char *ctrspec,
702     struct pmc_op_pmcallocate *pmc_config)
703 {
704 	if (pe != PMC_EV_TSC_TSC)
705 		return (-1);
706 
707 	/* TSC events must be unqualified. */
708 	if (ctrspec && *ctrspec != '\0')
709 		return (-1);
710 
711 	pmc_config->pm_md.pm_amd.pm_amd_config = 0;
712 	pmc_config->pm_caps |= PMC_CAP_READ;
713 
714 	return (0);
715 }
716 #endif
717 
718 static struct pmc_event_alias generic_aliases[] = {
719 	EV_ALIAS("instructions",		"SOFT-CLOCK.HARD"),
720 	EV_ALIAS(NULL, NULL)
721 };
722 
723 static int
724 soft_allocate_pmc(enum pmc_event pe, char *ctrspec,
725     struct pmc_op_pmcallocate *pmc_config)
726 {
727 	(void)ctrspec;
728 	(void)pmc_config;
729 
730 	if ((int)pe < PMC_EV_SOFT_FIRST || (int)pe > PMC_EV_SOFT_LAST)
731 		return (-1);
732 
733 	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
734 	return (0);
735 }
736 
737 #if	defined(__arm__)
738 static struct pmc_event_alias cortex_a8_aliases[] = {
739 	EV_ALIAS("dc-misses",		"L1_DCACHE_REFILL"),
740 	EV_ALIAS("ic-misses",		"L1_ICACHE_REFILL"),
741 	EV_ALIAS("instructions",	"INSTR_EXECUTED"),
742 	EV_ALIAS(NULL, NULL)
743 };
744 
745 static struct pmc_event_alias cortex_a9_aliases[] = {
746 	EV_ALIAS("dc-misses",		"L1_DCACHE_REFILL"),
747 	EV_ALIAS("ic-misses",		"L1_ICACHE_REFILL"),
748 	EV_ALIAS("instructions",	"INSTR_EXECUTED"),
749 	EV_ALIAS(NULL, NULL)
750 };
751 
752 static int
753 armv7_allocate_pmc(enum pmc_event pe, char *ctrspec __unused,
754     struct pmc_op_pmcallocate *pmc_config __unused)
755 {
756 	switch (pe) {
757 	default:
758 		break;
759 	}
760 
761 	return (0);
762 }
763 #endif
764 
765 #if	defined(__aarch64__)
766 static struct pmc_event_alias cortex_a53_aliases[] = {
767 	EV_ALIAS(NULL, NULL)
768 };
769 static struct pmc_event_alias cortex_a57_aliases[] = {
770 	EV_ALIAS(NULL, NULL)
771 };
772 static struct pmc_event_alias cortex_a76_aliases[] = {
773 	EV_ALIAS(NULL, NULL)
774 };
775 
776 static int
777 arm64_allocate_pmc(enum pmc_event pe, char *ctrspec,
778     struct pmc_op_pmcallocate *pmc_config)
779 {
780 	char *p;
781 
782 	while ((p = strsep(&ctrspec, ",")) != NULL) {
783 		if (KWMATCH(p, "os"))
784 			pmc_config->pm_caps |= PMC_CAP_SYSTEM;
785 		else if (KWMATCH(p, "usr"))
786 			pmc_config->pm_caps |= PMC_CAP_USER;
787 		else
788 			return (-1);
789 	}
790 
791 	return (0);
792 }
793 
794 static int
795 cmn600_pmu_allocate_pmc(enum pmc_event pe, char *ctrspec,
796     struct pmc_op_pmcallocate *pmc_config)
797 {
798 	uint32_t nodeid, occupancy, xpport, xpchannel;
799 	char *e, *p, *q;
800 	unsigned int i;
801 	char *xpport_names[] = { "East", "West", "North", "South", "devport0",
802 	    "devport1" };
803 	char *xpchannel_names[] = { "REQ", "RSP", "SNP", "DAT" };
804 
805 	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
806 	pmc_config->pm_caps |= PMC_CAP_SYSTEM;
807 	pmc_config->pm_md.pm_cmn600.pma_cmn600_config = 0;
808 	/*
809 	 * CMN600 extra fields:
810 	 * * nodeid - node coordinates x[2-3],y[2-3],p[1],s[2]
811 	 * 		width of x and y fields depend on matrix size.
812 	 * * occupancy - numeric value to select desired filter.
813 	 * * xpport - East, West, North, South, devport0, devport1 (or 0, 1, ..., 5)
814 	 * * xpchannel - REQ, RSP, SNP, DAT (or 0, 1, 2, 3)
815 	 */
816 
817 	while ((p = strsep(&ctrspec, ",")) != NULL) {
818 		if (KWPREFIXMATCH(p, "nodeid=")) {
819 			q = strchr(p, '=');
820 			if (*++q == '\0') /* skip '=' */
821 				return (-1);
822 
823 			nodeid = strtol(q, &e, 0);
824 			if (e == q || *e != '\0')
825 				return (-1);
826 
827 			pmc_config->pm_md.pm_cmn600.pma_cmn600_nodeid |= nodeid;
828 
829 		} else if (KWPREFIXMATCH(p, "occupancy=")) {
830 			q = strchr(p, '=');
831 			if (*++q == '\0') /* skip '=' */
832 				return (-1);
833 
834 			occupancy = strtol(q, &e, 0);
835 			if (e == q || *e != '\0')
836 				return (-1);
837 
838 			pmc_config->pm_md.pm_cmn600.pma_cmn600_occupancy = occupancy;
839 		} else if (KWPREFIXMATCH(p, "xpport=")) {
840 			q = strchr(p, '=');
841 			if (*++q == '\0') /* skip '=' */
842 				return (-1);
843 
844 			xpport = strtol(q, &e, 0);
845 			if (e == q || *e != '\0') {
846 				for (i = 0; i < nitems(xpport_names); i++) {
847 					if (strcasecmp(xpport_names[i], q) == 0) {
848 						xpport = i;
849 						break;
850 					}
851 				}
852 				if (i == nitems(xpport_names))
853 					return (-1);
854 			}
855 
856 			pmc_config->pm_md.pm_cmn600.pma_cmn600_config |= xpport << 2;
857 		} else if (KWPREFIXMATCH(p, "xpchannel=")) {
858 			q = strchr(p, '=');
859 			if (*++q == '\0') /* skip '=' */
860 				return (-1);
861 
862 			xpchannel = strtol(q, &e, 0);
863 			if (e == q || *e != '\0') {
864 				for (i = 0; i < nitems(xpchannel_names); i++) {
865 					if (strcasecmp(xpchannel_names[i], q) == 0) {
866 						xpchannel = i;
867 						break;
868 					}
869 				}
870 				if (i == nitems(xpchannel_names))
871 					return (-1);
872 			}
873 
874 			pmc_config->pm_md.pm_cmn600.pma_cmn600_config |= xpchannel << 5;
875 		} else
876 			return (-1);
877 	}
878 
879 	return (0);
880 }
881 
882 static int
883 dmc620_pmu_allocate_pmc(enum pmc_event pe, char *ctrspec,
884     struct pmc_op_pmcallocate *pmc_config)
885 {
886 	char		*e, *p, *q;
887 	uint64_t	match, mask;
888 	uint32_t	count;
889 
890 	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
891 	pmc_config->pm_caps |= PMC_CAP_SYSTEM;
892 	pmc_config->pm_md.pm_dmc620.pm_dmc620_config = 0;
893 
894 	while ((p = strsep(&ctrspec, ",")) != NULL) {
895 		if (KWPREFIXMATCH(p, "count=")) {
896 			q = strchr(p, '=');
897 			if (*++q == '\0') /* skip '=' */
898 				return (-1);
899 
900 			count = strtol(q, &e, 0);
901 			if (e == q || *e != '\0')
902 				return (-1);
903 
904 			pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
905 			pmc_config->pm_md.pm_dmc620.pm_dmc620_config |= count;
906 
907 		} else if (KWMATCH(p, "inv")) {
908 			pmc_config->pm_caps |= PMC_CAP_INVERT;
909 		} else if (KWPREFIXMATCH(p, "match=")) {
910 			match = strtol(q, &e, 0);
911 			if (e == q || *e != '\0')
912 				return (-1);
913 
914 			pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
915 			pmc_config->pm_md.pm_dmc620.pm_dmc620_match = match;
916 		} else if (KWPREFIXMATCH(p, "mask=")) {
917 			q = strchr(p, '=');
918 			if (*++q == '\0') /* skip '=' */
919 				return (-1);
920 
921 			mask = strtol(q, &e, 0);
922 			if (e == q || *e != '\0')
923 				return (-1);
924 
925 			pmc_config->pm_md.pm_dmc620.pm_dmc620_mask = mask;
926 			pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
927 		} else
928 			return (-1);
929 	}
930 
931 	return (0);
932 }
933 #endif
934 
935 #if defined(__powerpc__)
936 
937 static struct pmc_event_alias ppc7450_aliases[] = {
938 	EV_ALIAS("instructions",	"INSTR_COMPLETED"),
939 	EV_ALIAS("branches",		"BRANCHES_COMPLETED"),
940 	EV_ALIAS("branch-mispredicts",	"MISPREDICTED_BRANCHES"),
941 	EV_ALIAS(NULL, NULL)
942 };
943 
944 static struct pmc_event_alias ppc970_aliases[] = {
945 	EV_ALIAS("instructions", "INSTR_COMPLETED"),
946 	EV_ALIAS("cycles",       "CYCLES"),
947 	EV_ALIAS(NULL, NULL)
948 };
949 
950 static struct pmc_event_alias e500_aliases[] = {
951 	EV_ALIAS("instructions", "INSTR_COMPLETED"),
952 	EV_ALIAS("cycles",       "CYCLES"),
953 	EV_ALIAS(NULL, NULL)
954 };
955 
956 #define	POWERPC_KW_OS		"os"
957 #define	POWERPC_KW_USR		"usr"
958 #define	POWERPC_KW_ANYTHREAD	"anythread"
959 
960 static int
961 powerpc_allocate_pmc(enum pmc_event pe, char *ctrspec __unused,
962 		     struct pmc_op_pmcallocate *pmc_config __unused)
963 {
964 	char *p;
965 
966 	(void) pe;
967 
968 	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
969 
970 	while ((p = strsep(&ctrspec, ",")) != NULL) {
971 		if (KWMATCH(p, POWERPC_KW_OS))
972 			pmc_config->pm_caps |= PMC_CAP_SYSTEM;
973 		else if (KWMATCH(p, POWERPC_KW_USR))
974 			pmc_config->pm_caps |= PMC_CAP_USER;
975 		else if (KWMATCH(p, POWERPC_KW_ANYTHREAD))
976 			pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM);
977 		else
978 			return (-1);
979 	}
980 
981 	return (0);
982 }
983 
984 #endif /* __powerpc__ */
985 
986 
987 /*
988  * Match an event name `name' with its canonical form.
989  *
990  * Matches are case insensitive and spaces, periods, underscores and
991  * hyphen characters are considered to match each other.
992  *
993  * Returns 1 for a match, 0 otherwise.
994  */
995 
996 static int
997 pmc_match_event_name(const char *name, const char *canonicalname)
998 {
999 	int cc, nc;
1000 	const unsigned char *c, *n;
1001 
1002 	c = (const unsigned char *) canonicalname;
1003 	n = (const unsigned char *) name;
1004 
1005 	for (; (nc = *n) && (cc = *c); n++, c++) {
1006 
1007 		if ((nc == ' ' || nc == '_' || nc == '-' || nc == '.') &&
1008 		    (cc == ' ' || cc == '_' || cc == '-' || cc == '.'))
1009 			continue;
1010 
1011 		if (toupper(nc) == toupper(cc))
1012 			continue;
1013 
1014 
1015 		return (0);
1016 	}
1017 
1018 	if (*n == '\0' && *c == '\0')
1019 		return (1);
1020 
1021 	return (0);
1022 }
1023 
1024 /*
1025  * Match an event name against all the event named supported by a
1026  * PMC class.
1027  *
1028  * Returns an event descriptor pointer on match or NULL otherwise.
1029  */
1030 static const struct pmc_event_descr *
1031 pmc_match_event_class(const char *name,
1032     const struct pmc_class_descr *pcd)
1033 {
1034 	size_t n;
1035 	const struct pmc_event_descr *ev;
1036 
1037 	ev = pcd->pm_evc_event_table;
1038 	for (n = 0; n < pcd->pm_evc_event_table_size; n++, ev++)
1039 		if (pmc_match_event_name(name, ev->pm_ev_name))
1040 			return (ev);
1041 
1042 	return (NULL);
1043 }
1044 
1045 /*
1046  * API entry points
1047  */
1048 
1049 int
1050 pmc_allocate(const char *ctrspec, enum pmc_mode mode,
1051     uint32_t flags, int cpu, pmc_id_t *pmcid,
1052     uint64_t count)
1053 {
1054 	size_t n;
1055 	int retval;
1056 	char *r, *spec_copy;
1057 	const char *ctrname;
1058 	const struct pmc_event_descr *ev;
1059 	const struct pmc_event_alias *alias;
1060 	struct pmc_op_pmcallocate pmc_config;
1061 	const struct pmc_class_descr *pcd;
1062 
1063 	spec_copy = NULL;
1064 	retval    = -1;
1065 
1066 	if (mode != PMC_MODE_SS && mode != PMC_MODE_TS &&
1067 	    mode != PMC_MODE_SC && mode != PMC_MODE_TC) {
1068 		errno = EINVAL;
1069 		goto out;
1070 	}
1071 	bzero(&pmc_config, sizeof(pmc_config));
1072 	pmc_config.pm_cpu   = cpu;
1073 	pmc_config.pm_mode  = mode;
1074 	pmc_config.pm_flags = flags;
1075 	pmc_config.pm_count = count;
1076 	if (PMC_IS_SAMPLING_MODE(mode))
1077 		pmc_config.pm_caps |= PMC_CAP_INTERRUPT;
1078 
1079 	/*
1080 	 * Try to pull the raw event ID directly from the pmu-events table. If
1081 	 * this is unsupported on the platform, or the event is not found,
1082 	 * continue with searching the regular event tables.
1083 	 */
1084 	r = spec_copy = strdup(ctrspec);
1085 	ctrname = strsep(&r, ",");
1086 	if (pmc_pmu_enabled()) {
1087 		if (pmc_pmu_pmcallocate(ctrname, &pmc_config) == 0)
1088 			goto found;
1089 
1090 		/* Otherwise, reset any changes */
1091 		pmc_config.pm_ev = 0;
1092 		pmc_config.pm_caps = 0;
1093 		pmc_config.pm_class = 0;
1094 	}
1095 	free(spec_copy);
1096 	spec_copy = NULL;
1097 
1098 	/* replace an event alias with the canonical event specifier */
1099 	if (pmc_mdep_event_aliases)
1100 		for (alias = pmc_mdep_event_aliases; alias->pm_alias; alias++)
1101 			if (!strcasecmp(ctrspec, alias->pm_alias)) {
1102 				spec_copy = strdup(alias->pm_spec);
1103 				break;
1104 			}
1105 
1106 	if (spec_copy == NULL)
1107 		spec_copy = strdup(ctrspec);
1108 
1109 	r = spec_copy;
1110 	ctrname = strsep(&r, ",");
1111 
1112 	/*
1113 	 * If a explicit class prefix was given by the user, restrict the
1114 	 * search for the event to the specified PMC class.
1115 	 */
1116 	ev = NULL;
1117 	for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) {
1118 		pcd = pmc_class_table[n];
1119 		if (pcd != NULL && strncasecmp(ctrname, pcd->pm_evc_name,
1120 		    pcd->pm_evc_name_size) == 0) {
1121 			if ((ev = pmc_match_event_class(ctrname +
1122 			    pcd->pm_evc_name_size, pcd)) == NULL) {
1123 				errno = EINVAL;
1124 				goto out;
1125 			}
1126 			break;
1127 		}
1128 	}
1129 
1130 	/*
1131 	 * Otherwise, search for this event in all compatible PMC
1132 	 * classes.
1133 	 */
1134 	for (n = 0; ev == NULL && n < PMC_CLASS_TABLE_SIZE; n++) {
1135 		pcd = pmc_class_table[n];
1136 		if (pcd != NULL)
1137 			ev = pmc_match_event_class(ctrname, pcd);
1138 	}
1139 
1140 	if (ev == NULL) {
1141 		errno = EINVAL;
1142 		goto out;
1143 	}
1144 
1145 	pmc_config.pm_ev    = ev->pm_ev_code;
1146 	pmc_config.pm_class = pcd->pm_evc_class;
1147 
1148  	if (pcd->pm_evc_allocate_pmc(ev->pm_ev_code, r, &pmc_config) < 0) {
1149 		errno = EINVAL;
1150 		goto out;
1151 	}
1152 
1153 found:
1154 	if (PMC_CALL(PMC_OP_PMCALLOCATE, &pmc_config) == 0) {
1155 		*pmcid = pmc_config.pm_pmcid;
1156 		retval = 0;
1157 	}
1158 out:
1159 	if (spec_copy)
1160 		free(spec_copy);
1161 
1162 	return (retval);
1163 }
1164 
1165 int
1166 pmc_attach(pmc_id_t pmc, pid_t pid)
1167 {
1168 	struct pmc_op_pmcattach pmc_attach_args;
1169 
1170 	pmc_attach_args.pm_pmc = pmc;
1171 	pmc_attach_args.pm_pid = pid;
1172 
1173 	return (PMC_CALL(PMC_OP_PMCATTACH, &pmc_attach_args));
1174 }
1175 
1176 int
1177 pmc_capabilities(pmc_id_t pmcid, uint32_t *caps)
1178 {
1179 	unsigned int i;
1180 	enum pmc_class cl;
1181 
1182 	cl = PMC_ID_TO_CLASS(pmcid);
1183 	for (i = 0; i < cpu_info.pm_nclass; i++)
1184 		if (cpu_info.pm_classes[i].pm_class == cl) {
1185 			*caps = cpu_info.pm_classes[i].pm_caps;
1186 			return (0);
1187 		}
1188 	errno = EINVAL;
1189 	return (-1);
1190 }
1191 
1192 int
1193 pmc_configure_logfile(int fd)
1194 {
1195 	struct pmc_op_configurelog cla;
1196 
1197 	cla.pm_flags = 0;
1198 	cla.pm_logfd = fd;
1199 	if (PMC_CALL(PMC_OP_CONFIGURELOG, &cla) < 0)
1200 		return (-1);
1201 	return (0);
1202 }
1203 
1204 int
1205 pmc_cpuinfo(const struct pmc_cpuinfo **pci)
1206 {
1207 	if (pmc_syscall == -1) {
1208 		errno = ENXIO;
1209 		return (-1);
1210 	}
1211 
1212 	*pci = &cpu_info;
1213 	return (0);
1214 }
1215 
1216 int
1217 pmc_detach(pmc_id_t pmc, pid_t pid)
1218 {
1219 	struct pmc_op_pmcattach pmc_detach_args;
1220 
1221 	pmc_detach_args.pm_pmc = pmc;
1222 	pmc_detach_args.pm_pid = pid;
1223 	return (PMC_CALL(PMC_OP_PMCDETACH, &pmc_detach_args));
1224 }
1225 
1226 int
1227 pmc_disable(int cpu, int pmc)
1228 {
1229 	struct pmc_op_pmcadmin ssa;
1230 
1231 	ssa.pm_cpu = cpu;
1232 	ssa.pm_pmc = pmc;
1233 	ssa.pm_state = PMC_STATE_DISABLED;
1234 	return (PMC_CALL(PMC_OP_PMCADMIN, &ssa));
1235 }
1236 
1237 int
1238 pmc_enable(int cpu, int pmc)
1239 {
1240 	struct pmc_op_pmcadmin ssa;
1241 
1242 	ssa.pm_cpu = cpu;
1243 	ssa.pm_pmc = pmc;
1244 	ssa.pm_state = PMC_STATE_FREE;
1245 	return (PMC_CALL(PMC_OP_PMCADMIN, &ssa));
1246 }
1247 
1248 /*
1249  * Return a list of events known to a given PMC class.  'cl' is the
1250  * PMC class identifier, 'eventnames' is the returned list of 'const
1251  * char *' pointers pointing to the names of the events. 'nevents' is
1252  * the number of event name pointers returned.
1253  *
1254  * The space for 'eventnames' is allocated using malloc(3).  The caller
1255  * is responsible for freeing this space when done.
1256  */
1257 int
1258 pmc_event_names_of_class(enum pmc_class cl, const char ***eventnames,
1259     int *nevents)
1260 {
1261 	int count;
1262 	const char **names;
1263 	const struct pmc_event_descr *ev;
1264 
1265 	switch (cl)
1266 	{
1267 	case PMC_CLASS_IAF:
1268 		ev = iaf_event_table;
1269 		count = PMC_EVENT_TABLE_SIZE(iaf);
1270 		break;
1271 	case PMC_CLASS_TSC:
1272 		ev = tsc_event_table;
1273 		count = PMC_EVENT_TABLE_SIZE(tsc);
1274 		break;
1275 	case PMC_CLASS_K8:
1276 		ev = k8_event_table;
1277 		count = PMC_EVENT_TABLE_SIZE(k8);
1278 		break;
1279 	case PMC_CLASS_ARMV7:
1280 		switch (cpu_info.pm_cputype) {
1281 		default:
1282 		case PMC_CPU_ARMV7_CORTEX_A8:
1283 			ev = cortex_a8_event_table;
1284 			count = PMC_EVENT_TABLE_SIZE(cortex_a8);
1285 			break;
1286 		case PMC_CPU_ARMV7_CORTEX_A9:
1287 			ev = cortex_a9_event_table;
1288 			count = PMC_EVENT_TABLE_SIZE(cortex_a9);
1289 			break;
1290 		}
1291 		break;
1292 	case PMC_CLASS_ARMV8:
1293 		switch (cpu_info.pm_cputype) {
1294 		default:
1295 		case PMC_CPU_ARMV8_CORTEX_A53:
1296 			ev = cortex_a53_event_table;
1297 			count = PMC_EVENT_TABLE_SIZE(cortex_a53);
1298 			break;
1299 		case PMC_CPU_ARMV8_CORTEX_A57:
1300 			ev = cortex_a57_event_table;
1301 			count = PMC_EVENT_TABLE_SIZE(cortex_a57);
1302 			break;
1303 		case PMC_CPU_ARMV8_CORTEX_A76:
1304 			ev = cortex_a76_event_table;
1305 			count = PMC_EVENT_TABLE_SIZE(cortex_a76);
1306 			break;
1307 		}
1308 		break;
1309 	case PMC_CLASS_CMN600_PMU:
1310 		ev = cmn600_pmu_event_table;
1311 		count = PMC_EVENT_TABLE_SIZE(cmn600_pmu);
1312 		break;
1313 	case PMC_CLASS_DMC620_PMU_CD2:
1314 		ev = dmc620_pmu_cd2_event_table;
1315 		count = PMC_EVENT_TABLE_SIZE(dmc620_pmu_cd2);
1316 		break;
1317 	case PMC_CLASS_DMC620_PMU_C:
1318 		ev = dmc620_pmu_c_event_table;
1319 		count = PMC_EVENT_TABLE_SIZE(dmc620_pmu_c);
1320 		break;
1321 	case PMC_CLASS_PPC7450:
1322 		ev = ppc7450_event_table;
1323 		count = PMC_EVENT_TABLE_SIZE(ppc7450);
1324 		break;
1325 	case PMC_CLASS_PPC970:
1326 		ev = ppc970_event_table;
1327 		count = PMC_EVENT_TABLE_SIZE(ppc970);
1328 		break;
1329 	case PMC_CLASS_E500:
1330 		ev = e500_event_table;
1331 		count = PMC_EVENT_TABLE_SIZE(e500);
1332 		break;
1333 	case PMC_CLASS_SOFT:
1334 		ev = soft_event_table;
1335 		count = soft_event_info.pm_nevent;
1336 		break;
1337 	default:
1338 		errno = EINVAL;
1339 		return (-1);
1340 	}
1341 
1342 	if ((names = malloc(count * sizeof(const char *))) == NULL)
1343 		return (-1);
1344 
1345 	*eventnames = names;
1346 	*nevents = count;
1347 
1348 	for (;count--; ev++, names++)
1349 		*names = ev->pm_ev_name;
1350 
1351 	return (0);
1352 }
1353 
1354 int
1355 pmc_flush_logfile(void)
1356 {
1357 	return (PMC_CALL(PMC_OP_FLUSHLOG, 0));
1358 }
1359 
1360 int
1361 pmc_close_logfile(void)
1362 {
1363 	return (PMC_CALL(PMC_OP_CLOSELOG, 0));
1364 }
1365 
1366 int
1367 pmc_get_driver_stats(struct pmc_driverstats *ds)
1368 {
1369 	struct pmc_op_getdriverstats gms;
1370 
1371 	if (PMC_CALL(PMC_OP_GETDRIVERSTATS, &gms) < 0)
1372 		return (-1);
1373 
1374 	/* copy out fields in the current userland<->library interface */
1375 	ds->pm_intr_ignored    = gms.pm_intr_ignored;
1376 	ds->pm_intr_processed  = gms.pm_intr_processed;
1377 	ds->pm_intr_bufferfull = gms.pm_intr_bufferfull;
1378 	ds->pm_syscalls        = gms.pm_syscalls;
1379 	ds->pm_syscall_errors  = gms.pm_syscall_errors;
1380 	ds->pm_buffer_requests = gms.pm_buffer_requests;
1381 	ds->pm_buffer_requests_failed = gms.pm_buffer_requests_failed;
1382 	ds->pm_log_sweeps      = gms.pm_log_sweeps;
1383 	return (0);
1384 }
1385 
1386 int
1387 pmc_get_msr(pmc_id_t pmc, uint32_t *msr)
1388 {
1389 	struct pmc_op_getmsr gm;
1390 
1391 	gm.pm_pmcid = pmc;
1392 	if (PMC_CALL(PMC_OP_PMCGETMSR, &gm) < 0)
1393 		return (-1);
1394 	*msr = gm.pm_msr;
1395 	return (0);
1396 }
1397 
1398 int
1399 pmc_init(void)
1400 {
1401 	int error, pmc_mod_id;
1402 	unsigned int n;
1403 	uint32_t abi_version;
1404 	struct module_stat pmc_modstat;
1405 	struct pmc_op_getcpuinfo op_cpu_info;
1406 
1407 	if (pmc_syscall != -1) /* already inited */
1408 		return (0);
1409 
1410 	/* retrieve the system call number from the KLD */
1411 	if ((pmc_mod_id = modfind(PMC_MODULE_NAME)) < 0)
1412 		return (-1);
1413 
1414 	pmc_modstat.version = sizeof(struct module_stat);
1415 	if ((error = modstat(pmc_mod_id, &pmc_modstat)) < 0)
1416 		return (-1);
1417 
1418 	pmc_syscall = pmc_modstat.data.intval;
1419 
1420 	/* check the kernel module's ABI against our compiled-in version */
1421 	abi_version = PMC_VERSION;
1422 	if (PMC_CALL(PMC_OP_GETMODULEVERSION, &abi_version) < 0)
1423 		return (pmc_syscall = -1);
1424 
1425 	/* ignore patch & minor numbers for the comparison */
1426 	if ((abi_version & 0xFF000000) != (PMC_VERSION & 0xFF000000)) {
1427 		errno  = EPROGMISMATCH;
1428 		return (pmc_syscall = -1);
1429 	}
1430 
1431 	bzero(&op_cpu_info, sizeof(op_cpu_info));
1432 	if (PMC_CALL(PMC_OP_GETCPUINFO, &op_cpu_info) < 0)
1433 		return (pmc_syscall = -1);
1434 
1435 	cpu_info.pm_cputype = op_cpu_info.pm_cputype;
1436 	cpu_info.pm_ncpu    = op_cpu_info.pm_ncpu;
1437 	cpu_info.pm_npmc    = op_cpu_info.pm_npmc;
1438 	cpu_info.pm_nclass  = op_cpu_info.pm_nclass;
1439 	for (n = 0; n < op_cpu_info.pm_nclass; n++)
1440 		memcpy(&cpu_info.pm_classes[n], &op_cpu_info.pm_classes[n],
1441 		    sizeof(cpu_info.pm_classes[n]));
1442 
1443 	pmc_class_table = calloc(PMC_CLASS_TABLE_SIZE,
1444 	    sizeof(struct pmc_class_descr *));
1445 
1446 	if (pmc_class_table == NULL)
1447 		return (-1);
1448 
1449 	/*
1450 	 * Get soft events list.
1451 	 */
1452 	soft_event_info.pm_class = PMC_CLASS_SOFT;
1453 	if (PMC_CALL(PMC_OP_GETDYNEVENTINFO, &soft_event_info) < 0)
1454 		return (pmc_syscall = -1);
1455 
1456 	/* Map soft events to static list. */
1457 	for (n = 0; n < soft_event_info.pm_nevent; n++) {
1458 		soft_event_table[n].pm_ev_name =
1459 		    soft_event_info.pm_events[n].pm_ev_name;
1460 		soft_event_table[n].pm_ev_code =
1461 		    soft_event_info.pm_events[n].pm_ev_code;
1462 	}
1463 	soft_class_table_descr.pm_evc_event_table_size = \
1464 	    soft_event_info.pm_nevent;
1465 	soft_class_table_descr.pm_evc_event_table = \
1466 	    soft_event_table;
1467 
1468 	/*
1469 	 * Fill in the class table.
1470 	 */
1471 	n = 0;
1472 	for (unsigned i = 0; i < PMC_CLASS_TABLE_SIZE; i++) {
1473 		switch (cpu_info.pm_classes[i].pm_class) {
1474 #if defined(__amd64__) || defined(__i386__)
1475 		case PMC_CLASS_TSC:
1476 			pmc_class_table[n++] = &tsc_class_table_descr;
1477 			break;
1478 
1479 		case PMC_CLASS_K8:
1480 			pmc_class_table[n++] = &k8_class_table_descr;
1481 			break;
1482 #endif
1483 
1484 		case PMC_CLASS_SOFT:
1485 			pmc_class_table[n++] = &soft_class_table_descr;
1486 			break;
1487 
1488 #if defined(__arm__)
1489 		case PMC_CLASS_ARMV7:
1490 			switch (cpu_info.pm_cputype) {
1491 			case PMC_CPU_ARMV7_CORTEX_A8:
1492 				pmc_class_table[n++] =
1493 				    &cortex_a8_class_table_descr;
1494 				break;
1495 			case PMC_CPU_ARMV7_CORTEX_A9:
1496 				pmc_class_table[n++] =
1497 				    &cortex_a9_class_table_descr;
1498 				break;
1499 			default:
1500 				errno = ENXIO;
1501 				return (pmc_syscall = -1);
1502 			}
1503 			break;
1504 #endif
1505 
1506 #if defined(__aarch64__)
1507 		case PMC_CLASS_ARMV8:
1508 			switch (cpu_info.pm_cputype) {
1509 			case PMC_CPU_ARMV8_CORTEX_A53:
1510 				pmc_class_table[n++] =
1511 				    &cortex_a53_class_table_descr;
1512 				break;
1513 			case PMC_CPU_ARMV8_CORTEX_A57:
1514 				pmc_class_table[n++] =
1515 				    &cortex_a57_class_table_descr;
1516 				break;
1517 			case PMC_CPU_ARMV8_CORTEX_A76:
1518 				pmc_class_table[n++] =
1519 				    &cortex_a76_class_table_descr;
1520 				break;
1521 			default:
1522 				errno = ENXIO;
1523 				return (pmc_syscall = -1);
1524 			}
1525 			break;
1526 
1527 		case PMC_CLASS_DMC620_PMU_CD2:
1528 			pmc_class_table[n++] =
1529 			    &dmc620_pmu_cd2_class_table_descr;
1530 			break;
1531 
1532 		case PMC_CLASS_DMC620_PMU_C:
1533 			pmc_class_table[n++] = &dmc620_pmu_c_class_table_descr;
1534 			break;
1535 
1536 		case PMC_CLASS_CMN600_PMU:
1537 			pmc_class_table[n++] = &cmn600_pmu_class_table_descr;
1538 			break;
1539 #endif
1540 
1541 #if defined(__powerpc__)
1542 		case PMC_CLASS_PPC7450:
1543 			pmc_class_table[n++] = &ppc7450_class_table_descr;
1544 			break;
1545 
1546 		case PMC_CLASS_PPC970:
1547 			pmc_class_table[n++] = &ppc970_class_table_descr;
1548 			break;
1549 
1550 		case PMC_CLASS_E500:
1551 			pmc_class_table[n++] = &e500_class_table_descr;
1552 			break;
1553 #endif
1554 
1555 		default:
1556 #if defined(DEBUG)
1557 			printf("pm_class: 0x%x\n",
1558 			    cpu_info.pm_classes[i].pm_class);
1559 #endif
1560 			break;
1561 		}
1562 	}
1563 
1564 #define	PMC_MDEP_INIT(C) pmc_mdep_event_aliases = C##_aliases
1565 
1566 	/* Configure the event name parser. */
1567 	switch (cpu_info.pm_cputype) {
1568 #if defined(__amd64__) || defined(__i386__)
1569 	case PMC_CPU_AMD_K8:
1570 		PMC_MDEP_INIT(k8);
1571 		break;
1572 #endif
1573 	case PMC_CPU_GENERIC:
1574 		PMC_MDEP_INIT(generic);
1575 		break;
1576 #if defined(__arm__)
1577 	case PMC_CPU_ARMV7_CORTEX_A8:
1578 		PMC_MDEP_INIT(cortex_a8);
1579 		break;
1580 	case PMC_CPU_ARMV7_CORTEX_A9:
1581 		PMC_MDEP_INIT(cortex_a9);
1582 		break;
1583 #endif
1584 #if defined(__aarch64__)
1585 	case PMC_CPU_ARMV8_CORTEX_A53:
1586 		PMC_MDEP_INIT(cortex_a53);
1587 		break;
1588 	case PMC_CPU_ARMV8_CORTEX_A57:
1589 		PMC_MDEP_INIT(cortex_a57);
1590 		break;
1591 	case PMC_CPU_ARMV8_CORTEX_A76:
1592 		PMC_MDEP_INIT(cortex_a76);
1593 		break;
1594 #endif
1595 #if defined(__powerpc__)
1596 	case PMC_CPU_PPC_7450:
1597 		PMC_MDEP_INIT(ppc7450);
1598 		break;
1599 	case PMC_CPU_PPC_970:
1600 		PMC_MDEP_INIT(ppc970);
1601 		break;
1602 	case PMC_CPU_PPC_E500:
1603 		PMC_MDEP_INIT(e500);
1604 		break;
1605 #endif
1606 	default:
1607 		/*
1608 		 * Some kind of CPU this version of the library knows nothing
1609 		 * about.  This shouldn't happen since the abi version check
1610 		 * should have caught this.
1611 		 */
1612 #if defined(__amd64__) || defined(__i386__) || defined(__powerpc64__)
1613 		break;
1614 #endif
1615 		errno = ENXIO;
1616 		return (pmc_syscall = -1);
1617 	}
1618 
1619 	return (0);
1620 }
1621 
1622 const char *
1623 pmc_name_of_capability(enum pmc_caps cap)
1624 {
1625 	int i;
1626 
1627 	/*
1628 	 * 'cap' should have a single bit set and should be in
1629 	 * range.
1630 	 */
1631 	if ((cap & (cap - 1)) || cap < PMC_CAP_FIRST ||
1632 	    cap > PMC_CAP_LAST) {
1633 		errno = EINVAL;
1634 		return (NULL);
1635 	}
1636 
1637 	i = ffs(cap);
1638 	return (pmc_capability_names[i - 1]);
1639 }
1640 
1641 const char *
1642 pmc_name_of_class(enum pmc_class pc)
1643 {
1644 	size_t n;
1645 
1646 	for (n = 0; n < PMC_TABLE_SIZE(pmc_class_names); n++)
1647 		if (pc == pmc_class_names[n].pm_class)
1648 			return (pmc_class_names[n].pm_name);
1649 
1650 	errno = EINVAL;
1651 	return (NULL);
1652 }
1653 
1654 const char *
1655 pmc_name_of_cputype(enum pmc_cputype cp)
1656 {
1657 	size_t n;
1658 
1659 	for (n = 0; n < PMC_TABLE_SIZE(pmc_cputype_names); n++)
1660 		if (cp == pmc_cputype_names[n].pm_cputype)
1661 			return (pmc_cputype_names[n].pm_name);
1662 
1663 	errno = EINVAL;
1664 	return (NULL);
1665 }
1666 
1667 const char *
1668 pmc_name_of_disposition(enum pmc_disp pd)
1669 {
1670 	if ((int) pd >= PMC_DISP_FIRST &&
1671 	    pd <= PMC_DISP_LAST)
1672 		return (pmc_disposition_names[pd]);
1673 
1674 	errno = EINVAL;
1675 	return (NULL);
1676 }
1677 
1678 const char *
1679 _pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu)
1680 {
1681 	const struct pmc_event_descr *ev, *evfence;
1682 
1683 	ev = evfence = NULL;
1684 	if (pe >= PMC_EV_K8_FIRST && pe <= PMC_EV_K8_LAST) {
1685 		ev = k8_event_table;
1686 		evfence = k8_event_table + PMC_EVENT_TABLE_SIZE(k8);
1687 
1688 	} else if (pe >= PMC_EV_ARMV7_FIRST && pe <= PMC_EV_ARMV7_LAST) {
1689 		switch (cpu) {
1690 		case PMC_CPU_ARMV7_CORTEX_A8:
1691 			ev = cortex_a8_event_table;
1692 			evfence = cortex_a8_event_table + PMC_EVENT_TABLE_SIZE(cortex_a8);
1693 			break;
1694 		case PMC_CPU_ARMV7_CORTEX_A9:
1695 			ev = cortex_a9_event_table;
1696 			evfence = cortex_a9_event_table + PMC_EVENT_TABLE_SIZE(cortex_a9);
1697 			break;
1698 		default:	/* Unknown CPU type. */
1699 			break;
1700 		}
1701 	} else if (pe >= PMC_EV_ARMV8_FIRST && pe <= PMC_EV_ARMV8_LAST) {
1702 		switch (cpu) {
1703 		case PMC_CPU_ARMV8_CORTEX_A53:
1704 			ev = cortex_a53_event_table;
1705 			evfence = cortex_a53_event_table + PMC_EVENT_TABLE_SIZE(cortex_a53);
1706 			break;
1707 		case PMC_CPU_ARMV8_CORTEX_A57:
1708 			ev = cortex_a57_event_table;
1709 			evfence = cortex_a57_event_table + PMC_EVENT_TABLE_SIZE(cortex_a57);
1710 			break;
1711 		case PMC_CPU_ARMV8_CORTEX_A76:
1712 			ev = cortex_a76_event_table;
1713 			evfence = cortex_a76_event_table + PMC_EVENT_TABLE_SIZE(cortex_a76);
1714 			break;
1715 		default:	/* Unknown CPU type. */
1716 			break;
1717 		}
1718 	} else if (pe >= PMC_EV_CMN600_PMU_FIRST &&
1719 	    pe <= PMC_EV_CMN600_PMU_LAST) {
1720 		ev = cmn600_pmu_event_table;
1721 		evfence = cmn600_pmu_event_table +
1722 		    PMC_EVENT_TABLE_SIZE(cmn600_pmu);
1723 	} else if (pe >= PMC_EV_DMC620_PMU_CD2_FIRST &&
1724 	    pe <= PMC_EV_DMC620_PMU_CD2_LAST) {
1725 		ev = dmc620_pmu_cd2_event_table;
1726 		evfence = dmc620_pmu_cd2_event_table +
1727 		    PMC_EVENT_TABLE_SIZE(dmc620_pmu_cd2);
1728 	} else if (pe >= PMC_EV_DMC620_PMU_C_FIRST &&
1729 	    pe <= PMC_EV_DMC620_PMU_C_LAST) {
1730 		ev = dmc620_pmu_c_event_table;
1731 		evfence = dmc620_pmu_c_event_table +
1732 		    PMC_EVENT_TABLE_SIZE(dmc620_pmu_c);
1733 	} else if (pe >= PMC_EV_PPC7450_FIRST && pe <= PMC_EV_PPC7450_LAST) {
1734 		ev = ppc7450_event_table;
1735 		evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450);
1736 	} else if (pe >= PMC_EV_PPC970_FIRST && pe <= PMC_EV_PPC970_LAST) {
1737 		ev = ppc970_event_table;
1738 		evfence = ppc970_event_table + PMC_EVENT_TABLE_SIZE(ppc970);
1739 	} else if (pe >= PMC_EV_E500_FIRST && pe <= PMC_EV_E500_LAST) {
1740 		ev = e500_event_table;
1741 		evfence = e500_event_table + PMC_EVENT_TABLE_SIZE(e500);
1742 	} else if (pe == PMC_EV_TSC_TSC) {
1743 		ev = tsc_event_table;
1744 		evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc);
1745 	} else if ((int)pe >= PMC_EV_SOFT_FIRST && (int)pe <= PMC_EV_SOFT_LAST) {
1746 		ev = soft_event_table;
1747 		evfence = soft_event_table + soft_event_info.pm_nevent;
1748 	}
1749 
1750 	for (; ev != evfence; ev++)
1751 		if (pe == ev->pm_ev_code)
1752 			return (ev->pm_ev_name);
1753 
1754 	return (NULL);
1755 }
1756 
1757 const char *
1758 pmc_name_of_event(enum pmc_event pe)
1759 {
1760 	const char *n;
1761 
1762 	if ((n = _pmc_name_of_event(pe, cpu_info.pm_cputype)) != NULL)
1763 		return (n);
1764 
1765 	errno = EINVAL;
1766 	return (NULL);
1767 }
1768 
1769 const char *
1770 pmc_name_of_mode(enum pmc_mode pm)
1771 {
1772 	if ((int) pm >= PMC_MODE_FIRST &&
1773 	    pm <= PMC_MODE_LAST)
1774 		return (pmc_mode_names[pm]);
1775 
1776 	errno = EINVAL;
1777 	return (NULL);
1778 }
1779 
1780 const char *
1781 pmc_name_of_state(enum pmc_state ps)
1782 {
1783 	if ((int) ps >= PMC_STATE_FIRST &&
1784 	    ps <= PMC_STATE_LAST)
1785 		return (pmc_state_names[ps]);
1786 
1787 	errno = EINVAL;
1788 	return (NULL);
1789 }
1790 
1791 int
1792 pmc_ncpu(void)
1793 {
1794 	if (pmc_syscall == -1) {
1795 		errno = ENXIO;
1796 		return (-1);
1797 	}
1798 
1799 	return (cpu_info.pm_ncpu);
1800 }
1801 
1802 int
1803 pmc_npmc(int cpu)
1804 {
1805 	if (pmc_syscall == -1) {
1806 		errno = ENXIO;
1807 		return (-1);
1808 	}
1809 
1810 	if (cpu < 0 || cpu >= (int) cpu_info.pm_ncpu) {
1811 		errno = EINVAL;
1812 		return (-1);
1813 	}
1814 
1815 	return (cpu_info.pm_npmc);
1816 }
1817 
1818 int
1819 pmc_pmcinfo(int cpu, struct pmc_pmcinfo **ppmci)
1820 {
1821 	int nbytes, npmc;
1822 	struct pmc_op_getpmcinfo *pmci;
1823 
1824 	if ((npmc = pmc_npmc(cpu)) < 0)
1825 		return (-1);
1826 
1827 	nbytes = sizeof(struct pmc_op_getpmcinfo) +
1828 	    npmc * sizeof(struct pmc_info);
1829 
1830 	if ((pmci = calloc(1, nbytes)) == NULL)
1831 		return (-1);
1832 
1833 	pmci->pm_cpu  = cpu;
1834 
1835 	if (PMC_CALL(PMC_OP_GETPMCINFO, pmci) < 0) {
1836 		free(pmci);
1837 		return (-1);
1838 	}
1839 
1840 	/* kernel<->library, library<->userland interfaces are identical */
1841 	*ppmci = (struct pmc_pmcinfo *) pmci;
1842 	return (0);
1843 }
1844 
1845 int
1846 pmc_read(pmc_id_t pmc, pmc_value_t *value)
1847 {
1848 	struct pmc_op_pmcrw pmc_read_op;
1849 
1850 	pmc_read_op.pm_pmcid = pmc;
1851 	pmc_read_op.pm_flags = PMC_F_OLDVALUE;
1852 	pmc_read_op.pm_value = -1;
1853 
1854 	if (PMC_CALL(PMC_OP_PMCRW, &pmc_read_op) < 0)
1855 		return (-1);
1856 
1857 	*value = pmc_read_op.pm_value;
1858 	return (0);
1859 }
1860 
1861 int
1862 pmc_release(pmc_id_t pmc)
1863 {
1864 	struct pmc_op_simple	pmc_release_args;
1865 
1866 	pmc_release_args.pm_pmcid = pmc;
1867 	return (PMC_CALL(PMC_OP_PMCRELEASE, &pmc_release_args));
1868 }
1869 
1870 int
1871 pmc_rw(pmc_id_t pmc, pmc_value_t newvalue, pmc_value_t *oldvaluep)
1872 {
1873 	struct pmc_op_pmcrw pmc_rw_op;
1874 
1875 	pmc_rw_op.pm_pmcid = pmc;
1876 	pmc_rw_op.pm_flags = PMC_F_NEWVALUE | PMC_F_OLDVALUE;
1877 	pmc_rw_op.pm_value = newvalue;
1878 
1879 	if (PMC_CALL(PMC_OP_PMCRW, &pmc_rw_op) < 0)
1880 		return (-1);
1881 
1882 	*oldvaluep = pmc_rw_op.pm_value;
1883 	return (0);
1884 }
1885 
1886 int
1887 pmc_set(pmc_id_t pmc, pmc_value_t value)
1888 {
1889 	struct pmc_op_pmcsetcount sc;
1890 
1891 	sc.pm_pmcid = pmc;
1892 	sc.pm_count = value;
1893 
1894 	if (PMC_CALL(PMC_OP_PMCSETCOUNT, &sc) < 0)
1895 		return (-1);
1896 	return (0);
1897 }
1898 
1899 int
1900 pmc_start(pmc_id_t pmc)
1901 {
1902 	struct pmc_op_simple	pmc_start_args;
1903 
1904 	pmc_start_args.pm_pmcid = pmc;
1905 	return (PMC_CALL(PMC_OP_PMCSTART, &pmc_start_args));
1906 }
1907 
1908 int
1909 pmc_stop(pmc_id_t pmc)
1910 {
1911 	struct pmc_op_simple	pmc_stop_args;
1912 
1913 	pmc_stop_args.pm_pmcid = pmc;
1914 	return (PMC_CALL(PMC_OP_PMCSTOP, &pmc_stop_args));
1915 }
1916 
1917 int
1918 pmc_width(pmc_id_t pmcid, uint32_t *width)
1919 {
1920 	unsigned int i;
1921 	enum pmc_class cl;
1922 
1923 	cl = PMC_ID_TO_CLASS(pmcid);
1924 	for (i = 0; i < cpu_info.pm_nclass; i++)
1925 		if (cpu_info.pm_classes[i].pm_class == cl) {
1926 			*width = cpu_info.pm_classes[i].pm_width;
1927 			return (0);
1928 		}
1929 	errno = EINVAL;
1930 	return (-1);
1931 }
1932 
1933 int
1934 pmc_write(pmc_id_t pmc, pmc_value_t value)
1935 {
1936 	struct pmc_op_pmcrw pmc_write_op;
1937 
1938 	pmc_write_op.pm_pmcid = pmc;
1939 	pmc_write_op.pm_flags = PMC_F_NEWVALUE;
1940 	pmc_write_op.pm_value = value;
1941 	return (PMC_CALL(PMC_OP_PMCRW, &pmc_write_op));
1942 }
1943 
1944 int
1945 pmc_writelog(uint32_t userdata)
1946 {
1947 	struct pmc_op_writelog wl;
1948 
1949 	wl.pm_userdata = userdata;
1950 	return (PMC_CALL(PMC_OP_WRITELOG, &wl));
1951 }
1952