libpmc.c revision 233335
1/*-
2 * Copyright (c) 2003-2008 Joseph Koshy
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/lib/libpmc/libpmc.c 233335 2012-03-23 00:10:21Z gonzo $");
29
30#include <sys/types.h>
31#include <sys/module.h>
32#include <sys/pmc.h>
33#include <sys/syscall.h>
34
35#include <ctype.h>
36#include <errno.h>
37#include <fcntl.h>
38#include <pmc.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <strings.h>
43#include <unistd.h>
44
45#include "libpmcinternal.h"
46
47/* Function prototypes */
48#if defined(__i386__)
49static int k7_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
50    struct pmc_op_pmcallocate *_pmc_config);
51#endif
52#if defined(__amd64__) || defined(__i386__)
53static int iaf_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
54    struct pmc_op_pmcallocate *_pmc_config);
55static int iap_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
56    struct pmc_op_pmcallocate *_pmc_config);
57static int ucf_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
58    struct pmc_op_pmcallocate *_pmc_config);
59static int ucp_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
60    struct pmc_op_pmcallocate *_pmc_config);
61static int k8_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
62    struct pmc_op_pmcallocate *_pmc_config);
63static int p4_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
64    struct pmc_op_pmcallocate *_pmc_config);
65#endif
66#if defined(__i386__)
67static int p5_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
68    struct pmc_op_pmcallocate *_pmc_config);
69static int p6_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
70    struct pmc_op_pmcallocate *_pmc_config);
71#endif
72#if defined(__amd64__) || defined(__i386__)
73static int tsc_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
74    struct pmc_op_pmcallocate *_pmc_config);
75#endif
76#if defined(__XSCALE__)
77static int xscale_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
78    struct pmc_op_pmcallocate *_pmc_config);
79#endif
80
81#if defined(__mips__)
82static int mips_allocate_pmc(enum pmc_event _pe, char* ctrspec,
83			     struct pmc_op_pmcallocate *_pmc_config);
84#endif /* __mips__ */
85
86#if defined(__powerpc__)
87static int ppc7450_allocate_pmc(enum pmc_event _pe, char* ctrspec,
88			     struct pmc_op_pmcallocate *_pmc_config);
89#endif /* __powerpc__ */
90
91#define PMC_CALL(cmd, params)				\
92	syscall(pmc_syscall, PMC_OP_##cmd, (params))
93
94/*
95 * Event aliases provide a way for the user to ask for generic events
96 * like "cache-misses", or "instructions-retired".  These aliases are
97 * mapped to the appropriate canonical event descriptions using a
98 * lookup table.
99 */
100struct pmc_event_alias {
101	const char	*pm_alias;
102	const char	*pm_spec;
103};
104
105static const struct pmc_event_alias *pmc_mdep_event_aliases;
106
107/*
108 * The pmc_event_descr structure maps symbolic names known to the user
109 * to integer codes used by the PMC KLD.
110 */
111struct pmc_event_descr {
112	const char	*pm_ev_name;
113	enum pmc_event	pm_ev_code;
114};
115
116/*
117 * The pmc_class_descr structure maps class name prefixes for
118 * event names to event tables and other PMC class data.
119 */
120struct pmc_class_descr {
121	const char	*pm_evc_name;
122	size_t		pm_evc_name_size;
123	enum pmc_class	pm_evc_class;
124	const struct pmc_event_descr *pm_evc_event_table;
125	size_t		pm_evc_event_table_size;
126	int		(*pm_evc_allocate_pmc)(enum pmc_event _pe,
127			    char *_ctrspec, struct pmc_op_pmcallocate *_pa);
128};
129
130#define	PMC_TABLE_SIZE(N)	(sizeof(N)/sizeof(N[0]))
131#define	PMC_EVENT_TABLE_SIZE(N)	PMC_TABLE_SIZE(N##_event_table)
132
133#undef	__PMC_EV
134#define	__PMC_EV(C,N) { #N, PMC_EV_ ## C ## _ ## N },
135
136/*
137 * PMC_CLASSDEP_TABLE(NAME, CLASS)
138 *
139 * Define a table mapping event names and aliases to HWPMC event IDs.
140 */
141#define	PMC_CLASSDEP_TABLE(N, C)				\
142	static const struct pmc_event_descr N##_event_table[] =	\
143	{							\
144		__PMC_EV_##C()					\
145	}
146
147PMC_CLASSDEP_TABLE(iaf, IAF);
148PMC_CLASSDEP_TABLE(k7, K7);
149PMC_CLASSDEP_TABLE(k8, K8);
150PMC_CLASSDEP_TABLE(p4, P4);
151PMC_CLASSDEP_TABLE(p5, P5);
152PMC_CLASSDEP_TABLE(p6, P6);
153PMC_CLASSDEP_TABLE(xscale, XSCALE);
154PMC_CLASSDEP_TABLE(mips24k, MIPS24K);
155PMC_CLASSDEP_TABLE(octeon, OCTEON);
156PMC_CLASSDEP_TABLE(ucf, UCF);
157PMC_CLASSDEP_TABLE(ppc7450, PPC7450);
158
159#undef	__PMC_EV_ALIAS
160#define	__PMC_EV_ALIAS(N,CODE) 	{ N, PMC_EV_##CODE },
161
162static const struct pmc_event_descr atom_event_table[] =
163{
164	__PMC_EV_ALIAS_ATOM()
165};
166
167static const struct pmc_event_descr core_event_table[] =
168{
169	__PMC_EV_ALIAS_CORE()
170};
171
172
173static const struct pmc_event_descr core2_event_table[] =
174{
175	__PMC_EV_ALIAS_CORE2()
176};
177
178static const struct pmc_event_descr corei7_event_table[] =
179{
180	__PMC_EV_ALIAS_COREI7()
181};
182
183static const struct pmc_event_descr sandybridge_event_table[] =
184{
185	__PMC_EV_ALIAS_SANDYBRIDGE()
186};
187
188static const struct pmc_event_descr westmere_event_table[] =
189{
190	__PMC_EV_ALIAS_WESTMERE()
191};
192
193static const struct pmc_event_descr corei7uc_event_table[] =
194{
195	__PMC_EV_ALIAS_COREI7UC()
196};
197
198static const struct pmc_event_descr sandybridgeuc_event_table[] =
199{
200	__PMC_EV_ALIAS_SANDYBRIDGEUC()
201};
202
203static const struct pmc_event_descr westmereuc_event_table[] =
204{
205	__PMC_EV_ALIAS_WESTMEREUC()
206};
207
208/*
209 * PMC_MDEP_TABLE(NAME, PRIMARYCLASS, ADDITIONAL_CLASSES...)
210 *
211 * Map a CPU to the PMC classes it supports.
212 */
213#define	PMC_MDEP_TABLE(N,C,...)				\
214	static const enum pmc_class N##_pmc_classes[] = {	\
215		PMC_CLASS_##C, __VA_ARGS__			\
216	}
217
218PMC_MDEP_TABLE(atom, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC);
219PMC_MDEP_TABLE(core, IAP, PMC_CLASS_TSC);
220PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC);
221PMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
222PMC_MDEP_TABLE(sandybridge, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
223PMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
224PMC_MDEP_TABLE(k7, K7, PMC_CLASS_TSC);
225PMC_MDEP_TABLE(k8, K8, PMC_CLASS_TSC);
226PMC_MDEP_TABLE(p4, P4, PMC_CLASS_TSC);
227PMC_MDEP_TABLE(p5, P5, PMC_CLASS_TSC);
228PMC_MDEP_TABLE(p6, P6, PMC_CLASS_TSC);
229PMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_XSCALE);
230PMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_MIPS24K);
231PMC_MDEP_TABLE(octeon, OCTEON, PMC_CLASS_OCTEON);
232PMC_MDEP_TABLE(ppc7450, PPC7450, PMC_CLASS_PPC7450);
233
234static const struct pmc_event_descr tsc_event_table[] =
235{
236	__PMC_EV_TSC()
237};
238
239#undef	PMC_CLASS_TABLE_DESC
240#define	PMC_CLASS_TABLE_DESC(NAME, CLASS, EVENTS, ALLOCATOR)	\
241static const struct pmc_class_descr NAME##_class_table_descr =	\
242	{							\
243		.pm_evc_name  = #CLASS "-",			\
244		.pm_evc_name_size = sizeof(#CLASS "-") - 1,	\
245		.pm_evc_class = PMC_CLASS_##CLASS ,		\
246		.pm_evc_event_table = EVENTS##_event_table ,	\
247		.pm_evc_event_table_size = 			\
248			PMC_EVENT_TABLE_SIZE(EVENTS),		\
249		.pm_evc_allocate_pmc = ALLOCATOR##_allocate_pmc	\
250	}
251
252#if	defined(__i386__) || defined(__amd64__)
253PMC_CLASS_TABLE_DESC(iaf, IAF, iaf, iaf);
254PMC_CLASS_TABLE_DESC(atom, IAP, atom, iap);
255PMC_CLASS_TABLE_DESC(core, IAP, core, iap);
256PMC_CLASS_TABLE_DESC(core2, IAP, core2, iap);
257PMC_CLASS_TABLE_DESC(corei7, IAP, corei7, iap);
258PMC_CLASS_TABLE_DESC(sandybridge, IAP, sandybridge, iap);
259PMC_CLASS_TABLE_DESC(westmere, IAP, westmere, iap);
260PMC_CLASS_TABLE_DESC(ucf, UCF, ucf, ucf);
261PMC_CLASS_TABLE_DESC(corei7uc, UCP, corei7uc, ucp);
262PMC_CLASS_TABLE_DESC(sandybridgeuc, UCP, sandybridgeuc, ucp);
263PMC_CLASS_TABLE_DESC(westmereuc, UCP, westmereuc, ucp);
264#endif
265#if	defined(__i386__)
266PMC_CLASS_TABLE_DESC(k7, K7, k7, k7);
267#endif
268#if	defined(__i386__) || defined(__amd64__)
269PMC_CLASS_TABLE_DESC(k8, K8, k8, k8);
270PMC_CLASS_TABLE_DESC(p4, P4, p4, p4);
271#endif
272#if	defined(__i386__)
273PMC_CLASS_TABLE_DESC(p5, P5, p5, p5);
274PMC_CLASS_TABLE_DESC(p6, P6, p6, p6);
275#endif
276#if	defined(__i386__) || defined(__amd64__)
277PMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc);
278#endif
279#if	defined(__XSCALE__)
280PMC_CLASS_TABLE_DESC(xscale, XSCALE, xscale, xscale);
281#endif
282
283#if defined(__mips__)
284PMC_CLASS_TABLE_DESC(mips24k, MIPS24K, mips24k, mips);
285PMC_CLASS_TABLE_DESC(octeon, OCTEON, octeon, mips);
286#endif /* __mips__ */
287
288#if defined(__powerpc__)
289PMC_CLASS_TABLE_DESC(ppc7450, PPC7450, ppc7450, ppc7450);
290#endif
291
292#undef	PMC_CLASS_TABLE_DESC
293
294static const struct pmc_class_descr **pmc_class_table;
295#define	PMC_CLASS_TABLE_SIZE	cpu_info.pm_nclass
296
297static const enum pmc_class *pmc_mdep_class_list;
298static size_t pmc_mdep_class_list_size;
299
300/*
301 * Mapping tables, mapping enumeration values to human readable
302 * strings.
303 */
304
305static const char * pmc_capability_names[] = {
306#undef	__PMC_CAP
307#define	__PMC_CAP(N,V,D)	#N ,
308	__PMC_CAPS()
309};
310
311static const char * pmc_class_names[] = {
312#undef	__PMC_CLASS
313#define __PMC_CLASS(C)	#C ,
314	__PMC_CLASSES()
315};
316
317struct pmc_cputype_map {
318	enum pmc_cputype pm_cputype;
319	const char	*pm_name;
320};
321
322static const struct pmc_cputype_map pmc_cputype_names[] = {
323#undef	__PMC_CPU
324#define	__PMC_CPU(S, V, D) { .pm_cputype = PMC_CPU_##S, .pm_name = #S } ,
325	__PMC_CPUS()
326};
327
328static const char * pmc_disposition_names[] = {
329#undef	__PMC_DISP
330#define	__PMC_DISP(D)	#D ,
331	__PMC_DISPOSITIONS()
332};
333
334static const char * pmc_mode_names[] = {
335#undef  __PMC_MODE
336#define __PMC_MODE(M,N)	#M ,
337	__PMC_MODES()
338};
339
340static const char * pmc_state_names[] = {
341#undef  __PMC_STATE
342#define __PMC_STATE(S) #S ,
343	__PMC_STATES()
344};
345
346static int pmc_syscall = -1;		/* filled in by pmc_init() */
347
348static struct pmc_cpuinfo cpu_info;	/* filled in by pmc_init() */
349
350/* Event masks for events */
351struct pmc_masks {
352	const char	*pm_name;
353	const uint32_t	pm_value;
354};
355#define	PMCMASK(N,V)	{ .pm_name = #N, .pm_value = (V) }
356#define	NULLMASK	{ .pm_name = NULL }
357
358#if defined(__amd64__) || defined(__i386__)
359static int
360pmc_parse_mask(const struct pmc_masks *pmask, char *p, uint32_t *evmask)
361{
362	const struct pmc_masks *pm;
363	char *q, *r;
364	int c;
365
366	if (pmask == NULL)	/* no mask keywords */
367		return (-1);
368	q = strchr(p, '=');	/* skip '=' */
369	if (*++q == '\0')	/* no more data */
370		return (-1);
371	c = 0;			/* count of mask keywords seen */
372	while ((r = strsep(&q, "+")) != NULL) {
373		for (pm = pmask; pm->pm_name && strcasecmp(r, pm->pm_name);
374		    pm++)
375			;
376		if (pm->pm_name == NULL) /* not found */
377			return (-1);
378		*evmask |= pm->pm_value;
379		c++;
380	}
381	return (c);
382}
383#endif
384
385#define	KWMATCH(p,kw)		(strcasecmp((p), (kw)) == 0)
386#define	KWPREFIXMATCH(p,kw)	(strncasecmp((p), (kw), sizeof((kw)) - 1) == 0)
387#define	EV_ALIAS(N,S)		{ .pm_alias = N, .pm_spec = S }
388
389#if defined(__i386__)
390
391/*
392 * AMD K7 (Athlon) CPUs.
393 */
394
395static struct pmc_event_alias k7_aliases[] = {
396	EV_ALIAS("branches",		"k7-retired-branches"),
397	EV_ALIAS("branch-mispredicts",	"k7-retired-branches-mispredicted"),
398	EV_ALIAS("cycles",		"tsc"),
399	EV_ALIAS("dc-misses",		"k7-dc-misses"),
400	EV_ALIAS("ic-misses",		"k7-ic-misses"),
401	EV_ALIAS("instructions",	"k7-retired-instructions"),
402	EV_ALIAS("interrupts",		"k7-hardware-interrupts"),
403	EV_ALIAS(NULL, NULL)
404};
405
406#define	K7_KW_COUNT	"count"
407#define	K7_KW_EDGE	"edge"
408#define	K7_KW_INV	"inv"
409#define	K7_KW_OS	"os"
410#define	K7_KW_UNITMASK	"unitmask"
411#define	K7_KW_USR	"usr"
412
413static int
414k7_allocate_pmc(enum pmc_event pe, char *ctrspec,
415    struct pmc_op_pmcallocate *pmc_config)
416{
417	char		*e, *p, *q;
418	int		c, has_unitmask;
419	uint32_t	count, unitmask;
420
421	pmc_config->pm_md.pm_amd.pm_amd_config = 0;
422	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
423
424	if (pe == PMC_EV_K7_DC_REFILLS_FROM_L2 ||
425	    pe == PMC_EV_K7_DC_REFILLS_FROM_SYSTEM ||
426	    pe == PMC_EV_K7_DC_WRITEBACKS) {
427		has_unitmask = 1;
428		unitmask = AMD_PMC_UNITMASK_MOESI;
429	} else
430		unitmask = has_unitmask = 0;
431
432	while ((p = strsep(&ctrspec, ",")) != NULL) {
433		if (KWPREFIXMATCH(p, K7_KW_COUNT "=")) {
434			q = strchr(p, '=');
435			if (*++q == '\0') /* skip '=' */
436				return (-1);
437
438			count = strtol(q, &e, 0);
439			if (e == q || *e != '\0')
440				return (-1);
441
442			pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
443			pmc_config->pm_md.pm_amd.pm_amd_config |=
444			    AMD_PMC_TO_COUNTER(count);
445
446		} else if (KWMATCH(p, K7_KW_EDGE)) {
447			pmc_config->pm_caps |= PMC_CAP_EDGE;
448		} else if (KWMATCH(p, K7_KW_INV)) {
449			pmc_config->pm_caps |= PMC_CAP_INVERT;
450		} else if (KWMATCH(p, K7_KW_OS)) {
451			pmc_config->pm_caps |= PMC_CAP_SYSTEM;
452		} else if (KWPREFIXMATCH(p, K7_KW_UNITMASK "=")) {
453			if (has_unitmask == 0)
454				return (-1);
455			unitmask = 0;
456			q = strchr(p, '=');
457			if (*++q == '\0') /* skip '=' */
458				return (-1);
459
460			while ((c = tolower(*q++)) != 0)
461				if (c == 'm')
462					unitmask |= AMD_PMC_UNITMASK_M;
463				else if (c == 'o')
464					unitmask |= AMD_PMC_UNITMASK_O;
465				else if (c == 'e')
466					unitmask |= AMD_PMC_UNITMASK_E;
467				else if (c == 's')
468					unitmask |= AMD_PMC_UNITMASK_S;
469				else if (c == 'i')
470					unitmask |= AMD_PMC_UNITMASK_I;
471				else if (c == '+')
472					continue;
473				else
474					return (-1);
475
476			if (unitmask == 0)
477				return (-1);
478
479		} else if (KWMATCH(p, K7_KW_USR)) {
480			pmc_config->pm_caps |= PMC_CAP_USER;
481		} else
482			return (-1);
483	}
484
485	if (has_unitmask) {
486		pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
487		pmc_config->pm_md.pm_amd.pm_amd_config |=
488		    AMD_PMC_TO_UNITMASK(unitmask);
489	}
490
491	return (0);
492
493}
494
495#endif
496
497#if defined(__amd64__) || defined(__i386__)
498
499/*
500 * Intel Core (Family 6, Model E) PMCs.
501 */
502
503static struct pmc_event_alias core_aliases[] = {
504	EV_ALIAS("branches",		"iap-br-instr-ret"),
505	EV_ALIAS("branch-mispredicts",	"iap-br-mispred-ret"),
506	EV_ALIAS("cycles",		"tsc-tsc"),
507	EV_ALIAS("ic-misses",		"iap-icache-misses"),
508	EV_ALIAS("instructions",	"iap-instr-ret"),
509	EV_ALIAS("interrupts",		"iap-core-hw-int-rx"),
510	EV_ALIAS("unhalted-cycles",	"iap-unhalted-core-cycles"),
511	EV_ALIAS(NULL, NULL)
512};
513
514/*
515 * Intel Core2 (Family 6, Model F), Core2Extreme (Family 6, Model 17H)
516 * and Atom (Family 6, model 1CH) PMCs.
517 *
518 * We map aliases to events on the fixed-function counters if these
519 * are present.  Note that not all CPUs in this family contain fixed-function
520 * counters.
521 */
522
523static struct pmc_event_alias core2_aliases[] = {
524	EV_ALIAS("branches",		"iap-br-inst-retired.any"),
525	EV_ALIAS("branch-mispredicts",	"iap-br-inst-retired.mispred"),
526	EV_ALIAS("cycles",		"tsc-tsc"),
527	EV_ALIAS("ic-misses",		"iap-l1i-misses"),
528	EV_ALIAS("instructions",	"iaf-instr-retired.any"),
529	EV_ALIAS("interrupts",		"iap-hw-int-rcv"),
530	EV_ALIAS("unhalted-cycles",	"iaf-cpu-clk-unhalted.core"),
531	EV_ALIAS(NULL, NULL)
532};
533
534static struct pmc_event_alias core2_aliases_without_iaf[] = {
535	EV_ALIAS("branches",		"iap-br-inst-retired.any"),
536	EV_ALIAS("branch-mispredicts",	"iap-br-inst-retired.mispred"),
537	EV_ALIAS("cycles",		"tsc-tsc"),
538	EV_ALIAS("ic-misses",		"iap-l1i-misses"),
539	EV_ALIAS("instructions",	"iap-inst-retired.any_p"),
540	EV_ALIAS("interrupts",		"iap-hw-int-rcv"),
541	EV_ALIAS("unhalted-cycles",	"iap-cpu-clk-unhalted.core_p"),
542	EV_ALIAS(NULL, NULL)
543};
544
545#define	atom_aliases			core2_aliases
546#define	atom_aliases_without_iaf	core2_aliases_without_iaf
547#define corei7_aliases			core2_aliases
548#define corei7_aliases_without_iaf	core2_aliases_without_iaf
549#define sandybridge_aliases		core2_aliases
550#define sandybridge_aliases_without_iaf	core2_aliases_without_iaf
551#define westmere_aliases		core2_aliases
552#define westmere_aliases_without_iaf	core2_aliases_without_iaf
553
554#define	IAF_KW_OS		"os"
555#define	IAF_KW_USR		"usr"
556#define	IAF_KW_ANYTHREAD	"anythread"
557
558/*
559 * Parse an event specifier for Intel fixed function counters.
560 */
561static int
562iaf_allocate_pmc(enum pmc_event pe, char *ctrspec,
563    struct pmc_op_pmcallocate *pmc_config)
564{
565	char *p;
566
567	(void) pe;
568
569	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
570	pmc_config->pm_md.pm_iaf.pm_iaf_flags = 0;
571
572	while ((p = strsep(&ctrspec, ",")) != NULL) {
573		if (KWMATCH(p, IAF_KW_OS))
574			pmc_config->pm_caps |= PMC_CAP_SYSTEM;
575		else if (KWMATCH(p, IAF_KW_USR))
576			pmc_config->pm_caps |= PMC_CAP_USER;
577		else if (KWMATCH(p, IAF_KW_ANYTHREAD))
578			pmc_config->pm_md.pm_iaf.pm_iaf_flags |= IAF_ANY;
579		else
580			return (-1);
581	}
582
583	return (0);
584}
585
586/*
587 * Core/Core2 support.
588 */
589
590#define	IAP_KW_AGENT		"agent"
591#define	IAP_KW_ANYTHREAD	"anythread"
592#define	IAP_KW_CACHESTATE	"cachestate"
593#define	IAP_KW_CMASK		"cmask"
594#define	IAP_KW_CORE		"core"
595#define	IAP_KW_EDGE		"edge"
596#define	IAP_KW_INV		"inv"
597#define	IAP_KW_OS		"os"
598#define	IAP_KW_PREFETCH		"prefetch"
599#define	IAP_KW_SNOOPRESPONSE	"snoopresponse"
600#define	IAP_KW_SNOOPTYPE	"snooptype"
601#define	IAP_KW_TRANSITION	"trans"
602#define	IAP_KW_USR		"usr"
603#define	IAP_KW_RSP		"rsp"
604
605static struct pmc_masks iap_core_mask[] = {
606	PMCMASK(all,	(0x3 << 14)),
607	PMCMASK(this,	(0x1 << 14)),
608	NULLMASK
609};
610
611static struct pmc_masks iap_agent_mask[] = {
612	PMCMASK(this,	0),
613	PMCMASK(any,	(0x1 << 13)),
614	NULLMASK
615};
616
617static struct pmc_masks iap_prefetch_mask[] = {
618	PMCMASK(both,		(0x3 << 12)),
619	PMCMASK(only,		(0x1 << 12)),
620	PMCMASK(exclude,	0),
621	NULLMASK
622};
623
624static struct pmc_masks iap_cachestate_mask[] = {
625	PMCMASK(i,		(1 <<  8)),
626	PMCMASK(s,		(1 <<  9)),
627	PMCMASK(e,		(1 << 10)),
628	PMCMASK(m,		(1 << 11)),
629	NULLMASK
630};
631
632static struct pmc_masks iap_snoopresponse_mask[] = {
633	PMCMASK(clean,		(1 << 8)),
634	PMCMASK(hit,		(1 << 9)),
635	PMCMASK(hitm,		(1 << 11)),
636	NULLMASK
637};
638
639static struct pmc_masks iap_snooptype_mask[] = {
640	PMCMASK(cmp2s,		(1 << 8)),
641	PMCMASK(cmp2i,		(1 << 9)),
642	NULLMASK
643};
644
645static struct pmc_masks iap_transition_mask[] = {
646	PMCMASK(any,		0x00),
647	PMCMASK(frequency,	0x10),
648	NULLMASK
649};
650
651static struct pmc_masks iap_rsp_mask[] = {
652	PMCMASK(DMND_DATA_RD,		(1 <<  0)),
653	PMCMASK(DMND_RFO,		(1 <<  1)),
654	PMCMASK(DMND_IFETCH,		(1 <<  2)),
655	PMCMASK(WB,			(1 <<  3)),
656	PMCMASK(PF_DATA_RD,		(1 <<  4)),
657	PMCMASK(PF_RFO,			(1 <<  5)),
658	PMCMASK(PF_IFETCH,		(1 <<  6)),
659	PMCMASK(OTHER,			(1 <<  7)),
660	PMCMASK(UNCORE_HIT,		(1 <<  8)),
661	PMCMASK(OTHER_CORE_HIT_SNP,	(1 <<  9)),
662	PMCMASK(OTHER_CORE_HITM,	(1 << 10)),
663	PMCMASK(REMOTE_CACHE_FWD,	(1 << 12)),
664	PMCMASK(REMOTE_DRAM,		(1 << 13)),
665	PMCMASK(LOCAL_DRAM,		(1 << 14)),
666	PMCMASK(NON_DRAM,		(1 << 15)),
667	NULLMASK
668};
669
670static int
671iap_allocate_pmc(enum pmc_event pe, char *ctrspec,
672    struct pmc_op_pmcallocate *pmc_config)
673{
674	char *e, *p, *q;
675	uint32_t cachestate, evmask, rsp;
676	int count, n;
677
678	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE |
679	    PMC_CAP_QUALIFIER);
680	pmc_config->pm_md.pm_iap.pm_iap_config = 0;
681
682	cachestate = evmask = rsp = 0;
683
684	/* Parse additional modifiers if present */
685	while ((p = strsep(&ctrspec, ",")) != NULL) {
686
687		n = 0;
688		if (KWPREFIXMATCH(p, IAP_KW_CMASK "=")) {
689			q = strchr(p, '=');
690			if (*++q == '\0') /* skip '=' */
691				return (-1);
692			count = strtol(q, &e, 0);
693			if (e == q || *e != '\0')
694				return (-1);
695			pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
696			pmc_config->pm_md.pm_iap.pm_iap_config |=
697			    IAP_CMASK(count);
698		} else if (KWMATCH(p, IAP_KW_EDGE)) {
699			pmc_config->pm_caps |= PMC_CAP_EDGE;
700		} else if (KWMATCH(p, IAP_KW_INV)) {
701			pmc_config->pm_caps |= PMC_CAP_INVERT;
702		} else if (KWMATCH(p, IAP_KW_OS)) {
703			pmc_config->pm_caps |= PMC_CAP_SYSTEM;
704		} else if (KWMATCH(p, IAP_KW_USR)) {
705			pmc_config->pm_caps |= PMC_CAP_USER;
706		} else if (KWMATCH(p, IAP_KW_ANYTHREAD)) {
707			pmc_config->pm_md.pm_iap.pm_iap_config |= IAP_ANY;
708		} else if (KWPREFIXMATCH(p, IAP_KW_CORE "=")) {
709			n = pmc_parse_mask(iap_core_mask, p, &evmask);
710			if (n != 1)
711				return (-1);
712		} else if (KWPREFIXMATCH(p, IAP_KW_AGENT "=")) {
713			n = pmc_parse_mask(iap_agent_mask, p, &evmask);
714			if (n != 1)
715				return (-1);
716		} else if (KWPREFIXMATCH(p, IAP_KW_PREFETCH "=")) {
717			n = pmc_parse_mask(iap_prefetch_mask, p, &evmask);
718			if (n != 1)
719				return (-1);
720		} else if (KWPREFIXMATCH(p, IAP_KW_CACHESTATE "=")) {
721			n = pmc_parse_mask(iap_cachestate_mask, p, &cachestate);
722		} else if (cpu_info.pm_cputype == PMC_CPU_INTEL_CORE &&
723		    KWPREFIXMATCH(p, IAP_KW_TRANSITION "=")) {
724			n = pmc_parse_mask(iap_transition_mask, p, &evmask);
725			if (n != 1)
726				return (-1);
727		} else if (cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM ||
728		    cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2 ||
729		    cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2EXTREME) {
730			if (KWPREFIXMATCH(p, IAP_KW_SNOOPRESPONSE "=")) {
731				n = pmc_parse_mask(iap_snoopresponse_mask, p,
732				    &evmask);
733			} else if (KWPREFIXMATCH(p, IAP_KW_SNOOPTYPE "=")) {
734				n = pmc_parse_mask(iap_snooptype_mask, p,
735				    &evmask);
736			} else
737				return (-1);
738		} else if (cpu_info.pm_cputype == PMC_CPU_INTEL_COREI7 ||
739		    cpu_info.pm_cputype == PMC_CPU_INTEL_WESTMERE) {
740			if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) {
741				n = pmc_parse_mask(iap_rsp_mask, p, &rsp);
742			} else
743				return (-1);
744		} else
745			return (-1);
746
747		if (n < 0)	/* Parsing failed. */
748			return (-1);
749	}
750
751	pmc_config->pm_md.pm_iap.pm_iap_config |= evmask;
752
753	/*
754	 * If the event requires a 'cachestate' qualifier but was not
755	 * specified by the user, use a sensible default.
756	 */
757	switch (pe) {
758	case PMC_EV_IAP_EVENT_28H: /* Core, Core2, Atom */
759	case PMC_EV_IAP_EVENT_29H: /* Core, Core2, Atom */
760	case PMC_EV_IAP_EVENT_2AH: /* Core, Core2, Atom */
761	case PMC_EV_IAP_EVENT_2BH: /* Atom, Core2 */
762	case PMC_EV_IAP_EVENT_2EH: /* Core, Core2, Atom */
763	case PMC_EV_IAP_EVENT_30H: /* Core, Core2, Atom */
764	case PMC_EV_IAP_EVENT_32H: /* Core */
765	case PMC_EV_IAP_EVENT_40H: /* Core */
766	case PMC_EV_IAP_EVENT_41H: /* Core */
767	case PMC_EV_IAP_EVENT_42H: /* Core, Core2, Atom */
768		if (cachestate == 0)
769			cachestate = (0xF << 8);
770		break;
771	case PMC_EV_IAP_EVENT_77H: /* Atom */
772		/* IAP_EVENT_77H only accepts a cachestate qualifier on the
773		 * Atom processor
774		 */
775		if(cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM && cachestate == 0)
776			cachestate = (0xF << 8);
777	    break;
778	default:
779		break;
780	}
781
782	pmc_config->pm_md.pm_iap.pm_iap_config |= cachestate;
783	pmc_config->pm_md.pm_iap.pm_iap_rsp = rsp;
784
785	return (0);
786}
787
788/*
789 * Intel Uncore.
790 */
791
792static int
793ucf_allocate_pmc(enum pmc_event pe, char *ctrspec,
794    struct pmc_op_pmcallocate *pmc_config)
795{
796	(void) pe;
797	(void) ctrspec;
798
799	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
800	pmc_config->pm_md.pm_ucf.pm_ucf_flags = 0;
801
802	return (0);
803}
804
805#define	UCP_KW_CMASK		"cmask"
806#define	UCP_KW_EDGE		"edge"
807#define	UCP_KW_INV		"inv"
808
809static int
810ucp_allocate_pmc(enum pmc_event pe, char *ctrspec,
811    struct pmc_op_pmcallocate *pmc_config)
812{
813	char *e, *p, *q;
814	int count, n;
815
816	(void) pe;
817
818	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE |
819	    PMC_CAP_QUALIFIER);
820	pmc_config->pm_md.pm_ucp.pm_ucp_config = 0;
821
822	/* Parse additional modifiers if present */
823	while ((p = strsep(&ctrspec, ",")) != NULL) {
824
825		n = 0;
826		if (KWPREFIXMATCH(p, UCP_KW_CMASK "=")) {
827			q = strchr(p, '=');
828			if (*++q == '\0') /* skip '=' */
829				return (-1);
830			count = strtol(q, &e, 0);
831			if (e == q || *e != '\0')
832				return (-1);
833			pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
834			pmc_config->pm_md.pm_ucp.pm_ucp_config |=
835			    UCP_CMASK(count);
836		} else if (KWMATCH(p, UCP_KW_EDGE)) {
837			pmc_config->pm_caps |= PMC_CAP_EDGE;
838		} else if (KWMATCH(p, UCP_KW_INV)) {
839			pmc_config->pm_caps |= PMC_CAP_INVERT;
840		} else
841			return (-1);
842
843		if (n < 0)	/* Parsing failed. */
844			return (-1);
845	}
846
847	return (0);
848}
849
850/*
851 * AMD K8 PMCs.
852 *
853 * These are very similar to AMD K7 PMCs, but support more kinds of
854 * events.
855 */
856
857static struct pmc_event_alias k8_aliases[] = {
858	EV_ALIAS("branches",		"k8-fr-retired-taken-branches"),
859	EV_ALIAS("branch-mispredicts",
860	    "k8-fr-retired-taken-branches-mispredicted"),
861	EV_ALIAS("cycles",		"tsc"),
862	EV_ALIAS("dc-misses",		"k8-dc-miss"),
863	EV_ALIAS("ic-misses",		"k8-ic-miss"),
864	EV_ALIAS("instructions",	"k8-fr-retired-x86-instructions"),
865	EV_ALIAS("interrupts",		"k8-fr-taken-hardware-interrupts"),
866	EV_ALIAS("unhalted-cycles",	"k8-bu-cpu-clk-unhalted"),
867	EV_ALIAS(NULL, NULL)
868};
869
870#define	__K8MASK(N,V) PMCMASK(N,(1 << (V)))
871
872/*
873 * Parsing tables
874 */
875
876/* fp dispatched fpu ops */
877static const struct pmc_masks k8_mask_fdfo[] = {
878	__K8MASK(add-pipe-excluding-junk-ops,	0),
879	__K8MASK(multiply-pipe-excluding-junk-ops,	1),
880	__K8MASK(store-pipe-excluding-junk-ops,	2),
881	__K8MASK(add-pipe-junk-ops,		3),
882	__K8MASK(multiply-pipe-junk-ops,	4),
883	__K8MASK(store-pipe-junk-ops,		5),
884	NULLMASK
885};
886
887/* ls segment register loads */
888static const struct pmc_masks k8_mask_lsrl[] = {
889	__K8MASK(es,	0),
890	__K8MASK(cs,	1),
891	__K8MASK(ss,	2),
892	__K8MASK(ds,	3),
893	__K8MASK(fs,	4),
894	__K8MASK(gs,	5),
895	__K8MASK(hs,	6),
896	NULLMASK
897};
898
899/* ls locked operation */
900static const struct pmc_masks k8_mask_llo[] = {
901	__K8MASK(locked-instructions,	0),
902	__K8MASK(cycles-in-request,	1),
903	__K8MASK(cycles-to-complete,	2),
904	NULLMASK
905};
906
907/* dc refill from {l2,system} and dc copyback */
908static const struct pmc_masks k8_mask_dc[] = {
909	__K8MASK(invalid,	0),
910	__K8MASK(shared,	1),
911	__K8MASK(exclusive,	2),
912	__K8MASK(owner,		3),
913	__K8MASK(modified,	4),
914	NULLMASK
915};
916
917/* dc one bit ecc error */
918static const struct pmc_masks k8_mask_dobee[] = {
919	__K8MASK(scrubber,	0),
920	__K8MASK(piggyback,	1),
921	NULLMASK
922};
923
924/* dc dispatched prefetch instructions */
925static const struct pmc_masks k8_mask_ddpi[] = {
926	__K8MASK(load,	0),
927	__K8MASK(store,	1),
928	__K8MASK(nta,	2),
929	NULLMASK
930};
931
932/* dc dcache accesses by locks */
933static const struct pmc_masks k8_mask_dabl[] = {
934	__K8MASK(accesses,	0),
935	__K8MASK(misses,	1),
936	NULLMASK
937};
938
939/* bu internal l2 request */
940static const struct pmc_masks k8_mask_bilr[] = {
941	__K8MASK(ic-fill,	0),
942	__K8MASK(dc-fill,	1),
943	__K8MASK(tlb-reload,	2),
944	__K8MASK(tag-snoop,	3),
945	__K8MASK(cancelled,	4),
946	NULLMASK
947};
948
949/* bu fill request l2 miss */
950static const struct pmc_masks k8_mask_bfrlm[] = {
951	__K8MASK(ic-fill,	0),
952	__K8MASK(dc-fill,	1),
953	__K8MASK(tlb-reload,	2),
954	NULLMASK
955};
956
957/* bu fill into l2 */
958static const struct pmc_masks k8_mask_bfil[] = {
959	__K8MASK(dirty-l2-victim,	0),
960	__K8MASK(victim-from-l2,	1),
961	NULLMASK
962};
963
964/* fr retired fpu instructions */
965static const struct pmc_masks k8_mask_frfi[] = {
966	__K8MASK(x87,			0),
967	__K8MASK(mmx-3dnow,		1),
968	__K8MASK(packed-sse-sse2,	2),
969	__K8MASK(scalar-sse-sse2,	3),
970	NULLMASK
971};
972
973/* fr retired fastpath double op instructions */
974static const struct pmc_masks k8_mask_frfdoi[] = {
975	__K8MASK(low-op-pos-0,		0),
976	__K8MASK(low-op-pos-1,		1),
977	__K8MASK(low-op-pos-2,		2),
978	NULLMASK
979};
980
981/* fr fpu exceptions */
982static const struct pmc_masks k8_mask_ffe[] = {
983	__K8MASK(x87-reclass-microfaults,	0),
984	__K8MASK(sse-retype-microfaults,	1),
985	__K8MASK(sse-reclass-microfaults,	2),
986	__K8MASK(sse-and-x87-microtraps,	3),
987	NULLMASK
988};
989
990/* nb memory controller page access event */
991static const struct pmc_masks k8_mask_nmcpae[] = {
992	__K8MASK(page-hit,	0),
993	__K8MASK(page-miss,	1),
994	__K8MASK(page-conflict,	2),
995	NULLMASK
996};
997
998/* nb memory controller turnaround */
999static const struct pmc_masks k8_mask_nmct[] = {
1000	__K8MASK(dimm-turnaround,		0),
1001	__K8MASK(read-to-write-turnaround,	1),
1002	__K8MASK(write-to-read-turnaround,	2),
1003	NULLMASK
1004};
1005
1006/* nb memory controller bypass saturation */
1007static const struct pmc_masks k8_mask_nmcbs[] = {
1008	__K8MASK(memory-controller-hi-pri-bypass,	0),
1009	__K8MASK(memory-controller-lo-pri-bypass,	1),
1010	__K8MASK(dram-controller-interface-bypass,	2),
1011	__K8MASK(dram-controller-queue-bypass,		3),
1012	NULLMASK
1013};
1014
1015/* nb sized commands */
1016static const struct pmc_masks k8_mask_nsc[] = {
1017	__K8MASK(nonpostwrszbyte,	0),
1018	__K8MASK(nonpostwrszdword,	1),
1019	__K8MASK(postwrszbyte,		2),
1020	__K8MASK(postwrszdword,		3),
1021	__K8MASK(rdszbyte,		4),
1022	__K8MASK(rdszdword,		5),
1023	__K8MASK(rdmodwr,		6),
1024	NULLMASK
1025};
1026
1027/* nb probe result */
1028static const struct pmc_masks k8_mask_npr[] = {
1029	__K8MASK(probe-miss,		0),
1030	__K8MASK(probe-hit,		1),
1031	__K8MASK(probe-hit-dirty-no-memory-cancel, 2),
1032	__K8MASK(probe-hit-dirty-with-memory-cancel, 3),
1033	NULLMASK
1034};
1035
1036/* nb hypertransport bus bandwidth */
1037static const struct pmc_masks k8_mask_nhbb[] = { /* HT bus bandwidth */
1038	__K8MASK(command,	0),
1039	__K8MASK(data,	1),
1040	__K8MASK(buffer-release, 2),
1041	__K8MASK(nop,	3),
1042	NULLMASK
1043};
1044
1045#undef	__K8MASK
1046
1047#define	K8_KW_COUNT	"count"
1048#define	K8_KW_EDGE	"edge"
1049#define	K8_KW_INV	"inv"
1050#define	K8_KW_MASK	"mask"
1051#define	K8_KW_OS	"os"
1052#define	K8_KW_USR	"usr"
1053
1054static int
1055k8_allocate_pmc(enum pmc_event pe, char *ctrspec,
1056    struct pmc_op_pmcallocate *pmc_config)
1057{
1058	char		*e, *p, *q;
1059	int		n;
1060	uint32_t	count, evmask;
1061	const struct pmc_masks	*pm, *pmask;
1062
1063	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
1064	pmc_config->pm_md.pm_amd.pm_amd_config = 0;
1065
1066	pmask = NULL;
1067	evmask = 0;
1068
1069#define	__K8SETMASK(M) pmask = k8_mask_##M
1070
1071	/* setup parsing tables */
1072	switch (pe) {
1073	case PMC_EV_K8_FP_DISPATCHED_FPU_OPS:
1074		__K8SETMASK(fdfo);
1075		break;
1076	case PMC_EV_K8_LS_SEGMENT_REGISTER_LOAD:
1077		__K8SETMASK(lsrl);
1078		break;
1079	case PMC_EV_K8_LS_LOCKED_OPERATION:
1080		__K8SETMASK(llo);
1081		break;
1082	case PMC_EV_K8_DC_REFILL_FROM_L2:
1083	case PMC_EV_K8_DC_REFILL_FROM_SYSTEM:
1084	case PMC_EV_K8_DC_COPYBACK:
1085		__K8SETMASK(dc);
1086		break;
1087	case PMC_EV_K8_DC_ONE_BIT_ECC_ERROR:
1088		__K8SETMASK(dobee);
1089		break;
1090	case PMC_EV_K8_DC_DISPATCHED_PREFETCH_INSTRUCTIONS:
1091		__K8SETMASK(ddpi);
1092		break;
1093	case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS:
1094		__K8SETMASK(dabl);
1095		break;
1096	case PMC_EV_K8_BU_INTERNAL_L2_REQUEST:
1097		__K8SETMASK(bilr);
1098		break;
1099	case PMC_EV_K8_BU_FILL_REQUEST_L2_MISS:
1100		__K8SETMASK(bfrlm);
1101		break;
1102	case PMC_EV_K8_BU_FILL_INTO_L2:
1103		__K8SETMASK(bfil);
1104		break;
1105	case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS:
1106		__K8SETMASK(frfi);
1107		break;
1108	case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS:
1109		__K8SETMASK(frfdoi);
1110		break;
1111	case PMC_EV_K8_FR_FPU_EXCEPTIONS:
1112		__K8SETMASK(ffe);
1113		break;
1114	case PMC_EV_K8_NB_MEMORY_CONTROLLER_PAGE_ACCESS_EVENT:
1115		__K8SETMASK(nmcpae);
1116		break;
1117	case PMC_EV_K8_NB_MEMORY_CONTROLLER_TURNAROUND:
1118		__K8SETMASK(nmct);
1119		break;
1120	case PMC_EV_K8_NB_MEMORY_CONTROLLER_BYPASS_SATURATION:
1121		__K8SETMASK(nmcbs);
1122		break;
1123	case PMC_EV_K8_NB_SIZED_COMMANDS:
1124		__K8SETMASK(nsc);
1125		break;
1126	case PMC_EV_K8_NB_PROBE_RESULT:
1127		__K8SETMASK(npr);
1128		break;
1129	case PMC_EV_K8_NB_HT_BUS0_BANDWIDTH:
1130	case PMC_EV_K8_NB_HT_BUS1_BANDWIDTH:
1131	case PMC_EV_K8_NB_HT_BUS2_BANDWIDTH:
1132		__K8SETMASK(nhbb);
1133		break;
1134
1135	default:
1136		break;		/* no options defined */
1137	}
1138
1139	while ((p = strsep(&ctrspec, ",")) != NULL) {
1140		if (KWPREFIXMATCH(p, K8_KW_COUNT "=")) {
1141			q = strchr(p, '=');
1142			if (*++q == '\0') /* skip '=' */
1143				return (-1);
1144
1145			count = strtol(q, &e, 0);
1146			if (e == q || *e != '\0')
1147				return (-1);
1148
1149			pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
1150			pmc_config->pm_md.pm_amd.pm_amd_config |=
1151			    AMD_PMC_TO_COUNTER(count);
1152
1153		} else if (KWMATCH(p, K8_KW_EDGE)) {
1154			pmc_config->pm_caps |= PMC_CAP_EDGE;
1155		} else if (KWMATCH(p, K8_KW_INV)) {
1156			pmc_config->pm_caps |= PMC_CAP_INVERT;
1157		} else if (KWPREFIXMATCH(p, K8_KW_MASK "=")) {
1158			if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0)
1159				return (-1);
1160			pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
1161		} else if (KWMATCH(p, K8_KW_OS)) {
1162			pmc_config->pm_caps |= PMC_CAP_SYSTEM;
1163		} else if (KWMATCH(p, K8_KW_USR)) {
1164			pmc_config->pm_caps |= PMC_CAP_USER;
1165		} else
1166			return (-1);
1167	}
1168
1169	/* other post processing */
1170	switch (pe) {
1171	case PMC_EV_K8_FP_DISPATCHED_FPU_OPS:
1172	case PMC_EV_K8_FP_CYCLES_WITH_NO_FPU_OPS_RETIRED:
1173	case PMC_EV_K8_FP_DISPATCHED_FPU_FAST_FLAG_OPS:
1174	case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS:
1175	case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS:
1176	case PMC_EV_K8_FR_FPU_EXCEPTIONS:
1177		/* XXX only available in rev B and later */
1178		break;
1179	case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS:
1180		/* XXX only available in rev C and later */
1181		break;
1182	case PMC_EV_K8_LS_LOCKED_OPERATION:
1183		/* XXX CPU Rev A,B evmask is to be zero */
1184		if (evmask & (evmask - 1)) /* > 1 bit set */
1185			return (-1);
1186		if (evmask == 0) {
1187			evmask = 0x01; /* Rev C and later: #instrs */
1188			pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
1189		}
1190		break;
1191	default:
1192		if (evmask == 0 && pmask != NULL) {
1193			for (pm = pmask; pm->pm_name; pm++)
1194				evmask |= pm->pm_value;
1195			pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
1196		}
1197	}
1198
1199	if (pmc_config->pm_caps & PMC_CAP_QUALIFIER)
1200		pmc_config->pm_md.pm_amd.pm_amd_config =
1201		    AMD_PMC_TO_UNITMASK(evmask);
1202
1203	return (0);
1204}
1205
1206#endif
1207
1208#if defined(__amd64__) || defined(__i386__)
1209
1210/*
1211 * Intel P4 PMCs
1212 */
1213
1214static struct pmc_event_alias p4_aliases[] = {
1215	EV_ALIAS("branches",		"p4-branch-retired,mask=mmtp+mmtm"),
1216	EV_ALIAS("branch-mispredicts",	"p4-mispred-branch-retired"),
1217	EV_ALIAS("cycles",		"tsc"),
1218	EV_ALIAS("instructions",
1219	    "p4-instr-retired,mask=nbogusntag+nbogustag"),
1220	EV_ALIAS("unhalted-cycles",	"p4-global-power-events"),
1221	EV_ALIAS(NULL, NULL)
1222};
1223
1224#define	P4_KW_ACTIVE	"active"
1225#define	P4_KW_ACTIVE_ANY "any"
1226#define	P4_KW_ACTIVE_BOTH "both"
1227#define	P4_KW_ACTIVE_NONE "none"
1228#define	P4_KW_ACTIVE_SINGLE "single"
1229#define	P4_KW_BUSREQTYPE "busreqtype"
1230#define	P4_KW_CASCADE	"cascade"
1231#define	P4_KW_EDGE	"edge"
1232#define	P4_KW_INV	"complement"
1233#define	P4_KW_OS	"os"
1234#define	P4_KW_MASK	"mask"
1235#define	P4_KW_PRECISE	"precise"
1236#define	P4_KW_TAG	"tag"
1237#define	P4_KW_THRESHOLD	"threshold"
1238#define	P4_KW_USR	"usr"
1239
1240#define	__P4MASK(N,V) PMCMASK(N, (1 << (V)))
1241
1242static const struct pmc_masks p4_mask_tcdm[] = { /* tc deliver mode */
1243	__P4MASK(dd, 0),
1244	__P4MASK(db, 1),
1245	__P4MASK(di, 2),
1246	__P4MASK(bd, 3),
1247	__P4MASK(bb, 4),
1248	__P4MASK(bi, 5),
1249	__P4MASK(id, 6),
1250	__P4MASK(ib, 7),
1251	NULLMASK
1252};
1253
1254static const struct pmc_masks p4_mask_bfr[] = { /* bpu fetch request */
1255	__P4MASK(tcmiss, 0),
1256	NULLMASK,
1257};
1258
1259static const struct pmc_masks p4_mask_ir[] = { /* itlb reference */
1260	__P4MASK(hit, 0),
1261	__P4MASK(miss, 1),
1262	__P4MASK(hit-uc, 2),
1263	NULLMASK
1264};
1265
1266static const struct pmc_masks p4_mask_memcan[] = { /* memory cancel */
1267	__P4MASK(st-rb-full, 2),
1268	__P4MASK(64k-conf, 3),
1269	NULLMASK
1270};
1271
1272static const struct pmc_masks p4_mask_memcomp[] = { /* memory complete */
1273	__P4MASK(lsc, 0),
1274	__P4MASK(ssc, 1),
1275	NULLMASK
1276};
1277
1278static const struct pmc_masks p4_mask_lpr[] = { /* load port replay */
1279	__P4MASK(split-ld, 1),
1280	NULLMASK
1281};
1282
1283static const struct pmc_masks p4_mask_spr[] = { /* store port replay */
1284	__P4MASK(split-st, 1),
1285	NULLMASK
1286};
1287
1288static const struct pmc_masks p4_mask_mlr[] = { /* mob load replay */
1289	__P4MASK(no-sta, 1),
1290	__P4MASK(no-std, 3),
1291	__P4MASK(partial-data, 4),
1292	__P4MASK(unalgn-addr, 5),
1293	NULLMASK
1294};
1295
1296static const struct pmc_masks p4_mask_pwt[] = { /* page walk type */
1297	__P4MASK(dtmiss, 0),
1298	__P4MASK(itmiss, 1),
1299	NULLMASK
1300};
1301
1302static const struct pmc_masks p4_mask_bcr[] = { /* bsq cache reference */
1303	__P4MASK(rd-2ndl-hits, 0),
1304	__P4MASK(rd-2ndl-hite, 1),
1305	__P4MASK(rd-2ndl-hitm, 2),
1306	__P4MASK(rd-3rdl-hits, 3),
1307	__P4MASK(rd-3rdl-hite, 4),
1308	__P4MASK(rd-3rdl-hitm, 5),
1309	__P4MASK(rd-2ndl-miss, 8),
1310	__P4MASK(rd-3rdl-miss, 9),
1311	__P4MASK(wr-2ndl-miss, 10),
1312	NULLMASK
1313};
1314
1315static const struct pmc_masks p4_mask_ia[] = { /* ioq allocation */
1316	__P4MASK(all-read, 5),
1317	__P4MASK(all-write, 6),
1318	__P4MASK(mem-uc, 7),
1319	__P4MASK(mem-wc, 8),
1320	__P4MASK(mem-wt, 9),
1321	__P4MASK(mem-wp, 10),
1322	__P4MASK(mem-wb, 11),
1323	__P4MASK(own, 13),
1324	__P4MASK(other, 14),
1325	__P4MASK(prefetch, 15),
1326	NULLMASK
1327};
1328
1329static const struct pmc_masks p4_mask_iae[] = { /* ioq active entries */
1330	__P4MASK(all-read, 5),
1331	__P4MASK(all-write, 6),
1332	__P4MASK(mem-uc, 7),
1333	__P4MASK(mem-wc, 8),
1334	__P4MASK(mem-wt, 9),
1335	__P4MASK(mem-wp, 10),
1336	__P4MASK(mem-wb, 11),
1337	__P4MASK(own, 13),
1338	__P4MASK(other, 14),
1339	__P4MASK(prefetch, 15),
1340	NULLMASK
1341};
1342
1343static const struct pmc_masks p4_mask_fda[] = { /* fsb data activity */
1344	__P4MASK(drdy-drv, 0),
1345	__P4MASK(drdy-own, 1),
1346	__P4MASK(drdy-other, 2),
1347	__P4MASK(dbsy-drv, 3),
1348	__P4MASK(dbsy-own, 4),
1349	__P4MASK(dbsy-other, 5),
1350	NULLMASK
1351};
1352
1353static const struct pmc_masks p4_mask_ba[] = { /* bsq allocation */
1354	__P4MASK(req-type0, 0),
1355	__P4MASK(req-type1, 1),
1356	__P4MASK(req-len0, 2),
1357	__P4MASK(req-len1, 3),
1358	__P4MASK(req-io-type, 5),
1359	__P4MASK(req-lock-type, 6),
1360	__P4MASK(req-cache-type, 7),
1361	__P4MASK(req-split-type, 8),
1362	__P4MASK(req-dem-type, 9),
1363	__P4MASK(req-ord-type, 10),
1364	__P4MASK(mem-type0, 11),
1365	__P4MASK(mem-type1, 12),
1366	__P4MASK(mem-type2, 13),
1367	NULLMASK
1368};
1369
1370static const struct pmc_masks p4_mask_sia[] = { /* sse input assist */
1371	__P4MASK(all, 15),
1372	NULLMASK
1373};
1374
1375static const struct pmc_masks p4_mask_psu[] = { /* packed sp uop */
1376	__P4MASK(all, 15),
1377	NULLMASK
1378};
1379
1380static const struct pmc_masks p4_mask_pdu[] = { /* packed dp uop */
1381	__P4MASK(all, 15),
1382	NULLMASK
1383};
1384
1385static const struct pmc_masks p4_mask_ssu[] = { /* scalar sp uop */
1386	__P4MASK(all, 15),
1387	NULLMASK
1388};
1389
1390static const struct pmc_masks p4_mask_sdu[] = { /* scalar dp uop */
1391	__P4MASK(all, 15),
1392	NULLMASK
1393};
1394
1395static const struct pmc_masks p4_mask_64bmu[] = { /* 64 bit mmx uop */
1396	__P4MASK(all, 15),
1397	NULLMASK
1398};
1399
1400static const struct pmc_masks p4_mask_128bmu[] = { /* 128 bit mmx uop */
1401	__P4MASK(all, 15),
1402	NULLMASK
1403};
1404
1405static const struct pmc_masks p4_mask_xfu[] = { /* X87 fp uop */
1406	__P4MASK(all, 15),
1407	NULLMASK
1408};
1409
1410static const struct pmc_masks p4_mask_xsmu[] = { /* x87 simd moves uop */
1411	__P4MASK(allp0, 3),
1412	__P4MASK(allp2, 4),
1413	NULLMASK
1414};
1415
1416static const struct pmc_masks p4_mask_gpe[] = { /* global power events */
1417	__P4MASK(running, 0),
1418	NULLMASK
1419};
1420
1421static const struct pmc_masks p4_mask_tmx[] = { /* TC ms xfer */
1422	__P4MASK(cisc, 0),
1423	NULLMASK
1424};
1425
1426static const struct pmc_masks p4_mask_uqw[] = { /* uop queue writes */
1427	__P4MASK(from-tc-build, 0),
1428	__P4MASK(from-tc-deliver, 1),
1429	__P4MASK(from-rom, 2),
1430	NULLMASK
1431};
1432
1433static const struct pmc_masks p4_mask_rmbt[] = {
1434	/* retired mispred branch type */
1435	__P4MASK(conditional, 1),
1436	__P4MASK(call, 2),
1437	__P4MASK(return, 3),
1438	__P4MASK(indirect, 4),
1439	NULLMASK
1440};
1441
1442static const struct pmc_masks p4_mask_rbt[] = { /* retired branch type */
1443	__P4MASK(conditional, 1),
1444	__P4MASK(call, 2),
1445	__P4MASK(retired, 3),
1446	__P4MASK(indirect, 4),
1447	NULLMASK
1448};
1449
1450static const struct pmc_masks p4_mask_rs[] = { /* resource stall */
1451	__P4MASK(sbfull, 5),
1452	NULLMASK
1453};
1454
1455static const struct pmc_masks p4_mask_wb[] = { /* WC buffer */
1456	__P4MASK(wcb-evicts, 0),
1457	__P4MASK(wcb-full-evict, 1),
1458	NULLMASK
1459};
1460
1461static const struct pmc_masks p4_mask_fee[] = { /* front end event */
1462	__P4MASK(nbogus, 0),
1463	__P4MASK(bogus, 1),
1464	NULLMASK
1465};
1466
1467static const struct pmc_masks p4_mask_ee[] = { /* execution event */
1468	__P4MASK(nbogus0, 0),
1469	__P4MASK(nbogus1, 1),
1470	__P4MASK(nbogus2, 2),
1471	__P4MASK(nbogus3, 3),
1472	__P4MASK(bogus0, 4),
1473	__P4MASK(bogus1, 5),
1474	__P4MASK(bogus2, 6),
1475	__P4MASK(bogus3, 7),
1476	NULLMASK
1477};
1478
1479static const struct pmc_masks p4_mask_re[] = { /* replay event */
1480	__P4MASK(nbogus, 0),
1481	__P4MASK(bogus, 1),
1482	NULLMASK
1483};
1484
1485static const struct pmc_masks p4_mask_insret[] = { /* instr retired */
1486	__P4MASK(nbogusntag, 0),
1487	__P4MASK(nbogustag, 1),
1488	__P4MASK(bogusntag, 2),
1489	__P4MASK(bogustag, 3),
1490	NULLMASK
1491};
1492
1493static const struct pmc_masks p4_mask_ur[] = { /* uops retired */
1494	__P4MASK(nbogus, 0),
1495	__P4MASK(bogus, 1),
1496	NULLMASK
1497};
1498
1499static const struct pmc_masks p4_mask_ut[] = { /* uop type */
1500	__P4MASK(tagloads, 1),
1501	__P4MASK(tagstores, 2),
1502	NULLMASK
1503};
1504
1505static const struct pmc_masks p4_mask_br[] = { /* branch retired */
1506	__P4MASK(mmnp, 0),
1507	__P4MASK(mmnm, 1),
1508	__P4MASK(mmtp, 2),
1509	__P4MASK(mmtm, 3),
1510	NULLMASK
1511};
1512
1513static const struct pmc_masks p4_mask_mbr[] = { /* mispred branch retired */
1514	__P4MASK(nbogus, 0),
1515	NULLMASK
1516};
1517
1518static const struct pmc_masks p4_mask_xa[] = { /* x87 assist */
1519	__P4MASK(fpsu, 0),
1520	__P4MASK(fpso, 1),
1521	__P4MASK(poao, 2),
1522	__P4MASK(poau, 3),
1523	__P4MASK(prea, 4),
1524	NULLMASK
1525};
1526
1527static const struct pmc_masks p4_mask_machclr[] = { /* machine clear */
1528	__P4MASK(clear, 0),
1529	__P4MASK(moclear, 2),
1530	__P4MASK(smclear, 3),
1531	NULLMASK
1532};
1533
1534/* P4 event parser */
1535static int
1536p4_allocate_pmc(enum pmc_event pe, char *ctrspec,
1537    struct pmc_op_pmcallocate *pmc_config)
1538{
1539
1540	char	*e, *p, *q;
1541	int	count, has_tag, has_busreqtype, n;
1542	uint32_t evmask, cccractivemask;
1543	const struct pmc_masks *pm, *pmask;
1544
1545	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
1546	pmc_config->pm_md.pm_p4.pm_p4_cccrconfig =
1547	    pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 0;
1548
1549	pmask   = NULL;
1550	evmask  = 0;
1551	cccractivemask = 0x3;
1552	has_tag = has_busreqtype = 0;
1553
1554#define	__P4SETMASK(M) do {				\
1555	pmask = p4_mask_##M;				\
1556} while (0)
1557
1558	switch (pe) {
1559	case PMC_EV_P4_TC_DELIVER_MODE:
1560		__P4SETMASK(tcdm);
1561		break;
1562	case PMC_EV_P4_BPU_FETCH_REQUEST:
1563		__P4SETMASK(bfr);
1564		break;
1565	case PMC_EV_P4_ITLB_REFERENCE:
1566		__P4SETMASK(ir);
1567		break;
1568	case PMC_EV_P4_MEMORY_CANCEL:
1569		__P4SETMASK(memcan);
1570		break;
1571	case PMC_EV_P4_MEMORY_COMPLETE:
1572		__P4SETMASK(memcomp);
1573		break;
1574	case PMC_EV_P4_LOAD_PORT_REPLAY:
1575		__P4SETMASK(lpr);
1576		break;
1577	case PMC_EV_P4_STORE_PORT_REPLAY:
1578		__P4SETMASK(spr);
1579		break;
1580	case PMC_EV_P4_MOB_LOAD_REPLAY:
1581		__P4SETMASK(mlr);
1582		break;
1583	case PMC_EV_P4_PAGE_WALK_TYPE:
1584		__P4SETMASK(pwt);
1585		break;
1586	case PMC_EV_P4_BSQ_CACHE_REFERENCE:
1587		__P4SETMASK(bcr);
1588		break;
1589	case PMC_EV_P4_IOQ_ALLOCATION:
1590		__P4SETMASK(ia);
1591		has_busreqtype = 1;
1592		break;
1593	case PMC_EV_P4_IOQ_ACTIVE_ENTRIES:
1594		__P4SETMASK(iae);
1595		has_busreqtype = 1;
1596		break;
1597	case PMC_EV_P4_FSB_DATA_ACTIVITY:
1598		__P4SETMASK(fda);
1599		break;
1600	case PMC_EV_P4_BSQ_ALLOCATION:
1601		__P4SETMASK(ba);
1602		break;
1603	case PMC_EV_P4_SSE_INPUT_ASSIST:
1604		__P4SETMASK(sia);
1605		break;
1606	case PMC_EV_P4_PACKED_SP_UOP:
1607		__P4SETMASK(psu);
1608		break;
1609	case PMC_EV_P4_PACKED_DP_UOP:
1610		__P4SETMASK(pdu);
1611		break;
1612	case PMC_EV_P4_SCALAR_SP_UOP:
1613		__P4SETMASK(ssu);
1614		break;
1615	case PMC_EV_P4_SCALAR_DP_UOP:
1616		__P4SETMASK(sdu);
1617		break;
1618	case PMC_EV_P4_64BIT_MMX_UOP:
1619		__P4SETMASK(64bmu);
1620		break;
1621	case PMC_EV_P4_128BIT_MMX_UOP:
1622		__P4SETMASK(128bmu);
1623		break;
1624	case PMC_EV_P4_X87_FP_UOP:
1625		__P4SETMASK(xfu);
1626		break;
1627	case PMC_EV_P4_X87_SIMD_MOVES_UOP:
1628		__P4SETMASK(xsmu);
1629		break;
1630	case PMC_EV_P4_GLOBAL_POWER_EVENTS:
1631		__P4SETMASK(gpe);
1632		break;
1633	case PMC_EV_P4_TC_MS_XFER:
1634		__P4SETMASK(tmx);
1635		break;
1636	case PMC_EV_P4_UOP_QUEUE_WRITES:
1637		__P4SETMASK(uqw);
1638		break;
1639	case PMC_EV_P4_RETIRED_MISPRED_BRANCH_TYPE:
1640		__P4SETMASK(rmbt);
1641		break;
1642	case PMC_EV_P4_RETIRED_BRANCH_TYPE:
1643		__P4SETMASK(rbt);
1644		break;
1645	case PMC_EV_P4_RESOURCE_STALL:
1646		__P4SETMASK(rs);
1647		break;
1648	case PMC_EV_P4_WC_BUFFER:
1649		__P4SETMASK(wb);
1650		break;
1651	case PMC_EV_P4_BSQ_ACTIVE_ENTRIES:
1652	case PMC_EV_P4_B2B_CYCLES:
1653	case PMC_EV_P4_BNR:
1654	case PMC_EV_P4_SNOOP:
1655	case PMC_EV_P4_RESPONSE:
1656		break;
1657	case PMC_EV_P4_FRONT_END_EVENT:
1658		__P4SETMASK(fee);
1659		break;
1660	case PMC_EV_P4_EXECUTION_EVENT:
1661		__P4SETMASK(ee);
1662		break;
1663	case PMC_EV_P4_REPLAY_EVENT:
1664		__P4SETMASK(re);
1665		break;
1666	case PMC_EV_P4_INSTR_RETIRED:
1667		__P4SETMASK(insret);
1668		break;
1669	case PMC_EV_P4_UOPS_RETIRED:
1670		__P4SETMASK(ur);
1671		break;
1672	case PMC_EV_P4_UOP_TYPE:
1673		__P4SETMASK(ut);
1674		break;
1675	case PMC_EV_P4_BRANCH_RETIRED:
1676		__P4SETMASK(br);
1677		break;
1678	case PMC_EV_P4_MISPRED_BRANCH_RETIRED:
1679		__P4SETMASK(mbr);
1680		break;
1681	case PMC_EV_P4_X87_ASSIST:
1682		__P4SETMASK(xa);
1683		break;
1684	case PMC_EV_P4_MACHINE_CLEAR:
1685		__P4SETMASK(machclr);
1686		break;
1687	default:
1688		return (-1);
1689	}
1690
1691	/* process additional flags */
1692	while ((p = strsep(&ctrspec, ",")) != NULL) {
1693		if (KWPREFIXMATCH(p, P4_KW_ACTIVE)) {
1694			q = strchr(p, '=');
1695			if (*++q == '\0') /* skip '=' */
1696				return (-1);
1697
1698			if (strcasecmp(q, P4_KW_ACTIVE_NONE) == 0)
1699				cccractivemask = 0x0;
1700			else if (strcasecmp(q, P4_KW_ACTIVE_SINGLE) == 0)
1701				cccractivemask = 0x1;
1702			else if (strcasecmp(q, P4_KW_ACTIVE_BOTH) == 0)
1703				cccractivemask = 0x2;
1704			else if (strcasecmp(q, P4_KW_ACTIVE_ANY) == 0)
1705				cccractivemask = 0x3;
1706			else
1707				return (-1);
1708
1709		} else if (KWPREFIXMATCH(p, P4_KW_BUSREQTYPE)) {
1710			if (has_busreqtype == 0)
1711				return (-1);
1712
1713			q = strchr(p, '=');
1714			if (*++q == '\0') /* skip '=' */
1715				return (-1);
1716
1717			count = strtol(q, &e, 0);
1718			if (e == q || *e != '\0')
1719				return (-1);
1720			evmask = (evmask & ~0x1F) | (count & 0x1F);
1721		} else if (KWMATCH(p, P4_KW_CASCADE))
1722			pmc_config->pm_caps |= PMC_CAP_CASCADE;
1723		else if (KWMATCH(p, P4_KW_EDGE))
1724			pmc_config->pm_caps |= PMC_CAP_EDGE;
1725		else if (KWMATCH(p, P4_KW_INV))
1726			pmc_config->pm_caps |= PMC_CAP_INVERT;
1727		else if (KWPREFIXMATCH(p, P4_KW_MASK "=")) {
1728			if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0)
1729				return (-1);
1730			pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
1731		} else if (KWMATCH(p, P4_KW_OS))
1732			pmc_config->pm_caps |= PMC_CAP_SYSTEM;
1733		else if (KWMATCH(p, P4_KW_PRECISE))
1734			pmc_config->pm_caps |= PMC_CAP_PRECISE;
1735		else if (KWPREFIXMATCH(p, P4_KW_TAG "=")) {
1736			if (has_tag == 0)
1737				return (-1);
1738
1739			q = strchr(p, '=');
1740			if (*++q == '\0') /* skip '=' */
1741				return (-1);
1742
1743			count = strtol(q, &e, 0);
1744			if (e == q || *e != '\0')
1745				return (-1);
1746
1747			pmc_config->pm_caps |= PMC_CAP_TAGGING;
1748			pmc_config->pm_md.pm_p4.pm_p4_escrconfig |=
1749			    P4_ESCR_TO_TAG_VALUE(count);
1750		} else if (KWPREFIXMATCH(p, P4_KW_THRESHOLD "=")) {
1751			q = strchr(p, '=');
1752			if (*++q == '\0') /* skip '=' */
1753				return (-1);
1754
1755			count = strtol(q, &e, 0);
1756			if (e == q || *e != '\0')
1757				return (-1);
1758
1759			pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
1760			pmc_config->pm_md.pm_p4.pm_p4_cccrconfig &=
1761			    ~P4_CCCR_THRESHOLD_MASK;
1762			pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |=
1763			    P4_CCCR_TO_THRESHOLD(count);
1764		} else if (KWMATCH(p, P4_KW_USR))
1765			pmc_config->pm_caps |= PMC_CAP_USER;
1766		else
1767			return (-1);
1768	}
1769
1770	/* other post processing */
1771	if (pe == PMC_EV_P4_IOQ_ALLOCATION ||
1772	    pe == PMC_EV_P4_FSB_DATA_ACTIVITY ||
1773	    pe == PMC_EV_P4_BSQ_ALLOCATION)
1774		pmc_config->pm_caps |= PMC_CAP_EDGE;
1775
1776	/* fill in thread activity mask */
1777	pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |=
1778	    P4_CCCR_TO_ACTIVE_THREAD(cccractivemask);
1779
1780	if (evmask)
1781		pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
1782
1783	switch (pe) {
1784	case PMC_EV_P4_FSB_DATA_ACTIVITY:
1785		if ((evmask & 0x06) == 0x06 ||
1786		    (evmask & 0x18) == 0x18)
1787			return (-1); /* can't have own+other bits together */
1788		if (evmask == 0) /* default:drdy-{drv,own}+dbsy{drv,own} */
1789			evmask = 0x1D;
1790		break;
1791	case PMC_EV_P4_MACHINE_CLEAR:
1792		/* only one bit is allowed to be set */
1793		if ((evmask & (evmask - 1)) != 0)
1794			return (-1);
1795		if (evmask == 0) {
1796			evmask = 0x1;	/* 'CLEAR' */
1797			pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
1798		}
1799		break;
1800	default:
1801		if (evmask == 0 && pmask) {
1802			for (pm = pmask; pm->pm_name; pm++)
1803				evmask |= pm->pm_value;
1804			pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
1805		}
1806	}
1807
1808	pmc_config->pm_md.pm_p4.pm_p4_escrconfig =
1809	    P4_ESCR_TO_EVENT_MASK(evmask);
1810
1811	return (0);
1812}
1813
1814#endif
1815
1816#if defined(__i386__)
1817
1818/*
1819 * Pentium style PMCs
1820 */
1821
1822static struct pmc_event_alias p5_aliases[] = {
1823	EV_ALIAS("branches",		"p5-taken-branches"),
1824	EV_ALIAS("cycles",		"tsc"),
1825	EV_ALIAS("dc-misses",		"p5-data-read-miss-or-write-miss"),
1826	EV_ALIAS("ic-misses",		"p5-code-cache-miss"),
1827	EV_ALIAS("instructions",	"p5-instructions-executed"),
1828	EV_ALIAS("interrupts",		"p5-hardware-interrupts"),
1829	EV_ALIAS("unhalted-cycles",
1830	    "p5-number-of-cycles-not-in-halt-state"),
1831	EV_ALIAS(NULL, NULL)
1832};
1833
1834static int
1835p5_allocate_pmc(enum pmc_event pe, char *ctrspec,
1836    struct pmc_op_pmcallocate *pmc_config)
1837{
1838	return (-1 || pe || ctrspec || pmc_config); /* shut up gcc */
1839}
1840
1841/*
1842 * Pentium Pro style PMCs.  These PMCs are found in Pentium II, Pentium III,
1843 * and Pentium M CPUs.
1844 */
1845
1846static struct pmc_event_alias p6_aliases[] = {
1847	EV_ALIAS("branches",		"p6-br-inst-retired"),
1848	EV_ALIAS("branch-mispredicts",	"p6-br-miss-pred-retired"),
1849	EV_ALIAS("cycles",		"tsc"),
1850	EV_ALIAS("dc-misses",		"p6-dcu-lines-in"),
1851	EV_ALIAS("ic-misses",		"p6-ifu-fetch-miss"),
1852	EV_ALIAS("instructions",	"p6-inst-retired"),
1853	EV_ALIAS("interrupts",		"p6-hw-int-rx"),
1854	EV_ALIAS("unhalted-cycles",	"p6-cpu-clk-unhalted"),
1855	EV_ALIAS(NULL, NULL)
1856};
1857
1858#define	P6_KW_CMASK	"cmask"
1859#define	P6_KW_EDGE	"edge"
1860#define	P6_KW_INV	"inv"
1861#define	P6_KW_OS	"os"
1862#define	P6_KW_UMASK	"umask"
1863#define	P6_KW_USR	"usr"
1864
1865static struct pmc_masks p6_mask_mesi[] = {
1866	PMCMASK(m,	0x01),
1867	PMCMASK(e,	0x02),
1868	PMCMASK(s,	0x04),
1869	PMCMASK(i,	0x08),
1870	NULLMASK
1871};
1872
1873static struct pmc_masks p6_mask_mesihw[] = {
1874	PMCMASK(m,	0x01),
1875	PMCMASK(e,	0x02),
1876	PMCMASK(s,	0x04),
1877	PMCMASK(i,	0x08),
1878	PMCMASK(nonhw,	0x00),
1879	PMCMASK(hw,	0x10),
1880	PMCMASK(both,	0x30),
1881	NULLMASK
1882};
1883
1884static struct pmc_masks p6_mask_hw[] = {
1885	PMCMASK(nonhw,	0x00),
1886	PMCMASK(hw,	0x10),
1887	PMCMASK(both,	0x30),
1888	NULLMASK
1889};
1890
1891static struct pmc_masks p6_mask_any[] = {
1892	PMCMASK(self,	0x00),
1893	PMCMASK(any,	0x20),
1894	NULLMASK
1895};
1896
1897static struct pmc_masks p6_mask_ekp[] = {
1898	PMCMASK(nta,	0x00),
1899	PMCMASK(t1,	0x01),
1900	PMCMASK(t2,	0x02),
1901	PMCMASK(wos,	0x03),
1902	NULLMASK
1903};
1904
1905static struct pmc_masks p6_mask_pps[] = {
1906	PMCMASK(packed-and-scalar, 0x00),
1907	PMCMASK(scalar,	0x01),
1908	NULLMASK
1909};
1910
1911static struct pmc_masks p6_mask_mite[] = {
1912	PMCMASK(packed-multiply,	 0x01),
1913	PMCMASK(packed-shift,		0x02),
1914	PMCMASK(pack,			0x04),
1915	PMCMASK(unpack,			0x08),
1916	PMCMASK(packed-logical,		0x10),
1917	PMCMASK(packed-arithmetic,	0x20),
1918	NULLMASK
1919};
1920
1921static struct pmc_masks p6_mask_fmt[] = {
1922	PMCMASK(mmxtofp,	0x00),
1923	PMCMASK(fptommx,	0x01),
1924	NULLMASK
1925};
1926
1927static struct pmc_masks p6_mask_sr[] = {
1928	PMCMASK(es,	0x01),
1929	PMCMASK(ds,	0x02),
1930	PMCMASK(fs,	0x04),
1931	PMCMASK(gs,	0x08),
1932	NULLMASK
1933};
1934
1935static struct pmc_masks p6_mask_eet[] = {
1936	PMCMASK(all,	0x00),
1937	PMCMASK(freq,	0x02),
1938	NULLMASK
1939};
1940
1941static struct pmc_masks p6_mask_efur[] = {
1942	PMCMASK(all,	0x00),
1943	PMCMASK(loadop,	0x01),
1944	PMCMASK(stdsta,	0x02),
1945	NULLMASK
1946};
1947
1948static struct pmc_masks p6_mask_essir[] = {
1949	PMCMASK(sse-packed-single,	0x00),
1950	PMCMASK(sse-packed-single-scalar-single, 0x01),
1951	PMCMASK(sse2-packed-double,	0x02),
1952	PMCMASK(sse2-scalar-double,	0x03),
1953	NULLMASK
1954};
1955
1956static struct pmc_masks p6_mask_esscir[] = {
1957	PMCMASK(sse-packed-single,	0x00),
1958	PMCMASK(sse-scalar-single,	0x01),
1959	PMCMASK(sse2-packed-double,	0x02),
1960	PMCMASK(sse2-scalar-double,	0x03),
1961	NULLMASK
1962};
1963
1964/* P6 event parser */
1965static int
1966p6_allocate_pmc(enum pmc_event pe, char *ctrspec,
1967    struct pmc_op_pmcallocate *pmc_config)
1968{
1969	char *e, *p, *q;
1970	uint32_t evmask;
1971	int count, n;
1972	const struct pmc_masks *pm, *pmask;
1973
1974	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
1975	pmc_config->pm_md.pm_ppro.pm_ppro_config = 0;
1976
1977	evmask = 0;
1978
1979#define	P6MASKSET(M)	pmask = p6_mask_ ## M
1980
1981	switch(pe) {
1982	case PMC_EV_P6_L2_IFETCH:	P6MASKSET(mesi); break;
1983	case PMC_EV_P6_L2_LD:		P6MASKSET(mesi); break;
1984	case PMC_EV_P6_L2_ST:		P6MASKSET(mesi); break;
1985	case PMC_EV_P6_L2_RQSTS:	P6MASKSET(mesi); break;
1986	case PMC_EV_P6_BUS_DRDY_CLOCKS:
1987	case PMC_EV_P6_BUS_LOCK_CLOCKS:
1988	case PMC_EV_P6_BUS_TRAN_BRD:
1989	case PMC_EV_P6_BUS_TRAN_RFO:
1990	case PMC_EV_P6_BUS_TRANS_WB:
1991	case PMC_EV_P6_BUS_TRAN_IFETCH:
1992	case PMC_EV_P6_BUS_TRAN_INVAL:
1993	case PMC_EV_P6_BUS_TRAN_PWR:
1994	case PMC_EV_P6_BUS_TRANS_P:
1995	case PMC_EV_P6_BUS_TRANS_IO:
1996	case PMC_EV_P6_BUS_TRAN_DEF:
1997	case PMC_EV_P6_BUS_TRAN_BURST:
1998	case PMC_EV_P6_BUS_TRAN_ANY:
1999	case PMC_EV_P6_BUS_TRAN_MEM:
2000		P6MASKSET(any);	break;
2001	case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED:
2002	case PMC_EV_P6_EMON_KNI_PREF_MISS:
2003		P6MASKSET(ekp); break;
2004	case PMC_EV_P6_EMON_KNI_INST_RETIRED:
2005	case PMC_EV_P6_EMON_KNI_COMP_INST_RET:
2006		P6MASKSET(pps);	break;
2007	case PMC_EV_P6_MMX_INSTR_TYPE_EXEC:
2008		P6MASKSET(mite); break;
2009	case PMC_EV_P6_FP_MMX_TRANS:
2010		P6MASKSET(fmt);	break;
2011	case PMC_EV_P6_SEG_RENAME_STALLS:
2012	case PMC_EV_P6_SEG_REG_RENAMES:
2013		P6MASKSET(sr);	break;
2014	case PMC_EV_P6_EMON_EST_TRANS:
2015		P6MASKSET(eet);	break;
2016	case PMC_EV_P6_EMON_FUSED_UOPS_RET:
2017		P6MASKSET(efur); break;
2018	case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED:
2019		P6MASKSET(essir); break;
2020	case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED:
2021		P6MASKSET(esscir); break;
2022	default:
2023		pmask = NULL;
2024		break;
2025	}
2026
2027	/* Pentium M PMCs have a few events with different semantics */
2028	if (cpu_info.pm_cputype == PMC_CPU_INTEL_PM) {
2029		if (pe == PMC_EV_P6_L2_LD ||
2030		    pe == PMC_EV_P6_L2_LINES_IN ||
2031		    pe == PMC_EV_P6_L2_LINES_OUT)
2032			P6MASKSET(mesihw);
2033		else if (pe == PMC_EV_P6_L2_M_LINES_OUTM)
2034			P6MASKSET(hw);
2035	}
2036
2037	/* Parse additional modifiers if present */
2038	while ((p = strsep(&ctrspec, ",")) != NULL) {
2039		if (KWPREFIXMATCH(p, P6_KW_CMASK "=")) {
2040			q = strchr(p, '=');
2041			if (*++q == '\0') /* skip '=' */
2042				return (-1);
2043			count = strtol(q, &e, 0);
2044			if (e == q || *e != '\0')
2045				return (-1);
2046			pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
2047			pmc_config->pm_md.pm_ppro.pm_ppro_config |=
2048			    P6_EVSEL_TO_CMASK(count);
2049		} else if (KWMATCH(p, P6_KW_EDGE)) {
2050			pmc_config->pm_caps |= PMC_CAP_EDGE;
2051		} else if (KWMATCH(p, P6_KW_INV)) {
2052			pmc_config->pm_caps |= PMC_CAP_INVERT;
2053		} else if (KWMATCH(p, P6_KW_OS)) {
2054			pmc_config->pm_caps |= PMC_CAP_SYSTEM;
2055		} else if (KWPREFIXMATCH(p, P6_KW_UMASK "=")) {
2056			evmask = 0;
2057			if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0)
2058				return (-1);
2059			if ((pe == PMC_EV_P6_BUS_DRDY_CLOCKS ||
2060			     pe == PMC_EV_P6_BUS_LOCK_CLOCKS ||
2061			     pe == PMC_EV_P6_BUS_TRAN_BRD ||
2062			     pe == PMC_EV_P6_BUS_TRAN_RFO ||
2063			     pe == PMC_EV_P6_BUS_TRAN_IFETCH ||
2064			     pe == PMC_EV_P6_BUS_TRAN_INVAL ||
2065			     pe == PMC_EV_P6_BUS_TRAN_PWR ||
2066			     pe == PMC_EV_P6_BUS_TRAN_DEF ||
2067			     pe == PMC_EV_P6_BUS_TRAN_BURST ||
2068			     pe == PMC_EV_P6_BUS_TRAN_ANY ||
2069			     pe == PMC_EV_P6_BUS_TRAN_MEM ||
2070			     pe == PMC_EV_P6_BUS_TRANS_IO ||
2071			     pe == PMC_EV_P6_BUS_TRANS_P ||
2072			     pe == PMC_EV_P6_BUS_TRANS_WB ||
2073			     pe == PMC_EV_P6_EMON_EST_TRANS ||
2074			     pe == PMC_EV_P6_EMON_FUSED_UOPS_RET ||
2075			     pe == PMC_EV_P6_EMON_KNI_COMP_INST_RET ||
2076			     pe == PMC_EV_P6_EMON_KNI_INST_RETIRED ||
2077			     pe == PMC_EV_P6_EMON_KNI_PREF_DISPATCHED ||
2078			     pe == PMC_EV_P6_EMON_KNI_PREF_MISS ||
2079			     pe == PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED ||
2080			     pe == PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED ||
2081			     pe == PMC_EV_P6_FP_MMX_TRANS)
2082			    && (n > 1))	/* Only one mask keyword is allowed. */
2083				return (-1);
2084			pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
2085		} else if (KWMATCH(p, P6_KW_USR)) {
2086			pmc_config->pm_caps |= PMC_CAP_USER;
2087		} else
2088			return (-1);
2089	}
2090
2091	/* post processing */
2092	switch (pe) {
2093
2094		/*
2095		 * The following events default to an evmask of 0
2096		 */
2097
2098		/* default => 'self' */
2099	case PMC_EV_P6_BUS_DRDY_CLOCKS:
2100	case PMC_EV_P6_BUS_LOCK_CLOCKS:
2101	case PMC_EV_P6_BUS_TRAN_BRD:
2102	case PMC_EV_P6_BUS_TRAN_RFO:
2103	case PMC_EV_P6_BUS_TRANS_WB:
2104	case PMC_EV_P6_BUS_TRAN_IFETCH:
2105	case PMC_EV_P6_BUS_TRAN_INVAL:
2106	case PMC_EV_P6_BUS_TRAN_PWR:
2107	case PMC_EV_P6_BUS_TRANS_P:
2108	case PMC_EV_P6_BUS_TRANS_IO:
2109	case PMC_EV_P6_BUS_TRAN_DEF:
2110	case PMC_EV_P6_BUS_TRAN_BURST:
2111	case PMC_EV_P6_BUS_TRAN_ANY:
2112	case PMC_EV_P6_BUS_TRAN_MEM:
2113
2114		/* default => 'nta' */
2115	case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED:
2116	case PMC_EV_P6_EMON_KNI_PREF_MISS:
2117
2118		/* default => 'packed and scalar' */
2119	case PMC_EV_P6_EMON_KNI_INST_RETIRED:
2120	case PMC_EV_P6_EMON_KNI_COMP_INST_RET:
2121
2122		/* default => 'mmx to fp transitions' */
2123	case PMC_EV_P6_FP_MMX_TRANS:
2124
2125		/* default => 'SSE Packed Single' */
2126	case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED:
2127	case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED:
2128
2129		/* default => 'all fused micro-ops' */
2130	case PMC_EV_P6_EMON_FUSED_UOPS_RET:
2131
2132		/* default => 'all transitions' */
2133	case PMC_EV_P6_EMON_EST_TRANS:
2134		break;
2135
2136	case PMC_EV_P6_MMX_UOPS_EXEC:
2137		evmask = 0x0F;		/* only value allowed */
2138		break;
2139
2140	default:
2141		/*
2142		 * For all other events, set the default event mask
2143		 * to a logical OR of all the allowed event mask bits.
2144		 */
2145		if (evmask == 0 && pmask) {
2146			for (pm = pmask; pm->pm_name; pm++)
2147				evmask |= pm->pm_value;
2148			pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
2149		}
2150
2151		break;
2152	}
2153
2154	if (pmc_config->pm_caps & PMC_CAP_QUALIFIER)
2155		pmc_config->pm_md.pm_ppro.pm_ppro_config |=
2156		    P6_EVSEL_TO_UMASK(evmask);
2157
2158	return (0);
2159}
2160
2161#endif
2162
2163#if	defined(__i386__) || defined(__amd64__)
2164static int
2165tsc_allocate_pmc(enum pmc_event pe, char *ctrspec,
2166    struct pmc_op_pmcallocate *pmc_config)
2167{
2168	if (pe != PMC_EV_TSC_TSC)
2169		return (-1);
2170
2171	/* TSC events must be unqualified. */
2172	if (ctrspec && *ctrspec != '\0')
2173		return (-1);
2174
2175	pmc_config->pm_md.pm_amd.pm_amd_config = 0;
2176	pmc_config->pm_caps |= PMC_CAP_READ;
2177
2178	return (0);
2179}
2180#endif
2181
2182#if	defined(__XSCALE__)
2183
2184static struct pmc_event_alias xscale_aliases[] = {
2185	EV_ALIAS("branches",		"BRANCH_RETIRED"),
2186	EV_ALIAS("branch-mispredicts",	"BRANCH_MISPRED"),
2187	EV_ALIAS("dc-misses",		"DC_MISS"),
2188	EV_ALIAS("ic-misses",		"IC_MISS"),
2189	EV_ALIAS("instructions",	"INSTR_RETIRED"),
2190	EV_ALIAS(NULL, NULL)
2191};
2192static int
2193xscale_allocate_pmc(enum pmc_event pe, char *ctrspec __unused,
2194    struct pmc_op_pmcallocate *pmc_config __unused)
2195{
2196	switch (pe) {
2197	default:
2198		break;
2199	}
2200
2201	return (0);
2202}
2203#endif
2204
2205#if defined(__mips__)
2206
2207static struct pmc_event_alias mips24k_aliases[] = {
2208	EV_ALIAS("instructions",	"INSTR_EXECUTED"),
2209	EV_ALIAS("branches",		"BRANCH_COMPLETED"),
2210	EV_ALIAS("branch-mispredicts",	"BRANCH_MISPRED"),
2211	EV_ALIAS(NULL, NULL)
2212};
2213
2214static struct pmc_event_alias octeon_aliases[] = {
2215	EV_ALIAS("instructions",	"RET"),
2216	EV_ALIAS("branches",		"BR"),
2217	EV_ALIAS("branch-mispredicts",	"BRMIS"),
2218	EV_ALIAS(NULL, NULL)
2219};
2220
2221#define	MIPS_KW_OS		"os"
2222#define	MIPS_KW_USR		"usr"
2223#define	MIPS_KW_ANYTHREAD	"anythread"
2224
2225static int
2226mips_allocate_pmc(enum pmc_event pe, char *ctrspec __unused,
2227		  struct pmc_op_pmcallocate *pmc_config __unused)
2228{
2229	char *p;
2230
2231	(void) pe;
2232
2233	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
2234
2235	while ((p = strsep(&ctrspec, ",")) != NULL) {
2236		if (KWMATCH(p, MIPS_KW_OS))
2237			pmc_config->pm_caps |= PMC_CAP_SYSTEM;
2238		else if (KWMATCH(p, MIPS_KW_USR))
2239			pmc_config->pm_caps |= PMC_CAP_USER;
2240		else if (KWMATCH(p, MIPS_KW_ANYTHREAD))
2241			pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM);
2242		else
2243			return (-1);
2244	}
2245
2246	return (0);
2247}
2248
2249#endif /* __mips__ */
2250
2251#if defined(__powerpc__)
2252
2253static struct pmc_event_alias ppc7450_aliases[] = {
2254	EV_ALIAS("instructions",	"INSTR_COMPLETED"),
2255	EV_ALIAS("branches",		"BRANCHES_COMPLETED"),
2256	EV_ALIAS("branch-mispredicts",	"MISPREDICTED_BRANCHES"),
2257	EV_ALIAS(NULL, NULL)
2258};
2259
2260#define	PPC7450_KW_OS		"os"
2261#define	PPC7450_KW_USR		"usr"
2262#define	PPC7450_KW_ANYTHREAD	"anythread"
2263
2264static int
2265ppc7450_allocate_pmc(enum pmc_event pe, char *ctrspec __unused,
2266		  struct pmc_op_pmcallocate *pmc_config __unused)
2267{
2268	char *p;
2269
2270	(void) pe;
2271
2272	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
2273
2274	while ((p = strsep(&ctrspec, ",")) != NULL) {
2275		if (KWMATCH(p, PPC7450_KW_OS))
2276			pmc_config->pm_caps |= PMC_CAP_SYSTEM;
2277		else if (KWMATCH(p, PPC7450_KW_USR))
2278			pmc_config->pm_caps |= PMC_CAP_USER;
2279		else if (KWMATCH(p, PPC7450_KW_ANYTHREAD))
2280			pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM);
2281		else
2282			return (-1);
2283	}
2284
2285	return (0);
2286}
2287#endif /* __powerpc__ */
2288
2289
2290/*
2291 * Match an event name `name' with its canonical form.
2292 *
2293 * Matches are case insensitive and spaces, periods, underscores and
2294 * hyphen characters are considered to match each other.
2295 *
2296 * Returns 1 for a match, 0 otherwise.
2297 */
2298
2299static int
2300pmc_match_event_name(const char *name, const char *canonicalname)
2301{
2302	int cc, nc;
2303	const unsigned char *c, *n;
2304
2305	c = (const unsigned char *) canonicalname;
2306	n = (const unsigned char *) name;
2307
2308	for (; (nc = *n) && (cc = *c); n++, c++) {
2309
2310		if ((nc == ' ' || nc == '_' || nc == '-' || nc == '.') &&
2311		    (cc == ' ' || cc == '_' || cc == '-' || cc == '.'))
2312			continue;
2313
2314		if (toupper(nc) == toupper(cc))
2315			continue;
2316
2317
2318		return (0);
2319	}
2320
2321	if (*n == '\0' && *c == '\0')
2322		return (1);
2323
2324	return (0);
2325}
2326
2327/*
2328 * Match an event name against all the event named supported by a
2329 * PMC class.
2330 *
2331 * Returns an event descriptor pointer on match or NULL otherwise.
2332 */
2333static const struct pmc_event_descr *
2334pmc_match_event_class(const char *name,
2335    const struct pmc_class_descr *pcd)
2336{
2337	size_t n;
2338	const struct pmc_event_descr *ev;
2339
2340	ev = pcd->pm_evc_event_table;
2341	for (n = 0; n < pcd->pm_evc_event_table_size; n++, ev++)
2342		if (pmc_match_event_name(name, ev->pm_ev_name))
2343			return (ev);
2344
2345	return (NULL);
2346}
2347
2348static int
2349pmc_mdep_is_compatible_class(enum pmc_class pc)
2350{
2351	size_t n;
2352
2353	for (n = 0; n < pmc_mdep_class_list_size; n++)
2354		if (pmc_mdep_class_list[n] == pc)
2355			return (1);
2356	return (0);
2357}
2358
2359/*
2360 * API entry points
2361 */
2362
2363int
2364pmc_allocate(const char *ctrspec, enum pmc_mode mode,
2365    uint32_t flags, int cpu, pmc_id_t *pmcid)
2366{
2367	size_t n;
2368	int retval;
2369	char *r, *spec_copy;
2370	const char *ctrname;
2371	const struct pmc_event_descr *ev;
2372	const struct pmc_event_alias *alias;
2373	struct pmc_op_pmcallocate pmc_config;
2374	const struct pmc_class_descr *pcd;
2375
2376	spec_copy = NULL;
2377	retval    = -1;
2378
2379	if (mode != PMC_MODE_SS && mode != PMC_MODE_TS &&
2380	    mode != PMC_MODE_SC && mode != PMC_MODE_TC) {
2381		errno = EINVAL;
2382		goto out;
2383	}
2384
2385	/* replace an event alias with the canonical event specifier */
2386	if (pmc_mdep_event_aliases)
2387		for (alias = pmc_mdep_event_aliases; alias->pm_alias; alias++)
2388			if (!strcasecmp(ctrspec, alias->pm_alias)) {
2389				spec_copy = strdup(alias->pm_spec);
2390				break;
2391			}
2392
2393	if (spec_copy == NULL)
2394		spec_copy = strdup(ctrspec);
2395
2396	r = spec_copy;
2397	ctrname = strsep(&r, ",");
2398
2399	/*
2400	 * If a explicit class prefix was given by the user, restrict the
2401	 * search for the event to the specified PMC class.
2402	 */
2403	ev = NULL;
2404	for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) {
2405		pcd = pmc_class_table[n];
2406		if (pmc_mdep_is_compatible_class(pcd->pm_evc_class) &&
2407		    strncasecmp(ctrname, pcd->pm_evc_name,
2408				pcd->pm_evc_name_size) == 0) {
2409			if ((ev = pmc_match_event_class(ctrname +
2410			    pcd->pm_evc_name_size, pcd)) == NULL) {
2411				errno = EINVAL;
2412				goto out;
2413			}
2414			break;
2415		}
2416	}
2417
2418	/*
2419	 * Otherwise, search for this event in all compatible PMC
2420	 * classes.
2421	 */
2422	for (n = 0; ev == NULL && n < PMC_CLASS_TABLE_SIZE; n++) {
2423		pcd = pmc_class_table[n];
2424		if (pmc_mdep_is_compatible_class(pcd->pm_evc_class))
2425			ev = pmc_match_event_class(ctrname, pcd);
2426	}
2427
2428	if (ev == NULL) {
2429		errno = EINVAL;
2430		goto out;
2431	}
2432
2433	bzero(&pmc_config, sizeof(pmc_config));
2434	pmc_config.pm_ev    = ev->pm_ev_code;
2435	pmc_config.pm_class = pcd->pm_evc_class;
2436	pmc_config.pm_cpu   = cpu;
2437	pmc_config.pm_mode  = mode;
2438	pmc_config.pm_flags = flags;
2439
2440	if (PMC_IS_SAMPLING_MODE(mode))
2441		pmc_config.pm_caps |= PMC_CAP_INTERRUPT;
2442
2443 	if (pcd->pm_evc_allocate_pmc(ev->pm_ev_code, r, &pmc_config) < 0) {
2444		errno = EINVAL;
2445		goto out;
2446	}
2447
2448	if (PMC_CALL(PMCALLOCATE, &pmc_config) < 0)
2449		goto out;
2450
2451	*pmcid = pmc_config.pm_pmcid;
2452
2453	retval = 0;
2454
2455 out:
2456	if (spec_copy)
2457		free(spec_copy);
2458
2459	return (retval);
2460}
2461
2462int
2463pmc_attach(pmc_id_t pmc, pid_t pid)
2464{
2465	struct pmc_op_pmcattach pmc_attach_args;
2466
2467	pmc_attach_args.pm_pmc = pmc;
2468	pmc_attach_args.pm_pid = pid;
2469
2470	return (PMC_CALL(PMCATTACH, &pmc_attach_args));
2471}
2472
2473int
2474pmc_capabilities(pmc_id_t pmcid, uint32_t *caps)
2475{
2476	unsigned int i;
2477	enum pmc_class cl;
2478
2479	cl = PMC_ID_TO_CLASS(pmcid);
2480	for (i = 0; i < cpu_info.pm_nclass; i++)
2481		if (cpu_info.pm_classes[i].pm_class == cl) {
2482			*caps = cpu_info.pm_classes[i].pm_caps;
2483			return (0);
2484		}
2485	errno = EINVAL;
2486	return (-1);
2487}
2488
2489int
2490pmc_configure_logfile(int fd)
2491{
2492	struct pmc_op_configurelog cla;
2493
2494	cla.pm_logfd = fd;
2495	if (PMC_CALL(CONFIGURELOG, &cla) < 0)
2496		return (-1);
2497	return (0);
2498}
2499
2500int
2501pmc_cpuinfo(const struct pmc_cpuinfo **pci)
2502{
2503	if (pmc_syscall == -1) {
2504		errno = ENXIO;
2505		return (-1);
2506	}
2507
2508	*pci = &cpu_info;
2509	return (0);
2510}
2511
2512int
2513pmc_detach(pmc_id_t pmc, pid_t pid)
2514{
2515	struct pmc_op_pmcattach pmc_detach_args;
2516
2517	pmc_detach_args.pm_pmc = pmc;
2518	pmc_detach_args.pm_pid = pid;
2519	return (PMC_CALL(PMCDETACH, &pmc_detach_args));
2520}
2521
2522int
2523pmc_disable(int cpu, int pmc)
2524{
2525	struct pmc_op_pmcadmin ssa;
2526
2527	ssa.pm_cpu = cpu;
2528	ssa.pm_pmc = pmc;
2529	ssa.pm_state = PMC_STATE_DISABLED;
2530	return (PMC_CALL(PMCADMIN, &ssa));
2531}
2532
2533int
2534pmc_enable(int cpu, int pmc)
2535{
2536	struct pmc_op_pmcadmin ssa;
2537
2538	ssa.pm_cpu = cpu;
2539	ssa.pm_pmc = pmc;
2540	ssa.pm_state = PMC_STATE_FREE;
2541	return (PMC_CALL(PMCADMIN, &ssa));
2542}
2543
2544/*
2545 * Return a list of events known to a given PMC class.  'cl' is the
2546 * PMC class identifier, 'eventnames' is the returned list of 'const
2547 * char *' pointers pointing to the names of the events. 'nevents' is
2548 * the number of event name pointers returned.
2549 *
2550 * The space for 'eventnames' is allocated using malloc(3).  The caller
2551 * is responsible for freeing this space when done.
2552 */
2553int
2554pmc_event_names_of_class(enum pmc_class cl, const char ***eventnames,
2555    int *nevents)
2556{
2557	int count;
2558	const char **names;
2559	const struct pmc_event_descr *ev;
2560
2561	switch (cl)
2562	{
2563	case PMC_CLASS_IAF:
2564		ev = iaf_event_table;
2565		count = PMC_EVENT_TABLE_SIZE(iaf);
2566		break;
2567	case PMC_CLASS_IAP:
2568		/*
2569		 * Return the most appropriate set of event name
2570		 * spellings for the current CPU.
2571		 */
2572		switch (cpu_info.pm_cputype) {
2573		default:
2574		case PMC_CPU_INTEL_ATOM:
2575			ev = atom_event_table;
2576			count = PMC_EVENT_TABLE_SIZE(atom);
2577			break;
2578		case PMC_CPU_INTEL_CORE:
2579			ev = core_event_table;
2580			count = PMC_EVENT_TABLE_SIZE(core);
2581			break;
2582		case PMC_CPU_INTEL_CORE2:
2583		case PMC_CPU_INTEL_CORE2EXTREME:
2584			ev = core2_event_table;
2585			count = PMC_EVENT_TABLE_SIZE(core2);
2586			break;
2587		case PMC_CPU_INTEL_COREI7:
2588			ev = corei7_event_table;
2589			count = PMC_EVENT_TABLE_SIZE(corei7);
2590			break;
2591		case PMC_CPU_INTEL_SANDYBRIDGE:
2592			ev = sandybridge_event_table;
2593			count = PMC_EVENT_TABLE_SIZE(sandybridge);
2594			break;
2595		case PMC_CPU_INTEL_WESTMERE:
2596			ev = westmere_event_table;
2597			count = PMC_EVENT_TABLE_SIZE(westmere);
2598			break;
2599		}
2600		break;
2601	case PMC_CLASS_UCF:
2602		ev = ucf_event_table;
2603		count = PMC_EVENT_TABLE_SIZE(ucf);
2604		break;
2605	case PMC_CLASS_UCP:
2606		/*
2607		 * Return the most appropriate set of event name
2608		 * spellings for the current CPU.
2609		 */
2610		switch (cpu_info.pm_cputype) {
2611		default:
2612		case PMC_CPU_INTEL_COREI7:
2613			ev = corei7uc_event_table;
2614			count = PMC_EVENT_TABLE_SIZE(corei7uc);
2615			break;
2616		case PMC_CPU_INTEL_SANDYBRIDGE:
2617			ev = sandybridgeuc_event_table;
2618			count = PMC_EVENT_TABLE_SIZE(sandybridgeuc);
2619			break;
2620		case PMC_CPU_INTEL_WESTMERE:
2621			ev = westmereuc_event_table;
2622			count = PMC_EVENT_TABLE_SIZE(westmereuc);
2623			break;
2624		}
2625		break;
2626	case PMC_CLASS_TSC:
2627		ev = tsc_event_table;
2628		count = PMC_EVENT_TABLE_SIZE(tsc);
2629		break;
2630	case PMC_CLASS_K7:
2631		ev = k7_event_table;
2632		count = PMC_EVENT_TABLE_SIZE(k7);
2633		break;
2634	case PMC_CLASS_K8:
2635		ev = k8_event_table;
2636		count = PMC_EVENT_TABLE_SIZE(k8);
2637		break;
2638	case PMC_CLASS_P4:
2639		ev = p4_event_table;
2640		count = PMC_EVENT_TABLE_SIZE(p4);
2641		break;
2642	case PMC_CLASS_P5:
2643		ev = p5_event_table;
2644		count = PMC_EVENT_TABLE_SIZE(p5);
2645		break;
2646	case PMC_CLASS_P6:
2647		ev = p6_event_table;
2648		count = PMC_EVENT_TABLE_SIZE(p6);
2649		break;
2650	case PMC_CLASS_XSCALE:
2651		ev = xscale_event_table;
2652		count = PMC_EVENT_TABLE_SIZE(xscale);
2653		break;
2654	case PMC_CLASS_MIPS24K:
2655		ev = mips24k_event_table;
2656		count = PMC_EVENT_TABLE_SIZE(mips24k);
2657		break;
2658	case PMC_CLASS_OCTEON:
2659		ev = octeon_event_table;
2660		count = PMC_EVENT_TABLE_SIZE(octeon);
2661		break;
2662	case PMC_CLASS_PPC7450:
2663		ev = ppc7450_event_table;
2664		count = PMC_EVENT_TABLE_SIZE(ppc7450);
2665		break;
2666	default:
2667		errno = EINVAL;
2668		return (-1);
2669	}
2670
2671	if ((names = malloc(count * sizeof(const char *))) == NULL)
2672		return (-1);
2673
2674	*eventnames = names;
2675	*nevents = count;
2676
2677	for (;count--; ev++, names++)
2678		*names = ev->pm_ev_name;
2679	return (0);
2680}
2681
2682int
2683pmc_flush_logfile(void)
2684{
2685	return (PMC_CALL(FLUSHLOG,0));
2686}
2687
2688int
2689pmc_close_logfile(void)
2690{
2691	return (PMC_CALL(CLOSELOG,0));
2692}
2693
2694int
2695pmc_get_driver_stats(struct pmc_driverstats *ds)
2696{
2697	struct pmc_op_getdriverstats gms;
2698
2699	if (PMC_CALL(GETDRIVERSTATS, &gms) < 0)
2700		return (-1);
2701
2702	/* copy out fields in the current userland<->library interface */
2703	ds->pm_intr_ignored    = gms.pm_intr_ignored;
2704	ds->pm_intr_processed  = gms.pm_intr_processed;
2705	ds->pm_intr_bufferfull = gms.pm_intr_bufferfull;
2706	ds->pm_syscalls        = gms.pm_syscalls;
2707	ds->pm_syscall_errors  = gms.pm_syscall_errors;
2708	ds->pm_buffer_requests = gms.pm_buffer_requests;
2709	ds->pm_buffer_requests_failed = gms.pm_buffer_requests_failed;
2710	ds->pm_log_sweeps      = gms.pm_log_sweeps;
2711	return (0);
2712}
2713
2714int
2715pmc_get_msr(pmc_id_t pmc, uint32_t *msr)
2716{
2717	struct pmc_op_getmsr gm;
2718
2719	gm.pm_pmcid = pmc;
2720	if (PMC_CALL(PMCGETMSR, &gm) < 0)
2721		return (-1);
2722	*msr = gm.pm_msr;
2723	return (0);
2724}
2725
2726int
2727pmc_init(void)
2728{
2729	int error, pmc_mod_id;
2730	unsigned int n;
2731	uint32_t abi_version;
2732	struct module_stat pmc_modstat;
2733	struct pmc_op_getcpuinfo op_cpu_info;
2734#if defined(__amd64__) || defined(__i386__)
2735	int cpu_has_iaf_counters;
2736	unsigned int t;
2737#endif
2738
2739	if (pmc_syscall != -1) /* already inited */
2740		return (0);
2741
2742	/* retrieve the system call number from the KLD */
2743	if ((pmc_mod_id = modfind(PMC_MODULE_NAME)) < 0)
2744		return (-1);
2745
2746	pmc_modstat.version = sizeof(struct module_stat);
2747	if ((error = modstat(pmc_mod_id, &pmc_modstat)) < 0)
2748		return (-1);
2749
2750	pmc_syscall = pmc_modstat.data.intval;
2751
2752	/* check the kernel module's ABI against our compiled-in version */
2753	abi_version = PMC_VERSION;
2754	if (PMC_CALL(GETMODULEVERSION, &abi_version) < 0)
2755		return (pmc_syscall = -1);
2756
2757	/* ignore patch & minor numbers for the comparision */
2758	if ((abi_version & 0xFF000000) != (PMC_VERSION & 0xFF000000)) {
2759		errno  = EPROGMISMATCH;
2760		return (pmc_syscall = -1);
2761	}
2762
2763	if (PMC_CALL(GETCPUINFO, &op_cpu_info) < 0)
2764		return (pmc_syscall = -1);
2765
2766	cpu_info.pm_cputype = op_cpu_info.pm_cputype;
2767	cpu_info.pm_ncpu    = op_cpu_info.pm_ncpu;
2768	cpu_info.pm_npmc    = op_cpu_info.pm_npmc;
2769	cpu_info.pm_nclass  = op_cpu_info.pm_nclass;
2770	for (n = 0; n < cpu_info.pm_nclass; n++)
2771		cpu_info.pm_classes[n] = op_cpu_info.pm_classes[n];
2772
2773	pmc_class_table = malloc(PMC_CLASS_TABLE_SIZE *
2774	    sizeof(struct pmc_class_descr *));
2775
2776	if (pmc_class_table == NULL)
2777		return (-1);
2778
2779	for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++)
2780		pmc_class_table[n] = NULL;
2781
2782	/*
2783	 * Fill in the class table.
2784	 */
2785	n = 0;
2786#if defined(__amd64__) || defined(__i386__)
2787	pmc_class_table[n++] = &tsc_class_table_descr;
2788
2789	/*
2790 	 * Check if this CPU has fixed function counters.
2791	 */
2792	cpu_has_iaf_counters = 0;
2793	for (t = 0; t < cpu_info.pm_nclass; t++)
2794		if (cpu_info.pm_classes[t].pm_class == PMC_CLASS_IAF &&
2795		    cpu_info.pm_classes[t].pm_num > 0)
2796			cpu_has_iaf_counters = 1;
2797#endif
2798
2799#define	PMC_MDEP_INIT(C) do {					\
2800		pmc_mdep_event_aliases    = C##_aliases;	\
2801		pmc_mdep_class_list  = C##_pmc_classes;		\
2802		pmc_mdep_class_list_size =			\
2803		    PMC_TABLE_SIZE(C##_pmc_classes);		\
2804	} while (0)
2805
2806#define	PMC_MDEP_INIT_INTEL_V2(C) do {					\
2807		PMC_MDEP_INIT(C);					\
2808		pmc_class_table[n++] = &iaf_class_table_descr;		\
2809		if (!cpu_has_iaf_counters) 				\
2810			pmc_mdep_event_aliases =			\
2811				C##_aliases_without_iaf;		\
2812		pmc_class_table[n] = &C##_class_table_descr;		\
2813	} while (0)
2814
2815	/* Configure the event name parser. */
2816	switch (cpu_info.pm_cputype) {
2817#if defined(__i386__)
2818	case PMC_CPU_AMD_K7:
2819		PMC_MDEP_INIT(k7);
2820		pmc_class_table[n] = &k7_class_table_descr;
2821		break;
2822	case PMC_CPU_INTEL_P5:
2823		PMC_MDEP_INIT(p5);
2824		pmc_class_table[n]  = &p5_class_table_descr;
2825		break;
2826	case PMC_CPU_INTEL_P6:		/* P6 ... Pentium M CPUs have */
2827	case PMC_CPU_INTEL_PII:		/* similar PMCs. */
2828	case PMC_CPU_INTEL_PIII:
2829	case PMC_CPU_INTEL_PM:
2830		PMC_MDEP_INIT(p6);
2831		pmc_class_table[n] = &p6_class_table_descr;
2832		break;
2833#endif
2834#if defined(__amd64__) || defined(__i386__)
2835	case PMC_CPU_AMD_K8:
2836		PMC_MDEP_INIT(k8);
2837		pmc_class_table[n] = &k8_class_table_descr;
2838		break;
2839	case PMC_CPU_INTEL_ATOM:
2840		PMC_MDEP_INIT_INTEL_V2(atom);
2841		break;
2842	case PMC_CPU_INTEL_CORE:
2843		PMC_MDEP_INIT(core);
2844		pmc_class_table[n] = &core_class_table_descr;
2845		break;
2846	case PMC_CPU_INTEL_CORE2:
2847	case PMC_CPU_INTEL_CORE2EXTREME:
2848		PMC_MDEP_INIT_INTEL_V2(core2);
2849		break;
2850	case PMC_CPU_INTEL_COREI7:
2851		pmc_class_table[n++] = &ucf_class_table_descr;
2852		pmc_class_table[n++] = &corei7uc_class_table_descr;
2853		PMC_MDEP_INIT_INTEL_V2(corei7);
2854		break;
2855	case PMC_CPU_INTEL_SANDYBRIDGE:
2856		pmc_class_table[n++] = &ucf_class_table_descr;
2857		pmc_class_table[n++] = &sandybridgeuc_class_table_descr;
2858		PMC_MDEP_INIT_INTEL_V2(sandybridge);
2859		break;
2860	case PMC_CPU_INTEL_WESTMERE:
2861		pmc_class_table[n++] = &ucf_class_table_descr;
2862		pmc_class_table[n++] = &westmereuc_class_table_descr;
2863		PMC_MDEP_INIT_INTEL_V2(westmere);
2864		break;
2865	case PMC_CPU_INTEL_PIV:
2866		PMC_MDEP_INIT(p4);
2867		pmc_class_table[n] = &p4_class_table_descr;
2868		break;
2869#endif
2870#if defined(__XSCALE__)
2871	case PMC_CPU_INTEL_XSCALE:
2872		PMC_MDEP_INIT(xscale);
2873		pmc_class_table[n] = &xscale_class_table_descr;
2874		break;
2875#endif
2876#if defined(__mips__)
2877	case PMC_CPU_MIPS_24K:
2878		PMC_MDEP_INIT(mips24k);
2879		pmc_class_table[n] = &mips24k_class_table_descr;
2880		break;
2881	case PMC_CPU_MIPS_OCTEON:
2882		PMC_MDEP_INIT(octeon);
2883		pmc_class_table[n] = &octeon_class_table_descr;
2884		break;
2885#endif /* __mips__ */
2886#if defined(__powerpc__)
2887	case PMC_CPU_PPC_7450:
2888		PMC_MDEP_INIT(ppc7450);
2889		pmc_class_table[n] = &ppc7450_class_table_descr;
2890		break;
2891#endif
2892	default:
2893		/*
2894		 * Some kind of CPU this version of the library knows nothing
2895		 * about.  This shouldn't happen since the abi version check
2896		 * should have caught this.
2897		 */
2898		errno = ENXIO;
2899		return (pmc_syscall = -1);
2900	}
2901
2902	return (0);
2903}
2904
2905const char *
2906pmc_name_of_capability(enum pmc_caps cap)
2907{
2908	int i;
2909
2910	/*
2911	 * 'cap' should have a single bit set and should be in
2912	 * range.
2913	 */
2914	if ((cap & (cap - 1)) || cap < PMC_CAP_FIRST ||
2915	    cap > PMC_CAP_LAST) {
2916		errno = EINVAL;
2917		return (NULL);
2918	}
2919
2920	i = ffs(cap);
2921	return (pmc_capability_names[i - 1]);
2922}
2923
2924const char *
2925pmc_name_of_class(enum pmc_class pc)
2926{
2927	if ((int) pc >= PMC_CLASS_FIRST &&
2928	    pc <= PMC_CLASS_LAST)
2929		return (pmc_class_names[pc]);
2930
2931	errno = EINVAL;
2932	return (NULL);
2933}
2934
2935const char *
2936pmc_name_of_cputype(enum pmc_cputype cp)
2937{
2938	size_t n;
2939
2940	for (n = 0; n < PMC_TABLE_SIZE(pmc_cputype_names); n++)
2941		if (cp == pmc_cputype_names[n].pm_cputype)
2942			return (pmc_cputype_names[n].pm_name);
2943
2944	errno = EINVAL;
2945	return (NULL);
2946}
2947
2948const char *
2949pmc_name_of_disposition(enum pmc_disp pd)
2950{
2951	if ((int) pd >= PMC_DISP_FIRST &&
2952	    pd <= PMC_DISP_LAST)
2953		return (pmc_disposition_names[pd]);
2954
2955	errno = EINVAL;
2956	return (NULL);
2957}
2958
2959const char *
2960_pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu)
2961{
2962	const struct pmc_event_descr *ev, *evfence;
2963
2964	ev = evfence = NULL;
2965	if (pe >= PMC_EV_IAF_FIRST && pe <= PMC_EV_IAF_LAST) {
2966		ev = iaf_event_table;
2967		evfence = iaf_event_table + PMC_EVENT_TABLE_SIZE(iaf);
2968	} else if (pe >= PMC_EV_IAP_FIRST && pe <= PMC_EV_IAP_LAST) {
2969		switch (cpu) {
2970		case PMC_CPU_INTEL_ATOM:
2971			ev = atom_event_table;
2972			evfence = atom_event_table + PMC_EVENT_TABLE_SIZE(atom);
2973			break;
2974		case PMC_CPU_INTEL_CORE:
2975			ev = core_event_table;
2976			evfence = core_event_table + PMC_EVENT_TABLE_SIZE(core);
2977			break;
2978		case PMC_CPU_INTEL_CORE2:
2979		case PMC_CPU_INTEL_CORE2EXTREME:
2980			ev = core2_event_table;
2981			evfence = core2_event_table + PMC_EVENT_TABLE_SIZE(core2);
2982			break;
2983		case PMC_CPU_INTEL_COREI7:
2984			ev = corei7_event_table;
2985			evfence = corei7_event_table + PMC_EVENT_TABLE_SIZE(corei7);
2986			break;
2987		case PMC_CPU_INTEL_SANDYBRIDGE:
2988			ev = sandybridge_event_table;
2989			evfence = sandybridge_event_table + PMC_EVENT_TABLE_SIZE(sandybridge);
2990			break;
2991		case PMC_CPU_INTEL_WESTMERE:
2992			ev = westmere_event_table;
2993			evfence = westmere_event_table + PMC_EVENT_TABLE_SIZE(westmere);
2994			break;
2995		default:	/* Unknown CPU type. */
2996			break;
2997		}
2998	} else if (pe >= PMC_EV_UCF_FIRST && pe <= PMC_EV_UCF_LAST) {
2999		ev = ucf_event_table;
3000		evfence = ucf_event_table + PMC_EVENT_TABLE_SIZE(ucf);
3001	} else if (pe >= PMC_EV_UCP_FIRST && pe <= PMC_EV_UCP_LAST) {
3002		switch (cpu) {
3003		case PMC_CPU_INTEL_COREI7:
3004			ev = corei7uc_event_table;
3005			evfence = corei7uc_event_table + PMC_EVENT_TABLE_SIZE(corei7uc);
3006			break;
3007		case PMC_CPU_INTEL_SANDYBRIDGE:
3008			ev = sandybridgeuc_event_table;
3009			evfence = sandybridgeuc_event_table + PMC_EVENT_TABLE_SIZE(sandybridgeuc);
3010			break;
3011		case PMC_CPU_INTEL_WESTMERE:
3012			ev = westmereuc_event_table;
3013			evfence = westmereuc_event_table + PMC_EVENT_TABLE_SIZE(westmereuc);
3014			break;
3015		default:	/* Unknown CPU type. */
3016			break;
3017		}
3018	} else if (pe >= PMC_EV_K7_FIRST && pe <= PMC_EV_K7_LAST) {
3019		ev = k7_event_table;
3020		evfence = k7_event_table + PMC_EVENT_TABLE_SIZE(k7);
3021	} else if (pe >= PMC_EV_K8_FIRST && pe <= PMC_EV_K8_LAST) {
3022		ev = k8_event_table;
3023		evfence = k8_event_table + PMC_EVENT_TABLE_SIZE(k8);
3024	} else if (pe >= PMC_EV_P4_FIRST && pe <= PMC_EV_P4_LAST) {
3025		ev = p4_event_table;
3026		evfence = p4_event_table + PMC_EVENT_TABLE_SIZE(p4);
3027	} else if (pe >= PMC_EV_P5_FIRST && pe <= PMC_EV_P5_LAST) {
3028		ev = p5_event_table;
3029		evfence = p5_event_table + PMC_EVENT_TABLE_SIZE(p5);
3030	} else if (pe >= PMC_EV_P6_FIRST && pe <= PMC_EV_P6_LAST) {
3031		ev = p6_event_table;
3032		evfence = p6_event_table + PMC_EVENT_TABLE_SIZE(p6);
3033	} else if (pe >= PMC_EV_XSCALE_FIRST && pe <= PMC_EV_XSCALE_LAST) {
3034		ev = xscale_event_table;
3035		evfence = xscale_event_table + PMC_EVENT_TABLE_SIZE(xscale);
3036	} else if (pe >= PMC_EV_MIPS24K_FIRST && pe <= PMC_EV_MIPS24K_LAST) {
3037		ev = mips24k_event_table;
3038		evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k
3039);
3040	} else if (pe >= PMC_EV_OCTEON_FIRST && pe <= PMC_EV_OCTEON_LAST) {
3041		ev = octeon_event_table;
3042		evfence = octeon_event_table + PMC_EVENT_TABLE_SIZE(octeon);
3043	} else if (pe >= PMC_EV_PPC7450_FIRST && pe <= PMC_EV_PPC7450_LAST) {
3044		ev = ppc7450_event_table;
3045		evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450
3046);
3047	} else if (pe == PMC_EV_TSC_TSC) {
3048		ev = tsc_event_table;
3049		evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc);
3050	}
3051
3052	for (; ev != evfence; ev++)
3053		if (pe == ev->pm_ev_code)
3054			return (ev->pm_ev_name);
3055
3056	return (NULL);
3057}
3058
3059const char *
3060pmc_name_of_event(enum pmc_event pe)
3061{
3062	const char *n;
3063
3064	if ((n = _pmc_name_of_event(pe, cpu_info.pm_cputype)) != NULL)
3065		return (n);
3066
3067	errno = EINVAL;
3068	return (NULL);
3069}
3070
3071const char *
3072pmc_name_of_mode(enum pmc_mode pm)
3073{
3074	if ((int) pm >= PMC_MODE_FIRST &&
3075	    pm <= PMC_MODE_LAST)
3076		return (pmc_mode_names[pm]);
3077
3078	errno = EINVAL;
3079	return (NULL);
3080}
3081
3082const char *
3083pmc_name_of_state(enum pmc_state ps)
3084{
3085	if ((int) ps >= PMC_STATE_FIRST &&
3086	    ps <= PMC_STATE_LAST)
3087		return (pmc_state_names[ps]);
3088
3089	errno = EINVAL;
3090	return (NULL);
3091}
3092
3093int
3094pmc_ncpu(void)
3095{
3096	if (pmc_syscall == -1) {
3097		errno = ENXIO;
3098		return (-1);
3099	}
3100
3101	return (cpu_info.pm_ncpu);
3102}
3103
3104int
3105pmc_npmc(int cpu)
3106{
3107	if (pmc_syscall == -1) {
3108		errno = ENXIO;
3109		return (-1);
3110	}
3111
3112	if (cpu < 0 || cpu >= (int) cpu_info.pm_ncpu) {
3113		errno = EINVAL;
3114		return (-1);
3115	}
3116
3117	return (cpu_info.pm_npmc);
3118}
3119
3120int
3121pmc_pmcinfo(int cpu, struct pmc_pmcinfo **ppmci)
3122{
3123	int nbytes, npmc;
3124	struct pmc_op_getpmcinfo *pmci;
3125
3126	if ((npmc = pmc_npmc(cpu)) < 0)
3127		return (-1);
3128
3129	nbytes = sizeof(struct pmc_op_getpmcinfo) +
3130	    npmc * sizeof(struct pmc_info);
3131
3132	if ((pmci = calloc(1, nbytes)) == NULL)
3133		return (-1);
3134
3135	pmci->pm_cpu  = cpu;
3136
3137	if (PMC_CALL(GETPMCINFO, pmci) < 0) {
3138		free(pmci);
3139		return (-1);
3140	}
3141
3142	/* kernel<->library, library<->userland interfaces are identical */
3143	*ppmci = (struct pmc_pmcinfo *) pmci;
3144	return (0);
3145}
3146
3147int
3148pmc_read(pmc_id_t pmc, pmc_value_t *value)
3149{
3150	struct pmc_op_pmcrw pmc_read_op;
3151
3152	pmc_read_op.pm_pmcid = pmc;
3153	pmc_read_op.pm_flags = PMC_F_OLDVALUE;
3154	pmc_read_op.pm_value = -1;
3155
3156	if (PMC_CALL(PMCRW, &pmc_read_op) < 0)
3157		return (-1);
3158
3159	*value = pmc_read_op.pm_value;
3160	return (0);
3161}
3162
3163int
3164pmc_release(pmc_id_t pmc)
3165{
3166	struct pmc_op_simple	pmc_release_args;
3167
3168	pmc_release_args.pm_pmcid = pmc;
3169	return (PMC_CALL(PMCRELEASE, &pmc_release_args));
3170}
3171
3172int
3173pmc_rw(pmc_id_t pmc, pmc_value_t newvalue, pmc_value_t *oldvaluep)
3174{
3175	struct pmc_op_pmcrw pmc_rw_op;
3176
3177	pmc_rw_op.pm_pmcid = pmc;
3178	pmc_rw_op.pm_flags = PMC_F_NEWVALUE | PMC_F_OLDVALUE;
3179	pmc_rw_op.pm_value = newvalue;
3180
3181	if (PMC_CALL(PMCRW, &pmc_rw_op) < 0)
3182		return (-1);
3183
3184	*oldvaluep = pmc_rw_op.pm_value;
3185	return (0);
3186}
3187
3188int
3189pmc_set(pmc_id_t pmc, pmc_value_t value)
3190{
3191	struct pmc_op_pmcsetcount sc;
3192
3193	sc.pm_pmcid = pmc;
3194	sc.pm_count = value;
3195
3196	if (PMC_CALL(PMCSETCOUNT, &sc) < 0)
3197		return (-1);
3198	return (0);
3199}
3200
3201int
3202pmc_start(pmc_id_t pmc)
3203{
3204	struct pmc_op_simple	pmc_start_args;
3205
3206	pmc_start_args.pm_pmcid = pmc;
3207	return (PMC_CALL(PMCSTART, &pmc_start_args));
3208}
3209
3210int
3211pmc_stop(pmc_id_t pmc)
3212{
3213	struct pmc_op_simple	pmc_stop_args;
3214
3215	pmc_stop_args.pm_pmcid = pmc;
3216	return (PMC_CALL(PMCSTOP, &pmc_stop_args));
3217}
3218
3219int
3220pmc_width(pmc_id_t pmcid, uint32_t *width)
3221{
3222	unsigned int i;
3223	enum pmc_class cl;
3224
3225	cl = PMC_ID_TO_CLASS(pmcid);
3226	for (i = 0; i < cpu_info.pm_nclass; i++)
3227		if (cpu_info.pm_classes[i].pm_class == cl) {
3228			*width = cpu_info.pm_classes[i].pm_width;
3229			return (0);
3230		}
3231	errno = EINVAL;
3232	return (-1);
3233}
3234
3235int
3236pmc_write(pmc_id_t pmc, pmc_value_t value)
3237{
3238	struct pmc_op_pmcrw pmc_write_op;
3239
3240	pmc_write_op.pm_pmcid = pmc;
3241	pmc_write_op.pm_flags = PMC_F_NEWVALUE;
3242	pmc_write_op.pm_value = value;
3243	return (PMC_CALL(PMCRW, &pmc_write_op));
3244}
3245
3246int
3247pmc_writelog(uint32_t userdata)
3248{
3249	struct pmc_op_writelog wl;
3250
3251	wl.pm_userdata = userdata;
3252	return (PMC_CALL(WRITELOG, &wl));
3253}
3254