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.c317
1 files changed, 274 insertions, 43 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 4f7b0efdde2f..4c19d5e79d8c 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -279,7 +279,24 @@ const char *event_type(int type)
279 return "unknown"; 279 return "unknown";
280} 280}
281 281
282static int parse_events__is_name_term(struct parse_events_term *term)
283{
284 return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME;
285}
286
287static char *get_config_name(struct list_head *head_terms)
288{
289 struct parse_events_term *term;
290
291 if (!head_terms)
292 return NULL;
282 293
294 list_for_each_entry(term, head_terms, list)
295 if (parse_events__is_name_term(term))
296 return term->val.str;
297
298 return NULL;
299}
283 300
284static struct perf_evsel * 301static struct perf_evsel *
285__add_event(struct list_head *list, int *idx, 302__add_event(struct list_head *list, int *idx,
@@ -333,11 +350,25 @@ static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES]
333 return -1; 350 return -1;
334} 351}
335 352
353typedef int config_term_func_t(struct perf_event_attr *attr,
354 struct parse_events_term *term,
355 struct parse_events_error *err);
356static int config_term_common(struct perf_event_attr *attr,
357 struct parse_events_term *term,
358 struct parse_events_error *err);
359static int config_attr(struct perf_event_attr *attr,
360 struct list_head *head,
361 struct parse_events_error *err,
362 config_term_func_t config_term);
363
336int parse_events_add_cache(struct list_head *list, int *idx, 364int parse_events_add_cache(struct list_head *list, int *idx,
337 char *type, char *op_result1, char *op_result2) 365 char *type, char *op_result1, char *op_result2,
366 struct parse_events_error *err,
367 struct list_head *head_config)
338{ 368{
339 struct perf_event_attr attr; 369 struct perf_event_attr attr;
340 char name[MAX_NAME_LEN]; 370 LIST_HEAD(config_terms);
371 char name[MAX_NAME_LEN], *config_name;
341 int cache_type = -1, cache_op = -1, cache_result = -1; 372 int cache_type = -1, cache_op = -1, cache_result = -1;
342 char *op_result[2] = { op_result1, op_result2 }; 373 char *op_result[2] = { op_result1, op_result2 };
343 int i, n; 374 int i, n;
@@ -351,6 +382,7 @@ int parse_events_add_cache(struct list_head *list, int *idx,
351 if (cache_type == -1) 382 if (cache_type == -1)
352 return -EINVAL; 383 return -EINVAL;
353 384
385 config_name = get_config_name(head_config);
354 n = snprintf(name, MAX_NAME_LEN, "%s", type); 386 n = snprintf(name, MAX_NAME_LEN, "%s", type);
355 387
356 for (i = 0; (i < 2) && (op_result[i]); i++) { 388 for (i = 0; (i < 2) && (op_result[i]); i++) {
@@ -391,7 +423,16 @@ int parse_events_add_cache(struct list_head *list, int *idx,
391 memset(&attr, 0, sizeof(attr)); 423 memset(&attr, 0, sizeof(attr));
392 attr.config = cache_type | (cache_op << 8) | (cache_result << 16); 424 attr.config = cache_type | (cache_op << 8) | (cache_result << 16);
393 attr.type = PERF_TYPE_HW_CACHE; 425 attr.type = PERF_TYPE_HW_CACHE;
394 return add_event(list, idx, &attr, name, NULL); 426
427 if (head_config) {
428 if (config_attr(&attr, head_config, err,
429 config_term_common))
430 return -EINVAL;
431
432 if (get_config_terms(head_config, &config_terms))
433 return -ENOMEM;
434 }
435 return add_event(list, idx, &attr, config_name ? : name, &config_terms);
395} 436}
396 437
397static void tracepoint_error(struct parse_events_error *e, int err, 438static void tracepoint_error(struct parse_events_error *e, int err,
@@ -399,6 +440,9 @@ static void tracepoint_error(struct parse_events_error *e, int err,
399{ 440{
400 char help[BUFSIZ]; 441 char help[BUFSIZ];
401 442
443 if (!e)
444 return;
445
402 /* 446 /*
403 * We get error directly from syscall errno ( > 0), 447 * We get error directly from syscall errno ( > 0),
404 * or from encoded pointer's error ( < 0). 448 * or from encoded pointer's error ( < 0).
@@ -537,6 +581,7 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
537struct __add_bpf_event_param { 581struct __add_bpf_event_param {
538 struct parse_events_evlist *data; 582 struct parse_events_evlist *data;
539 struct list_head *list; 583 struct list_head *list;
584 struct list_head *head_config;
540}; 585};
541 586
542static int add_bpf_event(struct probe_trace_event *tev, int fd, 587static int add_bpf_event(struct probe_trace_event *tev, int fd,
@@ -553,7 +598,8 @@ static int add_bpf_event(struct probe_trace_event *tev, int fd,
553 tev->group, tev->event, fd); 598 tev->group, tev->event, fd);
554 599
555 err = parse_events_add_tracepoint(&new_evsels, &evlist->idx, tev->group, 600 err = parse_events_add_tracepoint(&new_evsels, &evlist->idx, tev->group,
556 tev->event, evlist->error, NULL); 601 tev->event, evlist->error,
602 param->head_config);
557 if (err) { 603 if (err) {
558 struct perf_evsel *evsel, *tmp; 604 struct perf_evsel *evsel, *tmp;
559 605
@@ -578,11 +624,12 @@ static int add_bpf_event(struct probe_trace_event *tev, int fd,
578 624
579int parse_events_load_bpf_obj(struct parse_events_evlist *data, 625int parse_events_load_bpf_obj(struct parse_events_evlist *data,
580 struct list_head *list, 626 struct list_head *list,
581 struct bpf_object *obj) 627 struct bpf_object *obj,
628 struct list_head *head_config)
582{ 629{
583 int err; 630 int err;
584 char errbuf[BUFSIZ]; 631 char errbuf[BUFSIZ];
585 struct __add_bpf_event_param param = {data, list}; 632 struct __add_bpf_event_param param = {data, list, head_config};
586 static bool registered_unprobe_atexit = false; 633 static bool registered_unprobe_atexit = false;
587 634
588 if (IS_ERR(obj) || !obj) { 635 if (IS_ERR(obj) || !obj) {
@@ -628,17 +675,99 @@ errout:
628 return err; 675 return err;
629} 676}
630 677
678static int
679parse_events_config_bpf(struct parse_events_evlist *data,
680 struct bpf_object *obj,
681 struct list_head *head_config)
682{
683 struct parse_events_term *term;
684 int error_pos;
685
686 if (!head_config || list_empty(head_config))
687 return 0;
688
689 list_for_each_entry(term, head_config, list) {
690 char errbuf[BUFSIZ];
691 int err;
692
693 if (term->type_term != PARSE_EVENTS__TERM_TYPE_USER) {
694 snprintf(errbuf, sizeof(errbuf),
695 "Invalid config term for BPF object");
696 errbuf[BUFSIZ - 1] = '\0';
697
698 data->error->idx = term->err_term;
699 data->error->str = strdup(errbuf);
700 return -EINVAL;
701 }
702
703 err = bpf__config_obj(obj, term, data->evlist, &error_pos);
704 if (err) {
705 bpf__strerror_config_obj(obj, term, data->evlist,
706 &error_pos, err, errbuf,
707 sizeof(errbuf));
708 data->error->help = strdup(
709"Hint:\tValid config terms:\n"
710" \tmap:[<arraymap>].value<indices>=[value]\n"
711" \tmap:[<eventmap>].event<indices>=[event]\n"
712"\n"
713" \twhere <indices> is something like [0,3...5] or [all]\n"
714" \t(add -v to see detail)");
715 data->error->str = strdup(errbuf);
716 if (err == -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE)
717 data->error->idx = term->err_val;
718 else
719 data->error->idx = term->err_term + error_pos;
720 return err;
721 }
722 }
723 return 0;
724}
725
726/*
727 * Split config terms:
728 * perf record -e bpf.c/call-graph=fp,map:array.value[0]=1/ ...
729 * 'call-graph=fp' is 'evt config', should be applied to each
730 * events in bpf.c.
731 * 'map:array.value[0]=1' is 'obj config', should be processed
732 * with parse_events_config_bpf.
733 *
734 * Move object config terms from the first list to obj_head_config.
735 */
736static void
737split_bpf_config_terms(struct list_head *evt_head_config,
738 struct list_head *obj_head_config)
739{
740 struct parse_events_term *term, *temp;
741
742 /*
743 * Currectly, all possible user config term
744 * belong to bpf object. parse_events__is_hardcoded_term()
745 * happends to be a good flag.
746 *
747 * See parse_events_config_bpf() and
748 * config_term_tracepoint().
749 */
750 list_for_each_entry_safe(term, temp, evt_head_config, list)
751 if (!parse_events__is_hardcoded_term(term))
752 list_move_tail(&term->list, obj_head_config);
753}
754
631int parse_events_load_bpf(struct parse_events_evlist *data, 755int parse_events_load_bpf(struct parse_events_evlist *data,
632 struct list_head *list, 756 struct list_head *list,
633 char *bpf_file_name, 757 char *bpf_file_name,
634 bool source) 758 bool source,
759 struct list_head *head_config)
635{ 760{
761 int err;
636 struct bpf_object *obj; 762 struct bpf_object *obj;
763 LIST_HEAD(obj_head_config);
764
765 if (head_config)
766 split_bpf_config_terms(head_config, &obj_head_config);
637 767
638 obj = bpf__prepare_load(bpf_file_name, source); 768 obj = bpf__prepare_load(bpf_file_name, source);
639 if (IS_ERR(obj)) { 769 if (IS_ERR(obj)) {
640 char errbuf[BUFSIZ]; 770 char errbuf[BUFSIZ];
641 int err;
642 771
643 err = PTR_ERR(obj); 772 err = PTR_ERR(obj);
644 773
@@ -656,7 +785,18 @@ int parse_events_load_bpf(struct parse_events_evlist *data,
656 return err; 785 return err;
657 } 786 }
658 787
659 return parse_events_load_bpf_obj(data, list, obj); 788 err = parse_events_load_bpf_obj(data, list, obj, head_config);
789 if (err)
790 return err;
791 err = parse_events_config_bpf(data, obj, &obj_head_config);
792
793 /*
794 * Caller doesn't know anything about obj_head_config,
795 * so combine them together again before returnning.
796 */
797 if (head_config)
798 list_splice_tail(&obj_head_config, head_config);
799 return err;
660} 800}
661 801
662static int 802static int
@@ -743,9 +883,59 @@ static int check_type_val(struct parse_events_term *term,
743 return -EINVAL; 883 return -EINVAL;
744} 884}
745 885
746typedef int config_term_func_t(struct perf_event_attr *attr, 886/*
747 struct parse_events_term *term, 887 * Update according to parse-events.l
748 struct parse_events_error *err); 888 */
889static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = {
890 [PARSE_EVENTS__TERM_TYPE_USER] = "<sysfs term>",
891 [PARSE_EVENTS__TERM_TYPE_CONFIG] = "config",
892 [PARSE_EVENTS__TERM_TYPE_CONFIG1] = "config1",
893 [PARSE_EVENTS__TERM_TYPE_CONFIG2] = "config2",
894 [PARSE_EVENTS__TERM_TYPE_NAME] = "name",
895 [PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD] = "period",
896 [PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ] = "freq",
897 [PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE] = "branch_type",
898 [PARSE_EVENTS__TERM_TYPE_TIME] = "time",
899 [PARSE_EVENTS__TERM_TYPE_CALLGRAPH] = "call-graph",
900 [PARSE_EVENTS__TERM_TYPE_STACKSIZE] = "stack-size",
901 [PARSE_EVENTS__TERM_TYPE_NOINHERIT] = "no-inherit",
902 [PARSE_EVENTS__TERM_TYPE_INHERIT] = "inherit",
903};
904
905static bool config_term_shrinked;
906
907static bool
908config_term_avail(int term_type, struct parse_events_error *err)
909{
910 if (term_type < 0 || term_type >= __PARSE_EVENTS__TERM_TYPE_NR) {
911 err->str = strdup("Invalid term_type");
912 return false;
913 }
914 if (!config_term_shrinked)
915 return true;
916
917 switch (term_type) {
918 case PARSE_EVENTS__TERM_TYPE_CONFIG:
919 case PARSE_EVENTS__TERM_TYPE_CONFIG1:
920 case PARSE_EVENTS__TERM_TYPE_CONFIG2:
921 case PARSE_EVENTS__TERM_TYPE_NAME:
922 return true;
923 default:
924 if (!err)
925 return false;
926
927 /* term_type is validated so indexing is safe */
928 if (asprintf(&err->str, "'%s' is not usable in 'perf stat'",
929 config_term_names[term_type]) < 0)
930 err->str = NULL;
931 return false;
932 }
933}
934
935void parse_events__shrink_config_terms(void)
936{
937 config_term_shrinked = true;
938}
749 939
750static int config_term_common(struct perf_event_attr *attr, 940static int config_term_common(struct perf_event_attr *attr,
751 struct parse_events_term *term, 941 struct parse_events_term *term,
@@ -812,6 +1002,17 @@ do { \
812 return -EINVAL; 1002 return -EINVAL;
813 } 1003 }
814 1004
1005 /*
1006 * Check term availbility after basic checking so
1007 * PARSE_EVENTS__TERM_TYPE_USER can be found and filtered.
1008 *
1009 * If check availbility at the entry of this function,
1010 * user will see "'<sysfs term>' is not usable in 'perf stat'"
1011 * if an invalid config term is provided for legacy events
1012 * (for example, instructions/badterm/...), which is confusing.
1013 */
1014 if (!config_term_avail(term->type_term, err))
1015 return -EINVAL;
815 return 0; 1016 return 0;
816#undef CHECK_TYPE_VAL 1017#undef CHECK_TYPE_VAL
817} 1018}
@@ -958,23 +1159,8 @@ int parse_events_add_numeric(struct parse_events_evlist *data,
958 return -ENOMEM; 1159 return -ENOMEM;
959 } 1160 }
960 1161
961 return add_event(list, &data->idx, &attr, NULL, &config_terms); 1162 return add_event(list, &data->idx, &attr,
962} 1163 get_config_name(head_config), &config_terms);
963
964static int parse_events__is_name_term(struct parse_events_term *term)
965{
966 return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME;
967}
968
969static char *pmu_event_name(struct list_head *head_terms)
970{
971 struct parse_events_term *term;
972
973 list_for_each_entry(term, head_terms, list)
974 if (parse_events__is_name_term(term))
975 return term->val.str;
976
977 return NULL;
978} 1164}
979 1165
980int parse_events_add_pmu(struct parse_events_evlist *data, 1166int parse_events_add_pmu(struct parse_events_evlist *data,
@@ -1021,7 +1207,7 @@ int parse_events_add_pmu(struct parse_events_evlist *data,
1021 return -EINVAL; 1207 return -EINVAL;
1022 1208
1023 evsel = __add_event(list, &data->idx, &attr, 1209 evsel = __add_event(list, &data->idx, &attr,
1024 pmu_event_name(head_config), pmu->cpus, 1210 get_config_name(head_config), pmu->cpus,
1025 &config_terms); 1211 &config_terms);
1026 if (evsel) { 1212 if (evsel) {
1027 evsel->unit = info.unit; 1213 evsel->unit = info.unit;
@@ -1383,8 +1569,7 @@ int parse_events_terms(struct list_head *terms, const char *str)
1383 return 0; 1569 return 0;
1384 } 1570 }
1385 1571
1386 if (data.terms) 1572 parse_events_terms__delete(data.terms);
1387 parse_events__free_terms(data.terms);
1388 return ret; 1573 return ret;
1389} 1574}
1390 1575
@@ -1392,9 +1577,10 @@ int parse_events(struct perf_evlist *evlist, const char *str,
1392 struct parse_events_error *err) 1577 struct parse_events_error *err)
1393{ 1578{
1394 struct parse_events_evlist data = { 1579 struct parse_events_evlist data = {
1395 .list = LIST_HEAD_INIT(data.list), 1580 .list = LIST_HEAD_INIT(data.list),
1396 .idx = evlist->nr_entries, 1581 .idx = evlist->nr_entries,
1397 .error = err, 1582 .error = err,
1583 .evlist = evlist,
1398 }; 1584 };
1399 int ret; 1585 int ret;
1400 1586
@@ -2065,12 +2251,29 @@ int parse_events_term__clone(struct parse_events_term **new,
2065 term->err_term, term->err_val); 2251 term->err_term, term->err_val);
2066} 2252}
2067 2253
2068void parse_events__free_terms(struct list_head *terms) 2254void parse_events_terms__purge(struct list_head *terms)
2069{ 2255{
2070 struct parse_events_term *term, *h; 2256 struct parse_events_term *term, *h;
2071 2257
2072 list_for_each_entry_safe(term, h, terms, list) 2258 list_for_each_entry_safe(term, h, terms, list) {
2259 if (term->array.nr_ranges)
2260 free(term->array.ranges);
2261 list_del_init(&term->list);
2073 free(term); 2262 free(term);
2263 }
2264}
2265
2266void parse_events_terms__delete(struct list_head *terms)
2267{
2268 if (!terms)
2269 return;
2270 parse_events_terms__purge(terms);
2271 free(terms);
2272}
2273
2274void parse_events__clear_array(struct parse_events_array *a)
2275{
2276 free(a->ranges);
2074} 2277}
2075 2278
2076void parse_events_evlist_error(struct parse_events_evlist *data, 2279void parse_events_evlist_error(struct parse_events_evlist *data,
@@ -2085,6 +2288,33 @@ void parse_events_evlist_error(struct parse_events_evlist *data,
2085 WARN_ONCE(!err->str, "WARNING: failed to allocate error string"); 2288 WARN_ONCE(!err->str, "WARNING: failed to allocate error string");
2086} 2289}
2087 2290
2291static void config_terms_list(char *buf, size_t buf_sz)
2292{
2293 int i;
2294 bool first = true;
2295
2296 buf[0] = '\0';
2297 for (i = 0; i < __PARSE_EVENTS__TERM_TYPE_NR; i++) {
2298 const char *name = config_term_names[i];
2299
2300 if (!config_term_avail(i, NULL))
2301 continue;
2302 if (!name)
2303 continue;
2304 if (name[0] == '<')
2305 continue;
2306
2307 if (strlen(buf) + strlen(name) + 2 >= buf_sz)
2308 return;
2309
2310 if (!first)
2311 strcat(buf, ",");
2312 else
2313 first = false;
2314 strcat(buf, name);
2315 }
2316}
2317
2088/* 2318/*
2089 * Return string contains valid config terms of an event. 2319 * Return string contains valid config terms of an event.
2090 * @additional_terms: For terms such as PMU sysfs terms. 2320 * @additional_terms: For terms such as PMU sysfs terms.
@@ -2092,17 +2322,18 @@ void parse_events_evlist_error(struct parse_events_evlist *data,
2092char *parse_events_formats_error_string(char *additional_terms) 2322char *parse_events_formats_error_string(char *additional_terms)
2093{ 2323{
2094 char *str; 2324 char *str;
2095 static const char *static_terms = "config,config1,config2,name," 2325 /* "branch_type" is the longest name */
2096 "period,freq,branch_type,time," 2326 char static_terms[__PARSE_EVENTS__TERM_TYPE_NR *
2097 "call-graph,stack-size\n"; 2327 (sizeof("branch_type") - 1)];
2098 2328
2329 config_terms_list(static_terms, sizeof(static_terms));
2099 /* valid terms */ 2330 /* valid terms */
2100 if (additional_terms) { 2331 if (additional_terms) {
2101 if (!asprintf(&str, "valid terms: %s,%s", 2332 if (asprintf(&str, "valid terms: %s,%s",
2102 additional_terms, static_terms)) 2333 additional_terms, static_terms) < 0)
2103 goto fail; 2334 goto fail;
2104 } else { 2335 } else {
2105 if (!asprintf(&str, "valid terms: %s", static_terms)) 2336 if (asprintf(&str, "valid terms: %s", static_terms) < 0)
2106 goto fail; 2337 goto fail;
2107 } 2338 }
2108 return str; 2339 return str;