aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/parse-events.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /tools/perf/util/parse-events.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'tools/perf/util/parse-events.c')
-rw-r--r--tools/perf/util/parse-events.c214
1 files changed, 158 insertions, 56 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 8cfb48cbbea0..05d0c5c2030c 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1,4 +1,4 @@
1 1#include "../../../include/linux/hw_breakpoint.h"
2#include "util.h" 2#include "util.h"
3#include "../perf.h" 3#include "../perf.h"
4#include "parse-options.h" 4#include "parse-options.h"
@@ -7,10 +7,12 @@
7#include "string.h" 7#include "string.h"
8#include "cache.h" 8#include "cache.h"
9#include "header.h" 9#include "header.h"
10#include "debugfs.h"
10 11
11int nr_counters; 12int nr_counters;
12 13
13struct perf_event_attr attrs[MAX_COUNTERS]; 14struct perf_event_attr attrs[MAX_COUNTERS];
15char *filters[MAX_COUNTERS];
14 16
15struct event_symbol { 17struct event_symbol {
16 u8 type; 18 u8 type;
@@ -46,6 +48,8 @@ static struct event_symbol event_symbols[] = {
46 { CSW(PAGE_FAULTS_MAJ), "major-faults", "" }, 48 { CSW(PAGE_FAULTS_MAJ), "major-faults", "" },
47 { CSW(CONTEXT_SWITCHES), "context-switches", "cs" }, 49 { CSW(CONTEXT_SWITCHES), "context-switches", "cs" },
48 { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" }, 50 { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" },
51 { CSW(ALIGNMENT_FAULTS), "alignment-faults", "" },
52 { CSW(EMULATION_FAULTS), "emulation-faults", "" },
49}; 53};
50 54
51#define __PERF_EVENT_FIELD(config, name) \ 55#define __PERF_EVENT_FIELD(config, name) \
@@ -74,6 +78,8 @@ static const char *sw_event_names[] = {
74 "CPU-migrations", 78 "CPU-migrations",
75 "minor-faults", 79 "minor-faults",
76 "major-faults", 80 "major-faults",
81 "alignment-faults",
82 "emulation-faults",
77}; 83};
78 84
79#define MAX_ALIASES 8 85#define MAX_ALIASES 8
@@ -148,16 +154,6 @@ static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
148 154
149#define MAX_EVENT_LENGTH 512 155#define MAX_EVENT_LENGTH 512
150 156
151int valid_debugfs_mount(const char *debugfs)
152{
153 struct statfs st_fs;
154
155 if (statfs(debugfs, &st_fs) < 0)
156 return -ENOENT;
157 else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
158 return -ENOENT;
159 return 0;
160}
161 157
162struct tracepoint_path *tracepoint_id_to_path(u64 config) 158struct tracepoint_path *tracepoint_id_to_path(u64 config)
163{ 159{
@@ -170,7 +166,7 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
170 char evt_path[MAXPATHLEN]; 166 char evt_path[MAXPATHLEN];
171 char dir_path[MAXPATHLEN]; 167 char dir_path[MAXPATHLEN];
172 168
173 if (valid_debugfs_mount(debugfs_path)) 169 if (debugfs_valid_mountpoint(debugfs_path))
174 return NULL; 170 return NULL;
175 171
176 sys_dir = opendir(debugfs_path); 172 sys_dir = opendir(debugfs_path);
@@ -201,7 +197,7 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
201 if (id == config) { 197 if (id == config) {
202 closedir(evt_dir); 198 closedir(evt_dir);
203 closedir(sys_dir); 199 closedir(sys_dir);
204 path = calloc(1, sizeof(path)); 200 path = zalloc(sizeof(*path));
205 path->system = malloc(MAX_EVENT_LENGTH); 201 path->system = malloc(MAX_EVENT_LENGTH);
206 if (!path->system) { 202 if (!path->system) {
207 free(path); 203 free(path);
@@ -454,7 +450,8 @@ parse_single_tracepoint_event(char *sys_name,
454/* sys + ':' + event + ':' + flags*/ 450/* sys + ':' + event + ':' + flags*/
455#define MAX_EVOPT_LEN (MAX_EVENT_LENGTH * 2 + 2 + 128) 451#define MAX_EVOPT_LEN (MAX_EVENT_LENGTH * 2 + 2 + 128)
456static enum event_result 452static enum event_result
457parse_subsystem_tracepoint_event(char *sys_name, char *flags) 453parse_multiple_tracepoint_event(char *sys_name, const char *evt_exp,
454 char *flags)
458{ 455{
459 char evt_path[MAXPATHLEN]; 456 char evt_path[MAXPATHLEN];
460 struct dirent *evt_ent; 457 struct dirent *evt_ent;
@@ -471,7 +468,6 @@ parse_subsystem_tracepoint_event(char *sys_name, char *flags)
471 while ((evt_ent = readdir(evt_dir))) { 468 while ((evt_ent = readdir(evt_dir))) {
472 char event_opt[MAX_EVOPT_LEN + 1]; 469 char event_opt[MAX_EVOPT_LEN + 1];
473 int len; 470 int len;
474 unsigned int rem = MAX_EVOPT_LEN;
475 471
476 if (!strcmp(evt_ent->d_name, ".") 472 if (!strcmp(evt_ent->d_name, ".")
477 || !strcmp(evt_ent->d_name, "..") 473 || !strcmp(evt_ent->d_name, "..")
@@ -479,20 +475,15 @@ parse_subsystem_tracepoint_event(char *sys_name, char *flags)
479 || !strcmp(evt_ent->d_name, "filter")) 475 || !strcmp(evt_ent->d_name, "filter"))
480 continue; 476 continue;
481 477
482 len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s", sys_name, 478 if (!strglobmatch(evt_ent->d_name, evt_exp))
483 evt_ent->d_name); 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) 484 if (len < 0)
485 return EVT_FAILED; 485 return EVT_FAILED;
486 486
487 rem -= len;
488 if (flags) {
489 if (rem < strlen(flags) + 1)
490 return EVT_FAILED;
491
492 strcat(event_opt, ":");
493 strcat(event_opt, flags);
494 }
495
496 if (parse_events(NULL, event_opt, 0)) 487 if (parse_events(NULL, event_opt, 0))
497 return EVT_FAILED; 488 return EVT_FAILED;
498 } 489 }
@@ -509,7 +500,7 @@ static enum event_result parse_tracepoint_event(const char **strp,
509 char sys_name[MAX_EVENT_LENGTH]; 500 char sys_name[MAX_EVENT_LENGTH];
510 unsigned int sys_length, evt_length; 501 unsigned int sys_length, evt_length;
511 502
512 if (valid_debugfs_mount(debugfs_path)) 503 if (debugfs_valid_mountpoint(debugfs_path))
513 return 0; 504 return 0;
514 505
515 evt_name = strchr(*strp, ':'); 506 evt_name = strchr(*strp, ':');
@@ -535,15 +526,91 @@ static enum event_result parse_tracepoint_event(const char **strp,
535 if (evt_length >= MAX_EVENT_LENGTH) 526 if (evt_length >= MAX_EVENT_LENGTH)
536 return EVT_FAILED; 527 return EVT_FAILED;
537 528
538 if (!strcmp(evt_name, "*")) { 529 if (strpbrk(evt_name, "*?")) {
539 *strp = evt_name + evt_length; 530 *strp = evt_name + evt_length;
540 return parse_subsystem_tracepoint_event(sys_name, flags); 531 return parse_multiple_tracepoint_event(sys_name, evt_name,
532 flags);
541 } else 533 } else
542 return parse_single_tracepoint_event(sys_name, evt_name, 534 return parse_single_tracepoint_event(sys_name, evt_name,
543 evt_length, flags, 535 evt_length, flags,
544 attr, strp); 536 attr, strp);
545} 537}
546 538
539static enum event_result
540parse_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
571static enum event_result
572parse_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
547static int check_events(const char *str, unsigned int i) 614static int check_events(const char *str, unsigned int i)
548{ 615{
549 int n; 616 int n;
@@ -677,6 +744,12 @@ parse_event_symbols(const char **str, struct perf_event_attr *attr)
677 if (ret != EVT_FAILED) 744 if (ret != EVT_FAILED)
678 goto modifier; 745 goto modifier;
679 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");
680 return EVT_FAILED; 753 return EVT_FAILED;
681 754
682modifier: 755modifier:
@@ -685,11 +758,11 @@ modifier:
685 return ret; 758 return ret;
686} 759}
687 760
688static void store_event_type(const char *orgname) 761static int store_event_type(const char *orgname)
689{ 762{
690 char filename[PATH_MAX], *c; 763 char filename[PATH_MAX], *c;
691 FILE *file; 764 FILE *file;
692 int id; 765 int id, n;
693 766
694 sprintf(filename, "%s/", debugfs_path); 767 sprintf(filename, "%s/", debugfs_path);
695 strncat(filename, orgname, strlen(orgname)); 768 strncat(filename, orgname, strlen(orgname));
@@ -701,21 +774,24 @@ static void store_event_type(const char *orgname)
701 774
702 file = fopen(filename, "r"); 775 file = fopen(filename, "r");
703 if (!file) 776 if (!file)
704 return; 777 return 0;
705 if (fscanf(file, "%i", &id) < 1) 778 n = fscanf(file, "%i", &id);
706 die("cannot store event ID");
707 fclose(file); 779 fclose(file);
708 perf_header__push_event(id, orgname); 780 if (n < 1) {
781 pr_err("cannot store event ID\n");
782 return -EINVAL;
783 }
784 return perf_header__push_event(id, orgname);
709} 785}
710 786
711
712int parse_events(const struct option *opt __used, const char *str, int unset __used) 787int parse_events(const struct option *opt __used, const char *str, int unset __used)
713{ 788{
714 struct perf_event_attr attr; 789 struct perf_event_attr attr;
715 enum event_result ret; 790 enum event_result ret;
716 791
717 if (strchr(str, ':')) 792 if (strchr(str, ':'))
718 store_event_type(str); 793 if (store_event_type(str) < 0)
794 return -1;
719 795
720 for (;;) { 796 for (;;) {
721 if (nr_counters == MAX_COUNTERS) 797 if (nr_counters == MAX_COUNTERS)
@@ -745,12 +821,35 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
745 return 0; 821 return 0;
746} 822}
747 823
824int 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
748static const char * const event_type_descriptors[] = { 846static const char * const event_type_descriptors[] = {
749 "",
750 "Hardware event", 847 "Hardware event",
751 "Software event", 848 "Software event",
752 "Tracepoint event", 849 "Tracepoint event",
753 "Hardware cache event", 850 "Hardware cache event",
851 "Raw hardware event descriptor",
852 "Hardware breakpoint",
754}; 853};
755 854
756/* 855/*
@@ -764,7 +863,7 @@ static void print_tracepoint_events(void)
764 char evt_path[MAXPATHLEN]; 863 char evt_path[MAXPATHLEN];
765 char dir_path[MAXPATHLEN]; 864 char dir_path[MAXPATHLEN];
766 865
767 if (valid_debugfs_mount(debugfs_path)) 866 if (debugfs_valid_mountpoint(debugfs_path))
768 return; 867 return;
769 868
770 sys_dir = opendir(debugfs_path); 869 sys_dir = opendir(debugfs_path);
@@ -782,8 +881,8 @@ static void print_tracepoint_events(void)
782 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 881 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
783 snprintf(evt_path, MAXPATHLEN, "%s:%s", 882 snprintf(evt_path, MAXPATHLEN, "%s:%s",
784 sys_dirent.d_name, evt_dirent.d_name); 883 sys_dirent.d_name, evt_dirent.d_name);
785 fprintf(stderr, " %-42s [%s]\n", evt_path, 884 printf(" %-42s [%s]\n", evt_path,
786 event_type_descriptors[PERF_TYPE_TRACEPOINT+1]); 885 event_type_descriptors[PERF_TYPE_TRACEPOINT]);
787 } 886 }
788 closedir(evt_dir); 887 closedir(evt_dir);
789 } 888 }
@@ -799,28 +898,26 @@ void print_events(void)
799 unsigned int i, type, op, prev_type = -1; 898 unsigned int i, type, op, prev_type = -1;
800 char name[40]; 899 char name[40];
801 900
802 fprintf(stderr, "\n"); 901 printf("\n");
803 fprintf(stderr, "List of pre-defined events (to be used in -e):\n"); 902 printf("List of pre-defined events (to be used in -e):\n");
804 903
805 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { 904 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
806 type = syms->type + 1; 905 type = syms->type;
807 if (type >= ARRAY_SIZE(event_type_descriptors))
808 type = 0;
809 906
810 if (type != prev_type) 907 if (type != prev_type)
811 fprintf(stderr, "\n"); 908 printf("\n");
812 909
813 if (strlen(syms->alias)) 910 if (strlen(syms->alias))
814 sprintf(name, "%s OR %s", syms->symbol, syms->alias); 911 sprintf(name, "%s OR %s", syms->symbol, syms->alias);
815 else 912 else
816 strcpy(name, syms->symbol); 913 strcpy(name, syms->symbol);
817 fprintf(stderr, " %-42s [%s]\n", name, 914 printf(" %-42s [%s]\n", name,
818 event_type_descriptors[type]); 915 event_type_descriptors[type]);
819 916
820 prev_type = type; 917 prev_type = type;
821 } 918 }
822 919
823 fprintf(stderr, "\n"); 920 printf("\n");
824 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { 921 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
825 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { 922 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
826 /* skip invalid cache type */ 923 /* skip invalid cache type */
@@ -828,17 +925,22 @@ void print_events(void)
828 continue; 925 continue;
829 926
830 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { 927 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
831 fprintf(stderr, " %-42s [%s]\n", 928 printf(" %-42s [%s]\n",
832 event_cache_name(type, op, i), 929 event_cache_name(type, op, i),
833 event_type_descriptors[4]); 930 event_type_descriptors[PERF_TYPE_HW_CACHE]);
834 } 931 }
835 } 932 }
836 } 933 }
837 934
838 fprintf(stderr, "\n"); 935 printf("\n");
839 fprintf(stderr, " %-42s [raw hardware event descriptor]\n", 936 printf(" %-42s [%s]\n",
840 "rNNN"); 937 "rNNN", event_type_descriptors[PERF_TYPE_RAW]);
841 fprintf(stderr, "\n"); 938 printf("\n");
939
940 printf(" %-42s [%s]\n",
941 "mem:<addr>[:access]",
942 event_type_descriptors[PERF_TYPE_BREAKPOINT]);
943 printf("\n");
842 944
843 print_tracepoint_events(); 945 print_tracepoint_events();
844 946