Deleted Added
full compact
libpmc.c (183725) libpmc.c (185363)
1/*-
2 * Copyright (c) 2003-2008 Joseph Koshy
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

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>
1/*-
2 * Copyright (c) 2003-2008 Joseph Koshy
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/lib/libpmc/libpmc.c 183725 2008-10-09 14:55:45Z jkoshy $");
28__FBSDID("$FreeBSD: head/lib/libpmc/libpmc.c 185363 2008-11-27 09:00:47Z jkoshy $");
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
29
30#include <sys/types.h>
31#include <sys/module.h>
32#include <sys/pmc.h>
33#include <sys/syscall.h>
34
35#include <ctype.h>
36#include <errno.h>
37#include <fcntl.h>
38#include <pmc.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <strings.h>
43#include <unistd.h>
44
45#include "libpmcinternal.h"
46
45/* Function prototypes */
46#if defined(__i386__)
47static 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__)
47/* Function prototypes */
48#if defined(__i386__)
49static int k7_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
50 struct pmc_op_pmcallocate *_pmc_config);
51#endif
52#if defined(__amd64__) || defined(__i386__)
53static int iaf_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
54 struct pmc_op_pmcallocate *_pmc_config);
55static int iap_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
56 struct pmc_op_pmcallocate *_pmc_config);
51static int k8_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
52 struct pmc_op_pmcallocate *_pmc_config);
53static int p4_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
54 struct pmc_op_pmcallocate *_pmc_config);
55#endif
56#if defined(__i386__)
57static int p5_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
58 struct pmc_op_pmcallocate *_pmc_config);

--- 46 unchanged lines hidden (view full) ---

105
106#define PMC_TABLE_SIZE(N) (sizeof(N)/sizeof(N[0]))
107#define PMC_EVENT_TABLE_SIZE(N) PMC_TABLE_SIZE(N##_event_table)
108
109#undef __PMC_EV
110#define __PMC_EV(C,N) { #N, PMC_EV_ ## C ## _ ## N },
111
112/*
57static int k8_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
58 struct pmc_op_pmcallocate *_pmc_config);
59static int p4_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
60 struct pmc_op_pmcallocate *_pmc_config);
61#endif
62#if defined(__i386__)
63static int p5_allocate_pmc(enum pmc_event _pe, char *_ctrspec,
64 struct pmc_op_pmcallocate *_pmc_config);

--- 46 unchanged lines hidden (view full) ---

111
112#define PMC_TABLE_SIZE(N) (sizeof(N)/sizeof(N[0]))
113#define PMC_EVENT_TABLE_SIZE(N) PMC_TABLE_SIZE(N##_event_table)
114
115#undef __PMC_EV
116#define __PMC_EV(C,N) { #N, PMC_EV_ ## C ## _ ## N },
117
118/*
113 * PMC_MDEP_TABLE(NAME, CLASS, ADDITIONAL_CLASSES...)
119 * PMC_CLASSDEP_TABLE(NAME, CLASS)
114 *
120 *
115 * Build an event descriptor table and a list of valid PMC classes.
121 * Define a table mapping event names and aliases to HWPMC event IDs.
116 */
122 */
117#define PMC_MDEP_TABLE(N,C,...) \
123#define PMC_CLASSDEP_TABLE(N, C) \
118 static const struct pmc_event_descr N##_event_table[] = \
119 { \
120 __PMC_EV_##C() \
124 static const struct pmc_event_descr N##_event_table[] = \
125 { \
126 __PMC_EV_##C() \
121 }; \
127 }
128
129PMC_CLASSDEP_TABLE(iaf, IAF);
130PMC_CLASSDEP_TABLE(k7, K7);
131PMC_CLASSDEP_TABLE(k8, K8);
132PMC_CLASSDEP_TABLE(p4, P4);
133PMC_CLASSDEP_TABLE(p5, P5);
134PMC_CLASSDEP_TABLE(p6, P6);
135
136#undef __PMC_EV_ALIAS
137#define __PMC_EV_ALIAS(N,CODE) { N, PMC_EV_##CODE },
138
139static const struct pmc_event_descr atom_event_table[] =
140{
141 __PMC_EV_ALIAS_ATOM()
142};
143
144static const struct pmc_event_descr core_event_table[] =
145{
146 __PMC_EV_ALIAS_CORE()
147};
148
149
150static const struct pmc_event_descr core2_event_table[] =
151{
152 __PMC_EV_ALIAS_CORE2()
153};
154
155/*
156 * PMC_MDEP_TABLE(NAME, PRIMARYCLASS, ADDITIONAL_CLASSES...)
157 *
158 * Map a CPU to the PMC classes it supports.
159 */
160#define PMC_MDEP_TABLE(N,C,...) \
122 static const enum pmc_class N##_pmc_classes[] = { \
123 PMC_CLASS_##C, __VA_ARGS__ \
124 }
125
161 static const enum pmc_class N##_pmc_classes[] = { \
162 PMC_CLASS_##C, __VA_ARGS__ \
163 }
164
165PMC_MDEP_TABLE(atom, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC);
166PMC_MDEP_TABLE(core, IAP, PMC_CLASS_TSC);
167PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC);
126PMC_MDEP_TABLE(k7, K7, PMC_CLASS_TSC);
127PMC_MDEP_TABLE(k8, K8, PMC_CLASS_TSC);
128PMC_MDEP_TABLE(p4, P4, PMC_CLASS_TSC);
129PMC_MDEP_TABLE(p5, P5, PMC_CLASS_TSC);
130PMC_MDEP_TABLE(p6, P6, PMC_CLASS_TSC);
131
132static const struct pmc_event_descr tsc_event_table[] =
133{
134 __PMC_EV_TSC()
135};
136
137#undef PMC_CLASS_TABLE_DESC
168PMC_MDEP_TABLE(k7, K7, PMC_CLASS_TSC);
169PMC_MDEP_TABLE(k8, K8, PMC_CLASS_TSC);
170PMC_MDEP_TABLE(p4, P4, PMC_CLASS_TSC);
171PMC_MDEP_TABLE(p5, P5, PMC_CLASS_TSC);
172PMC_MDEP_TABLE(p6, P6, PMC_CLASS_TSC);
173
174static const struct pmc_event_descr tsc_event_table[] =
175{
176 __PMC_EV_TSC()
177};
178
179#undef PMC_CLASS_TABLE_DESC
138#define PMC_CLASS_TABLE_DESC(N, C) { \
139 .pm_evc_name = #N "-", \
140 .pm_evc_name_size = sizeof(#N "-") - 1, \
141 .pm_evc_class = PMC_CLASS_##C , \
142 .pm_evc_event_table = N##_event_table , \
180#define PMC_CLASS_TABLE_DESC(NAME, CLASS, EVENTS, ALLOCATOR) \
181static const struct pmc_class_descr NAME##_class_table_descr = \
182 { \
183 .pm_evc_name = #CLASS "-", \
184 .pm_evc_name_size = sizeof(#CLASS "-") - 1, \
185 .pm_evc_class = PMC_CLASS_##CLASS , \
186 .pm_evc_event_table = EVENTS##_event_table , \
143 .pm_evc_event_table_size = \
187 .pm_evc_event_table_size = \
144 PMC_EVENT_TABLE_SIZE(N), \
145 .pm_evc_allocate_pmc = N##_allocate_pmc \
188 PMC_EVENT_TABLE_SIZE(EVENTS), \
189 .pm_evc_allocate_pmc = ALLOCATOR##_allocate_pmc \
146 }
147
190 }
191
148static const struct pmc_class_descr pmc_class_table[] =
149{
192#if defined(__i386__) || defined(__amd64__)
193PMC_CLASS_TABLE_DESC(iaf, IAF, iaf, iaf);
194PMC_CLASS_TABLE_DESC(atom, IAP, atom, iap);
195PMC_CLASS_TABLE_DESC(core, IAP, core, iap);
196PMC_CLASS_TABLE_DESC(core2, IAP, core2, iap);
197#endif
150#if defined(__i386__)
198#if defined(__i386__)
151 PMC_CLASS_TABLE_DESC(k7, K7),
199PMC_CLASS_TABLE_DESC(k7, K7, k7, k7);
152#endif
153#if defined(__i386__) || defined(__amd64__)
200#endif
201#if defined(__i386__) || defined(__amd64__)
154 PMC_CLASS_TABLE_DESC(k8, K8),
155 PMC_CLASS_TABLE_DESC(p4, P4),
202PMC_CLASS_TABLE_DESC(k8, K8, k8, k8);
203PMC_CLASS_TABLE_DESC(p4, P4, p4, p4);
156#endif
157#if defined(__i386__)
204#endif
205#if defined(__i386__)
158 PMC_CLASS_TABLE_DESC(p5, P5),
159 PMC_CLASS_TABLE_DESC(p6, P6),
206PMC_CLASS_TABLE_DESC(p5, P5, p5, p5);
207PMC_CLASS_TABLE_DESC(p6, P6, p6, p6);
160#endif
161#if defined(__i386__) || defined(__amd64__)
208#endif
209#if defined(__i386__) || defined(__amd64__)
162 PMC_CLASS_TABLE_DESC(tsc, TSC)
210PMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc);
163#endif
211#endif
164};
165
212
166static size_t pmc_event_class_table_size =
167 PMC_TABLE_SIZE(pmc_class_table);
168
169#undef PMC_CLASS_TABLE_DESC
170
213#undef PMC_CLASS_TABLE_DESC
214
215static const struct pmc_class_descr **pmc_class_table;
216#define PMC_CLASS_TABLE_SIZE cpu_info.pm_nclass
217
171static const enum pmc_class *pmc_mdep_class_list;
172static size_t pmc_mdep_class_list_size;
173
174/*
175 * Mapping tables, mapping enumeration values to human readable
176 * strings.
177 */
178

--- 187 unchanged lines hidden (view full) ---

366
367}
368
369#endif
370
371#if defined(__amd64__) || defined(__i386__)
372
373/*
218static const enum pmc_class *pmc_mdep_class_list;
219static size_t pmc_mdep_class_list_size;
220
221/*
222 * Mapping tables, mapping enumeration values to human readable
223 * strings.
224 */
225

--- 187 unchanged lines hidden (view full) ---

413
414}
415
416#endif
417
418#if defined(__amd64__) || defined(__i386__)
419
420/*
421 * Intel Core (Family 6, Model E) PMCs.
422 */
423
424static struct pmc_event_alias core_aliases[] = {
425 EV_ALIAS("branches", "iap-br-instr-ret"),
426 EV_ALIAS("branch-mispredicts", "iap-br-mispred-ret"),
427 EV_ALIAS("cycles", "tsc-tsc"),
428 EV_ALIAS("ic-misses", "iap-icache-misses"),
429 EV_ALIAS("instructions", "iap-instr-ret"),
430 EV_ALIAS("interrupts", "iap-core-hw-int-rx"),
431 EV_ALIAS("unhalted-cycles", "iap-unhalted-core-cycles"),
432 EV_ALIAS(NULL, NULL)
433};
434
435/*
436 * Intel Core2 (Family 6, Model F), Core2Extreme (Family 6, Model 17H)
437 * and Atom (Family 6, model 1CH) PMCs.
438 */
439
440static struct pmc_event_alias core2_aliases[] = {
441 EV_ALIAS("branches", "iap-br-inst-retired.any"),
442 EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"),
443 EV_ALIAS("cycles", "tsc-tsc"),
444 EV_ALIAS("ic-misses", "iap-l1i-misses"),
445 EV_ALIAS("instructions", "iaf-instr-retired.any"),
446 EV_ALIAS("interrupts", "iap-hw-int-rcv"),
447 EV_ALIAS("unhalted-cycles", "iaf-cpu-clk-unhalted.core"),
448 EV_ALIAS(NULL, NULL)
449};
450#define atom_aliases core2_aliases
451
452#define IAF_KW_OS "os"
453#define IAF_KW_USR "usr"
454#define IAF_KW_ANYTHREAD "anythread"
455
456/*
457 * Parse an event specifier for Intel fixed function counters.
458 */
459static int
460iaf_allocate_pmc(enum pmc_event pe, char *ctrspec,
461 struct pmc_op_pmcallocate *pmc_config)
462{
463 char *p;
464
465 (void) pe;
466
467 pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
468 pmc_config->pm_md.pm_iaf.pm_iaf_flags = 0;
469
470 while ((p = strsep(&ctrspec, ",")) != NULL) {
471 if (KWMATCH(p, IAF_KW_OS))
472 pmc_config->pm_caps |= PMC_CAP_SYSTEM;
473 else if (KWMATCH(p, IAF_KW_USR))
474 pmc_config->pm_caps |= PMC_CAP_USER;
475 else if (KWMATCH(p, IAF_KW_ANYTHREAD))
476 pmc_config->pm_md.pm_iaf.pm_iaf_flags |= IAF_ANY;
477 else
478 return (-1);
479 }
480
481 return (0);
482}
483
484/*
485 * Core/Core2 support.
486 */
487
488#define IAP_KW_AGENT "agent"
489#define IAP_KW_ANYTHREAD "anythread"
490#define IAP_KW_CACHESTATE "cachestate"
491#define IAP_KW_CMASK "cmask"
492#define IAP_KW_CORE "core"
493#define IAP_KW_EDGE "edge"
494#define IAP_KW_INV "inv"
495#define IAP_KW_OS "os"
496#define IAP_KW_PREFETCH "prefetch"
497#define IAP_KW_SNOOPRESPONSE "snoopresponse"
498#define IAP_KW_SNOOPTYPE "snooptype"
499#define IAP_KW_TRANSITION "trans"
500#define IAP_KW_USR "usr"
501
502static struct pmc_masks iap_core_mask[] = {
503 PMCMASK(all, (0x3 << 14)),
504 PMCMASK(this, (0x1 << 14)),
505 NULLMASK
506};
507
508static struct pmc_masks iap_agent_mask[] = {
509 PMCMASK(this, 0),
510 PMCMASK(any, (0x1 << 13)),
511 NULLMASK
512};
513
514static struct pmc_masks iap_prefetch_mask[] = {
515 PMCMASK(both, (0x3 << 12)),
516 PMCMASK(only, (0x1 << 12)),
517 PMCMASK(exclude, 0),
518 NULLMASK
519};
520
521static struct pmc_masks iap_cachestate_mask[] = {
522 PMCMASK(i, (1 << 8)),
523 PMCMASK(s, (1 << 9)),
524 PMCMASK(e, (1 << 10)),
525 PMCMASK(m, (1 << 11)),
526 NULLMASK
527};
528
529static struct pmc_masks iap_snoopresponse_mask[] = {
530 PMCMASK(clean, (1 << 8)),
531 PMCMASK(hit, (1 << 9)),
532 PMCMASK(hitm, (1 << 11)),
533 NULLMASK
534};
535
536static struct pmc_masks iap_snooptype_mask[] = {
537 PMCMASK(cmp2s, (1 << 8)),
538 PMCMASK(cmp2i, (1 << 9)),
539 NULLMASK
540};
541
542static struct pmc_masks iap_transition_mask[] = {
543 PMCMASK(any, 0x00),
544 PMCMASK(frequency, 0x10),
545 NULLMASK
546};
547
548static int
549iap_allocate_pmc(enum pmc_event pe, char *ctrspec,
550 struct pmc_op_pmcallocate *pmc_config)
551{
552 char *e, *p, *q;
553 uint32_t cachestate, evmask;
554 int count, n;
555
556 pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE |
557 PMC_CAP_QUALIFIER);
558 pmc_config->pm_md.pm_iap.pm_iap_config = 0;
559
560 cachestate = evmask = 0;
561
562 /* Parse additional modifiers if present */
563 while ((p = strsep(&ctrspec, ",")) != NULL) {
564
565 n = 0;
566 if (KWPREFIXMATCH(p, IAP_KW_CMASK "=")) {
567 q = strchr(p, '=');
568 if (*++q == '\0') /* skip '=' */
569 return (-1);
570 count = strtol(q, &e, 0);
571 if (e == q || *e != '\0')
572 return (-1);
573 pmc_config->pm_caps |= PMC_CAP_THRESHOLD;
574 pmc_config->pm_md.pm_iap.pm_iap_config |=
575 IAP_CMASK(count);
576 } else if (KWMATCH(p, IAP_KW_EDGE)) {
577 pmc_config->pm_caps |= PMC_CAP_EDGE;
578 } else if (KWMATCH(p, IAP_KW_INV)) {
579 pmc_config->pm_caps |= PMC_CAP_INVERT;
580 } else if (KWMATCH(p, IAP_KW_OS)) {
581 pmc_config->pm_caps |= PMC_CAP_SYSTEM;
582 } else if (KWMATCH(p, IAP_KW_USR)) {
583 pmc_config->pm_caps |= PMC_CAP_USER;
584 } else if (KWMATCH(p, IAP_KW_ANYTHREAD)) {
585 pmc_config->pm_md.pm_iap.pm_iap_config |= IAP_ANY;
586 } else if (KWMATCH(p, IAP_KW_CORE)) {
587 n = pmc_parse_mask(iap_core_mask, p, &evmask);
588 if (n != 1)
589 return (-1);
590 } else if (KWMATCH(p, IAP_KW_AGENT)) {
591 n = pmc_parse_mask(iap_agent_mask, p, &evmask);
592 if (n != 1)
593 return (-1);
594 } else if (KWMATCH(p, IAP_KW_PREFETCH)) {
595 n = pmc_parse_mask(iap_prefetch_mask, p, &evmask);
596 if (n != 1)
597 return (-1);
598 } else if (KWMATCH(p, IAP_KW_CACHESTATE)) {
599 n = pmc_parse_mask(iap_cachestate_mask, p, &cachestate);
600 } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_CORE &&
601 KWMATCH(p, IAP_KW_TRANSITION)) {
602 n = pmc_parse_mask(iap_transition_mask, p, &evmask);
603 if (n != 1)
604 return (-1);
605 } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM ||
606 cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2) {
607 if (KWMATCH(p, IAP_KW_SNOOPRESPONSE)) {
608 n = pmc_parse_mask(iap_snoopresponse_mask, p,
609 &evmask);
610 } else if (KWMATCH(p, IAP_KW_SNOOPTYPE)) {
611 n = pmc_parse_mask(iap_snooptype_mask, p,
612 &evmask);
613 } else
614 return (-1);
615 } else
616 return (-1);
617
618 if (n < 0) /* Parsing failed. */
619 return (-1);
620 }
621
622 pmc_config->pm_md.pm_iap.pm_iap_config |= evmask;
623
624 /*
625 * If the event requires a 'cachestate' qualifier but was not
626 * specified by the user, use a sensible default.
627 */
628 switch (pe) {
629 case PMC_EV_IAP_EVENT_28H: /* Core, Core2, Atom */
630 case PMC_EV_IAP_EVENT_29H: /* Core, Core2, Atom */
631 case PMC_EV_IAP_EVENT_2AH: /* Core, Core2, Atom */
632 case PMC_EV_IAP_EVENT_2BH: /* Atom, Core2 */
633 case PMC_EV_IAP_EVENT_2EH: /* Core, Core2, Atom */
634 case PMC_EV_IAP_EVENT_30H: /* Core, Core2, Atom */
635 case PMC_EV_IAP_EVENT_32H: /* Core */
636 case PMC_EV_IAP_EVENT_40H: /* Core */
637 case PMC_EV_IAP_EVENT_41H: /* Core */
638 case PMC_EV_IAP_EVENT_42H: /* Core, Core2, Atom */
639 case PMC_EV_IAP_EVENT_77H: /* Core */
640 if (cachestate == 0)
641 cachestate = (0xF << 8);
642 default:
643 break;
644 }
645
646 pmc_config->pm_md.pm_iap.pm_iap_config |= cachestate;
647
648 return (0);
649}
650
651/*
374 * AMD K8 PMCs.
375 *
376 * These are very similar to AMD K7 PMCs, but support more kinds of
377 * events.
378 */
379
380static struct pmc_event_alias k8_aliases[] = {
381 EV_ALIAS("branches", "k8-fr-retired-taken-branches"),

--- 1317 unchanged lines hidden (view full) ---

1699 pmc_config->pm_caps |= PMC_CAP_READ;
1700
1701 return (0);
1702}
1703#endif
1704
1705/*
1706 * Match an event name `name' with its canonical form.
652 * AMD K8 PMCs.
653 *
654 * These are very similar to AMD K7 PMCs, but support more kinds of
655 * events.
656 */
657
658static struct pmc_event_alias k8_aliases[] = {
659 EV_ALIAS("branches", "k8-fr-retired-taken-branches"),

--- 1317 unchanged lines hidden (view full) ---

1977 pmc_config->pm_caps |= PMC_CAP_READ;
1978
1979 return (0);
1980}
1981#endif
1982
1983/*
1984 * Match an event name `name' with its canonical form.
1707 *
1708 * Matches are case insensitive and spaces, underscores and hyphen
1709 * characters are considered to match each other.
1710 *
1985 *
1986 * Matches are case insensitive and spaces, periods, underscores and
1987 * hyphen characters are considered to match each other.
1988 *
1711 * Returns 1 for a match, 0 otherwise.
1712 */
1713
1714static int
1715pmc_match_event_name(const char *name, const char *canonicalname)
1716{
1717 int cc, nc;
1718 const unsigned char *c, *n;
1719
1720 c = (const unsigned char *) canonicalname;
1721 n = (const unsigned char *) name;
1722
1723 for (; (nc = *n) && (cc = *c); n++, c++) {
1724
1989 * Returns 1 for a match, 0 otherwise.
1990 */
1991
1992static int
1993pmc_match_event_name(const char *name, const char *canonicalname)
1994{
1995 int cc, nc;
1996 const unsigned char *c, *n;
1997
1998 c = (const unsigned char *) canonicalname;
1999 n = (const unsigned char *) name;
2000
2001 for (; (nc = *n) && (cc = *c); n++, c++) {
2002
1725 if (toupper(nc) == cc)
2003 if ((nc == ' ' || nc == '_' || nc == '-' || nc == '.') &&
2004 (cc == ' ' || cc == '_' || cc == '-' || cc == '.'))
1726 continue;
1727
2005 continue;
2006
1728 if ((nc == ' ' || nc == '_' || nc == '-') &&
1729 (cc == ' ' || cc == '_' || cc == '-'))
2007 if (toupper(nc) == toupper(cc))
1730 continue;
1731
2008 continue;
2009
2010
1732 return (0);
1733 }
1734
1735 if (*n == '\0' && *c == '\0')
1736 return (1);
1737
1738 return (0);
1739}

--- 5 unchanged lines hidden (view full) ---

1745 * Returns an event descriptor pointer on match or NULL otherwise.
1746 */
1747static const struct pmc_event_descr *
1748pmc_match_event_class(const char *name,
1749 const struct pmc_class_descr *pcd)
1750{
1751 size_t n;
1752 const struct pmc_event_descr *ev;
2011 return (0);
2012 }
2013
2014 if (*n == '\0' && *c == '\0')
2015 return (1);
2016
2017 return (0);
2018}

--- 5 unchanged lines hidden (view full) ---

2024 * Returns an event descriptor pointer on match or NULL otherwise.
2025 */
2026static const struct pmc_event_descr *
2027pmc_match_event_class(const char *name,
2028 const struct pmc_class_descr *pcd)
2029{
2030 size_t n;
2031 const struct pmc_event_descr *ev;
1753
2032
1754 ev = pcd->pm_evc_event_table;
1755 for (n = 0; n < pcd->pm_evc_event_table_size; n++, ev++)
1756 if (pmc_match_event_name(name, ev->pm_ev_name))
1757 return (ev);
1758
1759 return (NULL);
1760}
1761

--- 48 unchanged lines hidden (view full) ---

1810 r = spec_copy;
1811 ctrname = strsep(&r, ",");
1812
1813 /*
1814 * If a explicit class prefix was given by the user, restrict the
1815 * search for the event to the specified PMC class.
1816 */
1817 ev = NULL;
2033 ev = pcd->pm_evc_event_table;
2034 for (n = 0; n < pcd->pm_evc_event_table_size; n++, ev++)
2035 if (pmc_match_event_name(name, ev->pm_ev_name))
2036 return (ev);
2037
2038 return (NULL);
2039}
2040

--- 48 unchanged lines hidden (view full) ---

2089 r = spec_copy;
2090 ctrname = strsep(&r, ",");
2091
2092 /*
2093 * If a explicit class prefix was given by the user, restrict the
2094 * search for the event to the specified PMC class.
2095 */
2096 ev = NULL;
1818 for (n = 0; n < pmc_event_class_table_size; n++) {
1819 pcd = &pmc_class_table[n];
2097 for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) {
2098 pcd = pmc_class_table[n];
1820 if (pmc_mdep_is_compatible_class(pcd->pm_evc_class) &&
1821 strncasecmp(ctrname, pcd->pm_evc_name,
1822 pcd->pm_evc_name_size) == 0) {
1823 if ((ev = pmc_match_event_class(ctrname +
1824 pcd->pm_evc_name_size, pcd)) == NULL) {
1825 errno = EINVAL;
1826 goto out;
1827 }
1828 break;
1829 }
1830 }
1831
1832 /*
1833 * Otherwise, search for this event in all compatible PMC
1834 * classes.
1835 */
2099 if (pmc_mdep_is_compatible_class(pcd->pm_evc_class) &&
2100 strncasecmp(ctrname, pcd->pm_evc_name,
2101 pcd->pm_evc_name_size) == 0) {
2102 if ((ev = pmc_match_event_class(ctrname +
2103 pcd->pm_evc_name_size, pcd)) == NULL) {
2104 errno = EINVAL;
2105 goto out;
2106 }
2107 break;
2108 }
2109 }
2110
2111 /*
2112 * Otherwise, search for this event in all compatible PMC
2113 * classes.
2114 */
1836 for (n = 0; ev == NULL && n < pmc_event_class_table_size; n++) {
1837 pcd = &pmc_class_table[n];
2115 for (n = 0; ev == NULL && n < PMC_CLASS_TABLE_SIZE; n++) {
2116 pcd = pmc_class_table[n];
1838 if (pmc_mdep_is_compatible_class(pcd->pm_evc_class))
1839 ev = pmc_match_event_class(ctrname, pcd);
1840 }
1841
1842 if (ev == NULL) {
1843 errno = EINVAL;
1844 goto out;
1845 }

--- 123 unchanged lines hidden (view full) ---

1969 int *nevents)
1970{
1971 int count;
1972 const char **names;
1973 const struct pmc_event_descr *ev;
1974
1975 switch (cl)
1976 {
2117 if (pmc_mdep_is_compatible_class(pcd->pm_evc_class))
2118 ev = pmc_match_event_class(ctrname, pcd);
2119 }
2120
2121 if (ev == NULL) {
2122 errno = EINVAL;
2123 goto out;
2124 }

--- 123 unchanged lines hidden (view full) ---

2248 int *nevents)
2249{
2250 int count;
2251 const char **names;
2252 const struct pmc_event_descr *ev;
2253
2254 switch (cl)
2255 {
2256 case PMC_CLASS_IAF:
2257 ev = iaf_event_table;
2258 count = PMC_EVENT_TABLE_SIZE(iaf);
2259 break;
2260 case PMC_CLASS_IAP:
2261 /*
2262 * Return the most appropriate set of event name
2263 * spellings for the current CPU.
2264 */
2265 switch (cpu_info.pm_cputype) {
2266 default:
2267 case PMC_CPU_INTEL_ATOM:
2268 ev = atom_event_table;
2269 count = PMC_EVENT_TABLE_SIZE(atom);
2270 break;
2271 case PMC_CPU_INTEL_CORE:
2272 ev = core_event_table;
2273 count = PMC_EVENT_TABLE_SIZE(core);
2274 break;
2275 case PMC_CPU_INTEL_CORE2:
2276 ev = core2_event_table;
2277 count = PMC_EVENT_TABLE_SIZE(core2);
2278 break;
2279 }
2280 break;
1977 case PMC_CLASS_TSC:
1978 ev = tsc_event_table;
1979 count = PMC_EVENT_TABLE_SIZE(tsc);
1980 break;
1981 case PMC_CLASS_K7:
1982 ev = k7_event_table;
1983 count = PMC_EVENT_TABLE_SIZE(k7);
1984 break;

--- 105 unchanged lines hidden (view full) ---

2090
2091 cpu_info.pm_cputype = op_cpu_info.pm_cputype;
2092 cpu_info.pm_ncpu = op_cpu_info.pm_ncpu;
2093 cpu_info.pm_npmc = op_cpu_info.pm_npmc;
2094 cpu_info.pm_nclass = op_cpu_info.pm_nclass;
2095 for (n = 0; n < cpu_info.pm_nclass; n++)
2096 cpu_info.pm_classes[n] = op_cpu_info.pm_classes[n];
2097
2281 case PMC_CLASS_TSC:
2282 ev = tsc_event_table;
2283 count = PMC_EVENT_TABLE_SIZE(tsc);
2284 break;
2285 case PMC_CLASS_K7:
2286 ev = k7_event_table;
2287 count = PMC_EVENT_TABLE_SIZE(k7);
2288 break;

--- 105 unchanged lines hidden (view full) ---

2394
2395 cpu_info.pm_cputype = op_cpu_info.pm_cputype;
2396 cpu_info.pm_ncpu = op_cpu_info.pm_ncpu;
2397 cpu_info.pm_npmc = op_cpu_info.pm_npmc;
2398 cpu_info.pm_nclass = op_cpu_info.pm_nclass;
2399 for (n = 0; n < cpu_info.pm_nclass; n++)
2400 cpu_info.pm_classes[n] = op_cpu_info.pm_classes[n];
2401
2402 pmc_class_table = malloc(PMC_CLASS_TABLE_SIZE *
2403 sizeof(struct pmc_class_descr *));
2404
2405 if (pmc_class_table == NULL)
2406 return (-1);
2407
2408
2409 /*
2410 * Fill in the class table.
2411 */
2412 n = 0;
2413#if defined(__amd64__) || defined(__i386__)
2414 pmc_class_table[n++] = &tsc_class_table_descr;
2415#endif
2416
2098#define PMC_MDEP_INIT(C) do { \
2099 pmc_mdep_event_aliases = C##_aliases; \
2100 pmc_mdep_class_list = C##_pmc_classes; \
2101 pmc_mdep_class_list_size = \
2102 PMC_TABLE_SIZE(C##_pmc_classes); \
2103 } while (0)
2104
2105 /* Configure the event name parser. */
2106 switch (cpu_info.pm_cputype) {
2107#if defined(__i386__)
2108 case PMC_CPU_AMD_K7:
2109 PMC_MDEP_INIT(k7);
2417#define PMC_MDEP_INIT(C) do { \
2418 pmc_mdep_event_aliases = C##_aliases; \
2419 pmc_mdep_class_list = C##_pmc_classes; \
2420 pmc_mdep_class_list_size = \
2421 PMC_TABLE_SIZE(C##_pmc_classes); \
2422 } while (0)
2423
2424 /* Configure the event name parser. */
2425 switch (cpu_info.pm_cputype) {
2426#if defined(__i386__)
2427 case PMC_CPU_AMD_K7:
2428 PMC_MDEP_INIT(k7);
2429 pmc_class_table[n] = &k7_class_table_descr;
2110 break;
2111 case PMC_CPU_INTEL_P5:
2112 PMC_MDEP_INIT(p5);
2430 break;
2431 case PMC_CPU_INTEL_P5:
2432 PMC_MDEP_INIT(p5);
2433 pmc_class_table[n] = &p5_class_table_descr;
2113 break;
2114 case PMC_CPU_INTEL_P6: /* P6 ... Pentium M CPUs have */
2115 case PMC_CPU_INTEL_PII: /* similar PMCs. */
2116 case PMC_CPU_INTEL_PIII:
2117 case PMC_CPU_INTEL_PM:
2118 PMC_MDEP_INIT(p6);
2434 break;
2435 case PMC_CPU_INTEL_P6: /* P6 ... Pentium M CPUs have */
2436 case PMC_CPU_INTEL_PII: /* similar PMCs. */
2437 case PMC_CPU_INTEL_PIII:
2438 case PMC_CPU_INTEL_PM:
2439 PMC_MDEP_INIT(p6);
2440 pmc_class_table[n] = &p6_class_table_descr;
2119 break;
2120#endif
2121#if defined(__amd64__) || defined(__i386__)
2122 case PMC_CPU_AMD_K8:
2123 PMC_MDEP_INIT(k8);
2441 break;
2442#endif
2443#if defined(__amd64__) || defined(__i386__)
2444 case PMC_CPU_AMD_K8:
2445 PMC_MDEP_INIT(k8);
2446 pmc_class_table[n] = &k8_class_table_descr;
2124 break;
2447 break;
2448 case PMC_CPU_INTEL_ATOM:
2449 PMC_MDEP_INIT(atom);
2450 pmc_class_table[n++] = &iaf_class_table_descr;
2451 pmc_class_table[n] = &atom_class_table_descr;
2452 break;
2453 case PMC_CPU_INTEL_CORE:
2454 PMC_MDEP_INIT(core);
2455 pmc_class_table[n] = &core_class_table_descr;
2456 break;
2457 case PMC_CPU_INTEL_CORE2:
2458 PMC_MDEP_INIT(core2);
2459 pmc_class_table[n++] = &iaf_class_table_descr;
2460 pmc_class_table[n] = &core2_class_table_descr;
2461 break;
2125 case PMC_CPU_INTEL_PIV:
2126 PMC_MDEP_INIT(p4);
2462 case PMC_CPU_INTEL_PIV:
2463 PMC_MDEP_INIT(p4);
2464 pmc_class_table[n] = &p4_class_table_descr;
2127 break;
2128#endif
2129
2465 break;
2466#endif
2467
2468
2130 default:
2131 /*
2132 * Some kind of CPU this version of the library knows nothing
2133 * about. This shouldn't happen since the abi version check
2134 * should have caught this.
2135 */
2136 errno = ENXIO;
2137 return (pmc_syscall = -1);

--- 52 unchanged lines hidden (view full) ---

2190 pd <= PMC_DISP_LAST)
2191 return (pmc_disposition_names[pd]);
2192
2193 errno = EINVAL;
2194 return (NULL);
2195}
2196
2197const char *
2469 default:
2470 /*
2471 * Some kind of CPU this version of the library knows nothing
2472 * about. This shouldn't happen since the abi version check
2473 * should have caught this.
2474 */
2475 errno = ENXIO;
2476 return (pmc_syscall = -1);

--- 52 unchanged lines hidden (view full) ---

2529 pd <= PMC_DISP_LAST)
2530 return (pmc_disposition_names[pd]);
2531
2532 errno = EINVAL;
2533 return (NULL);
2534}
2535
2536const char *
2198pmc_name_of_event(enum pmc_event pe)
2537_pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu)
2199{
2200 const struct pmc_event_descr *ev, *evfence;
2201
2202 ev = evfence = NULL;
2538{
2539 const struct pmc_event_descr *ev, *evfence;
2540
2541 ev = evfence = NULL;
2203 if (pe >= PMC_EV_K7_FIRST && pe <= PMC_EV_K7_LAST) {
2542 if (pe >= PMC_EV_IAF_FIRST && pe <= PMC_EV_IAF_LAST) {
2543 ev = iaf_event_table;
2544 evfence = iaf_event_table + PMC_EVENT_TABLE_SIZE(iaf);
2545 } else if (pe >= PMC_EV_IAP_FIRST && pe <= PMC_EV_IAP_LAST) {
2546 switch (cpu) {
2547 case PMC_CPU_INTEL_ATOM:
2548 ev = atom_event_table;
2549 evfence = atom_event_table + PMC_EVENT_TABLE_SIZE(atom);
2550 break;
2551 case PMC_CPU_INTEL_CORE:
2552 ev = core_event_table;
2553 evfence = core_event_table + PMC_EVENT_TABLE_SIZE(core);
2554 break;
2555 case PMC_CPU_INTEL_CORE2:
2556 ev = core2_event_table;
2557 evfence = core2_event_table + PMC_EVENT_TABLE_SIZE(core2);
2558 break;
2559 default: /* Unknown CPU type. */
2560 break;
2561 }
2562 } if (pe >= PMC_EV_K7_FIRST && pe <= PMC_EV_K7_LAST) {
2204 ev = k7_event_table;
2205 evfence = k7_event_table + PMC_EVENT_TABLE_SIZE(k7);
2206 } else if (pe >= PMC_EV_K8_FIRST && pe <= PMC_EV_K8_LAST) {
2207 ev = k8_event_table;
2208 evfence = k8_event_table + PMC_EVENT_TABLE_SIZE(k8);
2209 } else if (pe >= PMC_EV_P4_FIRST && pe <= PMC_EV_P4_LAST) {
2210 ev = p4_event_table;
2211 evfence = p4_event_table + PMC_EVENT_TABLE_SIZE(p4);

--- 7 unchanged lines hidden (view full) ---

2219 ev = tsc_event_table;
2220 evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc);
2221 }
2222
2223 for (; ev != evfence; ev++)
2224 if (pe == ev->pm_ev_code)
2225 return (ev->pm_ev_name);
2226
2563 ev = k7_event_table;
2564 evfence = k7_event_table + PMC_EVENT_TABLE_SIZE(k7);
2565 } else if (pe >= PMC_EV_K8_FIRST && pe <= PMC_EV_K8_LAST) {
2566 ev = k8_event_table;
2567 evfence = k8_event_table + PMC_EVENT_TABLE_SIZE(k8);
2568 } else if (pe >= PMC_EV_P4_FIRST && pe <= PMC_EV_P4_LAST) {
2569 ev = p4_event_table;
2570 evfence = p4_event_table + PMC_EVENT_TABLE_SIZE(p4);

--- 7 unchanged lines hidden (view full) ---

2578 ev = tsc_event_table;
2579 evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc);
2580 }
2581
2582 for (; ev != evfence; ev++)
2583 if (pe == ev->pm_ev_code)
2584 return (ev->pm_ev_name);
2585
2586 return (NULL);
2587}
2588
2589const char *
2590pmc_name_of_event(enum pmc_event pe)
2591{
2592 const char *n;
2593
2594 if ((n = _pmc_name_of_event(pe, cpu_info.pm_cputype)) != NULL)
2595 return (n);
2596
2227 errno = EINVAL;
2228 return (NULL);
2229}
2230
2231const char *
2232pmc_name_of_mode(enum pmc_mode pm)
2233{
2234 if ((int) pm >= PMC_MODE_FIRST &&

--- 179 unchanged lines hidden ---
2597 errno = EINVAL;
2598 return (NULL);
2599}
2600
2601const char *
2602pmc_name_of_mode(enum pmc_mode pm)
2603{
2604 if ((int) pm >= PMC_MODE_FIRST &&

--- 179 unchanged lines hidden ---