aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/parse-events.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/parse-events.c')
-rw-r--r--tools/perf/util/parse-events.c204
1 files changed, 154 insertions, 50 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index a587d41ae3c9..d06c66cd358b 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -18,6 +18,12 @@ struct event_symbol {
18 const char *alias; 18 const char *alias;
19}; 19};
20 20
21enum event_result {
22 EVT_FAILED,
23 EVT_HANDLED,
24 EVT_HANDLED_ALL
25};
26
21char debugfs_path[MAXPATHLEN]; 27char debugfs_path[MAXPATHLEN];
22 28
23#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x 29#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
@@ -344,7 +350,7 @@ static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int
344 return -1; 350 return -1;
345} 351}
346 352
347static int 353static enum event_result
348parse_generic_hw_event(const char **str, struct perf_counter_attr *attr) 354parse_generic_hw_event(const char **str, struct perf_counter_attr *attr)
349{ 355{
350 const char *s = *str; 356 const char *s = *str;
@@ -356,7 +362,7 @@ parse_generic_hw_event(const char **str, struct perf_counter_attr *attr)
356 * then bail out: 362 * then bail out:
357 */ 363 */
358 if (cache_type == -1) 364 if (cache_type == -1)
359 return 0; 365 return EVT_FAILED;
360 366
361 while ((cache_op == -1 || cache_result == -1) && *s == '-') { 367 while ((cache_op == -1 || cache_result == -1) && *s == '-') {
362 ++s; 368 ++s;
@@ -402,27 +408,112 @@ parse_generic_hw_event(const char **str, struct perf_counter_attr *attr)
402 attr->type = PERF_TYPE_HW_CACHE; 408 attr->type = PERF_TYPE_HW_CACHE;
403 409
404 *str = s; 410 *str = s;
405 return 1; 411 return EVT_HANDLED;
412}
413
414static enum event_result
415parse_single_tracepoint_event(char *sys_name,
416 const char *evt_name,
417 unsigned int evt_length,
418 char *flags,
419 struct perf_counter_attr *attr,
420 const char **strp)
421{
422 char evt_path[MAXPATHLEN];
423 char id_buf[4];
424 u64 id;
425 int fd;
426
427 if (flags) {
428 if (!strncmp(flags, "record", strlen(flags)))
429 attr->sample_type |= PERF_SAMPLE_RAW;
430 }
431
432 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
433 sys_name, evt_name);
434
435 fd = open(evt_path, O_RDONLY);
436 if (fd < 0)
437 return EVT_FAILED;
438
439 if (read(fd, id_buf, sizeof(id_buf)) < 0) {
440 close(fd);
441 return EVT_FAILED;
442 }
443
444 close(fd);
445 id = atoll(id_buf);
446 attr->config = id;
447 attr->type = PERF_TYPE_TRACEPOINT;
448 *strp = evt_name + evt_length;
449
450 return EVT_HANDLED;
406} 451}
407 452
408static int parse_tracepoint_event(const char **strp, 453/* sys + ':' + event + ':' + flags*/
454#define MAX_EVOPT_LEN (MAX_EVENT_LENGTH * 2 + 2 + 128)
455static enum event_result
456parse_subsystem_tracepoint_event(char *sys_name, char *flags)
457{
458 char evt_path[MAXPATHLEN];
459 struct dirent *evt_ent;
460 DIR *evt_dir;
461
462 snprintf(evt_path, MAXPATHLEN, "%s/%s", debugfs_path, sys_name);
463 evt_dir = opendir(evt_path);
464
465 if (!evt_dir) {
466 perror("Can't open event dir");
467 return EVT_FAILED;
468 }
469
470 while ((evt_ent = readdir(evt_dir))) {
471 char event_opt[MAX_EVOPT_LEN + 1];
472 int len;
473 unsigned int rem = MAX_EVOPT_LEN;
474
475 if (!strcmp(evt_ent->d_name, ".")
476 || !strcmp(evt_ent->d_name, "..")
477 || !strcmp(evt_ent->d_name, "enable")
478 || !strcmp(evt_ent->d_name, "filter"))
479 continue;
480
481 len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s", sys_name,
482 evt_ent->d_name);
483 if (len < 0)
484 return EVT_FAILED;
485
486 rem -= len;
487 if (flags) {
488 if (rem < strlen(flags) + 1)
489 return EVT_FAILED;
490
491 strcat(event_opt, ":");
492 strcat(event_opt, flags);
493 }
494
495 if (parse_events(NULL, event_opt, 0))
496 return EVT_FAILED;
497 }
498
499 return EVT_HANDLED_ALL;
500}
501
502
503static enum event_result parse_tracepoint_event(const char **strp,
409 struct perf_counter_attr *attr) 504 struct perf_counter_attr *attr)
410{ 505{
411 const char *evt_name; 506 const char *evt_name;
412 char *flags; 507 char *flags;
413 char sys_name[MAX_EVENT_LENGTH]; 508 char sys_name[MAX_EVENT_LENGTH];
414 char id_buf[4];
415 int fd;
416 unsigned int sys_length, evt_length; 509 unsigned int sys_length, evt_length;
417 u64 id;
418 char evt_path[MAXPATHLEN];
419 510
420 if (valid_debugfs_mount(debugfs_path)) 511 if (valid_debugfs_mount(debugfs_path))
421 return 0; 512 return 0;
422 513
423 evt_name = strchr(*strp, ':'); 514 evt_name = strchr(*strp, ':');
424 if (!evt_name) 515 if (!evt_name)
425 return 0; 516 return EVT_FAILED;
426 517
427 sys_length = evt_name - *strp; 518 sys_length = evt_name - *strp;
428 if (sys_length >= MAX_EVENT_LENGTH) 519 if (sys_length >= MAX_EVENT_LENGTH)
@@ -436,30 +527,19 @@ static int parse_tracepoint_event(const char **strp,
436 if (flags) { 527 if (flags) {
437 *flags = '\0'; 528 *flags = '\0';
438 flags++; 529 flags++;
439 if (!strncmp(flags, "record", strlen(flags)))
440 attr->sample_type |= PERF_SAMPLE_RAW;
441 } 530 }
442 531
443 evt_length = strlen(evt_name); 532 evt_length = strlen(evt_name);
444 if (evt_length >= MAX_EVENT_LENGTH) 533 if (evt_length >= MAX_EVENT_LENGTH)
445 return 0; 534 return EVT_FAILED;
446 535
447 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, 536 if (!strcmp(evt_name, "*")) {
448 sys_name, evt_name); 537 *strp = evt_name + evt_length;
449 fd = open(evt_path, O_RDONLY); 538 return parse_subsystem_tracepoint_event(sys_name, flags);
450 if (fd < 0) 539 } else
451 return 0; 540 return parse_single_tracepoint_event(sys_name, evt_name,
452 541 evt_length, flags,
453 if (read(fd, id_buf, sizeof(id_buf)) < 0) { 542 attr, strp);
454 close(fd);
455 return 0;
456 }
457 close(fd);
458 id = atoll(id_buf);
459 attr->config = id;
460 attr->type = PERF_TYPE_TRACEPOINT;
461 *strp = evt_name + evt_length;
462 return 1;
463} 543}
464 544
465static int check_events(const char *str, unsigned int i) 545static int check_events(const char *str, unsigned int i)
@@ -477,7 +557,7 @@ static int check_events(const char *str, unsigned int i)
477 return 0; 557 return 0;
478} 558}
479 559
480static int 560static enum event_result
481parse_symbolic_event(const char **strp, struct perf_counter_attr *attr) 561parse_symbolic_event(const char **strp, struct perf_counter_attr *attr)
482{ 562{
483 const char *str = *strp; 563 const char *str = *strp;
@@ -490,31 +570,32 @@ parse_symbolic_event(const char **strp, struct perf_counter_attr *attr)
490 attr->type = event_symbols[i].type; 570 attr->type = event_symbols[i].type;
491 attr->config = event_symbols[i].config; 571 attr->config = event_symbols[i].config;
492 *strp = str + n; 572 *strp = str + n;
493 return 1; 573 return EVT_HANDLED;
494 } 574 }
495 } 575 }
496 return 0; 576 return EVT_FAILED;
497} 577}
498 578
499static int parse_raw_event(const char **strp, struct perf_counter_attr *attr) 579static enum event_result
580parse_raw_event(const char **strp, struct perf_counter_attr *attr)
500{ 581{
501 const char *str = *strp; 582 const char *str = *strp;
502 u64 config; 583 u64 config;
503 int n; 584 int n;
504 585
505 if (*str != 'r') 586 if (*str != 'r')
506 return 0; 587 return EVT_FAILED;
507 n = hex2u64(str + 1, &config); 588 n = hex2u64(str + 1, &config);
508 if (n > 0) { 589 if (n > 0) {
509 *strp = str + n + 1; 590 *strp = str + n + 1;
510 attr->type = PERF_TYPE_RAW; 591 attr->type = PERF_TYPE_RAW;
511 attr->config = config; 592 attr->config = config;
512 return 1; 593 return EVT_HANDLED;
513 } 594 }
514 return 0; 595 return EVT_FAILED;
515} 596}
516 597
517static int 598static enum event_result
518parse_numeric_event(const char **strp, struct perf_counter_attr *attr) 599parse_numeric_event(const char **strp, struct perf_counter_attr *attr)
519{ 600{
520 const char *str = *strp; 601 const char *str = *strp;
@@ -530,13 +611,13 @@ parse_numeric_event(const char **strp, struct perf_counter_attr *attr)
530 attr->type = type; 611 attr->type = type;
531 attr->config = config; 612 attr->config = config;
532 *strp = endp; 613 *strp = endp;
533 return 1; 614 return EVT_HANDLED;
534 } 615 }
535 } 616 }
536 return 0; 617 return EVT_FAILED;
537} 618}
538 619
539static int 620static enum event_result
540parse_event_modifier(const char **strp, struct perf_counter_attr *attr) 621parse_event_modifier(const char **strp, struct perf_counter_attr *attr)
541{ 622{
542 const char *str = *strp; 623 const char *str = *strp;
@@ -569,37 +650,60 @@ parse_event_modifier(const char **strp, struct perf_counter_attr *attr)
569 * Each event can have multiple symbolic names. 650 * Each event can have multiple symbolic names.
570 * Symbolic names are (almost) exactly matched. 651 * Symbolic names are (almost) exactly matched.
571 */ 652 */
572static int parse_event_symbols(const char **str, struct perf_counter_attr *attr) 653static enum event_result
654parse_event_symbols(const char **str, struct perf_counter_attr *attr)
573{ 655{
574 if (!(parse_tracepoint_event(str, attr) || 656 enum event_result ret;
575 parse_raw_event(str, attr) || 657
576 parse_numeric_event(str, attr) || 658 ret = parse_tracepoint_event(str, attr);
577 parse_symbolic_event(str, attr) || 659 if (ret != EVT_FAILED)
578 parse_generic_hw_event(str, attr))) 660 goto modifier;
579 return 0; 661
662 ret = parse_raw_event(str, attr);
663 if (ret != EVT_FAILED)
664 goto modifier;
580 665
666 ret = parse_numeric_event(str, attr);
667 if (ret != EVT_FAILED)
668 goto modifier;
669
670 ret = parse_symbolic_event(str, attr);
671 if (ret != EVT_FAILED)
672 goto modifier;
673
674 ret = parse_generic_hw_event(str, attr);
675 if (ret != EVT_FAILED)
676 goto modifier;
677
678 return EVT_FAILED;
679
680modifier:
581 parse_event_modifier(str, attr); 681 parse_event_modifier(str, attr);
582 682
583 return 1; 683 return ret;
584} 684}
585 685
586int parse_events(const struct option *opt __used, const char *str, int unset __used) 686int parse_events(const struct option *opt __used, const char *str, int unset __used)
587{ 687{
588 struct perf_counter_attr attr; 688 struct perf_counter_attr attr;
689 enum event_result ret;
589 690
590 for (;;) { 691 for (;;) {
591 if (nr_counters == MAX_COUNTERS) 692 if (nr_counters == MAX_COUNTERS)
592 return -1; 693 return -1;
593 694
594 memset(&attr, 0, sizeof(attr)); 695 memset(&attr, 0, sizeof(attr));
595 if (!parse_event_symbols(&str, &attr)) 696 ret = parse_event_symbols(&str, &attr);
697 if (ret == EVT_FAILED)
596 return -1; 698 return -1;
597 699
598 if (!(*str == 0 || *str == ',' || isspace(*str))) 700 if (!(*str == 0 || *str == ',' || isspace(*str)))
599 return -1; 701 return -1;
600 702
601 attrs[nr_counters] = attr; 703 if (ret != EVT_HANDLED_ALL) {
602 nr_counters++; 704 attrs[nr_counters] = attr;
705 nr_counters++;
706 }
603 707
604 if (*str == 0) 708 if (*str == 0)
605 break; 709 break;