1 #include "../../../include/linux/hw_breakpoint.h" 2 #include "util.h" 3 #include "../perf.h" 4 #include "parse-options.h" 5 #include "parse-events.h" 6 #include "exec_cmd.h" 7 #include "string.h" 8 #include "cache.h" 9 #include "header.h" 10 #include "debugfs.h" 11 12 int nr_counters; 13 14 struct perf_event_attr attrs[MAX_COUNTERS]; 15 char *filters[MAX_COUNTERS]; 16 17 struct event_symbol { 18 u8 type; 19 u64 config; 20 const char *symbol; 21 const char *alias; 22 }; 23 24 enum event_result { 25 EVT_FAILED, 26 EVT_HANDLED, 27 EVT_HANDLED_ALL 28 }; 29 30 char debugfs_path[MAXPATHLEN]; 31 32 #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x 33 #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x 34 35 static struct event_symbol event_symbols[] = { 36 { CHW(CPU_CYCLES), "cpu-cycles", "cycles" }, 37 { CHW(INSTRUCTIONS), "instructions", "" }, 38 { CHW(CACHE_REFERENCES), "cache-references", "" }, 39 { CHW(CACHE_MISSES), "cache-misses", "" }, 40 { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" }, 41 { CHW(BRANCH_MISSES), "branch-misses", "" }, 42 { CHW(BUS_CYCLES), "bus-cycles", "" }, 43 44 { CSW(CPU_CLOCK), "cpu-clock", "" }, 45 { CSW(TASK_CLOCK), "task-clock", "" }, 46 { CSW(PAGE_FAULTS), "page-faults", "faults" }, 47 { CSW(PAGE_FAULTS_MIN), "minor-faults", "" }, 48 { CSW(PAGE_FAULTS_MAJ), "major-faults", "" }, 49 { CSW(CONTEXT_SWITCHES), "context-switches", "cs" }, 50 { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" }, 51 { CSW(ALIGNMENT_FAULTS), "alignment-faults", "" }, 52 { CSW(EMULATION_FAULTS), "emulation-faults", "" }, 53 }; 54 55 #define __PERF_EVENT_FIELD(config, name) \ 56 ((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT) 57 58 #define PERF_EVENT_RAW(config) __PERF_EVENT_FIELD(config, RAW) 59 #define PERF_EVENT_CONFIG(config) __PERF_EVENT_FIELD(config, CONFIG) 60 #define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE) 61 #define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT) 62 63 static const char *hw_event_names[] = { 64 "cycles", 65 "instructions", 66 "cache-references", 67 "cache-misses", 68 "branches", 69 "branch-misses", 70 "bus-cycles", 71 }; 72 73 static const char *sw_event_names[] = { 74 "cpu-clock-msecs", 75 "task-clock-msecs", 76 "page-faults", 77 "context-switches", 78 "CPU-migrations", 79 "minor-faults", 80 "major-faults", 81 "alignment-faults", 82 "emulation-faults", 83 }; 84 85 #define MAX_ALIASES 8 86 87 static const char *hw_cache[][MAX_ALIASES] = { 88 { "L1-dcache", "l1-d", "l1d", "L1-data", }, 89 { "L1-icache", "l1-i", "l1i", "L1-instruction", }, 90 { "LLC", "L2" }, 91 { "dTLB", "d-tlb", "Data-TLB", }, 92 { "iTLB", "i-tlb", "Instruction-TLB", }, 93 { "branch", "branches", "bpu", "btb", "bpc", }, 94 }; 95 96 static const char *hw_cache_op[][MAX_ALIASES] = { 97 { "load", "loads", "read", }, 98 { "store", "stores", "write", }, 99 { "prefetch", "prefetches", "speculative-read", "speculative-load", }, 100 }; 101 102 static const char *hw_cache_result[][MAX_ALIASES] = { 103 { "refs", "Reference", "ops", "access", }, 104 { "misses", "miss", }, 105 }; 106 107 #define C(x) PERF_COUNT_HW_CACHE_##x 108 #define CACHE_READ (1 << C(OP_READ)) 109 #define CACHE_WRITE (1 << C(OP_WRITE)) 110 #define CACHE_PREFETCH (1 << C(OP_PREFETCH)) 111 #define COP(x) (1 << x) 112 113 /* 114 * cache operartion stat 115 * L1I : Read and prefetch only 116 * ITLB and BPU : Read-only 117 */ 118 static unsigned long hw_cache_stat[C(MAX)] = { 119 [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), 120 [C(L1I)] = (CACHE_READ | CACHE_PREFETCH), 121 [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), 122 [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), 123 [C(ITLB)] = (CACHE_READ), 124 [C(BPU)] = (CACHE_READ), 125 }; 126 127 #define for_each_subsystem(sys_dir, sys_dirent, sys_next) \ 128 while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \ 129 if (sys_dirent.d_type == DT_DIR && \ 130 (strcmp(sys_dirent.d_name, ".")) && \ 131 (strcmp(sys_dirent.d_name, ".."))) 132 133 static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir) 134 { 135 char evt_path[MAXPATHLEN]; 136 int fd; 137 138 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, 139 sys_dir->d_name, evt_dir->d_name); 140 fd = open(evt_path, O_RDONLY); 141 if (fd < 0) 142 return -EINVAL; 143 close(fd); 144 145 return 0; 146 } 147 148 #define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) \ 149 while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \ 150 if (evt_dirent.d_type == DT_DIR && \ 151 (strcmp(evt_dirent.d_name, ".")) && \ 152 (strcmp(evt_dirent.d_name, "..")) && \ 153 (!tp_event_has_id(&sys_dirent, &evt_dirent))) 154 155 #define MAX_EVENT_LENGTH 512 156 157 158 struct tracepoint_path *tracepoint_id_to_path(u64 config) 159 { 160 struct tracepoint_path *path = NULL; 161 DIR *sys_dir, *evt_dir; 162 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 163 char id_buf[4]; 164 int fd; 165 u64 id; 166 char evt_path[MAXPATHLEN]; 167 char dir_path[MAXPATHLEN]; 168 169 if (debugfs_valid_mountpoint(debugfs_path)) 170 return NULL; 171 172 sys_dir = opendir(debugfs_path); 173 if (!sys_dir) 174 return NULL; 175 176 for_each_subsystem(sys_dir, sys_dirent, sys_next) { 177 178 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, 179 sys_dirent.d_name); 180 evt_dir = opendir(dir_path); 181 if (!evt_dir) 182 continue; 183 184 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 185 186 snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, 187 evt_dirent.d_name); 188 fd = open(evt_path, O_RDONLY); 189 if (fd < 0) 190 continue; 191 if (read(fd, id_buf, sizeof(id_buf)) < 0) { 192 close(fd); 193 continue; 194 } 195 close(fd); 196 id = atoll(id_buf); 197 if (id == config) { 198 closedir(evt_dir); 199 closedir(sys_dir); 200 path = zalloc(sizeof(*path)); 201 path->system = malloc(MAX_EVENT_LENGTH); 202 if (!path->system) { 203 free(path); 204 return NULL; 205 } 206 path->name = malloc(MAX_EVENT_LENGTH); 207 if (!path->name) { 208 free(path->system); 209 free(path); 210 return NULL; 211 } 212 strncpy(path->system, sys_dirent.d_name, 213 MAX_EVENT_LENGTH); 214 strncpy(path->name, evt_dirent.d_name, 215 MAX_EVENT_LENGTH); 216 return path; 217 } 218 } 219 closedir(evt_dir); 220 } 221 222 closedir(sys_dir); 223 return NULL; 224 } 225 226 #define TP_PATH_LEN (MAX_EVENT_LENGTH * 2 + 1) 227 static const char *tracepoint_id_to_name(u64 config) 228 { 229 static char buf[TP_PATH_LEN]; 230 struct tracepoint_path *path; 231 232 path = tracepoint_id_to_path(config); 233 if (path) { 234 snprintf(buf, TP_PATH_LEN, "%s:%s", path->system, path->name); 235 free(path->name); 236 free(path->system); 237 free(path); 238 } else 239 snprintf(buf, TP_PATH_LEN, "%s:%s", "unknown", "unknown"); 240 241 return buf; 242 } 243 244 static int is_cache_op_valid(u8 cache_type, u8 cache_op) 245 { 246 if (hw_cache_stat[cache_type] & COP(cache_op)) 247 return 1; /* valid */ 248 else 249 return 0; /* invalid */ 250 } 251 252 static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result) 253 { 254 static char name[50]; 255 256 if (cache_result) { 257 sprintf(name, "%s-%s-%s", hw_cache[cache_type][0], 258 hw_cache_op[cache_op][0], 259 hw_cache_result[cache_result][0]); 260 } else { 261 sprintf(name, "%s-%s", hw_cache[cache_type][0], 262 hw_cache_op[cache_op][1]); 263 } 264 265 return name; 266 } 267 268 const char *event_name(int counter) 269 { 270 u64 config = attrs[counter].config; 271 int type = attrs[counter].type; 272 273 return __event_name(type, config); 274 } 275 276 const char *__event_name(int type, u64 config) 277 { 278 static char buf[32]; 279 280 if (type == PERF_TYPE_RAW) { 281 sprintf(buf, "raw 0x%llx", config); 282 return buf; 283 } 284 285 switch (type) { 286 case PERF_TYPE_HARDWARE: 287 if (config < PERF_COUNT_HW_MAX) 288 return hw_event_names[config]; 289 return "unknown-hardware"; 290 291 case PERF_TYPE_HW_CACHE: { 292 u8 cache_type, cache_op, cache_result; 293 294 cache_type = (config >> 0) & 0xff; 295 if (cache_type > PERF_COUNT_HW_CACHE_MAX) 296 return "unknown-ext-hardware-cache-type"; 297 298 cache_op = (config >> 8) & 0xff; 299 if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX) 300 return "unknown-ext-hardware-cache-op"; 301 302 cache_result = (config >> 16) & 0xff; 303 if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX) 304 return "unknown-ext-hardware-cache-result"; 305 306 if (!is_cache_op_valid(cache_type, cache_op)) 307 return "invalid-cache"; 308 309 return event_cache_name(cache_type, cache_op, cache_result); 310 } 311 312 case PERF_TYPE_SOFTWARE: 313 if (config < PERF_COUNT_SW_MAX) 314 return sw_event_names[config]; 315 return "unknown-software"; 316 317 case PERF_TYPE_TRACEPOINT: 318 return tracepoint_id_to_name(config); 319 320 default: 321 break; 322 } 323 324 return "unknown"; 325 } 326 327 static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int size) 328 { 329 int i, j; 330 int n, longest = -1; 331 332 for (i = 0; i < size; i++) { 333 for (j = 0; j < MAX_ALIASES && names[i][j]; j++) { 334 n = strlen(names[i][j]); 335 if (n > longest && !strncasecmp(*str, names[i][j], n)) 336 longest = n; 337 } 338 if (longest > 0) { 339 *str += longest; 340 return i; 341 } 342 } 343 344 return -1; 345 } 346 347 static enum event_result 348 parse_generic_hw_event(const char **str, struct perf_event_attr *attr) 349 { 350 const char *s = *str; 351 int cache_type = -1, cache_op = -1, cache_result = -1; 352 353 cache_type = parse_aliases(&s, hw_cache, PERF_COUNT_HW_CACHE_MAX); 354 /* 355 * No fallback - if we cannot get a clear cache type 356 * then bail out: 357 */ 358 if (cache_type == -1) 359 return EVT_FAILED; 360 361 while ((cache_op == -1 || cache_result == -1) && *s == '-') { 362 ++s; 363 364 if (cache_op == -1) { 365 cache_op = parse_aliases(&s, hw_cache_op, 366 PERF_COUNT_HW_CACHE_OP_MAX); 367 if (cache_op >= 0) { 368 if (!is_cache_op_valid(cache_type, cache_op)) 369 return 0; 370 continue; 371 } 372 } 373 374 if (cache_result == -1) { 375 cache_result = parse_aliases(&s, hw_cache_result, 376 PERF_COUNT_HW_CACHE_RESULT_MAX); 377 if (cache_result >= 0) 378 continue; 379 } 380 381 /* 382 * Can't parse this as a cache op or result, so back up 383 * to the '-'. 384 */ 385 --s; 386 break; 387 } 388 389 /* 390 * Fall back to reads: 391 */ 392 if (cache_op == -1) 393 cache_op = PERF_COUNT_HW_CACHE_OP_READ; 394 395 /* 396 * Fall back to accesses: 397 */ 398 if (cache_result == -1) 399 cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS; 400 401 attr->config = cache_type | (cache_op << 8) | (cache_result << 16); 402 attr->type = PERF_TYPE_HW_CACHE; 403 404 *str = s; 405 return EVT_HANDLED; 406 } 407 408 static enum event_result 409 parse_single_tracepoint_event(char *sys_name, 410 const char *evt_name, 411 unsigned int evt_length, 412 char *flags, 413 struct perf_event_attr *attr, 414 const char **strp) 415 { 416 char evt_path[MAXPATHLEN]; 417 char id_buf[4]; 418 u64 id; 419 int fd; 420 421 if (flags) { 422 if (!strncmp(flags, "record", strlen(flags))) { 423 attr->sample_type |= PERF_SAMPLE_RAW; 424 attr->sample_type |= PERF_SAMPLE_TIME; 425 attr->sample_type |= PERF_SAMPLE_CPU; 426 } 427 } 428 429 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, 430 sys_name, evt_name); 431 432 fd = open(evt_path, O_RDONLY); 433 if (fd < 0) 434 return EVT_FAILED; 435 436 if (read(fd, id_buf, sizeof(id_buf)) < 0) { 437 close(fd); 438 return EVT_FAILED; 439 } 440 441 close(fd); 442 id = atoll(id_buf); 443 attr->config = id; 444 attr->type = PERF_TYPE_TRACEPOINT; 445 *strp = evt_name + evt_length; 446 447 return EVT_HANDLED; 448 } 449 450 /* sys + ':' + event + ':' + flags*/ 451 #define MAX_EVOPT_LEN (MAX_EVENT_LENGTH * 2 + 2 + 128) 452 static enum event_result 453 parse_multiple_tracepoint_event(char *sys_name, const char *evt_exp, 454 char *flags) 455 { 456 char evt_path[MAXPATHLEN]; 457 struct dirent *evt_ent; 458 DIR *evt_dir; 459 460 snprintf(evt_path, MAXPATHLEN, "%s/%s", debugfs_path, sys_name); 461 evt_dir = opendir(evt_path); 462 463 if (!evt_dir) { 464 perror("Can't open event dir"); 465 return EVT_FAILED; 466 } 467 468 while ((evt_ent = readdir(evt_dir))) { 469 char event_opt[MAX_EVOPT_LEN + 1]; 470 int len; 471 472 if (!strcmp(evt_ent->d_name, ".") 473 || !strcmp(evt_ent->d_name, "..") 474 || !strcmp(evt_ent->d_name, "enable") 475 || !strcmp(evt_ent->d_name, "filter")) 476 continue; 477 478 if (!strglobmatch(evt_ent->d_name, evt_exp)) 479 continue; 480 481 len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s%s%s", sys_name, 482 evt_ent->d_name, flags ? ":" : "", 483 flags ?: ""); 484 if (len < 0) 485 return EVT_FAILED; 486 487 if (parse_events(NULL, event_opt, 0)) 488 return EVT_FAILED; 489 } 490 491 return EVT_HANDLED_ALL; 492 } 493 494 495 static enum event_result parse_tracepoint_event(const char **strp, 496 struct perf_event_attr *attr) 497 { 498 const char *evt_name; 499 char *flags; 500 char sys_name[MAX_EVENT_LENGTH]; 501 unsigned int sys_length, evt_length; 502 503 if (debugfs_valid_mountpoint(debugfs_path)) 504 return 0; 505 506 evt_name = strchr(*strp, ':'); 507 if (!evt_name) 508 return EVT_FAILED; 509 510 sys_length = evt_name - *strp; 511 if (sys_length >= MAX_EVENT_LENGTH) 512 return 0; 513 514 strncpy(sys_name, *strp, sys_length); 515 sys_name[sys_length] = '\0'; 516 evt_name = evt_name + 1; 517 518 flags = strchr(evt_name, ':'); 519 if (flags) { 520 /* split it out: */ 521 evt_name = strndup(evt_name, flags - evt_name); 522 flags++; 523 } 524 525 evt_length = strlen(evt_name); 526 if (evt_length >= MAX_EVENT_LENGTH) 527 return EVT_FAILED; 528 529 if (strpbrk(evt_name, "*?")) { 530 *strp = evt_name + evt_length; 531 return parse_multiple_tracepoint_event(sys_name, evt_name, 532 flags); 533 } else 534 return parse_single_tracepoint_event(sys_name, evt_name, 535 evt_length, flags, 536 attr, strp); 537 } 538 539 static enum event_result 540 parse_breakpoint_type(const char *type, const char **strp, 541 struct perf_event_attr *attr) 542 { 543 int i; 544 545 for (i = 0; i < 3; i++) { 546 if (!type[i]) 547 break; 548 549 switch (type[i]) { 550 case 'r': 551 attr->bp_type |= HW_BREAKPOINT_R; 552 break; 553 case 'w': 554 attr->bp_type |= HW_BREAKPOINT_W; 555 break; 556 case 'x': 557 attr->bp_type |= HW_BREAKPOINT_X; 558 break; 559 default: 560 return EVT_FAILED; 561 } 562 } 563 if (!attr->bp_type) /* Default */ 564 attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W; 565 566 *strp = type + i; 567 568 return EVT_HANDLED; 569 } 570 571 static enum event_result 572 parse_breakpoint_event(const char **strp, struct perf_event_attr *attr) 573 { 574 const char *target; 575 const char *type; 576 char *endaddr; 577 u64 addr; 578 enum event_result err; 579 580 target = strchr(*strp, ':'); 581 if (!target) 582 return EVT_FAILED; 583 584 if (strncmp(*strp, "mem", target - *strp) != 0) 585 return EVT_FAILED; 586 587 target++; 588 589 addr = strtoull(target, &endaddr, 0); 590 if (target == endaddr) 591 return EVT_FAILED; 592 593 attr->bp_addr = addr; 594 *strp = endaddr; 595 596 type = strchr(target, ':'); 597 598 /* If no type is defined, just rw as default */ 599 if (!type) { 600 attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W; 601 } else { 602 err = parse_breakpoint_type(++type, strp, attr); 603 if (err == EVT_FAILED) 604 return EVT_FAILED; 605 } 606 607 /* We should find a nice way to override the access type */ 608 attr->bp_len = HW_BREAKPOINT_LEN_4; 609 attr->type = PERF_TYPE_BREAKPOINT; 610 611 return EVT_HANDLED; 612 } 613 614 static int check_events(const char *str, unsigned int i) 615 { 616 int n; 617 618 n = strlen(event_symbols[i].symbol); 619 if (!strncmp(str, event_symbols[i].symbol, n)) 620 return n; 621 622 n = strlen(event_symbols[i].alias); 623 if (n) 624 if (!strncmp(str, event_symbols[i].alias, n)) 625 return n; 626 return 0; 627 } 628 629 static enum event_result 630 parse_symbolic_event(const char **strp, struct perf_event_attr *attr) 631 { 632 const char *str = *strp; 633 unsigned int i; 634 int n; 635 636 for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { 637 n = check_events(str, i); 638 if (n > 0) { 639 attr->type = event_symbols[i].type; 640 attr->config = event_symbols[i].config; 641 *strp = str + n; 642 return EVT_HANDLED; 643 } 644 } 645 return EVT_FAILED; 646 } 647 648 static enum event_result 649 parse_raw_event(const char **strp, struct perf_event_attr *attr) 650 { 651 const char *str = *strp; 652 u64 config; 653 int n; 654 655 if (*str != 'r') 656 return EVT_FAILED; 657 n = hex2u64(str + 1, &config); 658 if (n > 0) { 659 *strp = str + n + 1; 660 attr->type = PERF_TYPE_RAW; 661 attr->config = config; 662 return EVT_HANDLED; 663 } 664 return EVT_FAILED; 665 } 666 667 static enum event_result 668 parse_numeric_event(const char **strp, struct perf_event_attr *attr) 669 { 670 const char *str = *strp; 671 char *endp; 672 unsigned long type; 673 u64 config; 674 675 type = strtoul(str, &endp, 0); 676 if (endp > str && type < PERF_TYPE_MAX && *endp == ':') { 677 str = endp + 1; 678 config = strtoul(str, &endp, 0); 679 if (endp > str) { 680 attr->type = type; 681 attr->config = config; 682 *strp = endp; 683 return EVT_HANDLED; 684 } 685 } 686 return EVT_FAILED; 687 } 688 689 static enum event_result 690 parse_event_modifier(const char **strp, struct perf_event_attr *attr) 691 { 692 const char *str = *strp; 693 int eu = 1, ek = 1, eh = 1; 694 695 if (*str++ != ':') 696 return 0; 697 while (*str) { 698 if (*str == 'u') 699 eu = 0; 700 else if (*str == 'k') 701 ek = 0; 702 else if (*str == 'h') 703 eh = 0; 704 else 705 break; 706 ++str; 707 } 708 if (str >= *strp + 2) { 709 *strp = str; 710 attr->exclude_user = eu; 711 attr->exclude_kernel = ek; 712 attr->exclude_hv = eh; 713 return 1; 714 } 715 return 0; 716 } 717 718 /* 719 * Each event can have multiple symbolic names. 720 * Symbolic names are (almost) exactly matched. 721 */ 722 static enum event_result 723 parse_event_symbols(const char **str, struct perf_event_attr *attr) 724 { 725 enum event_result ret; 726 727 ret = parse_tracepoint_event(str, attr); 728 if (ret != EVT_FAILED) 729 goto modifier; 730 731 ret = parse_raw_event(str, attr); 732 if (ret != EVT_FAILED) 733 goto modifier; 734 735 ret = parse_numeric_event(str, attr); 736 if (ret != EVT_FAILED) 737 goto modifier; 738 739 ret = parse_symbolic_event(str, attr); 740 if (ret != EVT_FAILED) 741 goto modifier; 742 743 ret = parse_generic_hw_event(str, attr); 744 if (ret != EVT_FAILED) 745 goto modifier; 746 747 ret = parse_breakpoint_event(str, attr); 748 if (ret != EVT_FAILED) 749 goto modifier; 750 751 fprintf(stderr, "invalid or unsupported event: '%s'\n", *str); 752 fprintf(stderr, "Run 'perf list' for a list of valid events\n"); 753 return EVT_FAILED; 754 755 modifier: 756 parse_event_modifier(str, attr); 757 758 return ret; 759 } 760 761 static int store_event_type(const char *orgname) 762 { 763 char filename[PATH_MAX], *c; 764 FILE *file; 765 int id, n; 766 767 sprintf(filename, "%s/", debugfs_path); 768 strncat(filename, orgname, strlen(orgname)); 769 strcat(filename, "/id"); 770 771 c = strchr(filename, ':'); 772 if (c) 773 *c = '/'; 774 775 file = fopen(filename, "r"); 776 if (!file) 777 return 0; 778 n = fscanf(file, "%i", &id); 779 fclose(file); 780 if (n < 1) { 781 pr_err("cannot store event ID\n"); 782 return -EINVAL; 783 } 784 return perf_header__push_event(id, orgname); 785 } 786 787 int parse_events(const struct option *opt __used, const char *str, int unset __used) 788 { 789 struct perf_event_attr attr; 790 enum event_result ret; 791 792 if (strchr(str, ':')) 793 if (store_event_type(str) < 0) 794 return -1; 795 796 for (;;) { 797 if (nr_counters == MAX_COUNTERS) 798 return -1; 799 800 memset(&attr, 0, sizeof(attr)); 801 ret = parse_event_symbols(&str, &attr); 802 if (ret == EVT_FAILED) 803 return -1; 804 805 if (!(*str == 0 || *str == ',' || isspace(*str))) 806 return -1; 807 808 if (ret != EVT_HANDLED_ALL) { 809 attrs[nr_counters] = attr; 810 nr_counters++; 811 } 812 813 if (*str == 0) 814 break; 815 if (*str == ',') 816 ++str; 817 while (isspace(*str)) 818 ++str; 819 } 820 821 return 0; 822 } 823 824 int parse_filter(const struct option *opt __used, const char *str, 825 int unset __used) 826 { 827 int i = nr_counters - 1; 828 int len = strlen(str); 829 830 if (i < 0 || attrs[i].type != PERF_TYPE_TRACEPOINT) { 831 fprintf(stderr, 832 "-F option should follow a -e tracepoint option\n"); 833 return -1; 834 } 835 836 filters[i] = malloc(len + 1); 837 if (!filters[i]) { 838 fprintf(stderr, "not enough memory to hold filter string\n"); 839 return -1; 840 } 841 strcpy(filters[i], str); 842 843 return 0; 844 } 845 846 static const char * const event_type_descriptors[] = { 847 "Hardware event", 848 "Software event", 849 "Tracepoint event", 850 "Hardware cache event", 851 "Raw hardware event descriptor", 852 "Hardware breakpoint", 853 }; 854 855 /* 856 * Print the events from <debugfs_mount_point>/tracing/events 857 */ 858 859 static void print_tracepoint_events(void) 860 { 861 DIR *sys_dir, *evt_dir; 862 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 863 char evt_path[MAXPATHLEN]; 864 char dir_path[MAXPATHLEN]; 865 866 if (debugfs_valid_mountpoint(debugfs_path)) 867 return; 868 869 sys_dir = opendir(debugfs_path); 870 if (!sys_dir) 871 return; 872 873 for_each_subsystem(sys_dir, sys_dirent, sys_next) { 874 875 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, 876 sys_dirent.d_name); 877 evt_dir = opendir(dir_path); 878 if (!evt_dir) 879 continue; 880 881 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 882 snprintf(evt_path, MAXPATHLEN, "%s:%s", 883 sys_dirent.d_name, evt_dirent.d_name); 884 printf(" %-42s [%s]\n", evt_path, 885 event_type_descriptors[PERF_TYPE_TRACEPOINT]); 886 } 887 closedir(evt_dir); 888 } 889 closedir(sys_dir); 890 } 891 892 /* 893 * Print the help text for the event symbols: 894 */ 895 void print_events(void) 896 { 897 struct event_symbol *syms = event_symbols; 898 unsigned int i, type, op, prev_type = -1; 899 char name[40]; 900 901 printf("\n"); 902 printf("List of pre-defined events (to be used in -e):\n"); 903 904 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { 905 type = syms->type; 906 907 if (type != prev_type) 908 printf("\n"); 909 910 if (strlen(syms->alias)) 911 sprintf(name, "%s OR %s", syms->symbol, syms->alias); 912 else 913 strcpy(name, syms->symbol); 914 printf(" %-42s [%s]\n", name, 915 event_type_descriptors[type]); 916 917 prev_type = type; 918 } 919 920 printf("\n"); 921 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { 922 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { 923 /* skip invalid cache type */ 924 if (!is_cache_op_valid(type, op)) 925 continue; 926 927 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { 928 printf(" %-42s [%s]\n", 929 event_cache_name(type, op, i), 930 event_type_descriptors[PERF_TYPE_HW_CACHE]); 931 } 932 } 933 } 934 935 printf("\n"); 936 printf(" %-42s [%s]\n", 937 "rNNN", event_type_descriptors[PERF_TYPE_RAW]); 938 printf("\n"); 939 940 printf(" %-42s [%s]\n", 941 "mem:<addr>[:access]", 942 event_type_descriptors[PERF_TYPE_BREAKPOINT]); 943 printf("\n"); 944 945 print_tracepoint_events(); 946 947 exit(129); 948 } 949