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 --- |