xref: /freebsd/lib/libpmc/libpmc.c (revision 4f9b4ac4c279650aa4f4ed7cd1b5fdfa60fbf60c)
1ebccf1e3SJoseph Koshy /*-
25e53a4f9SPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
35e53a4f9SPedro F. Giffuni  *
4484202faSJoseph Koshy  * Copyright (c) 2003-2008 Joseph Koshy
5ebccf1e3SJoseph Koshy  * All rights reserved.
6ebccf1e3SJoseph Koshy  *
7ebccf1e3SJoseph Koshy  * Redistribution and use in source and binary forms, with or without
8ebccf1e3SJoseph Koshy  * modification, are permitted provided that the following conditions
9ebccf1e3SJoseph Koshy  * are met:
10ebccf1e3SJoseph Koshy  * 1. Redistributions of source code must retain the above copyright
11ebccf1e3SJoseph Koshy  *    notice, this list of conditions and the following disclaimer.
12ebccf1e3SJoseph Koshy  * 2. Redistributions in binary form must reproduce the above copyright
13ebccf1e3SJoseph Koshy  *    notice, this list of conditions and the following disclaimer in the
14ebccf1e3SJoseph Koshy  *    documentation and/or other materials provided with the distribution.
15ebccf1e3SJoseph Koshy  *
16ebccf1e3SJoseph Koshy  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17ebccf1e3SJoseph Koshy  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18ebccf1e3SJoseph Koshy  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19ebccf1e3SJoseph Koshy  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20ebccf1e3SJoseph Koshy  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21ebccf1e3SJoseph Koshy  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22ebccf1e3SJoseph Koshy  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23ebccf1e3SJoseph Koshy  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24ebccf1e3SJoseph Koshy  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25ebccf1e3SJoseph Koshy  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26ebccf1e3SJoseph Koshy  * SUCH DAMAGE.
27ebccf1e3SJoseph Koshy  */
28ebccf1e3SJoseph Koshy 
29ebccf1e3SJoseph Koshy #include <sys/cdefs.h>
30ebccf1e3SJoseph Koshy __FBSDID("$FreeBSD$");
31ebccf1e3SJoseph Koshy 
32ebccf1e3SJoseph Koshy #include <sys/types.h>
33169dd953SJustin Hibbits #include <sys/param.h>
34ebccf1e3SJoseph Koshy #include <sys/module.h>
35ebccf1e3SJoseph Koshy #include <sys/pmc.h>
36ebccf1e3SJoseph Koshy #include <sys/syscall.h>
37ebccf1e3SJoseph Koshy 
38ebccf1e3SJoseph Koshy #include <ctype.h>
39ebccf1e3SJoseph Koshy #include <errno.h>
40ebccf1e3SJoseph Koshy #include <fcntl.h>
41ebccf1e3SJoseph Koshy #include <pmc.h>
42ebccf1e3SJoseph Koshy #include <stdio.h>
43ebccf1e3SJoseph Koshy #include <stdlib.h>
44ebccf1e3SJoseph Koshy #include <string.h>
45ebccf1e3SJoseph Koshy #include <strings.h>
46ebccf1e3SJoseph Koshy #include <unistd.h>
47ebccf1e3SJoseph Koshy 
480cfab8ddSJoseph Koshy #include "libpmcinternal.h"
490cfab8ddSJoseph Koshy 
50ebccf1e3SJoseph Koshy /* Function prototypes */
5104e9feb0SMarcel Moolenaar #if defined(__i386__)
52ebccf1e3SJoseph Koshy static int k7_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
53ebccf1e3SJoseph Koshy     struct pmc_op_pmcallocate *_pmc_config);
54f263522aSJoseph Koshy #endif
5586a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__)
560cfab8ddSJoseph Koshy static int iaf_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
570cfab8ddSJoseph Koshy     struct pmc_op_pmcallocate *_pmc_config);
580cfab8ddSJoseph Koshy static int iap_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
590cfab8ddSJoseph Koshy     struct pmc_op_pmcallocate *_pmc_config);
601fa7f10bSFabien Thomas static int ucf_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
611fa7f10bSFabien Thomas     struct pmc_op_pmcallocate *_pmc_config);
621fa7f10bSFabien Thomas static int ucp_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
631fa7f10bSFabien Thomas     struct pmc_op_pmcallocate *_pmc_config);
64f263522aSJoseph Koshy static int k8_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
65ebccf1e3SJoseph Koshy     struct pmc_op_pmcallocate *_pmc_config);
6686a65549SJoseph Koshy static int p4_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
6786a65549SJoseph Koshy     struct pmc_op_pmcallocate *_pmc_config);
68f263522aSJoseph Koshy #endif
69f263522aSJoseph Koshy #if defined(__i386__)
70ebccf1e3SJoseph Koshy static int p5_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
71ebccf1e3SJoseph Koshy     struct pmc_op_pmcallocate *_pmc_config);
72f263522aSJoseph Koshy static int p6_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
73ebccf1e3SJoseph Koshy     struct pmc_op_pmcallocate *_pmc_config);
74ebccf1e3SJoseph Koshy #endif
75789140c0SJoseph Koshy #if defined(__amd64__) || defined(__i386__)
76789140c0SJoseph Koshy static int tsc_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
77789140c0SJoseph Koshy     struct pmc_op_pmcallocate *_pmc_config);
78789140c0SJoseph Koshy #endif
796411d14dSRuslan Bukin #if defined(__arm__)
800ce207d2SRui Paulo #if defined(__XSCALE__)
810ce207d2SRui Paulo static int xscale_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
820ce207d2SRui Paulo     struct pmc_op_pmcallocate *_pmc_config);
830ce207d2SRui Paulo #endif
846411d14dSRuslan Bukin static int armv7_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
856411d14dSRuslan Bukin     struct pmc_op_pmcallocate *_pmc_config);
866411d14dSRuslan Bukin #endif
87bc88bb2bSRuslan Bukin #if defined(__aarch64__)
88bc88bb2bSRuslan Bukin static int arm64_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
89bc88bb2bSRuslan Bukin     struct pmc_op_pmcallocate *_pmc_config);
90bc88bb2bSRuslan Bukin #endif
91660df75eSGeorge V. Neville-Neil #if defined(__mips__)
922827d3e1SOleksandr Tymoshenko static int mips_allocate_pmc(enum pmc_event _pe, char* ctrspec,
93660df75eSGeorge V. Neville-Neil 			     struct pmc_op_pmcallocate *_pmc_config);
94660df75eSGeorge V. Neville-Neil #endif /* __mips__ */
95f5f9340bSFabien Thomas static int soft_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
96f5f9340bSFabien Thomas     struct pmc_op_pmcallocate *_pmc_config);
97660df75eSGeorge V. Neville-Neil 
987b25dccaSJustin Hibbits #if defined(__powerpc__)
99169dd953SJustin Hibbits static int powerpc_allocate_pmc(enum pmc_event _pe, char* ctrspec,
1007b25dccaSJustin Hibbits 			     struct pmc_op_pmcallocate *_pmc_config);
1017b25dccaSJustin Hibbits #endif /* __powerpc__ */
102660df75eSGeorge V. Neville-Neil 
103ebccf1e3SJoseph Koshy #define PMC_CALL(cmd, params)				\
104ebccf1e3SJoseph Koshy 	syscall(pmc_syscall, PMC_OP_##cmd, (params))
105ebccf1e3SJoseph Koshy 
106ebccf1e3SJoseph Koshy /*
107ebccf1e3SJoseph Koshy  * Event aliases provide a way for the user to ask for generic events
108ebccf1e3SJoseph Koshy  * like "cache-misses", or "instructions-retired".  These aliases are
109ebccf1e3SJoseph Koshy  * mapped to the appropriate canonical event descriptions using a
110ebccf1e3SJoseph Koshy  * lookup table.
111ebccf1e3SJoseph Koshy  */
112ebccf1e3SJoseph Koshy struct pmc_event_alias {
113ebccf1e3SJoseph Koshy 	const char	*pm_alias;
114ebccf1e3SJoseph Koshy 	const char	*pm_spec;
115ebccf1e3SJoseph Koshy };
116ebccf1e3SJoseph Koshy 
117ebccf1e3SJoseph Koshy static const struct pmc_event_alias *pmc_mdep_event_aliases;
118ebccf1e3SJoseph Koshy 
119ebccf1e3SJoseph Koshy /*
120789140c0SJoseph Koshy  * The pmc_event_descr structure maps symbolic names known to the user
121ebccf1e3SJoseph Koshy  * to integer codes used by the PMC KLD.
122ebccf1e3SJoseph Koshy  */
123ebccf1e3SJoseph Koshy struct pmc_event_descr {
124ebccf1e3SJoseph Koshy 	const char	*pm_ev_name;
125ebccf1e3SJoseph Koshy 	enum pmc_event	pm_ev_code;
126ebccf1e3SJoseph Koshy };
127ebccf1e3SJoseph Koshy 
128789140c0SJoseph Koshy /*
129789140c0SJoseph Koshy  * The pmc_class_descr structure maps class name prefixes for
130789140c0SJoseph Koshy  * event names to event tables and other PMC class data.
131789140c0SJoseph Koshy  */
132789140c0SJoseph Koshy struct pmc_class_descr {
133789140c0SJoseph Koshy 	const char	*pm_evc_name;
134789140c0SJoseph Koshy 	size_t		pm_evc_name_size;
135789140c0SJoseph Koshy 	enum pmc_class	pm_evc_class;
136789140c0SJoseph Koshy 	const struct pmc_event_descr *pm_evc_event_table;
137789140c0SJoseph Koshy 	size_t		pm_evc_event_table_size;
138789140c0SJoseph Koshy 	int		(*pm_evc_allocate_pmc)(enum pmc_event _pe,
139789140c0SJoseph Koshy 			    char *_ctrspec, struct pmc_op_pmcallocate *_pa);
140ebccf1e3SJoseph Koshy };
141ebccf1e3SJoseph Koshy 
142789140c0SJoseph Koshy #define	PMC_TABLE_SIZE(N)	(sizeof(N)/sizeof(N[0]))
143789140c0SJoseph Koshy #define	PMC_EVENT_TABLE_SIZE(N)	PMC_TABLE_SIZE(N##_event_table)
144789140c0SJoseph Koshy 
145789140c0SJoseph Koshy #undef	__PMC_EV
146789140c0SJoseph Koshy #define	__PMC_EV(C,N) { #N, PMC_EV_ ## C ## _ ## N },
147789140c0SJoseph Koshy 
148789140c0SJoseph Koshy /*
1490cfab8ddSJoseph Koshy  * PMC_CLASSDEP_TABLE(NAME, CLASS)
150789140c0SJoseph Koshy  *
1510cfab8ddSJoseph Koshy  * Define a table mapping event names and aliases to HWPMC event IDs.
152789140c0SJoseph Koshy  */
1530cfab8ddSJoseph Koshy #define	PMC_CLASSDEP_TABLE(N, C)				\
154789140c0SJoseph Koshy 	static const struct pmc_event_descr N##_event_table[] =	\
155789140c0SJoseph Koshy 	{							\
156789140c0SJoseph Koshy 		__PMC_EV_##C()					\
1570cfab8ddSJoseph Koshy 	}
1580cfab8ddSJoseph Koshy 
1590cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(iaf, IAF);
1600cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(k7, K7);
1610cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(k8, K8);
1620cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(p4, P4);
1630cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(p5, P5);
1640cfab8ddSJoseph Koshy PMC_CLASSDEP_TABLE(p6, P6);
1650ce207d2SRui Paulo PMC_CLASSDEP_TABLE(xscale, XSCALE);
1666411d14dSRuslan Bukin PMC_CLASSDEP_TABLE(armv7, ARMV7);
167bc88bb2bSRuslan Bukin PMC_CLASSDEP_TABLE(armv8, ARMV8);
168660df75eSGeorge V. Neville-Neil PMC_CLASSDEP_TABLE(mips24k, MIPS24K);
169f6e6460dSAdrian Chadd PMC_CLASSDEP_TABLE(mips74k, MIPS74K);
170c2657f80SOleksandr Tymoshenko PMC_CLASSDEP_TABLE(octeon, OCTEON);
1711fa7f10bSFabien Thomas PMC_CLASSDEP_TABLE(ucf, UCF);
1727b25dccaSJustin Hibbits PMC_CLASSDEP_TABLE(ppc7450, PPC7450);
173169dd953SJustin Hibbits PMC_CLASSDEP_TABLE(ppc970, PPC970);
174a7452468SJustin Hibbits PMC_CLASSDEP_TABLE(e500, E500);
1750cfab8ddSJoseph Koshy 
176f5f9340bSFabien Thomas static struct pmc_event_descr soft_event_table[PMC_EV_DYN_COUNT];
177f5f9340bSFabien Thomas 
1780cfab8ddSJoseph Koshy #undef	__PMC_EV_ALIAS
1790cfab8ddSJoseph Koshy #define	__PMC_EV_ALIAS(N,CODE) 	{ N, PMC_EV_##CODE },
1800cfab8ddSJoseph Koshy 
1810cfab8ddSJoseph Koshy static const struct pmc_event_descr atom_event_table[] =
1820cfab8ddSJoseph Koshy {
1830cfab8ddSJoseph Koshy 	__PMC_EV_ALIAS_ATOM()
1840cfab8ddSJoseph Koshy };
1850cfab8ddSJoseph Koshy 
186e8f021a3SHiren Panchasara static const struct pmc_event_descr atom_silvermont_event_table[] =
187e8f021a3SHiren Panchasara {
188e8f021a3SHiren Panchasara 	__PMC_EV_ALIAS_ATOM_SILVERMONT()
189e8f021a3SHiren Panchasara };
190e8f021a3SHiren Panchasara 
1910cfab8ddSJoseph Koshy static const struct pmc_event_descr core_event_table[] =
1920cfab8ddSJoseph Koshy {
1930cfab8ddSJoseph Koshy 	__PMC_EV_ALIAS_CORE()
1940cfab8ddSJoseph Koshy };
1950cfab8ddSJoseph Koshy 
1960cfab8ddSJoseph Koshy 
1970cfab8ddSJoseph Koshy static const struct pmc_event_descr core2_event_table[] =
1980cfab8ddSJoseph Koshy {
1990cfab8ddSJoseph Koshy 	__PMC_EV_ALIAS_CORE2()
2000cfab8ddSJoseph Koshy };
2010cfab8ddSJoseph Koshy 
202597979c4SJeff Roberson static const struct pmc_event_descr corei7_event_table[] =
203597979c4SJeff Roberson {
204597979c4SJeff Roberson 	__PMC_EV_ALIAS_COREI7()
205597979c4SJeff Roberson };
206597979c4SJeff Roberson 
20749fe48abSKonstantin Belousov static const struct pmc_event_descr nehalem_ex_event_table[] =
20849fe48abSKonstantin Belousov {
20949fe48abSKonstantin Belousov 	__PMC_EV_ALIAS_COREI7()
21049fe48abSKonstantin Belousov };
21149fe48abSKonstantin Belousov 
212cc0c1555SSean Bruno static const struct pmc_event_descr haswell_event_table[] =
213cc0c1555SSean Bruno {
214cc0c1555SSean Bruno 	__PMC_EV_ALIAS_HASWELL()
215cc0c1555SSean Bruno };
216cc0c1555SSean Bruno 
217d95b3509SRandall Stewart static const struct pmc_event_descr haswell_xeon_event_table[] =
218d95b3509SRandall Stewart {
219d95b3509SRandall Stewart 	__PMC_EV_ALIAS_HASWELL_XEON()
220d95b3509SRandall Stewart };
221d95b3509SRandall Stewart 
222f19bae41SRandall Stewart static const struct pmc_event_descr broadwell_event_table[] =
223f19bae41SRandall Stewart {
224f19bae41SRandall Stewart 	__PMC_EV_ALIAS_BROADWELL()
225f19bae41SRandall Stewart };
226f19bae41SRandall Stewart 
227f19bae41SRandall Stewart static const struct pmc_event_descr broadwell_xeon_event_table[] =
228f19bae41SRandall Stewart {
229f19bae41SRandall Stewart 	__PMC_EV_ALIAS_BROADWELL_XEON()
230f19bae41SRandall Stewart };
231f19bae41SRandall Stewart 
232f19bae41SRandall Stewart static const struct pmc_event_descr skylake_event_table[] =
233f19bae41SRandall Stewart {
234f19bae41SRandall Stewart 	__PMC_EV_ALIAS_SKYLAKE()
235f19bae41SRandall Stewart };
236d95b3509SRandall Stewart 
237b99b705dSKonstantin Belousov static const struct pmc_event_descr skylake_xeon_event_table[] =
238b99b705dSKonstantin Belousov {
239b99b705dSKonstantin Belousov 	__PMC_EV_ALIAS_SKYLAKE_XEON()
240b99b705dSKonstantin Belousov };
241b99b705dSKonstantin Belousov 
2421e862e5aSFabien Thomas static const struct pmc_event_descr ivybridge_event_table[] =
2431e862e5aSFabien Thomas {
2441e862e5aSFabien Thomas 	__PMC_EV_ALIAS_IVYBRIDGE()
2451e862e5aSFabien Thomas };
2461e862e5aSFabien Thomas 
2473f929d8cSSean Bruno static const struct pmc_event_descr ivybridge_xeon_event_table[] =
2483f929d8cSSean Bruno {
2493f929d8cSSean Bruno 	__PMC_EV_ALIAS_IVYBRIDGE_XEON()
2503f929d8cSSean Bruno };
2513f929d8cSSean Bruno 
25278d763a2SDavide Italiano static const struct pmc_event_descr sandybridge_event_table[] =
25378d763a2SDavide Italiano {
25478d763a2SDavide Italiano 	__PMC_EV_ALIAS_SANDYBRIDGE()
25578d763a2SDavide Italiano };
25678d763a2SDavide Italiano 
257fabe02f5SSean Bruno static const struct pmc_event_descr sandybridge_xeon_event_table[] =
258fabe02f5SSean Bruno {
259fabe02f5SSean Bruno 	__PMC_EV_ALIAS_SANDYBRIDGE_XEON()
260fabe02f5SSean Bruno };
261fabe02f5SSean Bruno 
2621fa7f10bSFabien Thomas static const struct pmc_event_descr westmere_event_table[] =
2631fa7f10bSFabien Thomas {
2641fa7f10bSFabien Thomas 	__PMC_EV_ALIAS_WESTMERE()
2651fa7f10bSFabien Thomas };
2661fa7f10bSFabien Thomas 
26749fe48abSKonstantin Belousov static const struct pmc_event_descr westmere_ex_event_table[] =
26849fe48abSKonstantin Belousov {
26949fe48abSKonstantin Belousov 	__PMC_EV_ALIAS_WESTMERE()
27049fe48abSKonstantin Belousov };
27149fe48abSKonstantin Belousov 
2721fa7f10bSFabien Thomas static const struct pmc_event_descr corei7uc_event_table[] =
2731fa7f10bSFabien Thomas {
2741fa7f10bSFabien Thomas 	__PMC_EV_ALIAS_COREI7UC()
2751fa7f10bSFabien Thomas };
2761fa7f10bSFabien Thomas 
277cc0c1555SSean Bruno static const struct pmc_event_descr haswelluc_event_table[] =
278cc0c1555SSean Bruno {
279cc0c1555SSean Bruno 	__PMC_EV_ALIAS_HASWELLUC()
280cc0c1555SSean Bruno };
281cc0c1555SSean Bruno 
282f19bae41SRandall Stewart static const struct pmc_event_descr broadwelluc_event_table[] =
283f19bae41SRandall Stewart {
284f19bae41SRandall Stewart 	__PMC_EV_ALIAS_BROADWELLUC()
285f19bae41SRandall Stewart };
286f19bae41SRandall Stewart 
28778d763a2SDavide Italiano static const struct pmc_event_descr sandybridgeuc_event_table[] =
28878d763a2SDavide Italiano {
28978d763a2SDavide Italiano 	__PMC_EV_ALIAS_SANDYBRIDGEUC()
29078d763a2SDavide Italiano };
29178d763a2SDavide Italiano 
2921fa7f10bSFabien Thomas static const struct pmc_event_descr westmereuc_event_table[] =
2931fa7f10bSFabien Thomas {
2941fa7f10bSFabien Thomas 	__PMC_EV_ALIAS_WESTMEREUC()
2951fa7f10bSFabien Thomas };
2961fa7f10bSFabien Thomas 
2973e0bfdd8SRuslan Bukin static const struct pmc_event_descr cortex_a8_event_table[] =
2983e0bfdd8SRuslan Bukin {
2993e0bfdd8SRuslan Bukin 	__PMC_EV_ALIAS_ARMV7_CORTEX_A8()
3003e0bfdd8SRuslan Bukin };
3013e0bfdd8SRuslan Bukin 
3023e0bfdd8SRuslan Bukin static const struct pmc_event_descr cortex_a9_event_table[] =
3033e0bfdd8SRuslan Bukin {
3043e0bfdd8SRuslan Bukin 	__PMC_EV_ALIAS_ARMV7_CORTEX_A9()
3053e0bfdd8SRuslan Bukin };
3063e0bfdd8SRuslan Bukin 
307bc88bb2bSRuslan Bukin static const struct pmc_event_descr cortex_a53_event_table[] =
308bc88bb2bSRuslan Bukin {
309bc88bb2bSRuslan Bukin 	__PMC_EV_ALIAS_ARMV8_CORTEX_A53()
310bc88bb2bSRuslan Bukin };
311bc88bb2bSRuslan Bukin 
312bc88bb2bSRuslan Bukin static const struct pmc_event_descr cortex_a57_event_table[] =
313bc88bb2bSRuslan Bukin {
314bc88bb2bSRuslan Bukin 	__PMC_EV_ALIAS_ARMV8_CORTEX_A57()
315bc88bb2bSRuslan Bukin };
316bc88bb2bSRuslan Bukin 
3170cfab8ddSJoseph Koshy /*
3180cfab8ddSJoseph Koshy  * PMC_MDEP_TABLE(NAME, PRIMARYCLASS, ADDITIONAL_CLASSES...)
3190cfab8ddSJoseph Koshy  *
3200cfab8ddSJoseph Koshy  * Map a CPU to the PMC classes it supports.
3210cfab8ddSJoseph Koshy  */
3220cfab8ddSJoseph Koshy #define	PMC_MDEP_TABLE(N,C,...)				\
323789140c0SJoseph Koshy 	static const enum pmc_class N##_pmc_classes[] = {	\
324789140c0SJoseph Koshy 		PMC_CLASS_##C, __VA_ARGS__			\
325789140c0SJoseph Koshy 	}
326789140c0SJoseph Koshy 
327f5f9340bSFabien Thomas PMC_MDEP_TABLE(atom, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
328e8f021a3SHiren Panchasara PMC_MDEP_TABLE(atom_silvermont, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
329f5f9340bSFabien Thomas PMC_MDEP_TABLE(core, IAP, PMC_CLASS_SOFT, PMC_CLASS_TSC);
330f5f9340bSFabien Thomas PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
331f5f9340bSFabien Thomas PMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
33249fe48abSKonstantin Belousov PMC_MDEP_TABLE(nehalem_ex, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
333cc0c1555SSean Bruno PMC_MDEP_TABLE(haswell, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
334d95b3509SRandall Stewart PMC_MDEP_TABLE(haswell_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
335f19bae41SRandall Stewart PMC_MDEP_TABLE(broadwell, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
336f19bae41SRandall Stewart PMC_MDEP_TABLE(broadwell_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
337f19bae41SRandall Stewart PMC_MDEP_TABLE(skylake, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
338b99b705dSKonstantin Belousov PMC_MDEP_TABLE(skylake_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
3391e862e5aSFabien Thomas PMC_MDEP_TABLE(ivybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
3403f929d8cSSean Bruno PMC_MDEP_TABLE(ivybridge_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
341f5f9340bSFabien Thomas PMC_MDEP_TABLE(sandybridge, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
342fabe02f5SSean Bruno PMC_MDEP_TABLE(sandybridge_xeon, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
343f5f9340bSFabien Thomas PMC_MDEP_TABLE(westmere, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC, PMC_CLASS_UCF, PMC_CLASS_UCP);
34449fe48abSKonstantin Belousov PMC_MDEP_TABLE(westmere_ex, IAP, PMC_CLASS_SOFT, PMC_CLASS_IAF, PMC_CLASS_TSC);
345f5f9340bSFabien Thomas PMC_MDEP_TABLE(k7, K7, PMC_CLASS_SOFT, PMC_CLASS_TSC);
346f5f9340bSFabien Thomas PMC_MDEP_TABLE(k8, K8, PMC_CLASS_SOFT, PMC_CLASS_TSC);
347f5f9340bSFabien Thomas PMC_MDEP_TABLE(p4, P4, PMC_CLASS_SOFT, PMC_CLASS_TSC);
348f5f9340bSFabien Thomas PMC_MDEP_TABLE(p5, P5, PMC_CLASS_SOFT, PMC_CLASS_TSC);
349f5f9340bSFabien Thomas PMC_MDEP_TABLE(p6, P6, PMC_CLASS_SOFT, PMC_CLASS_TSC);
350f5f9340bSFabien Thomas PMC_MDEP_TABLE(xscale, XSCALE, PMC_CLASS_SOFT, PMC_CLASS_XSCALE);
3513e0bfdd8SRuslan Bukin PMC_MDEP_TABLE(cortex_a8, ARMV7, PMC_CLASS_SOFT, PMC_CLASS_ARMV7);
3523e0bfdd8SRuslan Bukin PMC_MDEP_TABLE(cortex_a9, ARMV7, PMC_CLASS_SOFT, PMC_CLASS_ARMV7);
353bc88bb2bSRuslan Bukin PMC_MDEP_TABLE(cortex_a53, ARMV8, PMC_CLASS_SOFT, PMC_CLASS_ARMV8);
354bc88bb2bSRuslan Bukin PMC_MDEP_TABLE(cortex_a57, ARMV8, PMC_CLASS_SOFT, PMC_CLASS_ARMV8);
355f5f9340bSFabien Thomas PMC_MDEP_TABLE(mips24k, MIPS24K, PMC_CLASS_SOFT, PMC_CLASS_MIPS24K);
356f6e6460dSAdrian Chadd PMC_MDEP_TABLE(mips74k, MIPS74K, PMC_CLASS_SOFT, PMC_CLASS_MIPS74K);
357f5f9340bSFabien Thomas PMC_MDEP_TABLE(octeon, OCTEON, PMC_CLASS_SOFT, PMC_CLASS_OCTEON);
358a7452468SJustin Hibbits PMC_MDEP_TABLE(ppc7450, PPC7450, PMC_CLASS_SOFT, PMC_CLASS_PPC7450, PMC_CLASS_TSC);
359a7452468SJustin Hibbits PMC_MDEP_TABLE(ppc970, PPC970, PMC_CLASS_SOFT, PMC_CLASS_PPC970, PMC_CLASS_TSC);
360a7452468SJustin Hibbits PMC_MDEP_TABLE(e500, E500, PMC_CLASS_SOFT, PMC_CLASS_E500, PMC_CLASS_TSC);
361f5f9340bSFabien Thomas PMC_MDEP_TABLE(generic, SOFT, PMC_CLASS_SOFT);
362789140c0SJoseph Koshy 
363789140c0SJoseph Koshy static const struct pmc_event_descr tsc_event_table[] =
364789140c0SJoseph Koshy {
365789140c0SJoseph Koshy 	__PMC_EV_TSC()
366789140c0SJoseph Koshy };
367789140c0SJoseph Koshy 
368789140c0SJoseph Koshy #undef	PMC_CLASS_TABLE_DESC
3690cfab8ddSJoseph Koshy #define	PMC_CLASS_TABLE_DESC(NAME, CLASS, EVENTS, ALLOCATOR)	\
3700cfab8ddSJoseph Koshy static const struct pmc_class_descr NAME##_class_table_descr =	\
3710cfab8ddSJoseph Koshy 	{							\
3720cfab8ddSJoseph Koshy 		.pm_evc_name  = #CLASS "-",			\
3730cfab8ddSJoseph Koshy 		.pm_evc_name_size = sizeof(#CLASS "-") - 1,	\
3740cfab8ddSJoseph Koshy 		.pm_evc_class = PMC_CLASS_##CLASS ,		\
3750cfab8ddSJoseph Koshy 		.pm_evc_event_table = EVENTS##_event_table ,	\
376789140c0SJoseph Koshy 		.pm_evc_event_table_size = 			\
3770cfab8ddSJoseph Koshy 			PMC_EVENT_TABLE_SIZE(EVENTS),		\
3780cfab8ddSJoseph Koshy 		.pm_evc_allocate_pmc = ALLOCATOR##_allocate_pmc	\
379789140c0SJoseph Koshy 	}
380789140c0SJoseph Koshy 
381789140c0SJoseph Koshy #if	defined(__i386__) || defined(__amd64__)
3820cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(iaf, IAF, iaf, iaf);
3830cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(atom, IAP, atom, iap);
384e8f021a3SHiren Panchasara PMC_CLASS_TABLE_DESC(atom_silvermont, IAP, atom_silvermont, iap);
3850cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(core, IAP, core, iap);
3860cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(core2, IAP, core2, iap);
387597979c4SJeff Roberson PMC_CLASS_TABLE_DESC(corei7, IAP, corei7, iap);
38849fe48abSKonstantin Belousov PMC_CLASS_TABLE_DESC(nehalem_ex, IAP, nehalem_ex, iap);
389cc0c1555SSean Bruno PMC_CLASS_TABLE_DESC(haswell, IAP, haswell, iap);
390ae9975dbSRyan Stone PMC_CLASS_TABLE_DESC(haswell_xeon, IAP, haswell_xeon, iap);
391f19bae41SRandall Stewart PMC_CLASS_TABLE_DESC(broadwell, IAP, broadwell, iap);
392f19bae41SRandall Stewart PMC_CLASS_TABLE_DESC(broadwell_xeon, IAP, broadwell_xeon, iap);
393f19bae41SRandall Stewart PMC_CLASS_TABLE_DESC(skylake, IAP, skylake, iap);
394b99b705dSKonstantin Belousov PMC_CLASS_TABLE_DESC(skylake_xeon, IAP, skylake_xeon, iap);
3951e862e5aSFabien Thomas PMC_CLASS_TABLE_DESC(ivybridge, IAP, ivybridge, iap);
3963f929d8cSSean Bruno PMC_CLASS_TABLE_DESC(ivybridge_xeon, IAP, ivybridge_xeon, iap);
39778d763a2SDavide Italiano PMC_CLASS_TABLE_DESC(sandybridge, IAP, sandybridge, iap);
398fabe02f5SSean Bruno PMC_CLASS_TABLE_DESC(sandybridge_xeon, IAP, sandybridge_xeon, iap);
3991fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(westmere, IAP, westmere, iap);
40049fe48abSKonstantin Belousov PMC_CLASS_TABLE_DESC(westmere_ex, IAP, westmere_ex, iap);
4011fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(ucf, UCF, ucf, ucf);
4021fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(corei7uc, UCP, corei7uc, ucp);
403cc0c1555SSean Bruno PMC_CLASS_TABLE_DESC(haswelluc, UCP, haswelluc, ucp);
404f19bae41SRandall Stewart PMC_CLASS_TABLE_DESC(broadwelluc, UCP, broadwelluc, ucp);
40578d763a2SDavide Italiano PMC_CLASS_TABLE_DESC(sandybridgeuc, UCP, sandybridgeuc, ucp);
4061fa7f10bSFabien Thomas PMC_CLASS_TABLE_DESC(westmereuc, UCP, westmereuc, ucp);
407789140c0SJoseph Koshy #endif
408789140c0SJoseph Koshy #if	defined(__i386__)
4090cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(k7, K7, k7, k7);
410789140c0SJoseph Koshy #endif
411789140c0SJoseph Koshy #if	defined(__i386__) || defined(__amd64__)
4120cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(k8, K8, k8, k8);
4130cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(p4, P4, p4, p4);
414789140c0SJoseph Koshy #endif
4150cfab8ddSJoseph Koshy #if	defined(__i386__)
4160cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(p5, P5, p5, p5);
4170cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(p6, P6, p6, p6);
4180cfab8ddSJoseph Koshy #endif
4190cfab8ddSJoseph Koshy #if	defined(__i386__) || defined(__amd64__)
4200cfab8ddSJoseph Koshy PMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc);
4210cfab8ddSJoseph Koshy #endif
4226411d14dSRuslan Bukin #if	defined(__arm__)
4230ce207d2SRui Paulo #if	defined(__XSCALE__)
4240ce207d2SRui Paulo PMC_CLASS_TABLE_DESC(xscale, XSCALE, xscale, xscale);
4250ce207d2SRui Paulo #endif
4263ed01392SBjoern A. Zeeb PMC_CLASS_TABLE_DESC(cortex_a8, ARMV7, cortex_a8, armv7);
4273e0bfdd8SRuslan Bukin PMC_CLASS_TABLE_DESC(cortex_a9, ARMV7, cortex_a9, armv7);
4286411d14dSRuslan Bukin #endif
429bc88bb2bSRuslan Bukin #if	defined(__aarch64__)
430bc88bb2bSRuslan Bukin PMC_CLASS_TABLE_DESC(cortex_a53, ARMV8, cortex_a53, arm64);
431bc88bb2bSRuslan Bukin PMC_CLASS_TABLE_DESC(cortex_a57, ARMV8, cortex_a57, arm64);
432bc88bb2bSRuslan Bukin #endif
433660df75eSGeorge V. Neville-Neil #if defined(__mips__)
4342827d3e1SOleksandr Tymoshenko PMC_CLASS_TABLE_DESC(mips24k, MIPS24K, mips24k, mips);
435f6e6460dSAdrian Chadd PMC_CLASS_TABLE_DESC(mips74k, MIPS74K, mips74k, mips);
436c2657f80SOleksandr Tymoshenko PMC_CLASS_TABLE_DESC(octeon, OCTEON, octeon, mips);
437660df75eSGeorge V. Neville-Neil #endif /* __mips__ */
4387b25dccaSJustin Hibbits #if defined(__powerpc__)
439169dd953SJustin Hibbits PMC_CLASS_TABLE_DESC(ppc7450, PPC7450, ppc7450, powerpc);
440169dd953SJustin Hibbits PMC_CLASS_TABLE_DESC(ppc970, PPC970, ppc970, powerpc);
441a7452468SJustin Hibbits PMC_CLASS_TABLE_DESC(e500, E500, e500, powerpc);
4427b25dccaSJustin Hibbits #endif
4437b25dccaSJustin Hibbits 
444f5f9340bSFabien Thomas static struct pmc_class_descr soft_class_table_descr =
445f5f9340bSFabien Thomas {
446f5f9340bSFabien Thomas 	.pm_evc_name  = "SOFT-",
447f5f9340bSFabien Thomas 	.pm_evc_name_size = sizeof("SOFT-") - 1,
448f5f9340bSFabien Thomas 	.pm_evc_class = PMC_CLASS_SOFT,
449f5f9340bSFabien Thomas 	.pm_evc_event_table = NULL,
450f5f9340bSFabien Thomas 	.pm_evc_event_table_size = 0,
451f5f9340bSFabien Thomas 	.pm_evc_allocate_pmc = soft_allocate_pmc
452f5f9340bSFabien Thomas };
453f5f9340bSFabien Thomas 
454789140c0SJoseph Koshy #undef	PMC_CLASS_TABLE_DESC
455789140c0SJoseph Koshy 
4560cfab8ddSJoseph Koshy static const struct pmc_class_descr **pmc_class_table;
4570cfab8ddSJoseph Koshy #define	PMC_CLASS_TABLE_SIZE	cpu_info.pm_nclass
4580cfab8ddSJoseph Koshy 
459789140c0SJoseph Koshy static const enum pmc_class *pmc_mdep_class_list;
460789140c0SJoseph Koshy static size_t pmc_mdep_class_list_size;
461789140c0SJoseph Koshy 
462ebccf1e3SJoseph Koshy /*
463ebccf1e3SJoseph Koshy  * Mapping tables, mapping enumeration values to human readable
464ebccf1e3SJoseph Koshy  * strings.
465ebccf1e3SJoseph Koshy  */
466ebccf1e3SJoseph Koshy 
467ebccf1e3SJoseph Koshy static const char * pmc_capability_names[] = {
468ebccf1e3SJoseph Koshy #undef	__PMC_CAP
469ebccf1e3SJoseph Koshy #define	__PMC_CAP(N,V,D)	#N ,
470ebccf1e3SJoseph Koshy 	__PMC_CAPS()
471ebccf1e3SJoseph Koshy };
472ebccf1e3SJoseph Koshy 
4730ceb54c2SJohn Baldwin struct pmc_class_map {
4740ceb54c2SJohn Baldwin 	enum pmc_class	pm_class;
4750ceb54c2SJohn Baldwin 	const char	*pm_name;
4760ceb54c2SJohn Baldwin };
4770ceb54c2SJohn Baldwin 
4780ceb54c2SJohn Baldwin static const struct pmc_class_map pmc_class_names[] = {
479ebccf1e3SJoseph Koshy #undef	__PMC_CLASS
4800ceb54c2SJohn Baldwin #define __PMC_CLASS(S,V,D) { .pm_class = PMC_CLASS_##S, .pm_name = #S } ,
481ebccf1e3SJoseph Koshy 	__PMC_CLASSES()
482ebccf1e3SJoseph Koshy };
483ebccf1e3SJoseph Koshy 
484789140c0SJoseph Koshy struct pmc_cputype_map {
485562fc14bSDimitry Andric 	enum pmc_cputype pm_cputype;
486789140c0SJoseph Koshy 	const char	*pm_name;
487789140c0SJoseph Koshy };
488789140c0SJoseph Koshy 
489789140c0SJoseph Koshy static const struct pmc_cputype_map pmc_cputype_names[] = {
490ebccf1e3SJoseph Koshy #undef	__PMC_CPU
491789140c0SJoseph Koshy #define	__PMC_CPU(S, V, D) { .pm_cputype = PMC_CPU_##S, .pm_name = #S } ,
492ebccf1e3SJoseph Koshy 	__PMC_CPUS()
493ebccf1e3SJoseph Koshy };
494ebccf1e3SJoseph Koshy 
495ebccf1e3SJoseph Koshy static const char * pmc_disposition_names[] = {
496ebccf1e3SJoseph Koshy #undef	__PMC_DISP
497ebccf1e3SJoseph Koshy #define	__PMC_DISP(D)	#D ,
498ebccf1e3SJoseph Koshy 	__PMC_DISPOSITIONS()
499ebccf1e3SJoseph Koshy };
500ebccf1e3SJoseph Koshy 
501ebccf1e3SJoseph Koshy static const char * pmc_mode_names[] = {
502ebccf1e3SJoseph Koshy #undef  __PMC_MODE
503ebccf1e3SJoseph Koshy #define __PMC_MODE(M,N)	#M ,
504ebccf1e3SJoseph Koshy 	__PMC_MODES()
505ebccf1e3SJoseph Koshy };
506ebccf1e3SJoseph Koshy 
507ebccf1e3SJoseph Koshy static const char * pmc_state_names[] = {
508ebccf1e3SJoseph Koshy #undef  __PMC_STATE
509ebccf1e3SJoseph Koshy #define __PMC_STATE(S) #S ,
510ebccf1e3SJoseph Koshy 	__PMC_STATES()
511ebccf1e3SJoseph Koshy };
512ebccf1e3SJoseph Koshy 
513f5f9340bSFabien Thomas /*
514f5f9340bSFabien Thomas  * Filled in by pmc_init().
515f5f9340bSFabien Thomas  */
516f5f9340bSFabien Thomas static int pmc_syscall = -1;
517f5f9340bSFabien Thomas static struct pmc_cpuinfo cpu_info;
518f5f9340bSFabien Thomas static struct pmc_op_getdyneventinfo soft_event_info;
5191455fcd3SJoseph Koshy 
520ebccf1e3SJoseph Koshy /* Event masks for events */
521ebccf1e3SJoseph Koshy struct pmc_masks {
522ebccf1e3SJoseph Koshy 	const char	*pm_name;
5231e862e5aSFabien Thomas 	const uint64_t	pm_value;
524ebccf1e3SJoseph Koshy };
525ebccf1e3SJoseph Koshy #define	PMCMASK(N,V)	{ .pm_name = #N, .pm_value = (V) }
5261fa7f10bSFabien Thomas #define	NULLMASK	{ .pm_name = NULL }
527ebccf1e3SJoseph Koshy 
52886a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__)
529ebccf1e3SJoseph Koshy static int
5301e862e5aSFabien Thomas pmc_parse_mask(const struct pmc_masks *pmask, char *p, uint64_t *evmask)
531ebccf1e3SJoseph Koshy {
532ebccf1e3SJoseph Koshy 	const struct pmc_masks *pm;
533ebccf1e3SJoseph Koshy 	char *q, *r;
534ebccf1e3SJoseph Koshy 	int c;
535ebccf1e3SJoseph Koshy 
536ebccf1e3SJoseph Koshy 	if (pmask == NULL)	/* no mask keywords */
537aa342b1fSJoseph Koshy 		return (-1);
538ebccf1e3SJoseph Koshy 	q = strchr(p, '=');	/* skip '=' */
539ebccf1e3SJoseph Koshy 	if (*++q == '\0')	/* no more data */
540aa342b1fSJoseph Koshy 		return (-1);
541ebccf1e3SJoseph Koshy 	c = 0;			/* count of mask keywords seen */
542ebccf1e3SJoseph Koshy 	while ((r = strsep(&q, "+")) != NULL) {
543789140c0SJoseph Koshy 		for (pm = pmask; pm->pm_name && strcasecmp(r, pm->pm_name);
544789140c0SJoseph Koshy 		    pm++)
545ebccf1e3SJoseph Koshy 			;
546ebccf1e3SJoseph Koshy 		if (pm->pm_name == NULL) /* not found */
547aa342b1fSJoseph Koshy 			return (-1);
548ebccf1e3SJoseph Koshy 		*evmask |= pm->pm_value;
549ebccf1e3SJoseph Koshy 		c++;
550ebccf1e3SJoseph Koshy 	}
551aa342b1fSJoseph Koshy 	return (c);
552ebccf1e3SJoseph Koshy }
55304e9feb0SMarcel Moolenaar #endif
554ebccf1e3SJoseph Koshy 
555ebccf1e3SJoseph Koshy #define	KWMATCH(p,kw)		(strcasecmp((p), (kw)) == 0)
556ebccf1e3SJoseph Koshy #define	KWPREFIXMATCH(p,kw)	(strncasecmp((p), (kw), sizeof((kw)) - 1) == 0)
557ebccf1e3SJoseph Koshy #define	EV_ALIAS(N,S)		{ .pm_alias = N, .pm_spec = S }
558ebccf1e3SJoseph Koshy 
55904e9feb0SMarcel Moolenaar #if defined(__i386__)
560ebccf1e3SJoseph Koshy 
561ebccf1e3SJoseph Koshy /*
562ebccf1e3SJoseph Koshy  * AMD K7 (Athlon) CPUs.
563ebccf1e3SJoseph Koshy  */
564ebccf1e3SJoseph Koshy 
565ebccf1e3SJoseph Koshy static struct pmc_event_alias k7_aliases[] = {
566ebccf1e3SJoseph Koshy 	EV_ALIAS("branches",		"k7-retired-branches"),
567ebccf1e3SJoseph Koshy 	EV_ALIAS("branch-mispredicts",	"k7-retired-branches-mispredicted"),
568ebccf1e3SJoseph Koshy 	EV_ALIAS("cycles",		"tsc"),
5696aa5a193SJoseph Koshy 	EV_ALIAS("dc-misses",		"k7-dc-misses"),
570ebccf1e3SJoseph Koshy 	EV_ALIAS("ic-misses",		"k7-ic-misses"),
571ebccf1e3SJoseph Koshy 	EV_ALIAS("instructions",	"k7-retired-instructions"),
572ebccf1e3SJoseph Koshy 	EV_ALIAS("interrupts",		"k7-hardware-interrupts"),
573ebccf1e3SJoseph Koshy 	EV_ALIAS(NULL, NULL)
574ebccf1e3SJoseph Koshy };
575ebccf1e3SJoseph Koshy 
576ebccf1e3SJoseph Koshy #define	K7_KW_COUNT	"count"
577ebccf1e3SJoseph Koshy #define	K7_KW_EDGE	"edge"
578ebccf1e3SJoseph Koshy #define	K7_KW_INV	"inv"
579ebccf1e3SJoseph Koshy #define	K7_KW_OS	"os"
580ebccf1e3SJoseph Koshy #define	K7_KW_UNITMASK	"unitmask"
581ebccf1e3SJoseph Koshy #define	K7_KW_USR	"usr"
582ebccf1e3SJoseph Koshy 
583ebccf1e3SJoseph Koshy static int
584ebccf1e3SJoseph Koshy k7_allocate_pmc(enum pmc_event pe, char *ctrspec,
585ebccf1e3SJoseph Koshy     struct pmc_op_pmcallocate *pmc_config)
586ebccf1e3SJoseph Koshy {
587ebccf1e3SJoseph Koshy 	char		*e, *p, *q;
588ebccf1e3SJoseph Koshy 	int		c, has_unitmask;
589ebccf1e3SJoseph Koshy 	uint32_t	count, unitmask;
590ebccf1e3SJoseph Koshy 
591f263522aSJoseph Koshy 	pmc_config->pm_md.pm_amd.pm_amd_config = 0;
592789140c0SJoseph Koshy 	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
593ebccf1e3SJoseph Koshy 
594ebccf1e3SJoseph Koshy 	if (pe == PMC_EV_K7_DC_REFILLS_FROM_L2 ||
595ebccf1e3SJoseph Koshy 	    pe == PMC_EV_K7_DC_REFILLS_FROM_SYSTEM ||
596ebccf1e3SJoseph Koshy 	    pe == PMC_EV_K7_DC_WRITEBACKS) {
597ebccf1e3SJoseph Koshy 		has_unitmask = 1;
598f263522aSJoseph Koshy 		unitmask = AMD_PMC_UNITMASK_MOESI;
599ebccf1e3SJoseph Koshy 	} else
600ebccf1e3SJoseph Koshy 		unitmask = has_unitmask = 0;
601ebccf1e3SJoseph Koshy 
602ebccf1e3SJoseph Koshy 	while ((p = strsep(&ctrspec, ",")) != NULL) {
603ebccf1e3SJoseph Koshy 		if (KWPREFIXMATCH(p, K7_KW_COUNT "=")) {
604ebccf1e3SJoseph Koshy 			q = strchr(p, '=');
605ebccf1e3SJoseph Koshy 			if (*++q == '\0') /* skip '=' */
606aa342b1fSJoseph Koshy 				return (-1);
607ebccf1e3SJoseph Koshy 
608ebccf1e3SJoseph Koshy 			count = strtol(q, &e, 0);
609ebccf1e3SJoseph Koshy 			if (e == q || *e != '\0')
610aa342b1fSJoseph Koshy 				return (-1);
611ebccf1e3SJoseph Koshy 
612ebccf1e3SJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
613f263522aSJoseph Koshy 			pmc_config->pm_md.pm_amd.pm_amd_config |=
614f263522aSJoseph Koshy 			    AMD_PMC_TO_COUNTER(count);
615ebccf1e3SJoseph Koshy 
616ebccf1e3SJoseph Koshy 		} else if (KWMATCH(p, K7_KW_EDGE)) {
617ebccf1e3SJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_EDGE;
618ebccf1e3SJoseph Koshy 		} else if (KWMATCH(p, K7_KW_INV)) {
619ebccf1e3SJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_INVERT;
620ebccf1e3SJoseph Koshy 		} else if (KWMATCH(p, K7_KW_OS)) {
621ebccf1e3SJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_SYSTEM;
622ebccf1e3SJoseph Koshy 		} else if (KWPREFIXMATCH(p, K7_KW_UNITMASK "=")) {
623ebccf1e3SJoseph Koshy 			if (has_unitmask == 0)
624aa342b1fSJoseph Koshy 				return (-1);
625ebccf1e3SJoseph Koshy 			unitmask = 0;
626ebccf1e3SJoseph Koshy 			q = strchr(p, '=');
627ebccf1e3SJoseph Koshy 			if (*++q == '\0') /* skip '=' */
628aa342b1fSJoseph Koshy 				return (-1);
629ebccf1e3SJoseph Koshy 
630ebccf1e3SJoseph Koshy 			while ((c = tolower(*q++)) != 0)
631ebccf1e3SJoseph Koshy 				if (c == 'm')
632f263522aSJoseph Koshy 					unitmask |= AMD_PMC_UNITMASK_M;
633ebccf1e3SJoseph Koshy 				else if (c == 'o')
634f263522aSJoseph Koshy 					unitmask |= AMD_PMC_UNITMASK_O;
635ebccf1e3SJoseph Koshy 				else if (c == 'e')
636f263522aSJoseph Koshy 					unitmask |= AMD_PMC_UNITMASK_E;
637ebccf1e3SJoseph Koshy 				else if (c == 's')
638f263522aSJoseph Koshy 					unitmask |= AMD_PMC_UNITMASK_S;
639ebccf1e3SJoseph Koshy 				else if (c == 'i')
640f263522aSJoseph Koshy 					unitmask |= AMD_PMC_UNITMASK_I;
641ebccf1e3SJoseph Koshy 				else if (c == '+')
642ebccf1e3SJoseph Koshy 					continue;
643ebccf1e3SJoseph Koshy 				else
644aa342b1fSJoseph Koshy 					return (-1);
645ebccf1e3SJoseph Koshy 
646ebccf1e3SJoseph Koshy 			if (unitmask == 0)
647aa342b1fSJoseph Koshy 				return (-1);
648ebccf1e3SJoseph Koshy 
649ebccf1e3SJoseph Koshy 		} else if (KWMATCH(p, K7_KW_USR)) {
650ebccf1e3SJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_USER;
651ebccf1e3SJoseph Koshy 		} else
652aa342b1fSJoseph Koshy 			return (-1);
653ebccf1e3SJoseph Koshy 	}
654ebccf1e3SJoseph Koshy 
655ebccf1e3SJoseph Koshy 	if (has_unitmask) {
656ebccf1e3SJoseph Koshy 		pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
657f263522aSJoseph Koshy 		pmc_config->pm_md.pm_amd.pm_amd_config |=
658f263522aSJoseph Koshy 		    AMD_PMC_TO_UNITMASK(unitmask);
659ebccf1e3SJoseph Koshy 	}
660ebccf1e3SJoseph Koshy 
661aa342b1fSJoseph Koshy 	return (0);
662ebccf1e3SJoseph Koshy 
663ebccf1e3SJoseph Koshy }
664ebccf1e3SJoseph Koshy 
665f263522aSJoseph Koshy #endif
666f263522aSJoseph Koshy 
66786a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__)
668f263522aSJoseph Koshy 
669f263522aSJoseph Koshy /*
6700cfab8ddSJoseph Koshy  * Intel Core (Family 6, Model E) PMCs.
6710cfab8ddSJoseph Koshy  */
6720cfab8ddSJoseph Koshy 
6730cfab8ddSJoseph Koshy static struct pmc_event_alias core_aliases[] = {
6740cfab8ddSJoseph Koshy 	EV_ALIAS("branches",		"iap-br-instr-ret"),
6750cfab8ddSJoseph Koshy 	EV_ALIAS("branch-mispredicts",	"iap-br-mispred-ret"),
6760cfab8ddSJoseph Koshy 	EV_ALIAS("cycles",		"tsc-tsc"),
6770cfab8ddSJoseph Koshy 	EV_ALIAS("ic-misses",		"iap-icache-misses"),
6780cfab8ddSJoseph Koshy 	EV_ALIAS("instructions",	"iap-instr-ret"),
6790cfab8ddSJoseph Koshy 	EV_ALIAS("interrupts",		"iap-core-hw-int-rx"),
6800cfab8ddSJoseph Koshy 	EV_ALIAS("unhalted-cycles",	"iap-unhalted-core-cycles"),
6810cfab8ddSJoseph Koshy 	EV_ALIAS(NULL, NULL)
6820cfab8ddSJoseph Koshy };
6830cfab8ddSJoseph Koshy 
6840cfab8ddSJoseph Koshy /*
6850cfab8ddSJoseph Koshy  * Intel Core2 (Family 6, Model F), Core2Extreme (Family 6, Model 17H)
6860cfab8ddSJoseph Koshy  * and Atom (Family 6, model 1CH) PMCs.
687791f5d5bSJoseph Koshy  *
688791f5d5bSJoseph Koshy  * We map aliases to events on the fixed-function counters if these
689791f5d5bSJoseph Koshy  * are present.  Note that not all CPUs in this family contain fixed-function
690791f5d5bSJoseph Koshy  * counters.
6910cfab8ddSJoseph Koshy  */
6920cfab8ddSJoseph Koshy 
6930cfab8ddSJoseph Koshy static struct pmc_event_alias core2_aliases[] = {
6940cfab8ddSJoseph Koshy 	EV_ALIAS("branches",		"iap-br-inst-retired.any"),
6950cfab8ddSJoseph Koshy 	EV_ALIAS("branch-mispredicts",	"iap-br-inst-retired.mispred"),
6960cfab8ddSJoseph Koshy 	EV_ALIAS("cycles",		"tsc-tsc"),
6970cfab8ddSJoseph Koshy 	EV_ALIAS("ic-misses",		"iap-l1i-misses"),
6980cfab8ddSJoseph Koshy 	EV_ALIAS("instructions",	"iaf-instr-retired.any"),
6990cfab8ddSJoseph Koshy 	EV_ALIAS("interrupts",		"iap-hw-int-rcv"),
7000cfab8ddSJoseph Koshy 	EV_ALIAS("unhalted-cycles",	"iaf-cpu-clk-unhalted.core"),
7010cfab8ddSJoseph Koshy 	EV_ALIAS(NULL, NULL)
7020cfab8ddSJoseph Koshy };
703791f5d5bSJoseph Koshy 
704791f5d5bSJoseph Koshy static struct pmc_event_alias core2_aliases_without_iaf[] = {
705791f5d5bSJoseph Koshy 	EV_ALIAS("branches",		"iap-br-inst-retired.any"),
706791f5d5bSJoseph Koshy 	EV_ALIAS("branch-mispredicts",	"iap-br-inst-retired.mispred"),
707791f5d5bSJoseph Koshy 	EV_ALIAS("cycles",		"tsc-tsc"),
708791f5d5bSJoseph Koshy 	EV_ALIAS("ic-misses",		"iap-l1i-misses"),
709791f5d5bSJoseph Koshy 	EV_ALIAS("instructions",	"iap-inst-retired.any_p"),
710791f5d5bSJoseph Koshy 	EV_ALIAS("interrupts",		"iap-hw-int-rcv"),
711791f5d5bSJoseph Koshy 	EV_ALIAS("unhalted-cycles",	"iap-cpu-clk-unhalted.core_p"),
712791f5d5bSJoseph Koshy 	EV_ALIAS(NULL, NULL)
713791f5d5bSJoseph Koshy };
714791f5d5bSJoseph Koshy 
7150cfab8ddSJoseph Koshy #define	atom_aliases			core2_aliases
716791f5d5bSJoseph Koshy #define	atom_aliases_without_iaf	core2_aliases_without_iaf
717e8f021a3SHiren Panchasara #define	atom_silvermont_aliases		core2_aliases
718e8f021a3SHiren Panchasara #define	atom_silvermont_aliases_without_iaf	core2_aliases_without_iaf
719597979c4SJeff Roberson #define corei7_aliases			core2_aliases
720791f5d5bSJoseph Koshy #define corei7_aliases_without_iaf	core2_aliases_without_iaf
72149fe48abSKonstantin Belousov #define nehalem_ex_aliases		core2_aliases
72249fe48abSKonstantin Belousov #define nehalem_ex_aliases_without_iaf	core2_aliases_without_iaf
723cc0c1555SSean Bruno #define haswell_aliases			core2_aliases
724cc0c1555SSean Bruno #define haswell_aliases_without_iaf	core2_aliases_without_iaf
725d95b3509SRandall Stewart #define haswell_xeon_aliases			core2_aliases
726d95b3509SRandall Stewart #define haswell_xeon_aliases_without_iaf	core2_aliases_without_iaf
727f19bae41SRandall Stewart #define broadwell_aliases			core2_aliases
728f19bae41SRandall Stewart #define broadwell_aliases_without_iaf	core2_aliases_without_iaf
729f19bae41SRandall Stewart #define broadwell_xeon_aliases			core2_aliases
730f19bae41SRandall Stewart #define broadwell_xeon_aliases_without_iaf	core2_aliases_without_iaf
731f19bae41SRandall Stewart #define skylake_aliases			core2_aliases
732f19bae41SRandall Stewart #define skylake_aliases_without_iaf	core2_aliases_without_iaf
733b99b705dSKonstantin Belousov #define skylake_xeon_aliases		core2_aliases
734b99b705dSKonstantin Belousov #define skylake_xeon_aliases_without_iaf	core2_aliases_without_iaf
7351e862e5aSFabien Thomas #define ivybridge_aliases		core2_aliases
7361e862e5aSFabien Thomas #define ivybridge_aliases_without_iaf	core2_aliases_without_iaf
7373f929d8cSSean Bruno #define ivybridge_xeon_aliases		core2_aliases
7383f929d8cSSean Bruno #define ivybridge_xeon_aliases_without_iaf	core2_aliases_without_iaf
73978d763a2SDavide Italiano #define sandybridge_aliases		core2_aliases
74078d763a2SDavide Italiano #define sandybridge_aliases_without_iaf	core2_aliases_without_iaf
741fabe02f5SSean Bruno #define sandybridge_xeon_aliases	core2_aliases
742fabe02f5SSean Bruno #define sandybridge_xeon_aliases_without_iaf	core2_aliases_without_iaf
7431fa7f10bSFabien Thomas #define westmere_aliases		core2_aliases
7441fa7f10bSFabien Thomas #define westmere_aliases_without_iaf	core2_aliases_without_iaf
74549fe48abSKonstantin Belousov #define westmere_ex_aliases		core2_aliases
74649fe48abSKonstantin Belousov #define westmere_ex_aliases_without_iaf	core2_aliases_without_iaf
7470cfab8ddSJoseph Koshy 
7480cfab8ddSJoseph Koshy #define	IAF_KW_OS		"os"
7490cfab8ddSJoseph Koshy #define	IAF_KW_USR		"usr"
7500cfab8ddSJoseph Koshy #define	IAF_KW_ANYTHREAD	"anythread"
7510cfab8ddSJoseph Koshy 
7520cfab8ddSJoseph Koshy /*
7530cfab8ddSJoseph Koshy  * Parse an event specifier for Intel fixed function counters.
7540cfab8ddSJoseph Koshy  */
7550cfab8ddSJoseph Koshy static int
7560cfab8ddSJoseph Koshy iaf_allocate_pmc(enum pmc_event pe, char *ctrspec,
7570cfab8ddSJoseph Koshy     struct pmc_op_pmcallocate *pmc_config)
7580cfab8ddSJoseph Koshy {
7590cfab8ddSJoseph Koshy 	char *p;
7600cfab8ddSJoseph Koshy 
7610cfab8ddSJoseph Koshy 	(void) pe;
7620cfab8ddSJoseph Koshy 
7630cfab8ddSJoseph Koshy 	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
7640cfab8ddSJoseph Koshy 	pmc_config->pm_md.pm_iaf.pm_iaf_flags = 0;
7650cfab8ddSJoseph Koshy 
7660cfab8ddSJoseph Koshy 	while ((p = strsep(&ctrspec, ",")) != NULL) {
7670cfab8ddSJoseph Koshy 		if (KWMATCH(p, IAF_KW_OS))
7680cfab8ddSJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_SYSTEM;
7690cfab8ddSJoseph Koshy 		else if (KWMATCH(p, IAF_KW_USR))
7700cfab8ddSJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_USER;
7710cfab8ddSJoseph Koshy 		else if (KWMATCH(p, IAF_KW_ANYTHREAD))
7720cfab8ddSJoseph Koshy 			pmc_config->pm_md.pm_iaf.pm_iaf_flags |= IAF_ANY;
7730cfab8ddSJoseph Koshy 		else
7740cfab8ddSJoseph Koshy 			return (-1);
7750cfab8ddSJoseph Koshy 	}
7760cfab8ddSJoseph Koshy 
7770cfab8ddSJoseph Koshy 	return (0);
7780cfab8ddSJoseph Koshy }
7790cfab8ddSJoseph Koshy 
7800cfab8ddSJoseph Koshy /*
7810cfab8ddSJoseph Koshy  * Core/Core2 support.
7820cfab8ddSJoseph Koshy  */
7830cfab8ddSJoseph Koshy 
7840cfab8ddSJoseph Koshy #define	IAP_KW_AGENT		"agent"
7850cfab8ddSJoseph Koshy #define	IAP_KW_ANYTHREAD	"anythread"
7860cfab8ddSJoseph Koshy #define	IAP_KW_CACHESTATE	"cachestate"
7870cfab8ddSJoseph Koshy #define	IAP_KW_CMASK		"cmask"
7880cfab8ddSJoseph Koshy #define	IAP_KW_CORE		"core"
7890cfab8ddSJoseph Koshy #define	IAP_KW_EDGE		"edge"
7900cfab8ddSJoseph Koshy #define	IAP_KW_INV		"inv"
7910cfab8ddSJoseph Koshy #define	IAP_KW_OS		"os"
7920cfab8ddSJoseph Koshy #define	IAP_KW_PREFETCH		"prefetch"
7930cfab8ddSJoseph Koshy #define	IAP_KW_SNOOPRESPONSE	"snoopresponse"
7940cfab8ddSJoseph Koshy #define	IAP_KW_SNOOPTYPE	"snooptype"
7950cfab8ddSJoseph Koshy #define	IAP_KW_TRANSITION	"trans"
7960cfab8ddSJoseph Koshy #define	IAP_KW_USR		"usr"
7971fa7f10bSFabien Thomas #define	IAP_KW_RSP		"rsp"
7980cfab8ddSJoseph Koshy 
7990cfab8ddSJoseph Koshy static struct pmc_masks iap_core_mask[] = {
8000cfab8ddSJoseph Koshy 	PMCMASK(all,	(0x3 << 14)),
8010cfab8ddSJoseph Koshy 	PMCMASK(this,	(0x1 << 14)),
8020cfab8ddSJoseph Koshy 	NULLMASK
8030cfab8ddSJoseph Koshy };
8040cfab8ddSJoseph Koshy 
8050cfab8ddSJoseph Koshy static struct pmc_masks iap_agent_mask[] = {
8060cfab8ddSJoseph Koshy 	PMCMASK(this,	0),
8070cfab8ddSJoseph Koshy 	PMCMASK(any,	(0x1 << 13)),
8080cfab8ddSJoseph Koshy 	NULLMASK
8090cfab8ddSJoseph Koshy };
8100cfab8ddSJoseph Koshy 
8110cfab8ddSJoseph Koshy static struct pmc_masks iap_prefetch_mask[] = {
8120cfab8ddSJoseph Koshy 	PMCMASK(both,		(0x3 << 12)),
8130cfab8ddSJoseph Koshy 	PMCMASK(only,		(0x1 << 12)),
8140cfab8ddSJoseph Koshy 	PMCMASK(exclude,	0),
8150cfab8ddSJoseph Koshy 	NULLMASK
8160cfab8ddSJoseph Koshy };
8170cfab8ddSJoseph Koshy 
8180cfab8ddSJoseph Koshy static struct pmc_masks iap_cachestate_mask[] = {
8190cfab8ddSJoseph Koshy 	PMCMASK(i,		(1 <<  8)),
8200cfab8ddSJoseph Koshy 	PMCMASK(s,		(1 <<  9)),
8210cfab8ddSJoseph Koshy 	PMCMASK(e,		(1 << 10)),
8220cfab8ddSJoseph Koshy 	PMCMASK(m,		(1 << 11)),
8230cfab8ddSJoseph Koshy 	NULLMASK
8240cfab8ddSJoseph Koshy };
8250cfab8ddSJoseph Koshy 
8260cfab8ddSJoseph Koshy static struct pmc_masks iap_snoopresponse_mask[] = {
8270cfab8ddSJoseph Koshy 	PMCMASK(clean,		(1 << 8)),
8280cfab8ddSJoseph Koshy 	PMCMASK(hit,		(1 << 9)),
8290cfab8ddSJoseph Koshy 	PMCMASK(hitm,		(1 << 11)),
8300cfab8ddSJoseph Koshy 	NULLMASK
8310cfab8ddSJoseph Koshy };
8320cfab8ddSJoseph Koshy 
8330cfab8ddSJoseph Koshy static struct pmc_masks iap_snooptype_mask[] = {
8340cfab8ddSJoseph Koshy 	PMCMASK(cmp2s,		(1 << 8)),
8350cfab8ddSJoseph Koshy 	PMCMASK(cmp2i,		(1 << 9)),
8360cfab8ddSJoseph Koshy 	NULLMASK
8370cfab8ddSJoseph Koshy };
8380cfab8ddSJoseph Koshy 
8390cfab8ddSJoseph Koshy static struct pmc_masks iap_transition_mask[] = {
8400cfab8ddSJoseph Koshy 	PMCMASK(any,		0x00),
8410cfab8ddSJoseph Koshy 	PMCMASK(frequency,	0x10),
8420cfab8ddSJoseph Koshy 	NULLMASK
8430cfab8ddSJoseph Koshy };
8440cfab8ddSJoseph Koshy 
8451e862e5aSFabien Thomas static struct pmc_masks iap_rsp_mask_i7_wm[] = {
8461fa7f10bSFabien Thomas 	PMCMASK(DMND_DATA_RD,		(1 <<  0)),
8471fa7f10bSFabien Thomas 	PMCMASK(DMND_RFO,		(1 <<  1)),
8481fa7f10bSFabien Thomas 	PMCMASK(DMND_IFETCH,		(1 <<  2)),
8491fa7f10bSFabien Thomas 	PMCMASK(WB,			(1 <<  3)),
8501fa7f10bSFabien Thomas 	PMCMASK(PF_DATA_RD,		(1 <<  4)),
8511fa7f10bSFabien Thomas 	PMCMASK(PF_RFO,			(1 <<  5)),
8521fa7f10bSFabien Thomas 	PMCMASK(PF_IFETCH,		(1 <<  6)),
8531fa7f10bSFabien Thomas 	PMCMASK(OTHER,			(1 <<  7)),
8541fa7f10bSFabien Thomas 	PMCMASK(UNCORE_HIT,		(1 <<  8)),
8551fa7f10bSFabien Thomas 	PMCMASK(OTHER_CORE_HIT_SNP,	(1 <<  9)),
8561fa7f10bSFabien Thomas 	PMCMASK(OTHER_CORE_HITM,	(1 << 10)),
8571fa7f10bSFabien Thomas 	PMCMASK(REMOTE_CACHE_FWD,	(1 << 12)),
8581fa7f10bSFabien Thomas 	PMCMASK(REMOTE_DRAM,		(1 << 13)),
8591fa7f10bSFabien Thomas 	PMCMASK(LOCAL_DRAM,		(1 << 14)),
8601fa7f10bSFabien Thomas 	PMCMASK(NON_DRAM,		(1 << 15)),
8611fa7f10bSFabien Thomas 	NULLMASK
8621fa7f10bSFabien Thomas };
8631fa7f10bSFabien Thomas 
864fabe02f5SSean Bruno static struct pmc_masks iap_rsp_mask_sb_sbx_ib[] = {
8651e862e5aSFabien Thomas 	PMCMASK(REQ_DMND_DATA_RD,	(1ULL <<  0)),
8661e862e5aSFabien Thomas 	PMCMASK(REQ_DMND_RFO,		(1ULL <<  1)),
8671e862e5aSFabien Thomas 	PMCMASK(REQ_DMND_IFETCH,	(1ULL <<  2)),
8681e862e5aSFabien Thomas 	PMCMASK(REQ_WB,			(1ULL <<  3)),
8691e862e5aSFabien Thomas 	PMCMASK(REQ_PF_DATA_RD,		(1ULL <<  4)),
8701e862e5aSFabien Thomas 	PMCMASK(REQ_PF_RFO,		(1ULL <<  5)),
8711e862e5aSFabien Thomas 	PMCMASK(REQ_PF_IFETCH,		(1ULL <<  6)),
8721e862e5aSFabien Thomas 	PMCMASK(REQ_PF_LLC_DATA_RD,	(1ULL <<  7)),
8731e862e5aSFabien Thomas 	PMCMASK(REQ_PF_LLC_RFO,		(1ULL <<  8)),
8741e862e5aSFabien Thomas 	PMCMASK(REQ_PF_LLC_IFETCH,	(1ULL <<  9)),
8751e862e5aSFabien Thomas 	PMCMASK(REQ_BUS_LOCKS,		(1ULL << 10)),
8761e862e5aSFabien Thomas 	PMCMASK(REQ_STRM_ST,		(1ULL << 11)),
8771e862e5aSFabien Thomas 	PMCMASK(REQ_OTHER,		(1ULL << 15)),
8781e862e5aSFabien Thomas 	PMCMASK(RES_ANY,		(1ULL << 16)),
8791e862e5aSFabien Thomas 	PMCMASK(RES_SUPPLIER_SUPP,	(1ULL << 17)),
8801e862e5aSFabien Thomas 	PMCMASK(RES_SUPPLIER_LLC_HITM,	(1ULL << 18)),
8811e862e5aSFabien Thomas 	PMCMASK(RES_SUPPLIER_LLC_HITE,	(1ULL << 19)),
8821e862e5aSFabien Thomas 	PMCMASK(RES_SUPPLIER_LLC_HITS,	(1ULL << 20)),
8831e862e5aSFabien Thomas 	PMCMASK(RES_SUPPLIER_LLC_HITF,	(1ULL << 21)),
8841e862e5aSFabien Thomas 	PMCMASK(RES_SUPPLIER_LOCAL,	(1ULL << 22)),
885cdfd0cc8SSean Bruno 	PMCMASK(RES_SNOOP_SNP_NONE,	(1ULL << 31)),
8861e862e5aSFabien Thomas 	PMCMASK(RES_SNOOP_SNP_NO_NEEDED,(1ULL << 32)),
8871e862e5aSFabien Thomas 	PMCMASK(RES_SNOOP_SNP_MISS,	(1ULL << 33)),
8881e862e5aSFabien Thomas 	PMCMASK(RES_SNOOP_HIT_NO_FWD,	(1ULL << 34)),
8891e862e5aSFabien Thomas 	PMCMASK(RES_SNOOP_HIT_FWD,	(1ULL << 35)),
8901e862e5aSFabien Thomas 	PMCMASK(RES_SNOOP_HITM,		(1ULL << 36)),
8911e862e5aSFabien Thomas 	PMCMASK(RES_NON_DRAM,		(1ULL << 37)),
8921e862e5aSFabien Thomas 	NULLMASK
8931e862e5aSFabien Thomas };
8941e862e5aSFabien Thomas 
895f19bae41SRandall Stewart /* Broadwell is defined to use the same mask as Haswell */
896cc0c1555SSean Bruno static struct pmc_masks iap_rsp_mask_haswell[] = {
897cc0c1555SSean Bruno 	PMCMASK(REQ_DMND_DATA_RD,	(1ULL <<  0)),
898cc0c1555SSean Bruno 	PMCMASK(REQ_DMND_RFO,		(1ULL <<  1)),
899cc0c1555SSean Bruno 	PMCMASK(REQ_DMND_IFETCH,	(1ULL <<  2)),
900cc0c1555SSean Bruno 	PMCMASK(REQ_PF_DATA_RD,		(1ULL <<  4)),
901cc0c1555SSean Bruno 	PMCMASK(REQ_PF_RFO,		(1ULL <<  5)),
902cc0c1555SSean Bruno 	PMCMASK(REQ_PF_IFETCH,		(1ULL <<  6)),
903cc0c1555SSean Bruno 	PMCMASK(REQ_OTHER,		(1ULL << 15)),
904cc0c1555SSean Bruno 	PMCMASK(RES_ANY,		(1ULL << 16)),
905cc0c1555SSean Bruno 	PMCMASK(RES_SUPPLIER_SUPP,	(1ULL << 17)),
906cc0c1555SSean Bruno 	PMCMASK(RES_SUPPLIER_LLC_HITM,	(1ULL << 18)),
907cc0c1555SSean Bruno 	PMCMASK(RES_SUPPLIER_LLC_HITE,	(1ULL << 19)),
908cc0c1555SSean Bruno 	PMCMASK(RES_SUPPLIER_LLC_HITS,	(1ULL << 20)),
909cc0c1555SSean Bruno 	PMCMASK(RES_SUPPLIER_LLC_HITF,	(1ULL << 21)),
910cc0c1555SSean Bruno 	PMCMASK(RES_SUPPLIER_LOCAL,	(1ULL << 22)),
911f19bae41SRandall Stewart 	/*
912f19bae41SRandall Stewart 	 * For processor type 06_45H 22 is L4_HIT_LOCAL_L4
913f19bae41SRandall Stewart 	 * and 23, 24 and 25 are also defined.
914f19bae41SRandall Stewart 	 */
915cc0c1555SSean Bruno 	PMCMASK(RES_SNOOP_SNP_NONE,	(1ULL << 31)),
916cc0c1555SSean Bruno 	PMCMASK(RES_SNOOP_SNP_NO_NEEDED,(1ULL << 32)),
917cc0c1555SSean Bruno 	PMCMASK(RES_SNOOP_SNP_MISS,	(1ULL << 33)),
918cc0c1555SSean Bruno 	PMCMASK(RES_SNOOP_HIT_NO_FWD,	(1ULL << 34)),
919cc0c1555SSean Bruno 	PMCMASK(RES_SNOOP_HIT_FWD,	(1ULL << 35)),
920cc0c1555SSean Bruno 	PMCMASK(RES_SNOOP_HITM,		(1ULL << 36)),
921cc0c1555SSean Bruno 	PMCMASK(RES_NON_DRAM,		(1ULL << 37)),
922cc0c1555SSean Bruno 	NULLMASK
923cc0c1555SSean Bruno };
924cc0c1555SSean Bruno 
925f19bae41SRandall Stewart static struct pmc_masks iap_rsp_mask_skylake[] = {
926f19bae41SRandall Stewart 	PMCMASK(REQ_DMND_DATA_RD,	(1ULL <<  0)),
927f19bae41SRandall Stewart 	PMCMASK(REQ_DMND_RFO,		(1ULL <<  1)),
928f19bae41SRandall Stewart 	PMCMASK(REQ_DMND_IFETCH,	(1ULL <<  2)),
929f19bae41SRandall Stewart 	PMCMASK(REQ_PF_DATA_RD,		(1ULL <<  7)),
930f19bae41SRandall Stewart 	PMCMASK(REQ_PF_RFO,		(1ULL <<  8)),
931f19bae41SRandall Stewart 	PMCMASK(REQ_STRM_ST,		(1ULL << 11)),
932f19bae41SRandall Stewart 	PMCMASK(REQ_OTHER,		(1ULL << 15)),
933f19bae41SRandall Stewart 	PMCMASK(RES_ANY,		(1ULL << 16)),
934f19bae41SRandall Stewart 	PMCMASK(RES_SUPPLIER_SUPP,	(1ULL << 17)),
935f19bae41SRandall Stewart 	PMCMASK(RES_SUPPLIER_LLC_HITM,	(1ULL << 18)),
936f19bae41SRandall Stewart 	PMCMASK(RES_SUPPLIER_LLC_HITE,	(1ULL << 19)),
937f19bae41SRandall Stewart 	PMCMASK(RES_SUPPLIER_LLC_HITS,	(1ULL << 20)),
938f19bae41SRandall Stewart 	PMCMASK(RES_SUPPLIER_L4_HIT,	(1ULL << 22)),
939f19bae41SRandall Stewart 	PMCMASK(RES_SUPPLIER_DRAM,	(1ULL << 26)),
940f19bae41SRandall Stewart 	PMCMASK(RES_SUPPLIER_SPL_HIT,	(1ULL << 30)),
941f19bae41SRandall Stewart 	PMCMASK(RES_SNOOP_SNP_NONE,	(1ULL << 31)),
942f19bae41SRandall Stewart 	PMCMASK(RES_SNOOP_SNP_NO_NEEDED,(1ULL << 32)),
943f19bae41SRandall Stewart 	PMCMASK(RES_SNOOP_SNP_MISS,	(1ULL << 33)),
944f19bae41SRandall Stewart 	PMCMASK(RES_SNOOP_HIT_NO_FWD,	(1ULL << 34)),
945f19bae41SRandall Stewart 	PMCMASK(RES_SNOOP_HIT_FWD,	(1ULL << 35)),
946f19bae41SRandall Stewart 	PMCMASK(RES_SNOOP_HITM,		(1ULL << 36)),
947f19bae41SRandall Stewart 	PMCMASK(RES_NON_DRAM,		(1ULL << 37)),
948f19bae41SRandall Stewart 	NULLMASK
949f19bae41SRandall Stewart };
950f19bae41SRandall Stewart 
951f19bae41SRandall Stewart 
9520cfab8ddSJoseph Koshy static int
9530cfab8ddSJoseph Koshy iap_allocate_pmc(enum pmc_event pe, char *ctrspec,
9540cfab8ddSJoseph Koshy     struct pmc_op_pmcallocate *pmc_config)
9550cfab8ddSJoseph Koshy {
9560cfab8ddSJoseph Koshy 	char *e, *p, *q;
9571e862e5aSFabien Thomas 	uint64_t cachestate, evmask, rsp;
9580cfab8ddSJoseph Koshy 	int count, n;
9590cfab8ddSJoseph Koshy 
9600cfab8ddSJoseph Koshy 	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE |
9610cfab8ddSJoseph Koshy 	    PMC_CAP_QUALIFIER);
9620cfab8ddSJoseph Koshy 	pmc_config->pm_md.pm_iap.pm_iap_config = 0;
9630cfab8ddSJoseph Koshy 
9641fa7f10bSFabien Thomas 	cachestate = evmask = rsp = 0;
9650cfab8ddSJoseph Koshy 
9660cfab8ddSJoseph Koshy 	/* Parse additional modifiers if present */
9670cfab8ddSJoseph Koshy 	while ((p = strsep(&ctrspec, ",")) != NULL) {
9680cfab8ddSJoseph Koshy 
9690cfab8ddSJoseph Koshy 		n = 0;
9700cfab8ddSJoseph Koshy 		if (KWPREFIXMATCH(p, IAP_KW_CMASK "=")) {
9710cfab8ddSJoseph Koshy 			q = strchr(p, '=');
9720cfab8ddSJoseph Koshy 			if (*++q == '\0') /* skip '=' */
9730cfab8ddSJoseph Koshy 				return (-1);
9740cfab8ddSJoseph Koshy 			count = strtol(q, &e, 0);
9750cfab8ddSJoseph Koshy 			if (e == q || *e != '\0')
9760cfab8ddSJoseph Koshy 				return (-1);
9770cfab8ddSJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
9780cfab8ddSJoseph Koshy 			pmc_config->pm_md.pm_iap.pm_iap_config |=
9790cfab8ddSJoseph Koshy 			    IAP_CMASK(count);
9800cfab8ddSJoseph Koshy 		} else if (KWMATCH(p, IAP_KW_EDGE)) {
9810cfab8ddSJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_EDGE;
9820cfab8ddSJoseph Koshy 		} else if (KWMATCH(p, IAP_KW_INV)) {
9830cfab8ddSJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_INVERT;
9840cfab8ddSJoseph Koshy 		} else if (KWMATCH(p, IAP_KW_OS)) {
9850cfab8ddSJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_SYSTEM;
9860cfab8ddSJoseph Koshy 		} else if (KWMATCH(p, IAP_KW_USR)) {
9870cfab8ddSJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_USER;
9880cfab8ddSJoseph Koshy 		} else if (KWMATCH(p, IAP_KW_ANYTHREAD)) {
9890cfab8ddSJoseph Koshy 			pmc_config->pm_md.pm_iap.pm_iap_config |= IAP_ANY;
990b47ea38eSJoseph Koshy 		} else if (KWPREFIXMATCH(p, IAP_KW_CORE "=")) {
9910cfab8ddSJoseph Koshy 			n = pmc_parse_mask(iap_core_mask, p, &evmask);
9920cfab8ddSJoseph Koshy 			if (n != 1)
9930cfab8ddSJoseph Koshy 				return (-1);
994b47ea38eSJoseph Koshy 		} else if (KWPREFIXMATCH(p, IAP_KW_AGENT "=")) {
9950cfab8ddSJoseph Koshy 			n = pmc_parse_mask(iap_agent_mask, p, &evmask);
9960cfab8ddSJoseph Koshy 			if (n != 1)
9970cfab8ddSJoseph Koshy 				return (-1);
998b47ea38eSJoseph Koshy 		} else if (KWPREFIXMATCH(p, IAP_KW_PREFETCH "=")) {
9990cfab8ddSJoseph Koshy 			n = pmc_parse_mask(iap_prefetch_mask, p, &evmask);
10000cfab8ddSJoseph Koshy 			if (n != 1)
10010cfab8ddSJoseph Koshy 				return (-1);
1002b47ea38eSJoseph Koshy 		} else if (KWPREFIXMATCH(p, IAP_KW_CACHESTATE "=")) {
10030cfab8ddSJoseph Koshy 			n = pmc_parse_mask(iap_cachestate_mask, p, &cachestate);
10040cfab8ddSJoseph Koshy 		} else if (cpu_info.pm_cputype == PMC_CPU_INTEL_CORE &&
1005b47ea38eSJoseph Koshy 		    KWPREFIXMATCH(p, IAP_KW_TRANSITION "=")) {
10060cfab8ddSJoseph Koshy 			n = pmc_parse_mask(iap_transition_mask, p, &evmask);
10070cfab8ddSJoseph Koshy 			if (n != 1)
10080cfab8ddSJoseph Koshy 				return (-1);
10090cfab8ddSJoseph Koshy 		} else if (cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM ||
1010e8f021a3SHiren Panchasara 		    cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM_SILVERMONT ||
1011b4d091f3SJoseph Koshy 		    cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2 ||
10121fa7f10bSFabien Thomas 		    cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2EXTREME) {
1013b47ea38eSJoseph Koshy 			if (KWPREFIXMATCH(p, IAP_KW_SNOOPRESPONSE "=")) {
10140cfab8ddSJoseph Koshy 				n = pmc_parse_mask(iap_snoopresponse_mask, p,
10150cfab8ddSJoseph Koshy 				    &evmask);
1016b47ea38eSJoseph Koshy 			} else if (KWPREFIXMATCH(p, IAP_KW_SNOOPTYPE "=")) {
10170cfab8ddSJoseph Koshy 				n = pmc_parse_mask(iap_snooptype_mask, p,
10180cfab8ddSJoseph Koshy 				    &evmask);
10190cfab8ddSJoseph Koshy 			} else
10200cfab8ddSJoseph Koshy 				return (-1);
10211fa7f10bSFabien Thomas 		} else if (cpu_info.pm_cputype == PMC_CPU_INTEL_COREI7 ||
102249fe48abSKonstantin Belousov 		    cpu_info.pm_cputype == PMC_CPU_INTEL_WESTMERE ||
102349fe48abSKonstantin Belousov 		    cpu_info.pm_cputype == PMC_CPU_INTEL_NEHALEM_EX ||
102449fe48abSKonstantin Belousov 		    cpu_info.pm_cputype == PMC_CPU_INTEL_WESTMERE_EX) {
10251fa7f10bSFabien Thomas 			if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) {
10261e862e5aSFabien Thomas 				n = pmc_parse_mask(iap_rsp_mask_i7_wm, p, &rsp);
10271e862e5aSFabien Thomas 			} else
10281e862e5aSFabien Thomas 				return (-1);
10291e862e5aSFabien Thomas 		} else if (cpu_info.pm_cputype == PMC_CPU_INTEL_SANDYBRIDGE ||
1030fabe02f5SSean Bruno 		    cpu_info.pm_cputype == PMC_CPU_INTEL_SANDYBRIDGE_XEON ||
10313f929d8cSSean Bruno 		    cpu_info.pm_cputype == PMC_CPU_INTEL_IVYBRIDGE ||
10323f929d8cSSean Bruno 		    cpu_info.pm_cputype == PMC_CPU_INTEL_IVYBRIDGE_XEON ) {
10331e862e5aSFabien Thomas 			if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) {
1034fabe02f5SSean Bruno 				n = pmc_parse_mask(iap_rsp_mask_sb_sbx_ib, p, &rsp);
10351fa7f10bSFabien Thomas 			} else
10361fa7f10bSFabien Thomas 				return (-1);
1037d95b3509SRandall Stewart 		} else if (cpu_info.pm_cputype == PMC_CPU_INTEL_HASWELL ||
1038d95b3509SRandall Stewart 		    cpu_info.pm_cputype == PMC_CPU_INTEL_HASWELL_XEON) {
1039cc0c1555SSean Bruno 			if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) {
1040cc0c1555SSean Bruno 				n = pmc_parse_mask(iap_rsp_mask_haswell, p, &rsp);
1041cc0c1555SSean Bruno 			} else
1042cc0c1555SSean Bruno 				return (-1);
1043f19bae41SRandall Stewart 		} else if (cpu_info.pm_cputype == PMC_CPU_INTEL_BROADWELL ||
1044f19bae41SRandall Stewart 		    cpu_info.pm_cputype == PMC_CPU_INTEL_BROADWELL_XEON) {
1045f19bae41SRandall Stewart 			/* Broadwell is defined to use same mask as haswell */
1046f19bae41SRandall Stewart 			if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) {
1047f19bae41SRandall Stewart 				n = pmc_parse_mask(iap_rsp_mask_haswell, p, &rsp);
1048f19bae41SRandall Stewart 			} else
1049f19bae41SRandall Stewart 				return (-1);
1050f19bae41SRandall Stewart 
1051b99b705dSKonstantin Belousov 		} else if (cpu_info.pm_cputype == PMC_CPU_INTEL_SKYLAKE ||
1052b99b705dSKonstantin Belousov 		    cpu_info.pm_cputype == PMC_CPU_INTEL_SKYLAKE_XEON) {
1053f19bae41SRandall Stewart 			if (KWPREFIXMATCH(p, IAP_KW_RSP "=")) {
1054f19bae41SRandall Stewart 				n = pmc_parse_mask(iap_rsp_mask_skylake, p, &rsp);
1055f19bae41SRandall Stewart 			} else
1056f19bae41SRandall Stewart 				return (-1);
1057f19bae41SRandall Stewart 
10580cfab8ddSJoseph Koshy 		} else
10590cfab8ddSJoseph Koshy 			return (-1);
10600cfab8ddSJoseph Koshy 
10610cfab8ddSJoseph Koshy 		if (n < 0)	/* Parsing failed. */
10620cfab8ddSJoseph Koshy 			return (-1);
10630cfab8ddSJoseph Koshy 	}
10640cfab8ddSJoseph Koshy 
10650cfab8ddSJoseph Koshy 	pmc_config->pm_md.pm_iap.pm_iap_config |= evmask;
10660cfab8ddSJoseph Koshy 
10670cfab8ddSJoseph Koshy 	/*
10680cfab8ddSJoseph Koshy 	 * If the event requires a 'cachestate' qualifier but was not
10690cfab8ddSJoseph Koshy 	 * specified by the user, use a sensible default.
10700cfab8ddSJoseph Koshy 	 */
10710cfab8ddSJoseph Koshy 	switch (pe) {
10720cfab8ddSJoseph Koshy 	case PMC_EV_IAP_EVENT_28H: /* Core, Core2, Atom */
10730cfab8ddSJoseph Koshy 	case PMC_EV_IAP_EVENT_29H: /* Core, Core2, Atom */
10740cfab8ddSJoseph Koshy 	case PMC_EV_IAP_EVENT_2AH: /* Core, Core2, Atom */
10750cfab8ddSJoseph Koshy 	case PMC_EV_IAP_EVENT_2BH: /* Atom, Core2 */
10760cfab8ddSJoseph Koshy 	case PMC_EV_IAP_EVENT_2EH: /* Core, Core2, Atom */
10770cfab8ddSJoseph Koshy 	case PMC_EV_IAP_EVENT_30H: /* Core, Core2, Atom */
10780cfab8ddSJoseph Koshy 	case PMC_EV_IAP_EVENT_32H: /* Core */
10790cfab8ddSJoseph Koshy 	case PMC_EV_IAP_EVENT_40H: /* Core */
10800cfab8ddSJoseph Koshy 	case PMC_EV_IAP_EVENT_41H: /* Core */
10810cfab8ddSJoseph Koshy 	case PMC_EV_IAP_EVENT_42H: /* Core, Core2, Atom */
10820cfab8ddSJoseph Koshy 		if (cachestate == 0)
10830cfab8ddSJoseph Koshy 			cachestate = (0xF << 8);
1084aa1b887bSRyan Stone 		break;
1085aa1b887bSRyan Stone 	case PMC_EV_IAP_EVENT_77H: /* Atom */
1086aa1b887bSRyan Stone 		/* IAP_EVENT_77H only accepts a cachestate qualifier on the
1087aa1b887bSRyan Stone 		 * Atom processor
1088aa1b887bSRyan Stone 		 */
1089aa1b887bSRyan Stone 		if(cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM && cachestate == 0)
1090aa1b887bSRyan Stone 			cachestate = (0xF << 8);
1091aa1b887bSRyan Stone 	    break;
10920cfab8ddSJoseph Koshy 	default:
10930cfab8ddSJoseph Koshy 		break;
10940cfab8ddSJoseph Koshy 	}
10950cfab8ddSJoseph Koshy 
10960cfab8ddSJoseph Koshy 	pmc_config->pm_md.pm_iap.pm_iap_config |= cachestate;
10971fa7f10bSFabien Thomas 	pmc_config->pm_md.pm_iap.pm_iap_rsp = rsp;
10981fa7f10bSFabien Thomas 
10991fa7f10bSFabien Thomas 	return (0);
11001fa7f10bSFabien Thomas }
11011fa7f10bSFabien Thomas 
11021fa7f10bSFabien Thomas /*
11031fa7f10bSFabien Thomas  * Intel Uncore.
11041fa7f10bSFabien Thomas  */
11051fa7f10bSFabien Thomas 
11061fa7f10bSFabien Thomas static int
11071fa7f10bSFabien Thomas ucf_allocate_pmc(enum pmc_event pe, char *ctrspec,
11081fa7f10bSFabien Thomas     struct pmc_op_pmcallocate *pmc_config)
11091fa7f10bSFabien Thomas {
11101fa7f10bSFabien Thomas 	(void) pe;
11111fa7f10bSFabien Thomas 	(void) ctrspec;
11121fa7f10bSFabien Thomas 
11131fa7f10bSFabien Thomas 	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
11141fa7f10bSFabien Thomas 	pmc_config->pm_md.pm_ucf.pm_ucf_flags = 0;
11151fa7f10bSFabien Thomas 
11161fa7f10bSFabien Thomas 	return (0);
11171fa7f10bSFabien Thomas }
11181fa7f10bSFabien Thomas 
11191fa7f10bSFabien Thomas #define	UCP_KW_CMASK		"cmask"
11201fa7f10bSFabien Thomas #define	UCP_KW_EDGE		"edge"
11211fa7f10bSFabien Thomas #define	UCP_KW_INV		"inv"
11221fa7f10bSFabien Thomas 
11231fa7f10bSFabien Thomas static int
11241fa7f10bSFabien Thomas ucp_allocate_pmc(enum pmc_event pe, char *ctrspec,
11251fa7f10bSFabien Thomas     struct pmc_op_pmcallocate *pmc_config)
11261fa7f10bSFabien Thomas {
11271fa7f10bSFabien Thomas 	char *e, *p, *q;
11281fa7f10bSFabien Thomas 	int count, n;
11291fa7f10bSFabien Thomas 
11301fa7f10bSFabien Thomas 	(void) pe;
11311fa7f10bSFabien Thomas 
11321fa7f10bSFabien Thomas 	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE |
11331fa7f10bSFabien Thomas 	    PMC_CAP_QUALIFIER);
11341fa7f10bSFabien Thomas 	pmc_config->pm_md.pm_ucp.pm_ucp_config = 0;
11351fa7f10bSFabien Thomas 
11361fa7f10bSFabien Thomas 	/* Parse additional modifiers if present */
11371fa7f10bSFabien Thomas 	while ((p = strsep(&ctrspec, ",")) != NULL) {
11381fa7f10bSFabien Thomas 
11391fa7f10bSFabien Thomas 		n = 0;
11401fa7f10bSFabien Thomas 		if (KWPREFIXMATCH(p, UCP_KW_CMASK "=")) {
11411fa7f10bSFabien Thomas 			q = strchr(p, '=');
11421fa7f10bSFabien Thomas 			if (*++q == '\0') /* skip '=' */
11431fa7f10bSFabien Thomas 				return (-1);
11441fa7f10bSFabien Thomas 			count = strtol(q, &e, 0);
11451fa7f10bSFabien Thomas 			if (e == q || *e != '\0')
11461fa7f10bSFabien Thomas 				return (-1);
11471fa7f10bSFabien Thomas 			pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
11481fa7f10bSFabien Thomas 			pmc_config->pm_md.pm_ucp.pm_ucp_config |=
11491fa7f10bSFabien Thomas 			    UCP_CMASK(count);
11501fa7f10bSFabien Thomas 		} else if (KWMATCH(p, UCP_KW_EDGE)) {
11511fa7f10bSFabien Thomas 			pmc_config->pm_caps |= PMC_CAP_EDGE;
11521fa7f10bSFabien Thomas 		} else if (KWMATCH(p, UCP_KW_INV)) {
11531fa7f10bSFabien Thomas 			pmc_config->pm_caps |= PMC_CAP_INVERT;
11541fa7f10bSFabien Thomas 		} else
11551fa7f10bSFabien Thomas 			return (-1);
11561fa7f10bSFabien Thomas 
11571fa7f10bSFabien Thomas 		if (n < 0)	/* Parsing failed. */
11581fa7f10bSFabien Thomas 			return (-1);
11591fa7f10bSFabien Thomas 	}
11600cfab8ddSJoseph Koshy 
11610cfab8ddSJoseph Koshy 	return (0);
11620cfab8ddSJoseph Koshy }
11630cfab8ddSJoseph Koshy 
11640cfab8ddSJoseph Koshy /*
1165f263522aSJoseph Koshy  * AMD K8 PMCs.
1166f263522aSJoseph Koshy  *
1167f263522aSJoseph Koshy  * These are very similar to AMD K7 PMCs, but support more kinds of
1168f263522aSJoseph Koshy  * events.
1169f263522aSJoseph Koshy  */
1170f263522aSJoseph Koshy 
1171f263522aSJoseph Koshy static struct pmc_event_alias k8_aliases[] = {
1172f263522aSJoseph Koshy 	EV_ALIAS("branches",		"k8-fr-retired-taken-branches"),
1173f263522aSJoseph Koshy 	EV_ALIAS("branch-mispredicts",
1174f263522aSJoseph Koshy 	    "k8-fr-retired-taken-branches-mispredicted"),
1175f263522aSJoseph Koshy 	EV_ALIAS("cycles",		"tsc"),
1176f263522aSJoseph Koshy 	EV_ALIAS("dc-misses",		"k8-dc-miss"),
1177f263522aSJoseph Koshy 	EV_ALIAS("ic-misses",		"k8-ic-miss"),
1178f263522aSJoseph Koshy 	EV_ALIAS("instructions",	"k8-fr-retired-x86-instructions"),
1179f263522aSJoseph Koshy 	EV_ALIAS("interrupts",		"k8-fr-taken-hardware-interrupts"),
1180177a2f22SJoseph Koshy 	EV_ALIAS("unhalted-cycles",	"k8-bu-cpu-clk-unhalted"),
1181f263522aSJoseph Koshy 	EV_ALIAS(NULL, NULL)
1182f263522aSJoseph Koshy };
1183f263522aSJoseph Koshy 
1184f263522aSJoseph Koshy #define	__K8MASK(N,V) PMCMASK(N,(1 << (V)))
1185f263522aSJoseph Koshy 
1186f263522aSJoseph Koshy /*
1187f263522aSJoseph Koshy  * Parsing tables
1188f263522aSJoseph Koshy  */
1189f263522aSJoseph Koshy 
1190f263522aSJoseph Koshy /* fp dispatched fpu ops */
1191f263522aSJoseph Koshy static const struct pmc_masks k8_mask_fdfo[] = {
1192f263522aSJoseph Koshy 	__K8MASK(add-pipe-excluding-junk-ops,	0),
1193f263522aSJoseph Koshy 	__K8MASK(multiply-pipe-excluding-junk-ops,	1),
1194f263522aSJoseph Koshy 	__K8MASK(store-pipe-excluding-junk-ops,	2),
1195f263522aSJoseph Koshy 	__K8MASK(add-pipe-junk-ops,		3),
1196f263522aSJoseph Koshy 	__K8MASK(multiply-pipe-junk-ops,	4),
1197f263522aSJoseph Koshy 	__K8MASK(store-pipe-junk-ops,		5),
1198f263522aSJoseph Koshy 	NULLMASK
1199f263522aSJoseph Koshy };
1200f263522aSJoseph Koshy 
1201f263522aSJoseph Koshy /* ls segment register loads */
1202f263522aSJoseph Koshy static const struct pmc_masks k8_mask_lsrl[] = {
1203f263522aSJoseph Koshy 	__K8MASK(es,	0),
1204f263522aSJoseph Koshy 	__K8MASK(cs,	1),
1205f263522aSJoseph Koshy 	__K8MASK(ss,	2),
1206f263522aSJoseph Koshy 	__K8MASK(ds,	3),
1207f263522aSJoseph Koshy 	__K8MASK(fs,	4),
1208f263522aSJoseph Koshy 	__K8MASK(gs,	5),
1209f263522aSJoseph Koshy 	__K8MASK(hs,	6),
1210f263522aSJoseph Koshy 	NULLMASK
1211f263522aSJoseph Koshy };
1212f263522aSJoseph Koshy 
1213f263522aSJoseph Koshy /* ls locked operation */
1214f263522aSJoseph Koshy static const struct pmc_masks k8_mask_llo[] = {
1215f263522aSJoseph Koshy 	__K8MASK(locked-instructions,	0),
1216f263522aSJoseph Koshy 	__K8MASK(cycles-in-request,	1),
1217f263522aSJoseph Koshy 	__K8MASK(cycles-to-complete,	2),
1218f263522aSJoseph Koshy 	NULLMASK
1219f263522aSJoseph Koshy };
1220f263522aSJoseph Koshy 
1221f263522aSJoseph Koshy /* dc refill from {l2,system} and dc copyback */
1222f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dc[] = {
1223f263522aSJoseph Koshy 	__K8MASK(invalid,	0),
1224f263522aSJoseph Koshy 	__K8MASK(shared,	1),
1225f263522aSJoseph Koshy 	__K8MASK(exclusive,	2),
1226f263522aSJoseph Koshy 	__K8MASK(owner,		3),
1227f263522aSJoseph Koshy 	__K8MASK(modified,	4),
1228f263522aSJoseph Koshy 	NULLMASK
1229f263522aSJoseph Koshy };
1230f263522aSJoseph Koshy 
1231f263522aSJoseph Koshy /* dc one bit ecc error */
1232f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dobee[] = {
1233f263522aSJoseph Koshy 	__K8MASK(scrubber,	0),
1234f263522aSJoseph Koshy 	__K8MASK(piggyback,	1),
1235f263522aSJoseph Koshy 	NULLMASK
1236f263522aSJoseph Koshy };
1237f263522aSJoseph Koshy 
1238f263522aSJoseph Koshy /* dc dispatched prefetch instructions */
1239f263522aSJoseph Koshy static const struct pmc_masks k8_mask_ddpi[] = {
1240f263522aSJoseph Koshy 	__K8MASK(load,	0),
1241f263522aSJoseph Koshy 	__K8MASK(store,	1),
1242f263522aSJoseph Koshy 	__K8MASK(nta,	2),
1243f263522aSJoseph Koshy 	NULLMASK
1244f263522aSJoseph Koshy };
1245f263522aSJoseph Koshy 
1246f263522aSJoseph Koshy /* dc dcache accesses by locks */
1247f263522aSJoseph Koshy static const struct pmc_masks k8_mask_dabl[] = {
1248f263522aSJoseph Koshy 	__K8MASK(accesses,	0),
1249f263522aSJoseph Koshy 	__K8MASK(misses,	1),
1250f263522aSJoseph Koshy 	NULLMASK
1251f263522aSJoseph Koshy };
1252f263522aSJoseph Koshy 
1253f263522aSJoseph Koshy /* bu internal l2 request */
1254f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bilr[] = {
1255f263522aSJoseph Koshy 	__K8MASK(ic-fill,	0),
1256f263522aSJoseph Koshy 	__K8MASK(dc-fill,	1),
1257f263522aSJoseph Koshy 	__K8MASK(tlb-reload,	2),
1258f263522aSJoseph Koshy 	__K8MASK(tag-snoop,	3),
1259f263522aSJoseph Koshy 	__K8MASK(cancelled,	4),
1260f263522aSJoseph Koshy 	NULLMASK
1261f263522aSJoseph Koshy };
1262f263522aSJoseph Koshy 
1263f263522aSJoseph Koshy /* bu fill request l2 miss */
1264f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bfrlm[] = {
1265f263522aSJoseph Koshy 	__K8MASK(ic-fill,	0),
1266f263522aSJoseph Koshy 	__K8MASK(dc-fill,	1),
1267f263522aSJoseph Koshy 	__K8MASK(tlb-reload,	2),
1268f263522aSJoseph Koshy 	NULLMASK
1269f263522aSJoseph Koshy };
1270f263522aSJoseph Koshy 
1271f263522aSJoseph Koshy /* bu fill into l2 */
1272f263522aSJoseph Koshy static const struct pmc_masks k8_mask_bfil[] = {
1273f263522aSJoseph Koshy 	__K8MASK(dirty-l2-victim,	0),
1274f263522aSJoseph Koshy 	__K8MASK(victim-from-l2,	1),
1275f263522aSJoseph Koshy 	NULLMASK
1276f263522aSJoseph Koshy };
1277f263522aSJoseph Koshy 
1278f263522aSJoseph Koshy /* fr retired fpu instructions */
1279f263522aSJoseph Koshy static const struct pmc_masks k8_mask_frfi[] = {
1280f263522aSJoseph Koshy 	__K8MASK(x87,			0),
1281f263522aSJoseph Koshy 	__K8MASK(mmx-3dnow,		1),
1282f263522aSJoseph Koshy 	__K8MASK(packed-sse-sse2,	2),
1283f263522aSJoseph Koshy 	__K8MASK(scalar-sse-sse2,	3),
1284f263522aSJoseph Koshy 	NULLMASK
1285f263522aSJoseph Koshy };
1286f263522aSJoseph Koshy 
1287f263522aSJoseph Koshy /* fr retired fastpath double op instructions */
1288f263522aSJoseph Koshy static const struct pmc_masks k8_mask_frfdoi[] = {
1289f263522aSJoseph Koshy 	__K8MASK(low-op-pos-0,		0),
1290f263522aSJoseph Koshy 	__K8MASK(low-op-pos-1,		1),
1291f263522aSJoseph Koshy 	__K8MASK(low-op-pos-2,		2),
1292f263522aSJoseph Koshy 	NULLMASK
1293f263522aSJoseph Koshy };
1294f263522aSJoseph Koshy 
1295f263522aSJoseph Koshy /* fr fpu exceptions */
1296f263522aSJoseph Koshy static const struct pmc_masks k8_mask_ffe[] = {
1297f263522aSJoseph Koshy 	__K8MASK(x87-reclass-microfaults,	0),
1298f263522aSJoseph Koshy 	__K8MASK(sse-retype-microfaults,	1),
1299f263522aSJoseph Koshy 	__K8MASK(sse-reclass-microfaults,	2),
1300f263522aSJoseph Koshy 	__K8MASK(sse-and-x87-microtraps,	3),
1301f263522aSJoseph Koshy 	NULLMASK
1302f263522aSJoseph Koshy };
1303f263522aSJoseph Koshy 
1304f263522aSJoseph Koshy /* nb memory controller page access event */
1305f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmcpae[] = {
1306f263522aSJoseph Koshy 	__K8MASK(page-hit,	0),
1307f263522aSJoseph Koshy 	__K8MASK(page-miss,	1),
1308f263522aSJoseph Koshy 	__K8MASK(page-conflict,	2),
1309f263522aSJoseph Koshy 	NULLMASK
1310f263522aSJoseph Koshy };
1311f263522aSJoseph Koshy 
1312f263522aSJoseph Koshy /* nb memory controller turnaround */
1313f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmct[] = {
1314f263522aSJoseph Koshy 	__K8MASK(dimm-turnaround,		0),
1315f263522aSJoseph Koshy 	__K8MASK(read-to-write-turnaround,	1),
1316f263522aSJoseph Koshy 	__K8MASK(write-to-read-turnaround,	2),
1317f263522aSJoseph Koshy 	NULLMASK
1318f263522aSJoseph Koshy };
1319f263522aSJoseph Koshy 
1320f263522aSJoseph Koshy /* nb memory controller bypass saturation */
1321f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nmcbs[] = {
1322f263522aSJoseph Koshy 	__K8MASK(memory-controller-hi-pri-bypass,	0),
1323f263522aSJoseph Koshy 	__K8MASK(memory-controller-lo-pri-bypass,	1),
1324f263522aSJoseph Koshy 	__K8MASK(dram-controller-interface-bypass,	2),
1325f263522aSJoseph Koshy 	__K8MASK(dram-controller-queue-bypass,		3),
1326f263522aSJoseph Koshy 	NULLMASK
1327f263522aSJoseph Koshy };
1328f263522aSJoseph Koshy 
1329f263522aSJoseph Koshy /* nb sized commands */
1330f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nsc[] = {
1331f263522aSJoseph Koshy 	__K8MASK(nonpostwrszbyte,	0),
1332f263522aSJoseph Koshy 	__K8MASK(nonpostwrszdword,	1),
1333f263522aSJoseph Koshy 	__K8MASK(postwrszbyte,		2),
1334f263522aSJoseph Koshy 	__K8MASK(postwrszdword,		3),
1335f263522aSJoseph Koshy 	__K8MASK(rdszbyte,		4),
1336f263522aSJoseph Koshy 	__K8MASK(rdszdword,		5),
1337f263522aSJoseph Koshy 	__K8MASK(rdmodwr,		6),
1338f263522aSJoseph Koshy 	NULLMASK
1339f263522aSJoseph Koshy };
1340f263522aSJoseph Koshy 
1341f263522aSJoseph Koshy /* nb probe result */
1342f263522aSJoseph Koshy static const struct pmc_masks k8_mask_npr[] = {
1343f263522aSJoseph Koshy 	__K8MASK(probe-miss,		0),
1344f263522aSJoseph Koshy 	__K8MASK(probe-hit,		1),
1345f263522aSJoseph Koshy 	__K8MASK(probe-hit-dirty-no-memory-cancel, 2),
1346f263522aSJoseph Koshy 	__K8MASK(probe-hit-dirty-with-memory-cancel, 3),
1347f263522aSJoseph Koshy 	NULLMASK
1348f263522aSJoseph Koshy };
1349f263522aSJoseph Koshy 
1350f263522aSJoseph Koshy /* nb hypertransport bus bandwidth */
1351f263522aSJoseph Koshy static const struct pmc_masks k8_mask_nhbb[] = { /* HT bus bandwidth */
1352f263522aSJoseph Koshy 	__K8MASK(command,	0),
1353f263522aSJoseph Koshy 	__K8MASK(data,	1),
1354f263522aSJoseph Koshy 	__K8MASK(buffer-release, 2),
1355f263522aSJoseph Koshy 	__K8MASK(nop,	3),
1356f263522aSJoseph Koshy 	NULLMASK
1357f263522aSJoseph Koshy };
1358f263522aSJoseph Koshy 
1359f263522aSJoseph Koshy #undef	__K8MASK
1360f263522aSJoseph Koshy 
1361f263522aSJoseph Koshy #define	K8_KW_COUNT	"count"
1362f263522aSJoseph Koshy #define	K8_KW_EDGE	"edge"
1363f263522aSJoseph Koshy #define	K8_KW_INV	"inv"
1364f263522aSJoseph Koshy #define	K8_KW_MASK	"mask"
1365f263522aSJoseph Koshy #define	K8_KW_OS	"os"
1366f263522aSJoseph Koshy #define	K8_KW_USR	"usr"
1367f263522aSJoseph Koshy 
1368f263522aSJoseph Koshy static int
1369f263522aSJoseph Koshy k8_allocate_pmc(enum pmc_event pe, char *ctrspec,
1370f263522aSJoseph Koshy     struct pmc_op_pmcallocate *pmc_config)
1371f263522aSJoseph Koshy {
1372f263522aSJoseph Koshy 	char		*e, *p, *q;
1373f263522aSJoseph Koshy 	int		n;
13741e862e5aSFabien Thomas 	uint32_t	count;
13751e862e5aSFabien Thomas 	uint64_t	evmask;
1376f263522aSJoseph Koshy 	const struct pmc_masks	*pm, *pmask;
1377f263522aSJoseph Koshy 
1378789140c0SJoseph Koshy 	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
1379f263522aSJoseph Koshy 	pmc_config->pm_md.pm_amd.pm_amd_config = 0;
1380f263522aSJoseph Koshy 
1381f263522aSJoseph Koshy 	pmask = NULL;
1382f263522aSJoseph Koshy 	evmask = 0;
1383f263522aSJoseph Koshy 
1384f263522aSJoseph Koshy #define	__K8SETMASK(M) pmask = k8_mask_##M
1385f263522aSJoseph Koshy 
1386f263522aSJoseph Koshy 	/* setup parsing tables */
1387f263522aSJoseph Koshy 	switch (pe) {
1388f263522aSJoseph Koshy 	case PMC_EV_K8_FP_DISPATCHED_FPU_OPS:
1389f263522aSJoseph Koshy 		__K8SETMASK(fdfo);
1390f263522aSJoseph Koshy 		break;
1391f263522aSJoseph Koshy 	case PMC_EV_K8_LS_SEGMENT_REGISTER_LOAD:
1392f263522aSJoseph Koshy 		__K8SETMASK(lsrl);
1393f263522aSJoseph Koshy 		break;
1394f263522aSJoseph Koshy 	case PMC_EV_K8_LS_LOCKED_OPERATION:
1395f263522aSJoseph Koshy 		__K8SETMASK(llo);
1396f263522aSJoseph Koshy 		break;
1397f263522aSJoseph Koshy 	case PMC_EV_K8_DC_REFILL_FROM_L2:
1398f263522aSJoseph Koshy 	case PMC_EV_K8_DC_REFILL_FROM_SYSTEM:
1399f263522aSJoseph Koshy 	case PMC_EV_K8_DC_COPYBACK:
1400f263522aSJoseph Koshy 		__K8SETMASK(dc);
1401f263522aSJoseph Koshy 		break;
1402f263522aSJoseph Koshy 	case PMC_EV_K8_DC_ONE_BIT_ECC_ERROR:
1403f263522aSJoseph Koshy 		__K8SETMASK(dobee);
1404f263522aSJoseph Koshy 		break;
1405f263522aSJoseph Koshy 	case PMC_EV_K8_DC_DISPATCHED_PREFETCH_INSTRUCTIONS:
1406f263522aSJoseph Koshy 		__K8SETMASK(ddpi);
1407f263522aSJoseph Koshy 		break;
1408f263522aSJoseph Koshy 	case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS:
1409f263522aSJoseph Koshy 		__K8SETMASK(dabl);
1410f263522aSJoseph Koshy 		break;
1411f263522aSJoseph Koshy 	case PMC_EV_K8_BU_INTERNAL_L2_REQUEST:
1412f263522aSJoseph Koshy 		__K8SETMASK(bilr);
1413f263522aSJoseph Koshy 		break;
1414f263522aSJoseph Koshy 	case PMC_EV_K8_BU_FILL_REQUEST_L2_MISS:
1415f263522aSJoseph Koshy 		__K8SETMASK(bfrlm);
1416f263522aSJoseph Koshy 		break;
1417f263522aSJoseph Koshy 	case PMC_EV_K8_BU_FILL_INTO_L2:
1418f263522aSJoseph Koshy 		__K8SETMASK(bfil);
1419f263522aSJoseph Koshy 		break;
1420f263522aSJoseph Koshy 	case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS:
1421f263522aSJoseph Koshy 		__K8SETMASK(frfi);
1422f263522aSJoseph Koshy 		break;
1423f263522aSJoseph Koshy 	case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS:
1424f263522aSJoseph Koshy 		__K8SETMASK(frfdoi);
1425f263522aSJoseph Koshy 		break;
1426f263522aSJoseph Koshy 	case PMC_EV_K8_FR_FPU_EXCEPTIONS:
1427f263522aSJoseph Koshy 		__K8SETMASK(ffe);
1428f263522aSJoseph Koshy 		break;
1429f263522aSJoseph Koshy 	case PMC_EV_K8_NB_MEMORY_CONTROLLER_PAGE_ACCESS_EVENT:
1430f263522aSJoseph Koshy 		__K8SETMASK(nmcpae);
1431f263522aSJoseph Koshy 		break;
1432f263522aSJoseph Koshy 	case PMC_EV_K8_NB_MEMORY_CONTROLLER_TURNAROUND:
1433f263522aSJoseph Koshy 		__K8SETMASK(nmct);
1434f263522aSJoseph Koshy 		break;
1435f263522aSJoseph Koshy 	case PMC_EV_K8_NB_MEMORY_CONTROLLER_BYPASS_SATURATION:
1436f263522aSJoseph Koshy 		__K8SETMASK(nmcbs);
1437f263522aSJoseph Koshy 		break;
1438f263522aSJoseph Koshy 	case PMC_EV_K8_NB_SIZED_COMMANDS:
1439f263522aSJoseph Koshy 		__K8SETMASK(nsc);
1440f263522aSJoseph Koshy 		break;
1441f263522aSJoseph Koshy 	case PMC_EV_K8_NB_PROBE_RESULT:
1442f263522aSJoseph Koshy 		__K8SETMASK(npr);
1443f263522aSJoseph Koshy 		break;
1444f263522aSJoseph Koshy 	case PMC_EV_K8_NB_HT_BUS0_BANDWIDTH:
1445f263522aSJoseph Koshy 	case PMC_EV_K8_NB_HT_BUS1_BANDWIDTH:
1446f263522aSJoseph Koshy 	case PMC_EV_K8_NB_HT_BUS2_BANDWIDTH:
1447f263522aSJoseph Koshy 		__K8SETMASK(nhbb);
1448f263522aSJoseph Koshy 		break;
1449f263522aSJoseph Koshy 
1450f263522aSJoseph Koshy 	default:
1451f263522aSJoseph Koshy 		break;		/* no options defined */
1452f263522aSJoseph Koshy 	}
1453f263522aSJoseph Koshy 
1454f263522aSJoseph Koshy 	while ((p = strsep(&ctrspec, ",")) != NULL) {
1455f263522aSJoseph Koshy 		if (KWPREFIXMATCH(p, K8_KW_COUNT "=")) {
1456f263522aSJoseph Koshy 			q = strchr(p, '=');
1457f263522aSJoseph Koshy 			if (*++q == '\0') /* skip '=' */
1458aa342b1fSJoseph Koshy 				return (-1);
1459f263522aSJoseph Koshy 
1460f263522aSJoseph Koshy 			count = strtol(q, &e, 0);
1461f263522aSJoseph Koshy 			if (e == q || *e != '\0')
1462aa342b1fSJoseph Koshy 				return (-1);
1463f263522aSJoseph Koshy 
1464f263522aSJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
1465f263522aSJoseph Koshy 			pmc_config->pm_md.pm_amd.pm_amd_config |=
1466f263522aSJoseph Koshy 			    AMD_PMC_TO_COUNTER(count);
1467f263522aSJoseph Koshy 
1468f263522aSJoseph Koshy 		} else if (KWMATCH(p, K8_KW_EDGE)) {
1469f263522aSJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_EDGE;
1470f263522aSJoseph Koshy 		} else if (KWMATCH(p, K8_KW_INV)) {
1471f263522aSJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_INVERT;
1472f263522aSJoseph Koshy 		} else if (KWPREFIXMATCH(p, K8_KW_MASK "=")) {
1473f263522aSJoseph Koshy 			if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0)
1474aa342b1fSJoseph Koshy 				return (-1);
1475f263522aSJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
1476f263522aSJoseph Koshy 		} else if (KWMATCH(p, K8_KW_OS)) {
1477f263522aSJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_SYSTEM;
1478f263522aSJoseph Koshy 		} else if (KWMATCH(p, K8_KW_USR)) {
1479f263522aSJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_USER;
1480f263522aSJoseph Koshy 		} else
1481aa342b1fSJoseph Koshy 			return (-1);
1482f263522aSJoseph Koshy 	}
1483f263522aSJoseph Koshy 
1484f263522aSJoseph Koshy 	/* other post processing */
1485f263522aSJoseph Koshy 	switch (pe) {
1486f263522aSJoseph Koshy 	case PMC_EV_K8_FP_DISPATCHED_FPU_OPS:
1487f263522aSJoseph Koshy 	case PMC_EV_K8_FP_CYCLES_WITH_NO_FPU_OPS_RETIRED:
1488f263522aSJoseph Koshy 	case PMC_EV_K8_FP_DISPATCHED_FPU_FAST_FLAG_OPS:
1489f263522aSJoseph Koshy 	case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS:
1490f263522aSJoseph Koshy 	case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS:
1491f263522aSJoseph Koshy 	case PMC_EV_K8_FR_FPU_EXCEPTIONS:
1492f263522aSJoseph Koshy 		/* XXX only available in rev B and later */
1493f263522aSJoseph Koshy 		break;
1494f263522aSJoseph Koshy 	case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS:
1495f263522aSJoseph Koshy 		/* XXX only available in rev C and later */
1496f263522aSJoseph Koshy 		break;
1497f263522aSJoseph Koshy 	case PMC_EV_K8_LS_LOCKED_OPERATION:
1498f263522aSJoseph Koshy 		/* XXX CPU Rev A,B evmask is to be zero */
1499f263522aSJoseph Koshy 		if (evmask & (evmask - 1)) /* > 1 bit set */
1500aa342b1fSJoseph Koshy 			return (-1);
1501f263522aSJoseph Koshy 		if (evmask == 0) {
1502f263522aSJoseph Koshy 			evmask = 0x01; /* Rev C and later: #instrs */
1503f263522aSJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
1504f263522aSJoseph Koshy 		}
1505f263522aSJoseph Koshy 		break;
1506f263522aSJoseph Koshy 	default:
1507f263522aSJoseph Koshy 		if (evmask == 0 && pmask != NULL) {
1508f263522aSJoseph Koshy 			for (pm = pmask; pm->pm_name; pm++)
1509f263522aSJoseph Koshy 				evmask |= pm->pm_value;
1510f263522aSJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
1511f263522aSJoseph Koshy 		}
1512f263522aSJoseph Koshy 	}
1513f263522aSJoseph Koshy 
1514f263522aSJoseph Koshy 	if (pmc_config->pm_caps & PMC_CAP_QUALIFIER)
1515f263522aSJoseph Koshy 		pmc_config->pm_md.pm_amd.pm_amd_config =
1516f263522aSJoseph Koshy 		    AMD_PMC_TO_UNITMASK(evmask);
1517f263522aSJoseph Koshy 
1518aa342b1fSJoseph Koshy 	return (0);
1519f263522aSJoseph Koshy }
1520f263522aSJoseph Koshy 
1521f263522aSJoseph Koshy #endif
1522f263522aSJoseph Koshy 
152386a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__)
1524f263522aSJoseph Koshy 
1525ebccf1e3SJoseph Koshy /*
1526ebccf1e3SJoseph Koshy  * Intel P4 PMCs
1527ebccf1e3SJoseph Koshy  */
1528ebccf1e3SJoseph Koshy 
1529ebccf1e3SJoseph Koshy static struct pmc_event_alias p4_aliases[] = {
1530d56c5d4bSJoseph Koshy 	EV_ALIAS("branches",		"p4-branch-retired,mask=mmtp+mmtm"),
1531d56c5d4bSJoseph Koshy 	EV_ALIAS("branch-mispredicts",	"p4-mispred-branch-retired"),
1532ebccf1e3SJoseph Koshy 	EV_ALIAS("cycles",		"tsc"),
1533d56c5d4bSJoseph Koshy 	EV_ALIAS("instructions",
1534d56c5d4bSJoseph Koshy 	    "p4-instr-retired,mask=nbogusntag+nbogustag"),
1535177a2f22SJoseph Koshy 	EV_ALIAS("unhalted-cycles",	"p4-global-power-events"),
1536ebccf1e3SJoseph Koshy 	EV_ALIAS(NULL, NULL)
1537ebccf1e3SJoseph Koshy };
1538ebccf1e3SJoseph Koshy 
1539ebccf1e3SJoseph Koshy #define	P4_KW_ACTIVE	"active"
1540ebccf1e3SJoseph Koshy #define	P4_KW_ACTIVE_ANY "any"
1541ebccf1e3SJoseph Koshy #define	P4_KW_ACTIVE_BOTH "both"
1542ebccf1e3SJoseph Koshy #define	P4_KW_ACTIVE_NONE "none"
1543ebccf1e3SJoseph Koshy #define	P4_KW_ACTIVE_SINGLE "single"
1544ebccf1e3SJoseph Koshy #define	P4_KW_BUSREQTYPE "busreqtype"
1545ebccf1e3SJoseph Koshy #define	P4_KW_CASCADE	"cascade"
1546ebccf1e3SJoseph Koshy #define	P4_KW_EDGE	"edge"
1547ebccf1e3SJoseph Koshy #define	P4_KW_INV	"complement"
1548ebccf1e3SJoseph Koshy #define	P4_KW_OS	"os"
1549ebccf1e3SJoseph Koshy #define	P4_KW_MASK	"mask"
1550ebccf1e3SJoseph Koshy #define	P4_KW_PRECISE	"precise"
1551ebccf1e3SJoseph Koshy #define	P4_KW_TAG	"tag"
1552ebccf1e3SJoseph Koshy #define	P4_KW_THRESHOLD	"threshold"
1553ebccf1e3SJoseph Koshy #define	P4_KW_USR	"usr"
1554ebccf1e3SJoseph Koshy 
1555ebccf1e3SJoseph Koshy #define	__P4MASK(N,V) PMCMASK(N, (1 << (V)))
1556ebccf1e3SJoseph Koshy 
1557ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_tcdm[] = { /* tc deliver mode */
1558ebccf1e3SJoseph Koshy 	__P4MASK(dd, 0),
1559ebccf1e3SJoseph Koshy 	__P4MASK(db, 1),
1560ebccf1e3SJoseph Koshy 	__P4MASK(di, 2),
1561ebccf1e3SJoseph Koshy 	__P4MASK(bd, 3),
1562ebccf1e3SJoseph Koshy 	__P4MASK(bb, 4),
1563ebccf1e3SJoseph Koshy 	__P4MASK(bi, 5),
1564ebccf1e3SJoseph Koshy 	__P4MASK(id, 6),
1565ebccf1e3SJoseph Koshy 	__P4MASK(ib, 7),
1566ebccf1e3SJoseph Koshy 	NULLMASK
1567ebccf1e3SJoseph Koshy };
1568ebccf1e3SJoseph Koshy 
1569ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_bfr[] = { /* bpu fetch request */
1570ebccf1e3SJoseph Koshy 	__P4MASK(tcmiss, 0),
1571ebccf1e3SJoseph Koshy 	NULLMASK,
1572ebccf1e3SJoseph Koshy };
1573ebccf1e3SJoseph Koshy 
1574ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ir[] = { /* itlb reference */
1575ebccf1e3SJoseph Koshy 	__P4MASK(hit, 0),
1576ebccf1e3SJoseph Koshy 	__P4MASK(miss, 1),
1577ebccf1e3SJoseph Koshy 	__P4MASK(hit-uc, 2),
1578ebccf1e3SJoseph Koshy 	NULLMASK
1579ebccf1e3SJoseph Koshy };
1580ebccf1e3SJoseph Koshy 
1581ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_memcan[] = { /* memory cancel */
1582ebccf1e3SJoseph Koshy 	__P4MASK(st-rb-full, 2),
1583ebccf1e3SJoseph Koshy 	__P4MASK(64k-conf, 3),
1584ebccf1e3SJoseph Koshy 	NULLMASK
1585ebccf1e3SJoseph Koshy };
1586ebccf1e3SJoseph Koshy 
1587ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_memcomp[] = { /* memory complete */
1588ebccf1e3SJoseph Koshy 	__P4MASK(lsc, 0),
1589ebccf1e3SJoseph Koshy 	__P4MASK(ssc, 1),
1590ebccf1e3SJoseph Koshy 	NULLMASK
1591ebccf1e3SJoseph Koshy };
1592ebccf1e3SJoseph Koshy 
1593ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_lpr[] = { /* load port replay */
1594ebccf1e3SJoseph Koshy 	__P4MASK(split-ld, 1),
1595ebccf1e3SJoseph Koshy 	NULLMASK
1596ebccf1e3SJoseph Koshy };
1597ebccf1e3SJoseph Koshy 
1598ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_spr[] = { /* store port replay */
1599ebccf1e3SJoseph Koshy 	__P4MASK(split-st, 1),
1600ebccf1e3SJoseph Koshy 	NULLMASK
1601ebccf1e3SJoseph Koshy };
1602ebccf1e3SJoseph Koshy 
1603ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_mlr[] = { /* mob load replay */
1604ebccf1e3SJoseph Koshy 	__P4MASK(no-sta, 1),
1605ebccf1e3SJoseph Koshy 	__P4MASK(no-std, 3),
1606ebccf1e3SJoseph Koshy 	__P4MASK(partial-data, 4),
1607ebccf1e3SJoseph Koshy 	__P4MASK(unalgn-addr, 5),
1608ebccf1e3SJoseph Koshy 	NULLMASK
1609ebccf1e3SJoseph Koshy };
1610ebccf1e3SJoseph Koshy 
1611ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_pwt[] = { /* page walk type */
1612ebccf1e3SJoseph Koshy 	__P4MASK(dtmiss, 0),
1613ebccf1e3SJoseph Koshy 	__P4MASK(itmiss, 1),
1614ebccf1e3SJoseph Koshy 	NULLMASK
1615ebccf1e3SJoseph Koshy };
1616ebccf1e3SJoseph Koshy 
1617ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_bcr[] = { /* bsq cache reference */
1618ebccf1e3SJoseph Koshy 	__P4MASK(rd-2ndl-hits, 0),
1619ebccf1e3SJoseph Koshy 	__P4MASK(rd-2ndl-hite, 1),
1620ebccf1e3SJoseph Koshy 	__P4MASK(rd-2ndl-hitm, 2),
1621ebccf1e3SJoseph Koshy 	__P4MASK(rd-3rdl-hits, 3),
1622ebccf1e3SJoseph Koshy 	__P4MASK(rd-3rdl-hite, 4),
1623ebccf1e3SJoseph Koshy 	__P4MASK(rd-3rdl-hitm, 5),
1624ebccf1e3SJoseph Koshy 	__P4MASK(rd-2ndl-miss, 8),
1625ebccf1e3SJoseph Koshy 	__P4MASK(rd-3rdl-miss, 9),
1626ebccf1e3SJoseph Koshy 	__P4MASK(wr-2ndl-miss, 10),
1627ebccf1e3SJoseph Koshy 	NULLMASK
1628ebccf1e3SJoseph Koshy };
1629ebccf1e3SJoseph Koshy 
1630ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ia[] = { /* ioq allocation */
1631ebccf1e3SJoseph Koshy 	__P4MASK(all-read, 5),
1632ebccf1e3SJoseph Koshy 	__P4MASK(all-write, 6),
1633ebccf1e3SJoseph Koshy 	__P4MASK(mem-uc, 7),
1634ebccf1e3SJoseph Koshy 	__P4MASK(mem-wc, 8),
1635ebccf1e3SJoseph Koshy 	__P4MASK(mem-wt, 9),
1636ebccf1e3SJoseph Koshy 	__P4MASK(mem-wp, 10),
1637ebccf1e3SJoseph Koshy 	__P4MASK(mem-wb, 11),
1638ebccf1e3SJoseph Koshy 	__P4MASK(own, 13),
1639ebccf1e3SJoseph Koshy 	__P4MASK(other, 14),
1640ebccf1e3SJoseph Koshy 	__P4MASK(prefetch, 15),
1641ebccf1e3SJoseph Koshy 	NULLMASK
1642ebccf1e3SJoseph Koshy };
1643ebccf1e3SJoseph Koshy 
1644ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_iae[] = { /* ioq active entries */
1645ebccf1e3SJoseph Koshy 	__P4MASK(all-read, 5),
1646ebccf1e3SJoseph Koshy 	__P4MASK(all-write, 6),
1647ebccf1e3SJoseph Koshy 	__P4MASK(mem-uc, 7),
1648ebccf1e3SJoseph Koshy 	__P4MASK(mem-wc, 8),
1649ebccf1e3SJoseph Koshy 	__P4MASK(mem-wt, 9),
1650ebccf1e3SJoseph Koshy 	__P4MASK(mem-wp, 10),
1651ebccf1e3SJoseph Koshy 	__P4MASK(mem-wb, 11),
1652ebccf1e3SJoseph Koshy 	__P4MASK(own, 13),
1653ebccf1e3SJoseph Koshy 	__P4MASK(other, 14),
1654ebccf1e3SJoseph Koshy 	__P4MASK(prefetch, 15),
1655ebccf1e3SJoseph Koshy 	NULLMASK
1656ebccf1e3SJoseph Koshy };
1657ebccf1e3SJoseph Koshy 
1658ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_fda[] = { /* fsb data activity */
1659ebccf1e3SJoseph Koshy 	__P4MASK(drdy-drv, 0),
1660ebccf1e3SJoseph Koshy 	__P4MASK(drdy-own, 1),
1661ebccf1e3SJoseph Koshy 	__P4MASK(drdy-other, 2),
1662ebccf1e3SJoseph Koshy 	__P4MASK(dbsy-drv, 3),
1663ebccf1e3SJoseph Koshy 	__P4MASK(dbsy-own, 4),
1664ebccf1e3SJoseph Koshy 	__P4MASK(dbsy-other, 5),
1665ebccf1e3SJoseph Koshy 	NULLMASK
1666ebccf1e3SJoseph Koshy };
1667ebccf1e3SJoseph Koshy 
1668ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ba[] = { /* bsq allocation */
1669ebccf1e3SJoseph Koshy 	__P4MASK(req-type0, 0),
1670ebccf1e3SJoseph Koshy 	__P4MASK(req-type1, 1),
1671ebccf1e3SJoseph Koshy 	__P4MASK(req-len0, 2),
1672ebccf1e3SJoseph Koshy 	__P4MASK(req-len1, 3),
1673ebccf1e3SJoseph Koshy 	__P4MASK(req-io-type, 5),
1674ebccf1e3SJoseph Koshy 	__P4MASK(req-lock-type, 6),
1675ebccf1e3SJoseph Koshy 	__P4MASK(req-cache-type, 7),
1676ebccf1e3SJoseph Koshy 	__P4MASK(req-split-type, 8),
1677ebccf1e3SJoseph Koshy 	__P4MASK(req-dem-type, 9),
1678ebccf1e3SJoseph Koshy 	__P4MASK(req-ord-type, 10),
1679ebccf1e3SJoseph Koshy 	__P4MASK(mem-type0, 11),
1680ebccf1e3SJoseph Koshy 	__P4MASK(mem-type1, 12),
1681ebccf1e3SJoseph Koshy 	__P4MASK(mem-type2, 13),
1682ebccf1e3SJoseph Koshy 	NULLMASK
1683ebccf1e3SJoseph Koshy };
1684ebccf1e3SJoseph Koshy 
1685ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_sia[] = { /* sse input assist */
1686ebccf1e3SJoseph Koshy 	__P4MASK(all, 15),
1687ebccf1e3SJoseph Koshy 	NULLMASK
1688ebccf1e3SJoseph Koshy };
1689ebccf1e3SJoseph Koshy 
1690ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_psu[] = { /* packed sp uop */
1691ebccf1e3SJoseph Koshy 	__P4MASK(all, 15),
1692ebccf1e3SJoseph Koshy 	NULLMASK
1693ebccf1e3SJoseph Koshy };
1694ebccf1e3SJoseph Koshy 
1695ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_pdu[] = { /* packed dp uop */
1696ebccf1e3SJoseph Koshy 	__P4MASK(all, 15),
1697ebccf1e3SJoseph Koshy 	NULLMASK
1698ebccf1e3SJoseph Koshy };
1699ebccf1e3SJoseph Koshy 
1700ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ssu[] = { /* scalar sp uop */
1701ebccf1e3SJoseph Koshy 	__P4MASK(all, 15),
1702ebccf1e3SJoseph Koshy 	NULLMASK
1703ebccf1e3SJoseph Koshy };
1704ebccf1e3SJoseph Koshy 
1705ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_sdu[] = { /* scalar dp uop */
1706ebccf1e3SJoseph Koshy 	__P4MASK(all, 15),
1707ebccf1e3SJoseph Koshy 	NULLMASK
1708ebccf1e3SJoseph Koshy };
1709ebccf1e3SJoseph Koshy 
1710ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_64bmu[] = { /* 64 bit mmx uop */
1711ebccf1e3SJoseph Koshy 	__P4MASK(all, 15),
1712ebccf1e3SJoseph Koshy 	NULLMASK
1713ebccf1e3SJoseph Koshy };
1714ebccf1e3SJoseph Koshy 
1715ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_128bmu[] = { /* 128 bit mmx uop */
1716ebccf1e3SJoseph Koshy 	__P4MASK(all, 15),
1717ebccf1e3SJoseph Koshy 	NULLMASK
1718ebccf1e3SJoseph Koshy };
1719ebccf1e3SJoseph Koshy 
1720ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xfu[] = { /* X87 fp uop */
1721ebccf1e3SJoseph Koshy 	__P4MASK(all, 15),
1722ebccf1e3SJoseph Koshy 	NULLMASK
1723ebccf1e3SJoseph Koshy };
1724ebccf1e3SJoseph Koshy 
1725ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xsmu[] = { /* x87 simd moves uop */
1726ebccf1e3SJoseph Koshy 	__P4MASK(allp0, 3),
1727ebccf1e3SJoseph Koshy 	__P4MASK(allp2, 4),
1728ebccf1e3SJoseph Koshy 	NULLMASK
1729ebccf1e3SJoseph Koshy };
1730ebccf1e3SJoseph Koshy 
1731ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_gpe[] = { /* global power events */
1732ebccf1e3SJoseph Koshy 	__P4MASK(running, 0),
1733ebccf1e3SJoseph Koshy 	NULLMASK
1734ebccf1e3SJoseph Koshy };
1735ebccf1e3SJoseph Koshy 
1736ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_tmx[] = { /* TC ms xfer */
1737ebccf1e3SJoseph Koshy 	__P4MASK(cisc, 0),
1738ebccf1e3SJoseph Koshy 	NULLMASK
1739ebccf1e3SJoseph Koshy };
1740ebccf1e3SJoseph Koshy 
1741ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_uqw[] = { /* uop queue writes */
1742ebccf1e3SJoseph Koshy 	__P4MASK(from-tc-build, 0),
1743ebccf1e3SJoseph Koshy 	__P4MASK(from-tc-deliver, 1),
1744ebccf1e3SJoseph Koshy 	__P4MASK(from-rom, 2),
1745ebccf1e3SJoseph Koshy 	NULLMASK
1746ebccf1e3SJoseph Koshy };
1747ebccf1e3SJoseph Koshy 
1748d56c5d4bSJoseph Koshy static const struct pmc_masks p4_mask_rmbt[] = {
1749d56c5d4bSJoseph Koshy 	/* retired mispred branch type */
1750ebccf1e3SJoseph Koshy 	__P4MASK(conditional, 1),
1751ebccf1e3SJoseph Koshy 	__P4MASK(call, 2),
1752ebccf1e3SJoseph Koshy 	__P4MASK(return, 3),
1753ebccf1e3SJoseph Koshy 	__P4MASK(indirect, 4),
1754ebccf1e3SJoseph Koshy 	NULLMASK
1755ebccf1e3SJoseph Koshy };
1756ebccf1e3SJoseph Koshy 
1757ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_rbt[] = { /* retired branch type */
1758ebccf1e3SJoseph Koshy 	__P4MASK(conditional, 1),
1759ebccf1e3SJoseph Koshy 	__P4MASK(call, 2),
1760ebccf1e3SJoseph Koshy 	__P4MASK(retired, 3),
1761ebccf1e3SJoseph Koshy 	__P4MASK(indirect, 4),
1762ebccf1e3SJoseph Koshy 	NULLMASK
1763ebccf1e3SJoseph Koshy };
1764ebccf1e3SJoseph Koshy 
1765ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_rs[] = { /* resource stall */
1766ebccf1e3SJoseph Koshy 	__P4MASK(sbfull, 5),
1767ebccf1e3SJoseph Koshy 	NULLMASK
1768ebccf1e3SJoseph Koshy };
1769ebccf1e3SJoseph Koshy 
1770ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_wb[] = { /* WC buffer */
1771ebccf1e3SJoseph Koshy 	__P4MASK(wcb-evicts, 0),
1772ebccf1e3SJoseph Koshy 	__P4MASK(wcb-full-evict, 1),
1773ebccf1e3SJoseph Koshy 	NULLMASK
1774ebccf1e3SJoseph Koshy };
1775ebccf1e3SJoseph Koshy 
1776ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_fee[] = { /* front end event */
1777ebccf1e3SJoseph Koshy 	__P4MASK(nbogus, 0),
1778ebccf1e3SJoseph Koshy 	__P4MASK(bogus, 1),
1779ebccf1e3SJoseph Koshy 	NULLMASK
1780ebccf1e3SJoseph Koshy };
1781ebccf1e3SJoseph Koshy 
1782ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ee[] = { /* execution event */
1783ebccf1e3SJoseph Koshy 	__P4MASK(nbogus0, 0),
1784ebccf1e3SJoseph Koshy 	__P4MASK(nbogus1, 1),
1785ebccf1e3SJoseph Koshy 	__P4MASK(nbogus2, 2),
1786ebccf1e3SJoseph Koshy 	__P4MASK(nbogus3, 3),
1787ebccf1e3SJoseph Koshy 	__P4MASK(bogus0, 4),
1788ebccf1e3SJoseph Koshy 	__P4MASK(bogus1, 5),
1789ebccf1e3SJoseph Koshy 	__P4MASK(bogus2, 6),
1790ebccf1e3SJoseph Koshy 	__P4MASK(bogus3, 7),
1791ebccf1e3SJoseph Koshy 	NULLMASK
1792ebccf1e3SJoseph Koshy };
1793ebccf1e3SJoseph Koshy 
1794ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_re[] = { /* replay event */
1795ebccf1e3SJoseph Koshy 	__P4MASK(nbogus, 0),
1796ebccf1e3SJoseph Koshy 	__P4MASK(bogus, 1),
1797ebccf1e3SJoseph Koshy 	NULLMASK
1798ebccf1e3SJoseph Koshy };
1799ebccf1e3SJoseph Koshy 
1800ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_insret[] = { /* instr retired */
1801ebccf1e3SJoseph Koshy 	__P4MASK(nbogusntag, 0),
1802ebccf1e3SJoseph Koshy 	__P4MASK(nbogustag, 1),
1803ebccf1e3SJoseph Koshy 	__P4MASK(bogusntag, 2),
1804ebccf1e3SJoseph Koshy 	__P4MASK(bogustag, 3),
1805ebccf1e3SJoseph Koshy 	NULLMASK
1806ebccf1e3SJoseph Koshy };
1807ebccf1e3SJoseph Koshy 
1808ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ur[] = { /* uops retired */
1809ebccf1e3SJoseph Koshy 	__P4MASK(nbogus, 0),
1810ebccf1e3SJoseph Koshy 	__P4MASK(bogus, 1),
1811ebccf1e3SJoseph Koshy 	NULLMASK
1812ebccf1e3SJoseph Koshy };
1813ebccf1e3SJoseph Koshy 
1814ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_ut[] = { /* uop type */
1815ebccf1e3SJoseph Koshy 	__P4MASK(tagloads, 1),
1816ebccf1e3SJoseph Koshy 	__P4MASK(tagstores, 2),
1817ebccf1e3SJoseph Koshy 	NULLMASK
1818ebccf1e3SJoseph Koshy };
1819ebccf1e3SJoseph Koshy 
1820ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_br[] = { /* branch retired */
1821ebccf1e3SJoseph Koshy 	__P4MASK(mmnp, 0),
1822ebccf1e3SJoseph Koshy 	__P4MASK(mmnm, 1),
1823ebccf1e3SJoseph Koshy 	__P4MASK(mmtp, 2),
1824ebccf1e3SJoseph Koshy 	__P4MASK(mmtm, 3),
1825ebccf1e3SJoseph Koshy 	NULLMASK
1826ebccf1e3SJoseph Koshy };
1827ebccf1e3SJoseph Koshy 
1828ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_mbr[] = { /* mispred branch retired */
1829ebccf1e3SJoseph Koshy 	__P4MASK(nbogus, 0),
1830ebccf1e3SJoseph Koshy 	NULLMASK
1831ebccf1e3SJoseph Koshy };
1832ebccf1e3SJoseph Koshy 
1833ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_xa[] = { /* x87 assist */
1834ebccf1e3SJoseph Koshy 	__P4MASK(fpsu, 0),
1835ebccf1e3SJoseph Koshy 	__P4MASK(fpso, 1),
1836ebccf1e3SJoseph Koshy 	__P4MASK(poao, 2),
1837ebccf1e3SJoseph Koshy 	__P4MASK(poau, 3),
1838ebccf1e3SJoseph Koshy 	__P4MASK(prea, 4),
1839ebccf1e3SJoseph Koshy 	NULLMASK
1840ebccf1e3SJoseph Koshy };
1841ebccf1e3SJoseph Koshy 
1842ebccf1e3SJoseph Koshy static const struct pmc_masks p4_mask_machclr[] = { /* machine clear */
1843ebccf1e3SJoseph Koshy 	__P4MASK(clear, 0),
1844ebccf1e3SJoseph Koshy 	__P4MASK(moclear, 2),
1845ebccf1e3SJoseph Koshy 	__P4MASK(smclear, 3),
1846ebccf1e3SJoseph Koshy 	NULLMASK
1847ebccf1e3SJoseph Koshy };
1848ebccf1e3SJoseph Koshy 
1849ebccf1e3SJoseph Koshy /* P4 event parser */
1850ebccf1e3SJoseph Koshy static int
1851ebccf1e3SJoseph Koshy p4_allocate_pmc(enum pmc_event pe, char *ctrspec,
1852ebccf1e3SJoseph Koshy     struct pmc_op_pmcallocate *pmc_config)
1853ebccf1e3SJoseph Koshy {
1854ebccf1e3SJoseph Koshy 
1855ebccf1e3SJoseph Koshy 	char	*e, *p, *q;
1856ebccf1e3SJoseph Koshy 	int	count, has_tag, has_busreqtype, n;
18571e862e5aSFabien Thomas 	uint32_t cccractivemask;
18581e862e5aSFabien Thomas 	uint64_t evmask;
1859ebccf1e3SJoseph Koshy 	const struct pmc_masks *pm, *pmask;
1860ebccf1e3SJoseph Koshy 
1861789140c0SJoseph Koshy 	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
1862f263522aSJoseph Koshy 	pmc_config->pm_md.pm_p4.pm_p4_cccrconfig =
1863f263522aSJoseph Koshy 	    pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 0;
1864ebccf1e3SJoseph Koshy 
1865ebccf1e3SJoseph Koshy 	pmask   = NULL;
1866ebccf1e3SJoseph Koshy 	evmask  = 0;
1867ebccf1e3SJoseph Koshy 	cccractivemask = 0x3;
1868ebccf1e3SJoseph Koshy 	has_tag = has_busreqtype = 0;
1869ebccf1e3SJoseph Koshy 
1870ebccf1e3SJoseph Koshy #define	__P4SETMASK(M) do {				\
1871ebccf1e3SJoseph Koshy 	pmask = p4_mask_##M;				\
1872ebccf1e3SJoseph Koshy } while (0)
1873ebccf1e3SJoseph Koshy 
1874ebccf1e3SJoseph Koshy 	switch (pe) {
1875ebccf1e3SJoseph Koshy 	case PMC_EV_P4_TC_DELIVER_MODE:
1876ebccf1e3SJoseph Koshy 		__P4SETMASK(tcdm);
1877ebccf1e3SJoseph Koshy 		break;
1878ebccf1e3SJoseph Koshy 	case PMC_EV_P4_BPU_FETCH_REQUEST:
1879ebccf1e3SJoseph Koshy 		__P4SETMASK(bfr);
1880ebccf1e3SJoseph Koshy 		break;
1881ebccf1e3SJoseph Koshy 	case PMC_EV_P4_ITLB_REFERENCE:
1882ebccf1e3SJoseph Koshy 		__P4SETMASK(ir);
1883ebccf1e3SJoseph Koshy 		break;
1884ebccf1e3SJoseph Koshy 	case PMC_EV_P4_MEMORY_CANCEL:
1885ebccf1e3SJoseph Koshy 		__P4SETMASK(memcan);
1886ebccf1e3SJoseph Koshy 		break;
1887ebccf1e3SJoseph Koshy 	case PMC_EV_P4_MEMORY_COMPLETE:
1888ebccf1e3SJoseph Koshy 		__P4SETMASK(memcomp);
1889ebccf1e3SJoseph Koshy 		break;
1890ebccf1e3SJoseph Koshy 	case PMC_EV_P4_LOAD_PORT_REPLAY:
1891ebccf1e3SJoseph Koshy 		__P4SETMASK(lpr);
1892ebccf1e3SJoseph Koshy 		break;
1893ebccf1e3SJoseph Koshy 	case PMC_EV_P4_STORE_PORT_REPLAY:
1894ebccf1e3SJoseph Koshy 		__P4SETMASK(spr);
1895ebccf1e3SJoseph Koshy 		break;
1896ebccf1e3SJoseph Koshy 	case PMC_EV_P4_MOB_LOAD_REPLAY:
1897ebccf1e3SJoseph Koshy 		__P4SETMASK(mlr);
1898ebccf1e3SJoseph Koshy 		break;
1899ebccf1e3SJoseph Koshy 	case PMC_EV_P4_PAGE_WALK_TYPE:
1900ebccf1e3SJoseph Koshy 		__P4SETMASK(pwt);
1901ebccf1e3SJoseph Koshy 		break;
1902ebccf1e3SJoseph Koshy 	case PMC_EV_P4_BSQ_CACHE_REFERENCE:
1903ebccf1e3SJoseph Koshy 		__P4SETMASK(bcr);
1904ebccf1e3SJoseph Koshy 		break;
1905ebccf1e3SJoseph Koshy 	case PMC_EV_P4_IOQ_ALLOCATION:
1906ebccf1e3SJoseph Koshy 		__P4SETMASK(ia);
1907ebccf1e3SJoseph Koshy 		has_busreqtype = 1;
1908ebccf1e3SJoseph Koshy 		break;
1909ebccf1e3SJoseph Koshy 	case PMC_EV_P4_IOQ_ACTIVE_ENTRIES:
1910ebccf1e3SJoseph Koshy 		__P4SETMASK(iae);
1911ebccf1e3SJoseph Koshy 		has_busreqtype = 1;
1912ebccf1e3SJoseph Koshy 		break;
1913ebccf1e3SJoseph Koshy 	case PMC_EV_P4_FSB_DATA_ACTIVITY:
1914ebccf1e3SJoseph Koshy 		__P4SETMASK(fda);
1915ebccf1e3SJoseph Koshy 		break;
1916ebccf1e3SJoseph Koshy 	case PMC_EV_P4_BSQ_ALLOCATION:
1917ebccf1e3SJoseph Koshy 		__P4SETMASK(ba);
1918ebccf1e3SJoseph Koshy 		break;
1919ebccf1e3SJoseph Koshy 	case PMC_EV_P4_SSE_INPUT_ASSIST:
1920ebccf1e3SJoseph Koshy 		__P4SETMASK(sia);
1921ebccf1e3SJoseph Koshy 		break;
1922ebccf1e3SJoseph Koshy 	case PMC_EV_P4_PACKED_SP_UOP:
1923ebccf1e3SJoseph Koshy 		__P4SETMASK(psu);
1924ebccf1e3SJoseph Koshy 		break;
1925ebccf1e3SJoseph Koshy 	case PMC_EV_P4_PACKED_DP_UOP:
1926ebccf1e3SJoseph Koshy 		__P4SETMASK(pdu);
1927ebccf1e3SJoseph Koshy 		break;
1928ebccf1e3SJoseph Koshy 	case PMC_EV_P4_SCALAR_SP_UOP:
1929ebccf1e3SJoseph Koshy 		__P4SETMASK(ssu);
1930ebccf1e3SJoseph Koshy 		break;
1931ebccf1e3SJoseph Koshy 	case PMC_EV_P4_SCALAR_DP_UOP:
1932ebccf1e3SJoseph Koshy 		__P4SETMASK(sdu);
1933ebccf1e3SJoseph Koshy 		break;
1934ebccf1e3SJoseph Koshy 	case PMC_EV_P4_64BIT_MMX_UOP:
1935ebccf1e3SJoseph Koshy 		__P4SETMASK(64bmu);
1936ebccf1e3SJoseph Koshy 		break;
1937ebccf1e3SJoseph Koshy 	case PMC_EV_P4_128BIT_MMX_UOP:
1938ebccf1e3SJoseph Koshy 		__P4SETMASK(128bmu);
1939ebccf1e3SJoseph Koshy 		break;
1940ebccf1e3SJoseph Koshy 	case PMC_EV_P4_X87_FP_UOP:
1941ebccf1e3SJoseph Koshy 		__P4SETMASK(xfu);
1942ebccf1e3SJoseph Koshy 		break;
1943ebccf1e3SJoseph Koshy 	case PMC_EV_P4_X87_SIMD_MOVES_UOP:
1944ebccf1e3SJoseph Koshy 		__P4SETMASK(xsmu);
1945ebccf1e3SJoseph Koshy 		break;
1946ebccf1e3SJoseph Koshy 	case PMC_EV_P4_GLOBAL_POWER_EVENTS:
1947ebccf1e3SJoseph Koshy 		__P4SETMASK(gpe);
1948ebccf1e3SJoseph Koshy 		break;
1949ebccf1e3SJoseph Koshy 	case PMC_EV_P4_TC_MS_XFER:
1950ebccf1e3SJoseph Koshy 		__P4SETMASK(tmx);
1951ebccf1e3SJoseph Koshy 		break;
1952ebccf1e3SJoseph Koshy 	case PMC_EV_P4_UOP_QUEUE_WRITES:
1953ebccf1e3SJoseph Koshy 		__P4SETMASK(uqw);
1954ebccf1e3SJoseph Koshy 		break;
1955ebccf1e3SJoseph Koshy 	case PMC_EV_P4_RETIRED_MISPRED_BRANCH_TYPE:
1956ebccf1e3SJoseph Koshy 		__P4SETMASK(rmbt);
1957ebccf1e3SJoseph Koshy 		break;
1958ebccf1e3SJoseph Koshy 	case PMC_EV_P4_RETIRED_BRANCH_TYPE:
1959ebccf1e3SJoseph Koshy 		__P4SETMASK(rbt);
1960ebccf1e3SJoseph Koshy 		break;
1961ebccf1e3SJoseph Koshy 	case PMC_EV_P4_RESOURCE_STALL:
1962ebccf1e3SJoseph Koshy 		__P4SETMASK(rs);
1963ebccf1e3SJoseph Koshy 		break;
1964ebccf1e3SJoseph Koshy 	case PMC_EV_P4_WC_BUFFER:
1965ebccf1e3SJoseph Koshy 		__P4SETMASK(wb);
1966ebccf1e3SJoseph Koshy 		break;
1967ebccf1e3SJoseph Koshy 	case PMC_EV_P4_BSQ_ACTIVE_ENTRIES:
1968ebccf1e3SJoseph Koshy 	case PMC_EV_P4_B2B_CYCLES:
1969ebccf1e3SJoseph Koshy 	case PMC_EV_P4_BNR:
1970ebccf1e3SJoseph Koshy 	case PMC_EV_P4_SNOOP:
1971ebccf1e3SJoseph Koshy 	case PMC_EV_P4_RESPONSE:
1972ebccf1e3SJoseph Koshy 		break;
1973ebccf1e3SJoseph Koshy 	case PMC_EV_P4_FRONT_END_EVENT:
1974ebccf1e3SJoseph Koshy 		__P4SETMASK(fee);
1975ebccf1e3SJoseph Koshy 		break;
1976ebccf1e3SJoseph Koshy 	case PMC_EV_P4_EXECUTION_EVENT:
1977ebccf1e3SJoseph Koshy 		__P4SETMASK(ee);
1978ebccf1e3SJoseph Koshy 		break;
1979ebccf1e3SJoseph Koshy 	case PMC_EV_P4_REPLAY_EVENT:
1980ebccf1e3SJoseph Koshy 		__P4SETMASK(re);
1981ebccf1e3SJoseph Koshy 		break;
1982ebccf1e3SJoseph Koshy 	case PMC_EV_P4_INSTR_RETIRED:
1983ebccf1e3SJoseph Koshy 		__P4SETMASK(insret);
1984ebccf1e3SJoseph Koshy 		break;
1985ebccf1e3SJoseph Koshy 	case PMC_EV_P4_UOPS_RETIRED:
1986ebccf1e3SJoseph Koshy 		__P4SETMASK(ur);
1987ebccf1e3SJoseph Koshy 		break;
1988ebccf1e3SJoseph Koshy 	case PMC_EV_P4_UOP_TYPE:
1989ebccf1e3SJoseph Koshy 		__P4SETMASK(ut);
1990ebccf1e3SJoseph Koshy 		break;
1991ebccf1e3SJoseph Koshy 	case PMC_EV_P4_BRANCH_RETIRED:
1992ebccf1e3SJoseph Koshy 		__P4SETMASK(br);
1993ebccf1e3SJoseph Koshy 		break;
1994ebccf1e3SJoseph Koshy 	case PMC_EV_P4_MISPRED_BRANCH_RETIRED:
1995ebccf1e3SJoseph Koshy 		__P4SETMASK(mbr);
1996ebccf1e3SJoseph Koshy 		break;
1997ebccf1e3SJoseph Koshy 	case PMC_EV_P4_X87_ASSIST:
1998ebccf1e3SJoseph Koshy 		__P4SETMASK(xa);
1999ebccf1e3SJoseph Koshy 		break;
2000ebccf1e3SJoseph Koshy 	case PMC_EV_P4_MACHINE_CLEAR:
2001ebccf1e3SJoseph Koshy 		__P4SETMASK(machclr);
2002ebccf1e3SJoseph Koshy 		break;
2003ebccf1e3SJoseph Koshy 	default:
2004aa342b1fSJoseph Koshy 		return (-1);
2005ebccf1e3SJoseph Koshy 	}
2006ebccf1e3SJoseph Koshy 
2007ebccf1e3SJoseph Koshy 	/* process additional flags */
2008ebccf1e3SJoseph Koshy 	while ((p = strsep(&ctrspec, ",")) != NULL) {
2009ebccf1e3SJoseph Koshy 		if (KWPREFIXMATCH(p, P4_KW_ACTIVE)) {
2010ebccf1e3SJoseph Koshy 			q = strchr(p, '=');
2011ebccf1e3SJoseph Koshy 			if (*++q == '\0') /* skip '=' */
2012aa342b1fSJoseph Koshy 				return (-1);
2013ebccf1e3SJoseph Koshy 
2014789140c0SJoseph Koshy 			if (strcasecmp(q, P4_KW_ACTIVE_NONE) == 0)
2015ebccf1e3SJoseph Koshy 				cccractivemask = 0x0;
2016789140c0SJoseph Koshy 			else if (strcasecmp(q, P4_KW_ACTIVE_SINGLE) == 0)
2017ebccf1e3SJoseph Koshy 				cccractivemask = 0x1;
2018789140c0SJoseph Koshy 			else if (strcasecmp(q, P4_KW_ACTIVE_BOTH) == 0)
2019ebccf1e3SJoseph Koshy 				cccractivemask = 0x2;
2020789140c0SJoseph Koshy 			else if (strcasecmp(q, P4_KW_ACTIVE_ANY) == 0)
2021ebccf1e3SJoseph Koshy 				cccractivemask = 0x3;
2022ebccf1e3SJoseph Koshy 			else
2023aa342b1fSJoseph Koshy 				return (-1);
2024ebccf1e3SJoseph Koshy 
2025ebccf1e3SJoseph Koshy 		} else if (KWPREFIXMATCH(p, P4_KW_BUSREQTYPE)) {
2026ebccf1e3SJoseph Koshy 			if (has_busreqtype == 0)
2027aa342b1fSJoseph Koshy 				return (-1);
2028ebccf1e3SJoseph Koshy 
2029ebccf1e3SJoseph Koshy 			q = strchr(p, '=');
2030ebccf1e3SJoseph Koshy 			if (*++q == '\0') /* skip '=' */
2031aa342b1fSJoseph Koshy 				return (-1);
2032ebccf1e3SJoseph Koshy 
2033ebccf1e3SJoseph Koshy 			count = strtol(q, &e, 0);
2034ebccf1e3SJoseph Koshy 			if (e == q || *e != '\0')
2035aa342b1fSJoseph Koshy 				return (-1);
2036ebccf1e3SJoseph Koshy 			evmask = (evmask & ~0x1F) | (count & 0x1F);
2037ebccf1e3SJoseph Koshy 		} else if (KWMATCH(p, P4_KW_CASCADE))
2038ebccf1e3SJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_CASCADE;
2039ebccf1e3SJoseph Koshy 		else if (KWMATCH(p, P4_KW_EDGE))
2040ebccf1e3SJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_EDGE;
2041ebccf1e3SJoseph Koshy 		else if (KWMATCH(p, P4_KW_INV))
2042ebccf1e3SJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_INVERT;
2043ebccf1e3SJoseph Koshy 		else if (KWPREFIXMATCH(p, P4_KW_MASK "=")) {
2044ebccf1e3SJoseph Koshy 			if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0)
2045aa342b1fSJoseph Koshy 				return (-1);
2046ebccf1e3SJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
2047ebccf1e3SJoseph Koshy 		} else if (KWMATCH(p, P4_KW_OS))
2048ebccf1e3SJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_SYSTEM;
2049ebccf1e3SJoseph Koshy 		else if (KWMATCH(p, P4_KW_PRECISE))
2050ebccf1e3SJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_PRECISE;
2051ebccf1e3SJoseph Koshy 		else if (KWPREFIXMATCH(p, P4_KW_TAG "=")) {
2052ebccf1e3SJoseph Koshy 			if (has_tag == 0)
2053aa342b1fSJoseph Koshy 				return (-1);
2054ebccf1e3SJoseph Koshy 
2055ebccf1e3SJoseph Koshy 			q = strchr(p, '=');
2056ebccf1e3SJoseph Koshy 			if (*++q == '\0') /* skip '=' */
2057aa342b1fSJoseph Koshy 				return (-1);
2058ebccf1e3SJoseph Koshy 
2059ebccf1e3SJoseph Koshy 			count = strtol(q, &e, 0);
2060ebccf1e3SJoseph Koshy 			if (e == q || *e != '\0')
2061aa342b1fSJoseph Koshy 				return (-1);
2062ebccf1e3SJoseph Koshy 
2063ebccf1e3SJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_TAGGING;
2064f263522aSJoseph Koshy 			pmc_config->pm_md.pm_p4.pm_p4_escrconfig |=
2065ebccf1e3SJoseph Koshy 			    P4_ESCR_TO_TAG_VALUE(count);
2066ebccf1e3SJoseph Koshy 		} else if (KWPREFIXMATCH(p, P4_KW_THRESHOLD "=")) {
2067ebccf1e3SJoseph Koshy 			q = strchr(p, '=');
2068ebccf1e3SJoseph Koshy 			if (*++q == '\0') /* skip '=' */
2069aa342b1fSJoseph Koshy 				return (-1);
2070ebccf1e3SJoseph Koshy 
2071ebccf1e3SJoseph Koshy 			count = strtol(q, &e, 0);
2072ebccf1e3SJoseph Koshy 			if (e == q || *e != '\0')
2073aa342b1fSJoseph Koshy 				return (-1);
2074ebccf1e3SJoseph Koshy 
2075ebccf1e3SJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
2076f263522aSJoseph Koshy 			pmc_config->pm_md.pm_p4.pm_p4_cccrconfig &=
2077f263522aSJoseph Koshy 			    ~P4_CCCR_THRESHOLD_MASK;
2078f263522aSJoseph Koshy 			pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |=
2079f263522aSJoseph Koshy 			    P4_CCCR_TO_THRESHOLD(count);
2080ebccf1e3SJoseph Koshy 		} else if (KWMATCH(p, P4_KW_USR))
2081ebccf1e3SJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_USER;
2082ebccf1e3SJoseph Koshy 		else
2083aa342b1fSJoseph Koshy 			return (-1);
2084ebccf1e3SJoseph Koshy 	}
2085ebccf1e3SJoseph Koshy 
2086ebccf1e3SJoseph Koshy 	/* other post processing */
2087ebccf1e3SJoseph Koshy 	if (pe == PMC_EV_P4_IOQ_ALLOCATION ||
2088ebccf1e3SJoseph Koshy 	    pe == PMC_EV_P4_FSB_DATA_ACTIVITY ||
2089ebccf1e3SJoseph Koshy 	    pe == PMC_EV_P4_BSQ_ALLOCATION)
2090ebccf1e3SJoseph Koshy 		pmc_config->pm_caps |= PMC_CAP_EDGE;
2091ebccf1e3SJoseph Koshy 
2092ebccf1e3SJoseph Koshy 	/* fill in thread activity mask */
2093f263522aSJoseph Koshy 	pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |=
2094ebccf1e3SJoseph Koshy 	    P4_CCCR_TO_ACTIVE_THREAD(cccractivemask);
2095ebccf1e3SJoseph Koshy 
2096ebccf1e3SJoseph Koshy 	if (evmask)
2097ebccf1e3SJoseph Koshy 		pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
2098ebccf1e3SJoseph Koshy 
2099ebccf1e3SJoseph Koshy 	switch (pe) {
2100ebccf1e3SJoseph Koshy 	case PMC_EV_P4_FSB_DATA_ACTIVITY:
2101ebccf1e3SJoseph Koshy 		if ((evmask & 0x06) == 0x06 ||
2102ebccf1e3SJoseph Koshy 		    (evmask & 0x18) == 0x18)
2103aa342b1fSJoseph Koshy 			return (-1); /* can't have own+other bits together */
2104ebccf1e3SJoseph Koshy 		if (evmask == 0) /* default:drdy-{drv,own}+dbsy{drv,own} */
2105ebccf1e3SJoseph Koshy 			evmask = 0x1D;
2106ebccf1e3SJoseph Koshy 		break;
2107ebccf1e3SJoseph Koshy 	case PMC_EV_P4_MACHINE_CLEAR:
2108ebccf1e3SJoseph Koshy 		/* only one bit is allowed to be set */
2109ebccf1e3SJoseph Koshy 		if ((evmask & (evmask - 1)) != 0)
2110aa342b1fSJoseph Koshy 			return (-1);
2111ebccf1e3SJoseph Koshy 		if (evmask == 0) {
2112ebccf1e3SJoseph Koshy 			evmask = 0x1;	/* 'CLEAR' */
2113ebccf1e3SJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
2114ebccf1e3SJoseph Koshy 		}
2115ebccf1e3SJoseph Koshy 		break;
2116ebccf1e3SJoseph Koshy 	default:
2117ebccf1e3SJoseph Koshy 		if (evmask == 0 && pmask) {
2118ebccf1e3SJoseph Koshy 			for (pm = pmask; pm->pm_name; pm++)
2119ebccf1e3SJoseph Koshy 				evmask |= pm->pm_value;
2120ebccf1e3SJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
2121ebccf1e3SJoseph Koshy 		}
2122ebccf1e3SJoseph Koshy 	}
2123ebccf1e3SJoseph Koshy 
2124f263522aSJoseph Koshy 	pmc_config->pm_md.pm_p4.pm_p4_escrconfig =
2125f263522aSJoseph Koshy 	    P4_ESCR_TO_EVENT_MASK(evmask);
2126ebccf1e3SJoseph Koshy 
2127aa342b1fSJoseph Koshy 	return (0);
2128ebccf1e3SJoseph Koshy }
2129ebccf1e3SJoseph Koshy 
213086a65549SJoseph Koshy #endif
213186a65549SJoseph Koshy 
213286a65549SJoseph Koshy #if defined(__i386__)
213386a65549SJoseph Koshy 
2134ebccf1e3SJoseph Koshy /*
2135f263522aSJoseph Koshy  * Pentium style PMCs
2136f263522aSJoseph Koshy  */
2137f263522aSJoseph Koshy 
2138f263522aSJoseph Koshy static struct pmc_event_alias p5_aliases[] = {
21390b9b757dSJoseph Koshy 	EV_ALIAS("branches",		"p5-taken-branches"),
2140f263522aSJoseph Koshy 	EV_ALIAS("cycles",		"tsc"),
21410b9b757dSJoseph Koshy 	EV_ALIAS("dc-misses",		"p5-data-read-miss-or-write-miss"),
21420b9b757dSJoseph Koshy 	EV_ALIAS("ic-misses",		"p5-code-cache-miss"),
21430b9b757dSJoseph Koshy 	EV_ALIAS("instructions",	"p5-instructions-executed"),
21440b9b757dSJoseph Koshy 	EV_ALIAS("interrupts",		"p5-hardware-interrupts"),
21450b9b757dSJoseph Koshy 	EV_ALIAS("unhalted-cycles",
21460b9b757dSJoseph Koshy 	    "p5-number-of-cycles-not-in-halt-state"),
2147f263522aSJoseph Koshy 	EV_ALIAS(NULL, NULL)
2148f263522aSJoseph Koshy };
2149f263522aSJoseph Koshy 
2150f263522aSJoseph Koshy static int
2151f263522aSJoseph Koshy p5_allocate_pmc(enum pmc_event pe, char *ctrspec,
2152f263522aSJoseph Koshy     struct pmc_op_pmcallocate *pmc_config)
2153f263522aSJoseph Koshy {
2154aa342b1fSJoseph Koshy 	return (-1 || pe || ctrspec || pmc_config); /* shut up gcc */
2155f263522aSJoseph Koshy }
2156f263522aSJoseph Koshy 
2157f263522aSJoseph Koshy /*
2158ebccf1e3SJoseph Koshy  * Pentium Pro style PMCs.  These PMCs are found in Pentium II, Pentium III,
2159ebccf1e3SJoseph Koshy  * and Pentium M CPUs.
2160ebccf1e3SJoseph Koshy  */
2161ebccf1e3SJoseph Koshy 
2162ebccf1e3SJoseph Koshy static struct pmc_event_alias p6_aliases[] = {
2163ebccf1e3SJoseph Koshy 	EV_ALIAS("branches",		"p6-br-inst-retired"),
2164ebccf1e3SJoseph Koshy 	EV_ALIAS("branch-mispredicts",	"p6-br-miss-pred-retired"),
2165ebccf1e3SJoseph Koshy 	EV_ALIAS("cycles",		"tsc"),
2166d56c5d4bSJoseph Koshy 	EV_ALIAS("dc-misses",		"p6-dcu-lines-in"),
216773e2d811SJoseph Koshy 	EV_ALIAS("ic-misses",		"p6-ifu-fetch-miss"),
2168ebccf1e3SJoseph Koshy 	EV_ALIAS("instructions",	"p6-inst-retired"),
2169ebccf1e3SJoseph Koshy 	EV_ALIAS("interrupts",		"p6-hw-int-rx"),
2170177a2f22SJoseph Koshy 	EV_ALIAS("unhalted-cycles",	"p6-cpu-clk-unhalted"),
2171ebccf1e3SJoseph Koshy 	EV_ALIAS(NULL, NULL)
2172ebccf1e3SJoseph Koshy };
2173ebccf1e3SJoseph Koshy 
2174ebccf1e3SJoseph Koshy #define	P6_KW_CMASK	"cmask"
2175ebccf1e3SJoseph Koshy #define	P6_KW_EDGE	"edge"
2176ebccf1e3SJoseph Koshy #define	P6_KW_INV	"inv"
2177ebccf1e3SJoseph Koshy #define	P6_KW_OS	"os"
2178ebccf1e3SJoseph Koshy #define	P6_KW_UMASK	"umask"
2179ebccf1e3SJoseph Koshy #define	P6_KW_USR	"usr"
2180ebccf1e3SJoseph Koshy 
2181ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mesi[] = {
2182ebccf1e3SJoseph Koshy 	PMCMASK(m,	0x01),
2183ebccf1e3SJoseph Koshy 	PMCMASK(e,	0x02),
2184ebccf1e3SJoseph Koshy 	PMCMASK(s,	0x04),
2185ebccf1e3SJoseph Koshy 	PMCMASK(i,	0x08),
2186ebccf1e3SJoseph Koshy 	NULLMASK
2187ebccf1e3SJoseph Koshy };
2188ebccf1e3SJoseph Koshy 
2189ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mesihw[] = {
2190ebccf1e3SJoseph Koshy 	PMCMASK(m,	0x01),
2191ebccf1e3SJoseph Koshy 	PMCMASK(e,	0x02),
2192ebccf1e3SJoseph Koshy 	PMCMASK(s,	0x04),
2193ebccf1e3SJoseph Koshy 	PMCMASK(i,	0x08),
2194ebccf1e3SJoseph Koshy 	PMCMASK(nonhw,	0x00),
2195ebccf1e3SJoseph Koshy 	PMCMASK(hw,	0x10),
2196ebccf1e3SJoseph Koshy 	PMCMASK(both,	0x30),
2197ebccf1e3SJoseph Koshy 	NULLMASK
2198ebccf1e3SJoseph Koshy };
2199ebccf1e3SJoseph Koshy 
2200ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_hw[] = {
2201ebccf1e3SJoseph Koshy 	PMCMASK(nonhw,	0x00),
2202ebccf1e3SJoseph Koshy 	PMCMASK(hw,	0x10),
2203ebccf1e3SJoseph Koshy 	PMCMASK(both,	0x30),
2204ebccf1e3SJoseph Koshy 	NULLMASK
2205ebccf1e3SJoseph Koshy };
2206ebccf1e3SJoseph Koshy 
2207ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_any[] = {
2208ebccf1e3SJoseph Koshy 	PMCMASK(self,	0x00),
2209ebccf1e3SJoseph Koshy 	PMCMASK(any,	0x20),
2210ebccf1e3SJoseph Koshy 	NULLMASK
2211ebccf1e3SJoseph Koshy };
2212ebccf1e3SJoseph Koshy 
2213ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_ekp[] = {
2214ebccf1e3SJoseph Koshy 	PMCMASK(nta,	0x00),
2215ebccf1e3SJoseph Koshy 	PMCMASK(t1,	0x01),
2216ebccf1e3SJoseph Koshy 	PMCMASK(t2,	0x02),
2217ebccf1e3SJoseph Koshy 	PMCMASK(wos,	0x03),
2218ebccf1e3SJoseph Koshy 	NULLMASK
2219ebccf1e3SJoseph Koshy };
2220ebccf1e3SJoseph Koshy 
2221ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_pps[] = {
2222ebccf1e3SJoseph Koshy 	PMCMASK(packed-and-scalar, 0x00),
2223ebccf1e3SJoseph Koshy 	PMCMASK(scalar,	0x01),
2224ebccf1e3SJoseph Koshy 	NULLMASK
2225ebccf1e3SJoseph Koshy };
2226ebccf1e3SJoseph Koshy 
2227ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_mite[] = {
2228ebccf1e3SJoseph Koshy 	PMCMASK(packed-multiply,	 0x01),
2229ebccf1e3SJoseph Koshy 	PMCMASK(packed-shift,		0x02),
2230ebccf1e3SJoseph Koshy 	PMCMASK(pack,			0x04),
2231ebccf1e3SJoseph Koshy 	PMCMASK(unpack,			0x08),
2232ebccf1e3SJoseph Koshy 	PMCMASK(packed-logical,		0x10),
2233ebccf1e3SJoseph Koshy 	PMCMASK(packed-arithmetic,	0x20),
2234ebccf1e3SJoseph Koshy 	NULLMASK
2235ebccf1e3SJoseph Koshy };
2236ebccf1e3SJoseph Koshy 
2237ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_fmt[] = {
2238ebccf1e3SJoseph Koshy 	PMCMASK(mmxtofp,	0x00),
2239ebccf1e3SJoseph Koshy 	PMCMASK(fptommx,	0x01),
2240ebccf1e3SJoseph Koshy 	NULLMASK
2241ebccf1e3SJoseph Koshy };
2242ebccf1e3SJoseph Koshy 
2243ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_sr[] = {
2244ebccf1e3SJoseph Koshy 	PMCMASK(es,	0x01),
2245ebccf1e3SJoseph Koshy 	PMCMASK(ds,	0x02),
2246ebccf1e3SJoseph Koshy 	PMCMASK(fs,	0x04),
2247ebccf1e3SJoseph Koshy 	PMCMASK(gs,	0x08),
2248ebccf1e3SJoseph Koshy 	NULLMASK
2249ebccf1e3SJoseph Koshy };
2250ebccf1e3SJoseph Koshy 
2251ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_eet[] = {
2252ebccf1e3SJoseph Koshy 	PMCMASK(all,	0x00),
2253ebccf1e3SJoseph Koshy 	PMCMASK(freq,	0x02),
2254ebccf1e3SJoseph Koshy 	NULLMASK
2255ebccf1e3SJoseph Koshy };
2256ebccf1e3SJoseph Koshy 
2257ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_efur[] = {
2258ebccf1e3SJoseph Koshy 	PMCMASK(all,	0x00),
2259ebccf1e3SJoseph Koshy 	PMCMASK(loadop,	0x01),
2260ebccf1e3SJoseph Koshy 	PMCMASK(stdsta,	0x02),
2261ebccf1e3SJoseph Koshy 	NULLMASK
2262ebccf1e3SJoseph Koshy };
2263ebccf1e3SJoseph Koshy 
2264ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_essir[] = {
2265ebccf1e3SJoseph Koshy 	PMCMASK(sse-packed-single,	0x00),
2266ebccf1e3SJoseph Koshy 	PMCMASK(sse-packed-single-scalar-single, 0x01),
2267ebccf1e3SJoseph Koshy 	PMCMASK(sse2-packed-double,	0x02),
2268ebccf1e3SJoseph Koshy 	PMCMASK(sse2-scalar-double,	0x03),
2269ebccf1e3SJoseph Koshy 	NULLMASK
2270ebccf1e3SJoseph Koshy };
2271ebccf1e3SJoseph Koshy 
2272ebccf1e3SJoseph Koshy static struct pmc_masks p6_mask_esscir[] = {
2273ebccf1e3SJoseph Koshy 	PMCMASK(sse-packed-single,	0x00),
2274ebccf1e3SJoseph Koshy 	PMCMASK(sse-scalar-single,	0x01),
2275ebccf1e3SJoseph Koshy 	PMCMASK(sse2-packed-double,	0x02),
2276ebccf1e3SJoseph Koshy 	PMCMASK(sse2-scalar-double,	0x03),
2277ebccf1e3SJoseph Koshy 	NULLMASK
2278ebccf1e3SJoseph Koshy };
2279ebccf1e3SJoseph Koshy 
2280ebccf1e3SJoseph Koshy /* P6 event parser */
2281ebccf1e3SJoseph Koshy static int
2282ebccf1e3SJoseph Koshy p6_allocate_pmc(enum pmc_event pe, char *ctrspec,
2283ebccf1e3SJoseph Koshy     struct pmc_op_pmcallocate *pmc_config)
2284ebccf1e3SJoseph Koshy {
2285ebccf1e3SJoseph Koshy 	char *e, *p, *q;
22861e862e5aSFabien Thomas 	uint64_t evmask;
2287ebccf1e3SJoseph Koshy 	int count, n;
2288ebccf1e3SJoseph Koshy 	const struct pmc_masks *pm, *pmask;
2289ebccf1e3SJoseph Koshy 
2290789140c0SJoseph Koshy 	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
2291f263522aSJoseph Koshy 	pmc_config->pm_md.pm_ppro.pm_ppro_config = 0;
2292ebccf1e3SJoseph Koshy 
2293ebccf1e3SJoseph Koshy 	evmask = 0;
2294ebccf1e3SJoseph Koshy 
2295ebccf1e3SJoseph Koshy #define	P6MASKSET(M)	pmask = p6_mask_ ## M
2296ebccf1e3SJoseph Koshy 
2297ebccf1e3SJoseph Koshy 	switch(pe) {
2298ebccf1e3SJoseph Koshy 	case PMC_EV_P6_L2_IFETCH:	P6MASKSET(mesi); break;
2299ebccf1e3SJoseph Koshy 	case PMC_EV_P6_L2_LD:		P6MASKSET(mesi); break;
2300ebccf1e3SJoseph Koshy 	case PMC_EV_P6_L2_ST:		P6MASKSET(mesi); break;
2301ebccf1e3SJoseph Koshy 	case PMC_EV_P6_L2_RQSTS:	P6MASKSET(mesi); break;
2302ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_DRDY_CLOCKS:
2303ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_LOCK_CLOCKS:
2304ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRAN_BRD:
2305ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRAN_RFO:
2306ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRANS_WB:
2307ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRAN_IFETCH:
2308ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRAN_INVAL:
2309ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRAN_PWR:
2310ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRANS_P:
2311ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRANS_IO:
2312ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRAN_DEF:
2313ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRAN_BURST:
2314ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRAN_ANY:
2315ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRAN_MEM:
2316ebccf1e3SJoseph Koshy 		P6MASKSET(any);	break;
2317ebccf1e3SJoseph Koshy 	case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED:
2318ebccf1e3SJoseph Koshy 	case PMC_EV_P6_EMON_KNI_PREF_MISS:
2319ebccf1e3SJoseph Koshy 		P6MASKSET(ekp); break;
2320ebccf1e3SJoseph Koshy 	case PMC_EV_P6_EMON_KNI_INST_RETIRED:
2321ebccf1e3SJoseph Koshy 	case PMC_EV_P6_EMON_KNI_COMP_INST_RET:
2322ebccf1e3SJoseph Koshy 		P6MASKSET(pps);	break;
2323ebccf1e3SJoseph Koshy 	case PMC_EV_P6_MMX_INSTR_TYPE_EXEC:
2324ebccf1e3SJoseph Koshy 		P6MASKSET(mite); break;
2325ebccf1e3SJoseph Koshy 	case PMC_EV_P6_FP_MMX_TRANS:
2326ebccf1e3SJoseph Koshy 		P6MASKSET(fmt);	break;
2327ebccf1e3SJoseph Koshy 	case PMC_EV_P6_SEG_RENAME_STALLS:
2328ebccf1e3SJoseph Koshy 	case PMC_EV_P6_SEG_REG_RENAMES:
2329ebccf1e3SJoseph Koshy 		P6MASKSET(sr);	break;
2330ebccf1e3SJoseph Koshy 	case PMC_EV_P6_EMON_EST_TRANS:
2331ebccf1e3SJoseph Koshy 		P6MASKSET(eet);	break;
2332ebccf1e3SJoseph Koshy 	case PMC_EV_P6_EMON_FUSED_UOPS_RET:
2333ebccf1e3SJoseph Koshy 		P6MASKSET(efur); break;
2334ebccf1e3SJoseph Koshy 	case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED:
2335ebccf1e3SJoseph Koshy 		P6MASKSET(essir); break;
2336ebccf1e3SJoseph Koshy 	case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED:
2337ebccf1e3SJoseph Koshy 		P6MASKSET(esscir); break;
2338ebccf1e3SJoseph Koshy 	default:
2339ebccf1e3SJoseph Koshy 		pmask = NULL;
2340ebccf1e3SJoseph Koshy 		break;
2341ebccf1e3SJoseph Koshy 	}
2342ebccf1e3SJoseph Koshy 
2343ebccf1e3SJoseph Koshy 	/* Pentium M PMCs have a few events with different semantics */
2344ebccf1e3SJoseph Koshy 	if (cpu_info.pm_cputype == PMC_CPU_INTEL_PM) {
2345ebccf1e3SJoseph Koshy 		if (pe == PMC_EV_P6_L2_LD ||
2346ebccf1e3SJoseph Koshy 		    pe == PMC_EV_P6_L2_LINES_IN ||
2347ebccf1e3SJoseph Koshy 		    pe == PMC_EV_P6_L2_LINES_OUT)
2348ebccf1e3SJoseph Koshy 			P6MASKSET(mesihw);
2349ebccf1e3SJoseph Koshy 		else if (pe == PMC_EV_P6_L2_M_LINES_OUTM)
2350ebccf1e3SJoseph Koshy 			P6MASKSET(hw);
2351ebccf1e3SJoseph Koshy 	}
2352ebccf1e3SJoseph Koshy 
2353ebccf1e3SJoseph Koshy 	/* Parse additional modifiers if present */
2354ebccf1e3SJoseph Koshy 	while ((p = strsep(&ctrspec, ",")) != NULL) {
2355ebccf1e3SJoseph Koshy 		if (KWPREFIXMATCH(p, P6_KW_CMASK "=")) {
2356ebccf1e3SJoseph Koshy 			q = strchr(p, '=');
2357ebccf1e3SJoseph Koshy 			if (*++q == '\0') /* skip '=' */
2358aa342b1fSJoseph Koshy 				return (-1);
2359ebccf1e3SJoseph Koshy 			count = strtol(q, &e, 0);
2360ebccf1e3SJoseph Koshy 			if (e == q || *e != '\0')
2361aa342b1fSJoseph Koshy 				return (-1);
2362ebccf1e3SJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
2363f263522aSJoseph Koshy 			pmc_config->pm_md.pm_ppro.pm_ppro_config |=
2364f263522aSJoseph Koshy 			    P6_EVSEL_TO_CMASK(count);
2365ebccf1e3SJoseph Koshy 		} else if (KWMATCH(p, P6_KW_EDGE)) {
2366ebccf1e3SJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_EDGE;
2367ebccf1e3SJoseph Koshy 		} else if (KWMATCH(p, P6_KW_INV)) {
2368ebccf1e3SJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_INVERT;
2369ebccf1e3SJoseph Koshy 		} else if (KWMATCH(p, P6_KW_OS)) {
2370ebccf1e3SJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_SYSTEM;
2371ebccf1e3SJoseph Koshy 		} else if (KWPREFIXMATCH(p, P6_KW_UMASK "=")) {
2372ebccf1e3SJoseph Koshy 			evmask = 0;
2373ebccf1e3SJoseph Koshy 			if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0)
2374aa342b1fSJoseph Koshy 				return (-1);
2375ebccf1e3SJoseph Koshy 			if ((pe == PMC_EV_P6_BUS_DRDY_CLOCKS ||
2376ebccf1e3SJoseph Koshy 			     pe == PMC_EV_P6_BUS_LOCK_CLOCKS ||
2377ebccf1e3SJoseph Koshy 			     pe == PMC_EV_P6_BUS_TRAN_BRD ||
2378ebccf1e3SJoseph Koshy 			     pe == PMC_EV_P6_BUS_TRAN_RFO ||
2379ebccf1e3SJoseph Koshy 			     pe == PMC_EV_P6_BUS_TRAN_IFETCH ||
2380ebccf1e3SJoseph Koshy 			     pe == PMC_EV_P6_BUS_TRAN_INVAL ||
2381ebccf1e3SJoseph Koshy 			     pe == PMC_EV_P6_BUS_TRAN_PWR ||
2382ebccf1e3SJoseph Koshy 			     pe == PMC_EV_P6_BUS_TRAN_DEF ||
2383ebccf1e3SJoseph Koshy 			     pe == PMC_EV_P6_BUS_TRAN_BURST ||
2384ebccf1e3SJoseph Koshy 			     pe == PMC_EV_P6_BUS_TRAN_ANY ||
2385ebccf1e3SJoseph Koshy 			     pe == PMC_EV_P6_BUS_TRAN_MEM ||
2386ebccf1e3SJoseph Koshy 			     pe == PMC_EV_P6_BUS_TRANS_IO ||
2387ebccf1e3SJoseph Koshy 			     pe == PMC_EV_P6_BUS_TRANS_P ||
2388ebccf1e3SJoseph Koshy 			     pe == PMC_EV_P6_BUS_TRANS_WB ||
2389ebccf1e3SJoseph Koshy 			     pe == PMC_EV_P6_EMON_EST_TRANS ||
2390ebccf1e3SJoseph Koshy 			     pe == PMC_EV_P6_EMON_FUSED_UOPS_RET ||
2391ebccf1e3SJoseph Koshy 			     pe == PMC_EV_P6_EMON_KNI_COMP_INST_RET ||
2392ebccf1e3SJoseph Koshy 			     pe == PMC_EV_P6_EMON_KNI_INST_RETIRED ||
2393ebccf1e3SJoseph Koshy 			     pe == PMC_EV_P6_EMON_KNI_PREF_DISPATCHED ||
2394ebccf1e3SJoseph Koshy 			     pe == PMC_EV_P6_EMON_KNI_PREF_MISS ||
2395ebccf1e3SJoseph Koshy 			     pe == PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED ||
2396ebccf1e3SJoseph Koshy 			     pe == PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED ||
2397ebccf1e3SJoseph Koshy 			     pe == PMC_EV_P6_FP_MMX_TRANS)
2398aa342b1fSJoseph Koshy 			    && (n > 1))	/* Only one mask keyword is allowed. */
2399aa342b1fSJoseph Koshy 				return (-1);
2400ebccf1e3SJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
2401ebccf1e3SJoseph Koshy 		} else if (KWMATCH(p, P6_KW_USR)) {
2402ebccf1e3SJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_USER;
2403ebccf1e3SJoseph Koshy 		} else
2404aa342b1fSJoseph Koshy 			return (-1);
2405ebccf1e3SJoseph Koshy 	}
2406ebccf1e3SJoseph Koshy 
2407ebccf1e3SJoseph Koshy 	/* post processing */
2408ebccf1e3SJoseph Koshy 	switch (pe) {
2409ebccf1e3SJoseph Koshy 
2410ebccf1e3SJoseph Koshy 		/*
2411ebccf1e3SJoseph Koshy 		 * The following events default to an evmask of 0
2412ebccf1e3SJoseph Koshy 		 */
2413ebccf1e3SJoseph Koshy 
2414ebccf1e3SJoseph Koshy 		/* default => 'self' */
2415ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_DRDY_CLOCKS:
2416ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_LOCK_CLOCKS:
2417ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRAN_BRD:
2418ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRAN_RFO:
2419ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRANS_WB:
2420ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRAN_IFETCH:
2421ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRAN_INVAL:
2422ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRAN_PWR:
2423ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRANS_P:
2424ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRANS_IO:
2425ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRAN_DEF:
2426ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRAN_BURST:
2427ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRAN_ANY:
2428ebccf1e3SJoseph Koshy 	case PMC_EV_P6_BUS_TRAN_MEM:
2429ebccf1e3SJoseph Koshy 
2430ebccf1e3SJoseph Koshy 		/* default => 'nta' */
2431ebccf1e3SJoseph Koshy 	case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED:
2432ebccf1e3SJoseph Koshy 	case PMC_EV_P6_EMON_KNI_PREF_MISS:
2433ebccf1e3SJoseph Koshy 
2434ebccf1e3SJoseph Koshy 		/* default => 'packed and scalar' */
2435ebccf1e3SJoseph Koshy 	case PMC_EV_P6_EMON_KNI_INST_RETIRED:
2436ebccf1e3SJoseph Koshy 	case PMC_EV_P6_EMON_KNI_COMP_INST_RET:
2437ebccf1e3SJoseph Koshy 
2438ebccf1e3SJoseph Koshy 		/* default => 'mmx to fp transitions' */
2439ebccf1e3SJoseph Koshy 	case PMC_EV_P6_FP_MMX_TRANS:
2440ebccf1e3SJoseph Koshy 
2441ebccf1e3SJoseph Koshy 		/* default => 'SSE Packed Single' */
2442ebccf1e3SJoseph Koshy 	case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED:
2443ebccf1e3SJoseph Koshy 	case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED:
2444ebccf1e3SJoseph Koshy 
2445ebccf1e3SJoseph Koshy 		/* default => 'all fused micro-ops' */
2446ebccf1e3SJoseph Koshy 	case PMC_EV_P6_EMON_FUSED_UOPS_RET:
2447ebccf1e3SJoseph Koshy 
2448ebccf1e3SJoseph Koshy 		/* default => 'all transitions' */
2449ebccf1e3SJoseph Koshy 	case PMC_EV_P6_EMON_EST_TRANS:
2450ebccf1e3SJoseph Koshy 		break;
2451ebccf1e3SJoseph Koshy 
2452ebccf1e3SJoseph Koshy 	case PMC_EV_P6_MMX_UOPS_EXEC:
2453ebccf1e3SJoseph Koshy 		evmask = 0x0F;		/* only value allowed */
2454ebccf1e3SJoseph Koshy 		break;
2455ebccf1e3SJoseph Koshy 
2456ebccf1e3SJoseph Koshy 	default:
2457ebccf1e3SJoseph Koshy 		/*
2458ebccf1e3SJoseph Koshy 		 * For all other events, set the default event mask
2459ebccf1e3SJoseph Koshy 		 * to a logical OR of all the allowed event mask bits.
2460ebccf1e3SJoseph Koshy 		 */
2461ebccf1e3SJoseph Koshy 		if (evmask == 0 && pmask) {
2462ebccf1e3SJoseph Koshy 			for (pm = pmask; pm->pm_name; pm++)
2463ebccf1e3SJoseph Koshy 				evmask |= pm->pm_value;
2464ebccf1e3SJoseph Koshy 			pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
2465ebccf1e3SJoseph Koshy 		}
2466ebccf1e3SJoseph Koshy 
2467ebccf1e3SJoseph Koshy 		break;
2468ebccf1e3SJoseph Koshy 	}
2469ebccf1e3SJoseph Koshy 
2470ebccf1e3SJoseph Koshy 	if (pmc_config->pm_caps & PMC_CAP_QUALIFIER)
2471f263522aSJoseph Koshy 		pmc_config->pm_md.pm_ppro.pm_ppro_config |=
2472f263522aSJoseph Koshy 		    P6_EVSEL_TO_UMASK(evmask);
2473ebccf1e3SJoseph Koshy 
2474aa342b1fSJoseph Koshy 	return (0);
2475ebccf1e3SJoseph Koshy }
2476ebccf1e3SJoseph Koshy 
2477ebccf1e3SJoseph Koshy #endif
2478ebccf1e3SJoseph Koshy 
2479789140c0SJoseph Koshy #if	defined(__i386__) || defined(__amd64__)
2480789140c0SJoseph Koshy static int
2481789140c0SJoseph Koshy tsc_allocate_pmc(enum pmc_event pe, char *ctrspec,
2482789140c0SJoseph Koshy     struct pmc_op_pmcallocate *pmc_config)
2483789140c0SJoseph Koshy {
2484789140c0SJoseph Koshy 	if (pe != PMC_EV_TSC_TSC)
2485789140c0SJoseph Koshy 		return (-1);
2486789140c0SJoseph Koshy 
2487789140c0SJoseph Koshy 	/* TSC events must be unqualified. */
2488789140c0SJoseph Koshy 	if (ctrspec && *ctrspec != '\0')
2489789140c0SJoseph Koshy 		return (-1);
2490789140c0SJoseph Koshy 
2491789140c0SJoseph Koshy 	pmc_config->pm_md.pm_amd.pm_amd_config = 0;
2492789140c0SJoseph Koshy 	pmc_config->pm_caps |= PMC_CAP_READ;
2493789140c0SJoseph Koshy 
2494789140c0SJoseph Koshy 	return (0);
2495789140c0SJoseph Koshy }
2496789140c0SJoseph Koshy #endif
2497789140c0SJoseph Koshy 
2498f5f9340bSFabien Thomas static struct pmc_event_alias generic_aliases[] = {
2499f5f9340bSFabien Thomas 	EV_ALIAS("instructions",		"SOFT-CLOCK.HARD"),
2500f5f9340bSFabien Thomas 	EV_ALIAS(NULL, NULL)
2501f5f9340bSFabien Thomas };
2502f5f9340bSFabien Thomas 
2503f5f9340bSFabien Thomas static int
2504f5f9340bSFabien Thomas soft_allocate_pmc(enum pmc_event pe, char *ctrspec,
2505f5f9340bSFabien Thomas     struct pmc_op_pmcallocate *pmc_config)
2506f5f9340bSFabien Thomas {
2507f5f9340bSFabien Thomas 	(void)ctrspec;
2508f5f9340bSFabien Thomas 	(void)pmc_config;
2509f5f9340bSFabien Thomas 
2510f0bbe9aaSDimitry Andric 	if ((int)pe < PMC_EV_SOFT_FIRST || (int)pe > PMC_EV_SOFT_LAST)
2511f5f9340bSFabien Thomas 		return (-1);
2512f5f9340bSFabien Thomas 
2513f5f9340bSFabien Thomas 	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
2514f5f9340bSFabien Thomas 	return (0);
2515f5f9340bSFabien Thomas }
2516f5f9340bSFabien Thomas 
25176411d14dSRuslan Bukin #if	defined(__arm__)
25180ce207d2SRui Paulo #if	defined(__XSCALE__)
25190ce207d2SRui Paulo 
25200ce207d2SRui Paulo static struct pmc_event_alias xscale_aliases[] = {
25210ce207d2SRui Paulo 	EV_ALIAS("branches",		"BRANCH_RETIRED"),
25220ce207d2SRui Paulo 	EV_ALIAS("branch-mispredicts",	"BRANCH_MISPRED"),
25230ce207d2SRui Paulo 	EV_ALIAS("dc-misses",		"DC_MISS"),
25240ce207d2SRui Paulo 	EV_ALIAS("ic-misses",		"IC_MISS"),
25250ce207d2SRui Paulo 	EV_ALIAS("instructions",	"INSTR_RETIRED"),
25260ce207d2SRui Paulo 	EV_ALIAS(NULL, NULL)
25270ce207d2SRui Paulo };
25280ce207d2SRui Paulo static int
25290ce207d2SRui Paulo xscale_allocate_pmc(enum pmc_event pe, char *ctrspec __unused,
25300ce207d2SRui Paulo     struct pmc_op_pmcallocate *pmc_config __unused)
25310ce207d2SRui Paulo {
25320ce207d2SRui Paulo 	switch (pe) {
25330ce207d2SRui Paulo 	default:
25340ce207d2SRui Paulo 		break;
25350ce207d2SRui Paulo 	}
25360ce207d2SRui Paulo 
25370ce207d2SRui Paulo 	return (0);
25380ce207d2SRui Paulo }
25390ce207d2SRui Paulo #endif
25400ce207d2SRui Paulo 
25413e0bfdd8SRuslan Bukin static struct pmc_event_alias cortex_a8_aliases[] = {
25426411d14dSRuslan Bukin 	EV_ALIAS("dc-misses",		"L1_DCACHE_REFILL"),
25436411d14dSRuslan Bukin 	EV_ALIAS("ic-misses",		"L1_ICACHE_REFILL"),
25446411d14dSRuslan Bukin 	EV_ALIAS("instructions",	"INSTR_EXECUTED"),
25456411d14dSRuslan Bukin 	EV_ALIAS(NULL, NULL)
25466411d14dSRuslan Bukin };
25473e0bfdd8SRuslan Bukin 
25483e0bfdd8SRuslan Bukin static struct pmc_event_alias cortex_a9_aliases[] = {
25493e0bfdd8SRuslan Bukin 	EV_ALIAS("dc-misses",		"L1_DCACHE_REFILL"),
25503e0bfdd8SRuslan Bukin 	EV_ALIAS("ic-misses",		"L1_ICACHE_REFILL"),
25513e0bfdd8SRuslan Bukin 	EV_ALIAS("instructions",	"INSTR_EXECUTED"),
25523e0bfdd8SRuslan Bukin 	EV_ALIAS(NULL, NULL)
25533e0bfdd8SRuslan Bukin };
25543e0bfdd8SRuslan Bukin 
25556411d14dSRuslan Bukin static int
25566411d14dSRuslan Bukin armv7_allocate_pmc(enum pmc_event pe, char *ctrspec __unused,
25576411d14dSRuslan Bukin     struct pmc_op_pmcallocate *pmc_config __unused)
25586411d14dSRuslan Bukin {
25596411d14dSRuslan Bukin 	switch (pe) {
25606411d14dSRuslan Bukin 	default:
25616411d14dSRuslan Bukin 		break;
25626411d14dSRuslan Bukin 	}
25636411d14dSRuslan Bukin 
25646411d14dSRuslan Bukin 	return (0);
25656411d14dSRuslan Bukin }
25666411d14dSRuslan Bukin #endif
25676411d14dSRuslan Bukin 
2568bc88bb2bSRuslan Bukin #if	defined(__aarch64__)
2569bc88bb2bSRuslan Bukin static struct pmc_event_alias cortex_a53_aliases[] = {
2570bc88bb2bSRuslan Bukin 	EV_ALIAS(NULL, NULL)
2571bc88bb2bSRuslan Bukin };
2572bc88bb2bSRuslan Bukin static struct pmc_event_alias cortex_a57_aliases[] = {
2573bc88bb2bSRuslan Bukin 	EV_ALIAS(NULL, NULL)
2574bc88bb2bSRuslan Bukin };
2575bc88bb2bSRuslan Bukin static int
2576bc88bb2bSRuslan Bukin arm64_allocate_pmc(enum pmc_event pe, char *ctrspec __unused,
2577bc88bb2bSRuslan Bukin     struct pmc_op_pmcallocate *pmc_config __unused)
2578bc88bb2bSRuslan Bukin {
2579bc88bb2bSRuslan Bukin 	switch (pe) {
2580bc88bb2bSRuslan Bukin 	default:
2581bc88bb2bSRuslan Bukin 		break;
2582bc88bb2bSRuslan Bukin 	}
2583bc88bb2bSRuslan Bukin 
2584bc88bb2bSRuslan Bukin 	return (0);
2585bc88bb2bSRuslan Bukin }
2586bc88bb2bSRuslan Bukin #endif
2587bc88bb2bSRuslan Bukin 
2588660df75eSGeorge V. Neville-Neil #if defined(__mips__)
2589660df75eSGeorge V. Neville-Neil 
2590660df75eSGeorge V. Neville-Neil static struct pmc_event_alias mips24k_aliases[] = {
2591660df75eSGeorge V. Neville-Neil 	EV_ALIAS("instructions",	"INSTR_EXECUTED"),
2592660df75eSGeorge V. Neville-Neil 	EV_ALIAS("branches",		"BRANCH_COMPLETED"),
2593660df75eSGeorge V. Neville-Neil 	EV_ALIAS("branch-mispredicts",	"BRANCH_MISPRED"),
2594660df75eSGeorge V. Neville-Neil 	EV_ALIAS(NULL, NULL)
2595660df75eSGeorge V. Neville-Neil };
2596660df75eSGeorge V. Neville-Neil 
2597f6e6460dSAdrian Chadd static struct pmc_event_alias mips74k_aliases[] = {
2598f6e6460dSAdrian Chadd 	EV_ALIAS("instructions",	"INSTR_EXECUTED"),
2599f6e6460dSAdrian Chadd 	EV_ALIAS("branches",		"BRANCH_INSNS"),
2600f6e6460dSAdrian Chadd 	EV_ALIAS("branch-mispredicts",	"MISPREDICTED_BRANCH_INSNS"),
2601f6e6460dSAdrian Chadd 	EV_ALIAS(NULL, NULL)
2602f6e6460dSAdrian Chadd };
2603f6e6460dSAdrian Chadd 
2604c2657f80SOleksandr Tymoshenko static struct pmc_event_alias octeon_aliases[] = {
2605c2657f80SOleksandr Tymoshenko 	EV_ALIAS("instructions",	"RET"),
2606c2657f80SOleksandr Tymoshenko 	EV_ALIAS("branches",		"BR"),
2607c2657f80SOleksandr Tymoshenko 	EV_ALIAS("branch-mispredicts",	"BRMIS"),
2608c2657f80SOleksandr Tymoshenko 	EV_ALIAS(NULL, NULL)
2609c2657f80SOleksandr Tymoshenko };
2610c2657f80SOleksandr Tymoshenko 
26112827d3e1SOleksandr Tymoshenko #define	MIPS_KW_OS		"os"
26122827d3e1SOleksandr Tymoshenko #define	MIPS_KW_USR		"usr"
26132827d3e1SOleksandr Tymoshenko #define	MIPS_KW_ANYTHREAD	"anythread"
2614660df75eSGeorge V. Neville-Neil 
2615660df75eSGeorge V. Neville-Neil static int
26162827d3e1SOleksandr Tymoshenko mips_allocate_pmc(enum pmc_event pe, char *ctrspec __unused,
2617660df75eSGeorge V. Neville-Neil 		  struct pmc_op_pmcallocate *pmc_config __unused)
2618660df75eSGeorge V. Neville-Neil {
2619660df75eSGeorge V. Neville-Neil 	char *p;
2620660df75eSGeorge V. Neville-Neil 
2621660df75eSGeorge V. Neville-Neil 	(void) pe;
2622660df75eSGeorge V. Neville-Neil 
2623660df75eSGeorge V. Neville-Neil 	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
2624660df75eSGeorge V. Neville-Neil 
2625660df75eSGeorge V. Neville-Neil 	while ((p = strsep(&ctrspec, ",")) != NULL) {
26262827d3e1SOleksandr Tymoshenko 		if (KWMATCH(p, MIPS_KW_OS))
2627660df75eSGeorge V. Neville-Neil 			pmc_config->pm_caps |= PMC_CAP_SYSTEM;
26282827d3e1SOleksandr Tymoshenko 		else if (KWMATCH(p, MIPS_KW_USR))
2629660df75eSGeorge V. Neville-Neil 			pmc_config->pm_caps |= PMC_CAP_USER;
26302827d3e1SOleksandr Tymoshenko 		else if (KWMATCH(p, MIPS_KW_ANYTHREAD))
2631660df75eSGeorge V. Neville-Neil 			pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM);
2632660df75eSGeorge V. Neville-Neil 		else
2633660df75eSGeorge V. Neville-Neil 			return (-1);
2634660df75eSGeorge V. Neville-Neil 	}
2635660df75eSGeorge V. Neville-Neil 
2636660df75eSGeorge V. Neville-Neil 	return (0);
2637660df75eSGeorge V. Neville-Neil }
26382827d3e1SOleksandr Tymoshenko 
2639660df75eSGeorge V. Neville-Neil #endif /* __mips__ */
2640660df75eSGeorge V. Neville-Neil 
26417b25dccaSJustin Hibbits #if defined(__powerpc__)
26427b25dccaSJustin Hibbits 
26437b25dccaSJustin Hibbits static struct pmc_event_alias ppc7450_aliases[] = {
26447b25dccaSJustin Hibbits 	EV_ALIAS("instructions",	"INSTR_COMPLETED"),
26457b25dccaSJustin Hibbits 	EV_ALIAS("branches",		"BRANCHES_COMPLETED"),
26467b25dccaSJustin Hibbits 	EV_ALIAS("branch-mispredicts",	"MISPREDICTED_BRANCHES"),
26477b25dccaSJustin Hibbits 	EV_ALIAS(NULL, NULL)
26487b25dccaSJustin Hibbits };
26497b25dccaSJustin Hibbits 
2650169dd953SJustin Hibbits static struct pmc_event_alias ppc970_aliases[] = {
2651169dd953SJustin Hibbits 	EV_ALIAS("instructions", "INSTR_COMPLETED"),
2652169dd953SJustin Hibbits 	EV_ALIAS("cycles",       "CYCLES"),
2653169dd953SJustin Hibbits 	EV_ALIAS(NULL, NULL)
2654169dd953SJustin Hibbits };
2655169dd953SJustin Hibbits 
2656a7452468SJustin Hibbits static struct pmc_event_alias e500_aliases[] = {
2657a7452468SJustin Hibbits 	EV_ALIAS("instructions", "INSTR_COMPLETED"),
2658a7452468SJustin Hibbits 	EV_ALIAS("cycles",       "CYCLES"),
2659a7452468SJustin Hibbits 	EV_ALIAS(NULL, NULL)
2660a7452468SJustin Hibbits };
2661a7452468SJustin Hibbits 
2662169dd953SJustin Hibbits #define	POWERPC_KW_OS		"os"
2663169dd953SJustin Hibbits #define	POWERPC_KW_USR		"usr"
2664169dd953SJustin Hibbits #define	POWERPC_KW_ANYTHREAD	"anythread"
26657b25dccaSJustin Hibbits 
26667b25dccaSJustin Hibbits static int
2667169dd953SJustin Hibbits powerpc_allocate_pmc(enum pmc_event pe, char *ctrspec __unused,
26687b25dccaSJustin Hibbits 		     struct pmc_op_pmcallocate *pmc_config __unused)
26697b25dccaSJustin Hibbits {
26707b25dccaSJustin Hibbits 	char *p;
26717b25dccaSJustin Hibbits 
26727b25dccaSJustin Hibbits 	(void) pe;
26737b25dccaSJustin Hibbits 
26747b25dccaSJustin Hibbits 	pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
26757b25dccaSJustin Hibbits 
26767b25dccaSJustin Hibbits 	while ((p = strsep(&ctrspec, ",")) != NULL) {
2677169dd953SJustin Hibbits 		if (KWMATCH(p, POWERPC_KW_OS))
26787b25dccaSJustin Hibbits 			pmc_config->pm_caps |= PMC_CAP_SYSTEM;
2679169dd953SJustin Hibbits 		else if (KWMATCH(p, POWERPC_KW_USR))
26807b25dccaSJustin Hibbits 			pmc_config->pm_caps |= PMC_CAP_USER;
2681169dd953SJustin Hibbits 		else if (KWMATCH(p, POWERPC_KW_ANYTHREAD))
26827b25dccaSJustin Hibbits 			pmc_config->pm_caps |= (PMC_CAP_USER | PMC_CAP_SYSTEM);
26837b25dccaSJustin Hibbits 		else
26847b25dccaSJustin Hibbits 			return (-1);
26857b25dccaSJustin Hibbits 	}
26867b25dccaSJustin Hibbits 
26877b25dccaSJustin Hibbits 	return (0);
26887b25dccaSJustin Hibbits }
2689169dd953SJustin Hibbits 
26907b25dccaSJustin Hibbits #endif /* __powerpc__ */
26917b25dccaSJustin Hibbits 
2692660df75eSGeorge V. Neville-Neil 
2693789140c0SJoseph Koshy /*
2694789140c0SJoseph Koshy  * Match an event name `name' with its canonical form.
2695789140c0SJoseph Koshy  *
26960cfab8ddSJoseph Koshy  * Matches are case insensitive and spaces, periods, underscores and
26970cfab8ddSJoseph Koshy  * hyphen characters are considered to match each other.
2698789140c0SJoseph Koshy  *
2699789140c0SJoseph Koshy  * Returns 1 for a match, 0 otherwise.
2700789140c0SJoseph Koshy  */
2701789140c0SJoseph Koshy 
2702789140c0SJoseph Koshy static int
2703789140c0SJoseph Koshy pmc_match_event_name(const char *name, const char *canonicalname)
2704789140c0SJoseph Koshy {
2705789140c0SJoseph Koshy 	int cc, nc;
2706789140c0SJoseph Koshy 	const unsigned char *c, *n;
2707789140c0SJoseph Koshy 
2708789140c0SJoseph Koshy 	c = (const unsigned char *) canonicalname;
2709789140c0SJoseph Koshy 	n = (const unsigned char *) name;
2710789140c0SJoseph Koshy 
2711789140c0SJoseph Koshy 	for (; (nc = *n) && (cc = *c); n++, c++) {
2712789140c0SJoseph Koshy 
27130cfab8ddSJoseph Koshy 		if ((nc == ' ' || nc == '_' || nc == '-' || nc == '.') &&
27140cfab8ddSJoseph Koshy 		    (cc == ' ' || cc == '_' || cc == '-' || cc == '.'))
2715789140c0SJoseph Koshy 			continue;
2716789140c0SJoseph Koshy 
27170cfab8ddSJoseph Koshy 		if (toupper(nc) == toupper(cc))
2718789140c0SJoseph Koshy 			continue;
2719789140c0SJoseph Koshy 
27200cfab8ddSJoseph Koshy 
2721789140c0SJoseph Koshy 		return (0);
2722789140c0SJoseph Koshy 	}
2723789140c0SJoseph Koshy 
2724789140c0SJoseph Koshy 	if (*n == '\0' && *c == '\0')
2725789140c0SJoseph Koshy 		return (1);
2726789140c0SJoseph Koshy 
2727789140c0SJoseph Koshy 	return (0);
2728789140c0SJoseph Koshy }
2729789140c0SJoseph Koshy 
2730789140c0SJoseph Koshy /*
2731789140c0SJoseph Koshy  * Match an event name against all the event named supported by a
2732789140c0SJoseph Koshy  * PMC class.
2733789140c0SJoseph Koshy  *
2734789140c0SJoseph Koshy  * Returns an event descriptor pointer on match or NULL otherwise.
2735789140c0SJoseph Koshy  */
2736789140c0SJoseph Koshy static const struct pmc_event_descr *
2737789140c0SJoseph Koshy pmc_match_event_class(const char *name,
2738789140c0SJoseph Koshy     const struct pmc_class_descr *pcd)
2739789140c0SJoseph Koshy {
2740789140c0SJoseph Koshy 	size_t n;
2741789140c0SJoseph Koshy 	const struct pmc_event_descr *ev;
2742789140c0SJoseph Koshy 
2743789140c0SJoseph Koshy 	ev = pcd->pm_evc_event_table;
2744789140c0SJoseph Koshy 	for (n = 0; n < pcd->pm_evc_event_table_size; n++, ev++)
2745789140c0SJoseph Koshy 		if (pmc_match_event_name(name, ev->pm_ev_name))
2746789140c0SJoseph Koshy 			return (ev);
2747789140c0SJoseph Koshy 
2748789140c0SJoseph Koshy 	return (NULL);
2749789140c0SJoseph Koshy }
2750789140c0SJoseph Koshy 
2751789140c0SJoseph Koshy static int
2752789140c0SJoseph Koshy pmc_mdep_is_compatible_class(enum pmc_class pc)
2753789140c0SJoseph Koshy {
2754789140c0SJoseph Koshy 	size_t n;
2755789140c0SJoseph Koshy 
2756789140c0SJoseph Koshy 	for (n = 0; n < pmc_mdep_class_list_size; n++)
2757789140c0SJoseph Koshy 		if (pmc_mdep_class_list[n] == pc)
2758789140c0SJoseph Koshy 			return (1);
2759789140c0SJoseph Koshy 	return (0);
2760789140c0SJoseph Koshy }
2761789140c0SJoseph Koshy 
2762ebccf1e3SJoseph Koshy /*
2763ebccf1e3SJoseph Koshy  * API entry points
2764ebccf1e3SJoseph Koshy  */
2765ebccf1e3SJoseph Koshy 
2766ebccf1e3SJoseph Koshy int
2767ebccf1e3SJoseph Koshy pmc_allocate(const char *ctrspec, enum pmc_mode mode,
2768ebccf1e3SJoseph Koshy     uint32_t flags, int cpu, pmc_id_t *pmcid)
2769ebccf1e3SJoseph Koshy {
2770789140c0SJoseph Koshy 	size_t n;
2771ebccf1e3SJoseph Koshy 	int retval;
2772ebccf1e3SJoseph Koshy 	char *r, *spec_copy;
2773ebccf1e3SJoseph Koshy 	const char *ctrname;
2774789140c0SJoseph Koshy 	const struct pmc_event_descr *ev;
2775789140c0SJoseph Koshy 	const struct pmc_event_alias *alias;
2776ebccf1e3SJoseph Koshy 	struct pmc_op_pmcallocate pmc_config;
2777789140c0SJoseph Koshy 	const struct pmc_class_descr *pcd;
2778ebccf1e3SJoseph Koshy 
2779ebccf1e3SJoseph Koshy 	spec_copy = NULL;
2780ebccf1e3SJoseph Koshy 	retval    = -1;
2781ebccf1e3SJoseph Koshy 
2782ebccf1e3SJoseph Koshy 	if (mode != PMC_MODE_SS && mode != PMC_MODE_TS &&
2783ebccf1e3SJoseph Koshy 	    mode != PMC_MODE_SC && mode != PMC_MODE_TC) {
2784*4f9b4ac4SEric van Gyzen 		errno = EINVAL;
2785*4f9b4ac4SEric van Gyzen 		goto out;
2786959826caSMatt Macy 	}
2787959826caSMatt Macy 	bzero(&pmc_config, sizeof(pmc_config));
2788959826caSMatt Macy 	pmc_config.pm_cpu   = cpu;
2789959826caSMatt Macy 	pmc_config.pm_mode  = mode;
2790959826caSMatt Macy 	pmc_config.pm_flags = flags;
2791959826caSMatt Macy 	if (PMC_IS_SAMPLING_MODE(mode))
2792959826caSMatt Macy 		pmc_config.pm_caps |= PMC_CAP_INTERRUPT;
2793959826caSMatt Macy 	/*
2794959826caSMatt Macy 	 * Can we pull this straight from the pmu table?
2795959826caSMatt Macy 	 */
2796959826caSMatt Macy 	r = spec_copy = strdup(ctrspec);
2797959826caSMatt Macy 	ctrname = strsep(&r, ",");
2798959826caSMatt Macy 	if (pmc_pmu_pmcallocate(ctrname, &pmc_config) == 0) {
2799ed50b918SMatt Macy 		if (PMC_CALL(PMCALLOCATE, &pmc_config) < 0) {
2800ed50b918SMatt Macy 			goto out;
2801ed50b918SMatt Macy 		}
28021a32aa0fSMatt Macy 		retval = 0;
2803959826caSMatt Macy 		*pmcid = pmc_config.pm_pmcid;
2804ed50b918SMatt Macy 		goto out;
2805959826caSMatt Macy 	} else {
2806959826caSMatt Macy 		free(spec_copy);
2807959826caSMatt Macy 		spec_copy = NULL;
2808ebccf1e3SJoseph Koshy 	}
2809ebccf1e3SJoseph Koshy 
2810ebccf1e3SJoseph Koshy 	/* replace an event alias with the canonical event specifier */
2811ebccf1e3SJoseph Koshy 	if (pmc_mdep_event_aliases)
2812789140c0SJoseph Koshy 		for (alias = pmc_mdep_event_aliases; alias->pm_alias; alias++)
2813789140c0SJoseph Koshy 			if (!strcasecmp(ctrspec, alias->pm_alias)) {
2814789140c0SJoseph Koshy 				spec_copy = strdup(alias->pm_spec);
2815ebccf1e3SJoseph Koshy 				break;
2816ebccf1e3SJoseph Koshy 			}
2817ebccf1e3SJoseph Koshy 
2818ebccf1e3SJoseph Koshy 	if (spec_copy == NULL)
2819ebccf1e3SJoseph Koshy 		spec_copy = strdup(ctrspec);
2820ebccf1e3SJoseph Koshy 
2821ebccf1e3SJoseph Koshy 	r = spec_copy;
2822ebccf1e3SJoseph Koshy 	ctrname = strsep(&r, ",");
2823ebccf1e3SJoseph Koshy 
2824789140c0SJoseph Koshy 	/*
2825789140c0SJoseph Koshy 	 * If a explicit class prefix was given by the user, restrict the
2826789140c0SJoseph Koshy 	 * search for the event to the specified PMC class.
2827789140c0SJoseph Koshy 	 */
2828789140c0SJoseph Koshy 	ev = NULL;
28290cfab8ddSJoseph Koshy 	for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) {
28300cfab8ddSJoseph Koshy 		pcd = pmc_class_table[n];
2831789140c0SJoseph Koshy 		if (pmc_mdep_is_compatible_class(pcd->pm_evc_class) &&
2832789140c0SJoseph Koshy 		    strncasecmp(ctrname, pcd->pm_evc_name,
2833789140c0SJoseph Koshy 				pcd->pm_evc_name_size) == 0) {
2834789140c0SJoseph Koshy 			if ((ev = pmc_match_event_class(ctrname +
2835789140c0SJoseph Koshy 			    pcd->pm_evc_name_size, pcd)) == NULL) {
2836789140c0SJoseph Koshy 				errno = EINVAL;
2837789140c0SJoseph Koshy 				goto out;
2838789140c0SJoseph Koshy 			}
2839ebccf1e3SJoseph Koshy 			break;
2840789140c0SJoseph Koshy 		}
2841789140c0SJoseph Koshy 	}
2842ebccf1e3SJoseph Koshy 
2843789140c0SJoseph Koshy 	/*
2844789140c0SJoseph Koshy 	 * Otherwise, search for this event in all compatible PMC
2845789140c0SJoseph Koshy 	 * classes.
2846789140c0SJoseph Koshy 	 */
28470cfab8ddSJoseph Koshy 	for (n = 0; ev == NULL && n < PMC_CLASS_TABLE_SIZE; n++) {
28480cfab8ddSJoseph Koshy 		pcd = pmc_class_table[n];
2849789140c0SJoseph Koshy 		if (pmc_mdep_is_compatible_class(pcd->pm_evc_class))
2850789140c0SJoseph Koshy 			ev = pmc_match_event_class(ctrname, pcd);
2851789140c0SJoseph Koshy 	}
2852789140c0SJoseph Koshy 
2853789140c0SJoseph Koshy 	if (ev == NULL) {
2854ebccf1e3SJoseph Koshy 		errno = EINVAL;
2855ebccf1e3SJoseph Koshy 		goto out;
2856ebccf1e3SJoseph Koshy 	}
2857ebccf1e3SJoseph Koshy 
2858789140c0SJoseph Koshy 	pmc_config.pm_ev    = ev->pm_ev_code;
2859789140c0SJoseph Koshy 	pmc_config.pm_class = pcd->pm_evc_class;
2860ebccf1e3SJoseph Koshy 
2861789140c0SJoseph Koshy  	if (pcd->pm_evc_allocate_pmc(ev->pm_ev_code, r, &pmc_config) < 0) {
2862ebccf1e3SJoseph Koshy 		errno = EINVAL;
2863ebccf1e3SJoseph Koshy 		goto out;
2864ebccf1e3SJoseph Koshy 	}
2865ebccf1e3SJoseph Koshy 
2866ebccf1e3SJoseph Koshy 	if (PMC_CALL(PMCALLOCATE, &pmc_config) < 0)
2867ebccf1e3SJoseph Koshy 		goto out;
2868ebccf1e3SJoseph Koshy 
2869ebccf1e3SJoseph Koshy 	*pmcid = pmc_config.pm_pmcid;
2870ebccf1e3SJoseph Koshy 
2871ebccf1e3SJoseph Koshy 	retval = 0;
2872ebccf1e3SJoseph Koshy 
2873ebccf1e3SJoseph Koshy  out:
2874ebccf1e3SJoseph Koshy 	if (spec_copy)
2875ebccf1e3SJoseph Koshy 		free(spec_copy);
2876ebccf1e3SJoseph Koshy 
2877aa342b1fSJoseph Koshy 	return (retval);
2878ebccf1e3SJoseph Koshy }
2879ebccf1e3SJoseph Koshy 
2880ebccf1e3SJoseph Koshy int
2881ebccf1e3SJoseph Koshy pmc_attach(pmc_id_t pmc, pid_t pid)
2882ebccf1e3SJoseph Koshy {
2883ebccf1e3SJoseph Koshy 	struct pmc_op_pmcattach pmc_attach_args;
2884ebccf1e3SJoseph Koshy 
2885ebccf1e3SJoseph Koshy 	pmc_attach_args.pm_pmc = pmc;
2886ebccf1e3SJoseph Koshy 	pmc_attach_args.pm_pid = pid;
2887ebccf1e3SJoseph Koshy 
2888aa342b1fSJoseph Koshy 	return (PMC_CALL(PMCATTACH, &pmc_attach_args));
2889ebccf1e3SJoseph Koshy }
2890ebccf1e3SJoseph Koshy 
2891ebccf1e3SJoseph Koshy int
2892c5153e19SJoseph Koshy pmc_capabilities(pmc_id_t pmcid, uint32_t *caps)
2893c5153e19SJoseph Koshy {
2894c5153e19SJoseph Koshy 	unsigned int i;
2895c5153e19SJoseph Koshy 	enum pmc_class cl;
2896c5153e19SJoseph Koshy 
2897c5153e19SJoseph Koshy 	cl = PMC_ID_TO_CLASS(pmcid);
2898c5153e19SJoseph Koshy 	for (i = 0; i < cpu_info.pm_nclass; i++)
2899c5153e19SJoseph Koshy 		if (cpu_info.pm_classes[i].pm_class == cl) {
2900c5153e19SJoseph Koshy 			*caps = cpu_info.pm_classes[i].pm_caps;
2901aa342b1fSJoseph Koshy 			return (0);
2902c5153e19SJoseph Koshy 		}
2903484202faSJoseph Koshy 	errno = EINVAL;
2904484202faSJoseph Koshy 	return (-1);
2905c5153e19SJoseph Koshy }
2906c5153e19SJoseph Koshy 
2907f263522aSJoseph Koshy int
2908f263522aSJoseph Koshy pmc_configure_logfile(int fd)
2909ebccf1e3SJoseph Koshy {
2910f263522aSJoseph Koshy 	struct pmc_op_configurelog cla;
2911f263522aSJoseph Koshy 
2912f263522aSJoseph Koshy 	cla.pm_logfd = fd;
2913f263522aSJoseph Koshy 	if (PMC_CALL(CONFIGURELOG, &cla) < 0)
2914aa342b1fSJoseph Koshy 		return (-1);
2915aa342b1fSJoseph Koshy 	return (0);
2916ebccf1e3SJoseph Koshy }
2917ebccf1e3SJoseph Koshy 
2918f263522aSJoseph Koshy int
2919f263522aSJoseph Koshy pmc_cpuinfo(const struct pmc_cpuinfo **pci)
2920ebccf1e3SJoseph Koshy {
2921f263522aSJoseph Koshy 	if (pmc_syscall == -1) {
2922f263522aSJoseph Koshy 		errno = ENXIO;
2923aa342b1fSJoseph Koshy 		return (-1);
2924ebccf1e3SJoseph Koshy 	}
2925ebccf1e3SJoseph Koshy 
29261455fcd3SJoseph Koshy 	*pci = &cpu_info;
2927aa342b1fSJoseph Koshy 	return (0);
2928ebccf1e3SJoseph Koshy }
2929ebccf1e3SJoseph Koshy 
2930f263522aSJoseph Koshy int
2931f263522aSJoseph Koshy pmc_detach(pmc_id_t pmc, pid_t pid)
2932ebccf1e3SJoseph Koshy {
2933f263522aSJoseph Koshy 	struct pmc_op_pmcattach pmc_detach_args;
2934ebccf1e3SJoseph Koshy 
2935f263522aSJoseph Koshy 	pmc_detach_args.pm_pmc = pmc;
2936f263522aSJoseph Koshy 	pmc_detach_args.pm_pid = pid;
2937aa342b1fSJoseph Koshy 	return (PMC_CALL(PMCDETACH, &pmc_detach_args));
2938ebccf1e3SJoseph Koshy }
2939ebccf1e3SJoseph Koshy 
2940f263522aSJoseph Koshy int
2941f263522aSJoseph Koshy pmc_disable(int cpu, int pmc)
2942ebccf1e3SJoseph Koshy {
2943f263522aSJoseph Koshy 	struct pmc_op_pmcadmin ssa;
2944ebccf1e3SJoseph Koshy 
2945f263522aSJoseph Koshy 	ssa.pm_cpu = cpu;
2946f263522aSJoseph Koshy 	ssa.pm_pmc = pmc;
2947f263522aSJoseph Koshy 	ssa.pm_state = PMC_STATE_DISABLED;
2948aa342b1fSJoseph Koshy 	return (PMC_CALL(PMCADMIN, &ssa));
2949ebccf1e3SJoseph Koshy }
2950ebccf1e3SJoseph Koshy 
2951f263522aSJoseph Koshy int
2952f263522aSJoseph Koshy pmc_enable(int cpu, int pmc)
2953ebccf1e3SJoseph Koshy {
2954f263522aSJoseph Koshy 	struct pmc_op_pmcadmin ssa;
2955ebccf1e3SJoseph Koshy 
2956f263522aSJoseph Koshy 	ssa.pm_cpu = cpu;
2957f263522aSJoseph Koshy 	ssa.pm_pmc = pmc;
2958f263522aSJoseph Koshy 	ssa.pm_state = PMC_STATE_FREE;
2959aa342b1fSJoseph Koshy 	return (PMC_CALL(PMCADMIN, &ssa));
2960ebccf1e3SJoseph Koshy }
2961ebccf1e3SJoseph Koshy 
2962ebccf1e3SJoseph Koshy /*
2963ebccf1e3SJoseph Koshy  * Return a list of events known to a given PMC class.  'cl' is the
2964ebccf1e3SJoseph Koshy  * PMC class identifier, 'eventnames' is the returned list of 'const
2965ebccf1e3SJoseph Koshy  * char *' pointers pointing to the names of the events. 'nevents' is
2966ebccf1e3SJoseph Koshy  * the number of event name pointers returned.
2967ebccf1e3SJoseph Koshy  *
2968ebccf1e3SJoseph Koshy  * The space for 'eventnames' is allocated using malloc(3).  The caller
2969ebccf1e3SJoseph Koshy  * is responsible for freeing this space when done.
2970ebccf1e3SJoseph Koshy  */
2971ebccf1e3SJoseph Koshy int
2972ebccf1e3SJoseph Koshy pmc_event_names_of_class(enum pmc_class cl, const char ***eventnames,
2973ebccf1e3SJoseph Koshy     int *nevents)
2974ebccf1e3SJoseph Koshy {
2975ebccf1e3SJoseph Koshy 	int count;
2976ebccf1e3SJoseph Koshy 	const char **names;
2977ebccf1e3SJoseph Koshy 	const struct pmc_event_descr *ev;
2978ebccf1e3SJoseph Koshy 
2979ebccf1e3SJoseph Koshy 	switch (cl)
2980ebccf1e3SJoseph Koshy 	{
29810cfab8ddSJoseph Koshy 	case PMC_CLASS_IAF:
29820cfab8ddSJoseph Koshy 		ev = iaf_event_table;
29830cfab8ddSJoseph Koshy 		count = PMC_EVENT_TABLE_SIZE(iaf);
29840cfab8ddSJoseph Koshy 		break;
29850cfab8ddSJoseph Koshy 	case PMC_CLASS_IAP:
29860cfab8ddSJoseph Koshy 		/*
29870cfab8ddSJoseph Koshy 		 * Return the most appropriate set of event name
29880cfab8ddSJoseph Koshy 		 * spellings for the current CPU.
29890cfab8ddSJoseph Koshy 		 */
29900cfab8ddSJoseph Koshy 		switch (cpu_info.pm_cputype) {
29910cfab8ddSJoseph Koshy 		default:
29920cfab8ddSJoseph Koshy 		case PMC_CPU_INTEL_ATOM:
29930cfab8ddSJoseph Koshy 			ev = atom_event_table;
29940cfab8ddSJoseph Koshy 			count = PMC_EVENT_TABLE_SIZE(atom);
29950cfab8ddSJoseph Koshy 			break;
2996e8f021a3SHiren Panchasara 		case PMC_CPU_INTEL_ATOM_SILVERMONT:
2997e8f021a3SHiren Panchasara 			ev = atom_silvermont_event_table;
2998e8f021a3SHiren Panchasara 			count = PMC_EVENT_TABLE_SIZE(atom_silvermont);
2999e8f021a3SHiren Panchasara 			break;
30000cfab8ddSJoseph Koshy 		case PMC_CPU_INTEL_CORE:
30010cfab8ddSJoseph Koshy 			ev = core_event_table;
30020cfab8ddSJoseph Koshy 			count = PMC_EVENT_TABLE_SIZE(core);
30030cfab8ddSJoseph Koshy 			break;
30040cfab8ddSJoseph Koshy 		case PMC_CPU_INTEL_CORE2:
3005b4d091f3SJoseph Koshy 		case PMC_CPU_INTEL_CORE2EXTREME:
30060cfab8ddSJoseph Koshy 			ev = core2_event_table;
30070cfab8ddSJoseph Koshy 			count = PMC_EVENT_TABLE_SIZE(core2);
30080cfab8ddSJoseph Koshy 			break;
3009597979c4SJeff Roberson 		case PMC_CPU_INTEL_COREI7:
3010597979c4SJeff Roberson 			ev = corei7_event_table;
3011597979c4SJeff Roberson 			count = PMC_EVENT_TABLE_SIZE(corei7);
3012597979c4SJeff Roberson 			break;
301349fe48abSKonstantin Belousov 		case PMC_CPU_INTEL_NEHALEM_EX:
301449fe48abSKonstantin Belousov 			ev = nehalem_ex_event_table;
301549fe48abSKonstantin Belousov 			count = PMC_EVENT_TABLE_SIZE(nehalem_ex);
301649fe48abSKonstantin Belousov 			break;
3017cc0c1555SSean Bruno 		case PMC_CPU_INTEL_HASWELL:
3018cc0c1555SSean Bruno 			ev = haswell_event_table;
3019cc0c1555SSean Bruno 			count = PMC_EVENT_TABLE_SIZE(haswell);
3020cc0c1555SSean Bruno 			break;
3021d95b3509SRandall Stewart 		case PMC_CPU_INTEL_HASWELL_XEON:
3022d95b3509SRandall Stewart 			ev = haswell_xeon_event_table;
3023d95b3509SRandall Stewart 			count = PMC_EVENT_TABLE_SIZE(haswell_xeon);
3024d95b3509SRandall Stewart 			break;
3025f19bae41SRandall Stewart 		case PMC_CPU_INTEL_BROADWELL:
3026f19bae41SRandall Stewart 			ev = broadwell_event_table;
3027f19bae41SRandall Stewart 			count = PMC_EVENT_TABLE_SIZE(broadwell);
3028f19bae41SRandall Stewart 			break;
3029f19bae41SRandall Stewart 		case PMC_CPU_INTEL_BROADWELL_XEON:
3030f19bae41SRandall Stewart 			ev = broadwell_xeon_event_table;
3031f19bae41SRandall Stewart 			count = PMC_EVENT_TABLE_SIZE(broadwell_xeon);
3032f19bae41SRandall Stewart 			break;
3033f19bae41SRandall Stewart 		case PMC_CPU_INTEL_SKYLAKE:
3034f19bae41SRandall Stewart 			ev = skylake_event_table;
3035f19bae41SRandall Stewart 			count = PMC_EVENT_TABLE_SIZE(skylake);
3036f19bae41SRandall Stewart 			break;
3037b99b705dSKonstantin Belousov 		case PMC_CPU_INTEL_SKYLAKE_XEON:
3038b99b705dSKonstantin Belousov 			ev = skylake_xeon_event_table;
3039b99b705dSKonstantin Belousov 			count = PMC_EVENT_TABLE_SIZE(skylake_xeon);
3040b99b705dSKonstantin Belousov 			break;
30411e862e5aSFabien Thomas 		case PMC_CPU_INTEL_IVYBRIDGE:
30421e862e5aSFabien Thomas 			ev = ivybridge_event_table;
30431e862e5aSFabien Thomas 			count = PMC_EVENT_TABLE_SIZE(ivybridge);
30441e862e5aSFabien Thomas 			break;
30453f929d8cSSean Bruno 		case PMC_CPU_INTEL_IVYBRIDGE_XEON:
30463f929d8cSSean Bruno 			ev = ivybridge_xeon_event_table;
30473f929d8cSSean Bruno 			count = PMC_EVENT_TABLE_SIZE(ivybridge_xeon);
30483f929d8cSSean Bruno 			break;
304978d763a2SDavide Italiano 		case PMC_CPU_INTEL_SANDYBRIDGE:
305078d763a2SDavide Italiano 			ev = sandybridge_event_table;
305178d763a2SDavide Italiano 			count = PMC_EVENT_TABLE_SIZE(sandybridge);
305278d763a2SDavide Italiano 			break;
3053fabe02f5SSean Bruno 		case PMC_CPU_INTEL_SANDYBRIDGE_XEON:
3054fabe02f5SSean Bruno 			ev = sandybridge_xeon_event_table;
3055fabe02f5SSean Bruno 			count = PMC_EVENT_TABLE_SIZE(sandybridge_xeon);
3056fabe02f5SSean Bruno 			break;
30571fa7f10bSFabien Thomas 		case PMC_CPU_INTEL_WESTMERE:
30581fa7f10bSFabien Thomas 			ev = westmere_event_table;
30591fa7f10bSFabien Thomas 			count = PMC_EVENT_TABLE_SIZE(westmere);
30601fa7f10bSFabien Thomas 			break;
306149fe48abSKonstantin Belousov 		case PMC_CPU_INTEL_WESTMERE_EX:
306249fe48abSKonstantin Belousov 			ev = westmere_ex_event_table;
306349fe48abSKonstantin Belousov 			count = PMC_EVENT_TABLE_SIZE(westmere_ex);
306449fe48abSKonstantin Belousov 			break;
30651fa7f10bSFabien Thomas 		}
30661fa7f10bSFabien Thomas 		break;
30671fa7f10bSFabien Thomas 	case PMC_CLASS_UCF:
30681fa7f10bSFabien Thomas 		ev = ucf_event_table;
30691fa7f10bSFabien Thomas 		count = PMC_EVENT_TABLE_SIZE(ucf);
30701fa7f10bSFabien Thomas 		break;
30711fa7f10bSFabien Thomas 	case PMC_CLASS_UCP:
30721fa7f10bSFabien Thomas 		/*
30731fa7f10bSFabien Thomas 		 * Return the most appropriate set of event name
30741fa7f10bSFabien Thomas 		 * spellings for the current CPU.
30751fa7f10bSFabien Thomas 		 */
30761fa7f10bSFabien Thomas 		switch (cpu_info.pm_cputype) {
30771fa7f10bSFabien Thomas 		default:
30781fa7f10bSFabien Thomas 		case PMC_CPU_INTEL_COREI7:
30791fa7f10bSFabien Thomas 			ev = corei7uc_event_table;
30801fa7f10bSFabien Thomas 			count = PMC_EVENT_TABLE_SIZE(corei7uc);
30811fa7f10bSFabien Thomas 			break;
3082cc0c1555SSean Bruno 		case PMC_CPU_INTEL_HASWELL:
3083cc0c1555SSean Bruno 			ev = haswelluc_event_table;
3084cc0c1555SSean Bruno 			count = PMC_EVENT_TABLE_SIZE(haswelluc);
3085cc0c1555SSean Bruno 			break;
3086f19bae41SRandall Stewart 		case PMC_CPU_INTEL_BROADWELL:
3087f19bae41SRandall Stewart 			ev = broadwelluc_event_table;
3088f19bae41SRandall Stewart 			count = PMC_EVENT_TABLE_SIZE(broadwelluc);
3089f19bae41SRandall Stewart 			break;
309078d763a2SDavide Italiano 		case PMC_CPU_INTEL_SANDYBRIDGE:
309178d763a2SDavide Italiano 			ev = sandybridgeuc_event_table;
309278d763a2SDavide Italiano 			count = PMC_EVENT_TABLE_SIZE(sandybridgeuc);
309378d763a2SDavide Italiano 			break;
30941fa7f10bSFabien Thomas 		case PMC_CPU_INTEL_WESTMERE:
30951fa7f10bSFabien Thomas 			ev = westmereuc_event_table;
30961fa7f10bSFabien Thomas 			count = PMC_EVENT_TABLE_SIZE(westmereuc);
30971fa7f10bSFabien Thomas 			break;
30980cfab8ddSJoseph Koshy 		}
30990cfab8ddSJoseph Koshy 		break;
3100ebccf1e3SJoseph Koshy 	case PMC_CLASS_TSC:
3101789140c0SJoseph Koshy 		ev = tsc_event_table;
3102789140c0SJoseph Koshy 		count = PMC_EVENT_TABLE_SIZE(tsc);
3103ebccf1e3SJoseph Koshy 		break;
3104ebccf1e3SJoseph Koshy 	case PMC_CLASS_K7:
3105789140c0SJoseph Koshy 		ev = k7_event_table;
3106789140c0SJoseph Koshy 		count = PMC_EVENT_TABLE_SIZE(k7);
3107ebccf1e3SJoseph Koshy 		break;
3108ebccf1e3SJoseph Koshy 	case PMC_CLASS_K8:
3109789140c0SJoseph Koshy 		ev = k8_event_table;
3110789140c0SJoseph Koshy 		count = PMC_EVENT_TABLE_SIZE(k8);
3111ebccf1e3SJoseph Koshy 		break;
3112ebccf1e3SJoseph Koshy 	case PMC_CLASS_P4:
3113789140c0SJoseph Koshy 		ev = p4_event_table;
3114789140c0SJoseph Koshy 		count = PMC_EVENT_TABLE_SIZE(p4);
3115789140c0SJoseph Koshy 		break;
3116789140c0SJoseph Koshy 	case PMC_CLASS_P5:
3117789140c0SJoseph Koshy 		ev = p5_event_table;
3118789140c0SJoseph Koshy 		count = PMC_EVENT_TABLE_SIZE(p5);
3119789140c0SJoseph Koshy 		break;
3120789140c0SJoseph Koshy 	case PMC_CLASS_P6:
3121789140c0SJoseph Koshy 		ev = p6_event_table;
3122789140c0SJoseph Koshy 		count = PMC_EVENT_TABLE_SIZE(p6);
3123ebccf1e3SJoseph Koshy 		break;
31240ce207d2SRui Paulo 	case PMC_CLASS_XSCALE:
31250ce207d2SRui Paulo 		ev = xscale_event_table;
31260ce207d2SRui Paulo 		count = PMC_EVENT_TABLE_SIZE(xscale);
31270ce207d2SRui Paulo 		break;
31286411d14dSRuslan Bukin 	case PMC_CLASS_ARMV7:
31293e0bfdd8SRuslan Bukin 		switch (cpu_info.pm_cputype) {
31303e0bfdd8SRuslan Bukin 		default:
31313e0bfdd8SRuslan Bukin 		case PMC_CPU_ARMV7_CORTEX_A8:
31323e0bfdd8SRuslan Bukin 			ev = cortex_a8_event_table;
31333e0bfdd8SRuslan Bukin 			count = PMC_EVENT_TABLE_SIZE(cortex_a8);
31343e0bfdd8SRuslan Bukin 			break;
31353e0bfdd8SRuslan Bukin 		case PMC_CPU_ARMV7_CORTEX_A9:
31363e0bfdd8SRuslan Bukin 			ev = cortex_a9_event_table;
31373e0bfdd8SRuslan Bukin 			count = PMC_EVENT_TABLE_SIZE(cortex_a9);
31383e0bfdd8SRuslan Bukin 			break;
31393e0bfdd8SRuslan Bukin 		}
31406411d14dSRuslan Bukin 		break;
3141bc88bb2bSRuslan Bukin 	case PMC_CLASS_ARMV8:
3142bc88bb2bSRuslan Bukin 		switch (cpu_info.pm_cputype) {
3143bc88bb2bSRuslan Bukin 		default:
3144bc88bb2bSRuslan Bukin 		case PMC_CPU_ARMV8_CORTEX_A53:
3145bc88bb2bSRuslan Bukin 			ev = cortex_a53_event_table;
3146bc88bb2bSRuslan Bukin 			count = PMC_EVENT_TABLE_SIZE(cortex_a53);
3147bc88bb2bSRuslan Bukin 			break;
3148bc88bb2bSRuslan Bukin 		case PMC_CPU_ARMV8_CORTEX_A57:
3149bc88bb2bSRuslan Bukin 			ev = cortex_a57_event_table;
3150bc88bb2bSRuslan Bukin 			count = PMC_EVENT_TABLE_SIZE(cortex_a57);
3151bc88bb2bSRuslan Bukin 			break;
3152bc88bb2bSRuslan Bukin 		}
3153bc88bb2bSRuslan Bukin 		break;
3154660df75eSGeorge V. Neville-Neil 	case PMC_CLASS_MIPS24K:
3155660df75eSGeorge V. Neville-Neil 		ev = mips24k_event_table;
3156660df75eSGeorge V. Neville-Neil 		count = PMC_EVENT_TABLE_SIZE(mips24k);
3157660df75eSGeorge V. Neville-Neil 		break;
3158f6e6460dSAdrian Chadd 	case PMC_CLASS_MIPS74K:
3159f6e6460dSAdrian Chadd 		ev = mips74k_event_table;
3160f6e6460dSAdrian Chadd 		count = PMC_EVENT_TABLE_SIZE(mips74k);
3161f6e6460dSAdrian Chadd 		break;
3162c2657f80SOleksandr Tymoshenko 	case PMC_CLASS_OCTEON:
3163c2657f80SOleksandr Tymoshenko 		ev = octeon_event_table;
3164c2657f80SOleksandr Tymoshenko 		count = PMC_EVENT_TABLE_SIZE(octeon);
3165c2657f80SOleksandr Tymoshenko 		break;
31667b25dccaSJustin Hibbits 	case PMC_CLASS_PPC7450:
31677b25dccaSJustin Hibbits 		ev = ppc7450_event_table;
31687b25dccaSJustin Hibbits 		count = PMC_EVENT_TABLE_SIZE(ppc7450);
31697b25dccaSJustin Hibbits 		break;
3170169dd953SJustin Hibbits 	case PMC_CLASS_PPC970:
3171169dd953SJustin Hibbits 		ev = ppc970_event_table;
3172169dd953SJustin Hibbits 		count = PMC_EVENT_TABLE_SIZE(ppc970);
3173169dd953SJustin Hibbits 		break;
3174a7452468SJustin Hibbits 	case PMC_CLASS_E500:
3175a7452468SJustin Hibbits 		ev = e500_event_table;
3176a7452468SJustin Hibbits 		count = PMC_EVENT_TABLE_SIZE(e500);
3177a7452468SJustin Hibbits 		break;
3178f5f9340bSFabien Thomas 	case PMC_CLASS_SOFT:
3179f5f9340bSFabien Thomas 		ev = soft_event_table;
3180f5f9340bSFabien Thomas 		count = soft_event_info.pm_nevent;
3181f5f9340bSFabien Thomas 		break;
3182ebccf1e3SJoseph Koshy 	default:
3183ebccf1e3SJoseph Koshy 		errno = EINVAL;
3184aa342b1fSJoseph Koshy 		return (-1);
3185ebccf1e3SJoseph Koshy 	}
3186ebccf1e3SJoseph Koshy 
3187ebccf1e3SJoseph Koshy 	if ((names = malloc(count * sizeof(const char *))) == NULL)
3188aa342b1fSJoseph Koshy 		return (-1);
3189ebccf1e3SJoseph Koshy 
3190ebccf1e3SJoseph Koshy 	*eventnames = names;
3191ebccf1e3SJoseph Koshy 	*nevents = count;
3192ebccf1e3SJoseph Koshy 
3193ebccf1e3SJoseph Koshy 	for (;count--; ev++, names++)
3194ebccf1e3SJoseph Koshy 		*names = ev->pm_ev_name;
3195f5f9340bSFabien Thomas 
3196aa342b1fSJoseph Koshy 	return (0);
3197ebccf1e3SJoseph Koshy }
3198ebccf1e3SJoseph Koshy 
3199f263522aSJoseph Koshy int
3200f263522aSJoseph Koshy pmc_flush_logfile(void)
3201f263522aSJoseph Koshy {
3202aa342b1fSJoseph Koshy 	return (PMC_CALL(FLUSHLOG,0));
3203f263522aSJoseph Koshy }
3204ebccf1e3SJoseph Koshy 
3205ebccf1e3SJoseph Koshy int
3206dceed24aSFabien Thomas pmc_close_logfile(void)
3207dceed24aSFabien Thomas {
3208dceed24aSFabien Thomas 	return (PMC_CALL(CLOSELOG,0));
3209dceed24aSFabien Thomas }
3210dceed24aSFabien Thomas 
3211dceed24aSFabien Thomas int
3212f263522aSJoseph Koshy pmc_get_driver_stats(struct pmc_driverstats *ds)
3213ebccf1e3SJoseph Koshy {
3214f263522aSJoseph Koshy 	struct pmc_op_getdriverstats gms;
3215f263522aSJoseph Koshy 
3216f263522aSJoseph Koshy 	if (PMC_CALL(GETDRIVERSTATS, &gms) < 0)
3217aa342b1fSJoseph Koshy 		return (-1);
3218f263522aSJoseph Koshy 
3219f263522aSJoseph Koshy 	/* copy out fields in the current userland<->library interface */
3220f263522aSJoseph Koshy 	ds->pm_intr_ignored    = gms.pm_intr_ignored;
3221f263522aSJoseph Koshy 	ds->pm_intr_processed  = gms.pm_intr_processed;
3222f263522aSJoseph Koshy 	ds->pm_intr_bufferfull = gms.pm_intr_bufferfull;
3223f263522aSJoseph Koshy 	ds->pm_syscalls        = gms.pm_syscalls;
3224f263522aSJoseph Koshy 	ds->pm_syscall_errors  = gms.pm_syscall_errors;
3225f263522aSJoseph Koshy 	ds->pm_buffer_requests = gms.pm_buffer_requests;
3226f263522aSJoseph Koshy 	ds->pm_buffer_requests_failed = gms.pm_buffer_requests_failed;
3227f263522aSJoseph Koshy 	ds->pm_log_sweeps      = gms.pm_log_sweeps;
3228aa342b1fSJoseph Koshy 	return (0);
3229f263522aSJoseph Koshy }
3230f263522aSJoseph Koshy 
3231f263522aSJoseph Koshy int
3232f263522aSJoseph Koshy pmc_get_msr(pmc_id_t pmc, uint32_t *msr)
3233f263522aSJoseph Koshy {
3234f263522aSJoseph Koshy 	struct pmc_op_getmsr gm;
3235ebccf1e3SJoseph Koshy 
3236ebccf1e3SJoseph Koshy 	gm.pm_pmcid = pmc;
3237f263522aSJoseph Koshy 	if (PMC_CALL(PMCGETMSR, &gm) < 0)
3238aa342b1fSJoseph Koshy 		return (-1);
3239ebccf1e3SJoseph Koshy 	*msr = gm.pm_msr;
3240aa342b1fSJoseph Koshy 	return (0);
3241ebccf1e3SJoseph Koshy }
3242ebccf1e3SJoseph Koshy 
3243f263522aSJoseph Koshy int
3244f263522aSJoseph Koshy pmc_init(void)
3245f263522aSJoseph Koshy {
3246f263522aSJoseph Koshy 	int error, pmc_mod_id;
32471455fcd3SJoseph Koshy 	unsigned int n;
3248f263522aSJoseph Koshy 	uint32_t abi_version;
3249f263522aSJoseph Koshy 	struct module_stat pmc_modstat;
32501455fcd3SJoseph Koshy 	struct pmc_op_getcpuinfo op_cpu_info;
3251791f5d5bSJoseph Koshy #if defined(__amd64__) || defined(__i386__)
3252791f5d5bSJoseph Koshy 	int cpu_has_iaf_counters;
3253791f5d5bSJoseph Koshy 	unsigned int t;
3254791f5d5bSJoseph Koshy #endif
3255f263522aSJoseph Koshy 
3256f263522aSJoseph Koshy 	if (pmc_syscall != -1) /* already inited */
3257aa342b1fSJoseph Koshy 		return (0);
3258f263522aSJoseph Koshy 
3259f263522aSJoseph Koshy 	/* retrieve the system call number from the KLD */
3260f263522aSJoseph Koshy 	if ((pmc_mod_id = modfind(PMC_MODULE_NAME)) < 0)
3261aa342b1fSJoseph Koshy 		return (-1);
3262f263522aSJoseph Koshy 
3263f263522aSJoseph Koshy 	pmc_modstat.version = sizeof(struct module_stat);
3264f263522aSJoseph Koshy 	if ((error = modstat(pmc_mod_id, &pmc_modstat)) < 0)
3265aa342b1fSJoseph Koshy 		return (-1);
3266f263522aSJoseph Koshy 
3267f263522aSJoseph Koshy 	pmc_syscall = pmc_modstat.data.intval;
3268f263522aSJoseph Koshy 
3269f263522aSJoseph Koshy 	/* check the kernel module's ABI against our compiled-in version */
3270f263522aSJoseph Koshy 	abi_version = PMC_VERSION;
3271f263522aSJoseph Koshy 	if (PMC_CALL(GETMODULEVERSION, &abi_version) < 0)
3272f263522aSJoseph Koshy 		return (pmc_syscall = -1);
3273f263522aSJoseph Koshy 
327475f46cf6SPedro F. Giffuni 	/* ignore patch & minor numbers for the comparison */
3275f263522aSJoseph Koshy 	if ((abi_version & 0xFF000000) != (PMC_VERSION & 0xFF000000)) {
3276f263522aSJoseph Koshy 		errno  = EPROGMISMATCH;
3277f263522aSJoseph Koshy 		return (pmc_syscall = -1);
3278f263522aSJoseph Koshy 	}
3279f263522aSJoseph Koshy 
32801455fcd3SJoseph Koshy 	if (PMC_CALL(GETCPUINFO, &op_cpu_info) < 0)
3281f263522aSJoseph Koshy 		return (pmc_syscall = -1);
3282f263522aSJoseph Koshy 
32831455fcd3SJoseph Koshy 	cpu_info.pm_cputype = op_cpu_info.pm_cputype;
32841455fcd3SJoseph Koshy 	cpu_info.pm_ncpu    = op_cpu_info.pm_ncpu;
32851455fcd3SJoseph Koshy 	cpu_info.pm_npmc    = op_cpu_info.pm_npmc;
32861455fcd3SJoseph Koshy 	cpu_info.pm_nclass  = op_cpu_info.pm_nclass;
32871455fcd3SJoseph Koshy 	for (n = 0; n < cpu_info.pm_nclass; n++)
3288b83aeb5cSJustin Hibbits 		memcpy(&cpu_info.pm_classes[n], &op_cpu_info.pm_classes[n],
3289b83aeb5cSJustin Hibbits 		    sizeof(cpu_info.pm_classes[n]));
32901455fcd3SJoseph Koshy 
32910cfab8ddSJoseph Koshy 	pmc_class_table = malloc(PMC_CLASS_TABLE_SIZE *
32920cfab8ddSJoseph Koshy 	    sizeof(struct pmc_class_descr *));
32930cfab8ddSJoseph Koshy 
32940cfab8ddSJoseph Koshy 	if (pmc_class_table == NULL)
32950cfab8ddSJoseph Koshy 		return (-1);
32960cfab8ddSJoseph Koshy 
3297791f5d5bSJoseph Koshy 	for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++)
3298791f5d5bSJoseph Koshy 		pmc_class_table[n] = NULL;
32990cfab8ddSJoseph Koshy 
33000cfab8ddSJoseph Koshy 	/*
3301f5f9340bSFabien Thomas 	 * Get soft events list.
3302f5f9340bSFabien Thomas 	 */
3303f5f9340bSFabien Thomas 	soft_event_info.pm_class = PMC_CLASS_SOFT;
3304f5f9340bSFabien Thomas 	if (PMC_CALL(GETDYNEVENTINFO, &soft_event_info) < 0)
3305f5f9340bSFabien Thomas 		return (pmc_syscall = -1);
3306f5f9340bSFabien Thomas 
3307f5f9340bSFabien Thomas 	/* Map soft events to static list. */
3308f5f9340bSFabien Thomas 	for (n = 0; n < soft_event_info.pm_nevent; n++) {
3309f5f9340bSFabien Thomas 		soft_event_table[n].pm_ev_name =
3310f5f9340bSFabien Thomas 		    soft_event_info.pm_events[n].pm_ev_name;
3311f5f9340bSFabien Thomas 		soft_event_table[n].pm_ev_code =
3312f5f9340bSFabien Thomas 		    soft_event_info.pm_events[n].pm_ev_code;
3313f5f9340bSFabien Thomas 	}
3314f5f9340bSFabien Thomas 	soft_class_table_descr.pm_evc_event_table_size = \
3315f5f9340bSFabien Thomas 	    soft_event_info.pm_nevent;
3316f5f9340bSFabien Thomas 	soft_class_table_descr.pm_evc_event_table = \
3317f5f9340bSFabien Thomas 	    soft_event_table;
3318f5f9340bSFabien Thomas 
3319f5f9340bSFabien Thomas 	/*
33200cfab8ddSJoseph Koshy 	 * Fill in the class table.
33210cfab8ddSJoseph Koshy 	 */
33220cfab8ddSJoseph Koshy 	n = 0;
3323f5f9340bSFabien Thomas 
3324f5f9340bSFabien Thomas 	/* Fill soft events information. */
3325f5f9340bSFabien Thomas 	pmc_class_table[n++] = &soft_class_table_descr;
33260cfab8ddSJoseph Koshy #if defined(__amd64__) || defined(__i386__)
3327f5f9340bSFabien Thomas 	if (cpu_info.pm_cputype != PMC_CPU_GENERIC)
33280cfab8ddSJoseph Koshy 		pmc_class_table[n++] = &tsc_class_table_descr;
3329791f5d5bSJoseph Koshy 
3330791f5d5bSJoseph Koshy 	/*
3331791f5d5bSJoseph Koshy  	 * Check if this CPU has fixed function counters.
3332791f5d5bSJoseph Koshy 	 */
3333791f5d5bSJoseph Koshy 	cpu_has_iaf_counters = 0;
3334791f5d5bSJoseph Koshy 	for (t = 0; t < cpu_info.pm_nclass; t++)
33352aef9dd6SFabien Thomas 		if (cpu_info.pm_classes[t].pm_class == PMC_CLASS_IAF &&
33362aef9dd6SFabien Thomas 		    cpu_info.pm_classes[t].pm_num > 0)
3337791f5d5bSJoseph Koshy 			cpu_has_iaf_counters = 1;
33380cfab8ddSJoseph Koshy #endif
33390cfab8ddSJoseph Koshy 
3340789140c0SJoseph Koshy #define	PMC_MDEP_INIT(C) do {					\
3341789140c0SJoseph Koshy 		pmc_mdep_event_aliases    = C##_aliases;	\
3342789140c0SJoseph Koshy 		pmc_mdep_class_list  = C##_pmc_classes;		\
3343789140c0SJoseph Koshy 		pmc_mdep_class_list_size =			\
3344789140c0SJoseph Koshy 		    PMC_TABLE_SIZE(C##_pmc_classes);		\
3345789140c0SJoseph Koshy 	} while (0)
3346789140c0SJoseph Koshy 
3347791f5d5bSJoseph Koshy #define	PMC_MDEP_INIT_INTEL_V2(C) do {					\
3348791f5d5bSJoseph Koshy 		PMC_MDEP_INIT(C);					\
3349791f5d5bSJoseph Koshy 		pmc_class_table[n++] = &iaf_class_table_descr;		\
33502aef9dd6SFabien Thomas 		if (!cpu_has_iaf_counters) 				\
3351791f5d5bSJoseph Koshy 			pmc_mdep_event_aliases =			\
3352791f5d5bSJoseph Koshy 				C##_aliases_without_iaf;		\
3353791f5d5bSJoseph Koshy 		pmc_class_table[n] = &C##_class_table_descr;		\
3354791f5d5bSJoseph Koshy 	} while (0)
3355791f5d5bSJoseph Koshy 
3356789140c0SJoseph Koshy 	/* Configure the event name parser. */
3357f263522aSJoseph Koshy 	switch (cpu_info.pm_cputype) {
3358f263522aSJoseph Koshy #if defined(__i386__)
3359f263522aSJoseph Koshy 	case PMC_CPU_AMD_K7:
3360789140c0SJoseph Koshy 		PMC_MDEP_INIT(k7);
33610cfab8ddSJoseph Koshy 		pmc_class_table[n] = &k7_class_table_descr;
3362f263522aSJoseph Koshy 		break;
3363f263522aSJoseph Koshy 	case PMC_CPU_INTEL_P5:
3364789140c0SJoseph Koshy 		PMC_MDEP_INIT(p5);
33650cfab8ddSJoseph Koshy 		pmc_class_table[n]  = &p5_class_table_descr;
3366f263522aSJoseph Koshy 		break;
3367f263522aSJoseph Koshy 	case PMC_CPU_INTEL_P6:		/* P6 ... Pentium M CPUs have */
3368f263522aSJoseph Koshy 	case PMC_CPU_INTEL_PII:		/* similar PMCs. */
3369f263522aSJoseph Koshy 	case PMC_CPU_INTEL_PIII:
3370f263522aSJoseph Koshy 	case PMC_CPU_INTEL_PM:
3371789140c0SJoseph Koshy 		PMC_MDEP_INIT(p6);
33720cfab8ddSJoseph Koshy 		pmc_class_table[n] = &p6_class_table_descr;
3373f263522aSJoseph Koshy 		break;
337486a65549SJoseph Koshy #endif
337586a65549SJoseph Koshy #if defined(__amd64__) || defined(__i386__)
3376f263522aSJoseph Koshy 	case PMC_CPU_AMD_K8:
3377789140c0SJoseph Koshy 		PMC_MDEP_INIT(k8);
33780cfab8ddSJoseph Koshy 		pmc_class_table[n] = &k8_class_table_descr;
33790cfab8ddSJoseph Koshy 		break;
33800cfab8ddSJoseph Koshy 	case PMC_CPU_INTEL_ATOM:
3381791f5d5bSJoseph Koshy 		PMC_MDEP_INIT_INTEL_V2(atom);
33820cfab8ddSJoseph Koshy 		break;
3383e8f021a3SHiren Panchasara 	case PMC_CPU_INTEL_ATOM_SILVERMONT:
3384e8f021a3SHiren Panchasara 		PMC_MDEP_INIT_INTEL_V2(atom_silvermont);
3385e8f021a3SHiren Panchasara 		break;
33860cfab8ddSJoseph Koshy 	case PMC_CPU_INTEL_CORE:
33870cfab8ddSJoseph Koshy 		PMC_MDEP_INIT(core);
3388bc315bbdSJoseph Koshy 		pmc_class_table[n] = &core_class_table_descr;
33890cfab8ddSJoseph Koshy 		break;
33900cfab8ddSJoseph Koshy 	case PMC_CPU_INTEL_CORE2:
3391b4d091f3SJoseph Koshy 	case PMC_CPU_INTEL_CORE2EXTREME:
3392791f5d5bSJoseph Koshy 		PMC_MDEP_INIT_INTEL_V2(core2);
3393789140c0SJoseph Koshy 		break;
3394597979c4SJeff Roberson 	case PMC_CPU_INTEL_COREI7:
33951fa7f10bSFabien Thomas 		pmc_class_table[n++] = &ucf_class_table_descr;
33961fa7f10bSFabien Thomas 		pmc_class_table[n++] = &corei7uc_class_table_descr;
3397791f5d5bSJoseph Koshy 		PMC_MDEP_INIT_INTEL_V2(corei7);
3398597979c4SJeff Roberson 		break;
339949fe48abSKonstantin Belousov 	case PMC_CPU_INTEL_NEHALEM_EX:
340049fe48abSKonstantin Belousov 		PMC_MDEP_INIT_INTEL_V2(nehalem_ex);
340149fe48abSKonstantin Belousov 		break;
3402cc0c1555SSean Bruno 	case PMC_CPU_INTEL_HASWELL:
3403cc0c1555SSean Bruno 		pmc_class_table[n++] = &ucf_class_table_descr;
3404cc0c1555SSean Bruno 		pmc_class_table[n++] = &haswelluc_class_table_descr;
3405cc0c1555SSean Bruno 		PMC_MDEP_INIT_INTEL_V2(haswell);
3406cc0c1555SSean Bruno 		break;
3407d95b3509SRandall Stewart 	case PMC_CPU_INTEL_HASWELL_XEON:
3408d95b3509SRandall Stewart 		PMC_MDEP_INIT_INTEL_V2(haswell_xeon);
3409d95b3509SRandall Stewart 		break;
3410f19bae41SRandall Stewart 	case PMC_CPU_INTEL_BROADWELL:
3411f19bae41SRandall Stewart 		pmc_class_table[n++] = &ucf_class_table_descr;
3412f19bae41SRandall Stewart 		pmc_class_table[n++] = &broadwelluc_class_table_descr;
3413f19bae41SRandall Stewart 		PMC_MDEP_INIT_INTEL_V2(broadwell);
3414f19bae41SRandall Stewart 		break;
3415f19bae41SRandall Stewart 	case PMC_CPU_INTEL_BROADWELL_XEON:
3416f19bae41SRandall Stewart 		PMC_MDEP_INIT_INTEL_V2(broadwell_xeon);
3417f19bae41SRandall Stewart 		break;
3418f19bae41SRandall Stewart 	case PMC_CPU_INTEL_SKYLAKE:
3419f19bae41SRandall Stewart 		PMC_MDEP_INIT_INTEL_V2(skylake);
3420f19bae41SRandall Stewart 		break;
3421b99b705dSKonstantin Belousov 	case PMC_CPU_INTEL_SKYLAKE_XEON:
3422b99b705dSKonstantin Belousov 		PMC_MDEP_INIT_INTEL_V2(skylake_xeon);
3423b99b705dSKonstantin Belousov 		break;
34241e862e5aSFabien Thomas 	case PMC_CPU_INTEL_IVYBRIDGE:
34251e862e5aSFabien Thomas 		PMC_MDEP_INIT_INTEL_V2(ivybridge);
34261e862e5aSFabien Thomas 		break;
34273f929d8cSSean Bruno 	case PMC_CPU_INTEL_IVYBRIDGE_XEON:
34283f929d8cSSean Bruno 		PMC_MDEP_INIT_INTEL_V2(ivybridge_xeon);
34293f929d8cSSean Bruno 		break;
343078d763a2SDavide Italiano 	case PMC_CPU_INTEL_SANDYBRIDGE:
343178d763a2SDavide Italiano 		pmc_class_table[n++] = &ucf_class_table_descr;
343278d763a2SDavide Italiano 		pmc_class_table[n++] = &sandybridgeuc_class_table_descr;
343378d763a2SDavide Italiano 		PMC_MDEP_INIT_INTEL_V2(sandybridge);
343478d763a2SDavide Italiano 		break;
3435fabe02f5SSean Bruno 	case PMC_CPU_INTEL_SANDYBRIDGE_XEON:
3436fabe02f5SSean Bruno 		PMC_MDEP_INIT_INTEL_V2(sandybridge_xeon);
3437fabe02f5SSean Bruno 		break;
34381fa7f10bSFabien Thomas 	case PMC_CPU_INTEL_WESTMERE:
34391fa7f10bSFabien Thomas 		pmc_class_table[n++] = &ucf_class_table_descr;
34401fa7f10bSFabien Thomas 		pmc_class_table[n++] = &westmereuc_class_table_descr;
34411fa7f10bSFabien Thomas 		PMC_MDEP_INIT_INTEL_V2(westmere);
34421fa7f10bSFabien Thomas 		break;
344349fe48abSKonstantin Belousov 	case PMC_CPU_INTEL_WESTMERE_EX:
344449fe48abSKonstantin Belousov 		PMC_MDEP_INIT_INTEL_V2(westmere_ex);
344549fe48abSKonstantin Belousov 		break;
3446789140c0SJoseph Koshy 	case PMC_CPU_INTEL_PIV:
3447789140c0SJoseph Koshy 		PMC_MDEP_INIT(p4);
34480cfab8ddSJoseph Koshy 		pmc_class_table[n] = &p4_class_table_descr;
3449f263522aSJoseph Koshy 		break;
3450ebccf1e3SJoseph Koshy #endif
3451f5f9340bSFabien Thomas 	case PMC_CPU_GENERIC:
3452f5f9340bSFabien Thomas 		PMC_MDEP_INIT(generic);
3453f5f9340bSFabien Thomas 		break;
34546411d14dSRuslan Bukin #if defined(__arm__)
34550ce207d2SRui Paulo #if defined(__XSCALE__)
34560ce207d2SRui Paulo 	case PMC_CPU_INTEL_XSCALE:
34570ce207d2SRui Paulo 		PMC_MDEP_INIT(xscale);
34580ce207d2SRui Paulo 		pmc_class_table[n] = &xscale_class_table_descr;
34590ce207d2SRui Paulo 		break;
34600ce207d2SRui Paulo #endif
34613e0bfdd8SRuslan Bukin 	case PMC_CPU_ARMV7_CORTEX_A8:
34623e0bfdd8SRuslan Bukin 		PMC_MDEP_INIT(cortex_a8);
34633e0bfdd8SRuslan Bukin 		pmc_class_table[n] = &cortex_a8_class_table_descr;
34643e0bfdd8SRuslan Bukin 		break;
34653e0bfdd8SRuslan Bukin 	case PMC_CPU_ARMV7_CORTEX_A9:
34663e0bfdd8SRuslan Bukin 		PMC_MDEP_INIT(cortex_a9);
34673e0bfdd8SRuslan Bukin 		pmc_class_table[n] = &cortex_a9_class_table_descr;
34686411d14dSRuslan Bukin 		break;
34696411d14dSRuslan Bukin #endif
3470bc88bb2bSRuslan Bukin #if defined(__aarch64__)
3471bc88bb2bSRuslan Bukin 	case PMC_CPU_ARMV8_CORTEX_A53:
3472bc88bb2bSRuslan Bukin 		PMC_MDEP_INIT(cortex_a53);
3473bc88bb2bSRuslan Bukin 		pmc_class_table[n] = &cortex_a53_class_table_descr;
3474bc88bb2bSRuslan Bukin 		break;
3475bc88bb2bSRuslan Bukin 	case PMC_CPU_ARMV8_CORTEX_A57:
3476bc88bb2bSRuslan Bukin 		PMC_MDEP_INIT(cortex_a57);
3477bc88bb2bSRuslan Bukin 		pmc_class_table[n] = &cortex_a57_class_table_descr;
3478bc88bb2bSRuslan Bukin 		break;
3479bc88bb2bSRuslan Bukin #endif
3480660df75eSGeorge V. Neville-Neil #if defined(__mips__)
3481660df75eSGeorge V. Neville-Neil 	case PMC_CPU_MIPS_24K:
3482660df75eSGeorge V. Neville-Neil 		PMC_MDEP_INIT(mips24k);
3483660df75eSGeorge V. Neville-Neil 		pmc_class_table[n] = &mips24k_class_table_descr;
3484660df75eSGeorge V. Neville-Neil 		break;
3485f6e6460dSAdrian Chadd 	case PMC_CPU_MIPS_74K:
3486f6e6460dSAdrian Chadd 		PMC_MDEP_INIT(mips74k);
3487f6e6460dSAdrian Chadd 		pmc_class_table[n] = &mips74k_class_table_descr;
3488f6e6460dSAdrian Chadd 		break;
3489c2657f80SOleksandr Tymoshenko 	case PMC_CPU_MIPS_OCTEON:
3490c2657f80SOleksandr Tymoshenko 		PMC_MDEP_INIT(octeon);
3491c2657f80SOleksandr Tymoshenko 		pmc_class_table[n] = &octeon_class_table_descr;
3492c2657f80SOleksandr Tymoshenko 		break;
3493660df75eSGeorge V. Neville-Neil #endif /* __mips__ */
34947b25dccaSJustin Hibbits #if defined(__powerpc__)
34957b25dccaSJustin Hibbits 	case PMC_CPU_PPC_7450:
34967b25dccaSJustin Hibbits 		PMC_MDEP_INIT(ppc7450);
34977b25dccaSJustin Hibbits 		pmc_class_table[n] = &ppc7450_class_table_descr;
34987b25dccaSJustin Hibbits 		break;
3499169dd953SJustin Hibbits 	case PMC_CPU_PPC_970:
3500169dd953SJustin Hibbits 		PMC_MDEP_INIT(ppc970);
3501169dd953SJustin Hibbits 		pmc_class_table[n] = &ppc970_class_table_descr;
3502169dd953SJustin Hibbits 		break;
3503a7452468SJustin Hibbits 	case PMC_CPU_PPC_E500:
3504a7452468SJustin Hibbits 		PMC_MDEP_INIT(e500);
3505a7452468SJustin Hibbits 		pmc_class_table[n] = &e500_class_table_descr;
3506a7452468SJustin Hibbits 		break;
35077b25dccaSJustin Hibbits #endif
3508f263522aSJoseph Koshy 	default:
3509f263522aSJoseph Koshy 		/*
3510f263522aSJoseph Koshy 		 * Some kind of CPU this version of the library knows nothing
3511f263522aSJoseph Koshy 		 * about.  This shouldn't happen since the abi version check
3512f263522aSJoseph Koshy 		 * should have caught this.
3513f263522aSJoseph Koshy 		 */
3514f263522aSJoseph Koshy 		errno = ENXIO;
3515f263522aSJoseph Koshy 		return (pmc_syscall = -1);
3516f263522aSJoseph Koshy 	}
3517f263522aSJoseph Koshy 
3518aa342b1fSJoseph Koshy 	return (0);
3519f263522aSJoseph Koshy }
3520f263522aSJoseph Koshy 
3521f263522aSJoseph Koshy const char *
3522f263522aSJoseph Koshy pmc_name_of_capability(enum pmc_caps cap)
3523f263522aSJoseph Koshy {
3524f263522aSJoseph Koshy 	int i;
3525f263522aSJoseph Koshy 
3526f263522aSJoseph Koshy 	/*
3527f263522aSJoseph Koshy 	 * 'cap' should have a single bit set and should be in
3528f263522aSJoseph Koshy 	 * range.
3529f263522aSJoseph Koshy 	 */
3530f263522aSJoseph Koshy 	if ((cap & (cap - 1)) || cap < PMC_CAP_FIRST ||
3531f263522aSJoseph Koshy 	    cap > PMC_CAP_LAST) {
3532f263522aSJoseph Koshy 		errno = EINVAL;
3533aa342b1fSJoseph Koshy 		return (NULL);
3534f263522aSJoseph Koshy 	}
3535f263522aSJoseph Koshy 
3536f263522aSJoseph Koshy 	i = ffs(cap);
3537aa342b1fSJoseph Koshy 	return (pmc_capability_names[i - 1]);
3538f263522aSJoseph Koshy }
3539f263522aSJoseph Koshy 
3540f263522aSJoseph Koshy const char *
3541f263522aSJoseph Koshy pmc_name_of_class(enum pmc_class pc)
3542f263522aSJoseph Koshy {
35430ceb54c2SJohn Baldwin 	size_t n;
35440ceb54c2SJohn Baldwin 
35450ceb54c2SJohn Baldwin 	for (n = 0; n < PMC_TABLE_SIZE(pmc_class_names); n++)
35460ceb54c2SJohn Baldwin 		if (pc == pmc_class_names[n].pm_class)
35470ceb54c2SJohn Baldwin 			return (pmc_class_names[n].pm_name);
3548f263522aSJoseph Koshy 
3549f263522aSJoseph Koshy 	errno = EINVAL;
3550aa342b1fSJoseph Koshy 	return (NULL);
3551f263522aSJoseph Koshy }
3552f263522aSJoseph Koshy 
3553f263522aSJoseph Koshy const char *
3554f263522aSJoseph Koshy pmc_name_of_cputype(enum pmc_cputype cp)
3555f263522aSJoseph Koshy {
3556789140c0SJoseph Koshy 	size_t n;
3557789140c0SJoseph Koshy 
3558789140c0SJoseph Koshy 	for (n = 0; n < PMC_TABLE_SIZE(pmc_cputype_names); n++)
3559789140c0SJoseph Koshy 		if (cp == pmc_cputype_names[n].pm_cputype)
3560789140c0SJoseph Koshy 			return (pmc_cputype_names[n].pm_name);
3561789140c0SJoseph Koshy 
3562f263522aSJoseph Koshy 	errno = EINVAL;
3563aa342b1fSJoseph Koshy 	return (NULL);
3564f263522aSJoseph Koshy }
3565f263522aSJoseph Koshy 
3566f263522aSJoseph Koshy const char *
3567f263522aSJoseph Koshy pmc_name_of_disposition(enum pmc_disp pd)
3568f263522aSJoseph Koshy {
3569f263522aSJoseph Koshy 	if ((int) pd >= PMC_DISP_FIRST &&
3570f263522aSJoseph Koshy 	    pd <= PMC_DISP_LAST)
3571aa342b1fSJoseph Koshy 		return (pmc_disposition_names[pd]);
3572f263522aSJoseph Koshy 
3573f263522aSJoseph Koshy 	errno = EINVAL;
3574aa342b1fSJoseph Koshy 	return (NULL);
3575f263522aSJoseph Koshy }
3576f263522aSJoseph Koshy 
3577f263522aSJoseph Koshy const char *
35780cfab8ddSJoseph Koshy _pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu)
3579f263522aSJoseph Koshy {
3580789140c0SJoseph Koshy 	const struct pmc_event_descr *ev, *evfence;
3581789140c0SJoseph Koshy 
3582789140c0SJoseph Koshy 	ev = evfence = NULL;
35830cfab8ddSJoseph Koshy 	if (pe >= PMC_EV_IAF_FIRST && pe <= PMC_EV_IAF_LAST) {
35840cfab8ddSJoseph Koshy 		ev = iaf_event_table;
35850cfab8ddSJoseph Koshy 		evfence = iaf_event_table + PMC_EVENT_TABLE_SIZE(iaf);
35860cfab8ddSJoseph Koshy 	} else if (pe >= PMC_EV_IAP_FIRST && pe <= PMC_EV_IAP_LAST) {
35870cfab8ddSJoseph Koshy 		switch (cpu) {
35880cfab8ddSJoseph Koshy 		case PMC_CPU_INTEL_ATOM:
35890cfab8ddSJoseph Koshy 			ev = atom_event_table;
35900cfab8ddSJoseph Koshy 			evfence = atom_event_table + PMC_EVENT_TABLE_SIZE(atom);
35910cfab8ddSJoseph Koshy 			break;
3592e8f021a3SHiren Panchasara 		case PMC_CPU_INTEL_ATOM_SILVERMONT:
3593e8f021a3SHiren Panchasara 			ev = atom_silvermont_event_table;
3594e8f021a3SHiren Panchasara 			evfence = atom_silvermont_event_table +
3595e8f021a3SHiren Panchasara 			    PMC_EVENT_TABLE_SIZE(atom_silvermont);
3596e8f021a3SHiren Panchasara 			break;
35970cfab8ddSJoseph Koshy 		case PMC_CPU_INTEL_CORE:
35980cfab8ddSJoseph Koshy 			ev = core_event_table;
35990cfab8ddSJoseph Koshy 			evfence = core_event_table + PMC_EVENT_TABLE_SIZE(core);
36000cfab8ddSJoseph Koshy 			break;
36010cfab8ddSJoseph Koshy 		case PMC_CPU_INTEL_CORE2:
3602b4d091f3SJoseph Koshy 		case PMC_CPU_INTEL_CORE2EXTREME:
36030cfab8ddSJoseph Koshy 			ev = core2_event_table;
36040cfab8ddSJoseph Koshy 			evfence = core2_event_table + PMC_EVENT_TABLE_SIZE(core2);
36050cfab8ddSJoseph Koshy 			break;
3606597979c4SJeff Roberson 		case PMC_CPU_INTEL_COREI7:
3607597979c4SJeff Roberson 			ev = corei7_event_table;
3608597979c4SJeff Roberson 			evfence = corei7_event_table + PMC_EVENT_TABLE_SIZE(corei7);
3609597979c4SJeff Roberson 			break;
361049fe48abSKonstantin Belousov 		case PMC_CPU_INTEL_NEHALEM_EX:
361149fe48abSKonstantin Belousov 			ev = nehalem_ex_event_table;
361249fe48abSKonstantin Belousov 			evfence = nehalem_ex_event_table +
361349fe48abSKonstantin Belousov 			    PMC_EVENT_TABLE_SIZE(nehalem_ex);
361449fe48abSKonstantin Belousov 			break;
3615cc0c1555SSean Bruno 		case PMC_CPU_INTEL_HASWELL:
3616cc0c1555SSean Bruno 			ev = haswell_event_table;
3617cc0c1555SSean Bruno 			evfence = haswell_event_table + PMC_EVENT_TABLE_SIZE(haswell);
3618cc0c1555SSean Bruno 			break;
3619d95b3509SRandall Stewart 		case PMC_CPU_INTEL_HASWELL_XEON:
3620d95b3509SRandall Stewart 			ev = haswell_xeon_event_table;
3621d95b3509SRandall Stewart 			evfence = haswell_xeon_event_table + PMC_EVENT_TABLE_SIZE(haswell_xeon);
3622d95b3509SRandall Stewart 			break;
3623f19bae41SRandall Stewart 		case PMC_CPU_INTEL_BROADWELL:
3624f19bae41SRandall Stewart 			ev = broadwell_event_table;
3625f19bae41SRandall Stewart 			evfence = broadwell_event_table + PMC_EVENT_TABLE_SIZE(broadwell);
3626f19bae41SRandall Stewart 			break;
3627f19bae41SRandall Stewart 		case PMC_CPU_INTEL_BROADWELL_XEON:
3628f19bae41SRandall Stewart 			ev = broadwell_xeon_event_table;
3629f19bae41SRandall Stewart 			evfence = broadwell_xeon_event_table + PMC_EVENT_TABLE_SIZE(broadwell_xeon);
3630f19bae41SRandall Stewart 			break;
3631f19bae41SRandall Stewart 		case PMC_CPU_INTEL_SKYLAKE:
3632f19bae41SRandall Stewart 			ev = skylake_event_table;
36339491ba75SKonstantin Belousov 			evfence = skylake_event_table +
36349491ba75SKonstantin Belousov 			    PMC_EVENT_TABLE_SIZE(skylake);
3635f19bae41SRandall Stewart 			break;
3636b99b705dSKonstantin Belousov 		case PMC_CPU_INTEL_SKYLAKE_XEON:
3637b99b705dSKonstantin Belousov 			ev = skylake_xeon_event_table;
3638b99b705dSKonstantin Belousov 			evfence = skylake_xeon_event_table +
3639b99b705dSKonstantin Belousov 			    PMC_EVENT_TABLE_SIZE(skylake_xeon);
3640b99b705dSKonstantin Belousov 			break;
36411e862e5aSFabien Thomas 		case PMC_CPU_INTEL_IVYBRIDGE:
36421e862e5aSFabien Thomas 			ev = ivybridge_event_table;
36431e862e5aSFabien Thomas 			evfence = ivybridge_event_table + PMC_EVENT_TABLE_SIZE(ivybridge);
36441e862e5aSFabien Thomas 			break;
36453f929d8cSSean Bruno 		case PMC_CPU_INTEL_IVYBRIDGE_XEON:
36463f929d8cSSean Bruno 			ev = ivybridge_xeon_event_table;
36473f929d8cSSean Bruno 			evfence = ivybridge_xeon_event_table + PMC_EVENT_TABLE_SIZE(ivybridge_xeon);
36483f929d8cSSean Bruno 			break;
364978d763a2SDavide Italiano 		case PMC_CPU_INTEL_SANDYBRIDGE:
365078d763a2SDavide Italiano 			ev = sandybridge_event_table;
365178d763a2SDavide Italiano 			evfence = sandybridge_event_table + PMC_EVENT_TABLE_SIZE(sandybridge);
365278d763a2SDavide Italiano 			break;
3653fabe02f5SSean Bruno 		case PMC_CPU_INTEL_SANDYBRIDGE_XEON:
3654fabe02f5SSean Bruno 			ev = sandybridge_xeon_event_table;
3655fabe02f5SSean Bruno 			evfence = sandybridge_xeon_event_table + PMC_EVENT_TABLE_SIZE(sandybridge_xeon);
3656fabe02f5SSean Bruno 			break;
36571fa7f10bSFabien Thomas 		case PMC_CPU_INTEL_WESTMERE:
36581fa7f10bSFabien Thomas 			ev = westmere_event_table;
36591fa7f10bSFabien Thomas 			evfence = westmere_event_table + PMC_EVENT_TABLE_SIZE(westmere);
36601fa7f10bSFabien Thomas 			break;
366149fe48abSKonstantin Belousov 		case PMC_CPU_INTEL_WESTMERE_EX:
366249fe48abSKonstantin Belousov 			ev = westmere_ex_event_table;
366349fe48abSKonstantin Belousov 			evfence = westmere_ex_event_table +
366449fe48abSKonstantin Belousov 			    PMC_EVENT_TABLE_SIZE(westmere_ex);
366549fe48abSKonstantin Belousov 			break;
36660cfab8ddSJoseph Koshy 		default:	/* Unknown CPU type. */
36670cfab8ddSJoseph Koshy 			break;
36680cfab8ddSJoseph Koshy 		}
36691fa7f10bSFabien Thomas 	} else if (pe >= PMC_EV_UCF_FIRST && pe <= PMC_EV_UCF_LAST) {
36701fa7f10bSFabien Thomas 		ev = ucf_event_table;
36711fa7f10bSFabien Thomas 		evfence = ucf_event_table + PMC_EVENT_TABLE_SIZE(ucf);
36721fa7f10bSFabien Thomas 	} else if (pe >= PMC_EV_UCP_FIRST && pe <= PMC_EV_UCP_LAST) {
36731fa7f10bSFabien Thomas 		switch (cpu) {
36741fa7f10bSFabien Thomas 		case PMC_CPU_INTEL_COREI7:
36751fa7f10bSFabien Thomas 			ev = corei7uc_event_table;
36761fa7f10bSFabien Thomas 			evfence = corei7uc_event_table + PMC_EVENT_TABLE_SIZE(corei7uc);
36771fa7f10bSFabien Thomas 			break;
367878d763a2SDavide Italiano 		case PMC_CPU_INTEL_SANDYBRIDGE:
367978d763a2SDavide Italiano 			ev = sandybridgeuc_event_table;
368078d763a2SDavide Italiano 			evfence = sandybridgeuc_event_table + PMC_EVENT_TABLE_SIZE(sandybridgeuc);
368178d763a2SDavide Italiano 			break;
36821fa7f10bSFabien Thomas 		case PMC_CPU_INTEL_WESTMERE:
36831fa7f10bSFabien Thomas 			ev = westmereuc_event_table;
36841fa7f10bSFabien Thomas 			evfence = westmereuc_event_table + PMC_EVENT_TABLE_SIZE(westmereuc);
36851fa7f10bSFabien Thomas 			break;
36861fa7f10bSFabien Thomas 		default:	/* Unknown CPU type. */
36871fa7f10bSFabien Thomas 			break;
36881fa7f10bSFabien Thomas 		}
36891fa7f10bSFabien Thomas 	} else if (pe >= PMC_EV_K7_FIRST && pe <= PMC_EV_K7_LAST) {
3690789140c0SJoseph Koshy 		ev = k7_event_table;
3691789140c0SJoseph Koshy 		evfence = k7_event_table + PMC_EVENT_TABLE_SIZE(k7);
3692789140c0SJoseph Koshy 	} else if (pe >= PMC_EV_K8_FIRST && pe <= PMC_EV_K8_LAST) {
3693789140c0SJoseph Koshy 		ev = k8_event_table;
3694789140c0SJoseph Koshy 		evfence = k8_event_table + PMC_EVENT_TABLE_SIZE(k8);
3695789140c0SJoseph Koshy 	} else if (pe >= PMC_EV_P4_FIRST && pe <= PMC_EV_P4_LAST) {
3696789140c0SJoseph Koshy 		ev = p4_event_table;
3697789140c0SJoseph Koshy 		evfence = p4_event_table + PMC_EVENT_TABLE_SIZE(p4);
3698789140c0SJoseph Koshy 	} else if (pe >= PMC_EV_P5_FIRST && pe <= PMC_EV_P5_LAST) {
3699789140c0SJoseph Koshy 		ev = p5_event_table;
3700789140c0SJoseph Koshy 		evfence = p5_event_table + PMC_EVENT_TABLE_SIZE(p5);
3701789140c0SJoseph Koshy 	} else if (pe >= PMC_EV_P6_FIRST && pe <= PMC_EV_P6_LAST) {
3702789140c0SJoseph Koshy 		ev = p6_event_table;
3703789140c0SJoseph Koshy 		evfence = p6_event_table + PMC_EVENT_TABLE_SIZE(p6);
37040ce207d2SRui Paulo 	} else if (pe >= PMC_EV_XSCALE_FIRST && pe <= PMC_EV_XSCALE_LAST) {
37050ce207d2SRui Paulo 		ev = xscale_event_table;
37060ce207d2SRui Paulo 		evfence = xscale_event_table + PMC_EVENT_TABLE_SIZE(xscale);
37076411d14dSRuslan Bukin 	} else if (pe >= PMC_EV_ARMV7_FIRST && pe <= PMC_EV_ARMV7_LAST) {
37083e0bfdd8SRuslan Bukin 		switch (cpu) {
37093e0bfdd8SRuslan Bukin 		case PMC_CPU_ARMV7_CORTEX_A8:
37103e0bfdd8SRuslan Bukin 			ev = cortex_a8_event_table;
37113e0bfdd8SRuslan Bukin 			evfence = cortex_a8_event_table + PMC_EVENT_TABLE_SIZE(cortex_a8);
37123e0bfdd8SRuslan Bukin 			break;
37133e0bfdd8SRuslan Bukin 		case PMC_CPU_ARMV7_CORTEX_A9:
37143e0bfdd8SRuslan Bukin 			ev = cortex_a9_event_table;
37153e0bfdd8SRuslan Bukin 			evfence = cortex_a9_event_table + PMC_EVENT_TABLE_SIZE(cortex_a9);
37163e0bfdd8SRuslan Bukin 			break;
37173e0bfdd8SRuslan Bukin 		default:	/* Unknown CPU type. */
37183e0bfdd8SRuslan Bukin 			break;
37193e0bfdd8SRuslan Bukin 		}
3720bc88bb2bSRuslan Bukin 	} else if (pe >= PMC_EV_ARMV8_FIRST && pe <= PMC_EV_ARMV8_LAST) {
3721bc88bb2bSRuslan Bukin 		switch (cpu) {
3722bc88bb2bSRuslan Bukin 		case PMC_CPU_ARMV8_CORTEX_A53:
3723bc88bb2bSRuslan Bukin 			ev = cortex_a53_event_table;
3724bc88bb2bSRuslan Bukin 			evfence = cortex_a53_event_table + PMC_EVENT_TABLE_SIZE(cortex_a53);
3725bc88bb2bSRuslan Bukin 			break;
3726bc88bb2bSRuslan Bukin 		case PMC_CPU_ARMV8_CORTEX_A57:
3727bc88bb2bSRuslan Bukin 			ev = cortex_a57_event_table;
3728bc88bb2bSRuslan Bukin 			evfence = cortex_a57_event_table + PMC_EVENT_TABLE_SIZE(cortex_a57);
3729bc88bb2bSRuslan Bukin 			break;
3730bc88bb2bSRuslan Bukin 		default:	/* Unknown CPU type. */
3731bc88bb2bSRuslan Bukin 			break;
3732bc88bb2bSRuslan Bukin 		}
3733660df75eSGeorge V. Neville-Neil 	} else if (pe >= PMC_EV_MIPS24K_FIRST && pe <= PMC_EV_MIPS24K_LAST) {
3734660df75eSGeorge V. Neville-Neil 		ev = mips24k_event_table;
3735f5f9340bSFabien Thomas 		evfence = mips24k_event_table + PMC_EVENT_TABLE_SIZE(mips24k);
3736f6e6460dSAdrian Chadd 	} else if (pe >= PMC_EV_MIPS74K_FIRST && pe <= PMC_EV_MIPS74K_LAST) {
3737f6e6460dSAdrian Chadd 		ev = mips74k_event_table;
3738f6e6460dSAdrian Chadd 		evfence = mips74k_event_table + PMC_EVENT_TABLE_SIZE(mips74k);
3739c2657f80SOleksandr Tymoshenko 	} else if (pe >= PMC_EV_OCTEON_FIRST && pe <= PMC_EV_OCTEON_LAST) {
3740c2657f80SOleksandr Tymoshenko 		ev = octeon_event_table;
3741c2657f80SOleksandr Tymoshenko 		evfence = octeon_event_table + PMC_EVENT_TABLE_SIZE(octeon);
37427b25dccaSJustin Hibbits 	} else if (pe >= PMC_EV_PPC7450_FIRST && pe <= PMC_EV_PPC7450_LAST) {
37437b25dccaSJustin Hibbits 		ev = ppc7450_event_table;
3744f5f9340bSFabien Thomas 		evfence = ppc7450_event_table + PMC_EVENT_TABLE_SIZE(ppc7450);
3745169dd953SJustin Hibbits 	} else if (pe >= PMC_EV_PPC970_FIRST && pe <= PMC_EV_PPC970_LAST) {
3746169dd953SJustin Hibbits 		ev = ppc970_event_table;
3747169dd953SJustin Hibbits 		evfence = ppc970_event_table + PMC_EVENT_TABLE_SIZE(ppc970);
3748a7452468SJustin Hibbits 	} else if (pe >= PMC_EV_E500_FIRST && pe <= PMC_EV_E500_LAST) {
3749a7452468SJustin Hibbits 		ev = e500_event_table;
3750a7452468SJustin Hibbits 		evfence = e500_event_table + PMC_EVENT_TABLE_SIZE(e500);
3751789140c0SJoseph Koshy 	} else if (pe == PMC_EV_TSC_TSC) {
3752789140c0SJoseph Koshy 		ev = tsc_event_table;
3753789140c0SJoseph Koshy 		evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc);
3754f0bbe9aaSDimitry Andric 	} else if ((int)pe >= PMC_EV_SOFT_FIRST && (int)pe <= PMC_EV_SOFT_LAST) {
3755f5f9340bSFabien Thomas 		ev = soft_event_table;
3756f5f9340bSFabien Thomas 		evfence = soft_event_table + soft_event_info.pm_nevent;
3757789140c0SJoseph Koshy 	}
3758789140c0SJoseph Koshy 
3759789140c0SJoseph Koshy 	for (; ev != evfence; ev++)
3760789140c0SJoseph Koshy 		if (pe == ev->pm_ev_code)
3761789140c0SJoseph Koshy 			return (ev->pm_ev_name);
3762f263522aSJoseph Koshy 
37630cfab8ddSJoseph Koshy 	return (NULL);
37640cfab8ddSJoseph Koshy }
37650cfab8ddSJoseph Koshy 
37660cfab8ddSJoseph Koshy const char *
37670cfab8ddSJoseph Koshy pmc_name_of_event(enum pmc_event pe)
37680cfab8ddSJoseph Koshy {
37690cfab8ddSJoseph Koshy 	const char *n;
37700cfab8ddSJoseph Koshy 
37710cfab8ddSJoseph Koshy 	if ((n = _pmc_name_of_event(pe, cpu_info.pm_cputype)) != NULL)
37720cfab8ddSJoseph Koshy 		return (n);
37730cfab8ddSJoseph Koshy 
3774f263522aSJoseph Koshy 	errno = EINVAL;
3775aa342b1fSJoseph Koshy 	return (NULL);
3776f263522aSJoseph Koshy }
3777f263522aSJoseph Koshy 
3778f263522aSJoseph Koshy const char *
3779f263522aSJoseph Koshy pmc_name_of_mode(enum pmc_mode pm)
3780f263522aSJoseph Koshy {
3781f263522aSJoseph Koshy 	if ((int) pm >= PMC_MODE_FIRST &&
3782f263522aSJoseph Koshy 	    pm <= PMC_MODE_LAST)
3783aa342b1fSJoseph Koshy 		return (pmc_mode_names[pm]);
3784f263522aSJoseph Koshy 
3785f263522aSJoseph Koshy 	errno = EINVAL;
3786aa342b1fSJoseph Koshy 	return (NULL);
3787f263522aSJoseph Koshy }
3788f263522aSJoseph Koshy 
3789f263522aSJoseph Koshy const char *
3790f263522aSJoseph Koshy pmc_name_of_state(enum pmc_state ps)
3791f263522aSJoseph Koshy {
3792f263522aSJoseph Koshy 	if ((int) ps >= PMC_STATE_FIRST &&
3793f263522aSJoseph Koshy 	    ps <= PMC_STATE_LAST)
3794aa342b1fSJoseph Koshy 		return (pmc_state_names[ps]);
3795f263522aSJoseph Koshy 
3796f263522aSJoseph Koshy 	errno = EINVAL;
3797aa342b1fSJoseph Koshy 	return (NULL);
3798f263522aSJoseph Koshy }
3799f263522aSJoseph Koshy 
3800f263522aSJoseph Koshy int
3801f263522aSJoseph Koshy pmc_ncpu(void)
3802f263522aSJoseph Koshy {
3803f263522aSJoseph Koshy 	if (pmc_syscall == -1) {
3804f263522aSJoseph Koshy 		errno = ENXIO;
3805aa342b1fSJoseph Koshy 		return (-1);
3806f263522aSJoseph Koshy 	}
3807f263522aSJoseph Koshy 
3808aa342b1fSJoseph Koshy 	return (cpu_info.pm_ncpu);
3809f263522aSJoseph Koshy }
3810f263522aSJoseph Koshy 
3811f263522aSJoseph Koshy int
3812f263522aSJoseph Koshy pmc_npmc(int cpu)
3813f263522aSJoseph Koshy {
3814f263522aSJoseph Koshy 	if (pmc_syscall == -1) {
3815f263522aSJoseph Koshy 		errno = ENXIO;
3816aa342b1fSJoseph Koshy 		return (-1);
3817f263522aSJoseph Koshy 	}
3818f263522aSJoseph Koshy 
3819f263522aSJoseph Koshy 	if (cpu < 0 || cpu >= (int) cpu_info.pm_ncpu) {
3820f263522aSJoseph Koshy 		errno = EINVAL;
3821aa342b1fSJoseph Koshy 		return (-1);
3822f263522aSJoseph Koshy 	}
3823f263522aSJoseph Koshy 
3824aa342b1fSJoseph Koshy 	return (cpu_info.pm_npmc);
3825f263522aSJoseph Koshy }
3826f263522aSJoseph Koshy 
3827f263522aSJoseph Koshy int
3828f263522aSJoseph Koshy pmc_pmcinfo(int cpu, struct pmc_pmcinfo **ppmci)
3829f263522aSJoseph Koshy {
3830f263522aSJoseph Koshy 	int nbytes, npmc;
3831f263522aSJoseph Koshy 	struct pmc_op_getpmcinfo *pmci;
3832f263522aSJoseph Koshy 
3833f263522aSJoseph Koshy 	if ((npmc = pmc_npmc(cpu)) < 0)
3834aa342b1fSJoseph Koshy 		return (-1);
3835f263522aSJoseph Koshy 
3836f263522aSJoseph Koshy 	nbytes = sizeof(struct pmc_op_getpmcinfo) +
3837f263522aSJoseph Koshy 	    npmc * sizeof(struct pmc_info);
3838f263522aSJoseph Koshy 
3839f263522aSJoseph Koshy 	if ((pmci = calloc(1, nbytes)) == NULL)
3840aa342b1fSJoseph Koshy 		return (-1);
3841f263522aSJoseph Koshy 
3842f263522aSJoseph Koshy 	pmci->pm_cpu  = cpu;
3843f263522aSJoseph Koshy 
3844f263522aSJoseph Koshy 	if (PMC_CALL(GETPMCINFO, pmci) < 0) {
3845f263522aSJoseph Koshy 		free(pmci);
3846aa342b1fSJoseph Koshy 		return (-1);
3847f263522aSJoseph Koshy 	}
3848f263522aSJoseph Koshy 
3849f263522aSJoseph Koshy 	/* kernel<->library, library<->userland interfaces are identical */
3850f263522aSJoseph Koshy 	*ppmci = (struct pmc_pmcinfo *) pmci;
3851aa342b1fSJoseph Koshy 	return (0);
3852f263522aSJoseph Koshy }
3853f263522aSJoseph Koshy 
3854f263522aSJoseph Koshy int
3855f263522aSJoseph Koshy pmc_read(pmc_id_t pmc, pmc_value_t *value)
3856f263522aSJoseph Koshy {
3857f263522aSJoseph Koshy 	struct pmc_op_pmcrw pmc_read_op;
3858f263522aSJoseph Koshy 
3859f263522aSJoseph Koshy 	pmc_read_op.pm_pmcid = pmc;
3860f263522aSJoseph Koshy 	pmc_read_op.pm_flags = PMC_F_OLDVALUE;
3861f263522aSJoseph Koshy 	pmc_read_op.pm_value = -1;
3862f263522aSJoseph Koshy 
3863f263522aSJoseph Koshy 	if (PMC_CALL(PMCRW, &pmc_read_op) < 0)
3864aa342b1fSJoseph Koshy 		return (-1);
3865f263522aSJoseph Koshy 
3866f263522aSJoseph Koshy 	*value = pmc_read_op.pm_value;
3867aa342b1fSJoseph Koshy 	return (0);
3868f263522aSJoseph Koshy }
3869f263522aSJoseph Koshy 
3870f263522aSJoseph Koshy int
3871f263522aSJoseph Koshy pmc_release(pmc_id_t pmc)
3872f263522aSJoseph Koshy {
3873f263522aSJoseph Koshy 	struct pmc_op_simple	pmc_release_args;
3874f263522aSJoseph Koshy 
3875f263522aSJoseph Koshy 	pmc_release_args.pm_pmcid = pmc;
3876aa342b1fSJoseph Koshy 	return (PMC_CALL(PMCRELEASE, &pmc_release_args));
3877f263522aSJoseph Koshy }
3878f263522aSJoseph Koshy 
3879f263522aSJoseph Koshy int
3880f263522aSJoseph Koshy pmc_rw(pmc_id_t pmc, pmc_value_t newvalue, pmc_value_t *oldvaluep)
3881f263522aSJoseph Koshy {
3882f263522aSJoseph Koshy 	struct pmc_op_pmcrw pmc_rw_op;
3883f263522aSJoseph Koshy 
3884f263522aSJoseph Koshy 	pmc_rw_op.pm_pmcid = pmc;
3885f263522aSJoseph Koshy 	pmc_rw_op.pm_flags = PMC_F_NEWVALUE | PMC_F_OLDVALUE;
3886f263522aSJoseph Koshy 	pmc_rw_op.pm_value = newvalue;
3887f263522aSJoseph Koshy 
3888f263522aSJoseph Koshy 	if (PMC_CALL(PMCRW, &pmc_rw_op) < 0)
3889aa342b1fSJoseph Koshy 		return (-1);
3890f263522aSJoseph Koshy 
3891f263522aSJoseph Koshy 	*oldvaluep = pmc_rw_op.pm_value;
3892aa342b1fSJoseph Koshy 	return (0);
3893f263522aSJoseph Koshy }
3894f263522aSJoseph Koshy 
3895f263522aSJoseph Koshy int
3896f263522aSJoseph Koshy pmc_set(pmc_id_t pmc, pmc_value_t value)
3897f263522aSJoseph Koshy {
3898f263522aSJoseph Koshy 	struct pmc_op_pmcsetcount sc;
3899f263522aSJoseph Koshy 
3900f263522aSJoseph Koshy 	sc.pm_pmcid = pmc;
3901f263522aSJoseph Koshy 	sc.pm_count = value;
3902f263522aSJoseph Koshy 
3903f263522aSJoseph Koshy 	if (PMC_CALL(PMCSETCOUNT, &sc) < 0)
3904aa342b1fSJoseph Koshy 		return (-1);
3905aa342b1fSJoseph Koshy 	return (0);
3906f263522aSJoseph Koshy }
3907f263522aSJoseph Koshy 
3908f263522aSJoseph Koshy int
3909f263522aSJoseph Koshy pmc_start(pmc_id_t pmc)
3910f263522aSJoseph Koshy {
3911f263522aSJoseph Koshy 	struct pmc_op_simple	pmc_start_args;
3912f263522aSJoseph Koshy 
3913f263522aSJoseph Koshy 	pmc_start_args.pm_pmcid = pmc;
3914aa342b1fSJoseph Koshy 	return (PMC_CALL(PMCSTART, &pmc_start_args));
3915f263522aSJoseph Koshy }
3916f263522aSJoseph Koshy 
3917f263522aSJoseph Koshy int
3918f263522aSJoseph Koshy pmc_stop(pmc_id_t pmc)
3919f263522aSJoseph Koshy {
3920f263522aSJoseph Koshy 	struct pmc_op_simple	pmc_stop_args;
3921f263522aSJoseph Koshy 
3922f263522aSJoseph Koshy 	pmc_stop_args.pm_pmcid = pmc;
3923aa342b1fSJoseph Koshy 	return (PMC_CALL(PMCSTOP, &pmc_stop_args));
3924f263522aSJoseph Koshy }
3925f263522aSJoseph Koshy 
3926f263522aSJoseph Koshy int
3927f263522aSJoseph Koshy pmc_width(pmc_id_t pmcid, uint32_t *width)
3928f263522aSJoseph Koshy {
3929f263522aSJoseph Koshy 	unsigned int i;
3930f263522aSJoseph Koshy 	enum pmc_class cl;
3931f263522aSJoseph Koshy 
3932f263522aSJoseph Koshy 	cl = PMC_ID_TO_CLASS(pmcid);
3933f263522aSJoseph Koshy 	for (i = 0; i < cpu_info.pm_nclass; i++)
3934f263522aSJoseph Koshy 		if (cpu_info.pm_classes[i].pm_class == cl) {
3935f263522aSJoseph Koshy 			*width = cpu_info.pm_classes[i].pm_width;
3936aa342b1fSJoseph Koshy 			return (0);
3937f263522aSJoseph Koshy 		}
3938484202faSJoseph Koshy 	errno = EINVAL;
3939484202faSJoseph Koshy 	return (-1);
3940f263522aSJoseph Koshy }
3941f263522aSJoseph Koshy 
3942f263522aSJoseph Koshy int
3943f263522aSJoseph Koshy pmc_write(pmc_id_t pmc, pmc_value_t value)
3944f263522aSJoseph Koshy {
3945f263522aSJoseph Koshy 	struct pmc_op_pmcrw pmc_write_op;
3946f263522aSJoseph Koshy 
3947f263522aSJoseph Koshy 	pmc_write_op.pm_pmcid = pmc;
3948f263522aSJoseph Koshy 	pmc_write_op.pm_flags = PMC_F_NEWVALUE;
3949f263522aSJoseph Koshy 	pmc_write_op.pm_value = value;
3950aa342b1fSJoseph Koshy 	return (PMC_CALL(PMCRW, &pmc_write_op));
3951f263522aSJoseph Koshy }
3952f263522aSJoseph Koshy 
3953f263522aSJoseph Koshy int
3954f263522aSJoseph Koshy pmc_writelog(uint32_t userdata)
3955f263522aSJoseph Koshy {
3956f263522aSJoseph Koshy 	struct pmc_op_writelog wl;
3957f263522aSJoseph Koshy 
3958f263522aSJoseph Koshy 	wl.pm_userdata = userdata;
3959aa342b1fSJoseph Koshy 	return (PMC_CALL(WRITELOG, &wl));
3960f263522aSJoseph Koshy }
3961