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