]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - lib/libpmc/libpmc.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / lib / libpmc / libpmc.c
1 /*-
2  * Copyright (c) 2003-2006 Joseph Koshy
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/types.h>
31 #include <sys/module.h>
32 #include <sys/pmc.h>
33 #include <sys/syscall.h>
34
35 #include <ctype.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <pmc.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <strings.h>
43 #include <unistd.h>
44
45 /* Function prototypes */
46 #if defined(__i386__)
47 static int k7_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
48     struct pmc_op_pmcallocate *_pmc_config);
49 #endif
50 #if defined(__amd64__) || defined(__i386__)
51 static int k8_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
52     struct pmc_op_pmcallocate *_pmc_config);
53 static int p4_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
54     struct pmc_op_pmcallocate *_pmc_config);
55 #endif
56 #if defined(__i386__)
57 static int p5_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
58     struct pmc_op_pmcallocate *_pmc_config);
59 static int p6_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
60     struct pmc_op_pmcallocate *_pmc_config);
61 #endif
62
63 #define PMC_CALL(cmd, params)                           \
64         syscall(pmc_syscall, PMC_OP_##cmd, (params))
65
66 /*
67  * Event aliases provide a way for the user to ask for generic events
68  * like "cache-misses", or "instructions-retired".  These aliases are
69  * mapped to the appropriate canonical event descriptions using a
70  * lookup table.
71  */
72
73 struct pmc_event_alias {
74         const char      *pm_alias;
75         const char      *pm_spec;
76 };
77
78 static const struct pmc_event_alias *pmc_mdep_event_aliases;
79
80 /*
81  * The pmc_event_descr table maps symbolic names known to the user
82  * to integer codes used by the PMC KLD.
83  */
84
85 struct pmc_event_descr {
86         const char      *pm_ev_name;
87         enum pmc_event  pm_ev_code;
88         enum pmc_class  pm_ev_class;
89 };
90
91 static const struct pmc_event_descr
92 pmc_event_table[] =
93 {
94 #undef  __PMC_EV
95 #define __PMC_EV(C,N,EV) { #EV, PMC_EV_ ## C ## _ ## N, PMC_CLASS_ ## C },
96         __PMC_EVENTS()
97 };
98
99 /*
100  * Mapping tables, mapping enumeration values to human readable
101  * strings.
102  */
103
104 static const char * pmc_capability_names[] = {
105 #undef  __PMC_CAP
106 #define __PMC_CAP(N,V,D)        #N ,
107         __PMC_CAPS()
108 };
109
110 static const char * pmc_class_names[] = {
111 #undef  __PMC_CLASS
112 #define __PMC_CLASS(C)  #C ,
113         __PMC_CLASSES()
114 };
115
116 static const char * pmc_cputype_names[] = {
117 #undef  __PMC_CPU
118 #define __PMC_CPU(S, D) #S ,
119         __PMC_CPUS()
120 };
121
122 static const char * pmc_disposition_names[] = {
123 #undef  __PMC_DISP
124 #define __PMC_DISP(D)   #D ,
125         __PMC_DISPOSITIONS()
126 };
127
128 static const char * pmc_mode_names[] = {
129 #undef  __PMC_MODE
130 #define __PMC_MODE(M,N) #M ,
131         __PMC_MODES()
132 };
133
134 static const char * pmc_state_names[] = {
135 #undef  __PMC_STATE
136 #define __PMC_STATE(S) #S ,
137         __PMC_STATES()
138 };
139
140 static int pmc_syscall = -1;            /* filled in by pmc_init() */
141
142 static struct pmc_cpuinfo cpu_info;     /* filled in by pmc_init() */
143
144
145 /* Architecture dependent event parsing */
146 static int (*pmc_mdep_allocate_pmc)(enum pmc_event _pe, char *_ctrspec,
147     struct pmc_op_pmcallocate *_pmc_config);
148
149 /* Event masks for events */
150 struct pmc_masks {
151         const char      *pm_name;
152         const uint32_t  pm_value;
153 };
154 #define PMCMASK(N,V)    { .pm_name = #N, .pm_value = (V) }
155 #define NULLMASK        PMCMASK(NULL,0)
156
157 #if defined(__amd64__) || defined(__i386__)
158 static int
159 pmc_parse_mask(const struct pmc_masks *pmask, char *p, uint32_t *evmask)
160 {
161         const struct pmc_masks *pm;
162         char *q, *r;
163         int c;
164
165         if (pmask == NULL)      /* no mask keywords */
166                 return -1;
167         q = strchr(p, '=');     /* skip '=' */
168         if (*++q == '\0')       /* no more data */
169                 return -1;
170         c = 0;                  /* count of mask keywords seen */
171         while ((r = strsep(&q, "+")) != NULL) {
172                 for (pm = pmask; pm->pm_name && strcmp(r, pm->pm_name); pm++)
173                         ;
174                 if (pm->pm_name == NULL) /* not found */
175                         return -1;
176                 *evmask |= pm->pm_value;
177                 c++;
178         }
179         return c;
180 }
181 #endif
182
183 #define KWMATCH(p,kw)           (strcasecmp((p), (kw)) == 0)
184 #define KWPREFIXMATCH(p,kw)     (strncasecmp((p), (kw), sizeof((kw)) - 1) == 0)
185 #define EV_ALIAS(N,S)           { .pm_alias = N, .pm_spec = S }
186
187 #if defined(__i386__)
188
189 /*
190  * AMD K7 (Athlon) CPUs.
191  */
192
193 static struct pmc_event_alias k7_aliases[] = {
194         EV_ALIAS("branches",            "k7-retired-branches"),
195         EV_ALIAS("branch-mispredicts",  "k7-retired-branches-mispredicted"),
196         EV_ALIAS("cycles",              "tsc"),
197         EV_ALIAS("dc-misses",           "k7-dc-misses,mask=moesi"),
198         EV_ALIAS("ic-misses",           "k7-ic-misses"),
199         EV_ALIAS("instructions",        "k7-retired-instructions"),
200         EV_ALIAS("interrupts",          "k7-hardware-interrupts"),
201         EV_ALIAS(NULL, NULL)
202 };
203
204 #define K7_KW_COUNT     "count"
205 #define K7_KW_EDGE      "edge"
206 #define K7_KW_INV       "inv"
207 #define K7_KW_OS        "os"
208 #define K7_KW_UNITMASK  "unitmask"
209 #define K7_KW_USR       "usr"
210
211 static int
212 k7_allocate_pmc(enum pmc_event pe, char *ctrspec,
213     struct pmc_op_pmcallocate *pmc_config)
214 {
215         char            *e, *p, *q;
216         int             c, has_unitmask;
217         uint32_t        count, unitmask;
218
219         pmc_config->pm_md.pm_amd.pm_amd_config = 0;
220         pmc_config->pm_caps |= PMC_CAP_READ;
221
222         if (pe == PMC_EV_TSC_TSC) {
223                 /* TSC events must be unqualified. */
224                 if (ctrspec && *ctrspec != '\0')
225                         return -1;
226                 return 0;
227         }
228
229         if (pe == PMC_EV_K7_DC_REFILLS_FROM_L2 ||
230             pe == PMC_EV_K7_DC_REFILLS_FROM_SYSTEM ||
231             pe == PMC_EV_K7_DC_WRITEBACKS) {
232                 has_unitmask = 1;
233                 unitmask = AMD_PMC_UNITMASK_MOESI;
234         } else
235                 unitmask = has_unitmask = 0;
236
237         pmc_config->pm_caps |= PMC_CAP_WRITE;
238
239         while ((p = strsep(&ctrspec, ",")) != NULL) {
240                 if (KWPREFIXMATCH(p, K7_KW_COUNT "=")) {
241                         q = strchr(p, '=');
242                         if (*++q == '\0') /* skip '=' */
243                                 return -1;
244
245                         count = strtol(q, &e, 0);
246                         if (e == q || *e != '\0')
247                                 return -1;
248
249                         pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
250                         pmc_config->pm_md.pm_amd.pm_amd_config |=
251                             AMD_PMC_TO_COUNTER(count);
252
253                 } else if (KWMATCH(p, K7_KW_EDGE)) {
254                         pmc_config->pm_caps |= PMC_CAP_EDGE;
255                 } else if (KWMATCH(p, K7_KW_INV)) {
256                         pmc_config->pm_caps |= PMC_CAP_INVERT;
257                 } else if (KWMATCH(p, K7_KW_OS)) {
258                         pmc_config->pm_caps |= PMC_CAP_SYSTEM;
259                 } else if (KWPREFIXMATCH(p, K7_KW_UNITMASK "=")) {
260                         if (has_unitmask == 0)
261                                 return -1;
262                         unitmask = 0;
263                         q = strchr(p, '=');
264                         if (*++q == '\0') /* skip '=' */
265                                 return -1;
266
267                         while ((c = tolower(*q++)) != 0)
268                                 if (c == 'm')
269                                         unitmask |= AMD_PMC_UNITMASK_M;
270                                 else if (c == 'o')
271                                         unitmask |= AMD_PMC_UNITMASK_O;
272                                 else if (c == 'e')
273                                         unitmask |= AMD_PMC_UNITMASK_E;
274                                 else if (c == 's')
275                                         unitmask |= AMD_PMC_UNITMASK_S;
276                                 else if (c == 'i')
277                                         unitmask |= AMD_PMC_UNITMASK_I;
278                                 else if (c == '+')
279                                         continue;
280                                 else
281                                         return -1;
282
283                         if (unitmask == 0)
284                                 return -1;
285
286                 } else if (KWMATCH(p, K7_KW_USR)) {
287                         pmc_config->pm_caps |= PMC_CAP_USER;
288                 } else
289                         return -1;
290         }
291
292         if (has_unitmask) {
293                 pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
294                 pmc_config->pm_md.pm_amd.pm_amd_config |=
295                     AMD_PMC_TO_UNITMASK(unitmask);
296         }
297
298         return 0;
299
300 }
301
302 #endif
303
304 #if defined(__amd64__) || defined(__i386__)
305
306 /*
307  * AMD K8 PMCs.
308  *
309  * These are very similar to AMD K7 PMCs, but support more kinds of
310  * events.
311  */
312
313 static struct pmc_event_alias k8_aliases[] = {
314         EV_ALIAS("branches",            "k8-fr-retired-taken-branches"),
315         EV_ALIAS("branch-mispredicts",
316             "k8-fr-retired-taken-branches-mispredicted"),
317         EV_ALIAS("cycles",              "tsc"),
318         EV_ALIAS("dc-misses",           "k8-dc-miss"),
319         EV_ALIAS("ic-misses",           "k8-ic-miss"),
320         EV_ALIAS("instructions",        "k8-fr-retired-x86-instructions"),
321         EV_ALIAS("interrupts",          "k8-fr-taken-hardware-interrupts"),
322         EV_ALIAS("unhalted-cycles",     "k8-bu-cpu-clk-unhalted"),
323         EV_ALIAS(NULL, NULL)
324 };
325
326 #define __K8MASK(N,V) PMCMASK(N,(1 << (V)))
327
328 /*
329  * Parsing tables
330  */
331
332 /* fp dispatched fpu ops */
333 static const struct pmc_masks k8_mask_fdfo[] = {
334         __K8MASK(add-pipe-excluding-junk-ops,   0),
335         __K8MASK(multiply-pipe-excluding-junk-ops,      1),
336         __K8MASK(store-pipe-excluding-junk-ops, 2),
337         __K8MASK(add-pipe-junk-ops,             3),
338         __K8MASK(multiply-pipe-junk-ops,        4),
339         __K8MASK(store-pipe-junk-ops,           5),
340         NULLMASK
341 };
342
343 /* ls segment register loads */
344 static const struct pmc_masks k8_mask_lsrl[] = {
345         __K8MASK(es,    0),
346         __K8MASK(cs,    1),
347         __K8MASK(ss,    2),
348         __K8MASK(ds,    3),
349         __K8MASK(fs,    4),
350         __K8MASK(gs,    5),
351         __K8MASK(hs,    6),
352         NULLMASK
353 };
354
355 /* ls locked operation */
356 static const struct pmc_masks k8_mask_llo[] = {
357         __K8MASK(locked-instructions,   0),
358         __K8MASK(cycles-in-request,     1),
359         __K8MASK(cycles-to-complete,    2),
360         NULLMASK
361 };
362
363 /* dc refill from {l2,system} and dc copyback */
364 static const struct pmc_masks k8_mask_dc[] = {
365         __K8MASK(invalid,       0),
366         __K8MASK(shared,        1),
367         __K8MASK(exclusive,     2),
368         __K8MASK(owner,         3),
369         __K8MASK(modified,      4),
370         NULLMASK
371 };
372
373 /* dc one bit ecc error */
374 static const struct pmc_masks k8_mask_dobee[] = {
375         __K8MASK(scrubber,      0),
376         __K8MASK(piggyback,     1),
377         NULLMASK
378 };
379
380 /* dc dispatched prefetch instructions */
381 static const struct pmc_masks k8_mask_ddpi[] = {
382         __K8MASK(load,  0),
383         __K8MASK(store, 1),
384         __K8MASK(nta,   2),
385         NULLMASK
386 };
387
388 /* dc dcache accesses by locks */
389 static const struct pmc_masks k8_mask_dabl[] = {
390         __K8MASK(accesses,      0),
391         __K8MASK(misses,        1),
392         NULLMASK
393 };
394
395 /* bu internal l2 request */
396 static const struct pmc_masks k8_mask_bilr[] = {
397         __K8MASK(ic-fill,       0),
398         __K8MASK(dc-fill,       1),
399         __K8MASK(tlb-reload,    2),
400         __K8MASK(tag-snoop,     3),
401         __K8MASK(cancelled,     4),
402         NULLMASK
403 };
404
405 /* bu fill request l2 miss */
406 static const struct pmc_masks k8_mask_bfrlm[] = {
407         __K8MASK(ic-fill,       0),
408         __K8MASK(dc-fill,       1),
409         __K8MASK(tlb-reload,    2),
410         NULLMASK
411 };
412
413 /* bu fill into l2 */
414 static const struct pmc_masks k8_mask_bfil[] = {
415         __K8MASK(dirty-l2-victim,       0),
416         __K8MASK(victim-from-l2,        1),
417         NULLMASK
418 };
419
420 /* fr retired fpu instructions */
421 static const struct pmc_masks k8_mask_frfi[] = {
422         __K8MASK(x87,                   0),
423         __K8MASK(mmx-3dnow,             1),
424         __K8MASK(packed-sse-sse2,       2),
425         __K8MASK(scalar-sse-sse2,       3),
426         NULLMASK
427 };
428
429 /* fr retired fastpath double op instructions */
430 static const struct pmc_masks k8_mask_frfdoi[] = {
431         __K8MASK(low-op-pos-0,          0),
432         __K8MASK(low-op-pos-1,          1),
433         __K8MASK(low-op-pos-2,          2),
434         NULLMASK
435 };
436
437 /* fr fpu exceptions */
438 static const struct pmc_masks k8_mask_ffe[] = {
439         __K8MASK(x87-reclass-microfaults,       0),
440         __K8MASK(sse-retype-microfaults,        1),
441         __K8MASK(sse-reclass-microfaults,       2),
442         __K8MASK(sse-and-x87-microtraps,        3),
443         NULLMASK
444 };
445
446 /* nb memory controller page access event */
447 static const struct pmc_masks k8_mask_nmcpae[] = {
448         __K8MASK(page-hit,      0),
449         __K8MASK(page-miss,     1),
450         __K8MASK(page-conflict, 2),
451         NULLMASK
452 };
453
454 /* nb memory controller turnaround */
455 static const struct pmc_masks k8_mask_nmct[] = {
456         __K8MASK(dimm-turnaround,               0),
457         __K8MASK(read-to-write-turnaround,      1),
458         __K8MASK(write-to-read-turnaround,      2),
459         NULLMASK
460 };
461
462 /* nb memory controller bypass saturation */
463 static const struct pmc_masks k8_mask_nmcbs[] = {
464         __K8MASK(memory-controller-hi-pri-bypass,       0),
465         __K8MASK(memory-controller-lo-pri-bypass,       1),
466         __K8MASK(dram-controller-interface-bypass,      2),
467         __K8MASK(dram-controller-queue-bypass,          3),
468         NULLMASK
469 };
470
471 /* nb sized commands */
472 static const struct pmc_masks k8_mask_nsc[] = {
473         __K8MASK(nonpostwrszbyte,       0),
474         __K8MASK(nonpostwrszdword,      1),
475         __K8MASK(postwrszbyte,          2),
476         __K8MASK(postwrszdword,         3),
477         __K8MASK(rdszbyte,              4),
478         __K8MASK(rdszdword,             5),
479         __K8MASK(rdmodwr,               6),
480         NULLMASK
481 };
482
483 /* nb probe result */
484 static const struct pmc_masks k8_mask_npr[] = {
485         __K8MASK(probe-miss,            0),
486         __K8MASK(probe-hit,             1),
487         __K8MASK(probe-hit-dirty-no-memory-cancel, 2),
488         __K8MASK(probe-hit-dirty-with-memory-cancel, 3),
489         NULLMASK
490 };
491
492 /* nb hypertransport bus bandwidth */
493 static const struct pmc_masks k8_mask_nhbb[] = { /* HT bus bandwidth */
494         __K8MASK(command,       0),
495         __K8MASK(data,  1),
496         __K8MASK(buffer-release, 2),
497         __K8MASK(nop,   3),
498         NULLMASK
499 };
500
501 #undef  __K8MASK
502
503 #define K8_KW_COUNT     "count"
504 #define K8_KW_EDGE      "edge"
505 #define K8_KW_INV       "inv"
506 #define K8_KW_MASK      "mask"
507 #define K8_KW_OS        "os"
508 #define K8_KW_USR       "usr"
509
510 static int
511 k8_allocate_pmc(enum pmc_event pe, char *ctrspec,
512     struct pmc_op_pmcallocate *pmc_config)
513 {
514         char            *e, *p, *q;
515         int             n;
516         uint32_t        count, evmask;
517         const struct pmc_masks  *pm, *pmask;
518
519         pmc_config->pm_caps |= PMC_CAP_READ;
520         pmc_config->pm_md.pm_amd.pm_amd_config = 0;
521
522         if (pe == PMC_EV_TSC_TSC) {
523                 /* TSC events must be unqualified. */
524                 if (ctrspec && *ctrspec != '\0')
525                         return -1;
526                 return 0;
527         }
528
529         pmask = NULL;
530         evmask = 0;
531
532 #define __K8SETMASK(M) pmask = k8_mask_##M
533
534         /* setup parsing tables */
535         switch (pe) {
536         case PMC_EV_K8_FP_DISPATCHED_FPU_OPS:
537                 __K8SETMASK(fdfo);
538                 break;
539         case PMC_EV_K8_LS_SEGMENT_REGISTER_LOAD:
540                 __K8SETMASK(lsrl);
541                 break;
542         case PMC_EV_K8_LS_LOCKED_OPERATION:
543                 __K8SETMASK(llo);
544                 break;
545         case PMC_EV_K8_DC_REFILL_FROM_L2:
546         case PMC_EV_K8_DC_REFILL_FROM_SYSTEM:
547         case PMC_EV_K8_DC_COPYBACK:
548                 __K8SETMASK(dc);
549                 break;
550         case PMC_EV_K8_DC_ONE_BIT_ECC_ERROR:
551                 __K8SETMASK(dobee);
552                 break;
553         case PMC_EV_K8_DC_DISPATCHED_PREFETCH_INSTRUCTIONS:
554                 __K8SETMASK(ddpi);
555                 break;
556         case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS:
557                 __K8SETMASK(dabl);
558                 break;
559         case PMC_EV_K8_BU_INTERNAL_L2_REQUEST:
560                 __K8SETMASK(bilr);
561                 break;
562         case PMC_EV_K8_BU_FILL_REQUEST_L2_MISS:
563                 __K8SETMASK(bfrlm);
564                 break;
565         case PMC_EV_K8_BU_FILL_INTO_L2:
566                 __K8SETMASK(bfil);
567                 break;
568         case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS:
569                 __K8SETMASK(frfi);
570                 break;
571         case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS:
572                 __K8SETMASK(frfdoi);
573                 break;
574         case PMC_EV_K8_FR_FPU_EXCEPTIONS:
575                 __K8SETMASK(ffe);
576                 break;
577         case PMC_EV_K8_NB_MEMORY_CONTROLLER_PAGE_ACCESS_EVENT:
578                 __K8SETMASK(nmcpae);
579                 break;
580         case PMC_EV_K8_NB_MEMORY_CONTROLLER_TURNAROUND:
581                 __K8SETMASK(nmct);
582                 break;
583         case PMC_EV_K8_NB_MEMORY_CONTROLLER_BYPASS_SATURATION:
584                 __K8SETMASK(nmcbs);
585                 break;
586         case PMC_EV_K8_NB_SIZED_COMMANDS:
587                 __K8SETMASK(nsc);
588                 break;
589         case PMC_EV_K8_NB_PROBE_RESULT:
590                 __K8SETMASK(npr);
591                 break;
592         case PMC_EV_K8_NB_HT_BUS0_BANDWIDTH:
593         case PMC_EV_K8_NB_HT_BUS1_BANDWIDTH:
594         case PMC_EV_K8_NB_HT_BUS2_BANDWIDTH:
595                 __K8SETMASK(nhbb);
596                 break;
597
598         default:
599                 break;          /* no options defined */
600         }
601
602         pmc_config->pm_caps |= PMC_CAP_WRITE;
603
604         while ((p = strsep(&ctrspec, ",")) != NULL) {
605                 if (KWPREFIXMATCH(p, K8_KW_COUNT "=")) {
606                         q = strchr(p, '=');
607                         if (*++q == '\0') /* skip '=' */
608                                 return -1;
609
610                         count = strtol(q, &e, 0);
611                         if (e == q || *e != '\0')
612                                 return -1;
613
614                         pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
615                         pmc_config->pm_md.pm_amd.pm_amd_config |=
616                             AMD_PMC_TO_COUNTER(count);
617
618                 } else if (KWMATCH(p, K8_KW_EDGE)) {
619                         pmc_config->pm_caps |= PMC_CAP_EDGE;
620                 } else if (KWMATCH(p, K8_KW_INV)) {
621                         pmc_config->pm_caps |= PMC_CAP_INVERT;
622                 } else if (KWPREFIXMATCH(p, K8_KW_MASK "=")) {
623                         if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0)
624                                 return -1;
625                         pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
626                 } else if (KWMATCH(p, K8_KW_OS)) {
627                         pmc_config->pm_caps |= PMC_CAP_SYSTEM;
628                 } else if (KWMATCH(p, K8_KW_USR)) {
629                         pmc_config->pm_caps |= PMC_CAP_USER;
630                 } else
631                         return -1;
632         }
633
634         /* other post processing */
635
636         switch (pe) {
637         case PMC_EV_K8_FP_DISPATCHED_FPU_OPS:
638         case PMC_EV_K8_FP_CYCLES_WITH_NO_FPU_OPS_RETIRED:
639         case PMC_EV_K8_FP_DISPATCHED_FPU_FAST_FLAG_OPS:
640         case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS:
641         case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS:
642         case PMC_EV_K8_FR_FPU_EXCEPTIONS:
643                 /* XXX only available in rev B and later */
644                 break;
645         case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS:
646                 /* XXX only available in rev C and later */
647                 break;
648         case PMC_EV_K8_LS_LOCKED_OPERATION:
649                 /* XXX CPU Rev A,B evmask is to be zero */
650                 if (evmask & (evmask - 1)) /* > 1 bit set */
651                         return -1;
652                 if (evmask == 0) {
653                         evmask = 0x01; /* Rev C and later: #instrs */
654                         pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
655                 }
656                 break;
657         default:
658                 if (evmask == 0 && pmask != NULL) {
659                         for (pm = pmask; pm->pm_name; pm++)
660                                 evmask |= pm->pm_value;
661                         pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
662                 }
663         }
664
665         if (pmc_config->pm_caps & PMC_CAP_QUALIFIER)
666                 pmc_config->pm_md.pm_amd.pm_amd_config =
667                     AMD_PMC_TO_UNITMASK(evmask);
668
669         return 0;
670 }
671
672 #endif
673
674 #if defined(__amd64__) || defined(__i386__)
675
676 /*
677  * Intel P4 PMCs
678  */
679
680 static struct pmc_event_alias p4_aliases[] = {
681         EV_ALIAS("branches",            "p4-branch-retired,mask=mmtp+mmtm"),
682         EV_ALIAS("branch-mispredicts",  "p4-mispred-branch-retired"),
683         EV_ALIAS("cycles",              "tsc"),
684         EV_ALIAS("instructions",
685             "p4-instr-retired,mask=nbogusntag+nbogustag"),
686         EV_ALIAS("unhalted-cycles",     "p4-global-power-events"),
687         EV_ALIAS(NULL, NULL)
688 };
689
690 #define P4_KW_ACTIVE    "active"
691 #define P4_KW_ACTIVE_ANY "any"
692 #define P4_KW_ACTIVE_BOTH "both"
693 #define P4_KW_ACTIVE_NONE "none"
694 #define P4_KW_ACTIVE_SINGLE "single"
695 #define P4_KW_BUSREQTYPE "busreqtype"
696 #define P4_KW_CASCADE   "cascade"
697 #define P4_KW_EDGE      "edge"
698 #define P4_KW_INV       "complement"
699 #define P4_KW_OS        "os"
700 #define P4_KW_MASK      "mask"
701 #define P4_KW_PRECISE   "precise"
702 #define P4_KW_TAG       "tag"
703 #define P4_KW_THRESHOLD "threshold"
704 #define P4_KW_USR       "usr"
705
706 #define __P4MASK(N,V) PMCMASK(N, (1 << (V)))
707
708 static const struct pmc_masks p4_mask_tcdm[] = { /* tc deliver mode */
709         __P4MASK(dd, 0),
710         __P4MASK(db, 1),
711         __P4MASK(di, 2),
712         __P4MASK(bd, 3),
713         __P4MASK(bb, 4),
714         __P4MASK(bi, 5),
715         __P4MASK(id, 6),
716         __P4MASK(ib, 7),
717         NULLMASK
718 };
719
720 static const struct pmc_masks p4_mask_bfr[] = { /* bpu fetch request */
721         __P4MASK(tcmiss, 0),
722         NULLMASK,
723 };
724
725 static const struct pmc_masks p4_mask_ir[] = { /* itlb reference */
726         __P4MASK(hit, 0),
727         __P4MASK(miss, 1),
728         __P4MASK(hit-uc, 2),
729         NULLMASK
730 };
731
732 static const struct pmc_masks p4_mask_memcan[] = { /* memory cancel */
733         __P4MASK(st-rb-full, 2),
734         __P4MASK(64k-conf, 3),
735         NULLMASK
736 };
737
738 static const struct pmc_masks p4_mask_memcomp[] = { /* memory complete */
739         __P4MASK(lsc, 0),
740         __P4MASK(ssc, 1),
741         NULLMASK
742 };
743
744 static const struct pmc_masks p4_mask_lpr[] = { /* load port replay */
745         __P4MASK(split-ld, 1),
746         NULLMASK
747 };
748
749 static const struct pmc_masks p4_mask_spr[] = { /* store port replay */
750         __P4MASK(split-st, 1),
751         NULLMASK
752 };
753
754 static const struct pmc_masks p4_mask_mlr[] = { /* mob load replay */
755         __P4MASK(no-sta, 1),
756         __P4MASK(no-std, 3),
757         __P4MASK(partial-data, 4),
758         __P4MASK(unalgn-addr, 5),
759         NULLMASK
760 };
761
762 static const struct pmc_masks p4_mask_pwt[] = { /* page walk type */
763         __P4MASK(dtmiss, 0),
764         __P4MASK(itmiss, 1),
765         NULLMASK
766 };
767
768 static const struct pmc_masks p4_mask_bcr[] = { /* bsq cache reference */
769         __P4MASK(rd-2ndl-hits, 0),
770         __P4MASK(rd-2ndl-hite, 1),
771         __P4MASK(rd-2ndl-hitm, 2),
772         __P4MASK(rd-3rdl-hits, 3),
773         __P4MASK(rd-3rdl-hite, 4),
774         __P4MASK(rd-3rdl-hitm, 5),
775         __P4MASK(rd-2ndl-miss, 8),
776         __P4MASK(rd-3rdl-miss, 9),
777         __P4MASK(wr-2ndl-miss, 10),
778         NULLMASK
779 };
780
781 static const struct pmc_masks p4_mask_ia[] = { /* ioq allocation */
782         __P4MASK(all-read, 5),
783         __P4MASK(all-write, 6),
784         __P4MASK(mem-uc, 7),
785         __P4MASK(mem-wc, 8),
786         __P4MASK(mem-wt, 9),
787         __P4MASK(mem-wp, 10),
788         __P4MASK(mem-wb, 11),
789         __P4MASK(own, 13),
790         __P4MASK(other, 14),
791         __P4MASK(prefetch, 15),
792         NULLMASK
793 };
794
795 static const struct pmc_masks p4_mask_iae[] = { /* ioq active entries */
796         __P4MASK(all-read, 5),
797         __P4MASK(all-write, 6),
798         __P4MASK(mem-uc, 7),
799         __P4MASK(mem-wc, 8),
800         __P4MASK(mem-wt, 9),
801         __P4MASK(mem-wp, 10),
802         __P4MASK(mem-wb, 11),
803         __P4MASK(own, 13),
804         __P4MASK(other, 14),
805         __P4MASK(prefetch, 15),
806         NULLMASK
807 };
808
809 static const struct pmc_masks p4_mask_fda[] = { /* fsb data activity */
810         __P4MASK(drdy-drv, 0),
811         __P4MASK(drdy-own, 1),
812         __P4MASK(drdy-other, 2),
813         __P4MASK(dbsy-drv, 3),
814         __P4MASK(dbsy-own, 4),
815         __P4MASK(dbsy-other, 5),
816         NULLMASK
817 };
818
819 static const struct pmc_masks p4_mask_ba[] = { /* bsq allocation */
820         __P4MASK(req-type0, 0),
821         __P4MASK(req-type1, 1),
822         __P4MASK(req-len0, 2),
823         __P4MASK(req-len1, 3),
824         __P4MASK(req-io-type, 5),
825         __P4MASK(req-lock-type, 6),
826         __P4MASK(req-cache-type, 7),
827         __P4MASK(req-split-type, 8),
828         __P4MASK(req-dem-type, 9),
829         __P4MASK(req-ord-type, 10),
830         __P4MASK(mem-type0, 11),
831         __P4MASK(mem-type1, 12),
832         __P4MASK(mem-type2, 13),
833         NULLMASK
834 };
835
836 static const struct pmc_masks p4_mask_sia[] = { /* sse input assist */
837         __P4MASK(all, 15),
838         NULLMASK
839 };
840
841 static const struct pmc_masks p4_mask_psu[] = { /* packed sp uop */
842         __P4MASK(all, 15),
843         NULLMASK
844 };
845
846 static const struct pmc_masks p4_mask_pdu[] = { /* packed dp uop */
847         __P4MASK(all, 15),
848         NULLMASK
849 };
850
851 static const struct pmc_masks p4_mask_ssu[] = { /* scalar sp uop */
852         __P4MASK(all, 15),
853         NULLMASK
854 };
855
856 static const struct pmc_masks p4_mask_sdu[] = { /* scalar dp uop */
857         __P4MASK(all, 15),
858         NULLMASK
859 };
860
861 static const struct pmc_masks p4_mask_64bmu[] = { /* 64 bit mmx uop */
862         __P4MASK(all, 15),
863         NULLMASK
864 };
865
866 static const struct pmc_masks p4_mask_128bmu[] = { /* 128 bit mmx uop */
867         __P4MASK(all, 15),
868         NULLMASK
869 };
870
871 static const struct pmc_masks p4_mask_xfu[] = { /* X87 fp uop */
872         __P4MASK(all, 15),
873         NULLMASK
874 };
875
876 static const struct pmc_masks p4_mask_xsmu[] = { /* x87 simd moves uop */
877         __P4MASK(allp0, 3),
878         __P4MASK(allp2, 4),
879         NULLMASK
880 };
881
882 static const struct pmc_masks p4_mask_gpe[] = { /* global power events */
883         __P4MASK(running, 0),
884         NULLMASK
885 };
886
887 static const struct pmc_masks p4_mask_tmx[] = { /* TC ms xfer */
888         __P4MASK(cisc, 0),
889         NULLMASK
890 };
891
892 static const struct pmc_masks p4_mask_uqw[] = { /* uop queue writes */
893         __P4MASK(from-tc-build, 0),
894         __P4MASK(from-tc-deliver, 1),
895         __P4MASK(from-rom, 2),
896         NULLMASK
897 };
898
899 static const struct pmc_masks p4_mask_rmbt[] = {
900         /* retired mispred branch type */
901         __P4MASK(conditional, 1),
902         __P4MASK(call, 2),
903         __P4MASK(return, 3),
904         __P4MASK(indirect, 4),
905         NULLMASK
906 };
907
908 static const struct pmc_masks p4_mask_rbt[] = { /* retired branch type */
909         __P4MASK(conditional, 1),
910         __P4MASK(call, 2),
911         __P4MASK(retired, 3),
912         __P4MASK(indirect, 4),
913         NULLMASK
914 };
915
916 static const struct pmc_masks p4_mask_rs[] = { /* resource stall */
917         __P4MASK(sbfull, 5),
918         NULLMASK
919 };
920
921 static const struct pmc_masks p4_mask_wb[] = { /* WC buffer */
922         __P4MASK(wcb-evicts, 0),
923         __P4MASK(wcb-full-evict, 1),
924         NULLMASK
925 };
926
927 static const struct pmc_masks p4_mask_fee[] = { /* front end event */
928         __P4MASK(nbogus, 0),
929         __P4MASK(bogus, 1),
930         NULLMASK
931 };
932
933 static const struct pmc_masks p4_mask_ee[] = { /* execution event */
934         __P4MASK(nbogus0, 0),
935         __P4MASK(nbogus1, 1),
936         __P4MASK(nbogus2, 2),
937         __P4MASK(nbogus3, 3),
938         __P4MASK(bogus0, 4),
939         __P4MASK(bogus1, 5),
940         __P4MASK(bogus2, 6),
941         __P4MASK(bogus3, 7),
942         NULLMASK
943 };
944
945 static const struct pmc_masks p4_mask_re[] = { /* replay event */
946         __P4MASK(nbogus, 0),
947         __P4MASK(bogus, 1),
948         NULLMASK
949 };
950
951 static const struct pmc_masks p4_mask_insret[] = { /* instr retired */
952         __P4MASK(nbogusntag, 0),
953         __P4MASK(nbogustag, 1),
954         __P4MASK(bogusntag, 2),
955         __P4MASK(bogustag, 3),
956         NULLMASK
957 };
958
959 static const struct pmc_masks p4_mask_ur[] = { /* uops retired */
960         __P4MASK(nbogus, 0),
961         __P4MASK(bogus, 1),
962         NULLMASK
963 };
964
965 static const struct pmc_masks p4_mask_ut[] = { /* uop type */
966         __P4MASK(tagloads, 1),
967         __P4MASK(tagstores, 2),
968         NULLMASK
969 };
970
971 static const struct pmc_masks p4_mask_br[] = { /* branch retired */
972         __P4MASK(mmnp, 0),
973         __P4MASK(mmnm, 1),
974         __P4MASK(mmtp, 2),
975         __P4MASK(mmtm, 3),
976         NULLMASK
977 };
978
979 static const struct pmc_masks p4_mask_mbr[] = { /* mispred branch retired */
980         __P4MASK(nbogus, 0),
981         NULLMASK
982 };
983
984 static const struct pmc_masks p4_mask_xa[] = { /* x87 assist */
985         __P4MASK(fpsu, 0),
986         __P4MASK(fpso, 1),
987         __P4MASK(poao, 2),
988         __P4MASK(poau, 3),
989         __P4MASK(prea, 4),
990         NULLMASK
991 };
992
993 static const struct pmc_masks p4_mask_machclr[] = { /* machine clear */
994         __P4MASK(clear, 0),
995         __P4MASK(moclear, 2),
996         __P4MASK(smclear, 3),
997         NULLMASK
998 };
999
1000 /* P4 event parser */
1001 static int
1002 p4_allocate_pmc(enum pmc_event pe, char *ctrspec,
1003     struct pmc_op_pmcallocate *pmc_config)
1004 {
1005
1006         char    *e, *p, *q;
1007         int     count, has_tag, has_busreqtype, n;
1008         uint32_t evmask, cccractivemask;
1009         const struct pmc_masks *pm, *pmask;
1010
1011         pmc_config->pm_caps |= PMC_CAP_READ;
1012         pmc_config->pm_md.pm_p4.pm_p4_cccrconfig =
1013             pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 0;
1014
1015         if (pe == PMC_EV_TSC_TSC) {
1016                 /* TSC must not be further qualified */
1017                 if (ctrspec && *ctrspec != '\0')
1018                         return -1;
1019                 return 0;
1020         }
1021
1022         pmask   = NULL;
1023         evmask  = 0;
1024         cccractivemask = 0x3;
1025         has_tag = has_busreqtype = 0;
1026         pmc_config->pm_caps |= PMC_CAP_WRITE;
1027
1028 #define __P4SETMASK(M) do {                             \
1029         pmask = p4_mask_##M;                            \
1030 } while (0)
1031
1032         switch (pe) {
1033         case PMC_EV_P4_TC_DELIVER_MODE:
1034                 __P4SETMASK(tcdm);
1035                 break;
1036         case PMC_EV_P4_BPU_FETCH_REQUEST:
1037                 __P4SETMASK(bfr);
1038                 break;
1039         case PMC_EV_P4_ITLB_REFERENCE:
1040                 __P4SETMASK(ir);
1041                 break;
1042         case PMC_EV_P4_MEMORY_CANCEL:
1043                 __P4SETMASK(memcan);
1044                 break;
1045         case PMC_EV_P4_MEMORY_COMPLETE:
1046                 __P4SETMASK(memcomp);
1047                 break;
1048         case PMC_EV_P4_LOAD_PORT_REPLAY:
1049                 __P4SETMASK(lpr);
1050                 break;
1051         case PMC_EV_P4_STORE_PORT_REPLAY:
1052                 __P4SETMASK(spr);
1053                 break;
1054         case PMC_EV_P4_MOB_LOAD_REPLAY:
1055                 __P4SETMASK(mlr);
1056                 break;
1057         case PMC_EV_P4_PAGE_WALK_TYPE:
1058                 __P4SETMASK(pwt);
1059                 break;
1060         case PMC_EV_P4_BSQ_CACHE_REFERENCE:
1061                 __P4SETMASK(bcr);
1062                 break;
1063         case PMC_EV_P4_IOQ_ALLOCATION:
1064                 __P4SETMASK(ia);
1065                 has_busreqtype = 1;
1066                 break;
1067         case PMC_EV_P4_IOQ_ACTIVE_ENTRIES:
1068                 __P4SETMASK(iae);
1069                 has_busreqtype = 1;
1070                 break;
1071         case PMC_EV_P4_FSB_DATA_ACTIVITY:
1072                 __P4SETMASK(fda);
1073                 break;
1074         case PMC_EV_P4_BSQ_ALLOCATION:
1075                 __P4SETMASK(ba);
1076                 break;
1077         case PMC_EV_P4_SSE_INPUT_ASSIST:
1078                 __P4SETMASK(sia);
1079                 break;
1080         case PMC_EV_P4_PACKED_SP_UOP:
1081                 __P4SETMASK(psu);
1082                 break;
1083         case PMC_EV_P4_PACKED_DP_UOP:
1084                 __P4SETMASK(pdu);
1085                 break;
1086         case PMC_EV_P4_SCALAR_SP_UOP:
1087                 __P4SETMASK(ssu);
1088                 break;
1089         case PMC_EV_P4_SCALAR_DP_UOP:
1090                 __P4SETMASK(sdu);
1091                 break;
1092         case PMC_EV_P4_64BIT_MMX_UOP:
1093                 __P4SETMASK(64bmu);
1094                 break;
1095         case PMC_EV_P4_128BIT_MMX_UOP:
1096                 __P4SETMASK(128bmu);
1097                 break;
1098         case PMC_EV_P4_X87_FP_UOP:
1099                 __P4SETMASK(xfu);
1100                 break;
1101         case PMC_EV_P4_X87_SIMD_MOVES_UOP:
1102                 __P4SETMASK(xsmu);
1103                 break;
1104         case PMC_EV_P4_GLOBAL_POWER_EVENTS:
1105                 __P4SETMASK(gpe);
1106                 break;
1107         case PMC_EV_P4_TC_MS_XFER:
1108                 __P4SETMASK(tmx);
1109                 break;
1110         case PMC_EV_P4_UOP_QUEUE_WRITES:
1111                 __P4SETMASK(uqw);
1112                 break;
1113         case PMC_EV_P4_RETIRED_MISPRED_BRANCH_TYPE:
1114                 __P4SETMASK(rmbt);
1115                 break;
1116         case PMC_EV_P4_RETIRED_BRANCH_TYPE:
1117                 __P4SETMASK(rbt);
1118                 break;
1119         case PMC_EV_P4_RESOURCE_STALL:
1120                 __P4SETMASK(rs);
1121                 break;
1122         case PMC_EV_P4_WC_BUFFER:
1123                 __P4SETMASK(wb);
1124                 break;
1125         case PMC_EV_P4_BSQ_ACTIVE_ENTRIES:
1126         case PMC_EV_P4_B2B_CYCLES:
1127         case PMC_EV_P4_BNR:
1128         case PMC_EV_P4_SNOOP:
1129         case PMC_EV_P4_RESPONSE:
1130                 break;
1131         case PMC_EV_P4_FRONT_END_EVENT:
1132                 __P4SETMASK(fee);
1133                 break;
1134         case PMC_EV_P4_EXECUTION_EVENT:
1135                 __P4SETMASK(ee);
1136                 break;
1137         case PMC_EV_P4_REPLAY_EVENT:
1138                 __P4SETMASK(re);
1139                 break;
1140         case PMC_EV_P4_INSTR_RETIRED:
1141                 __P4SETMASK(insret);
1142                 break;
1143         case PMC_EV_P4_UOPS_RETIRED:
1144                 __P4SETMASK(ur);
1145                 break;
1146         case PMC_EV_P4_UOP_TYPE:
1147                 __P4SETMASK(ut);
1148                 break;
1149         case PMC_EV_P4_BRANCH_RETIRED:
1150                 __P4SETMASK(br);
1151                 break;
1152         case PMC_EV_P4_MISPRED_BRANCH_RETIRED:
1153                 __P4SETMASK(mbr);
1154                 break;
1155         case PMC_EV_P4_X87_ASSIST:
1156                 __P4SETMASK(xa);
1157                 break;
1158         case PMC_EV_P4_MACHINE_CLEAR:
1159                 __P4SETMASK(machclr);
1160                 break;
1161         default:
1162                 return -1;
1163         }
1164
1165         /* process additional flags */
1166         while ((p = strsep(&ctrspec, ",")) != NULL) {
1167                 if (KWPREFIXMATCH(p, P4_KW_ACTIVE)) {
1168                         q = strchr(p, '=');
1169                         if (*++q == '\0') /* skip '=' */
1170                                 return -1;
1171
1172                         if (strcmp(q, P4_KW_ACTIVE_NONE) == 0)
1173                                 cccractivemask = 0x0;
1174                         else if (strcmp(q, P4_KW_ACTIVE_SINGLE) == 0)
1175                                 cccractivemask = 0x1;
1176                         else if (strcmp(q, P4_KW_ACTIVE_BOTH) == 0)
1177                                 cccractivemask = 0x2;
1178                         else if (strcmp(q, P4_KW_ACTIVE_ANY) == 0)
1179                                 cccractivemask = 0x3;
1180                         else
1181                                 return -1;
1182
1183                 } else if (KWPREFIXMATCH(p, P4_KW_BUSREQTYPE)) {
1184                         if (has_busreqtype == 0)
1185                                 return -1;
1186
1187                         q = strchr(p, '=');
1188                         if (*++q == '\0') /* skip '=' */
1189                                 return -1;
1190
1191                         count = strtol(q, &e, 0);
1192                         if (e == q || *e != '\0')
1193                                 return -1;
1194                         evmask = (evmask & ~0x1F) | (count & 0x1F);
1195                 } else if (KWMATCH(p, P4_KW_CASCADE))
1196                         pmc_config->pm_caps |= PMC_CAP_CASCADE;
1197                 else if (KWMATCH(p, P4_KW_EDGE))
1198                         pmc_config->pm_caps |= PMC_CAP_EDGE;
1199                 else if (KWMATCH(p, P4_KW_INV))
1200                         pmc_config->pm_caps |= PMC_CAP_INVERT;
1201                 else if (KWPREFIXMATCH(p, P4_KW_MASK "=")) {
1202                         if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0)
1203                                 return -1;
1204                         pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
1205                 } else if (KWMATCH(p, P4_KW_OS))
1206                         pmc_config->pm_caps |= PMC_CAP_SYSTEM;
1207                 else if (KWMATCH(p, P4_KW_PRECISE))
1208                         pmc_config->pm_caps |= PMC_CAP_PRECISE;
1209                 else if (KWPREFIXMATCH(p, P4_KW_TAG "=")) {
1210                         if (has_tag == 0)
1211                                 return -1;
1212
1213                         q = strchr(p, '=');
1214                         if (*++q == '\0') /* skip '=' */
1215                                 return -1;
1216
1217                         count = strtol(q, &e, 0);
1218                         if (e == q || *e != '\0')
1219                                 return -1;
1220
1221                         pmc_config->pm_caps |= PMC_CAP_TAGGING;
1222                         pmc_config->pm_md.pm_p4.pm_p4_escrconfig |=
1223                             P4_ESCR_TO_TAG_VALUE(count);
1224                 } else if (KWPREFIXMATCH(p, P4_KW_THRESHOLD "=")) {
1225                         q = strchr(p, '=');
1226                         if (*++q == '\0') /* skip '=' */
1227                                 return -1;
1228
1229                         count = strtol(q, &e, 0);
1230                         if (e == q || *e != '\0')
1231                                 return -1;
1232
1233                         pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
1234                         pmc_config->pm_md.pm_p4.pm_p4_cccrconfig &=
1235                             ~P4_CCCR_THRESHOLD_MASK;
1236                         pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |=
1237                             P4_CCCR_TO_THRESHOLD(count);
1238                 } else if (KWMATCH(p, P4_KW_USR))
1239                         pmc_config->pm_caps |= PMC_CAP_USER;
1240                 else
1241                         return -1;
1242         }
1243
1244         /* other post processing */
1245         if (pe == PMC_EV_P4_IOQ_ALLOCATION ||
1246             pe == PMC_EV_P4_FSB_DATA_ACTIVITY ||
1247             pe == PMC_EV_P4_BSQ_ALLOCATION)
1248                 pmc_config->pm_caps |= PMC_CAP_EDGE;
1249
1250         /* fill in thread activity mask */
1251         pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |=
1252             P4_CCCR_TO_ACTIVE_THREAD(cccractivemask);
1253
1254         if (evmask)
1255                 pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
1256
1257         switch (pe) {
1258         case PMC_EV_P4_FSB_DATA_ACTIVITY:
1259                 if ((evmask & 0x06) == 0x06 ||
1260                     (evmask & 0x18) == 0x18)
1261                         return -1; /* can't have own+other bits together */
1262                 if (evmask == 0) /* default:drdy-{drv,own}+dbsy{drv,own} */
1263                         evmask = 0x1D;
1264                 break;
1265         case PMC_EV_P4_MACHINE_CLEAR:
1266                 /* only one bit is allowed to be set */
1267                 if ((evmask & (evmask - 1)) != 0)
1268                         return -1;
1269                 if (evmask == 0) {
1270                         evmask = 0x1;   /* 'CLEAR' */
1271                         pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
1272                 }
1273                 break;
1274         default:
1275                 if (evmask == 0 && pmask) {
1276                         for (pm = pmask; pm->pm_name; pm++)
1277                                 evmask |= pm->pm_value;
1278                         pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
1279                 }
1280         }
1281
1282         pmc_config->pm_md.pm_p4.pm_p4_escrconfig =
1283             P4_ESCR_TO_EVENT_MASK(evmask);
1284
1285         return 0;
1286 }
1287
1288 #endif
1289
1290 #if defined(__i386__)
1291
1292 /*
1293  * Pentium style PMCs
1294  */
1295
1296 static struct pmc_event_alias p5_aliases[] = {
1297         EV_ALIAS("cycles", "tsc"),
1298         EV_ALIAS(NULL, NULL)
1299 };
1300
1301 static int
1302 p5_allocate_pmc(enum pmc_event pe, char *ctrspec,
1303     struct pmc_op_pmcallocate *pmc_config)
1304 {
1305         return -1 || pe || ctrspec || pmc_config; /* shut up gcc */
1306 }
1307
1308 /*
1309  * Pentium Pro style PMCs.  These PMCs are found in Pentium II, Pentium III,
1310  * and Pentium M CPUs.
1311  */
1312
1313 static struct pmc_event_alias p6_aliases[] = {
1314         EV_ALIAS("branches",            "p6-br-inst-retired"),
1315         EV_ALIAS("branch-mispredicts",  "p6-br-miss-pred-retired"),
1316         EV_ALIAS("cycles",              "tsc"),
1317         EV_ALIAS("dc-misses",           "p6-dcu-lines-in"),
1318         EV_ALIAS("ic-misses",           "p6-ifu-fetch-miss"),
1319         EV_ALIAS("instructions",        "p6-inst-retired"),
1320         EV_ALIAS("interrupts",          "p6-hw-int-rx"),
1321         EV_ALIAS("unhalted-cycles",     "p6-cpu-clk-unhalted"),
1322         EV_ALIAS(NULL, NULL)
1323 };
1324
1325 #define P6_KW_CMASK     "cmask"
1326 #define P6_KW_EDGE      "edge"
1327 #define P6_KW_INV       "inv"
1328 #define P6_KW_OS        "os"
1329 #define P6_KW_UMASK     "umask"
1330 #define P6_KW_USR       "usr"
1331
1332 static struct pmc_masks p6_mask_mesi[] = {
1333         PMCMASK(m,      0x01),
1334         PMCMASK(e,      0x02),
1335         PMCMASK(s,      0x04),
1336         PMCMASK(i,      0x08),
1337         NULLMASK
1338 };
1339
1340 static struct pmc_masks p6_mask_mesihw[] = {
1341         PMCMASK(m,      0x01),
1342         PMCMASK(e,      0x02),
1343         PMCMASK(s,      0x04),
1344         PMCMASK(i,      0x08),
1345         PMCMASK(nonhw,  0x00),
1346         PMCMASK(hw,     0x10),
1347         PMCMASK(both,   0x30),
1348         NULLMASK
1349 };
1350
1351 static struct pmc_masks p6_mask_hw[] = {
1352         PMCMASK(nonhw,  0x00),
1353         PMCMASK(hw,     0x10),
1354         PMCMASK(both,   0x30),
1355         NULLMASK
1356 };
1357
1358 static struct pmc_masks p6_mask_any[] = {
1359         PMCMASK(self,   0x00),
1360         PMCMASK(any,    0x20),
1361         NULLMASK
1362 };
1363
1364 static struct pmc_masks p6_mask_ekp[] = {
1365         PMCMASK(nta,    0x00),
1366         PMCMASK(t1,     0x01),
1367         PMCMASK(t2,     0x02),
1368         PMCMASK(wos,    0x03),
1369         NULLMASK
1370 };
1371
1372 static struct pmc_masks p6_mask_pps[] = {
1373         PMCMASK(packed-and-scalar, 0x00),
1374         PMCMASK(scalar, 0x01),
1375         NULLMASK
1376 };
1377
1378 static struct pmc_masks p6_mask_mite[] = {
1379         PMCMASK(packed-multiply,         0x01),
1380         PMCMASK(packed-shift,           0x02),
1381         PMCMASK(pack,                   0x04),
1382         PMCMASK(unpack,                 0x08),
1383         PMCMASK(packed-logical,         0x10),
1384         PMCMASK(packed-arithmetic,      0x20),
1385         NULLMASK
1386 };
1387
1388 static struct pmc_masks p6_mask_fmt[] = {
1389         PMCMASK(mmxtofp,        0x00),
1390         PMCMASK(fptommx,        0x01),
1391         NULLMASK
1392 };
1393
1394 static struct pmc_masks p6_mask_sr[] = {
1395         PMCMASK(es,     0x01),
1396         PMCMASK(ds,     0x02),
1397         PMCMASK(fs,     0x04),
1398         PMCMASK(gs,     0x08),
1399         NULLMASK
1400 };
1401
1402 static struct pmc_masks p6_mask_eet[] = {
1403         PMCMASK(all,    0x00),
1404         PMCMASK(freq,   0x02),
1405         NULLMASK
1406 };
1407
1408 static struct pmc_masks p6_mask_efur[] = {
1409         PMCMASK(all,    0x00),
1410         PMCMASK(loadop, 0x01),
1411         PMCMASK(stdsta, 0x02),
1412         NULLMASK
1413 };
1414
1415 static struct pmc_masks p6_mask_essir[] = {
1416         PMCMASK(sse-packed-single,      0x00),
1417         PMCMASK(sse-packed-single-scalar-single, 0x01),
1418         PMCMASK(sse2-packed-double,     0x02),
1419         PMCMASK(sse2-scalar-double,     0x03),
1420         NULLMASK
1421 };
1422
1423 static struct pmc_masks p6_mask_esscir[] = {
1424         PMCMASK(sse-packed-single,      0x00),
1425         PMCMASK(sse-scalar-single,      0x01),
1426         PMCMASK(sse2-packed-double,     0x02),
1427         PMCMASK(sse2-scalar-double,     0x03),
1428         NULLMASK
1429 };
1430
1431 /* P6 event parser */
1432 static int
1433 p6_allocate_pmc(enum pmc_event pe, char *ctrspec,
1434     struct pmc_op_pmcallocate *pmc_config)
1435 {
1436         char *e, *p, *q;
1437         uint32_t evmask;
1438         int count, n;
1439         const struct pmc_masks *pm, *pmask;
1440
1441         pmc_config->pm_caps |= PMC_CAP_READ;
1442         pmc_config->pm_md.pm_ppro.pm_ppro_config = 0;
1443
1444         if (pe == PMC_EV_TSC_TSC) {
1445                 if (ctrspec && *ctrspec != '\0')
1446                         return -1;
1447                 return 0;
1448         }
1449
1450         pmc_config->pm_caps |= PMC_CAP_WRITE;
1451         evmask = 0;
1452
1453 #define P6MASKSET(M)    pmask = p6_mask_ ## M
1454
1455         switch(pe) {
1456         case PMC_EV_P6_L2_IFETCH:       P6MASKSET(mesi); break;
1457         case PMC_EV_P6_L2_LD:           P6MASKSET(mesi); break;
1458         case PMC_EV_P6_L2_ST:           P6MASKSET(mesi); break;
1459         case PMC_EV_P6_L2_RQSTS:        P6MASKSET(mesi); break;
1460         case PMC_EV_P6_BUS_DRDY_CLOCKS:
1461         case PMC_EV_P6_BUS_LOCK_CLOCKS:
1462         case PMC_EV_P6_BUS_TRAN_BRD:
1463         case PMC_EV_P6_BUS_TRAN_RFO:
1464         case PMC_EV_P6_BUS_TRANS_WB:
1465         case PMC_EV_P6_BUS_TRAN_IFETCH:
1466         case PMC_EV_P6_BUS_TRAN_INVAL:
1467         case PMC_EV_P6_BUS_TRAN_PWR:
1468         case PMC_EV_P6_BUS_TRANS_P:
1469         case PMC_EV_P6_BUS_TRANS_IO:
1470         case PMC_EV_P6_BUS_TRAN_DEF:
1471         case PMC_EV_P6_BUS_TRAN_BURST:
1472         case PMC_EV_P6_BUS_TRAN_ANY:
1473         case PMC_EV_P6_BUS_TRAN_MEM:
1474                 P6MASKSET(any); break;
1475         case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED:
1476         case PMC_EV_P6_EMON_KNI_PREF_MISS:
1477                 P6MASKSET(ekp); break;
1478         case PMC_EV_P6_EMON_KNI_INST_RETIRED:
1479         case PMC_EV_P6_EMON_KNI_COMP_INST_RET:
1480                 P6MASKSET(pps); break;
1481         case PMC_EV_P6_MMX_INSTR_TYPE_EXEC:
1482                 P6MASKSET(mite); break;
1483         case PMC_EV_P6_FP_MMX_TRANS:
1484                 P6MASKSET(fmt); break;
1485         case PMC_EV_P6_SEG_RENAME_STALLS:
1486         case PMC_EV_P6_SEG_REG_RENAMES:
1487                 P6MASKSET(sr);  break;
1488         case PMC_EV_P6_EMON_EST_TRANS:
1489                 P6MASKSET(eet); break;
1490         case PMC_EV_P6_EMON_FUSED_UOPS_RET:
1491                 P6MASKSET(efur); break;
1492         case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED:
1493                 P6MASKSET(essir); break;
1494         case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED:
1495                 P6MASKSET(esscir); break;
1496         default:
1497                 pmask = NULL;
1498                 break;
1499         }
1500
1501         /* Pentium M PMCs have a few events with different semantics */
1502         if (cpu_info.pm_cputype == PMC_CPU_INTEL_PM) {
1503                 if (pe == PMC_EV_P6_L2_LD ||
1504                     pe == PMC_EV_P6_L2_LINES_IN ||
1505                     pe == PMC_EV_P6_L2_LINES_OUT)
1506                         P6MASKSET(mesihw);
1507                 else if (pe == PMC_EV_P6_L2_M_LINES_OUTM)
1508                         P6MASKSET(hw);
1509         }
1510
1511         /* Parse additional modifiers if present */
1512         while ((p = strsep(&ctrspec, ",")) != NULL) {
1513                 if (KWPREFIXMATCH(p, P6_KW_CMASK "=")) {
1514                         q = strchr(p, '=');
1515                         if (*++q == '\0') /* skip '=' */
1516                                 return -1;
1517                         count = strtol(q, &e, 0);
1518                         if (e == q || *e != '\0')
1519                                 return -1;
1520                         pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
1521                         pmc_config->pm_md.pm_ppro.pm_ppro_config |=
1522                             P6_EVSEL_TO_CMASK(count);
1523                 } else if (KWMATCH(p, P6_KW_EDGE)) {
1524                         pmc_config->pm_caps |= PMC_CAP_EDGE;
1525                 } else if (KWMATCH(p, P6_KW_INV)) {
1526                         pmc_config->pm_caps |= PMC_CAP_INVERT;
1527                 } else if (KWMATCH(p, P6_KW_OS)) {
1528                         pmc_config->pm_caps |= PMC_CAP_SYSTEM;
1529                 } else if (KWPREFIXMATCH(p, P6_KW_UMASK "=")) {
1530                         evmask = 0;
1531                         if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0)
1532                                 return -1;
1533                         if ((pe == PMC_EV_P6_BUS_DRDY_CLOCKS ||
1534                              pe == PMC_EV_P6_BUS_LOCK_CLOCKS ||
1535                              pe == PMC_EV_P6_BUS_TRAN_BRD ||
1536                              pe == PMC_EV_P6_BUS_TRAN_RFO ||
1537                              pe == PMC_EV_P6_BUS_TRAN_IFETCH ||
1538                              pe == PMC_EV_P6_BUS_TRAN_INVAL ||
1539                              pe == PMC_EV_P6_BUS_TRAN_PWR ||
1540                              pe == PMC_EV_P6_BUS_TRAN_DEF ||
1541                              pe == PMC_EV_P6_BUS_TRAN_BURST ||
1542                              pe == PMC_EV_P6_BUS_TRAN_ANY ||
1543                              pe == PMC_EV_P6_BUS_TRAN_MEM ||
1544                              pe == PMC_EV_P6_BUS_TRANS_IO ||
1545                              pe == PMC_EV_P6_BUS_TRANS_P ||
1546                              pe == PMC_EV_P6_BUS_TRANS_WB ||
1547                              pe == PMC_EV_P6_EMON_EST_TRANS ||
1548                              pe == PMC_EV_P6_EMON_FUSED_UOPS_RET ||
1549                              pe == PMC_EV_P6_EMON_KNI_COMP_INST_RET ||
1550                              pe == PMC_EV_P6_EMON_KNI_INST_RETIRED ||
1551                              pe == PMC_EV_P6_EMON_KNI_PREF_DISPATCHED ||
1552                              pe == PMC_EV_P6_EMON_KNI_PREF_MISS ||
1553                              pe == PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED ||
1554                              pe == PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED ||
1555                              pe == PMC_EV_P6_FP_MMX_TRANS)
1556                             && (n > 1))
1557                                 return -1; /* only one mask keyword allowed */
1558                         pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
1559                 } else if (KWMATCH(p, P6_KW_USR)) {
1560                         pmc_config->pm_caps |= PMC_CAP_USER;
1561                 } else
1562                         return -1;
1563         }
1564
1565         /* post processing */
1566         switch (pe) {
1567
1568                 /*
1569                  * The following events default to an evmask of 0
1570                  */
1571
1572                 /* default => 'self' */
1573         case PMC_EV_P6_BUS_DRDY_CLOCKS:
1574         case PMC_EV_P6_BUS_LOCK_CLOCKS:
1575         case PMC_EV_P6_BUS_TRAN_BRD:
1576         case PMC_EV_P6_BUS_TRAN_RFO:
1577         case PMC_EV_P6_BUS_TRANS_WB:
1578         case PMC_EV_P6_BUS_TRAN_IFETCH:
1579         case PMC_EV_P6_BUS_TRAN_INVAL:
1580         case PMC_EV_P6_BUS_TRAN_PWR:
1581         case PMC_EV_P6_BUS_TRANS_P:
1582         case PMC_EV_P6_BUS_TRANS_IO:
1583         case PMC_EV_P6_BUS_TRAN_DEF:
1584         case PMC_EV_P6_BUS_TRAN_BURST:
1585         case PMC_EV_P6_BUS_TRAN_ANY:
1586         case PMC_EV_P6_BUS_TRAN_MEM:
1587
1588                 /* default => 'nta' */
1589         case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED:
1590         case PMC_EV_P6_EMON_KNI_PREF_MISS:
1591
1592                 /* default => 'packed and scalar' */
1593         case PMC_EV_P6_EMON_KNI_INST_RETIRED:
1594         case PMC_EV_P6_EMON_KNI_COMP_INST_RET:
1595
1596                 /* default => 'mmx to fp transitions' */
1597         case PMC_EV_P6_FP_MMX_TRANS:
1598
1599                 /* default => 'SSE Packed Single' */
1600         case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED:
1601         case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED:
1602
1603                 /* default => 'all fused micro-ops' */
1604         case PMC_EV_P6_EMON_FUSED_UOPS_RET:
1605
1606                 /* default => 'all transitions' */
1607         case PMC_EV_P6_EMON_EST_TRANS:
1608                 break;
1609
1610         case PMC_EV_P6_MMX_UOPS_EXEC:
1611                 evmask = 0x0F;          /* only value allowed */
1612                 break;
1613
1614         default:
1615
1616                 /*
1617                  * For all other events, set the default event mask
1618                  * to a logical OR of all the allowed event mask bits.
1619                  */
1620
1621                 if (evmask == 0 && pmask) {
1622                         for (pm = pmask; pm->pm_name; pm++)
1623                                 evmask |= pm->pm_value;
1624                         pmc_config->pm_caps |= PMC_CAP_QUALIFIER;
1625                 }
1626
1627                 break;
1628         }
1629
1630         if (pmc_config->pm_caps & PMC_CAP_QUALIFIER)
1631                 pmc_config->pm_md.pm_ppro.pm_ppro_config |=
1632                     P6_EVSEL_TO_UMASK(evmask);
1633
1634         return 0;
1635 }
1636
1637 #endif
1638
1639 /*
1640  * API entry points
1641  */
1642
1643
1644 int
1645 pmc_allocate(const char *ctrspec, enum pmc_mode mode,
1646     uint32_t flags, int cpu, pmc_id_t *pmcid)
1647 {
1648         int retval;
1649         enum pmc_event pe;
1650         char *r, *spec_copy;
1651         const char *ctrname;
1652         const struct pmc_event_alias *p;
1653         struct pmc_op_pmcallocate pmc_config;
1654
1655         spec_copy = NULL;
1656         retval    = -1;
1657
1658         if (mode != PMC_MODE_SS && mode != PMC_MODE_TS &&
1659             mode != PMC_MODE_SC && mode != PMC_MODE_TC) {
1660                 errno = EINVAL;
1661                 goto out;
1662         }
1663
1664         /* replace an event alias with the canonical event specifier */
1665         if (pmc_mdep_event_aliases)
1666                 for (p = pmc_mdep_event_aliases; p->pm_alias; p++)
1667                         if (!strcmp(ctrspec, p->pm_alias)) {
1668                                 spec_copy = strdup(p->pm_spec);
1669                                 break;
1670                         }
1671
1672         if (spec_copy == NULL)
1673                 spec_copy = strdup(ctrspec);
1674
1675         r = spec_copy;
1676         ctrname = strsep(&r, ",");
1677
1678         /* look for the given counter name */
1679
1680         for (pe = PMC_EVENT_FIRST; pe < (PMC_EVENT_LAST+1); pe++)
1681                 if (!strcmp(ctrname, pmc_event_table[pe].pm_ev_name))
1682                         break;
1683
1684         if (pe > PMC_EVENT_LAST) {
1685                 errno = EINVAL;
1686                 goto out;
1687         }
1688
1689         bzero(&pmc_config, sizeof(pmc_config));
1690         pmc_config.pm_ev    = pmc_event_table[pe].pm_ev_code;
1691         pmc_config.pm_class = pmc_event_table[pe].pm_ev_class;
1692         pmc_config.pm_cpu   = cpu;
1693         pmc_config.pm_mode  = mode;
1694         pmc_config.pm_flags = flags;
1695
1696         if (PMC_IS_SAMPLING_MODE(mode))
1697                 pmc_config.pm_caps |= PMC_CAP_INTERRUPT;
1698
1699         if (pmc_mdep_allocate_pmc(pe, r, &pmc_config) < 0) {
1700                 errno = EINVAL;
1701                 goto out;
1702         }
1703
1704         if (PMC_CALL(PMCALLOCATE, &pmc_config) < 0)
1705                 goto out;
1706
1707         *pmcid = pmc_config.pm_pmcid;
1708
1709         retval = 0;
1710
1711  out:
1712         if (spec_copy)
1713                 free(spec_copy);
1714
1715         return retval;
1716 }
1717
1718 int
1719 pmc_attach(pmc_id_t pmc, pid_t pid)
1720 {
1721         struct pmc_op_pmcattach pmc_attach_args;
1722
1723         pmc_attach_args.pm_pmc = pmc;
1724         pmc_attach_args.pm_pid = pid;
1725
1726         return PMC_CALL(PMCATTACH, &pmc_attach_args);
1727 }
1728
1729 int
1730 pmc_capabilities(pmc_id_t pmcid, uint32_t *caps)
1731 {
1732         unsigned int i;
1733         enum pmc_class cl;
1734
1735         cl = PMC_ID_TO_CLASS(pmcid);
1736         for (i = 0; i < cpu_info.pm_nclass; i++)
1737                 if (cpu_info.pm_classes[i].pm_class == cl) {
1738                         *caps = cpu_info.pm_classes[i].pm_caps;
1739                         return 0;
1740                 }
1741         return EINVAL;
1742 }
1743
1744 int
1745 pmc_configure_logfile(int fd)
1746 {
1747         struct pmc_op_configurelog cla;
1748
1749         cla.pm_logfd = fd;
1750         if (PMC_CALL(CONFIGURELOG, &cla) < 0)
1751                 return -1;
1752         return 0;
1753 }
1754
1755 int
1756 pmc_cpuinfo(const struct pmc_cpuinfo **pci)
1757 {
1758         if (pmc_syscall == -1) {
1759                 errno = ENXIO;
1760                 return -1;
1761         }
1762
1763         *pci = &cpu_info;
1764         return 0;
1765 }
1766
1767 int
1768 pmc_detach(pmc_id_t pmc, pid_t pid)
1769 {
1770         struct pmc_op_pmcattach pmc_detach_args;
1771
1772         pmc_detach_args.pm_pmc = pmc;
1773         pmc_detach_args.pm_pid = pid;
1774
1775         return PMC_CALL(PMCDETACH, &pmc_detach_args);
1776 }
1777
1778 int
1779 pmc_disable(int cpu, int pmc)
1780 {
1781         struct pmc_op_pmcadmin ssa;
1782
1783         ssa.pm_cpu = cpu;
1784         ssa.pm_pmc = pmc;
1785         ssa.pm_state = PMC_STATE_DISABLED;
1786         return PMC_CALL(PMCADMIN, &ssa);
1787 }
1788
1789 int
1790 pmc_enable(int cpu, int pmc)
1791 {
1792         struct pmc_op_pmcadmin ssa;
1793
1794         ssa.pm_cpu = cpu;
1795         ssa.pm_pmc = pmc;
1796         ssa.pm_state = PMC_STATE_FREE;
1797         return PMC_CALL(PMCADMIN, &ssa);
1798 }
1799
1800 /*
1801  * Return a list of events known to a given PMC class.  'cl' is the
1802  * PMC class identifier, 'eventnames' is the returned list of 'const
1803  * char *' pointers pointing to the names of the events. 'nevents' is
1804  * the number of event name pointers returned.
1805  *
1806  * The space for 'eventnames' is allocated using malloc(3).  The caller
1807  * is responsible for freeing this space when done.
1808  */
1809
1810 int
1811 pmc_event_names_of_class(enum pmc_class cl, const char ***eventnames,
1812     int *nevents)
1813 {
1814         int count;
1815         const char **names;
1816         const struct pmc_event_descr *ev;
1817
1818         switch (cl)
1819         {
1820         case PMC_CLASS_TSC:
1821                 ev = &pmc_event_table[PMC_EV_TSC_TSC];
1822                 count = 1;
1823                 break;
1824         case PMC_CLASS_K7:
1825                 ev = &pmc_event_table[PMC_EV_K7_FIRST];
1826                 count = PMC_EV_K7_LAST - PMC_EV_K7_FIRST + 1;
1827                 break;
1828         case PMC_CLASS_K8:
1829                 ev = &pmc_event_table[PMC_EV_K8_FIRST];
1830                 count = PMC_EV_K8_LAST - PMC_EV_K8_FIRST + 1;
1831                 break;
1832         case PMC_CLASS_P5:
1833                 ev = &pmc_event_table[PMC_EV_P5_FIRST];
1834                 count = PMC_EV_P5_LAST - PMC_EV_P5_FIRST + 1;
1835                 break;
1836         case PMC_CLASS_P6:
1837                 ev = &pmc_event_table[PMC_EV_P6_FIRST];
1838                 count = PMC_EV_P6_LAST - PMC_EV_P6_FIRST + 1;
1839                 break;
1840         case PMC_CLASS_P4:
1841                 ev = &pmc_event_table[PMC_EV_P4_FIRST];
1842                 count = PMC_EV_P4_LAST - PMC_EV_P4_FIRST + 1;
1843                 break;
1844         default:
1845                 errno = EINVAL;
1846                 return -1;
1847         }
1848
1849         if ((names = malloc(count * sizeof(const char *))) == NULL)
1850                 return -1;
1851
1852         *eventnames = names;
1853         *nevents = count;
1854
1855         for (;count--; ev++, names++)
1856                 *names = ev->pm_ev_name;
1857         return 0;
1858 }
1859
1860 int
1861 pmc_flush_logfile(void)
1862 {
1863         return PMC_CALL(FLUSHLOG,0);
1864 }
1865
1866 int
1867 pmc_get_driver_stats(struct pmc_driverstats *ds)
1868 {
1869         struct pmc_op_getdriverstats gms;
1870
1871         if (PMC_CALL(GETDRIVERSTATS, &gms) < 0)
1872                 return -1;
1873
1874         /* copy out fields in the current userland<->library interface */
1875         ds->pm_intr_ignored    = gms.pm_intr_ignored;
1876         ds->pm_intr_processed  = gms.pm_intr_processed;
1877         ds->pm_intr_bufferfull = gms.pm_intr_bufferfull;
1878         ds->pm_syscalls        = gms.pm_syscalls;
1879         ds->pm_syscall_errors  = gms.pm_syscall_errors;
1880         ds->pm_buffer_requests = gms.pm_buffer_requests;
1881         ds->pm_buffer_requests_failed = gms.pm_buffer_requests_failed;
1882         ds->pm_log_sweeps      = gms.pm_log_sweeps;
1883
1884         return 0;
1885 }
1886
1887 int
1888 pmc_get_msr(pmc_id_t pmc, uint32_t *msr)
1889 {
1890         struct pmc_op_getmsr gm;
1891
1892         gm.pm_pmcid = pmc;
1893         if (PMC_CALL(PMCGETMSR, &gm) < 0)
1894                 return -1;
1895         *msr = gm.pm_msr;
1896         return 0;
1897 }
1898
1899 int
1900 pmc_init(void)
1901 {
1902         int error, pmc_mod_id;
1903         unsigned int n;
1904         uint32_t abi_version;
1905         struct module_stat pmc_modstat;
1906         struct pmc_op_getcpuinfo op_cpu_info;
1907
1908         if (pmc_syscall != -1) /* already inited */
1909                 return 0;
1910
1911         /* retrieve the system call number from the KLD */
1912         if ((pmc_mod_id = modfind(PMC_MODULE_NAME)) < 0)
1913                 return -1;
1914
1915         pmc_modstat.version = sizeof(struct module_stat);
1916         if ((error = modstat(pmc_mod_id, &pmc_modstat)) < 0)
1917                 return -1;
1918
1919         pmc_syscall = pmc_modstat.data.intval;
1920
1921         /* check the kernel module's ABI against our compiled-in version */
1922         abi_version = PMC_VERSION;
1923         if (PMC_CALL(GETMODULEVERSION, &abi_version) < 0)
1924                 return (pmc_syscall = -1);
1925
1926         /* ignore patch & minor numbers for the comparision */
1927         if ((abi_version & 0xFF000000) != (PMC_VERSION & 0xFF000000)) {
1928                 errno  = EPROGMISMATCH;
1929                 return (pmc_syscall = -1);
1930         }
1931
1932         if (PMC_CALL(GETCPUINFO, &op_cpu_info) < 0)
1933                 return (pmc_syscall = -1);
1934
1935         cpu_info.pm_cputype = op_cpu_info.pm_cputype;
1936         cpu_info.pm_ncpu    = op_cpu_info.pm_ncpu;
1937         cpu_info.pm_npmc    = op_cpu_info.pm_npmc;
1938         cpu_info.pm_nclass  = op_cpu_info.pm_nclass;
1939         for (n = 0; n < cpu_info.pm_nclass; n++)
1940                 cpu_info.pm_classes[n] = op_cpu_info.pm_classes[n];
1941
1942         /* set parser pointer */
1943         switch (cpu_info.pm_cputype) {
1944 #if defined(__i386__)
1945         case PMC_CPU_AMD_K7:
1946                 pmc_mdep_event_aliases = k7_aliases;
1947                 pmc_mdep_allocate_pmc = k7_allocate_pmc;
1948                 break;
1949         case PMC_CPU_INTEL_P5:
1950                 pmc_mdep_event_aliases = p5_aliases;
1951                 pmc_mdep_allocate_pmc = p5_allocate_pmc;
1952                 break;
1953         case PMC_CPU_INTEL_P6:          /* P6 ... Pentium M CPUs have */
1954         case PMC_CPU_INTEL_PII:         /* similar PMCs. */
1955         case PMC_CPU_INTEL_PIII:
1956         case PMC_CPU_INTEL_PM:
1957                 pmc_mdep_event_aliases = p6_aliases;
1958                 pmc_mdep_allocate_pmc = p6_allocate_pmc;
1959                 break;
1960 #endif
1961 #if defined(__amd64__) || defined(__i386__)
1962         case PMC_CPU_INTEL_PIV:
1963                 pmc_mdep_event_aliases = p4_aliases;
1964                 pmc_mdep_allocate_pmc = p4_allocate_pmc;
1965                 break;
1966         case PMC_CPU_AMD_K8:
1967                 pmc_mdep_event_aliases = k8_aliases;
1968                 pmc_mdep_allocate_pmc = k8_allocate_pmc;
1969                 break;
1970 #endif
1971
1972         default:
1973                 /*
1974                  * Some kind of CPU this version of the library knows nothing
1975                  * about.  This shouldn't happen since the abi version check
1976                  * should have caught this.
1977                  */
1978                 errno = ENXIO;
1979                 return (pmc_syscall = -1);
1980         }
1981
1982         return 0;
1983 }
1984
1985 const char *
1986 pmc_name_of_capability(enum pmc_caps cap)
1987 {
1988         int i;
1989
1990         /*
1991          * 'cap' should have a single bit set and should be in
1992          * range.
1993          */
1994
1995         if ((cap & (cap - 1)) || cap < PMC_CAP_FIRST ||
1996             cap > PMC_CAP_LAST) {
1997                 errno = EINVAL;
1998                 return NULL;
1999         }
2000
2001         i = ffs(cap);
2002
2003         return pmc_capability_names[i - 1];
2004 }
2005
2006 const char *
2007 pmc_name_of_class(enum pmc_class pc)
2008 {
2009         if ((int) pc >= PMC_CLASS_FIRST &&
2010             pc <= PMC_CLASS_LAST)
2011                 return pmc_class_names[pc];
2012
2013         errno = EINVAL;
2014         return NULL;
2015 }
2016
2017 const char *
2018 pmc_name_of_cputype(enum pmc_cputype cp)
2019 {
2020         if ((int) cp >= PMC_CPU_FIRST &&
2021             cp <= PMC_CPU_LAST)
2022                 return pmc_cputype_names[cp];
2023         errno = EINVAL;
2024         return NULL;
2025 }
2026
2027 const char *
2028 pmc_name_of_disposition(enum pmc_disp pd)
2029 {
2030         if ((int) pd >= PMC_DISP_FIRST &&
2031             pd <= PMC_DISP_LAST)
2032                 return pmc_disposition_names[pd];
2033
2034         errno = EINVAL;
2035         return NULL;
2036 }
2037
2038 const char *
2039 pmc_name_of_event(enum pmc_event pe)
2040 {
2041         if ((int) pe >= PMC_EVENT_FIRST &&
2042             pe <= PMC_EVENT_LAST)
2043                 return pmc_event_table[pe].pm_ev_name;
2044
2045         errno = EINVAL;
2046         return NULL;
2047 }
2048
2049 const char *
2050 pmc_name_of_mode(enum pmc_mode pm)
2051 {
2052         if ((int) pm >= PMC_MODE_FIRST &&
2053             pm <= PMC_MODE_LAST)
2054                 return pmc_mode_names[pm];
2055
2056         errno = EINVAL;
2057         return NULL;
2058 }
2059
2060 const char *
2061 pmc_name_of_state(enum pmc_state ps)
2062 {
2063         if ((int) ps >= PMC_STATE_FIRST &&
2064             ps <= PMC_STATE_LAST)
2065                 return pmc_state_names[ps];
2066
2067         errno = EINVAL;
2068         return NULL;
2069 }
2070
2071 int
2072 pmc_ncpu(void)
2073 {
2074         if (pmc_syscall == -1) {
2075                 errno = ENXIO;
2076                 return -1;
2077         }
2078
2079         return cpu_info.pm_ncpu;
2080 }
2081
2082 int
2083 pmc_npmc(int cpu)
2084 {
2085         if (pmc_syscall == -1) {
2086                 errno = ENXIO;
2087                 return -1;
2088         }
2089
2090         if (cpu < 0 || cpu >= (int) cpu_info.pm_ncpu) {
2091                 errno = EINVAL;
2092                 return -1;
2093         }
2094
2095         return cpu_info.pm_npmc;
2096 }
2097
2098 int
2099 pmc_pmcinfo(int cpu, struct pmc_pmcinfo **ppmci)
2100 {
2101         int nbytes, npmc;
2102         struct pmc_op_getpmcinfo *pmci;
2103
2104         if ((npmc = pmc_npmc(cpu)) < 0)
2105                 return -1;
2106
2107         nbytes = sizeof(struct pmc_op_getpmcinfo) +
2108             npmc * sizeof(struct pmc_info);
2109
2110         if ((pmci = calloc(1, nbytes)) == NULL)
2111                 return -1;
2112
2113         pmci->pm_cpu  = cpu;
2114
2115         if (PMC_CALL(GETPMCINFO, pmci) < 0) {
2116                 free(pmci);
2117                 return -1;
2118         }
2119
2120         /* kernel<->library, library<->userland interfaces are identical */
2121         *ppmci = (struct pmc_pmcinfo *) pmci;
2122
2123         return 0;
2124 }
2125
2126 int
2127 pmc_read(pmc_id_t pmc, pmc_value_t *value)
2128 {
2129         struct pmc_op_pmcrw pmc_read_op;
2130
2131         pmc_read_op.pm_pmcid = pmc;
2132         pmc_read_op.pm_flags = PMC_F_OLDVALUE;
2133         pmc_read_op.pm_value = -1;
2134
2135         if (PMC_CALL(PMCRW, &pmc_read_op) < 0)
2136                 return -1;
2137
2138         *value = pmc_read_op.pm_value;
2139
2140         return 0;
2141 }
2142
2143 int
2144 pmc_release(pmc_id_t pmc)
2145 {
2146         struct pmc_op_simple    pmc_release_args;
2147
2148         pmc_release_args.pm_pmcid = pmc;
2149
2150         return PMC_CALL(PMCRELEASE, &pmc_release_args);
2151 }
2152
2153 int
2154 pmc_rw(pmc_id_t pmc, pmc_value_t newvalue, pmc_value_t *oldvaluep)
2155 {
2156         struct pmc_op_pmcrw pmc_rw_op;
2157
2158         pmc_rw_op.pm_pmcid = pmc;
2159         pmc_rw_op.pm_flags = PMC_F_NEWVALUE | PMC_F_OLDVALUE;
2160         pmc_rw_op.pm_value = newvalue;
2161
2162         if (PMC_CALL(PMCRW, &pmc_rw_op) < 0)
2163                 return -1;
2164
2165         *oldvaluep = pmc_rw_op.pm_value;
2166
2167         return 0;
2168 }
2169
2170 int
2171 pmc_set(pmc_id_t pmc, pmc_value_t value)
2172 {
2173         struct pmc_op_pmcsetcount sc;
2174
2175         sc.pm_pmcid = pmc;
2176         sc.pm_count = value;
2177
2178         if (PMC_CALL(PMCSETCOUNT, &sc) < 0)
2179                 return -1;
2180
2181         return 0;
2182
2183 }
2184
2185 int
2186 pmc_start(pmc_id_t pmc)
2187 {
2188         struct pmc_op_simple    pmc_start_args;
2189
2190         pmc_start_args.pm_pmcid = pmc;
2191         return PMC_CALL(PMCSTART, &pmc_start_args);
2192 }
2193
2194 int
2195 pmc_stop(pmc_id_t pmc)
2196 {
2197         struct pmc_op_simple    pmc_stop_args;
2198
2199         pmc_stop_args.pm_pmcid = pmc;
2200         return PMC_CALL(PMCSTOP, &pmc_stop_args);
2201 }
2202
2203 int
2204 pmc_width(pmc_id_t pmcid, uint32_t *width)
2205 {
2206         unsigned int i;
2207         enum pmc_class cl;
2208
2209         cl = PMC_ID_TO_CLASS(pmcid);
2210         for (i = 0; i < cpu_info.pm_nclass; i++)
2211                 if (cpu_info.pm_classes[i].pm_class == cl) {
2212                         *width = cpu_info.pm_classes[i].pm_width;
2213                         return 0;
2214                 }
2215         return EINVAL;
2216 }
2217
2218 int
2219 pmc_write(pmc_id_t pmc, pmc_value_t value)
2220 {
2221         struct pmc_op_pmcrw pmc_write_op;
2222
2223         pmc_write_op.pm_pmcid = pmc;
2224         pmc_write_op.pm_flags = PMC_F_NEWVALUE;
2225         pmc_write_op.pm_value = value;
2226
2227         return PMC_CALL(PMCRW, &pmc_write_op);
2228 }
2229
2230 int
2231 pmc_writelog(uint32_t userdata)
2232 {
2233         struct pmc_op_writelog wl;
2234
2235         wl.pm_userdata = userdata;
2236         return PMC_CALL(WRITELOG, &wl);
2237 }