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