libpmc.c revision 198433
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 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: head/lib/libpmc/libpmc.c 198433 2009-10-24 04:11:40Z 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 45#include "libpmcinternal.h" 46 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); 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); 65static int p6_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 66 struct pmc_op_pmcallocate *_pmc_config); 67#endif 68#if defined(__amd64__) || defined(__i386__) 69static int tsc_allocate_pmc(enum pmc_event _pe, char *_ctrspec, 70 struct pmc_op_pmcallocate *_pmc_config); 71#endif 72 73#define PMC_CALL(cmd, params) \ 74 syscall(pmc_syscall, PMC_OP_##cmd, (params)) 75 76/* 77 * Event aliases provide a way for the user to ask for generic events 78 * like "cache-misses", or "instructions-retired". These aliases are 79 * mapped to the appropriate canonical event descriptions using a 80 * lookup table. 81 */ 82struct pmc_event_alias { 83 const char *pm_alias; 84 const char *pm_spec; 85}; 86 87static const struct pmc_event_alias *pmc_mdep_event_aliases; 88 89/* 90 * The pmc_event_descr structure maps symbolic names known to the user 91 * to integer codes used by the PMC KLD. 92 */ 93struct pmc_event_descr { 94 const char *pm_ev_name; 95 enum pmc_event pm_ev_code; 96}; 97 98/* 99 * The pmc_class_descr structure maps class name prefixes for 100 * event names to event tables and other PMC class data. 101 */ 102struct pmc_class_descr { 103 const char *pm_evc_name; 104 size_t pm_evc_name_size; 105 enum pmc_class pm_evc_class; 106 const struct pmc_event_descr *pm_evc_event_table; 107 size_t pm_evc_event_table_size; 108 int (*pm_evc_allocate_pmc)(enum pmc_event _pe, 109 char *_ctrspec, struct pmc_op_pmcallocate *_pa); 110}; 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/* 119 * PMC_CLASSDEP_TABLE(NAME, CLASS) 120 * 121 * Define a table mapping event names and aliases to HWPMC event IDs. 122 */ 123#define PMC_CLASSDEP_TABLE(N, C) \ 124 static const struct pmc_event_descr N##_event_table[] = \ 125 { \ 126 __PMC_EV_##C() \ 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 155static const struct pmc_event_descr corei7_event_table[] = 156{ 157 __PMC_EV_ALIAS_COREI7() 158}; 159 160/* 161 * PMC_MDEP_TABLE(NAME, PRIMARYCLASS, ADDITIONAL_CLASSES...) 162 * 163 * Map a CPU to the PMC classes it supports. 164 */ 165#define PMC_MDEP_TABLE(N,C,...) \ 166 static const enum pmc_class N##_pmc_classes[] = { \ 167 PMC_CLASS_##C, __VA_ARGS__ \ 168 } 169 170PMC_MDEP_TABLE(atom, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC); 171PMC_MDEP_TABLE(core, IAP, PMC_CLASS_TSC); 172PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC); 173PMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC); 174PMC_MDEP_TABLE(k7, K7, PMC_CLASS_TSC); 175PMC_MDEP_TABLE(k8, K8, PMC_CLASS_TSC); 176PMC_MDEP_TABLE(p4, P4, PMC_CLASS_TSC); 177PMC_MDEP_TABLE(p5, P5, PMC_CLASS_TSC); 178PMC_MDEP_TABLE(p6, P6, PMC_CLASS_TSC); 179 180static const struct pmc_event_descr tsc_event_table[] = 181{ 182 __PMC_EV_TSC() 183}; 184 185#undef PMC_CLASS_TABLE_DESC 186#define PMC_CLASS_TABLE_DESC(NAME, CLASS, EVENTS, ALLOCATOR) \ 187static const struct pmc_class_descr NAME##_class_table_descr = \ 188 { \ 189 .pm_evc_name = #CLASS "-", \ 190 .pm_evc_name_size = sizeof(#CLASS "-") - 1, \ 191 .pm_evc_class = PMC_CLASS_##CLASS , \ 192 .pm_evc_event_table = EVENTS##_event_table , \ 193 .pm_evc_event_table_size = \ 194 PMC_EVENT_TABLE_SIZE(EVENTS), \ 195 .pm_evc_allocate_pmc = ALLOCATOR##_allocate_pmc \ 196 } 197 198#if defined(__i386__) || defined(__amd64__) 199PMC_CLASS_TABLE_DESC(iaf, IAF, iaf, iaf); 200PMC_CLASS_TABLE_DESC(atom, IAP, atom, iap); 201PMC_CLASS_TABLE_DESC(core, IAP, core, iap); 202PMC_CLASS_TABLE_DESC(core2, IAP, core2, iap); 203PMC_CLASS_TABLE_DESC(corei7, IAP, corei7, iap); 204#endif 205#if defined(__i386__) 206PMC_CLASS_TABLE_DESC(k7, K7, k7, k7); 207#endif 208#if defined(__i386__) || defined(__amd64__) 209PMC_CLASS_TABLE_DESC(k8, K8, k8, k8); 210PMC_CLASS_TABLE_DESC(p4, P4, p4, p4); 211#endif 212#if defined(__i386__) 213PMC_CLASS_TABLE_DESC(p5, P5, p5, p5); 214PMC_CLASS_TABLE_DESC(p6, P6, p6, p6); 215#endif 216#if defined(__i386__) || defined(__amd64__) 217PMC_CLASS_TABLE_DESC(tsc, TSC, tsc, tsc); 218#endif 219 220#undef PMC_CLASS_TABLE_DESC 221 222static const struct pmc_class_descr **pmc_class_table; 223#define PMC_CLASS_TABLE_SIZE cpu_info.pm_nclass 224 225static const enum pmc_class *pmc_mdep_class_list; 226static size_t pmc_mdep_class_list_size; 227 228/* 229 * Mapping tables, mapping enumeration values to human readable 230 * strings. 231 */ 232 233static const char * pmc_capability_names[] = { 234#undef __PMC_CAP 235#define __PMC_CAP(N,V,D) #N , 236 __PMC_CAPS() 237}; 238 239static const char * pmc_class_names[] = { 240#undef __PMC_CLASS 241#define __PMC_CLASS(C) #C , 242 __PMC_CLASSES() 243}; 244 245struct pmc_cputype_map { 246 enum pmc_class pm_cputype; 247 const char *pm_name; 248}; 249 250static const struct pmc_cputype_map pmc_cputype_names[] = { 251#undef __PMC_CPU 252#define __PMC_CPU(S, V, D) { .pm_cputype = PMC_CPU_##S, .pm_name = #S } , 253 __PMC_CPUS() 254}; 255 256static const char * pmc_disposition_names[] = { 257#undef __PMC_DISP 258#define __PMC_DISP(D) #D , 259 __PMC_DISPOSITIONS() 260}; 261 262static const char * pmc_mode_names[] = { 263#undef __PMC_MODE 264#define __PMC_MODE(M,N) #M , 265 __PMC_MODES() 266}; 267 268static const char * pmc_state_names[] = { 269#undef __PMC_STATE 270#define __PMC_STATE(S) #S , 271 __PMC_STATES() 272}; 273 274static int pmc_syscall = -1; /* filled in by pmc_init() */ 275 276static struct pmc_cpuinfo cpu_info; /* filled in by pmc_init() */ 277 278/* Event masks for events */ 279struct pmc_masks { 280 const char *pm_name; 281 const uint32_t pm_value; 282}; 283#define PMCMASK(N,V) { .pm_name = #N, .pm_value = (V) } 284#define NULLMASK PMCMASK(NULL,0) 285 286#if defined(__amd64__) || defined(__i386__) 287static int 288pmc_parse_mask(const struct pmc_masks *pmask, char *p, uint32_t *evmask) 289{ 290 const struct pmc_masks *pm; 291 char *q, *r; 292 int c; 293 294 if (pmask == NULL) /* no mask keywords */ 295 return (-1); 296 q = strchr(p, '='); /* skip '=' */ 297 if (*++q == '\0') /* no more data */ 298 return (-1); 299 c = 0; /* count of mask keywords seen */ 300 while ((r = strsep(&q, "+")) != NULL) { 301 for (pm = pmask; pm->pm_name && strcasecmp(r, pm->pm_name); 302 pm++) 303 ; 304 if (pm->pm_name == NULL) /* not found */ 305 return (-1); 306 *evmask |= pm->pm_value; 307 c++; 308 } 309 return (c); 310} 311#endif 312 313#define KWMATCH(p,kw) (strcasecmp((p), (kw)) == 0) 314#define KWPREFIXMATCH(p,kw) (strncasecmp((p), (kw), sizeof((kw)) - 1) == 0) 315#define EV_ALIAS(N,S) { .pm_alias = N, .pm_spec = S } 316 317#if defined(__i386__) 318 319/* 320 * AMD K7 (Athlon) CPUs. 321 */ 322 323static struct pmc_event_alias k7_aliases[] = { 324 EV_ALIAS("branches", "k7-retired-branches"), 325 EV_ALIAS("branch-mispredicts", "k7-retired-branches-mispredicted"), 326 EV_ALIAS("cycles", "tsc"), 327 EV_ALIAS("dc-misses", "k7-dc-misses"), 328 EV_ALIAS("ic-misses", "k7-ic-misses"), 329 EV_ALIAS("instructions", "k7-retired-instructions"), 330 EV_ALIAS("interrupts", "k7-hardware-interrupts"), 331 EV_ALIAS(NULL, NULL) 332}; 333 334#define K7_KW_COUNT "count" 335#define K7_KW_EDGE "edge" 336#define K7_KW_INV "inv" 337#define K7_KW_OS "os" 338#define K7_KW_UNITMASK "unitmask" 339#define K7_KW_USR "usr" 340 341static int 342k7_allocate_pmc(enum pmc_event pe, char *ctrspec, 343 struct pmc_op_pmcallocate *pmc_config) 344{ 345 char *e, *p, *q; 346 int c, has_unitmask; 347 uint32_t count, unitmask; 348 349 pmc_config->pm_md.pm_amd.pm_amd_config = 0; 350 pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 351 352 if (pe == PMC_EV_K7_DC_REFILLS_FROM_L2 || 353 pe == PMC_EV_K7_DC_REFILLS_FROM_SYSTEM || 354 pe == PMC_EV_K7_DC_WRITEBACKS) { 355 has_unitmask = 1; 356 unitmask = AMD_PMC_UNITMASK_MOESI; 357 } else 358 unitmask = has_unitmask = 0; 359 360 while ((p = strsep(&ctrspec, ",")) != NULL) { 361 if (KWPREFIXMATCH(p, K7_KW_COUNT "=")) { 362 q = strchr(p, '='); 363 if (*++q == '\0') /* skip '=' */ 364 return (-1); 365 366 count = strtol(q, &e, 0); 367 if (e == q || *e != '\0') 368 return (-1); 369 370 pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 371 pmc_config->pm_md.pm_amd.pm_amd_config |= 372 AMD_PMC_TO_COUNTER(count); 373 374 } else if (KWMATCH(p, K7_KW_EDGE)) { 375 pmc_config->pm_caps |= PMC_CAP_EDGE; 376 } else if (KWMATCH(p, K7_KW_INV)) { 377 pmc_config->pm_caps |= PMC_CAP_INVERT; 378 } else if (KWMATCH(p, K7_KW_OS)) { 379 pmc_config->pm_caps |= PMC_CAP_SYSTEM; 380 } else if (KWPREFIXMATCH(p, K7_KW_UNITMASK "=")) { 381 if (has_unitmask == 0) 382 return (-1); 383 unitmask = 0; 384 q = strchr(p, '='); 385 if (*++q == '\0') /* skip '=' */ 386 return (-1); 387 388 while ((c = tolower(*q++)) != 0) 389 if (c == 'm') 390 unitmask |= AMD_PMC_UNITMASK_M; 391 else if (c == 'o') 392 unitmask |= AMD_PMC_UNITMASK_O; 393 else if (c == 'e') 394 unitmask |= AMD_PMC_UNITMASK_E; 395 else if (c == 's') 396 unitmask |= AMD_PMC_UNITMASK_S; 397 else if (c == 'i') 398 unitmask |= AMD_PMC_UNITMASK_I; 399 else if (c == '+') 400 continue; 401 else 402 return (-1); 403 404 if (unitmask == 0) 405 return (-1); 406 407 } else if (KWMATCH(p, K7_KW_USR)) { 408 pmc_config->pm_caps |= PMC_CAP_USER; 409 } else 410 return (-1); 411 } 412 413 if (has_unitmask) { 414 pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 415 pmc_config->pm_md.pm_amd.pm_amd_config |= 416 AMD_PMC_TO_UNITMASK(unitmask); 417 } 418 419 return (0); 420 421} 422 423#endif 424 425#if defined(__amd64__) || defined(__i386__) 426 427/* 428 * Intel Core (Family 6, Model E) PMCs. 429 */ 430 431static struct pmc_event_alias core_aliases[] = { 432 EV_ALIAS("branches", "iap-br-instr-ret"), 433 EV_ALIAS("branch-mispredicts", "iap-br-mispred-ret"), 434 EV_ALIAS("cycles", "tsc-tsc"), 435 EV_ALIAS("ic-misses", "iap-icache-misses"), 436 EV_ALIAS("instructions", "iap-instr-ret"), 437 EV_ALIAS("interrupts", "iap-core-hw-int-rx"), 438 EV_ALIAS("unhalted-cycles", "iap-unhalted-core-cycles"), 439 EV_ALIAS(NULL, NULL) 440}; 441 442/* 443 * Intel Core2 (Family 6, Model F), Core2Extreme (Family 6, Model 17H) 444 * and Atom (Family 6, model 1CH) PMCs. 445 * 446 * We map aliases to events on the fixed-function counters if these 447 * are present. Note that not all CPUs in this family contain fixed-function 448 * counters. 449 */ 450 451static struct pmc_event_alias core2_aliases[] = { 452 EV_ALIAS("branches", "iap-br-inst-retired.any"), 453 EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 454 EV_ALIAS("cycles", "tsc-tsc"), 455 EV_ALIAS("ic-misses", "iap-l1i-misses"), 456 EV_ALIAS("instructions", "iaf-instr-retired.any"), 457 EV_ALIAS("interrupts", "iap-hw-int-rcv"), 458 EV_ALIAS("unhalted-cycles", "iaf-cpu-clk-unhalted.core"), 459 EV_ALIAS(NULL, NULL) 460}; 461 462static struct pmc_event_alias core2_aliases_without_iaf[] = { 463 EV_ALIAS("branches", "iap-br-inst-retired.any"), 464 EV_ALIAS("branch-mispredicts", "iap-br-inst-retired.mispred"), 465 EV_ALIAS("cycles", "tsc-tsc"), 466 EV_ALIAS("ic-misses", "iap-l1i-misses"), 467 EV_ALIAS("instructions", "iap-inst-retired.any_p"), 468 EV_ALIAS("interrupts", "iap-hw-int-rcv"), 469 EV_ALIAS("unhalted-cycles", "iap-cpu-clk-unhalted.core_p"), 470 EV_ALIAS(NULL, NULL) 471}; 472 473#define atom_aliases core2_aliases 474#define atom_aliases_without_iaf core2_aliases_without_iaf 475#define corei7_aliases core2_aliases 476#define corei7_aliases_without_iaf core2_aliases_without_iaf 477 478#define IAF_KW_OS "os" 479#define IAF_KW_USR "usr" 480#define IAF_KW_ANYTHREAD "anythread" 481 482/* 483 * Parse an event specifier for Intel fixed function counters. 484 */ 485static int 486iaf_allocate_pmc(enum pmc_event pe, char *ctrspec, 487 struct pmc_op_pmcallocate *pmc_config) 488{ 489 char *p; 490 491 (void) pe; 492 493 pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 494 pmc_config->pm_md.pm_iaf.pm_iaf_flags = 0; 495 496 while ((p = strsep(&ctrspec, ",")) != NULL) { 497 if (KWMATCH(p, IAF_KW_OS)) 498 pmc_config->pm_caps |= PMC_CAP_SYSTEM; 499 else if (KWMATCH(p, IAF_KW_USR)) 500 pmc_config->pm_caps |= PMC_CAP_USER; 501 else if (KWMATCH(p, IAF_KW_ANYTHREAD)) 502 pmc_config->pm_md.pm_iaf.pm_iaf_flags |= IAF_ANY; 503 else 504 return (-1); 505 } 506 507 return (0); 508} 509 510/* 511 * Core/Core2 support. 512 */ 513 514#define IAP_KW_AGENT "agent" 515#define IAP_KW_ANYTHREAD "anythread" 516#define IAP_KW_CACHESTATE "cachestate" 517#define IAP_KW_CMASK "cmask" 518#define IAP_KW_CORE "core" 519#define IAP_KW_EDGE "edge" 520#define IAP_KW_INV "inv" 521#define IAP_KW_OS "os" 522#define IAP_KW_PREFETCH "prefetch" 523#define IAP_KW_SNOOPRESPONSE "snoopresponse" 524#define IAP_KW_SNOOPTYPE "snooptype" 525#define IAP_KW_TRANSITION "trans" 526#define IAP_KW_USR "usr" 527 528static struct pmc_masks iap_core_mask[] = { 529 PMCMASK(all, (0x3 << 14)), 530 PMCMASK(this, (0x1 << 14)), 531 NULLMASK 532}; 533 534static struct pmc_masks iap_agent_mask[] = { 535 PMCMASK(this, 0), 536 PMCMASK(any, (0x1 << 13)), 537 NULLMASK 538}; 539 540static struct pmc_masks iap_prefetch_mask[] = { 541 PMCMASK(both, (0x3 << 12)), 542 PMCMASK(only, (0x1 << 12)), 543 PMCMASK(exclude, 0), 544 NULLMASK 545}; 546 547static struct pmc_masks iap_cachestate_mask[] = { 548 PMCMASK(i, (1 << 8)), 549 PMCMASK(s, (1 << 9)), 550 PMCMASK(e, (1 << 10)), 551 PMCMASK(m, (1 << 11)), 552 NULLMASK 553}; 554 555static struct pmc_masks iap_snoopresponse_mask[] = { 556 PMCMASK(clean, (1 << 8)), 557 PMCMASK(hit, (1 << 9)), 558 PMCMASK(hitm, (1 << 11)), 559 NULLMASK 560}; 561 562static struct pmc_masks iap_snooptype_mask[] = { 563 PMCMASK(cmp2s, (1 << 8)), 564 PMCMASK(cmp2i, (1 << 9)), 565 NULLMASK 566}; 567 568static struct pmc_masks iap_transition_mask[] = { 569 PMCMASK(any, 0x00), 570 PMCMASK(frequency, 0x10), 571 NULLMASK 572}; 573 574static int 575iap_allocate_pmc(enum pmc_event pe, char *ctrspec, 576 struct pmc_op_pmcallocate *pmc_config) 577{ 578 char *e, *p, *q; 579 uint32_t cachestate, evmask; 580 int count, n; 581 582 pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE | 583 PMC_CAP_QUALIFIER); 584 pmc_config->pm_md.pm_iap.pm_iap_config = 0; 585 586 cachestate = evmask = 0; 587 588 /* Parse additional modifiers if present */ 589 while ((p = strsep(&ctrspec, ",")) != NULL) { 590 591 n = 0; 592 if (KWPREFIXMATCH(p, IAP_KW_CMASK "=")) { 593 q = strchr(p, '='); 594 if (*++q == '\0') /* skip '=' */ 595 return (-1); 596 count = strtol(q, &e, 0); 597 if (e == q || *e != '\0') 598 return (-1); 599 pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 600 pmc_config->pm_md.pm_iap.pm_iap_config |= 601 IAP_CMASK(count); 602 } else if (KWMATCH(p, IAP_KW_EDGE)) { 603 pmc_config->pm_caps |= PMC_CAP_EDGE; 604 } else if (KWMATCH(p, IAP_KW_INV)) { 605 pmc_config->pm_caps |= PMC_CAP_INVERT; 606 } else if (KWMATCH(p, IAP_KW_OS)) { 607 pmc_config->pm_caps |= PMC_CAP_SYSTEM; 608 } else if (KWMATCH(p, IAP_KW_USR)) { 609 pmc_config->pm_caps |= PMC_CAP_USER; 610 } else if (KWMATCH(p, IAP_KW_ANYTHREAD)) { 611 pmc_config->pm_md.pm_iap.pm_iap_config |= IAP_ANY; 612 } else if (KWPREFIXMATCH(p, IAP_KW_CORE "=")) { 613 n = pmc_parse_mask(iap_core_mask, p, &evmask); 614 if (n != 1) 615 return (-1); 616 } else if (KWPREFIXMATCH(p, IAP_KW_AGENT "=")) { 617 n = pmc_parse_mask(iap_agent_mask, p, &evmask); 618 if (n != 1) 619 return (-1); 620 } else if (KWPREFIXMATCH(p, IAP_KW_PREFETCH "=")) { 621 n = pmc_parse_mask(iap_prefetch_mask, p, &evmask); 622 if (n != 1) 623 return (-1); 624 } else if (KWPREFIXMATCH(p, IAP_KW_CACHESTATE "=")) { 625 n = pmc_parse_mask(iap_cachestate_mask, p, &cachestate); 626 } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_CORE && 627 KWPREFIXMATCH(p, IAP_KW_TRANSITION "=")) { 628 n = pmc_parse_mask(iap_transition_mask, p, &evmask); 629 if (n != 1) 630 return (-1); 631 } else if (cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM || 632 cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2 || 633 cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2EXTREME || 634 cpu_info.pm_cputype == PMC_CPU_INTEL_COREI7) { 635 if (KWPREFIXMATCH(p, IAP_KW_SNOOPRESPONSE "=")) { 636 n = pmc_parse_mask(iap_snoopresponse_mask, p, 637 &evmask); 638 } else if (KWPREFIXMATCH(p, IAP_KW_SNOOPTYPE "=")) { 639 n = pmc_parse_mask(iap_snooptype_mask, p, 640 &evmask); 641 } else 642 return (-1); 643 } else 644 return (-1); 645 646 if (n < 0) /* Parsing failed. */ 647 return (-1); 648 } 649 650 pmc_config->pm_md.pm_iap.pm_iap_config |= evmask; 651 652 /* 653 * If the event requires a 'cachestate' qualifier but was not 654 * specified by the user, use a sensible default. 655 */ 656 switch (pe) { 657 case PMC_EV_IAP_EVENT_28H: /* Core, Core2, Atom */ 658 case PMC_EV_IAP_EVENT_29H: /* Core, Core2, Atom */ 659 case PMC_EV_IAP_EVENT_2AH: /* Core, Core2, Atom */ 660 case PMC_EV_IAP_EVENT_2BH: /* Atom, Core2 */ 661 case PMC_EV_IAP_EVENT_2EH: /* Core, Core2, Atom */ 662 case PMC_EV_IAP_EVENT_30H: /* Core, Core2, Atom */ 663 case PMC_EV_IAP_EVENT_32H: /* Core */ 664 case PMC_EV_IAP_EVENT_40H: /* Core */ 665 case PMC_EV_IAP_EVENT_41H: /* Core */ 666 case PMC_EV_IAP_EVENT_42H: /* Core, Core2, Atom */ 667 case PMC_EV_IAP_EVENT_77H: /* Core */ 668 if (cachestate == 0) 669 cachestate = (0xF << 8); 670 default: 671 break; 672 } 673 674 pmc_config->pm_md.pm_iap.pm_iap_config |= cachestate; 675 676 return (0); 677} 678 679/* 680 * AMD K8 PMCs. 681 * 682 * These are very similar to AMD K7 PMCs, but support more kinds of 683 * events. 684 */ 685 686static struct pmc_event_alias k8_aliases[] = { 687 EV_ALIAS("branches", "k8-fr-retired-taken-branches"), 688 EV_ALIAS("branch-mispredicts", 689 "k8-fr-retired-taken-branches-mispredicted"), 690 EV_ALIAS("cycles", "tsc"), 691 EV_ALIAS("dc-misses", "k8-dc-miss"), 692 EV_ALIAS("ic-misses", "k8-ic-miss"), 693 EV_ALIAS("instructions", "k8-fr-retired-x86-instructions"), 694 EV_ALIAS("interrupts", "k8-fr-taken-hardware-interrupts"), 695 EV_ALIAS("unhalted-cycles", "k8-bu-cpu-clk-unhalted"), 696 EV_ALIAS(NULL, NULL) 697}; 698 699#define __K8MASK(N,V) PMCMASK(N,(1 << (V))) 700 701/* 702 * Parsing tables 703 */ 704 705/* fp dispatched fpu ops */ 706static const struct pmc_masks k8_mask_fdfo[] = { 707 __K8MASK(add-pipe-excluding-junk-ops, 0), 708 __K8MASK(multiply-pipe-excluding-junk-ops, 1), 709 __K8MASK(store-pipe-excluding-junk-ops, 2), 710 __K8MASK(add-pipe-junk-ops, 3), 711 __K8MASK(multiply-pipe-junk-ops, 4), 712 __K8MASK(store-pipe-junk-ops, 5), 713 NULLMASK 714}; 715 716/* ls segment register loads */ 717static const struct pmc_masks k8_mask_lsrl[] = { 718 __K8MASK(es, 0), 719 __K8MASK(cs, 1), 720 __K8MASK(ss, 2), 721 __K8MASK(ds, 3), 722 __K8MASK(fs, 4), 723 __K8MASK(gs, 5), 724 __K8MASK(hs, 6), 725 NULLMASK 726}; 727 728/* ls locked operation */ 729static const struct pmc_masks k8_mask_llo[] = { 730 __K8MASK(locked-instructions, 0), 731 __K8MASK(cycles-in-request, 1), 732 __K8MASK(cycles-to-complete, 2), 733 NULLMASK 734}; 735 736/* dc refill from {l2,system} and dc copyback */ 737static const struct pmc_masks k8_mask_dc[] = { 738 __K8MASK(invalid, 0), 739 __K8MASK(shared, 1), 740 __K8MASK(exclusive, 2), 741 __K8MASK(owner, 3), 742 __K8MASK(modified, 4), 743 NULLMASK 744}; 745 746/* dc one bit ecc error */ 747static const struct pmc_masks k8_mask_dobee[] = { 748 __K8MASK(scrubber, 0), 749 __K8MASK(piggyback, 1), 750 NULLMASK 751}; 752 753/* dc dispatched prefetch instructions */ 754static const struct pmc_masks k8_mask_ddpi[] = { 755 __K8MASK(load, 0), 756 __K8MASK(store, 1), 757 __K8MASK(nta, 2), 758 NULLMASK 759}; 760 761/* dc dcache accesses by locks */ 762static const struct pmc_masks k8_mask_dabl[] = { 763 __K8MASK(accesses, 0), 764 __K8MASK(misses, 1), 765 NULLMASK 766}; 767 768/* bu internal l2 request */ 769static const struct pmc_masks k8_mask_bilr[] = { 770 __K8MASK(ic-fill, 0), 771 __K8MASK(dc-fill, 1), 772 __K8MASK(tlb-reload, 2), 773 __K8MASK(tag-snoop, 3), 774 __K8MASK(cancelled, 4), 775 NULLMASK 776}; 777 778/* bu fill request l2 miss */ 779static const struct pmc_masks k8_mask_bfrlm[] = { 780 __K8MASK(ic-fill, 0), 781 __K8MASK(dc-fill, 1), 782 __K8MASK(tlb-reload, 2), 783 NULLMASK 784}; 785 786/* bu fill into l2 */ 787static const struct pmc_masks k8_mask_bfil[] = { 788 __K8MASK(dirty-l2-victim, 0), 789 __K8MASK(victim-from-l2, 1), 790 NULLMASK 791}; 792 793/* fr retired fpu instructions */ 794static const struct pmc_masks k8_mask_frfi[] = { 795 __K8MASK(x87, 0), 796 __K8MASK(mmx-3dnow, 1), 797 __K8MASK(packed-sse-sse2, 2), 798 __K8MASK(scalar-sse-sse2, 3), 799 NULLMASK 800}; 801 802/* fr retired fastpath double op instructions */ 803static const struct pmc_masks k8_mask_frfdoi[] = { 804 __K8MASK(low-op-pos-0, 0), 805 __K8MASK(low-op-pos-1, 1), 806 __K8MASK(low-op-pos-2, 2), 807 NULLMASK 808}; 809 810/* fr fpu exceptions */ 811static const struct pmc_masks k8_mask_ffe[] = { 812 __K8MASK(x87-reclass-microfaults, 0), 813 __K8MASK(sse-retype-microfaults, 1), 814 __K8MASK(sse-reclass-microfaults, 2), 815 __K8MASK(sse-and-x87-microtraps, 3), 816 NULLMASK 817}; 818 819/* nb memory controller page access event */ 820static const struct pmc_masks k8_mask_nmcpae[] = { 821 __K8MASK(page-hit, 0), 822 __K8MASK(page-miss, 1), 823 __K8MASK(page-conflict, 2), 824 NULLMASK 825}; 826 827/* nb memory controller turnaround */ 828static const struct pmc_masks k8_mask_nmct[] = { 829 __K8MASK(dimm-turnaround, 0), 830 __K8MASK(read-to-write-turnaround, 1), 831 __K8MASK(write-to-read-turnaround, 2), 832 NULLMASK 833}; 834 835/* nb memory controller bypass saturation */ 836static const struct pmc_masks k8_mask_nmcbs[] = { 837 __K8MASK(memory-controller-hi-pri-bypass, 0), 838 __K8MASK(memory-controller-lo-pri-bypass, 1), 839 __K8MASK(dram-controller-interface-bypass, 2), 840 __K8MASK(dram-controller-queue-bypass, 3), 841 NULLMASK 842}; 843 844/* nb sized commands */ 845static const struct pmc_masks k8_mask_nsc[] = { 846 __K8MASK(nonpostwrszbyte, 0), 847 __K8MASK(nonpostwrszdword, 1), 848 __K8MASK(postwrszbyte, 2), 849 __K8MASK(postwrszdword, 3), 850 __K8MASK(rdszbyte, 4), 851 __K8MASK(rdszdword, 5), 852 __K8MASK(rdmodwr, 6), 853 NULLMASK 854}; 855 856/* nb probe result */ 857static const struct pmc_masks k8_mask_npr[] = { 858 __K8MASK(probe-miss, 0), 859 __K8MASK(probe-hit, 1), 860 __K8MASK(probe-hit-dirty-no-memory-cancel, 2), 861 __K8MASK(probe-hit-dirty-with-memory-cancel, 3), 862 NULLMASK 863}; 864 865/* nb hypertransport bus bandwidth */ 866static const struct pmc_masks k8_mask_nhbb[] = { /* HT bus bandwidth */ 867 __K8MASK(command, 0), 868 __K8MASK(data, 1), 869 __K8MASK(buffer-release, 2), 870 __K8MASK(nop, 3), 871 NULLMASK 872}; 873 874#undef __K8MASK 875 876#define K8_KW_COUNT "count" 877#define K8_KW_EDGE "edge" 878#define K8_KW_INV "inv" 879#define K8_KW_MASK "mask" 880#define K8_KW_OS "os" 881#define K8_KW_USR "usr" 882 883static int 884k8_allocate_pmc(enum pmc_event pe, char *ctrspec, 885 struct pmc_op_pmcallocate *pmc_config) 886{ 887 char *e, *p, *q; 888 int n; 889 uint32_t count, evmask; 890 const struct pmc_masks *pm, *pmask; 891 892 pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 893 pmc_config->pm_md.pm_amd.pm_amd_config = 0; 894 895 pmask = NULL; 896 evmask = 0; 897 898#define __K8SETMASK(M) pmask = k8_mask_##M 899 900 /* setup parsing tables */ 901 switch (pe) { 902 case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 903 __K8SETMASK(fdfo); 904 break; 905 case PMC_EV_K8_LS_SEGMENT_REGISTER_LOAD: 906 __K8SETMASK(lsrl); 907 break; 908 case PMC_EV_K8_LS_LOCKED_OPERATION: 909 __K8SETMASK(llo); 910 break; 911 case PMC_EV_K8_DC_REFILL_FROM_L2: 912 case PMC_EV_K8_DC_REFILL_FROM_SYSTEM: 913 case PMC_EV_K8_DC_COPYBACK: 914 __K8SETMASK(dc); 915 break; 916 case PMC_EV_K8_DC_ONE_BIT_ECC_ERROR: 917 __K8SETMASK(dobee); 918 break; 919 case PMC_EV_K8_DC_DISPATCHED_PREFETCH_INSTRUCTIONS: 920 __K8SETMASK(ddpi); 921 break; 922 case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 923 __K8SETMASK(dabl); 924 break; 925 case PMC_EV_K8_BU_INTERNAL_L2_REQUEST: 926 __K8SETMASK(bilr); 927 break; 928 case PMC_EV_K8_BU_FILL_REQUEST_L2_MISS: 929 __K8SETMASK(bfrlm); 930 break; 931 case PMC_EV_K8_BU_FILL_INTO_L2: 932 __K8SETMASK(bfil); 933 break; 934 case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 935 __K8SETMASK(frfi); 936 break; 937 case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 938 __K8SETMASK(frfdoi); 939 break; 940 case PMC_EV_K8_FR_FPU_EXCEPTIONS: 941 __K8SETMASK(ffe); 942 break; 943 case PMC_EV_K8_NB_MEMORY_CONTROLLER_PAGE_ACCESS_EVENT: 944 __K8SETMASK(nmcpae); 945 break; 946 case PMC_EV_K8_NB_MEMORY_CONTROLLER_TURNAROUND: 947 __K8SETMASK(nmct); 948 break; 949 case PMC_EV_K8_NB_MEMORY_CONTROLLER_BYPASS_SATURATION: 950 __K8SETMASK(nmcbs); 951 break; 952 case PMC_EV_K8_NB_SIZED_COMMANDS: 953 __K8SETMASK(nsc); 954 break; 955 case PMC_EV_K8_NB_PROBE_RESULT: 956 __K8SETMASK(npr); 957 break; 958 case PMC_EV_K8_NB_HT_BUS0_BANDWIDTH: 959 case PMC_EV_K8_NB_HT_BUS1_BANDWIDTH: 960 case PMC_EV_K8_NB_HT_BUS2_BANDWIDTH: 961 __K8SETMASK(nhbb); 962 break; 963 964 default: 965 break; /* no options defined */ 966 } 967 968 while ((p = strsep(&ctrspec, ",")) != NULL) { 969 if (KWPREFIXMATCH(p, K8_KW_COUNT "=")) { 970 q = strchr(p, '='); 971 if (*++q == '\0') /* skip '=' */ 972 return (-1); 973 974 count = strtol(q, &e, 0); 975 if (e == q || *e != '\0') 976 return (-1); 977 978 pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 979 pmc_config->pm_md.pm_amd.pm_amd_config |= 980 AMD_PMC_TO_COUNTER(count); 981 982 } else if (KWMATCH(p, K8_KW_EDGE)) { 983 pmc_config->pm_caps |= PMC_CAP_EDGE; 984 } else if (KWMATCH(p, K8_KW_INV)) { 985 pmc_config->pm_caps |= PMC_CAP_INVERT; 986 } else if (KWPREFIXMATCH(p, K8_KW_MASK "=")) { 987 if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 988 return (-1); 989 pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 990 } else if (KWMATCH(p, K8_KW_OS)) { 991 pmc_config->pm_caps |= PMC_CAP_SYSTEM; 992 } else if (KWMATCH(p, K8_KW_USR)) { 993 pmc_config->pm_caps |= PMC_CAP_USER; 994 } else 995 return (-1); 996 } 997 998 /* other post processing */ 999 switch (pe) { 1000 case PMC_EV_K8_FP_DISPATCHED_FPU_OPS: 1001 case PMC_EV_K8_FP_CYCLES_WITH_NO_FPU_OPS_RETIRED: 1002 case PMC_EV_K8_FP_DISPATCHED_FPU_FAST_FLAG_OPS: 1003 case PMC_EV_K8_FR_RETIRED_FASTPATH_DOUBLE_OP_INSTRUCTIONS: 1004 case PMC_EV_K8_FR_RETIRED_FPU_INSTRUCTIONS: 1005 case PMC_EV_K8_FR_FPU_EXCEPTIONS: 1006 /* XXX only available in rev B and later */ 1007 break; 1008 case PMC_EV_K8_DC_DCACHE_ACCESSES_BY_LOCKS: 1009 /* XXX only available in rev C and later */ 1010 break; 1011 case PMC_EV_K8_LS_LOCKED_OPERATION: 1012 /* XXX CPU Rev A,B evmask is to be zero */ 1013 if (evmask & (evmask - 1)) /* > 1 bit set */ 1014 return (-1); 1015 if (evmask == 0) { 1016 evmask = 0x01; /* Rev C and later: #instrs */ 1017 pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1018 } 1019 break; 1020 default: 1021 if (evmask == 0 && pmask != NULL) { 1022 for (pm = pmask; pm->pm_name; pm++) 1023 evmask |= pm->pm_value; 1024 pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1025 } 1026 } 1027 1028 if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 1029 pmc_config->pm_md.pm_amd.pm_amd_config = 1030 AMD_PMC_TO_UNITMASK(evmask); 1031 1032 return (0); 1033} 1034 1035#endif 1036 1037#if defined(__amd64__) || defined(__i386__) 1038 1039/* 1040 * Intel P4 PMCs 1041 */ 1042 1043static struct pmc_event_alias p4_aliases[] = { 1044 EV_ALIAS("branches", "p4-branch-retired,mask=mmtp+mmtm"), 1045 EV_ALIAS("branch-mispredicts", "p4-mispred-branch-retired"), 1046 EV_ALIAS("cycles", "tsc"), 1047 EV_ALIAS("instructions", 1048 "p4-instr-retired,mask=nbogusntag+nbogustag"), 1049 EV_ALIAS("unhalted-cycles", "p4-global-power-events"), 1050 EV_ALIAS(NULL, NULL) 1051}; 1052 1053#define P4_KW_ACTIVE "active" 1054#define P4_KW_ACTIVE_ANY "any" 1055#define P4_KW_ACTIVE_BOTH "both" 1056#define P4_KW_ACTIVE_NONE "none" 1057#define P4_KW_ACTIVE_SINGLE "single" 1058#define P4_KW_BUSREQTYPE "busreqtype" 1059#define P4_KW_CASCADE "cascade" 1060#define P4_KW_EDGE "edge" 1061#define P4_KW_INV "complement" 1062#define P4_KW_OS "os" 1063#define P4_KW_MASK "mask" 1064#define P4_KW_PRECISE "precise" 1065#define P4_KW_TAG "tag" 1066#define P4_KW_THRESHOLD "threshold" 1067#define P4_KW_USR "usr" 1068 1069#define __P4MASK(N,V) PMCMASK(N, (1 << (V))) 1070 1071static const struct pmc_masks p4_mask_tcdm[] = { /* tc deliver mode */ 1072 __P4MASK(dd, 0), 1073 __P4MASK(db, 1), 1074 __P4MASK(di, 2), 1075 __P4MASK(bd, 3), 1076 __P4MASK(bb, 4), 1077 __P4MASK(bi, 5), 1078 __P4MASK(id, 6), 1079 __P4MASK(ib, 7), 1080 NULLMASK 1081}; 1082 1083static const struct pmc_masks p4_mask_bfr[] = { /* bpu fetch request */ 1084 __P4MASK(tcmiss, 0), 1085 NULLMASK, 1086}; 1087 1088static const struct pmc_masks p4_mask_ir[] = { /* itlb reference */ 1089 __P4MASK(hit, 0), 1090 __P4MASK(miss, 1), 1091 __P4MASK(hit-uc, 2), 1092 NULLMASK 1093}; 1094 1095static const struct pmc_masks p4_mask_memcan[] = { /* memory cancel */ 1096 __P4MASK(st-rb-full, 2), 1097 __P4MASK(64k-conf, 3), 1098 NULLMASK 1099}; 1100 1101static const struct pmc_masks p4_mask_memcomp[] = { /* memory complete */ 1102 __P4MASK(lsc, 0), 1103 __P4MASK(ssc, 1), 1104 NULLMASK 1105}; 1106 1107static const struct pmc_masks p4_mask_lpr[] = { /* load port replay */ 1108 __P4MASK(split-ld, 1), 1109 NULLMASK 1110}; 1111 1112static const struct pmc_masks p4_mask_spr[] = { /* store port replay */ 1113 __P4MASK(split-st, 1), 1114 NULLMASK 1115}; 1116 1117static const struct pmc_masks p4_mask_mlr[] = { /* mob load replay */ 1118 __P4MASK(no-sta, 1), 1119 __P4MASK(no-std, 3), 1120 __P4MASK(partial-data, 4), 1121 __P4MASK(unalgn-addr, 5), 1122 NULLMASK 1123}; 1124 1125static const struct pmc_masks p4_mask_pwt[] = { /* page walk type */ 1126 __P4MASK(dtmiss, 0), 1127 __P4MASK(itmiss, 1), 1128 NULLMASK 1129}; 1130 1131static const struct pmc_masks p4_mask_bcr[] = { /* bsq cache reference */ 1132 __P4MASK(rd-2ndl-hits, 0), 1133 __P4MASK(rd-2ndl-hite, 1), 1134 __P4MASK(rd-2ndl-hitm, 2), 1135 __P4MASK(rd-3rdl-hits, 3), 1136 __P4MASK(rd-3rdl-hite, 4), 1137 __P4MASK(rd-3rdl-hitm, 5), 1138 __P4MASK(rd-2ndl-miss, 8), 1139 __P4MASK(rd-3rdl-miss, 9), 1140 __P4MASK(wr-2ndl-miss, 10), 1141 NULLMASK 1142}; 1143 1144static const struct pmc_masks p4_mask_ia[] = { /* ioq allocation */ 1145 __P4MASK(all-read, 5), 1146 __P4MASK(all-write, 6), 1147 __P4MASK(mem-uc, 7), 1148 __P4MASK(mem-wc, 8), 1149 __P4MASK(mem-wt, 9), 1150 __P4MASK(mem-wp, 10), 1151 __P4MASK(mem-wb, 11), 1152 __P4MASK(own, 13), 1153 __P4MASK(other, 14), 1154 __P4MASK(prefetch, 15), 1155 NULLMASK 1156}; 1157 1158static const struct pmc_masks p4_mask_iae[] = { /* ioq active entries */ 1159 __P4MASK(all-read, 5), 1160 __P4MASK(all-write, 6), 1161 __P4MASK(mem-uc, 7), 1162 __P4MASK(mem-wc, 8), 1163 __P4MASK(mem-wt, 9), 1164 __P4MASK(mem-wp, 10), 1165 __P4MASK(mem-wb, 11), 1166 __P4MASK(own, 13), 1167 __P4MASK(other, 14), 1168 __P4MASK(prefetch, 15), 1169 NULLMASK 1170}; 1171 1172static const struct pmc_masks p4_mask_fda[] = { /* fsb data activity */ 1173 __P4MASK(drdy-drv, 0), 1174 __P4MASK(drdy-own, 1), 1175 __P4MASK(drdy-other, 2), 1176 __P4MASK(dbsy-drv, 3), 1177 __P4MASK(dbsy-own, 4), 1178 __P4MASK(dbsy-other, 5), 1179 NULLMASK 1180}; 1181 1182static const struct pmc_masks p4_mask_ba[] = { /* bsq allocation */ 1183 __P4MASK(req-type0, 0), 1184 __P4MASK(req-type1, 1), 1185 __P4MASK(req-len0, 2), 1186 __P4MASK(req-len1, 3), 1187 __P4MASK(req-io-type, 5), 1188 __P4MASK(req-lock-type, 6), 1189 __P4MASK(req-cache-type, 7), 1190 __P4MASK(req-split-type, 8), 1191 __P4MASK(req-dem-type, 9), 1192 __P4MASK(req-ord-type, 10), 1193 __P4MASK(mem-type0, 11), 1194 __P4MASK(mem-type1, 12), 1195 __P4MASK(mem-type2, 13), 1196 NULLMASK 1197}; 1198 1199static const struct pmc_masks p4_mask_sia[] = { /* sse input assist */ 1200 __P4MASK(all, 15), 1201 NULLMASK 1202}; 1203 1204static const struct pmc_masks p4_mask_psu[] = { /* packed sp uop */ 1205 __P4MASK(all, 15), 1206 NULLMASK 1207}; 1208 1209static const struct pmc_masks p4_mask_pdu[] = { /* packed dp uop */ 1210 __P4MASK(all, 15), 1211 NULLMASK 1212}; 1213 1214static const struct pmc_masks p4_mask_ssu[] = { /* scalar sp uop */ 1215 __P4MASK(all, 15), 1216 NULLMASK 1217}; 1218 1219static const struct pmc_masks p4_mask_sdu[] = { /* scalar dp uop */ 1220 __P4MASK(all, 15), 1221 NULLMASK 1222}; 1223 1224static const struct pmc_masks p4_mask_64bmu[] = { /* 64 bit mmx uop */ 1225 __P4MASK(all, 15), 1226 NULLMASK 1227}; 1228 1229static const struct pmc_masks p4_mask_128bmu[] = { /* 128 bit mmx uop */ 1230 __P4MASK(all, 15), 1231 NULLMASK 1232}; 1233 1234static const struct pmc_masks p4_mask_xfu[] = { /* X87 fp uop */ 1235 __P4MASK(all, 15), 1236 NULLMASK 1237}; 1238 1239static const struct pmc_masks p4_mask_xsmu[] = { /* x87 simd moves uop */ 1240 __P4MASK(allp0, 3), 1241 __P4MASK(allp2, 4), 1242 NULLMASK 1243}; 1244 1245static const struct pmc_masks p4_mask_gpe[] = { /* global power events */ 1246 __P4MASK(running, 0), 1247 NULLMASK 1248}; 1249 1250static const struct pmc_masks p4_mask_tmx[] = { /* TC ms xfer */ 1251 __P4MASK(cisc, 0), 1252 NULLMASK 1253}; 1254 1255static const struct pmc_masks p4_mask_uqw[] = { /* uop queue writes */ 1256 __P4MASK(from-tc-build, 0), 1257 __P4MASK(from-tc-deliver, 1), 1258 __P4MASK(from-rom, 2), 1259 NULLMASK 1260}; 1261 1262static const struct pmc_masks p4_mask_rmbt[] = { 1263 /* retired mispred branch type */ 1264 __P4MASK(conditional, 1), 1265 __P4MASK(call, 2), 1266 __P4MASK(return, 3), 1267 __P4MASK(indirect, 4), 1268 NULLMASK 1269}; 1270 1271static const struct pmc_masks p4_mask_rbt[] = { /* retired branch type */ 1272 __P4MASK(conditional, 1), 1273 __P4MASK(call, 2), 1274 __P4MASK(retired, 3), 1275 __P4MASK(indirect, 4), 1276 NULLMASK 1277}; 1278 1279static const struct pmc_masks p4_mask_rs[] = { /* resource stall */ 1280 __P4MASK(sbfull, 5), 1281 NULLMASK 1282}; 1283 1284static const struct pmc_masks p4_mask_wb[] = { /* WC buffer */ 1285 __P4MASK(wcb-evicts, 0), 1286 __P4MASK(wcb-full-evict, 1), 1287 NULLMASK 1288}; 1289 1290static const struct pmc_masks p4_mask_fee[] = { /* front end event */ 1291 __P4MASK(nbogus, 0), 1292 __P4MASK(bogus, 1), 1293 NULLMASK 1294}; 1295 1296static const struct pmc_masks p4_mask_ee[] = { /* execution event */ 1297 __P4MASK(nbogus0, 0), 1298 __P4MASK(nbogus1, 1), 1299 __P4MASK(nbogus2, 2), 1300 __P4MASK(nbogus3, 3), 1301 __P4MASK(bogus0, 4), 1302 __P4MASK(bogus1, 5), 1303 __P4MASK(bogus2, 6), 1304 __P4MASK(bogus3, 7), 1305 NULLMASK 1306}; 1307 1308static const struct pmc_masks p4_mask_re[] = { /* replay event */ 1309 __P4MASK(nbogus, 0), 1310 __P4MASK(bogus, 1), 1311 NULLMASK 1312}; 1313 1314static const struct pmc_masks p4_mask_insret[] = { /* instr retired */ 1315 __P4MASK(nbogusntag, 0), 1316 __P4MASK(nbogustag, 1), 1317 __P4MASK(bogusntag, 2), 1318 __P4MASK(bogustag, 3), 1319 NULLMASK 1320}; 1321 1322static const struct pmc_masks p4_mask_ur[] = { /* uops retired */ 1323 __P4MASK(nbogus, 0), 1324 __P4MASK(bogus, 1), 1325 NULLMASK 1326}; 1327 1328static const struct pmc_masks p4_mask_ut[] = { /* uop type */ 1329 __P4MASK(tagloads, 1), 1330 __P4MASK(tagstores, 2), 1331 NULLMASK 1332}; 1333 1334static const struct pmc_masks p4_mask_br[] = { /* branch retired */ 1335 __P4MASK(mmnp, 0), 1336 __P4MASK(mmnm, 1), 1337 __P4MASK(mmtp, 2), 1338 __P4MASK(mmtm, 3), 1339 NULLMASK 1340}; 1341 1342static const struct pmc_masks p4_mask_mbr[] = { /* mispred branch retired */ 1343 __P4MASK(nbogus, 0), 1344 NULLMASK 1345}; 1346 1347static const struct pmc_masks p4_mask_xa[] = { /* x87 assist */ 1348 __P4MASK(fpsu, 0), 1349 __P4MASK(fpso, 1), 1350 __P4MASK(poao, 2), 1351 __P4MASK(poau, 3), 1352 __P4MASK(prea, 4), 1353 NULLMASK 1354}; 1355 1356static const struct pmc_masks p4_mask_machclr[] = { /* machine clear */ 1357 __P4MASK(clear, 0), 1358 __P4MASK(moclear, 2), 1359 __P4MASK(smclear, 3), 1360 NULLMASK 1361}; 1362 1363/* P4 event parser */ 1364static int 1365p4_allocate_pmc(enum pmc_event pe, char *ctrspec, 1366 struct pmc_op_pmcallocate *pmc_config) 1367{ 1368 1369 char *e, *p, *q; 1370 int count, has_tag, has_busreqtype, n; 1371 uint32_t evmask, cccractivemask; 1372 const struct pmc_masks *pm, *pmask; 1373 1374 pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1375 pmc_config->pm_md.pm_p4.pm_p4_cccrconfig = 1376 pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 0; 1377 1378 pmask = NULL; 1379 evmask = 0; 1380 cccractivemask = 0x3; 1381 has_tag = has_busreqtype = 0; 1382 1383#define __P4SETMASK(M) do { \ 1384 pmask = p4_mask_##M; \ 1385} while (0) 1386 1387 switch (pe) { 1388 case PMC_EV_P4_TC_DELIVER_MODE: 1389 __P4SETMASK(tcdm); 1390 break; 1391 case PMC_EV_P4_BPU_FETCH_REQUEST: 1392 __P4SETMASK(bfr); 1393 break; 1394 case PMC_EV_P4_ITLB_REFERENCE: 1395 __P4SETMASK(ir); 1396 break; 1397 case PMC_EV_P4_MEMORY_CANCEL: 1398 __P4SETMASK(memcan); 1399 break; 1400 case PMC_EV_P4_MEMORY_COMPLETE: 1401 __P4SETMASK(memcomp); 1402 break; 1403 case PMC_EV_P4_LOAD_PORT_REPLAY: 1404 __P4SETMASK(lpr); 1405 break; 1406 case PMC_EV_P4_STORE_PORT_REPLAY: 1407 __P4SETMASK(spr); 1408 break; 1409 case PMC_EV_P4_MOB_LOAD_REPLAY: 1410 __P4SETMASK(mlr); 1411 break; 1412 case PMC_EV_P4_PAGE_WALK_TYPE: 1413 __P4SETMASK(pwt); 1414 break; 1415 case PMC_EV_P4_BSQ_CACHE_REFERENCE: 1416 __P4SETMASK(bcr); 1417 break; 1418 case PMC_EV_P4_IOQ_ALLOCATION: 1419 __P4SETMASK(ia); 1420 has_busreqtype = 1; 1421 break; 1422 case PMC_EV_P4_IOQ_ACTIVE_ENTRIES: 1423 __P4SETMASK(iae); 1424 has_busreqtype = 1; 1425 break; 1426 case PMC_EV_P4_FSB_DATA_ACTIVITY: 1427 __P4SETMASK(fda); 1428 break; 1429 case PMC_EV_P4_BSQ_ALLOCATION: 1430 __P4SETMASK(ba); 1431 break; 1432 case PMC_EV_P4_SSE_INPUT_ASSIST: 1433 __P4SETMASK(sia); 1434 break; 1435 case PMC_EV_P4_PACKED_SP_UOP: 1436 __P4SETMASK(psu); 1437 break; 1438 case PMC_EV_P4_PACKED_DP_UOP: 1439 __P4SETMASK(pdu); 1440 break; 1441 case PMC_EV_P4_SCALAR_SP_UOP: 1442 __P4SETMASK(ssu); 1443 break; 1444 case PMC_EV_P4_SCALAR_DP_UOP: 1445 __P4SETMASK(sdu); 1446 break; 1447 case PMC_EV_P4_64BIT_MMX_UOP: 1448 __P4SETMASK(64bmu); 1449 break; 1450 case PMC_EV_P4_128BIT_MMX_UOP: 1451 __P4SETMASK(128bmu); 1452 break; 1453 case PMC_EV_P4_X87_FP_UOP: 1454 __P4SETMASK(xfu); 1455 break; 1456 case PMC_EV_P4_X87_SIMD_MOVES_UOP: 1457 __P4SETMASK(xsmu); 1458 break; 1459 case PMC_EV_P4_GLOBAL_POWER_EVENTS: 1460 __P4SETMASK(gpe); 1461 break; 1462 case PMC_EV_P4_TC_MS_XFER: 1463 __P4SETMASK(tmx); 1464 break; 1465 case PMC_EV_P4_UOP_QUEUE_WRITES: 1466 __P4SETMASK(uqw); 1467 break; 1468 case PMC_EV_P4_RETIRED_MISPRED_BRANCH_TYPE: 1469 __P4SETMASK(rmbt); 1470 break; 1471 case PMC_EV_P4_RETIRED_BRANCH_TYPE: 1472 __P4SETMASK(rbt); 1473 break; 1474 case PMC_EV_P4_RESOURCE_STALL: 1475 __P4SETMASK(rs); 1476 break; 1477 case PMC_EV_P4_WC_BUFFER: 1478 __P4SETMASK(wb); 1479 break; 1480 case PMC_EV_P4_BSQ_ACTIVE_ENTRIES: 1481 case PMC_EV_P4_B2B_CYCLES: 1482 case PMC_EV_P4_BNR: 1483 case PMC_EV_P4_SNOOP: 1484 case PMC_EV_P4_RESPONSE: 1485 break; 1486 case PMC_EV_P4_FRONT_END_EVENT: 1487 __P4SETMASK(fee); 1488 break; 1489 case PMC_EV_P4_EXECUTION_EVENT: 1490 __P4SETMASK(ee); 1491 break; 1492 case PMC_EV_P4_REPLAY_EVENT: 1493 __P4SETMASK(re); 1494 break; 1495 case PMC_EV_P4_INSTR_RETIRED: 1496 __P4SETMASK(insret); 1497 break; 1498 case PMC_EV_P4_UOPS_RETIRED: 1499 __P4SETMASK(ur); 1500 break; 1501 case PMC_EV_P4_UOP_TYPE: 1502 __P4SETMASK(ut); 1503 break; 1504 case PMC_EV_P4_BRANCH_RETIRED: 1505 __P4SETMASK(br); 1506 break; 1507 case PMC_EV_P4_MISPRED_BRANCH_RETIRED: 1508 __P4SETMASK(mbr); 1509 break; 1510 case PMC_EV_P4_X87_ASSIST: 1511 __P4SETMASK(xa); 1512 break; 1513 case PMC_EV_P4_MACHINE_CLEAR: 1514 __P4SETMASK(machclr); 1515 break; 1516 default: 1517 return (-1); 1518 } 1519 1520 /* process additional flags */ 1521 while ((p = strsep(&ctrspec, ",")) != NULL) { 1522 if (KWPREFIXMATCH(p, P4_KW_ACTIVE)) { 1523 q = strchr(p, '='); 1524 if (*++q == '\0') /* skip '=' */ 1525 return (-1); 1526 1527 if (strcasecmp(q, P4_KW_ACTIVE_NONE) == 0) 1528 cccractivemask = 0x0; 1529 else if (strcasecmp(q, P4_KW_ACTIVE_SINGLE) == 0) 1530 cccractivemask = 0x1; 1531 else if (strcasecmp(q, P4_KW_ACTIVE_BOTH) == 0) 1532 cccractivemask = 0x2; 1533 else if (strcasecmp(q, P4_KW_ACTIVE_ANY) == 0) 1534 cccractivemask = 0x3; 1535 else 1536 return (-1); 1537 1538 } else if (KWPREFIXMATCH(p, P4_KW_BUSREQTYPE)) { 1539 if (has_busreqtype == 0) 1540 return (-1); 1541 1542 q = strchr(p, '='); 1543 if (*++q == '\0') /* skip '=' */ 1544 return (-1); 1545 1546 count = strtol(q, &e, 0); 1547 if (e == q || *e != '\0') 1548 return (-1); 1549 evmask = (evmask & ~0x1F) | (count & 0x1F); 1550 } else if (KWMATCH(p, P4_KW_CASCADE)) 1551 pmc_config->pm_caps |= PMC_CAP_CASCADE; 1552 else if (KWMATCH(p, P4_KW_EDGE)) 1553 pmc_config->pm_caps |= PMC_CAP_EDGE; 1554 else if (KWMATCH(p, P4_KW_INV)) 1555 pmc_config->pm_caps |= PMC_CAP_INVERT; 1556 else if (KWPREFIXMATCH(p, P4_KW_MASK "=")) { 1557 if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1558 return (-1); 1559 pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1560 } else if (KWMATCH(p, P4_KW_OS)) 1561 pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1562 else if (KWMATCH(p, P4_KW_PRECISE)) 1563 pmc_config->pm_caps |= PMC_CAP_PRECISE; 1564 else if (KWPREFIXMATCH(p, P4_KW_TAG "=")) { 1565 if (has_tag == 0) 1566 return (-1); 1567 1568 q = strchr(p, '='); 1569 if (*++q == '\0') /* skip '=' */ 1570 return (-1); 1571 1572 count = strtol(q, &e, 0); 1573 if (e == q || *e != '\0') 1574 return (-1); 1575 1576 pmc_config->pm_caps |= PMC_CAP_TAGGING; 1577 pmc_config->pm_md.pm_p4.pm_p4_escrconfig |= 1578 P4_ESCR_TO_TAG_VALUE(count); 1579 } else if (KWPREFIXMATCH(p, P4_KW_THRESHOLD "=")) { 1580 q = strchr(p, '='); 1581 if (*++q == '\0') /* skip '=' */ 1582 return (-1); 1583 1584 count = strtol(q, &e, 0); 1585 if (e == q || *e != '\0') 1586 return (-1); 1587 1588 pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1589 pmc_config->pm_md.pm_p4.pm_p4_cccrconfig &= 1590 ~P4_CCCR_THRESHOLD_MASK; 1591 pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 1592 P4_CCCR_TO_THRESHOLD(count); 1593 } else if (KWMATCH(p, P4_KW_USR)) 1594 pmc_config->pm_caps |= PMC_CAP_USER; 1595 else 1596 return (-1); 1597 } 1598 1599 /* other post processing */ 1600 if (pe == PMC_EV_P4_IOQ_ALLOCATION || 1601 pe == PMC_EV_P4_FSB_DATA_ACTIVITY || 1602 pe == PMC_EV_P4_BSQ_ALLOCATION) 1603 pmc_config->pm_caps |= PMC_CAP_EDGE; 1604 1605 /* fill in thread activity mask */ 1606 pmc_config->pm_md.pm_p4.pm_p4_cccrconfig |= 1607 P4_CCCR_TO_ACTIVE_THREAD(cccractivemask); 1608 1609 if (evmask) 1610 pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1611 1612 switch (pe) { 1613 case PMC_EV_P4_FSB_DATA_ACTIVITY: 1614 if ((evmask & 0x06) == 0x06 || 1615 (evmask & 0x18) == 0x18) 1616 return (-1); /* can't have own+other bits together */ 1617 if (evmask == 0) /* default:drdy-{drv,own}+dbsy{drv,own} */ 1618 evmask = 0x1D; 1619 break; 1620 case PMC_EV_P4_MACHINE_CLEAR: 1621 /* only one bit is allowed to be set */ 1622 if ((evmask & (evmask - 1)) != 0) 1623 return (-1); 1624 if (evmask == 0) { 1625 evmask = 0x1; /* 'CLEAR' */ 1626 pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1627 } 1628 break; 1629 default: 1630 if (evmask == 0 && pmask) { 1631 for (pm = pmask; pm->pm_name; pm++) 1632 evmask |= pm->pm_value; 1633 pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1634 } 1635 } 1636 1637 pmc_config->pm_md.pm_p4.pm_p4_escrconfig = 1638 P4_ESCR_TO_EVENT_MASK(evmask); 1639 1640 return (0); 1641} 1642 1643#endif 1644 1645#if defined(__i386__) 1646 1647/* 1648 * Pentium style PMCs 1649 */ 1650 1651static struct pmc_event_alias p5_aliases[] = { 1652 EV_ALIAS("branches", "p5-taken-branches"), 1653 EV_ALIAS("cycles", "tsc"), 1654 EV_ALIAS("dc-misses", "p5-data-read-miss-or-write-miss"), 1655 EV_ALIAS("ic-misses", "p5-code-cache-miss"), 1656 EV_ALIAS("instructions", "p5-instructions-executed"), 1657 EV_ALIAS("interrupts", "p5-hardware-interrupts"), 1658 EV_ALIAS("unhalted-cycles", 1659 "p5-number-of-cycles-not-in-halt-state"), 1660 EV_ALIAS(NULL, NULL) 1661}; 1662 1663static int 1664p5_allocate_pmc(enum pmc_event pe, char *ctrspec, 1665 struct pmc_op_pmcallocate *pmc_config) 1666{ 1667 return (-1 || pe || ctrspec || pmc_config); /* shut up gcc */ 1668} 1669 1670/* 1671 * Pentium Pro style PMCs. These PMCs are found in Pentium II, Pentium III, 1672 * and Pentium M CPUs. 1673 */ 1674 1675static struct pmc_event_alias p6_aliases[] = { 1676 EV_ALIAS("branches", "p6-br-inst-retired"), 1677 EV_ALIAS("branch-mispredicts", "p6-br-miss-pred-retired"), 1678 EV_ALIAS("cycles", "tsc"), 1679 EV_ALIAS("dc-misses", "p6-dcu-lines-in"), 1680 EV_ALIAS("ic-misses", "p6-ifu-fetch-miss"), 1681 EV_ALIAS("instructions", "p6-inst-retired"), 1682 EV_ALIAS("interrupts", "p6-hw-int-rx"), 1683 EV_ALIAS("unhalted-cycles", "p6-cpu-clk-unhalted"), 1684 EV_ALIAS(NULL, NULL) 1685}; 1686 1687#define P6_KW_CMASK "cmask" 1688#define P6_KW_EDGE "edge" 1689#define P6_KW_INV "inv" 1690#define P6_KW_OS "os" 1691#define P6_KW_UMASK "umask" 1692#define P6_KW_USR "usr" 1693 1694static struct pmc_masks p6_mask_mesi[] = { 1695 PMCMASK(m, 0x01), 1696 PMCMASK(e, 0x02), 1697 PMCMASK(s, 0x04), 1698 PMCMASK(i, 0x08), 1699 NULLMASK 1700}; 1701 1702static struct pmc_masks p6_mask_mesihw[] = { 1703 PMCMASK(m, 0x01), 1704 PMCMASK(e, 0x02), 1705 PMCMASK(s, 0x04), 1706 PMCMASK(i, 0x08), 1707 PMCMASK(nonhw, 0x00), 1708 PMCMASK(hw, 0x10), 1709 PMCMASK(both, 0x30), 1710 NULLMASK 1711}; 1712 1713static struct pmc_masks p6_mask_hw[] = { 1714 PMCMASK(nonhw, 0x00), 1715 PMCMASK(hw, 0x10), 1716 PMCMASK(both, 0x30), 1717 NULLMASK 1718}; 1719 1720static struct pmc_masks p6_mask_any[] = { 1721 PMCMASK(self, 0x00), 1722 PMCMASK(any, 0x20), 1723 NULLMASK 1724}; 1725 1726static struct pmc_masks p6_mask_ekp[] = { 1727 PMCMASK(nta, 0x00), 1728 PMCMASK(t1, 0x01), 1729 PMCMASK(t2, 0x02), 1730 PMCMASK(wos, 0x03), 1731 NULLMASK 1732}; 1733 1734static struct pmc_masks p6_mask_pps[] = { 1735 PMCMASK(packed-and-scalar, 0x00), 1736 PMCMASK(scalar, 0x01), 1737 NULLMASK 1738}; 1739 1740static struct pmc_masks p6_mask_mite[] = { 1741 PMCMASK(packed-multiply, 0x01), 1742 PMCMASK(packed-shift, 0x02), 1743 PMCMASK(pack, 0x04), 1744 PMCMASK(unpack, 0x08), 1745 PMCMASK(packed-logical, 0x10), 1746 PMCMASK(packed-arithmetic, 0x20), 1747 NULLMASK 1748}; 1749 1750static struct pmc_masks p6_mask_fmt[] = { 1751 PMCMASK(mmxtofp, 0x00), 1752 PMCMASK(fptommx, 0x01), 1753 NULLMASK 1754}; 1755 1756static struct pmc_masks p6_mask_sr[] = { 1757 PMCMASK(es, 0x01), 1758 PMCMASK(ds, 0x02), 1759 PMCMASK(fs, 0x04), 1760 PMCMASK(gs, 0x08), 1761 NULLMASK 1762}; 1763 1764static struct pmc_masks p6_mask_eet[] = { 1765 PMCMASK(all, 0x00), 1766 PMCMASK(freq, 0x02), 1767 NULLMASK 1768}; 1769 1770static struct pmc_masks p6_mask_efur[] = { 1771 PMCMASK(all, 0x00), 1772 PMCMASK(loadop, 0x01), 1773 PMCMASK(stdsta, 0x02), 1774 NULLMASK 1775}; 1776 1777static struct pmc_masks p6_mask_essir[] = { 1778 PMCMASK(sse-packed-single, 0x00), 1779 PMCMASK(sse-packed-single-scalar-single, 0x01), 1780 PMCMASK(sse2-packed-double, 0x02), 1781 PMCMASK(sse2-scalar-double, 0x03), 1782 NULLMASK 1783}; 1784 1785static struct pmc_masks p6_mask_esscir[] = { 1786 PMCMASK(sse-packed-single, 0x00), 1787 PMCMASK(sse-scalar-single, 0x01), 1788 PMCMASK(sse2-packed-double, 0x02), 1789 PMCMASK(sse2-scalar-double, 0x03), 1790 NULLMASK 1791}; 1792 1793/* P6 event parser */ 1794static int 1795p6_allocate_pmc(enum pmc_event pe, char *ctrspec, 1796 struct pmc_op_pmcallocate *pmc_config) 1797{ 1798 char *e, *p, *q; 1799 uint32_t evmask; 1800 int count, n; 1801 const struct pmc_masks *pm, *pmask; 1802 1803 pmc_config->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE); 1804 pmc_config->pm_md.pm_ppro.pm_ppro_config = 0; 1805 1806 evmask = 0; 1807 1808#define P6MASKSET(M) pmask = p6_mask_ ## M 1809 1810 switch(pe) { 1811 case PMC_EV_P6_L2_IFETCH: P6MASKSET(mesi); break; 1812 case PMC_EV_P6_L2_LD: P6MASKSET(mesi); break; 1813 case PMC_EV_P6_L2_ST: P6MASKSET(mesi); break; 1814 case PMC_EV_P6_L2_RQSTS: P6MASKSET(mesi); break; 1815 case PMC_EV_P6_BUS_DRDY_CLOCKS: 1816 case PMC_EV_P6_BUS_LOCK_CLOCKS: 1817 case PMC_EV_P6_BUS_TRAN_BRD: 1818 case PMC_EV_P6_BUS_TRAN_RFO: 1819 case PMC_EV_P6_BUS_TRANS_WB: 1820 case PMC_EV_P6_BUS_TRAN_IFETCH: 1821 case PMC_EV_P6_BUS_TRAN_INVAL: 1822 case PMC_EV_P6_BUS_TRAN_PWR: 1823 case PMC_EV_P6_BUS_TRANS_P: 1824 case PMC_EV_P6_BUS_TRANS_IO: 1825 case PMC_EV_P6_BUS_TRAN_DEF: 1826 case PMC_EV_P6_BUS_TRAN_BURST: 1827 case PMC_EV_P6_BUS_TRAN_ANY: 1828 case PMC_EV_P6_BUS_TRAN_MEM: 1829 P6MASKSET(any); break; 1830 case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 1831 case PMC_EV_P6_EMON_KNI_PREF_MISS: 1832 P6MASKSET(ekp); break; 1833 case PMC_EV_P6_EMON_KNI_INST_RETIRED: 1834 case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 1835 P6MASKSET(pps); break; 1836 case PMC_EV_P6_MMX_INSTR_TYPE_EXEC: 1837 P6MASKSET(mite); break; 1838 case PMC_EV_P6_FP_MMX_TRANS: 1839 P6MASKSET(fmt); break; 1840 case PMC_EV_P6_SEG_RENAME_STALLS: 1841 case PMC_EV_P6_SEG_REG_RENAMES: 1842 P6MASKSET(sr); break; 1843 case PMC_EV_P6_EMON_EST_TRANS: 1844 P6MASKSET(eet); break; 1845 case PMC_EV_P6_EMON_FUSED_UOPS_RET: 1846 P6MASKSET(efur); break; 1847 case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 1848 P6MASKSET(essir); break; 1849 case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 1850 P6MASKSET(esscir); break; 1851 default: 1852 pmask = NULL; 1853 break; 1854 } 1855 1856 /* Pentium M PMCs have a few events with different semantics */ 1857 if (cpu_info.pm_cputype == PMC_CPU_INTEL_PM) { 1858 if (pe == PMC_EV_P6_L2_LD || 1859 pe == PMC_EV_P6_L2_LINES_IN || 1860 pe == PMC_EV_P6_L2_LINES_OUT) 1861 P6MASKSET(mesihw); 1862 else if (pe == PMC_EV_P6_L2_M_LINES_OUTM) 1863 P6MASKSET(hw); 1864 } 1865 1866 /* Parse additional modifiers if present */ 1867 while ((p = strsep(&ctrspec, ",")) != NULL) { 1868 if (KWPREFIXMATCH(p, P6_KW_CMASK "=")) { 1869 q = strchr(p, '='); 1870 if (*++q == '\0') /* skip '=' */ 1871 return (-1); 1872 count = strtol(q, &e, 0); 1873 if (e == q || *e != '\0') 1874 return (-1); 1875 pmc_config->pm_caps |= PMC_CAP_THRESHOLD; 1876 pmc_config->pm_md.pm_ppro.pm_ppro_config |= 1877 P6_EVSEL_TO_CMASK(count); 1878 } else if (KWMATCH(p, P6_KW_EDGE)) { 1879 pmc_config->pm_caps |= PMC_CAP_EDGE; 1880 } else if (KWMATCH(p, P6_KW_INV)) { 1881 pmc_config->pm_caps |= PMC_CAP_INVERT; 1882 } else if (KWMATCH(p, P6_KW_OS)) { 1883 pmc_config->pm_caps |= PMC_CAP_SYSTEM; 1884 } else if (KWPREFIXMATCH(p, P6_KW_UMASK "=")) { 1885 evmask = 0; 1886 if ((n = pmc_parse_mask(pmask, p, &evmask)) < 0) 1887 return (-1); 1888 if ((pe == PMC_EV_P6_BUS_DRDY_CLOCKS || 1889 pe == PMC_EV_P6_BUS_LOCK_CLOCKS || 1890 pe == PMC_EV_P6_BUS_TRAN_BRD || 1891 pe == PMC_EV_P6_BUS_TRAN_RFO || 1892 pe == PMC_EV_P6_BUS_TRAN_IFETCH || 1893 pe == PMC_EV_P6_BUS_TRAN_INVAL || 1894 pe == PMC_EV_P6_BUS_TRAN_PWR || 1895 pe == PMC_EV_P6_BUS_TRAN_DEF || 1896 pe == PMC_EV_P6_BUS_TRAN_BURST || 1897 pe == PMC_EV_P6_BUS_TRAN_ANY || 1898 pe == PMC_EV_P6_BUS_TRAN_MEM || 1899 pe == PMC_EV_P6_BUS_TRANS_IO || 1900 pe == PMC_EV_P6_BUS_TRANS_P || 1901 pe == PMC_EV_P6_BUS_TRANS_WB || 1902 pe == PMC_EV_P6_EMON_EST_TRANS || 1903 pe == PMC_EV_P6_EMON_FUSED_UOPS_RET || 1904 pe == PMC_EV_P6_EMON_KNI_COMP_INST_RET || 1905 pe == PMC_EV_P6_EMON_KNI_INST_RETIRED || 1906 pe == PMC_EV_P6_EMON_KNI_PREF_DISPATCHED || 1907 pe == PMC_EV_P6_EMON_KNI_PREF_MISS || 1908 pe == PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED || 1909 pe == PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED || 1910 pe == PMC_EV_P6_FP_MMX_TRANS) 1911 && (n > 1)) /* Only one mask keyword is allowed. */ 1912 return (-1); 1913 pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1914 } else if (KWMATCH(p, P6_KW_USR)) { 1915 pmc_config->pm_caps |= PMC_CAP_USER; 1916 } else 1917 return (-1); 1918 } 1919 1920 /* post processing */ 1921 switch (pe) { 1922 1923 /* 1924 * The following events default to an evmask of 0 1925 */ 1926 1927 /* default => 'self' */ 1928 case PMC_EV_P6_BUS_DRDY_CLOCKS: 1929 case PMC_EV_P6_BUS_LOCK_CLOCKS: 1930 case PMC_EV_P6_BUS_TRAN_BRD: 1931 case PMC_EV_P6_BUS_TRAN_RFO: 1932 case PMC_EV_P6_BUS_TRANS_WB: 1933 case PMC_EV_P6_BUS_TRAN_IFETCH: 1934 case PMC_EV_P6_BUS_TRAN_INVAL: 1935 case PMC_EV_P6_BUS_TRAN_PWR: 1936 case PMC_EV_P6_BUS_TRANS_P: 1937 case PMC_EV_P6_BUS_TRANS_IO: 1938 case PMC_EV_P6_BUS_TRAN_DEF: 1939 case PMC_EV_P6_BUS_TRAN_BURST: 1940 case PMC_EV_P6_BUS_TRAN_ANY: 1941 case PMC_EV_P6_BUS_TRAN_MEM: 1942 1943 /* default => 'nta' */ 1944 case PMC_EV_P6_EMON_KNI_PREF_DISPATCHED: 1945 case PMC_EV_P6_EMON_KNI_PREF_MISS: 1946 1947 /* default => 'packed and scalar' */ 1948 case PMC_EV_P6_EMON_KNI_INST_RETIRED: 1949 case PMC_EV_P6_EMON_KNI_COMP_INST_RET: 1950 1951 /* default => 'mmx to fp transitions' */ 1952 case PMC_EV_P6_FP_MMX_TRANS: 1953 1954 /* default => 'SSE Packed Single' */ 1955 case PMC_EV_P6_EMON_SSE_SSE2_INST_RETIRED: 1956 case PMC_EV_P6_EMON_SSE_SSE2_COMP_INST_RETIRED: 1957 1958 /* default => 'all fused micro-ops' */ 1959 case PMC_EV_P6_EMON_FUSED_UOPS_RET: 1960 1961 /* default => 'all transitions' */ 1962 case PMC_EV_P6_EMON_EST_TRANS: 1963 break; 1964 1965 case PMC_EV_P6_MMX_UOPS_EXEC: 1966 evmask = 0x0F; /* only value allowed */ 1967 break; 1968 1969 default: 1970 /* 1971 * For all other events, set the default event mask 1972 * to a logical OR of all the allowed event mask bits. 1973 */ 1974 if (evmask == 0 && pmask) { 1975 for (pm = pmask; pm->pm_name; pm++) 1976 evmask |= pm->pm_value; 1977 pmc_config->pm_caps |= PMC_CAP_QUALIFIER; 1978 } 1979 1980 break; 1981 } 1982 1983 if (pmc_config->pm_caps & PMC_CAP_QUALIFIER) 1984 pmc_config->pm_md.pm_ppro.pm_ppro_config |= 1985 P6_EVSEL_TO_UMASK(evmask); 1986 1987 return (0); 1988} 1989 1990#endif 1991 1992#if defined(__i386__) || defined(__amd64__) 1993static int 1994tsc_allocate_pmc(enum pmc_event pe, char *ctrspec, 1995 struct pmc_op_pmcallocate *pmc_config) 1996{ 1997 if (pe != PMC_EV_TSC_TSC) 1998 return (-1); 1999 2000 /* TSC events must be unqualified. */ 2001 if (ctrspec && *ctrspec != '\0') 2002 return (-1); 2003 2004 pmc_config->pm_md.pm_amd.pm_amd_config = 0; 2005 pmc_config->pm_caps |= PMC_CAP_READ; 2006 2007 return (0); 2008} 2009#endif 2010 2011/* 2012 * Match an event name `name' with its canonical form. 2013 * 2014 * Matches are case insensitive and spaces, periods, underscores and 2015 * hyphen characters are considered to match each other. 2016 * 2017 * Returns 1 for a match, 0 otherwise. 2018 */ 2019 2020static int 2021pmc_match_event_name(const char *name, const char *canonicalname) 2022{ 2023 int cc, nc; 2024 const unsigned char *c, *n; 2025 2026 c = (const unsigned char *) canonicalname; 2027 n = (const unsigned char *) name; 2028 2029 for (; (nc = *n) && (cc = *c); n++, c++) { 2030 2031 if ((nc == ' ' || nc == '_' || nc == '-' || nc == '.') && 2032 (cc == ' ' || cc == '_' || cc == '-' || cc == '.')) 2033 continue; 2034 2035 if (toupper(nc) == toupper(cc)) 2036 continue; 2037 2038 2039 return (0); 2040 } 2041 2042 if (*n == '\0' && *c == '\0') 2043 return (1); 2044 2045 return (0); 2046} 2047 2048/* 2049 * Match an event name against all the event named supported by a 2050 * PMC class. 2051 * 2052 * Returns an event descriptor pointer on match or NULL otherwise. 2053 */ 2054static const struct pmc_event_descr * 2055pmc_match_event_class(const char *name, 2056 const struct pmc_class_descr *pcd) 2057{ 2058 size_t n; 2059 const struct pmc_event_descr *ev; 2060 2061 ev = pcd->pm_evc_event_table; 2062 for (n = 0; n < pcd->pm_evc_event_table_size; n++, ev++) 2063 if (pmc_match_event_name(name, ev->pm_ev_name)) 2064 return (ev); 2065 2066 return (NULL); 2067} 2068 2069static int 2070pmc_mdep_is_compatible_class(enum pmc_class pc) 2071{ 2072 size_t n; 2073 2074 for (n = 0; n < pmc_mdep_class_list_size; n++) 2075 if (pmc_mdep_class_list[n] == pc) 2076 return (1); 2077 return (0); 2078} 2079 2080/* 2081 * API entry points 2082 */ 2083 2084int 2085pmc_allocate(const char *ctrspec, enum pmc_mode mode, 2086 uint32_t flags, int cpu, pmc_id_t *pmcid) 2087{ 2088 size_t n; 2089 int retval; 2090 char *r, *spec_copy; 2091 const char *ctrname; 2092 const struct pmc_event_descr *ev; 2093 const struct pmc_event_alias *alias; 2094 struct pmc_op_pmcallocate pmc_config; 2095 const struct pmc_class_descr *pcd; 2096 2097 spec_copy = NULL; 2098 retval = -1; 2099 2100 if (mode != PMC_MODE_SS && mode != PMC_MODE_TS && 2101 mode != PMC_MODE_SC && mode != PMC_MODE_TC) { 2102 errno = EINVAL; 2103 goto out; 2104 } 2105 2106 /* replace an event alias with the canonical event specifier */ 2107 if (pmc_mdep_event_aliases) 2108 for (alias = pmc_mdep_event_aliases; alias->pm_alias; alias++) 2109 if (!strcasecmp(ctrspec, alias->pm_alias)) { 2110 spec_copy = strdup(alias->pm_spec); 2111 break; 2112 } 2113 2114 if (spec_copy == NULL) 2115 spec_copy = strdup(ctrspec); 2116 2117 r = spec_copy; 2118 ctrname = strsep(&r, ","); 2119 2120 /* 2121 * If a explicit class prefix was given by the user, restrict the 2122 * search for the event to the specified PMC class. 2123 */ 2124 ev = NULL; 2125 for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) { 2126 pcd = pmc_class_table[n]; 2127 if (pmc_mdep_is_compatible_class(pcd->pm_evc_class) && 2128 strncasecmp(ctrname, pcd->pm_evc_name, 2129 pcd->pm_evc_name_size) == 0) { 2130 if ((ev = pmc_match_event_class(ctrname + 2131 pcd->pm_evc_name_size, pcd)) == NULL) { 2132 errno = EINVAL; 2133 goto out; 2134 } 2135 break; 2136 } 2137 } 2138 2139 /* 2140 * Otherwise, search for this event in all compatible PMC 2141 * classes. 2142 */ 2143 for (n = 0; ev == NULL && n < PMC_CLASS_TABLE_SIZE; n++) { 2144 pcd = pmc_class_table[n]; 2145 if (pmc_mdep_is_compatible_class(pcd->pm_evc_class)) 2146 ev = pmc_match_event_class(ctrname, pcd); 2147 } 2148 2149 if (ev == NULL) { 2150 errno = EINVAL; 2151 goto out; 2152 } 2153 2154 bzero(&pmc_config, sizeof(pmc_config)); 2155 pmc_config.pm_ev = ev->pm_ev_code; 2156 pmc_config.pm_class = pcd->pm_evc_class; 2157 pmc_config.pm_cpu = cpu; 2158 pmc_config.pm_mode = mode; 2159 pmc_config.pm_flags = flags; 2160 2161 if (PMC_IS_SAMPLING_MODE(mode)) 2162 pmc_config.pm_caps |= PMC_CAP_INTERRUPT; 2163 2164 if (pcd->pm_evc_allocate_pmc(ev->pm_ev_code, r, &pmc_config) < 0) { 2165 errno = EINVAL; 2166 goto out; 2167 } 2168 2169 if (PMC_CALL(PMCALLOCATE, &pmc_config) < 0) 2170 goto out; 2171 2172 *pmcid = pmc_config.pm_pmcid; 2173 2174 retval = 0; 2175 2176 out: 2177 if (spec_copy) 2178 free(spec_copy); 2179 2180 return (retval); 2181} 2182 2183int 2184pmc_attach(pmc_id_t pmc, pid_t pid) 2185{ 2186 struct pmc_op_pmcattach pmc_attach_args; 2187 2188 pmc_attach_args.pm_pmc = pmc; 2189 pmc_attach_args.pm_pid = pid; 2190 2191 return (PMC_CALL(PMCATTACH, &pmc_attach_args)); 2192} 2193 2194int 2195pmc_capabilities(pmc_id_t pmcid, uint32_t *caps) 2196{ 2197 unsigned int i; 2198 enum pmc_class cl; 2199 2200 cl = PMC_ID_TO_CLASS(pmcid); 2201 for (i = 0; i < cpu_info.pm_nclass; i++) 2202 if (cpu_info.pm_classes[i].pm_class == cl) { 2203 *caps = cpu_info.pm_classes[i].pm_caps; 2204 return (0); 2205 } 2206 errno = EINVAL; 2207 return (-1); 2208} 2209 2210int 2211pmc_configure_logfile(int fd) 2212{ 2213 struct pmc_op_configurelog cla; 2214 2215 cla.pm_logfd = fd; 2216 if (PMC_CALL(CONFIGURELOG, &cla) < 0) 2217 return (-1); 2218 return (0); 2219} 2220 2221int 2222pmc_cpuinfo(const struct pmc_cpuinfo **pci) 2223{ 2224 if (pmc_syscall == -1) { 2225 errno = ENXIO; 2226 return (-1); 2227 } 2228 2229 *pci = &cpu_info; 2230 return (0); 2231} 2232 2233int 2234pmc_detach(pmc_id_t pmc, pid_t pid) 2235{ 2236 struct pmc_op_pmcattach pmc_detach_args; 2237 2238 pmc_detach_args.pm_pmc = pmc; 2239 pmc_detach_args.pm_pid = pid; 2240 return (PMC_CALL(PMCDETACH, &pmc_detach_args)); 2241} 2242 2243int 2244pmc_disable(int cpu, int pmc) 2245{ 2246 struct pmc_op_pmcadmin ssa; 2247 2248 ssa.pm_cpu = cpu; 2249 ssa.pm_pmc = pmc; 2250 ssa.pm_state = PMC_STATE_DISABLED; 2251 return (PMC_CALL(PMCADMIN, &ssa)); 2252} 2253 2254int 2255pmc_enable(int cpu, int pmc) 2256{ 2257 struct pmc_op_pmcadmin ssa; 2258 2259 ssa.pm_cpu = cpu; 2260 ssa.pm_pmc = pmc; 2261 ssa.pm_state = PMC_STATE_FREE; 2262 return (PMC_CALL(PMCADMIN, &ssa)); 2263} 2264 2265/* 2266 * Return a list of events known to a given PMC class. 'cl' is the 2267 * PMC class identifier, 'eventnames' is the returned list of 'const 2268 * char *' pointers pointing to the names of the events. 'nevents' is 2269 * the number of event name pointers returned. 2270 * 2271 * The space for 'eventnames' is allocated using malloc(3). The caller 2272 * is responsible for freeing this space when done. 2273 */ 2274int 2275pmc_event_names_of_class(enum pmc_class cl, const char ***eventnames, 2276 int *nevents) 2277{ 2278 int count; 2279 const char **names; 2280 const struct pmc_event_descr *ev; 2281 2282 switch (cl) 2283 { 2284 case PMC_CLASS_IAF: 2285 ev = iaf_event_table; 2286 count = PMC_EVENT_TABLE_SIZE(iaf); 2287 break; 2288 case PMC_CLASS_IAP: 2289 /* 2290 * Return the most appropriate set of event name 2291 * spellings for the current CPU. 2292 */ 2293 switch (cpu_info.pm_cputype) { 2294 default: 2295 case PMC_CPU_INTEL_ATOM: 2296 ev = atom_event_table; 2297 count = PMC_EVENT_TABLE_SIZE(atom); 2298 break; 2299 case PMC_CPU_INTEL_CORE: 2300 ev = core_event_table; 2301 count = PMC_EVENT_TABLE_SIZE(core); 2302 break; 2303 case PMC_CPU_INTEL_CORE2: 2304 case PMC_CPU_INTEL_CORE2EXTREME: 2305 ev = core2_event_table; 2306 count = PMC_EVENT_TABLE_SIZE(core2); 2307 break; 2308 case PMC_CPU_INTEL_COREI7: 2309 ev = corei7_event_table; 2310 count = PMC_EVENT_TABLE_SIZE(corei7); 2311 break; 2312 } 2313 break; 2314 case PMC_CLASS_TSC: 2315 ev = tsc_event_table; 2316 count = PMC_EVENT_TABLE_SIZE(tsc); 2317 break; 2318 case PMC_CLASS_K7: 2319 ev = k7_event_table; 2320 count = PMC_EVENT_TABLE_SIZE(k7); 2321 break; 2322 case PMC_CLASS_K8: 2323 ev = k8_event_table; 2324 count = PMC_EVENT_TABLE_SIZE(k8); 2325 break; 2326 case PMC_CLASS_P4: 2327 ev = p4_event_table; 2328 count = PMC_EVENT_TABLE_SIZE(p4); 2329 break; 2330 case PMC_CLASS_P5: 2331 ev = p5_event_table; 2332 count = PMC_EVENT_TABLE_SIZE(p5); 2333 break; 2334 case PMC_CLASS_P6: 2335 ev = p6_event_table; 2336 count = PMC_EVENT_TABLE_SIZE(p6); 2337 break; 2338 default: 2339 errno = EINVAL; 2340 return (-1); 2341 } 2342 2343 if ((names = malloc(count * sizeof(const char *))) == NULL) 2344 return (-1); 2345 2346 *eventnames = names; 2347 *nevents = count; 2348 2349 for (;count--; ev++, names++) 2350 *names = ev->pm_ev_name; 2351 return (0); 2352} 2353 2354int 2355pmc_flush_logfile(void) 2356{ 2357 return (PMC_CALL(FLUSHLOG,0)); 2358} 2359 2360int 2361pmc_get_driver_stats(struct pmc_driverstats *ds) 2362{ 2363 struct pmc_op_getdriverstats gms; 2364 2365 if (PMC_CALL(GETDRIVERSTATS, &gms) < 0) 2366 return (-1); 2367 2368 /* copy out fields in the current userland<->library interface */ 2369 ds->pm_intr_ignored = gms.pm_intr_ignored; 2370 ds->pm_intr_processed = gms.pm_intr_processed; 2371 ds->pm_intr_bufferfull = gms.pm_intr_bufferfull; 2372 ds->pm_syscalls = gms.pm_syscalls; 2373 ds->pm_syscall_errors = gms.pm_syscall_errors; 2374 ds->pm_buffer_requests = gms.pm_buffer_requests; 2375 ds->pm_buffer_requests_failed = gms.pm_buffer_requests_failed; 2376 ds->pm_log_sweeps = gms.pm_log_sweeps; 2377 return (0); 2378} 2379 2380int 2381pmc_get_msr(pmc_id_t pmc, uint32_t *msr) 2382{ 2383 struct pmc_op_getmsr gm; 2384 2385 gm.pm_pmcid = pmc; 2386 if (PMC_CALL(PMCGETMSR, &gm) < 0) 2387 return (-1); 2388 *msr = gm.pm_msr; 2389 return (0); 2390} 2391 2392int 2393pmc_init(void) 2394{ 2395 int error, pmc_mod_id; 2396 unsigned int n; 2397 uint32_t abi_version; 2398 struct module_stat pmc_modstat; 2399 struct pmc_op_getcpuinfo op_cpu_info; 2400#if defined(__amd64__) || defined(__i386__) 2401 int cpu_has_iaf_counters; 2402 unsigned int t; 2403#endif 2404 2405 if (pmc_syscall != -1) /* already inited */ 2406 return (0); 2407 2408 /* retrieve the system call number from the KLD */ 2409 if ((pmc_mod_id = modfind(PMC_MODULE_NAME)) < 0) 2410 return (-1); 2411 2412 pmc_modstat.version = sizeof(struct module_stat); 2413 if ((error = modstat(pmc_mod_id, &pmc_modstat)) < 0) 2414 return (-1); 2415 2416 pmc_syscall = pmc_modstat.data.intval; 2417 2418 /* check the kernel module's ABI against our compiled-in version */ 2419 abi_version = PMC_VERSION; 2420 if (PMC_CALL(GETMODULEVERSION, &abi_version) < 0) 2421 return (pmc_syscall = -1); 2422 2423 /* ignore patch & minor numbers for the comparision */ 2424 if ((abi_version & 0xFF000000) != (PMC_VERSION & 0xFF000000)) { 2425 errno = EPROGMISMATCH; 2426 return (pmc_syscall = -1); 2427 } 2428 2429 if (PMC_CALL(GETCPUINFO, &op_cpu_info) < 0) 2430 return (pmc_syscall = -1); 2431 2432 cpu_info.pm_cputype = op_cpu_info.pm_cputype; 2433 cpu_info.pm_ncpu = op_cpu_info.pm_ncpu; 2434 cpu_info.pm_npmc = op_cpu_info.pm_npmc; 2435 cpu_info.pm_nclass = op_cpu_info.pm_nclass; 2436 for (n = 0; n < cpu_info.pm_nclass; n++) 2437 cpu_info.pm_classes[n] = op_cpu_info.pm_classes[n]; 2438 2439 pmc_class_table = malloc(PMC_CLASS_TABLE_SIZE * 2440 sizeof(struct pmc_class_descr *)); 2441 2442 if (pmc_class_table == NULL) 2443 return (-1); 2444 2445 for (n = 0; n < PMC_CLASS_TABLE_SIZE; n++) 2446 pmc_class_table[n] = NULL; 2447 2448 /* 2449 * Fill in the class table. 2450 */ 2451 n = 0; 2452#if defined(__amd64__) || defined(__i386__) 2453 pmc_class_table[n++] = &tsc_class_table_descr; 2454 2455 /* 2456 * Check if this CPU has fixed function counters. 2457 */ 2458 cpu_has_iaf_counters = 0; 2459 for (t = 0; t < cpu_info.pm_nclass; t++) 2460 if (cpu_info.pm_classes[t].pm_class == PMC_CLASS_IAF) 2461 cpu_has_iaf_counters = 1; 2462#endif 2463 2464#define PMC_MDEP_INIT(C) do { \ 2465 pmc_mdep_event_aliases = C##_aliases; \ 2466 pmc_mdep_class_list = C##_pmc_classes; \ 2467 pmc_mdep_class_list_size = \ 2468 PMC_TABLE_SIZE(C##_pmc_classes); \ 2469 } while (0) 2470 2471#define PMC_MDEP_INIT_INTEL_V2(C) do { \ 2472 PMC_MDEP_INIT(C); \ 2473 if (cpu_has_iaf_counters) \ 2474 pmc_class_table[n++] = &iaf_class_table_descr; \ 2475 else \ 2476 pmc_mdep_event_aliases = \ 2477 C##_aliases_without_iaf; \ 2478 pmc_class_table[n] = &C##_class_table_descr; \ 2479 } while (0) 2480 2481 /* Configure the event name parser. */ 2482 switch (cpu_info.pm_cputype) { 2483#if defined(__i386__) 2484 case PMC_CPU_AMD_K7: 2485 PMC_MDEP_INIT(k7); 2486 pmc_class_table[n] = &k7_class_table_descr; 2487 break; 2488 case PMC_CPU_INTEL_P5: 2489 PMC_MDEP_INIT(p5); 2490 pmc_class_table[n] = &p5_class_table_descr; 2491 break; 2492 case PMC_CPU_INTEL_P6: /* P6 ... Pentium M CPUs have */ 2493 case PMC_CPU_INTEL_PII: /* similar PMCs. */ 2494 case PMC_CPU_INTEL_PIII: 2495 case PMC_CPU_INTEL_PM: 2496 PMC_MDEP_INIT(p6); 2497 pmc_class_table[n] = &p6_class_table_descr; 2498 break; 2499#endif 2500#if defined(__amd64__) || defined(__i386__) 2501 case PMC_CPU_AMD_K8: 2502 PMC_MDEP_INIT(k8); 2503 pmc_class_table[n] = &k8_class_table_descr; 2504 break; 2505 case PMC_CPU_INTEL_ATOM: 2506 PMC_MDEP_INIT_INTEL_V2(atom); 2507 break; 2508 case PMC_CPU_INTEL_CORE: 2509 PMC_MDEP_INIT(core); 2510 break; 2511 case PMC_CPU_INTEL_CORE2: 2512 case PMC_CPU_INTEL_CORE2EXTREME: 2513 PMC_MDEP_INIT_INTEL_V2(core2); 2514 break; 2515 case PMC_CPU_INTEL_COREI7: 2516 PMC_MDEP_INIT_INTEL_V2(corei7); 2517 break; 2518 case PMC_CPU_INTEL_PIV: 2519 PMC_MDEP_INIT(p4); 2520 pmc_class_table[n] = &p4_class_table_descr; 2521 break; 2522#endif 2523 2524 2525 default: 2526 /* 2527 * Some kind of CPU this version of the library knows nothing 2528 * about. This shouldn't happen since the abi version check 2529 * should have caught this. 2530 */ 2531 errno = ENXIO; 2532 return (pmc_syscall = -1); 2533 } 2534 2535 return (0); 2536} 2537 2538const char * 2539pmc_name_of_capability(enum pmc_caps cap) 2540{ 2541 int i; 2542 2543 /* 2544 * 'cap' should have a single bit set and should be in 2545 * range. 2546 */ 2547 if ((cap & (cap - 1)) || cap < PMC_CAP_FIRST || 2548 cap > PMC_CAP_LAST) { 2549 errno = EINVAL; 2550 return (NULL); 2551 } 2552 2553 i = ffs(cap); 2554 return (pmc_capability_names[i - 1]); 2555} 2556 2557const char * 2558pmc_name_of_class(enum pmc_class pc) 2559{ 2560 if ((int) pc >= PMC_CLASS_FIRST && 2561 pc <= PMC_CLASS_LAST) 2562 return (pmc_class_names[pc]); 2563 2564 errno = EINVAL; 2565 return (NULL); 2566} 2567 2568const char * 2569pmc_name_of_cputype(enum pmc_cputype cp) 2570{ 2571 size_t n; 2572 2573 for (n = 0; n < PMC_TABLE_SIZE(pmc_cputype_names); n++) 2574 if (cp == pmc_cputype_names[n].pm_cputype) 2575 return (pmc_cputype_names[n].pm_name); 2576 2577 errno = EINVAL; 2578 return (NULL); 2579} 2580 2581const char * 2582pmc_name_of_disposition(enum pmc_disp pd) 2583{ 2584 if ((int) pd >= PMC_DISP_FIRST && 2585 pd <= PMC_DISP_LAST) 2586 return (pmc_disposition_names[pd]); 2587 2588 errno = EINVAL; 2589 return (NULL); 2590} 2591 2592const char * 2593_pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu) 2594{ 2595 const struct pmc_event_descr *ev, *evfence; 2596 2597 ev = evfence = NULL; 2598 if (pe >= PMC_EV_IAF_FIRST && pe <= PMC_EV_IAF_LAST) { 2599 ev = iaf_event_table; 2600 evfence = iaf_event_table + PMC_EVENT_TABLE_SIZE(iaf); 2601 } else if (pe >= PMC_EV_IAP_FIRST && pe <= PMC_EV_IAP_LAST) { 2602 switch (cpu) { 2603 case PMC_CPU_INTEL_ATOM: 2604 ev = atom_event_table; 2605 evfence = atom_event_table + PMC_EVENT_TABLE_SIZE(atom); 2606 break; 2607 case PMC_CPU_INTEL_CORE: 2608 ev = core_event_table; 2609 evfence = core_event_table + PMC_EVENT_TABLE_SIZE(core); 2610 break; 2611 case PMC_CPU_INTEL_CORE2: 2612 case PMC_CPU_INTEL_CORE2EXTREME: 2613 ev = core2_event_table; 2614 evfence = core2_event_table + PMC_EVENT_TABLE_SIZE(core2); 2615 break; 2616 case PMC_CPU_INTEL_COREI7: 2617 ev = corei7_event_table; 2618 evfence = corei7_event_table + PMC_EVENT_TABLE_SIZE(corei7); 2619 break; 2620 default: /* Unknown CPU type. */ 2621 break; 2622 } 2623 } if (pe >= PMC_EV_K7_FIRST && pe <= PMC_EV_K7_LAST) { 2624 ev = k7_event_table; 2625 evfence = k7_event_table + PMC_EVENT_TABLE_SIZE(k7); 2626 } else if (pe >= PMC_EV_K8_FIRST && pe <= PMC_EV_K8_LAST) { 2627 ev = k8_event_table; 2628 evfence = k8_event_table + PMC_EVENT_TABLE_SIZE(k8); 2629 } else if (pe >= PMC_EV_P4_FIRST && pe <= PMC_EV_P4_LAST) { 2630 ev = p4_event_table; 2631 evfence = p4_event_table + PMC_EVENT_TABLE_SIZE(p4); 2632 } else if (pe >= PMC_EV_P5_FIRST && pe <= PMC_EV_P5_LAST) { 2633 ev = p5_event_table; 2634 evfence = p5_event_table + PMC_EVENT_TABLE_SIZE(p5); 2635 } else if (pe >= PMC_EV_P6_FIRST && pe <= PMC_EV_P6_LAST) { 2636 ev = p6_event_table; 2637 evfence = p6_event_table + PMC_EVENT_TABLE_SIZE(p6); 2638 } else if (pe == PMC_EV_TSC_TSC) { 2639 ev = tsc_event_table; 2640 evfence = tsc_event_table + PMC_EVENT_TABLE_SIZE(tsc); 2641 } 2642 2643 for (; ev != evfence; ev++) 2644 if (pe == ev->pm_ev_code) 2645 return (ev->pm_ev_name); 2646 2647 return (NULL); 2648} 2649 2650const char * 2651pmc_name_of_event(enum pmc_event pe) 2652{ 2653 const char *n; 2654 2655 if ((n = _pmc_name_of_event(pe, cpu_info.pm_cputype)) != NULL) 2656 return (n); 2657 2658 errno = EINVAL; 2659 return (NULL); 2660} 2661 2662const char * 2663pmc_name_of_mode(enum pmc_mode pm) 2664{ 2665 if ((int) pm >= PMC_MODE_FIRST && 2666 pm <= PMC_MODE_LAST) 2667 return (pmc_mode_names[pm]); 2668 2669 errno = EINVAL; 2670 return (NULL); 2671} 2672 2673const char * 2674pmc_name_of_state(enum pmc_state ps) 2675{ 2676 if ((int) ps >= PMC_STATE_FIRST && 2677 ps <= PMC_STATE_LAST) 2678 return (pmc_state_names[ps]); 2679 2680 errno = EINVAL; 2681 return (NULL); 2682} 2683 2684int 2685pmc_ncpu(void) 2686{ 2687 if (pmc_syscall == -1) { 2688 errno = ENXIO; 2689 return (-1); 2690 } 2691 2692 return (cpu_info.pm_ncpu); 2693} 2694 2695int 2696pmc_npmc(int cpu) 2697{ 2698 if (pmc_syscall == -1) { 2699 errno = ENXIO; 2700 return (-1); 2701 } 2702 2703 if (cpu < 0 || cpu >= (int) cpu_info.pm_ncpu) { 2704 errno = EINVAL; 2705 return (-1); 2706 } 2707 2708 return (cpu_info.pm_npmc); 2709} 2710 2711int 2712pmc_pmcinfo(int cpu, struct pmc_pmcinfo **ppmci) 2713{ 2714 int nbytes, npmc; 2715 struct pmc_op_getpmcinfo *pmci; 2716 2717 if ((npmc = pmc_npmc(cpu)) < 0) 2718 return (-1); 2719 2720 nbytes = sizeof(struct pmc_op_getpmcinfo) + 2721 npmc * sizeof(struct pmc_info); 2722 2723 if ((pmci = calloc(1, nbytes)) == NULL) 2724 return (-1); 2725 2726 pmci->pm_cpu = cpu; 2727 2728 if (PMC_CALL(GETPMCINFO, pmci) < 0) { 2729 free(pmci); 2730 return (-1); 2731 } 2732 2733 /* kernel<->library, library<->userland interfaces are identical */ 2734 *ppmci = (struct pmc_pmcinfo *) pmci; 2735 return (0); 2736} 2737 2738int 2739pmc_read(pmc_id_t pmc, pmc_value_t *value) 2740{ 2741 struct pmc_op_pmcrw pmc_read_op; 2742 2743 pmc_read_op.pm_pmcid = pmc; 2744 pmc_read_op.pm_flags = PMC_F_OLDVALUE; 2745 pmc_read_op.pm_value = -1; 2746 2747 if (PMC_CALL(PMCRW, &pmc_read_op) < 0) 2748 return (-1); 2749 2750 *value = pmc_read_op.pm_value; 2751 return (0); 2752} 2753 2754int 2755pmc_release(pmc_id_t pmc) 2756{ 2757 struct pmc_op_simple pmc_release_args; 2758 2759 pmc_release_args.pm_pmcid = pmc; 2760 return (PMC_CALL(PMCRELEASE, &pmc_release_args)); 2761} 2762 2763int 2764pmc_rw(pmc_id_t pmc, pmc_value_t newvalue, pmc_value_t *oldvaluep) 2765{ 2766 struct pmc_op_pmcrw pmc_rw_op; 2767 2768 pmc_rw_op.pm_pmcid = pmc; 2769 pmc_rw_op.pm_flags = PMC_F_NEWVALUE | PMC_F_OLDVALUE; 2770 pmc_rw_op.pm_value = newvalue; 2771 2772 if (PMC_CALL(PMCRW, &pmc_rw_op) < 0) 2773 return (-1); 2774 2775 *oldvaluep = pmc_rw_op.pm_value; 2776 return (0); 2777} 2778 2779int 2780pmc_set(pmc_id_t pmc, pmc_value_t value) 2781{ 2782 struct pmc_op_pmcsetcount sc; 2783 2784 sc.pm_pmcid = pmc; 2785 sc.pm_count = value; 2786 2787 if (PMC_CALL(PMCSETCOUNT, &sc) < 0) 2788 return (-1); 2789 return (0); 2790} 2791 2792int 2793pmc_start(pmc_id_t pmc) 2794{ 2795 struct pmc_op_simple pmc_start_args; 2796 2797 pmc_start_args.pm_pmcid = pmc; 2798 return (PMC_CALL(PMCSTART, &pmc_start_args)); 2799} 2800 2801int 2802pmc_stop(pmc_id_t pmc) 2803{ 2804 struct pmc_op_simple pmc_stop_args; 2805 2806 pmc_stop_args.pm_pmcid = pmc; 2807 return (PMC_CALL(PMCSTOP, &pmc_stop_args)); 2808} 2809 2810int 2811pmc_width(pmc_id_t pmcid, uint32_t *width) 2812{ 2813 unsigned int i; 2814 enum pmc_class cl; 2815 2816 cl = PMC_ID_TO_CLASS(pmcid); 2817 for (i = 0; i < cpu_info.pm_nclass; i++) 2818 if (cpu_info.pm_classes[i].pm_class == cl) { 2819 *width = cpu_info.pm_classes[i].pm_width; 2820 return (0); 2821 } 2822 errno = EINVAL; 2823 return (-1); 2824} 2825 2826int 2827pmc_write(pmc_id_t pmc, pmc_value_t value) 2828{ 2829 struct pmc_op_pmcrw pmc_write_op; 2830 2831 pmc_write_op.pm_pmcid = pmc; 2832 pmc_write_op.pm_flags = PMC_F_NEWVALUE; 2833 pmc_write_op.pm_value = value; 2834 return (PMC_CALL(PMCRW, &pmc_write_op)); 2835} 2836 2837int 2838pmc_writelog(uint32_t userdata) 2839{ 2840 struct pmc_op_writelog wl; 2841 2842 wl.pm_userdata = userdata; 2843 return (PMC_CALL(WRITELOG, &wl)); 2844} 2845