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.c174
1 files changed, 131 insertions, 43 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 995fc25db8c6..98125319b158 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -6,7 +6,7 @@
6#include "parse-options.h" 6#include "parse-options.h"
7#include "parse-events.h" 7#include "parse-events.h"
8#include "exec_cmd.h" 8#include "exec_cmd.h"
9#include "string.h" 9#include "linux/string.h"
10#include "symbol.h" 10#include "symbol.h"
11#include "cache.h" 11#include "cache.h"
12#include "header.h" 12#include "header.h"
@@ -15,6 +15,7 @@
15#define YY_EXTRA_TYPE int 15#define YY_EXTRA_TYPE int
16#include "parse-events-flex.h" 16#include "parse-events-flex.h"
17#include "pmu.h" 17#include "pmu.h"
18#include "thread_map.h"
18 19
19#define MAX_NAME_LEN 100 20#define MAX_NAME_LEN 100
20 21
@@ -108,6 +109,10 @@ static struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
108 .symbol = "emulation-faults", 109 .symbol = "emulation-faults",
109 .alias = "", 110 .alias = "",
110 }, 111 },
112 [PERF_COUNT_SW_DUMMY] = {
113 .symbol = "dummy",
114 .alias = "",
115 },
111}; 116};
112 117
113#define __PERF_EVENT_FIELD(config, name) \ 118#define __PERF_EVENT_FIELD(config, name) \
@@ -217,6 +222,29 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
217 return NULL; 222 return NULL;
218} 223}
219 224
225struct tracepoint_path *tracepoint_name_to_path(const char *name)
226{
227 struct tracepoint_path *path = zalloc(sizeof(*path));
228 char *str = strchr(name, ':');
229
230 if (path == NULL || str == NULL) {
231 free(path);
232 return NULL;
233 }
234
235 path->system = strndup(name, str - name);
236 path->name = strdup(str+1);
237
238 if (path->system == NULL || path->name == NULL) {
239 free(path->system);
240 free(path->name);
241 free(path);
242 path = NULL;
243 }
244
245 return path;
246}
247
220const char *event_type(int type) 248const char *event_type(int type)
221{ 249{
222 switch (type) { 250 switch (type) {
@@ -241,40 +269,29 @@ const char *event_type(int type)
241 269
242 270
243 271
244static int __add_event(struct list_head **_list, int *idx, 272static int __add_event(struct list_head *list, int *idx,
245 struct perf_event_attr *attr, 273 struct perf_event_attr *attr,
246 char *name, struct cpu_map *cpus) 274 char *name, struct cpu_map *cpus)
247{ 275{
248 struct perf_evsel *evsel; 276 struct perf_evsel *evsel;
249 struct list_head *list = *_list;
250
251 if (!list) {
252 list = malloc(sizeof(*list));
253 if (!list)
254 return -ENOMEM;
255 INIT_LIST_HEAD(list);
256 }
257 277
258 event_attr_init(attr); 278 event_attr_init(attr);
259 279
260 evsel = perf_evsel__new(attr, (*idx)++); 280 evsel = perf_evsel__new(attr, (*idx)++);
261 if (!evsel) { 281 if (!evsel)
262 free(list);
263 return -ENOMEM; 282 return -ENOMEM;
264 }
265 283
266 evsel->cpus = cpus; 284 evsel->cpus = cpus;
267 if (name) 285 if (name)
268 evsel->name = strdup(name); 286 evsel->name = strdup(name);
269 list_add_tail(&evsel->node, list); 287 list_add_tail(&evsel->node, list);
270 *_list = list;
271 return 0; 288 return 0;
272} 289}
273 290
274static int add_event(struct list_head **_list, int *idx, 291static int add_event(struct list_head *list, int *idx,
275 struct perf_event_attr *attr, char *name) 292 struct perf_event_attr *attr, char *name)
276{ 293{
277 return __add_event(_list, idx, attr, name, NULL); 294 return __add_event(list, idx, attr, name, NULL);
278} 295}
279 296
280static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size) 297static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)
@@ -295,7 +312,7 @@ static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES]
295 return -1; 312 return -1;
296} 313}
297 314
298int parse_events_add_cache(struct list_head **list, int *idx, 315int parse_events_add_cache(struct list_head *list, int *idx,
299 char *type, char *op_result1, char *op_result2) 316 char *type, char *op_result1, char *op_result2)
300{ 317{
301 struct perf_event_attr attr; 318 struct perf_event_attr attr;
@@ -356,31 +373,21 @@ int parse_events_add_cache(struct list_head **list, int *idx,
356 return add_event(list, idx, &attr, name); 373 return add_event(list, idx, &attr, name);
357} 374}
358 375
359static int add_tracepoint(struct list_head **listp, int *idx, 376static int add_tracepoint(struct list_head *list, int *idx,
360 char *sys_name, char *evt_name) 377 char *sys_name, char *evt_name)
361{ 378{
362 struct perf_evsel *evsel; 379 struct perf_evsel *evsel;
363 struct list_head *list = *listp;
364
365 if (!list) {
366 list = malloc(sizeof(*list));
367 if (!list)
368 return -ENOMEM;
369 INIT_LIST_HEAD(list);
370 }
371 380
372 evsel = perf_evsel__newtp(sys_name, evt_name, (*idx)++); 381 evsel = perf_evsel__newtp(sys_name, evt_name, (*idx)++);
373 if (!evsel) { 382 if (!evsel)
374 free(list);
375 return -ENOMEM; 383 return -ENOMEM;
376 }
377 384
378 list_add_tail(&evsel->node, list); 385 list_add_tail(&evsel->node, list);
379 *listp = list; 386
380 return 0; 387 return 0;
381} 388}
382 389
383static int add_tracepoint_multi_event(struct list_head **list, int *idx, 390static int add_tracepoint_multi_event(struct list_head *list, int *idx,
384 char *sys_name, char *evt_name) 391 char *sys_name, char *evt_name)
385{ 392{
386 char evt_path[MAXPATHLEN]; 393 char evt_path[MAXPATHLEN];
@@ -412,7 +419,7 @@ static int add_tracepoint_multi_event(struct list_head **list, int *idx,
412 return ret; 419 return ret;
413} 420}
414 421
415static int add_tracepoint_event(struct list_head **list, int *idx, 422static int add_tracepoint_event(struct list_head *list, int *idx,
416 char *sys_name, char *evt_name) 423 char *sys_name, char *evt_name)
417{ 424{
418 return strpbrk(evt_name, "*?") ? 425 return strpbrk(evt_name, "*?") ?
@@ -420,7 +427,7 @@ static int add_tracepoint_event(struct list_head **list, int *idx,
420 add_tracepoint(list, idx, sys_name, evt_name); 427 add_tracepoint(list, idx, sys_name, evt_name);
421} 428}
422 429
423static int add_tracepoint_multi_sys(struct list_head **list, int *idx, 430static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
424 char *sys_name, char *evt_name) 431 char *sys_name, char *evt_name)
425{ 432{
426 struct dirent *events_ent; 433 struct dirent *events_ent;
@@ -452,7 +459,7 @@ static int add_tracepoint_multi_sys(struct list_head **list, int *idx,
452 return ret; 459 return ret;
453} 460}
454 461
455int parse_events_add_tracepoint(struct list_head **list, int *idx, 462int parse_events_add_tracepoint(struct list_head *list, int *idx,
456 char *sys, char *event) 463 char *sys, char *event)
457{ 464{
458 int ret; 465 int ret;
@@ -507,7 +514,7 @@ do { \
507 return 0; 514 return 0;
508} 515}
509 516
510int parse_events_add_breakpoint(struct list_head **list, int *idx, 517int parse_events_add_breakpoint(struct list_head *list, int *idx,
511 void *ptr, char *type) 518 void *ptr, char *type)
512{ 519{
513 struct perf_event_attr attr; 520 struct perf_event_attr attr;
@@ -588,7 +595,7 @@ static int config_attr(struct perf_event_attr *attr,
588 return 0; 595 return 0;
589} 596}
590 597
591int parse_events_add_numeric(struct list_head **list, int *idx, 598int parse_events_add_numeric(struct list_head *list, int *idx,
592 u32 type, u64 config, 599 u32 type, u64 config,
593 struct list_head *head_config) 600 struct list_head *head_config)
594{ 601{
@@ -621,7 +628,7 @@ static char *pmu_event_name(struct list_head *head_terms)
621 return NULL; 628 return NULL;
622} 629}
623 630
624int parse_events_add_pmu(struct list_head **list, int *idx, 631int parse_events_add_pmu(struct list_head *list, int *idx,
625 char *name, struct list_head *head_config) 632 char *name, struct list_head *head_config)
626{ 633{
627 struct perf_event_attr attr; 634 struct perf_event_attr attr;
@@ -664,6 +671,7 @@ void parse_events__set_leader(char *name, struct list_head *list)
664 leader->group_name = name ? strdup(name) : NULL; 671 leader->group_name = name ? strdup(name) : NULL;
665} 672}
666 673
674/* list_event is assumed to point to malloc'ed memory */
667void parse_events_update_lists(struct list_head *list_event, 675void parse_events_update_lists(struct list_head *list_event,
668 struct list_head *list_all) 676 struct list_head *list_all)
669{ 677{
@@ -684,6 +692,8 @@ struct event_modifier {
684 int eG; 692 int eG;
685 int precise; 693 int precise;
686 int exclude_GH; 694 int exclude_GH;
695 int sample_read;
696 int pinned;
687}; 697};
688 698
689static int get_event_modifier(struct event_modifier *mod, char *str, 699static int get_event_modifier(struct event_modifier *mod, char *str,
@@ -695,6 +705,8 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
695 int eH = evsel ? evsel->attr.exclude_host : 0; 705 int eH = evsel ? evsel->attr.exclude_host : 0;
696 int eG = evsel ? evsel->attr.exclude_guest : 0; 706 int eG = evsel ? evsel->attr.exclude_guest : 0;
697 int precise = evsel ? evsel->attr.precise_ip : 0; 707 int precise = evsel ? evsel->attr.precise_ip : 0;
708 int sample_read = 0;
709 int pinned = evsel ? evsel->attr.pinned : 0;
698 710
699 int exclude = eu | ek | eh; 711 int exclude = eu | ek | eh;
700 int exclude_GH = evsel ? evsel->exclude_GH : 0; 712 int exclude_GH = evsel ? evsel->exclude_GH : 0;
@@ -727,6 +739,10 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
727 /* use of precise requires exclude_guest */ 739 /* use of precise requires exclude_guest */
728 if (!exclude_GH) 740 if (!exclude_GH)
729 eG = 1; 741 eG = 1;
742 } else if (*str == 'S') {
743 sample_read = 1;
744 } else if (*str == 'D') {
745 pinned = 1;
730 } else 746 } else
731 break; 747 break;
732 748
@@ -753,6 +769,9 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
753 mod->eG = eG; 769 mod->eG = eG;
754 mod->precise = precise; 770 mod->precise = precise;
755 mod->exclude_GH = exclude_GH; 771 mod->exclude_GH = exclude_GH;
772 mod->sample_read = sample_read;
773 mod->pinned = pinned;
774
756 return 0; 775 return 0;
757} 776}
758 777
@@ -765,7 +784,7 @@ static int check_modifier(char *str)
765 char *p = str; 784 char *p = str;
766 785
767 /* The sizeof includes 0 byte as well. */ 786 /* The sizeof includes 0 byte as well. */
768 if (strlen(str) > (sizeof("ukhGHppp") - 1)) 787 if (strlen(str) > (sizeof("ukhGHpppSD") - 1))
769 return -1; 788 return -1;
770 789
771 while (*p) { 790 while (*p) {
@@ -803,6 +822,10 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
803 evsel->attr.exclude_host = mod.eH; 822 evsel->attr.exclude_host = mod.eH;
804 evsel->attr.exclude_guest = mod.eG; 823 evsel->attr.exclude_guest = mod.eG;
805 evsel->exclude_GH = mod.exclude_GH; 824 evsel->exclude_GH = mod.exclude_GH;
825 evsel->sample_read = mod.sample_read;
826
827 if (perf_evsel__is_group_leader(evsel))
828 evsel->attr.pinned = mod.pinned;
806 } 829 }
807 830
808 return 0; 831 return 0;
@@ -820,6 +843,32 @@ int parse_events_name(struct list_head *list, char *name)
820 return 0; 843 return 0;
821} 844}
822 845
846static int parse_events__scanner(const char *str, void *data, int start_token);
847
848static int parse_events_fixup(int ret, const char *str, void *data,
849 int start_token)
850{
851 char *o = strdup(str);
852 char *s = NULL;
853 char *t = o;
854 char *p;
855 int len = 0;
856
857 if (!o)
858 return ret;
859 while ((p = strsep(&t, ",")) != NULL) {
860 if (s)
861 str_append(&s, &len, ",");
862 str_append(&s, &len, "cpu/");
863 str_append(&s, &len, p);
864 str_append(&s, &len, "/");
865 }
866 free(o);
867 if (!s)
868 return -ENOMEM;
869 return parse_events__scanner(s, data, start_token);
870}
871
823static int parse_events__scanner(const char *str, void *data, int start_token) 872static int parse_events__scanner(const char *str, void *data, int start_token)
824{ 873{
825 YY_BUFFER_STATE buffer; 874 YY_BUFFER_STATE buffer;
@@ -840,6 +889,8 @@ static int parse_events__scanner(const char *str, void *data, int start_token)
840 parse_events__flush_buffer(buffer, scanner); 889 parse_events__flush_buffer(buffer, scanner);
841 parse_events__delete_buffer(buffer, scanner); 890 parse_events__delete_buffer(buffer, scanner);
842 parse_events_lex_destroy(scanner); 891 parse_events_lex_destroy(scanner);
892 if (ret && !strchr(str, '/'))
893 ret = parse_events_fixup(ret, str, data, start_token);
843 return ret; 894 return ret;
844} 895}
845 896
@@ -1026,6 +1077,33 @@ int is_valid_tracepoint(const char *event_string)
1026 return 0; 1077 return 0;
1027} 1078}
1028 1079
1080static bool is_event_supported(u8 type, unsigned config)
1081{
1082 bool ret = true;
1083 struct perf_evsel *evsel;
1084 struct perf_event_attr attr = {
1085 .type = type,
1086 .config = config,
1087 .disabled = 1,
1088 .exclude_kernel = 1,
1089 };
1090 struct {
1091 struct thread_map map;
1092 int threads[1];
1093 } tmap = {
1094 .map.nr = 1,
1095 .threads = { 0 },
1096 };
1097
1098 evsel = perf_evsel__new(&attr, 0);
1099 if (evsel) {
1100 ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0;
1101 perf_evsel__delete(evsel);
1102 }
1103
1104 return ret;
1105}
1106
1029static void __print_events_type(u8 type, struct event_symbol *syms, 1107static void __print_events_type(u8 type, struct event_symbol *syms,
1030 unsigned max) 1108 unsigned max)
1031{ 1109{
@@ -1033,14 +1111,16 @@ static void __print_events_type(u8 type, struct event_symbol *syms,
1033 unsigned i; 1111 unsigned i;
1034 1112
1035 for (i = 0; i < max ; i++, syms++) { 1113 for (i = 0; i < max ; i++, syms++) {
1114 if (!is_event_supported(type, i))
1115 continue;
1116
1036 if (strlen(syms->alias)) 1117 if (strlen(syms->alias))
1037 snprintf(name, sizeof(name), "%s OR %s", 1118 snprintf(name, sizeof(name), "%s OR %s",
1038 syms->symbol, syms->alias); 1119 syms->symbol, syms->alias);
1039 else 1120 else
1040 snprintf(name, sizeof(name), "%s", syms->symbol); 1121 snprintf(name, sizeof(name), "%s", syms->symbol);
1041 1122
1042 printf(" %-50s [%s]\n", name, 1123 printf(" %-50s [%s]\n", name, event_type_descriptors[type]);
1043 event_type_descriptors[type]);
1044 } 1124 }
1045} 1125}
1046 1126
@@ -1069,6 +1149,10 @@ int print_hwcache_events(const char *event_glob, bool name_only)
1069 if (event_glob != NULL && !strglobmatch(name, event_glob)) 1149 if (event_glob != NULL && !strglobmatch(name, event_glob))
1070 continue; 1150 continue;
1071 1151
1152 if (!is_event_supported(PERF_TYPE_HW_CACHE,
1153 type | (op << 8) | (i << 16)))
1154 continue;
1155
1072 if (name_only) 1156 if (name_only)
1073 printf("%s ", name); 1157 printf("%s ", name);
1074 else 1158 else
@@ -1079,6 +1163,8 @@ int print_hwcache_events(const char *event_glob, bool name_only)
1079 } 1163 }
1080 } 1164 }
1081 1165
1166 if (printed)
1167 printf("\n");
1082 return printed; 1168 return printed;
1083} 1169}
1084 1170
@@ -1096,6 +1182,9 @@ static void print_symbol_events(const char *event_glob, unsigned type,
1096 (syms->alias && strglobmatch(syms->alias, event_glob)))) 1182 (syms->alias && strglobmatch(syms->alias, event_glob))))
1097 continue; 1183 continue;
1098 1184
1185 if (!is_event_supported(type, i))
1186 continue;
1187
1099 if (name_only) { 1188 if (name_only) {
1100 printf("%s ", syms->symbol); 1189 printf("%s ", syms->symbol);
1101 continue; 1190 continue;
@@ -1133,11 +1222,12 @@ void print_events(const char *event_glob, bool name_only)
1133 1222
1134 print_hwcache_events(event_glob, name_only); 1223 print_hwcache_events(event_glob, name_only);
1135 1224
1225 print_pmu_events(event_glob, name_only);
1226
1136 if (event_glob != NULL) 1227 if (event_glob != NULL)
1137 return; 1228 return;
1138 1229
1139 if (!name_only) { 1230 if (!name_only) {
1140 printf("\n");
1141 printf(" %-50s [%s]\n", 1231 printf(" %-50s [%s]\n",
1142 "rNNN", 1232 "rNNN",
1143 event_type_descriptors[PERF_TYPE_RAW]); 1233 event_type_descriptors[PERF_TYPE_RAW]);
@@ -1237,6 +1327,4 @@ void parse_events__free_terms(struct list_head *terms)
1237 1327
1238 list_for_each_entry_safe(term, h, terms, list) 1328 list_for_each_entry_safe(term, h, terms, list)
1239 free(term); 1329 free(term);
1240
1241 free(terms);
1242} 1330}