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