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