diff options
Diffstat (limited to 'tools/perf/util/parse-events.c')
-rw-r--r-- | tools/perf/util/parse-events.c | 155 |
1 files changed, 128 insertions, 27 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 8cfb48cbbea0..9e5dbd66d34d 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 | ||
11 | int nr_counters; | 12 | int nr_counters; |
12 | 13 | ||
13 | struct perf_event_attr attrs[MAX_COUNTERS]; | 14 | struct perf_event_attr attrs[MAX_COUNTERS]; |
15 | char *filters[MAX_COUNTERS]; | ||
14 | 16 | ||
15 | struct event_symbol { | 17 | struct 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 | ||
151 | int 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 | ||
162 | struct tracepoint_path *tracepoint_id_to_path(u64 config) | 158 | struct 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); |
@@ -509,7 +505,7 @@ static enum event_result parse_tracepoint_event(const char **strp, | |||
509 | char sys_name[MAX_EVENT_LENGTH]; | 505 | char sys_name[MAX_EVENT_LENGTH]; |
510 | unsigned int sys_length, evt_length; | 506 | unsigned int sys_length, evt_length; |
511 | 507 | ||
512 | if (valid_debugfs_mount(debugfs_path)) | 508 | if (debugfs_valid_mountpoint(debugfs_path)) |
513 | return 0; | 509 | return 0; |
514 | 510 | ||
515 | evt_name = strchr(*strp, ':'); | 511 | evt_name = strchr(*strp, ':'); |
@@ -544,6 +540,81 @@ static enum event_result parse_tracepoint_event(const char **strp, | |||
544 | attr, strp); | 540 | attr, strp); |
545 | } | 541 | } |
546 | 542 | ||
543 | static enum event_result | ||
544 | parse_breakpoint_type(const char *type, const char **strp, | ||
545 | struct perf_event_attr *attr) | ||
546 | { | ||
547 | int i; | ||
548 | |||
549 | for (i = 0; i < 3; i++) { | ||
550 | if (!type[i]) | ||
551 | break; | ||
552 | |||
553 | switch (type[i]) { | ||
554 | case 'r': | ||
555 | attr->bp_type |= HW_BREAKPOINT_R; | ||
556 | break; | ||
557 | case 'w': | ||
558 | attr->bp_type |= HW_BREAKPOINT_W; | ||
559 | break; | ||
560 | case 'x': | ||
561 | attr->bp_type |= HW_BREAKPOINT_X; | ||
562 | break; | ||
563 | default: | ||
564 | return EVT_FAILED; | ||
565 | } | ||
566 | } | ||
567 | if (!attr->bp_type) /* Default */ | ||
568 | attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W; | ||
569 | |||
570 | *strp = type + i; | ||
571 | |||
572 | return EVT_HANDLED; | ||
573 | } | ||
574 | |||
575 | static enum event_result | ||
576 | parse_breakpoint_event(const char **strp, struct perf_event_attr *attr) | ||
577 | { | ||
578 | const char *target; | ||
579 | const char *type; | ||
580 | char *endaddr; | ||
581 | u64 addr; | ||
582 | enum event_result err; | ||
583 | |||
584 | target = strchr(*strp, ':'); | ||
585 | if (!target) | ||
586 | return EVT_FAILED; | ||
587 | |||
588 | if (strncmp(*strp, "mem", target - *strp) != 0) | ||
589 | return EVT_FAILED; | ||
590 | |||
591 | target++; | ||
592 | |||
593 | addr = strtoull(target, &endaddr, 0); | ||
594 | if (target == endaddr) | ||
595 | return EVT_FAILED; | ||
596 | |||
597 | attr->bp_addr = addr; | ||
598 | *strp = endaddr; | ||
599 | |||
600 | type = strchr(target, ':'); | ||
601 | |||
602 | /* If no type is defined, just rw as default */ | ||
603 | if (!type) { | ||
604 | attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W; | ||
605 | } else { | ||
606 | err = parse_breakpoint_type(++type, strp, attr); | ||
607 | if (err == EVT_FAILED) | ||
608 | return EVT_FAILED; | ||
609 | } | ||
610 | |||
611 | /* We should find a nice way to override the access type */ | ||
612 | attr->bp_len = HW_BREAKPOINT_LEN_4; | ||
613 | attr->type = PERF_TYPE_BREAKPOINT; | ||
614 | |||
615 | return EVT_HANDLED; | ||
616 | } | ||
617 | |||
547 | static int check_events(const char *str, unsigned int i) | 618 | static int check_events(const char *str, unsigned int i) |
548 | { | 619 | { |
549 | int n; | 620 | int n; |
@@ -677,6 +748,12 @@ parse_event_symbols(const char **str, struct perf_event_attr *attr) | |||
677 | if (ret != EVT_FAILED) | 748 | if (ret != EVT_FAILED) |
678 | goto modifier; | 749 | goto modifier; |
679 | 750 | ||
751 | ret = parse_breakpoint_event(str, attr); | ||
752 | if (ret != EVT_FAILED) | ||
753 | goto modifier; | ||
754 | |||
755 | fprintf(stderr, "invalid or unsupported event: '%s'\n", *str); | ||
756 | fprintf(stderr, "Run 'perf list' for a list of valid events\n"); | ||
680 | return EVT_FAILED; | 757 | return EVT_FAILED; |
681 | 758 | ||
682 | modifier: | 759 | modifier: |
@@ -708,7 +785,6 @@ static void store_event_type(const char *orgname) | |||
708 | perf_header__push_event(id, orgname); | 785 | perf_header__push_event(id, orgname); |
709 | } | 786 | } |
710 | 787 | ||
711 | |||
712 | int parse_events(const struct option *opt __used, const char *str, int unset __used) | 788 | int parse_events(const struct option *opt __used, const char *str, int unset __used) |
713 | { | 789 | { |
714 | struct perf_event_attr attr; | 790 | struct perf_event_attr attr; |
@@ -745,6 +821,28 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u | |||
745 | return 0; | 821 | return 0; |
746 | } | 822 | } |
747 | 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 | |||
748 | static const char * const event_type_descriptors[] = { | 846 | static const char * const event_type_descriptors[] = { |
749 | "", | 847 | "", |
750 | "Hardware event", | 848 | "Hardware event", |
@@ -764,7 +862,7 @@ static void print_tracepoint_events(void) | |||
764 | char evt_path[MAXPATHLEN]; | 862 | char evt_path[MAXPATHLEN]; |
765 | char dir_path[MAXPATHLEN]; | 863 | char dir_path[MAXPATHLEN]; |
766 | 864 | ||
767 | if (valid_debugfs_mount(debugfs_path)) | 865 | if (debugfs_valid_mountpoint(debugfs_path)) |
768 | return; | 866 | return; |
769 | 867 | ||
770 | sys_dir = opendir(debugfs_path); | 868 | sys_dir = opendir(debugfs_path); |
@@ -782,7 +880,7 @@ static void print_tracepoint_events(void) | |||
782 | for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { | 880 | for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { |
783 | snprintf(evt_path, MAXPATHLEN, "%s:%s", | 881 | snprintf(evt_path, MAXPATHLEN, "%s:%s", |
784 | sys_dirent.d_name, evt_dirent.d_name); | 882 | sys_dirent.d_name, evt_dirent.d_name); |
785 | fprintf(stderr, " %-42s [%s]\n", evt_path, | 883 | printf(" %-42s [%s]\n", evt_path, |
786 | event_type_descriptors[PERF_TYPE_TRACEPOINT+1]); | 884 | event_type_descriptors[PERF_TYPE_TRACEPOINT+1]); |
787 | } | 885 | } |
788 | closedir(evt_dir); | 886 | closedir(evt_dir); |
@@ -799,8 +897,8 @@ void print_events(void) | |||
799 | unsigned int i, type, op, prev_type = -1; | 897 | unsigned int i, type, op, prev_type = -1; |
800 | char name[40]; | 898 | char name[40]; |
801 | 899 | ||
802 | fprintf(stderr, "\n"); | 900 | printf("\n"); |
803 | fprintf(stderr, "List of pre-defined events (to be used in -e):\n"); | 901 | printf("List of pre-defined events (to be used in -e):\n"); |
804 | 902 | ||
805 | for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { | 903 | for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { |
806 | type = syms->type + 1; | 904 | type = syms->type + 1; |
@@ -808,19 +906,19 @@ void print_events(void) | |||
808 | type = 0; | 906 | type = 0; |
809 | 907 | ||
810 | if (type != prev_type) | 908 | if (type != prev_type) |
811 | fprintf(stderr, "\n"); | 909 | printf("\n"); |
812 | 910 | ||
813 | if (strlen(syms->alias)) | 911 | if (strlen(syms->alias)) |
814 | sprintf(name, "%s OR %s", syms->symbol, syms->alias); | 912 | sprintf(name, "%s OR %s", syms->symbol, syms->alias); |
815 | else | 913 | else |
816 | strcpy(name, syms->symbol); | 914 | strcpy(name, syms->symbol); |
817 | fprintf(stderr, " %-42s [%s]\n", name, | 915 | printf(" %-42s [%s]\n", name, |
818 | event_type_descriptors[type]); | 916 | event_type_descriptors[type]); |
819 | 917 | ||
820 | prev_type = type; | 918 | prev_type = type; |
821 | } | 919 | } |
822 | 920 | ||
823 | fprintf(stderr, "\n"); | 921 | printf("\n"); |
824 | for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { | 922 | for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { |
825 | for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { | 923 | for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { |
826 | /* skip invalid cache type */ | 924 | /* skip invalid cache type */ |
@@ -828,17 +926,20 @@ void print_events(void) | |||
828 | continue; | 926 | continue; |
829 | 927 | ||
830 | for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { | 928 | for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { |
831 | fprintf(stderr, " %-42s [%s]\n", | 929 | printf(" %-42s [%s]\n", |
832 | event_cache_name(type, op, i), | 930 | event_cache_name(type, op, i), |
833 | event_type_descriptors[4]); | 931 | event_type_descriptors[4]); |
834 | } | 932 | } |
835 | } | 933 | } |
836 | } | 934 | } |
837 | 935 | ||
838 | fprintf(stderr, "\n"); | 936 | printf("\n"); |
839 | fprintf(stderr, " %-42s [raw hardware event descriptor]\n", | 937 | printf(" %-42s [raw hardware event descriptor]\n", |
840 | "rNNN"); | 938 | "rNNN"); |
841 | fprintf(stderr, "\n"); | 939 | printf("\n"); |
940 | |||
941 | printf(" %-42s [hardware breakpoint]\n", "mem:<addr>[:access]"); | ||
942 | printf("\n"); | ||
842 | 943 | ||
843 | print_tracepoint_events(); | 944 | print_tracepoint_events(); |
844 | 945 | ||