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.c254
1 files changed, 173 insertions, 81 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 74a5af4d33ec..aed38e4b9dfa 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -239,8 +239,11 @@ const char *event_type(int type)
239 return "unknown"; 239 return "unknown";
240} 240}
241 241
242static int add_event(struct list_head **_list, int *idx, 242
243 struct perf_event_attr *attr, char *name) 243
244static int __add_event(struct list_head **_list, int *idx,
245 struct perf_event_attr *attr,
246 char *name, struct cpu_map *cpus)
244{ 247{
245 struct perf_evsel *evsel; 248 struct perf_evsel *evsel;
246 struct list_head *list = *_list; 249 struct list_head *list = *_list;
@@ -260,6 +263,7 @@ static int add_event(struct list_head **_list, int *idx,
260 return -ENOMEM; 263 return -ENOMEM;
261 } 264 }
262 265
266 evsel->cpus = cpus;
263 if (name) 267 if (name)
264 evsel->name = strdup(name); 268 evsel->name = strdup(name);
265 list_add_tail(&evsel->node, list); 269 list_add_tail(&evsel->node, list);
@@ -267,6 +271,12 @@ static int add_event(struct list_head **_list, int *idx,
267 return 0; 271 return 0;
268} 272}
269 273
274static int add_event(struct list_head **_list, int *idx,
275 struct perf_event_attr *attr, char *name)
276{
277 return __add_event(_list, idx, attr, name, NULL);
278}
279
270static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size) 280static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)
271{ 281{
272 int i, j; 282 int i, j;
@@ -308,7 +318,7 @@ int parse_events_add_cache(struct list_head **list, int *idx,
308 for (i = 0; (i < 2) && (op_result[i]); i++) { 318 for (i = 0; (i < 2) && (op_result[i]); i++) {
309 char *str = op_result[i]; 319 char *str = op_result[i];
310 320
311 snprintf(name + n, MAX_NAME_LEN - n, "-%s\n", str); 321 n += snprintf(name + n, MAX_NAME_LEN - n, "-%s", str);
312 322
313 if (cache_op == -1) { 323 if (cache_op == -1) {
314 cache_op = parse_aliases(str, perf_evsel__hw_cache_op, 324 cache_op = parse_aliases(str, perf_evsel__hw_cache_op,
@@ -346,42 +356,28 @@ int parse_events_add_cache(struct list_head **list, int *idx,
346 return add_event(list, idx, &attr, name); 356 return add_event(list, idx, &attr, name);
347} 357}
348 358
349static int add_tracepoint(struct list_head **list, int *idx, 359static int add_tracepoint(struct list_head **listp, int *idx,
350 char *sys_name, char *evt_name) 360 char *sys_name, char *evt_name)
351{ 361{
352 struct perf_event_attr attr; 362 struct perf_evsel *evsel;
353 char name[MAX_NAME_LEN]; 363 struct list_head *list = *listp;
354 char evt_path[MAXPATHLEN];
355 char id_buf[4];
356 u64 id;
357 int fd;
358
359 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path,
360 sys_name, evt_name);
361
362 fd = open(evt_path, O_RDONLY);
363 if (fd < 0)
364 return -1;
365 364
366 if (read(fd, id_buf, sizeof(id_buf)) < 0) { 365 if (!list) {
367 close(fd); 366 list = malloc(sizeof(*list));
368 return -1; 367 if (!list)
368 return -ENOMEM;
369 INIT_LIST_HEAD(list);
369 } 370 }
370 371
371 close(fd); 372 evsel = perf_evsel__newtp(sys_name, evt_name, (*idx)++);
372 id = atoll(id_buf); 373 if (!evsel) {
373 374 free(list);
374 memset(&attr, 0, sizeof(attr)); 375 return -ENOMEM;
375 attr.config = id; 376 }
376 attr.type = PERF_TYPE_TRACEPOINT;
377 attr.sample_type |= PERF_SAMPLE_RAW;
378 attr.sample_type |= PERF_SAMPLE_TIME;
379 attr.sample_type |= PERF_SAMPLE_CPU;
380 attr.sample_type |= PERF_SAMPLE_PERIOD;
381 attr.sample_period = 1;
382 377
383 snprintf(name, MAX_NAME_LEN, "%s:%s", sys_name, evt_name); 378 list_add_tail(&evsel->node, list);
384 return add_event(list, idx, &attr, name); 379 *listp = list;
380 return 0;
385} 381}
386 382
387static int add_tracepoint_multi(struct list_head **list, int *idx, 383static int add_tracepoint_multi(struct list_head **list, int *idx,
@@ -551,7 +547,7 @@ static int config_attr(struct perf_event_attr *attr,
551} 547}
552 548
553int parse_events_add_numeric(struct list_head **list, int *idx, 549int parse_events_add_numeric(struct list_head **list, int *idx,
554 unsigned long type, unsigned long config, 550 u32 type, u64 config,
555 struct list_head *head_config) 551 struct list_head *head_config)
556{ 552{
557 struct perf_event_attr attr; 553 struct perf_event_attr attr;
@@ -607,8 +603,23 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
607 if (perf_pmu__config(pmu, &attr, head_config)) 603 if (perf_pmu__config(pmu, &attr, head_config))
608 return -EINVAL; 604 return -EINVAL;
609 605
610 return add_event(list, idx, &attr, 606 return __add_event(list, idx, &attr, pmu_event_name(head_config),
611 pmu_event_name(head_config)); 607 pmu->cpus);
608}
609
610int parse_events__modifier_group(struct list_head *list,
611 char *event_mod)
612{
613 return parse_events__modifier_event(list, event_mod, true);
614}
615
616void parse_events__set_leader(char *name, struct list_head *list)
617{
618 struct perf_evsel *leader;
619
620 __perf_evlist__set_leader(list);
621 leader = list_entry(list->next, struct perf_evsel, node);
622 leader->group_name = name ? strdup(name) : NULL;
612} 623}
613 624
614void parse_events_update_lists(struct list_head *list_event, 625void parse_events_update_lists(struct list_head *list_event,
@@ -616,21 +627,45 @@ void parse_events_update_lists(struct list_head *list_event,
616{ 627{
617 /* 628 /*
618 * Called for single event definition. Update the 629 * Called for single event definition. Update the
619 * 'all event' list, and reinit the 'signle event' 630 * 'all event' list, and reinit the 'single event'
620 * list, for next event definition. 631 * list, for next event definition.
621 */ 632 */
622 list_splice_tail(list_event, list_all); 633 list_splice_tail(list_event, list_all);
623 free(list_event); 634 free(list_event);
624} 635}
625 636
626int parse_events_modifier(struct list_head *list, char *str) 637struct event_modifier {
638 int eu;
639 int ek;
640 int eh;
641 int eH;
642 int eG;
643 int precise;
644 int exclude_GH;
645};
646
647static int get_event_modifier(struct event_modifier *mod, char *str,
648 struct perf_evsel *evsel)
627{ 649{
628 struct perf_evsel *evsel; 650 int eu = evsel ? evsel->attr.exclude_user : 0;
629 int exclude = 0, exclude_GH = 0; 651 int ek = evsel ? evsel->attr.exclude_kernel : 0;
630 int eu = 0, ek = 0, eh = 0, eH = 0, eG = 0, precise = 0; 652 int eh = evsel ? evsel->attr.exclude_hv : 0;
653 int eH = evsel ? evsel->attr.exclude_host : 0;
654 int eG = evsel ? evsel->attr.exclude_guest : 0;
655 int precise = evsel ? evsel->attr.precise_ip : 0;
631 656
632 if (str == NULL) 657 int exclude = eu | ek | eh;
633 return 0; 658 int exclude_GH = evsel ? evsel->exclude_GH : 0;
659
660 /*
661 * We are here for group and 'GH' was not set as event
662 * modifier and whatever event/group modifier override
663 * default 'GH' setup.
664 */
665 if (evsel && !exclude_GH)
666 eH = eG = 0;
667
668 memset(mod, 0, sizeof(*mod));
634 669
635 while (*str) { 670 while (*str) {
636 if (*str == 'u') { 671 if (*str == 'u') {
@@ -674,13 +709,51 @@ int parse_events_modifier(struct list_head *list, char *str)
674 if (precise > 3) 709 if (precise > 3)
675 return -EINVAL; 710 return -EINVAL;
676 711
712 mod->eu = eu;
713 mod->ek = ek;
714 mod->eh = eh;
715 mod->eH = eH;
716 mod->eG = eG;
717 mod->precise = precise;
718 mod->exclude_GH = exclude_GH;
719 return 0;
720}
721
722int parse_events__modifier_event(struct list_head *list, char *str, bool add)
723{
724 struct perf_evsel *evsel;
725 struct event_modifier mod;
726
727 if (str == NULL)
728 return 0;
729
730 if (!add && get_event_modifier(&mod, str, NULL))
731 return -EINVAL;
732
677 list_for_each_entry(evsel, list, node) { 733 list_for_each_entry(evsel, list, node) {
678 evsel->attr.exclude_user = eu; 734
679 evsel->attr.exclude_kernel = ek; 735 if (add && get_event_modifier(&mod, str, evsel))
680 evsel->attr.exclude_hv = eh; 736 return -EINVAL;
681 evsel->attr.precise_ip = precise; 737
682 evsel->attr.exclude_host = eH; 738 evsel->attr.exclude_user = mod.eu;
683 evsel->attr.exclude_guest = eG; 739 evsel->attr.exclude_kernel = mod.ek;
740 evsel->attr.exclude_hv = mod.eh;
741 evsel->attr.precise_ip = mod.precise;
742 evsel->attr.exclude_host = mod.eH;
743 evsel->attr.exclude_guest = mod.eG;
744 evsel->exclude_GH = mod.exclude_GH;
745 }
746
747 return 0;
748}
749
750int parse_events_name(struct list_head *list, char *name)
751{
752 struct perf_evsel *evsel;
753
754 list_for_each_entry(evsel, list, node) {
755 if (!evsel->name)
756 evsel->name = strdup(name);
684 } 757 }
685 758
686 return 0; 759 return 0;
@@ -730,7 +803,8 @@ int parse_events_terms(struct list_head *terms, const char *str)
730 return ret; 803 return ret;
731} 804}
732 805
733int parse_events(struct perf_evlist *evlist, const char *str, int unset __used) 806int parse_events(struct perf_evlist *evlist, const char *str,
807 int unset __maybe_unused)
734{ 808{
735 struct parse_events_data__events data = { 809 struct parse_events_data__events data = {
736 .list = LIST_HEAD_INIT(data.list), 810 .list = LIST_HEAD_INIT(data.list),
@@ -756,20 +830,20 @@ int parse_events(struct perf_evlist *evlist, const char *str, int unset __used)
756} 830}
757 831
758int parse_events_option(const struct option *opt, const char *str, 832int parse_events_option(const struct option *opt, const char *str,
759 int unset __used) 833 int unset __maybe_unused)
760{ 834{
761 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; 835 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
762 return parse_events(evlist, str, unset); 836 return parse_events(evlist, str, unset);
763} 837}
764 838
765int parse_filter(const struct option *opt, const char *str, 839int parse_filter(const struct option *opt, const char *str,
766 int unset __used) 840 int unset __maybe_unused)
767{ 841{
768 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; 842 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
769 struct perf_evsel *last = NULL; 843 struct perf_evsel *last = NULL;
770 844
771 if (evlist->nr_entries > 0) 845 if (evlist->nr_entries > 0)
772 last = list_entry(evlist->entries.prev, struct perf_evsel, node); 846 last = perf_evlist__last(evlist);
773 847
774 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) { 848 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
775 fprintf(stderr, 849 fprintf(stderr,
@@ -799,7 +873,8 @@ static const char * const event_type_descriptors[] = {
799 * Print the events from <debugfs_mount_point>/tracing/events 873 * Print the events from <debugfs_mount_point>/tracing/events
800 */ 874 */
801 875
802void print_tracepoint_events(const char *subsys_glob, const char *event_glob) 876void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
877 bool name_only)
803{ 878{
804 DIR *sys_dir, *evt_dir; 879 DIR *sys_dir, *evt_dir;
805 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 880 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
@@ -829,6 +904,11 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
829 !strglobmatch(evt_dirent.d_name, event_glob)) 904 !strglobmatch(evt_dirent.d_name, event_glob))
830 continue; 905 continue;
831 906
907 if (name_only) {
908 printf("%s:%s ", sys_dirent.d_name, evt_dirent.d_name);
909 continue;
910 }
911
832 snprintf(evt_path, MAXPATHLEN, "%s:%s", 912 snprintf(evt_path, MAXPATHLEN, "%s:%s",
833 sys_dirent.d_name, evt_dirent.d_name); 913 sys_dirent.d_name, evt_dirent.d_name);
834 printf(" %-50s [%s]\n", evt_path, 914 printf(" %-50s [%s]\n", evt_path,
@@ -906,7 +986,7 @@ void print_events_type(u8 type)
906 __print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX); 986 __print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX);
907} 987}
908 988
909int print_hwcache_events(const char *event_glob) 989int print_hwcache_events(const char *event_glob, bool name_only)
910{ 990{
911 unsigned int type, op, i, printed = 0; 991 unsigned int type, op, i, printed = 0;
912 char name[64]; 992 char name[64];
@@ -923,8 +1003,11 @@ int print_hwcache_events(const char *event_glob)
923 if (event_glob != NULL && !strglobmatch(name, event_glob)) 1003 if (event_glob != NULL && !strglobmatch(name, event_glob))
924 continue; 1004 continue;
925 1005
926 printf(" %-50s [%s]\n", name, 1006 if (name_only)
927 event_type_descriptors[PERF_TYPE_HW_CACHE]); 1007 printf("%s ", name);
1008 else
1009 printf(" %-50s [%s]\n", name,
1010 event_type_descriptors[PERF_TYPE_HW_CACHE]);
928 ++printed; 1011 ++printed;
929 } 1012 }
930 } 1013 }
@@ -934,7 +1017,8 @@ int print_hwcache_events(const char *event_glob)
934} 1017}
935 1018
936static void print_symbol_events(const char *event_glob, unsigned type, 1019static void print_symbol_events(const char *event_glob, unsigned type,
937 struct event_symbol *syms, unsigned max) 1020 struct event_symbol *syms, unsigned max,
1021 bool name_only)
938{ 1022{
939 unsigned i, printed = 0; 1023 unsigned i, printed = 0;
940 char name[MAX_NAME_LEN]; 1024 char name[MAX_NAME_LEN];
@@ -946,6 +1030,11 @@ static void print_symbol_events(const char *event_glob, unsigned type,
946 (syms->alias && strglobmatch(syms->alias, event_glob)))) 1030 (syms->alias && strglobmatch(syms->alias, event_glob))))
947 continue; 1031 continue;
948 1032
1033 if (name_only) {
1034 printf("%s ", syms->symbol);
1035 continue;
1036 }
1037
949 if (strlen(syms->alias)) 1038 if (strlen(syms->alias))
950 snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); 1039 snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
951 else 1040 else
@@ -963,39 +1052,42 @@ static void print_symbol_events(const char *event_glob, unsigned type,
963/* 1052/*
964 * Print the help text for the event symbols: 1053 * Print the help text for the event symbols:
965 */ 1054 */
966void print_events(const char *event_glob) 1055void print_events(const char *event_glob, bool name_only)
967{ 1056{
968 1057 if (!name_only) {
969 printf("\n"); 1058 printf("\n");
970 printf("List of pre-defined events (to be used in -e):\n"); 1059 printf("List of pre-defined events (to be used in -e):\n");
1060 }
971 1061
972 print_symbol_events(event_glob, PERF_TYPE_HARDWARE, 1062 print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
973 event_symbols_hw, PERF_COUNT_HW_MAX); 1063 event_symbols_hw, PERF_COUNT_HW_MAX, name_only);
974 1064
975 print_symbol_events(event_glob, PERF_TYPE_SOFTWARE, 1065 print_symbol_events(event_glob, PERF_TYPE_SOFTWARE,
976 event_symbols_sw, PERF_COUNT_SW_MAX); 1066 event_symbols_sw, PERF_COUNT_SW_MAX, name_only);
977 1067
978 print_hwcache_events(event_glob); 1068 print_hwcache_events(event_glob, name_only);
979 1069
980 if (event_glob != NULL) 1070 if (event_glob != NULL)
981 return; 1071 return;
982 1072
983 printf("\n"); 1073 if (!name_only) {
984 printf(" %-50s [%s]\n", 1074 printf("\n");
985 "rNNN", 1075 printf(" %-50s [%s]\n",
986 event_type_descriptors[PERF_TYPE_RAW]); 1076 "rNNN",
987 printf(" %-50s [%s]\n", 1077 event_type_descriptors[PERF_TYPE_RAW]);
988 "cpu/t1=v1[,t2=v2,t3 ...]/modifier", 1078 printf(" %-50s [%s]\n",
989 event_type_descriptors[PERF_TYPE_RAW]); 1079 "cpu/t1=v1[,t2=v2,t3 ...]/modifier",
990 printf(" (see 'perf list --help' on how to encode it)\n"); 1080 event_type_descriptors[PERF_TYPE_RAW]);
991 printf("\n"); 1081 printf(" (see 'perf list --help' on how to encode it)\n");
992 1082 printf("\n");
993 printf(" %-50s [%s]\n", 1083
994 "mem:<addr>[:access]", 1084 printf(" %-50s [%s]\n",
1085 "mem:<addr>[:access]",
995 event_type_descriptors[PERF_TYPE_BREAKPOINT]); 1086 event_type_descriptors[PERF_TYPE_BREAKPOINT]);
996 printf("\n"); 1087 printf("\n");
1088 }
997 1089
998 print_tracepoint_events(NULL, NULL); 1090 print_tracepoint_events(NULL, NULL, name_only);
999} 1091}
1000 1092
1001int parse_events__is_hardcoded_term(struct parse_events__term *term) 1093int parse_events__is_hardcoded_term(struct parse_events__term *term)
@@ -1005,7 +1097,7 @@ int parse_events__is_hardcoded_term(struct parse_events__term *term)
1005 1097
1006static int new_term(struct parse_events__term **_term, int type_val, 1098static int new_term(struct parse_events__term **_term, int type_val,
1007 int type_term, char *config, 1099 int type_term, char *config,
1008 char *str, long num) 1100 char *str, u64 num)
1009{ 1101{
1010 struct parse_events__term *term; 1102 struct parse_events__term *term;
1011 1103
@@ -1034,7 +1126,7 @@ static int new_term(struct parse_events__term **_term, int type_val,
1034} 1126}
1035 1127
1036int parse_events__term_num(struct parse_events__term **term, 1128int parse_events__term_num(struct parse_events__term **term,
1037 int type_term, char *config, long num) 1129 int type_term, char *config, u64 num)
1038{ 1130{
1039 return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term, 1131 return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term,
1040 config, NULL, num); 1132 config, NULL, num);