From a1f8bc95c33e953e080f72be4b95176dacb423b0 Mon Sep 17 00:00:00 2001 From: Jason Yan Date: Mon, 20 Apr 2020 20:35:28 +0800 Subject: perf annotate: Remove unneeded conversion to bool The '>' expression itself is bool, no need to convert it to bool again. This fixes the following coccicheck warning: tools/perf/ui/browsers/annotate.c:212:30-35: WARNING: conversion to bool not needed here Signed-off-by: Jason Yan Cc: Alexander Shishkin Cc: Jiri Olsa Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lore.kernel.org/lkml/20200420123528.11655-1-yanaijie@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/annotate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 9023267e5643..bd77825fd5a1 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -209,7 +209,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) ui_browser__mark_fused(browser, pcnt_width + 3 + notes->widths.addr + width, from - 1, - to > from ? true : false); + to > from); } } -- cgit From 387ad33fe710758a8e1b860819a7452bceb4329a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:29 +0200 Subject: perf tools: Add fake pmu support Add a way to create a pmu event without the actual PMU being in place. This way we can test metrics defined for any processor. The interface is to define fake_pmu in struct parse_events_state data. It will be used only in tests via special interface function added in following changes. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-2-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 6 +++--- tools/perf/util/parse-events.h | 3 ++- tools/perf/util/parse-events.l | 8 ++++++-- tools/perf/util/parse-events.y | 41 +++++++++++++++++++++++++++++++++++++++-- 4 files changed, 50 insertions(+), 8 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 3decbb203846..4eb7bd53d048 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -1450,7 +1450,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, fprintf(stderr, "' that may result in non-fatal errors\n"); } - pmu = perf_pmu__find(name); + pmu = parse_state->fake_pmu ?: perf_pmu__find(name); if (!pmu) { char *err_str; @@ -1483,7 +1483,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, } } - if (perf_pmu__check_alias(pmu, head_config, &info)) + if (!parse_state->fake_pmu && perf_pmu__check_alias(pmu, head_config, &info)) return -EINVAL; if (verbose > 1) { @@ -1516,7 +1516,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, if (pmu->default_config && get_config_chgs(pmu, head_config, &config_terms)) return -ENOMEM; - if (perf_pmu__config(pmu, &attr, head_config, parse_state->error)) { + if (!parse_state->fake_pmu && perf_pmu__config(pmu, &attr, head_config, parse_state->error)) { struct evsel_config_term *pos, *tmp; list_for_each_entry_safe(pos, tmp, &config_terms, list) { diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index 1fe23a2f9b36..bf79e1eac7d9 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -127,9 +127,10 @@ struct parse_events_state { int idx; int nr_groups; struct parse_events_error *error; - struct evlist *evlist; + struct evlist *evlist; struct list_head *terms; int stoken; + struct perf_pmu *fake_pmu; }; void parse_events__handle_error(struct parse_events_error *err, int idx, diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 002802e17059..56912c9641f5 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l @@ -129,12 +129,16 @@ do { \ yyless(0); \ } while (0) -static int pmu_str_check(yyscan_t scanner) +static int pmu_str_check(yyscan_t scanner, struct parse_events_state *parse_state) { YYSTYPE *yylval = parse_events_get_lval(scanner); char *text = parse_events_get_text(scanner); yylval->str = strdup(text); + + if (parse_state->fake_pmu) + return PE_PMU_EVENT_FAKE; + switch (perf_pmu__parse_check(text)) { case PMU_EVENT_SYMBOL_PREFIX: return PE_PMU_EVENT_PRE; @@ -376,7 +380,7 @@ r{num_raw_hex} { return raw(yyscanner); } {modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); } {bpf_object} { if (!isbpf(yyscanner)) { USER_REJECT }; return str(yyscanner, PE_BPF_OBJECT); } {bpf_source} { if (!isbpf(yyscanner)) { USER_REJECT }; return str(yyscanner, PE_BPF_SOURCE); } -{name} { return pmu_str_check(yyscanner); } +{name} { return pmu_str_check(yyscanner, _parse_state); } {name_tag} { return str(yyscanner, PE_NAME); } "/" { BEGIN(config); return '/'; } - { return '-'; } diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index acef87d9af58..b9fb91fdc5de 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -69,7 +69,7 @@ static void inc_group_count(struct list_head *list, %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP %token PE_ERROR -%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT +%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE %token PE_ARRAY_ALL PE_ARRAY_RANGE %token PE_DRV_CFG_TERM %type PE_VALUE @@ -87,7 +87,7 @@ static void inc_group_count(struct list_head *list, %type PE_MODIFIER_EVENT %type PE_MODIFIER_BP %type PE_EVENT_NAME -%type PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT +%type PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE %type PE_DRV_CFG_TERM %destructor { free ($$); } %type event_term @@ -356,6 +356,43 @@ PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc YYABORT; $$ = list; } +| +PE_PMU_EVENT_FAKE sep_dc +{ + struct list_head *list; + int err; + + list = alloc_list(); + if (!list) + YYABORT; + + err = parse_events_add_pmu(_parse_state, list, $1, NULL, false, false); + free($1); + if (err < 0) { + free(list); + YYABORT; + } + $$ = list; +} +| +PE_PMU_EVENT_FAKE opt_pmu_config +{ + struct list_head *list; + int err; + + list = alloc_list(); + if (!list) + YYABORT; + + err = parse_events_add_pmu(_parse_state, list, $1, $2, false, false); + free($1); + parse_events_terms__delete($2); + if (err < 0) { + free(list); + YYABORT; + } + $$ = list; +} value_sym: PE_VALUE_SYM_HW -- cgit From 34bacc9578de2893ab6301cea89ea001d8e4cf5b Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:31 +0200 Subject: perf tests: Factor check_parse_id function Separating the generic part of check_parse_id function, so it can be used in following changes for the new test. Committer notes: Fix this error: tests/pmu-events.c:413:40: error: missing field 'idx' initializer [-Werror,-Wmissing-field-initializers] struct parse_events_error error = { 0 }; Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-4-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/pmu-events.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index ab64b4a4e284..82fa69a60ec8 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -390,9 +390,8 @@ static bool is_number(const char *str) return errno == 0 && end_ptr != str; } -static int check_parse_id(const char *id, bool same_cpu, struct pmu_event *pe) +static int check_parse_id(const char *id, struct parse_events_error *error) { - struct parse_events_error error; struct evlist *evlist; int ret; @@ -401,8 +400,18 @@ static int check_parse_id(const char *id, bool same_cpu, struct pmu_event *pe) return 0; evlist = evlist__new(); - memset(&error, 0, sizeof(error)); - ret = parse_events(evlist, id, &error); + if (!evlist) + return -ENOMEM; + ret = parse_events(evlist, id, error); + evlist__delete(evlist); + return ret; +} + +static int check_parse_cpu(const char *id, bool same_cpu, struct pmu_event *pe) +{ + struct parse_events_error error = { .idx = 0, }; + + int ret = check_parse_id(id, &error); if (ret && same_cpu) { pr_warning("Parse event failed metric '%s' id '%s' expr '%s'\n", pe->metric_name, id, pe->metric_expr); @@ -413,7 +422,6 @@ static int check_parse_id(const char *id, bool same_cpu, struct pmu_event *pe) id, pe->metric_name, pe->metric_expr); ret = 0; } - evlist__delete(evlist); free(error.str); free(error.help); free(error.first_str); @@ -474,7 +482,7 @@ static int test_parsing(void) expr__add_id(&ctx, strdup(cur->key), k++); hashmap__for_each_entry((&ctx.ids), cur, bkt) { - if (check_parse_id(cur->key, map == cpus_map, + if (check_parse_cpu(cur->key, map == cpus_map, pe)) ret++; } -- cgit From 3bf91aa5aa493b2ac24ffcfc93ffe861bf03685f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 3 Jun 2020 12:32:55 -0300 Subject: perf parse: Provide a way to pass a fake_pmu to parse_events() This is an alternative patch to what Jiri sent that instead of changing all callers to parse_events() for allowing to pass a fake_pmu, provide another function specifically for that. From Jiri's patch: This way it's possible to parse events from PMUs which are not present in the system. It's available only for testing purposes coming in following changes, so all the current users set fake_pmu argument as false. Based-on-a-patch-by: Jiri Olsa Link: http://lore.kernel.org/lkml/20200602214741.1218986-3-jolsa@kernel.org Acked-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ian Rogers Cc: Ingo Molnar Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 15 ++++++++------- tools/perf/util/parse-events.h | 11 +++++++++-- 2 files changed, 17 insertions(+), 9 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 4eb7bd53d048..c4906a6a9f1a 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -2088,15 +2088,16 @@ int parse_events_terms(struct list_head *terms, const char *str) return ret; } -int parse_events(struct evlist *evlist, const char *str, - struct parse_events_error *err) +int __parse_events(struct evlist *evlist, const char *str, + struct parse_events_error *err, struct perf_pmu *fake_pmu) { struct parse_events_state parse_state = { - .list = LIST_HEAD_INIT(parse_state.list), - .idx = evlist->core.nr_entries, - .error = err, - .evlist = evlist, - .stoken = PE_START_EVENTS, + .list = LIST_HEAD_INIT(parse_state.list), + .idx = evlist->core.nr_entries, + .error = err, + .evlist = evlist, + .stoken = PE_START_EVENTS, + .fake_pmu = fake_pmu, }; int ret; diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index bf79e1eac7d9..f0010095fc8c 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -33,8 +33,15 @@ const char *event_type(int type); int parse_events_option(const struct option *opt, const char *str, int unset); int parse_events_option_new_evlist(const struct option *opt, const char *str, int unset); -int parse_events(struct evlist *evlist, const char *str, - struct parse_events_error *error); +int __parse_events(struct evlist *evlist, const char *str, struct parse_events_error *error, + struct perf_pmu *fake_pmu); + +static inline int parse_events(struct evlist *evlist, const char *str, + struct parse_events_error *err) +{ + return __parse_events(evlist, str, err, NULL); +} + int parse_events_terms(struct list_head *terms, const char *str); int parse_filter(const struct option *opt, const char *str, int unset); int exclude_perf(const struct option *opt, const char *arg, int unset); -- cgit From e46fc8d9dd352c88fec49b140008958d2dc1efe1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 9 Jun 2020 13:23:24 -0300 Subject: perf pmu: Add a perf_pmu__fake object to use with __parse_events() When wanting to use the support in __parse_events() for fake pmus, just pass it. Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ian Rogers Cc: Jiri Olsa Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/pmu.c | 2 ++ tools/perf/util/pmu.h | 2 ++ 2 files changed, 4 insertions(+) (limited to 'tools') diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 93fe72a9dc0b..6d51042044fd 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -26,6 +26,8 @@ #include "strbuf.h" #include "fncache.h" +struct perf_pmu perf_pmu__fake; + struct perf_pmu_format { char *name; int value; diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index f971d9aa4570..44ccbdbb1c37 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -43,6 +43,8 @@ struct perf_pmu { struct list_head list; /* ELEM */ }; +extern struct perf_pmu perf_pmu__fake; + struct perf_pmu_info { const char *unit; const char *metric_expr; -- cgit From e1c92a7fbbc5668510736624df3028accd6af0ea Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 3 Jun 2020 12:51:15 -0300 Subject: perf tests: Add another metric parsing test The test goes through all metrics compiled for arch within pmu events and try to parse them. This test is different from 'test_parsing' in that we go through all the events in the current arch, not just one defined for current CPU model. Using 'fake_pmu' to parse events which do not have PMUs defined in the system. Say there's bad change in ivybridge metrics file, like: - a/tools/perf/pmu-events/arch/x86/ivybridge/ivb-metrics.json + b/tools/perf/pmu-events/arch/x86/ivybridge/ivb-metrics.json @@ -8,7 +8,7 @@ - "MetricExpr": "IDQ_UOPS_NOT_DELIVERED.CORE / (4 * (( + "MetricExpr": "IDQ_UOPS_NOT_DELIVERED.CORE / / (4 * the test fails with (on my kabylake laptop): $ perf test 'Parsing of PMU event table metrics with fake PMUs' -v parsing 'idq_uops_not_delivered.core / / (4 * (( ( cpu_clk_unh... syntax error, line 1 expr__parse failed test child finished with -1 ... The test also defines its own list of metrics and tries to parse them. It's handy for developing. Committer notes: Testing it: $ perf test fake 10: PMU events : 10.4: Parsing of PMU event table metrics with fake PMUs : FAILED! $ perf test -v fake |& tail parsing '(unc_p_freq_trans_cycles / unc_p_clockticks) * 100.' parsing '(unc_m_power_channel_ppd / unc_m_clockticks) * 100.' parsing '(unc_m_power_critical_throttle_cycles / unc_m_clockticks) * 100.' parsing '(unc_m_power_self_refresh / unc_m_clockticks) * 100.' parsing 'idq_uops_not_delivered.core / * (4 * cycles)' syntax error expr__parse failed test child finished with -1 ---- end ---- PMU events subtest 4: FAILED! $ And fix this error: tests/pmu-events.c:437:40: error: missing field 'idx' initializer [-Werror,-Wmissing-field-initializers] struct parse_events_error error = { 0 }; Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ian Rogers Cc: Ingo Molnar Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-5-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/pmu-events.c | 117 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 114 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index 82fa69a60ec8..b66b021476ec 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -390,7 +390,8 @@ static bool is_number(const char *str) return errno == 0 && end_ptr != str; } -static int check_parse_id(const char *id, struct parse_events_error *error) +static int check_parse_id(const char *id, struct parse_events_error *error, + struct perf_pmu *fake_pmu) { struct evlist *evlist; int ret; @@ -402,7 +403,7 @@ static int check_parse_id(const char *id, struct parse_events_error *error) evlist = evlist__new(); if (!evlist) return -ENOMEM; - ret = parse_events(evlist, id, error); + ret = __parse_events(evlist, id, error, fake_pmu); evlist__delete(evlist); return ret; } @@ -411,7 +412,7 @@ static int check_parse_cpu(const char *id, bool same_cpu, struct pmu_event *pe) { struct parse_events_error error = { .idx = 0, }; - int ret = check_parse_id(id, &error); + int ret = check_parse_id(id, &error, NULL); if (ret && same_cpu) { pr_warning("Parse event failed metric '%s' id '%s' expr '%s'\n", pe->metric_name, id, pe->metric_expr); @@ -429,6 +430,18 @@ static int check_parse_cpu(const char *id, bool same_cpu, struct pmu_event *pe) return ret; } +static int check_parse_fake(const char *id) +{ + struct parse_events_error error = { .idx = 0, }; + int ret = check_parse_id(id, &error, &perf_pmu__fake); + + free(error.str); + free(error.help); + free(error.first_str); + free(error.first_help); + return ret; +} + static void expr_failure(const char *msg, const struct pmu_events_map *map, const struct pmu_event *pe) @@ -498,6 +511,100 @@ static int test_parsing(void) return ret == 0 ? TEST_OK : TEST_SKIP; } +struct test_metric { + const char *str; +}; + +static struct test_metric metrics[] = { + { "(unc_p_power_state_occupancy.cores_c0 / unc_p_clockticks) * 100." }, + { "imx8_ddr0@read\\-cycles@ * 4 * 4", }, + { "imx8_ddr0@axid\\-read\\,axi_mask\\=0xffff\\,axi_id\\=0x0000@ * 4", }, + { "(cstate_pkg@c2\\-residency@ / msr@tsc@) * 100", }, + { "(imx8_ddr0@read\\-cycles@ + imx8_ddr0@write\\-cycles@)", }, +}; + +static int metric_parse_fake(const char *str) +{ + struct expr_parse_ctx ctx; + struct hashmap_entry *cur; + double result; + int ret = -1; + size_t bkt; + int i; + + pr_debug("parsing '%s'\n", str); + + expr__ctx_init(&ctx); + if (expr__find_other(str, NULL, &ctx, 0) < 0) { + pr_err("expr__find_other failed\n"); + return -1; + } + + /* + * Add all ids with a made up value. The value may + * trigger divide by zero when subtracted and so try to + * make them unique. + */ + i = 1; + hashmap__for_each_entry((&ctx.ids), cur, bkt) + expr__add_id(&ctx, strdup(cur->key), i++); + + hashmap__for_each_entry((&ctx.ids), cur, bkt) { + if (check_parse_fake(cur->key)) { + pr_err("check_parse_fake failed\n"); + goto out; + } + } + + if (expr__parse(&result, &ctx, str, 1)) + pr_err("expr__parse failed\n"); + else + ret = 0; + +out: + expr__ctx_clear(&ctx); + return ret; +} + +/* + * Parse all the metrics for current architecture, + * or all defined cpus via the 'fake_pmu' + * in parse_events. + */ +static int test_parsing_fake(void) +{ + struct pmu_events_map *map; + struct pmu_event *pe; + unsigned int i, j; + int err = 0; + + for (i = 0; i < ARRAY_SIZE(metrics); i++) { + err = metric_parse_fake(metrics[i].str); + if (err) + return err; + } + + i = 0; + for (;;) { + map = &pmu_events_map[i++]; + if (!map->table) + break; + j = 0; + for (;;) { + pe = &map->table[j++]; + if (!pe->name && !pe->metric_group && !pe->metric_name) + break; + if (!pe->metric_expr) + continue; + err = metric_parse_fake(pe->metric_expr); + if (err) + return err; + } + } + + return 0; +} + static const struct { int (*func)(void); const char *desc; @@ -514,6 +621,10 @@ static const struct { .func = test_parsing, .desc = "Parsing of PMU event table metrics", }, + { + .func = test_parsing_fake, + .desc = "Parsing of PMU event table metrics with fake PMUs", + }, }; const char *test__pmu_events_subtest_get_desc(int subtest) -- cgit From 8b4468a2107af32b796fa818e5fb76481c39ee5a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:33 +0200 Subject: perf parse: Factor out parse_groups() function Factor out the parse_groups function, it will be used for new test interface coming in following changes. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-6-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/metricgroup.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 9e21aa767e41..d72a565ec483 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -709,14 +709,12 @@ static void metricgroup__free_egroups(struct list_head *group_list) } } -int metricgroup__parse_groups(const struct option *opt, - const char *str, - bool metric_no_group, - bool metric_no_merge, - struct rblist *metric_events) +static int parse_groups(struct evlist *perf_evlist, const char *str, + bool metric_no_group, + bool metric_no_merge, + struct rblist *metric_events) { struct parse_events_error parse_error; - struct evlist *perf_evlist = *(struct evlist **)opt->value; struct strbuf extra_events; LIST_HEAD(group_list); int ret; @@ -742,6 +740,18 @@ out: return ret; } +int metricgroup__parse_groups(const struct option *opt, + const char *str, + bool metric_no_group, + bool metric_no_merge, + struct rblist *metric_events) +{ + struct evlist *perf_evlist = *(struct evlist **)opt->value; + + return parse_groups(perf_evlist, str, metric_no_group, + metric_no_merge, metric_events); +} + bool metricgroup__has_metric(const char *metric) { struct pmu_events_map *map = perf_pmu__find_map(NULL); -- cgit From 68173bda6ac9d498e450276323f1c10a1d0307ad Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 9 Jun 2020 12:50:42 -0300 Subject: perf tools: Add fake_pmu to parse_group() function Allow to pass fake_pmu in parse_groups function so it can be used in parse_events call. It's will be passed by the upcoming metricgroup__parse_groups_test function. Committer notes: Made it a 'struct perf_pmu' pointer, in line with the changes at the start of this patchkit to avoid statics deep down in library code. Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ingo Molnar Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-6-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/metricgroup.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index d72a565ec483..49e6f7c6fb70 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -712,6 +712,7 @@ static void metricgroup__free_egroups(struct list_head *group_list) static int parse_groups(struct evlist *perf_evlist, const char *str, bool metric_no_group, bool metric_no_merge, + struct perf_pmu *fake_pmu, struct rblist *metric_events) { struct parse_events_error parse_error; @@ -727,7 +728,7 @@ static int parse_groups(struct evlist *perf_evlist, const char *str, return ret; pr_debug("adding %s\n", extra_events.buf); bzero(&parse_error, sizeof(parse_error)); - ret = parse_events(perf_evlist, extra_events.buf, &parse_error); + ret = __parse_events(perf_evlist, extra_events.buf, &parse_error, fake_pmu); if (ret) { parse_events_print_error(&parse_error, extra_events.buf); goto out; @@ -749,7 +750,7 @@ int metricgroup__parse_groups(const struct option *opt, struct evlist *perf_evlist = *(struct evlist **)opt->value; return parse_groups(perf_evlist, str, metric_no_group, - metric_no_merge, metric_events); + metric_no_merge, NULL, metric_events); } bool metricgroup__has_metric(const char *metric) -- cgit From 1381396b0b778c918bf191b1960f92fbd563476d Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 9 Jun 2020 12:57:47 -0300 Subject: perf tools: Add map to parse_groups() function For testing purposes we need to pass our own map of events from parse_groups() through metricgroup__add_metric. Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ingo Molnar Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-8-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/metricgroup.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 49e6f7c6fb70..f89f656c7757 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -597,17 +597,14 @@ static int __metricgroup__add_metric(struct list_head *group_list, static int metricgroup__add_metric(const char *metric, bool metric_no_group, struct strbuf *events, - struct list_head *group_list) + struct list_head *group_list, + struct pmu_events_map *map) { - struct pmu_events_map *map = perf_pmu__find_map(NULL); struct pmu_event *pe; struct egroup *eg; int i, ret; bool has_match = false; - if (!map) - return 0; - for (i = 0; ; i++) { pe = &map->table[i]; @@ -668,7 +665,8 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, static int metricgroup__add_metric_list(const char *list, bool metric_no_group, struct strbuf *events, - struct list_head *group_list) + struct list_head *group_list, + struct pmu_events_map *map) { char *llist, *nlist, *p; int ret = -EINVAL; @@ -683,7 +681,7 @@ static int metricgroup__add_metric_list(const char *list, bool metric_no_group, while ((p = strsep(&llist, ",")) != NULL) { ret = metricgroup__add_metric(p, metric_no_group, events, - group_list); + group_list, map); if (ret == -EINVAL) { fprintf(stderr, "Cannot find metric or group `%s'\n", p); @@ -713,7 +711,8 @@ static int parse_groups(struct evlist *perf_evlist, const char *str, bool metric_no_group, bool metric_no_merge, struct perf_pmu *fake_pmu, - struct rblist *metric_events) + struct rblist *metric_events, + struct pmu_events_map *map) { struct parse_events_error parse_error; struct strbuf extra_events; @@ -723,7 +722,7 @@ static int parse_groups(struct evlist *perf_evlist, const char *str, if (metric_events->nr_entries == 0) metricgroup__rblist_init(metric_events); ret = metricgroup__add_metric_list(str, metric_no_group, - &extra_events, &group_list); + &extra_events, &group_list, map); if (ret) return ret; pr_debug("adding %s\n", extra_events.buf); @@ -748,9 +747,13 @@ int metricgroup__parse_groups(const struct option *opt, struct rblist *metric_events) { struct evlist *perf_evlist = *(struct evlist **)opt->value; + struct pmu_events_map *map = perf_pmu__find_map(NULL); + + if (!map) + return 0; return parse_groups(perf_evlist, str, metric_no_group, - metric_no_merge, NULL, metric_events); + metric_no_merge, NULL, metric_events, map); } bool metricgroup__has_metric(const char *metric) -- cgit From f78ac00a8c999f4418e69e606485784fc5ff1d09 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:36 +0200 Subject: perf tools: Add metricgroup__parse_groups_test function Add the metricgroup__parse_groups_test function. It will be used as test's interface to metric parsing in following changes. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-9-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/metricgroup.c | 11 +++++++++++ tools/perf/util/metricgroup.h | 9 +++++++++ 2 files changed, 20 insertions(+) (limited to 'tools') diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index f89f656c7757..edb13b8b7a57 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -756,6 +756,17 @@ int metricgroup__parse_groups(const struct option *opt, metric_no_merge, NULL, metric_events, map); } +int metricgroup__parse_groups_test(struct evlist *evlist, + struct pmu_events_map *map, + const char *str, + bool metric_no_group, + bool metric_no_merge, + struct rblist *metric_events) +{ + return parse_groups(evlist, str, metric_no_group, + metric_no_merge, &perf_pmu__fake, metric_events, map); +} + bool metricgroup__has_metric(const char *metric) { struct pmu_events_map *map = perf_pmu__find_map(NULL); diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h index 287850bcdeca..426c824e20bf 100644 --- a/tools/perf/util/metricgroup.h +++ b/tools/perf/util/metricgroup.h @@ -7,8 +7,10 @@ #include struct evsel; +struct evlist; struct option; struct rblist; +struct pmu_events_map; struct metric_event { struct rb_node nd; @@ -34,6 +36,13 @@ int metricgroup__parse_groups(const struct option *opt, bool metric_no_merge, struct rblist *metric_events); +int metricgroup__parse_groups_test(struct evlist *evlist, + struct pmu_events_map *map, + const char *str, + bool metric_no_group, + bool metric_no_merge, + struct rblist *metric_events); + void metricgroup__print(bool metrics, bool groups, char *filter, bool raw, bool details); bool metricgroup__has_metric(const char *metric); -- cgit From 2cfaa853d8ead2fe4cd82986163b5cea21e300bd Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:37 +0200 Subject: perf tools: Factor out prepare_metric function Factoring out prepare_metric function so it can be used in test interface coming in following changes. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-10-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/stat-shadow.c | 53 +++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 19 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index a7c13a88ecb9..27be7ce2fff4 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -730,25 +730,16 @@ static void print_smi_cost(struct perf_stat_config *config, out->print_metric(config, out->ctx, NULL, "%4.0f", "SMI#", smi_num); } -static void generic_metric(struct perf_stat_config *config, - const char *metric_expr, - struct evsel **metric_events, - char *name, - const char *metric_name, - const char *metric_unit, - int runtime, - int cpu, - struct perf_stat_output_ctx *out, - struct runtime_stat *st) +static int prepare_metric(struct evsel **metric_events, + struct expr_parse_ctx *pctx, + int cpu, + struct runtime_stat *st) { - print_metric_t print_metric = out->print_metric; - struct expr_parse_ctx pctx; - double ratio, scale; - int i; - void *ctxp = out->ctx; + double scale; char *n, *pn; + int i; - expr__ctx_init(&pctx); + expr__ctx_init(pctx); for (i = 0; metric_events[i]; i++) { struct saved_value *v; struct stats *stats; @@ -771,7 +762,7 @@ static void generic_metric(struct perf_stat_config *config, n = strdup(metric_events[i]->name); if (!n) - return; + return -ENOMEM; /* * This display code with --no-merge adds [cpu] postfixes. * These are not supported by the parser. Remove everything @@ -782,11 +773,35 @@ static void generic_metric(struct perf_stat_config *config, *pn = 0; if (metric_total) - expr__add_id(&pctx, n, metric_total); + expr__add_id(pctx, n, metric_total); else - expr__add_id(&pctx, n, avg_stats(stats)*scale); + expr__add_id(pctx, n, avg_stats(stats)*scale); } + return i; +} + +static void generic_metric(struct perf_stat_config *config, + const char *metric_expr, + struct evsel **metric_events, + char *name, + const char *metric_name, + const char *metric_unit, + int runtime, + int cpu, + struct perf_stat_output_ctx *out, + struct runtime_stat *st) +{ + print_metric_t print_metric = out->print_metric; + struct expr_parse_ctx pctx; + double ratio, scale; + int i; + void *ctxp = out->ctx; + + i = prepare_metric(metric_events, &pctx, cpu, st); + if (i < 0) + return; + if (!metric_events[i]) { if (expr__parse(&ratio, &pctx, metric_expr, runtime) == 0) { char *unit; -- cgit From 9afe5658a6fa89f59f01d2857d78203cc8665f1c Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:38 +0200 Subject: perf tools: Release metric_events rblist We don't release metric_events rblist, add the missing delete hook and call the release before leaving cmd_stat. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-11-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 1 + tools/perf/util/metricgroup.c | 19 +++++++++++++++++++ tools/perf/util/metricgroup.h | 1 + 3 files changed, 21 insertions(+) (limited to 'tools') diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 9be020e0098a..911b9c3538a2 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -2307,6 +2307,7 @@ out: evlist__delete(evsel_list); + metricgroup__rblist_exit(&stat_config.metric_events); runtime_stat_delete(&stat_config); return status; diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index edb13b8b7a57..82fecb5a302d 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -76,11 +76,30 @@ static struct rb_node *metric_event_new(struct rblist *rblist __maybe_unused, return &me->nd; } +static void metric_event_delete(struct rblist *rblist __maybe_unused, + struct rb_node *rb_node) +{ + struct metric_event *me = container_of(rb_node, struct metric_event, nd); + struct metric_expr *expr, *tmp; + + list_for_each_entry_safe(expr, tmp, &me->head, nd) { + free(expr); + } + + free(me); +} + static void metricgroup__rblist_init(struct rblist *metric_events) { rblist__init(metric_events); metric_events->node_cmp = metric_event_cmp; metric_events->node_new = metric_event_new; + metric_events->node_delete = metric_event_delete; +} + +void metricgroup__rblist_exit(struct rblist *metric_events) +{ + rblist__exit(metric_events); } struct egroup { diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h index 426c824e20bf..8315bd1a7da4 100644 --- a/tools/perf/util/metricgroup.h +++ b/tools/perf/util/metricgroup.h @@ -47,4 +47,5 @@ void metricgroup__print(bool metrics, bool groups, char *filter, bool raw, bool details); bool metricgroup__has_metric(const char *metric); int arch_get_runtimeparam(void); +void metricgroup__rblist_exit(struct rblist *metric_events); #endif -- cgit From 6d432c4c8aa5660d8f9f43326db8350b48dcb6f5 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:39 +0200 Subject: perf tools: Add test_generic_metric function Adding test_generic_metric that prepares and runs given metric over the data from struct runtime_stat object. Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-12-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/stat-shadow.c | 14 ++++++++++++++ tools/perf/util/stat.h | 3 +++ 2 files changed, 17 insertions(+) (limited to 'tools') diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index 27be7ce2fff4..8fdef47005e6 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -842,6 +842,20 @@ static void generic_metric(struct perf_stat_config *config, expr__ctx_clear(&pctx); } +double test_generic_metric(struct metric_expr *mexp, int cpu, struct runtime_stat *st) +{ + struct expr_parse_ctx pctx; + double ratio; + + if (prepare_metric(mexp->metric_events, &pctx, cpu, st) < 0) + return 0.; + + if (expr__parse(&ratio, &pctx, mexp->metric_expr, 1)) + return 0.; + + return ratio; +} + void perf_stat__print_shadow_stats(struct perf_stat_config *config, struct evsel *evsel, double avg, int cpu, diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index f75ae679eb28..6911c7249199 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -230,4 +230,7 @@ perf_evlist__print_counters(struct evlist *evlist, struct target *_target, struct timespec *ts, int argc, const char **argv); + +struct metric_expr; +double test_generic_metric(struct metric_expr *mexp, int cpu, struct runtime_stat *st); #endif -- cgit From 0a507af9c681ac2adedc5fe1b2d534e27be85446 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:40 +0200 Subject: perf tests: Add parse metric test for ipc metric Adding new test that process metrics code and checks the expected results. Starting with easy ipc metric. Committer testing: # perf test "Parse and process metrics" 67: Parse and process metrics : Ok # # perf test -v "Parse and process metrics" 67: Parse and process metrics : --- start --- test child forked, pid 103402 metric expr inst_retired.any / cpu_clk_unhalted.thread for IPC found event inst_retired.any found event cpu_clk_unhalted.thread adding {inst_retired.any,cpu_clk_unhalted.thread}:W test child finished with 0 ---- end ---- Parse and process metrics: Ok # Had to fix it to initialize that 'struct value' array sentinel with a named initializer to fix the build with some versions of clang: tests/parse-metric.c:135:7: error: missing field 'val' initializer [-Werror,-Wmissing-field-initializers] { 0 }, Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-13-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 4 ++ tools/perf/tests/parse-metric.c | 145 ++++++++++++++++++++++++++++++++++++++++ tools/perf/tests/tests.h | 1 + 4 files changed, 151 insertions(+) create mode 100644 tools/perf/tests/parse-metric.c (limited to 'tools') diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index cd00498a5dce..84352fc49a20 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build @@ -59,6 +59,7 @@ perf-y += genelf.o perf-y += api-io.o perf-y += demangle-java-test.o perf-y += pfm.o +perf-y += parse-metric.o $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build $(call rule_mkdir) diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index da5b6cc23f25..d328caaba45d 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -337,6 +337,10 @@ static struct test generic_tests[] = { .desc = "Demangle Java", .func = test__demangle_java, }, + { + .desc = "Parse and process metrics", + .func = test__parse_metric, + }, { .func = NULL, }, diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c new file mode 100644 index 000000000000..79d956dc6a74 --- /dev/null +++ b/tools/perf/tests/parse-metric.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include "metricgroup.h" +#include "tests.h" +#include "pmu-events/pmu-events.h" +#include "evlist.h" +#include "rblist.h" +#include "debug.h" +#include "expr.h" +#include "stat.h" + +static struct pmu_event pme_test[] = { +{ + .metric_expr = "inst_retired.any / cpu_clk_unhalted.thread", + .metric_name = "IPC", +}, +}; + +static struct pmu_events_map map = { + .cpuid = "test", + .version = "1", + .type = "core", + .table = pme_test, +}; + +struct value { + const char *event; + u64 val; +}; + +static u64 find_value(const char *name, struct value *values) +{ + struct value *v = values; + + while (v->event) { + if (!strcmp(name, v->event)) + return v->val; + v++; + }; + return 0; +} + +static void load_runtime_stat(struct runtime_stat *st, struct evlist *evlist, + struct value *vals) +{ + struct evsel *evsel; + u64 count; + + evlist__for_each_entry(evlist, evsel) { + count = find_value(evsel->name, vals); + perf_stat__update_shadow_stats(evsel, count, 0, st); + } +} + +static double compute_single(struct rblist *metric_events, struct evlist *evlist, + struct runtime_stat *st) +{ + struct evsel *evsel = evlist__first(evlist); + struct metric_event *me; + + me = metricgroup__lookup(metric_events, evsel, false); + if (me != NULL) { + struct metric_expr *mexp; + + mexp = list_first_entry(&me->head, struct metric_expr, nd); + return test_generic_metric(mexp, 0, st); + } + return 0.; +} + +static int compute_metric(const char *name, struct value *vals, double *ratio) +{ + struct rblist metric_events = { + .nr_entries = 0, + }; + struct perf_cpu_map *cpus; + struct runtime_stat st; + struct evlist *evlist; + int err; + + /* + * We need to prepare evlist for stat mode running on CPU 0 + * because that's where all the stats are going to be created. + */ + evlist = evlist__new(); + if (!evlist) + return -ENOMEM; + + cpus = perf_cpu_map__new("0"); + if (!cpus) + return -ENOMEM; + + perf_evlist__set_maps(&evlist->core, cpus, NULL); + + /* Parse the metric into metric_events list. */ + err = metricgroup__parse_groups_test(evlist, &map, name, + false, false, + &metric_events); + + TEST_ASSERT_VAL("failed to parse metric", err == 0); + + if (perf_evlist__alloc_stats(evlist, false)) + return -1; + + /* Load the runtime stats with given numbers for events. */ + runtime_stat__init(&st); + load_runtime_stat(&st, evlist, vals); + + /* And execute the metric */ + *ratio = compute_single(&metric_events, evlist, &st); + + /* ... clenup. */ + metricgroup__rblist_exit(&metric_events); + runtime_stat__exit(&st); + perf_evlist__free_stats(evlist); + perf_cpu_map__put(cpus); + evlist__delete(evlist); + return 0; +} + +static int test_ipc(void) +{ + double ratio; + struct value vals[] = { + { .event = "inst_retired.any", .val = 300 }, + { .event = "cpu_clk_unhalted.thread", .val = 200 }, + { .event = NULL, }, + }; + + TEST_ASSERT_VAL("failed to compute metric", + compute_metric("IPC", vals, &ratio) == 0); + + TEST_ASSERT_VAL("IPC failed, wrong ratio", + ratio == 1.5); + return 0; +} + +int test__parse_metric(struct test *test __maybe_unused, int subtest __maybe_unused) +{ + TEST_ASSERT_VAL("IPC failed", test_ipc() == 0); + return 0; +} diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 76a4e352eaaf..4447a516c689 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -121,6 +121,7 @@ int test__demangle_java(struct test *test, int subtest); int test__pfm(struct test *test, int subtest); const char *test__pfm_subtest_get_desc(int subtest); int test__pfm_subtest_get_nr(void); +int test__parse_metric(struct test *test, int subtest); bool test__bp_signal_is_supported(void); bool test__bp_account_is_supported(void); -- cgit From 218ca91df47712a7b2b5a554e39c4a2c819a9e86 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 2 Jun 2020 23:47:41 +0200 Subject: perf tests: Add parse metric test for frontend metric Adding new metric test for frontend metric. It's stolen from x86 pmu events. Committer testing: # perf test "Parse and process metrics" 67: Parse and process metrics : Ok # perf test -v "Parse and process metrics" # 67: Parse and process metrics : --- start --- test child forked, pid 104881 metric expr inst_retired.any / cpu_clk_unhalted.thread for IPC found event inst_retired.any found event cpu_clk_unhalted.thread adding {inst_retired.any,cpu_clk_unhalted.thread}:W metric expr idq_uops_not_delivered.core / (4 * (( ( cpu_clk_unhalted.thread / 2 ) * ( 1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk ) ))) for Frontend_Bound_SMT found event cpu_clk_unhalted.one_thread_active found event cpu_clk_unhalted.ref_xclk found event idq_uops_not_delivered.core found event cpu_clk_unhalted.thread adding {cpu_clk_unhalted.one_thread_active,cpu_clk_unhalted.ref_xclk,idq_uops_not_delivered.core,cpu_clk_unhalted.thread}:W test child finished with 0 ---- end ---- Parse and process metrics: Ok # Had to fix it to initialize that 'struct value' array sentinel with a named initializer to fix the build with some versions of clang: tests/parse-metric.c:154:7: error: missing field 'val' initializer [-Werror,-Wmissing-field-initializers] { 0 }, Signed-off-by: Jiri Olsa Acked-by: Ian Rogers Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Andi Kleen Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200602214741.1218986-14-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/parse-metric.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'tools') diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c index 79d956dc6a74..8c48251425e1 100644 --- a/tools/perf/tests/parse-metric.c +++ b/tools/perf/tests/parse-metric.c @@ -17,6 +17,11 @@ static struct pmu_event pme_test[] = { .metric_expr = "inst_retired.any / cpu_clk_unhalted.thread", .metric_name = "IPC", }, +{ + .metric_expr = "idq_uops_not_delivered.core / (4 * (( ( cpu_clk_unhalted.thread / 2 ) * " + "( 1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk ) )))", + .metric_name = "Frontend_Bound_SMT", +}, }; static struct pmu_events_map map = { @@ -138,8 +143,28 @@ static int test_ipc(void) return 0; } +static int test_frontend(void) +{ + double ratio; + struct value vals[] = { + { .event = "idq_uops_not_delivered.core", .val = 300 }, + { .event = "cpu_clk_unhalted.thread", .val = 200 }, + { .event = "cpu_clk_unhalted.one_thread_active", .val = 400 }, + { .event = "cpu_clk_unhalted.ref_xclk", .val = 600 }, + { .event = NULL, }, + }; + + TEST_ASSERT_VAL("failed to compute metric", + compute_metric("Frontend_Bound_SMT", vals, &ratio) == 0); + + TEST_ASSERT_VAL("Frontend_Bound_SMT failed, wrong ratio", + ratio == 0.45); + return 0; +} + int test__parse_metric(struct test *test __maybe_unused, int subtest __maybe_unused) { TEST_ASSERT_VAL("IPC failed", test_ipc() == 0); + TEST_ASSERT_VAL("frontend failed", test_frontend() == 0); return 0; } -- cgit From afdd63f5933b3c970438e8ab6bb0cd9f392f3bf6 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 10 Jun 2020 11:39:16 -0300 Subject: perf script: Fixup some evsel/evlist method names Fixups related to the introduction of libperf, where the perf_{evsel,evlist}__ prefix is reserved for functions operating on struct perf_{evsel,evlist}. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 181d65e5a450..1ff6a8a8dde5 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -388,7 +388,7 @@ static int evsel__check_stype(struct evsel *evsel, u64 sample_type, const char * return evsel__do_check_stype(evsel, sample_type, sample_msg, field, false); } -static int perf_evsel__check_attr(struct evsel *evsel, struct perf_session *session) +static int evsel__check_attr(struct evsel *evsel, struct perf_session *session) { struct perf_event_attr *attr = &evsel->core.attr; bool allow_user_set; @@ -522,7 +522,7 @@ static int perf_session__check_output_opt(struct perf_session *session) } if (evsel && output[j].fields && - perf_evsel__check_attr(evsel, session)) + evsel__check_attr(evsel, session)) return -1; if (evsel == NULL) @@ -1692,7 +1692,7 @@ struct perf_script { int range_num; }; -static int perf_evlist__max_name_len(struct evlist *evlist) +static int evlist__max_name_len(struct evlist *evlist) { struct evsel *evsel; int max = 0; @@ -1875,7 +1875,7 @@ static void process_event(struct perf_script *script, const char *evname = evsel__name(evsel); if (!script->name_width) - script->name_width = perf_evlist__max_name_len(script->session->evlist); + script->name_width = evlist__max_name_len(script->session->evlist); fprintf(fp, "%*s: ", script->name_width, evname ?: "[unknown]"); } @@ -2120,7 +2120,7 @@ static int process_attr(struct perf_tool *tool, union perf_event *event, } if (evsel->core.attr.sample_type) { - err = perf_evsel__check_attr(evsel, scr->session); + err = evsel__check_attr(evsel, scr->session); if (err) return err; } -- cgit From 3e21a28a01e227726456a51933ed004c2df31850 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 10 Jun 2020 16:58:22 -0700 Subject: perf expr: Add d_ratio operation d_ratio avoids division by 0 yielding infinity, such as when a counter doesn't get scheduled. An example usage is: { "BriefDescription": "DCache L1 misses", "MetricExpr": "d_ratio(MEM_LOAD_RETIRED.L1_MISS, MEM_LOAD_RETIRED.L1_HIT + MEM_LOAD_RETIRED.L1_MISS + MEM_LOAD_RETIRED.FB_HIT)", "MetricGroup": "DCache;DCache_L1", "MetricName": "DCache_L1_Miss", "ScaleUnit": "100%", } Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Kajol Jain Cc: Mark Rutland Cc: Namhyung Kim Cc: Paul Clarke Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200610235823.52557-1-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/expr.c | 2 ++ tools/perf/util/expr.l | 1 + tools/perf/util/expr.y | 14 ++++++++++++-- 3 files changed, 15 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c index 1cb02ca2b15f..c4877b36ab58 100644 --- a/tools/perf/tests/expr.c +++ b/tools/perf/tests/expr.c @@ -39,6 +39,8 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused) ret |= test(&ctx, "1+1 if 3*4 else 0", 2); ret |= test(&ctx, "1.1 + 2.1", 3.2); ret |= test(&ctx, ".1 + 2.", 2.1); + ret |= test(&ctx, "d_ratio(1, 2)", 0.5); + ret |= test(&ctx, "d_ratio(2.5, 0)", 0); if (ret) return ret; diff --git a/tools/perf/util/expr.l b/tools/perf/util/expr.l index f397bf8b1a48..298d86660a96 100644 --- a/tools/perf/util/expr.l +++ b/tools/perf/util/expr.l @@ -100,6 +100,7 @@ symbol ({spec}|{sym})+ } } +d_ratio { return D_RATIO; } max { return MAX; } min { return MIN; } if { return IF; } diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y index bf3e898e3055..fe145344bb39 100644 --- a/tools/perf/util/expr.y +++ b/tools/perf/util/expr.y @@ -10,6 +10,14 @@ #include "smt.h" #include +static double d_ratio(double val0, double val1) +{ + if (val1 == 0) { + return 0; + } + return val0 / val1; +} + %} %define api.pure full @@ -28,7 +36,7 @@ %token NUMBER %token ID %destructor { free ($$); } -%token MIN MAX IF ELSE SMT_ON +%token MIN MAX IF ELSE SMT_ON D_RATIO %left MIN MAX IF %left '|' %left '^' @@ -64,7 +72,8 @@ other: ID } | MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' | ',' - +| +D_RATIO all_expr: if_expr { *final_val = $1; } ; @@ -105,6 +114,7 @@ expr: NUMBER | MIN '(' expr ',' expr ')' { $$ = $3 < $5 ? $3 : $5; } | MAX '(' expr ',' expr ')' { $$ = $3 > $5 ? $3 : $5; } | SMT_ON { $$ = smt_on() > 0; } + | D_RATIO '(' expr ',' expr ')' { $$ = d_ratio($3,$5); } ; %% -- cgit From ff1a12f962dff5b490c5ce1c2c4bcd0bf3bf517d Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 10 Jun 2020 16:58:23 -0700 Subject: perf expr: Add < and > operators These are broadly useful but required to handle TMA metrics. For example encoding Ports_Utilization from: https://download.01.org/perfmon/TMA_Metrics.csv requires '<'. { "BriefDescription": "This metric estimates fraction of cycles the CPU performance was potentially limited due to Core computation issues (non divider-related). Two distinct categories can be attributed into this metric: (1) heavy data-dependency among contiguous instructions would manifest in this metric - such cases are often referred to as low Instruction Level Parallelism (ILP). (2) Contention on some hardware execution unit other than Divider. For example; when there are too many multiply operations.", "MetricExpr": "( ( cpu@EXE_ACTIVITY.EXE_BOUND_0_PORTS@ + cpu@EXE_ACTIVITY.1_PORTS_UTIL@ + ( cpu@EXE_ACTIVITY.2_PORTS_UTIL@ * ( ( ( cpu@UOPS_RETIRED.RETIRE_SLOTS@ ) / ( cpu@CPU_CLK_UNHALTED.THREAD@ ) ) / ( ( 4.000000 ) + 1.000000 ) ) ) ) / ( cpu@CPU_CLK_UNHALTED.THREAD@ ) if ( cpu@ARITH.DIVIDER_ACTIVE\\,cmask\\=1@ < cpu@EXE_ACTIVITY.EXE_BOUND_0_PORTS@ ) else ( ( cpu@EXE_ACTIVITY.EXE_BOUND_0_PORTS@ + cpu@EXE_ACTIVITY.1_PORTS_UTIL@ + ( cpu@EXE_ACTIVITY.2_PORTS_UTIL@ * ( ( ( cpu@UOPS_RETIRED.RETIRE_SLOTS@ ) / ( cpu@CPU_CLK_UNHALTED.THREAD@ ) ) / ( ( 4.000000 ) + 1.000000 ) ) ) ) - cpu@EXE_ACTIVITY.EXE_BOUND_0_PORTS@ ) / ( cpu@CPU_CLK_UNHALTED.THREAD@ ) )", "MetricGroup": "Topdown_Group_Ports_Utilization", "MetricName": "Topdown_Metric_Ports_Utilization" }, Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Kajol Jain Cc: Mark Rutland Cc: Namhyung Kim Cc: Paul Clarke Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200610235823.52557-2-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/expr.c | 6 ++++++ tools/perf/util/expr.l | 2 ++ tools/perf/util/expr.y | 5 ++++- 3 files changed, 12 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c index c4877b36ab58..b7e5ef3007fc 100644 --- a/tools/perf/tests/expr.c +++ b/tools/perf/tests/expr.c @@ -41,6 +41,12 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused) ret |= test(&ctx, ".1 + 2.", 2.1); ret |= test(&ctx, "d_ratio(1, 2)", 0.5); ret |= test(&ctx, "d_ratio(2.5, 0)", 0); + ret |= test(&ctx, "1.1 < 2.2", 1); + ret |= test(&ctx, "2.2 > 1.1", 1); + ret |= test(&ctx, "1.1 < 1.1", 0); + ret |= test(&ctx, "2.2 > 2.2", 0); + ret |= test(&ctx, "2.2 < 1.1", 0); + ret |= test(&ctx, "1.1 > 2.2", 0); if (ret) return ret; diff --git a/tools/perf/util/expr.l b/tools/perf/util/expr.l index 298d86660a96..13e5e3c75f56 100644 --- a/tools/perf/util/expr.l +++ b/tools/perf/util/expr.l @@ -111,6 +111,8 @@ else { return ELSE; } "|" { return '|'; } "^" { return '^'; } "&" { return '&'; } +"<" { return '<'; } +">" { return '>'; } "-" { return '-'; } "+" { return '+'; } "*" { return '*'; } diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y index fe145344bb39..5fcb98800f9c 100644 --- a/tools/perf/util/expr.y +++ b/tools/perf/util/expr.y @@ -41,6 +41,7 @@ static double d_ratio(double val0, double val1) %left '|' %left '^' %left '&' +%left '<' '>' %left '-' '+' %left '*' '/' '%' %left NEG NOT @@ -73,7 +74,7 @@ other: ID | MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' | ',' | -D_RATIO +'<' | '>' | D_RATIO all_expr: if_expr { *final_val = $1; } ; @@ -94,6 +95,8 @@ expr: NUMBER | expr '|' expr { $$ = (long)$1 | (long)$3; } | expr '&' expr { $$ = (long)$1 & (long)$3; } | expr '^' expr { $$ = (long)$1 ^ (long)$3; } + | expr '<' expr { $$ = $1 < $3; } + | expr '>' expr { $$ = $1 > $3; } | expr '+' expr { $$ = $1 + $3; } | expr '-' expr { $$ = $1 - $3; } | expr '*' expr { $$ = $1 * $3; } -- cgit From 47446212832871e66f3b5fbf021c148eced2e24c Mon Sep 17 00:00:00 2001 From: Mike Leach Date: Tue, 16 Jun 2020 17:40:41 +0100 Subject: perf cs-etm: Allow no CoreSight sink to be specified on command line Adjust the handling of the session sink selection to allow no sink to be selected on the command line. This then forwards the sink selection to the CoreSight infrastructure which will attempt to select a sink based on the default sink select priorities. Signed-off-by: Mike Leach Tested-by: Leo Yan Cc: Mathieu Poirier Cc: Peter Zijlstra Cc: Suzuki Poulouse Cc: coresight@lists.linaro.org Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arm/util/cs-etm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c index cea5e33d61d2..cad7bf783413 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -243,10 +243,10 @@ static int cs_etm_set_sink_attr(struct perf_pmu *pmu, } /* - * No sink was provided on the command line - for _now_ treat - * this as an error. + * No sink was provided on the command line - allow the CoreSight + * system to look for a default */ - return ret; + return 0; } static int cs_etm_recording_options(struct auxtrace_record *itr, -- cgit From c1b4745b48b3c5a29df6ef2b68384e7cccdc3691 Mon Sep 17 00:00:00 2001 From: John Garry Date: Wed, 17 Jun 2020 17:01:53 +0800 Subject: perf pmu: List kernel supplied event aliases for arm64 In commit dc098b35b56f ("perf list: List kernel supplied event aliases"), the aliases for events are supplied in addition to CPU event in perf list. This relies on the name of the core PMU being "cpu", which is not the case for arm64, so arm64 has always missed this. Use generic is_pmu_core() helper which takes account of arm64 to make this feature work for arm64 (and possibly other archs). Sample, before: armv8_pmuv3_0/br_mis_pred/ [Kernel PMU event] after: br_mis_pred OR armv8_pmuv3_0/br_mis_pred/ [Kernel PMU event] Signed-off-by: John Garry Acked-by: Jiri Olsa Acked-by: Namhyung Kim Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ian Rogers Cc: Mark Rutland Cc: Peter Zijlstra Cc: Will Deacon Cc: linux-arm-kernel@lists.infradead.org Cc: linuxarm@huawei.com Link: http://lore.kernel.org/lkml/1592384514-119954-2-git-send-email-john.garry@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/pmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 6d51042044fd..d039879bd914 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -1477,7 +1477,7 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, list_for_each_entry(alias, &pmu->aliases, list) { char *name = alias->desc ? alias->name : format_alias(buf, sizeof(buf), pmu, alias); - bool is_cpu = !strcmp(pmu->name, "cpu"); + bool is_cpu = is_pmu_core(pmu->name); if (alias->deprecated && !deprecated) continue; -- cgit From ce0dc7d22271fa7eac3875fc9b57772742b8245e Mon Sep 17 00:00:00 2001 From: John Garry Date: Wed, 17 Jun 2020 17:01:54 +0800 Subject: perf pmu: Improve CPU core PMU HW event list ordering For perf list, the CPU core PMU HW event ordering is such that not all events may will be listed adjacent - consider this example: $ tools/perf/perf list List of pre-defined events (to be used in -e): duration_time [Tool event] branch-instructions OR cpu/branch-instructions/ [Kernel PMU event] branch-misses OR cpu/branch-misses/ [Kernel PMU event] bus-cycles OR cpu/bus-cycles/ [Kernel PMU event] cache-misses OR cpu/cache-misses/ [Kernel PMU event] cache-references OR cpu/cache-references/ [Kernel PMU event] cpu-cycles OR cpu/cpu-cycles/ [Kernel PMU event] cstate_core/c3-residency/ [Kernel PMU event] cstate_core/c6-residency/ [Kernel PMU event] cstate_core/c7-residency/ [Kernel PMU event] cstate_pkg/c2-residency/ [Kernel PMU event] cstate_pkg/c3-residency/ [Kernel PMU event] cstate_pkg/c6-residency/ [Kernel PMU event] cstate_pkg/c7-residency/ [Kernel PMU event] cycles-ct OR cpu/cycles-ct/ [Kernel PMU event] cycles-t OR cpu/cycles-t/ [Kernel PMU event] el-abort OR cpu/el-abort/ [Kernel PMU event] el-capacity OR cpu/el-capacity/ [Kernel PMU event] Notice in the above example how the cstate_core PMU events are mixed in the middle of the CPU core events. For my arm64 platform, all the uncore events get mixed in, making the list very disorganised: page-faults OR faults [Software event] task-clock [Software event] duration_time [Tool event] L1-dcache-load-misses [Hardware cache event] L1-dcache-loads [Hardware cache event] L1-icache-load-misses [Hardware cache event] L1-icache-loads [Hardware cache event] branch-load-misses [Hardware cache event] branch-loads [Hardware cache event] dTLB-load-misses [Hardware cache event] dTLB-loads [Hardware cache event] iTLB-load-misses [Hardware cache event] iTLB-loads [Hardware cache event] br_mis_pred OR armv8_pmuv3_0/br_mis_pred/ [Kernel PMU event] br_mis_pred_retired OR armv8_pmuv3_0/br_mis_pred_retired/ [Kernel PMU event] br_pred OR armv8_pmuv3_0/br_pred/ [Kernel PMU event] br_retired OR armv8_pmuv3_0/br_retired/ [Kernel PMU event] br_return_retired OR armv8_pmuv3_0/br_return_retired/ [Kernel PMU event] bus_access OR armv8_pmuv3_0/bus_access/ [Kernel PMU event] bus_cycles OR armv8_pmuv3_0/bus_cycles/ [Kernel PMU event] cid_write_retired OR armv8_pmuv3_0/cid_write_retired/ [Kernel PMU event] cpu_cycles OR armv8_pmuv3_0/cpu_cycles/ [Kernel PMU event] dtlb_walk OR armv8_pmuv3_0/dtlb_walk/ [Kernel PMU event] exc_return OR armv8_pmuv3_0/exc_return/ [Kernel PMU event] exc_taken OR armv8_pmuv3_0/exc_taken/ [Kernel PMU event] hisi_sccl1_ddrc0/act_cmd/ [Kernel PMU event] hisi_sccl1_ddrc0/flux_rcmd/ [Kernel PMU event] hisi_sccl1_ddrc0/flux_rd/ [Kernel PMU event] hisi_sccl1_ddrc0/flux_wcmd/ [Kernel PMU event] hisi_sccl1_ddrc0/flux_wr/ [Kernel PMU event] hisi_sccl1_ddrc0/pre_cmd/ [Kernel PMU event] hisi_sccl1_ddrc0/rnk_chg/ [Kernel PMU event] ... hisi_sccl7_l3c21/wr_hit_cpipe/ [Kernel PMU event] hisi_sccl7_l3c21/wr_hit_spipe/ [Kernel PMU event] hisi_sccl7_l3c21/wr_spipe/ [Kernel PMU event] inst_retired OR armv8_pmuv3_0/inst_retired/ [Kernel PMU event] inst_spec OR armv8_pmuv3_0/inst_spec/ [Kernel PMU event] itlb_walk OR armv8_pmuv3_0/itlb_walk/ [Kernel PMU event] l1d_cache OR armv8_pmuv3_0/l1d_cache/ [Kernel PMU event] l1d_cache_refill OR armv8_pmuv3_0/l1d_cache_refill/ [Kernel PMU event] l1d_cache_wb OR armv8_pmuv3_0/l1d_cache_wb/ [Kernel PMU event] l1d_tlb OR armv8_pmuv3_0/l1d_tlb/ [Kernel PMU event] l1d_tlb_refill OR armv8_pmuv3_0/l1d_tlb_refill/ [Kernel PMU event] So the events are list alphabetically. However, CPU core event listing is special from commit dc098b35b56f ("perf list: List kernel supplied event aliases"), in that the alias and full event is shown (in that order). As such, the core events may become sparse. Improve this by grouping the CPU core events and ensure that they are listed first for kernel PMU events. For the first example, above, this now looks like: duration_time [Tool event] branch-instructions OR cpu/branch-instructions/ [Kernel PMU event] branch-misses OR cpu/branch-misses/ [Kernel PMU event] bus-cycles OR cpu/bus-cycles/ [Kernel PMU event] cache-misses OR cpu/cache-misses/ [Kernel PMU event] cache-references OR cpu/cache-references/ [Kernel PMU event] cpu-cycles OR cpu/cpu-cycles/ [Kernel PMU event] cycles-ct OR cpu/cycles-ct/ [Kernel PMU event] cycles-t OR cpu/cycles-t/ [Kernel PMU event] el-abort OR cpu/el-abort/ [Kernel PMU event] el-capacity OR cpu/el-capacity/ [Kernel PMU event] el-commit OR cpu/el-commit/ [Kernel PMU event] el-conflict OR cpu/el-conflict/ [Kernel PMU event] el-start OR cpu/el-start/ [Kernel PMU event] instructions OR cpu/instructions/ [Kernel PMU event] mem-loads OR cpu/mem-loads/ [Kernel PMU event] mem-stores OR cpu/mem-stores/ [Kernel PMU event] ref-cycles OR cpu/ref-cycles/ [Kernel PMU event] topdown-fetch-bubbles OR cpu/topdown-fetch-bubbles/ [Kernel PMU event] topdown-recovery-bubbles OR cpu/topdown-recovery-bubbles/ [Kernel PMU event] topdown-slots-issued OR cpu/topdown-slots-issued/ [Kernel PMU event] topdown-slots-retired OR cpu/topdown-slots-retired/ [Kernel PMU event] topdown-total-slots OR cpu/topdown-total-slots/ [Kernel PMU event] tx-abort OR cpu/tx-abort/ [Kernel PMU event] tx-capacity OR cpu/tx-capacity/ [Kernel PMU event] tx-commit OR cpu/tx-commit/ [Kernel PMU event] tx-conflict OR cpu/tx-conflict/ [Kernel PMU event] tx-start OR cpu/tx-start/ [Kernel PMU event] cstate_core/c3-residency/ [Kernel PMU event] cstate_core/c6-residency/ [Kernel PMU event] cstate_core/c7-residency/ [Kernel PMU event] cstate_pkg/c2-residency/ [Kernel PMU event] cstate_pkg/c3-residency/ [Kernel PMU event] cstate_pkg/c6-residency/ [Kernel PMU event] cstate_pkg/c7-residency/ [Kernel PMU event] Signed-off-by: John Garry Acked-by: Jiri Olsa Acked-by: Namhyung Kim Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Andi Kleen Cc: Ian Rogers Cc: Mark Rutland Cc: Peter Zijlstra Cc: Will Deacon Cc: linux-arm-kernel@lists.infradead.org Cc: linuxarm@huawei.com Link: http://lore.kernel.org/lkml/1592384514-119954-3-git-send-email-john.garry@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/pmu.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'tools') diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index d039879bd914..f1688e1f6ed7 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -1402,6 +1402,7 @@ struct sevent { char *pmu; char *metric_expr; char *metric_name; + int is_cpu; }; static int cmp_sevent(const void *a, const void *b) @@ -1418,6 +1419,11 @@ static int cmp_sevent(const void *a, const void *b) if (n) return n; } + + /* Order CPU core events to be first */ + if (as->is_cpu != bs->is_cpu) + return bs->is_cpu - as->is_cpu; + return strcmp(as->name, bs->name); } @@ -1509,6 +1515,7 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, aliases[j].pmu = pmu->name; aliases[j].metric_expr = alias->metric_expr; aliases[j].metric_name = alias->metric_name; + aliases[j].is_cpu = is_cpu; j++; } if (pmu->selectable && -- cgit From e251abee87cf9c49a2ec1b143bd71f92b71557c1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jun 2020 09:16:20 -0300 Subject: perf evlist: Fix the class prefix for 'struct evlist' 'add' evsel methods To differentiate from libperf's 'struct perf_evlist' methods. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kvm.c | 2 +- tools/perf/builtin-record.c | 4 ++-- tools/perf/builtin-stat.c | 16 +++++++--------- tools/perf/builtin-top.c | 2 +- tools/perf/builtin-trace.c | 3 +-- tools/perf/util/evlist.c | 17 +++++++---------- tools/perf/util/evlist.h | 17 ++++++++--------- 7 files changed, 27 insertions(+), 34 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 95a77058023e..460945ded6dd 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -1319,7 +1319,7 @@ static struct evlist *kvm_live_event_list(void) *name = '\0'; name++; - if (perf_evlist__add_newtp(evlist, sys, name, NULL)) { + if (evlist__add_newtp(evlist, sys, name, NULL)) { pr_err("Failed to add %s tracepoint to the list\n", *events_tp); free(tp); goto out; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index e108d90ae2ed..1eeb58eac5df 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -852,7 +852,7 @@ static int record__open(struct record *rec) * event synthesis. */ if (opts->initial_delay || target__has_cpu(&opts->target)) { - if (perf_evlist__add_dummy(evlist)) + if (evlist__add_dummy(evlist)) return -ENOMEM; /* Disable tracking of mmaps on lead event. */ @@ -2722,7 +2722,7 @@ int cmd_record(int argc, const char **argv) record.opts.tail_synthesize = true; if (rec->evlist->core.nr_entries == 0 && - __perf_evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) { + __evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) { pr_err("Not enough memory for event selector list\n"); goto out; } diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 911b9c3538a2..922d9961ba98 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1679,19 +1679,17 @@ static int add_default_attributes(void) if (target__has_cpu(&target)) default_attrs0[0].config = PERF_COUNT_SW_CPU_CLOCK; - if (perf_evlist__add_default_attrs(evsel_list, default_attrs0) < 0) + if (evlist__add_default_attrs(evsel_list, default_attrs0) < 0) return -1; if (pmu_have_event("cpu", "stalled-cycles-frontend")) { - if (perf_evlist__add_default_attrs(evsel_list, - frontend_attrs) < 0) + if (evlist__add_default_attrs(evsel_list, frontend_attrs) < 0) return -1; } if (pmu_have_event("cpu", "stalled-cycles-backend")) { - if (perf_evlist__add_default_attrs(evsel_list, - backend_attrs) < 0) + if (evlist__add_default_attrs(evsel_list, backend_attrs) < 0) return -1; } - if (perf_evlist__add_default_attrs(evsel_list, default_attrs1) < 0) + if (evlist__add_default_attrs(evsel_list, default_attrs1) < 0) return -1; } @@ -1701,21 +1699,21 @@ static int add_default_attributes(void) return 0; /* Append detailed run extra attributes: */ - if (perf_evlist__add_default_attrs(evsel_list, detailed_attrs) < 0) + if (evlist__add_default_attrs(evsel_list, detailed_attrs) < 0) return -1; if (detailed_run < 2) return 0; /* Append very detailed run extra attributes: */ - if (perf_evlist__add_default_attrs(evsel_list, very_detailed_attrs) < 0) + if (evlist__add_default_attrs(evsel_list, very_detailed_attrs) < 0) return -1; if (detailed_run < 3) return 0; /* Append very, very detailed run extra attributes: */ - return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs); + return evlist__add_default_attrs(evsel_list, very_very_detailed_attrs); } static const char * const stat_record_usage[] = { diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 13889d73f8dd..994c230027bb 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1627,7 +1627,7 @@ int cmd_top(int argc, const char **argv) goto out_delete_evlist; if (!top.evlist->core.nr_entries && - perf_evlist__add_default(top.evlist) < 0) { + evlist__add_default(top.evlist) < 0) { pr_err("Not enough memory for event selector list\n"); goto out_delete_evlist; } diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 4cbb64edc998..b9c8b40c7135 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3917,8 +3917,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) } if (trace->sched && - perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime", - trace__sched_stat_runtime)) + evlist__add_newtp(evlist, "sched", "sched_stat_runtime", trace__sched_stat_runtime)) goto out_error_sched_stat_runtime; /* * If a global cgroup was set, apply it to all the events without an diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 173b4f0e0e6e..d574e774073c 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -79,7 +79,7 @@ struct evlist *perf_evlist__new_default(void) { struct evlist *evlist = evlist__new(); - if (evlist && perf_evlist__add_default(evlist)) { + if (evlist && evlist__add_default(evlist)) { evlist__delete(evlist); evlist = NULL; } @@ -91,7 +91,7 @@ struct evlist *perf_evlist__new_dummy(void) { struct evlist *evlist = evlist__new(); - if (evlist && perf_evlist__add_dummy(evlist)) { + if (evlist && evlist__add_dummy(evlist)) { evlist__delete(evlist); evlist = NULL; } @@ -231,7 +231,7 @@ void perf_evlist__set_leader(struct evlist *evlist) } } -int __perf_evlist__add_default(struct evlist *evlist, bool precise) +int __evlist__add_default(struct evlist *evlist, bool precise) { struct evsel *evsel = evsel__new_cycles(precise); @@ -242,7 +242,7 @@ int __perf_evlist__add_default(struct evlist *evlist, bool precise) return 0; } -int perf_evlist__add_dummy(struct evlist *evlist) +int evlist__add_dummy(struct evlist *evlist) { struct perf_event_attr attr = { .type = PERF_TYPE_SOFTWARE, @@ -258,8 +258,7 @@ int perf_evlist__add_dummy(struct evlist *evlist) return 0; } -static int evlist__add_attrs(struct evlist *evlist, - struct perf_event_attr *attrs, size_t nr_attrs) +static int evlist__add_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs) { struct evsel *evsel, *n; LIST_HEAD(head); @@ -282,8 +281,7 @@ out_delete_partial_list: return -1; } -int __perf_evlist__add_default_attrs(struct evlist *evlist, - struct perf_event_attr *attrs, size_t nr_attrs) +int __evlist__add_default_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs) { size_t i; @@ -322,8 +320,7 @@ perf_evlist__find_tracepoint_by_name(struct evlist *evlist, return NULL; } -int perf_evlist__add_newtp(struct evlist *evlist, - const char *sys, const char *name, void *handler) +int evlist__add_newtp(struct evlist *evlist, const char *sys, const char *name, void *handler) { struct evsel *evsel = evsel__newtp(sys, name); diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index b6f325dfb4d2..94f210d2f313 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -92,20 +92,20 @@ void evlist__delete(struct evlist *evlist); void evlist__add(struct evlist *evlist, struct evsel *entry); void evlist__remove(struct evlist *evlist, struct evsel *evsel); -int __perf_evlist__add_default(struct evlist *evlist, bool precise); +int __evlist__add_default(struct evlist *evlist, bool precise); -static inline int perf_evlist__add_default(struct evlist *evlist) +static inline int evlist__add_default(struct evlist *evlist) { - return __perf_evlist__add_default(evlist, true); + return __evlist__add_default(evlist, true); } -int __perf_evlist__add_default_attrs(struct evlist *evlist, +int __evlist__add_default_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs); -#define perf_evlist__add_default_attrs(evlist, array) \ - __perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array)) +#define evlist__add_default_attrs(evlist, array) \ + __evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array)) -int perf_evlist__add_dummy(struct evlist *evlist); +int evlist__add_dummy(struct evlist *evlist); int perf_evlist__add_sb_event(struct evlist *evlist, struct perf_event_attr *attr, @@ -116,8 +116,7 @@ int perf_evlist__start_sb_thread(struct evlist *evlist, struct target *target); void perf_evlist__stop_sb_thread(struct evlist *evlist); -int perf_evlist__add_newtp(struct evlist *evlist, - const char *sys, const char *name, void *handler); +int evlist__add_newtp(struct evlist *evlist, const char *sys, const char *name, void *handler); int __evlist__set_tracepoints_handlers(struct evlist *evlist, const struct evsel_str_handler *assocs, -- cgit From d1f249ecbd8413cb15f3bbad403253a183aa1d81 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jun 2020 09:19:46 -0300 Subject: perf evlist: Fix the class prefix for 'struct evlist' strerror methods To differentiate from libperf's 'struct perf_evlist' methods. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 4 ++-- tools/perf/tests/code-reading.c | 2 +- tools/perf/util/evlist.c | 5 ++--- tools/perf/util/evlist.h | 4 ++-- 4 files changed, 7 insertions(+), 8 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index b9c8b40c7135..a333a9a64f27 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -4149,11 +4149,11 @@ out_error_raw_syscalls: goto out_error; out_error_mmap: - perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf)); + evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf)); goto out_error; out_error_open: - perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf)); + evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf)); out_error: fprintf(trace->output, "%s\n", errbuf); diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 6fe221d31f07..035c9123549a 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -678,7 +678,7 @@ static int do_test_code_reading(bool try_kcore) if (verbose > 0) { char errbuf[512]; - perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf)); + evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf)); pr_debug("perf_evlist__open() failed!\n%s\n", errbuf); } diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index d574e774073c..4b7f9f9b1588 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1461,8 +1461,7 @@ int perf_evlist__parse_sample_timestamp(struct evlist *evlist, return evsel__parse_sample_timestamp(evsel, event, timestamp); } -int perf_evlist__strerror_open(struct evlist *evlist, - int err, char *buf, size_t size) +int evlist__strerror_open(struct evlist *evlist, int err, char *buf, size_t size) { int printed, value; char sbuf[STRERR_BUFSIZE], *emsg = str_error_r(err, sbuf, sizeof(sbuf)); @@ -1515,7 +1514,7 @@ out_default: return 0; } -int perf_evlist__strerror_mmap(struct evlist *evlist, int err, char *buf, size_t size) +int evlist__strerror_mmap(struct evlist *evlist, int err, char *buf, size_t size) { char sbuf[STRERR_BUFSIZE], *emsg = str_error_r(err, sbuf, sizeof(sbuf)); int pages_attempted = evlist->core.mmap_len / 1024, pages_max_per_user, printed = 0; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 94f210d2f313..a832639a8221 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -257,8 +257,8 @@ static inline struct evsel *evlist__last(struct evlist *evlist) return container_of(evsel, struct evsel, core); } -int perf_evlist__strerror_open(struct evlist *evlist, int err, char *buf, size_t size); -int perf_evlist__strerror_mmap(struct evlist *evlist, int err, char *buf, size_t size); +int evlist__strerror_open(struct evlist *evlist, int err, char *buf, size_t size); +int evlist__strerror_mmap(struct evlist *evlist, int err, char *buf, size_t size); bool perf_evlist__can_select_event(struct evlist *evlist, const char *str); void perf_evlist__to_front(struct evlist *evlist, -- cgit From b3c2cc2bd21d1d97b34fcd1a08ca7f8cc29202a0 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jun 2020 09:24:21 -0300 Subject: perf evlist: Fix the class prefix for 'struct evlist' sample_type methods To differentiate from libperf's 'struct perf_evlist' methods. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-c2c.c | 2 +- tools/perf/builtin-report.c | 6 +++--- tools/perf/builtin-script.c | 4 ++-- tools/perf/util/evlist.c | 8 ++++---- tools/perf/util/evlist.h | 6 +++--- tools/perf/util/session.c | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index d617d5682c68..5938b100eaf4 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -2582,7 +2582,7 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset) static int setup_callchain(struct evlist *evlist) { - u64 sample_type = perf_evlist__combined_sample_type(evlist); + u64 sample_type = evlist__combined_sample_type(evlist); enum perf_call_graph_mode mode = CALLCHAIN_NONE; if ((sample_type & PERF_SAMPLE_REGS_USER) && diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 5f1d2a878fad..67e0692489fa 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -338,7 +338,7 @@ static int process_read_event(struct perf_tool *tool, static int report__setup_sample_type(struct report *rep) { struct perf_session *session = rep->session; - u64 sample_type = perf_evlist__combined_sample_type(session->evlist); + u64 sample_type = evlist__combined_sample_type(session->evlist); bool is_pipe = perf_data__is_pipe(session->data); if (session->itrace_synth_opts->callchain || @@ -1093,7 +1093,7 @@ static int process_attr(struct perf_tool *tool __maybe_unused, * Check if we need to enable callchains based * on events sample_type. */ - sample_type = perf_evlist__combined_sample_type(*pevlist); + sample_type = evlist__combined_sample_type(*pevlist); callchain_param_setup(sample_type); return 0; } @@ -1389,7 +1389,7 @@ repeat: has_br_stack = perf_header__has_feat(&session->header, HEADER_BRANCH_STACK); - if (perf_evlist__combined_sample_type(session->evlist) & PERF_SAMPLE_STACK_USER) + if (evlist__combined_sample_type(session->evlist) & PERF_SAMPLE_STACK_USER) has_br_stack = false; setup_forced_leader(&report, session->evlist); diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 1ff6a8a8dde5..a47d3386f4b4 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -2129,7 +2129,7 @@ static int process_attr(struct perf_tool *tool, union perf_event *event, * Check if we need to enable callchains based * on events sample_type. */ - sample_type = perf_evlist__combined_sample_type(evlist); + sample_type = evlist__combined_sample_type(evlist); callchain_param_setup(sample_type); /* Enable fields for callchain entries */ @@ -3171,7 +3171,7 @@ static int have_cmd(int argc, const char **argv) static void script__setup_sample_type(struct perf_script *script) { struct perf_session *session = script->session; - u64 sample_type = perf_evlist__combined_sample_type(session->evlist); + u64 sample_type = evlist__combined_sample_type(session->evlist); if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) { if ((sample_type & PERF_SAMPLE_REGS_USER) && diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 4b7f9f9b1588..6415f97e2299 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1085,7 +1085,7 @@ int perf_evlist__append_tp_filter_pid(struct evlist *evlist, pid_t pid) return perf_evlist__append_tp_filter_pids(evlist, 1, &pid); } -bool perf_evlist__valid_sample_type(struct evlist *evlist) +bool evlist__valid_sample_type(struct evlist *evlist) { struct evsel *pos; @@ -1104,7 +1104,7 @@ bool perf_evlist__valid_sample_type(struct evlist *evlist) return true; } -u64 __perf_evlist__combined_sample_type(struct evlist *evlist) +u64 __evlist__combined_sample_type(struct evlist *evlist) { struct evsel *evsel; @@ -1117,10 +1117,10 @@ u64 __perf_evlist__combined_sample_type(struct evlist *evlist) return evlist->combined_sample_type; } -u64 perf_evlist__combined_sample_type(struct evlist *evlist) +u64 evlist__combined_sample_type(struct evlist *evlist) { evlist->combined_sample_type = 0; - return __perf_evlist__combined_sample_type(evlist); + return __evlist__combined_sample_type(evlist); } u64 perf_evlist__combined_branch_type(struct evlist *evlist) diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index a832639a8221..2edc1512c443 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -218,8 +218,8 @@ int perf_evlist__apply_filters(struct evlist *evlist, struct evsel **err_evsel); void __perf_evlist__set_leader(struct list_head *list); void perf_evlist__set_leader(struct evlist *evlist); -u64 __perf_evlist__combined_sample_type(struct evlist *evlist); -u64 perf_evlist__combined_sample_type(struct evlist *evlist); +u64 __evlist__combined_sample_type(struct evlist *evlist); +u64 evlist__combined_sample_type(struct evlist *evlist); u64 perf_evlist__combined_branch_type(struct evlist *evlist); bool perf_evlist__sample_id_all(struct evlist *evlist); u16 perf_evlist__id_hdr_size(struct evlist *evlist); @@ -231,7 +231,7 @@ int perf_evlist__parse_sample_timestamp(struct evlist *evlist, union perf_event *event, u64 *timestamp); -bool perf_evlist__valid_sample_type(struct evlist *evlist); +bool evlist__valid_sample_type(struct evlist *evlist); bool perf_evlist__valid_sample_id_all(struct evlist *evlist); bool perf_evlist__valid_read_format(struct evlist *evlist); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 1a157e84a04a..cbc8c476c8d3 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -115,7 +115,7 @@ static int perf_session__open(struct perf_session *session) if (perf_header__has_feat(&session->header, HEADER_STAT)) return 0; - if (!perf_evlist__valid_sample_type(session->evlist)) { + if (!evlist__valid_sample_type(session->evlist)) { pr_err("non matching sample_type\n"); return -1; } @@ -1160,7 +1160,7 @@ static void perf_evlist__print_tstamp(struct evlist *evlist, union perf_event *event, struct perf_sample *sample) { - u64 sample_type = __perf_evlist__combined_sample_type(evlist); + u64 sample_type = __evlist__combined_sample_type(evlist); if (event->header.type != PERF_RECORD_SAMPLE && !perf_evlist__sample_id_all(evlist)) { -- cgit From 8cedf3a5c1f232fd8adf60affd040d32c5d9800f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jun 2020 09:29:48 -0300 Subject: perf evlist: Fix the class prefix for 'struct evlist' sample_id_all methods To differentiate from libperf's 'struct perf_evlist' methods. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 2 +- tools/perf/util/evlist.c | 6 +++--- tools/perf/util/evlist.h | 4 ++-- tools/perf/util/session.c | 12 ++++++------ 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 1eeb58eac5df..19b1d5effb7a 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1646,7 +1646,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) * Normally perf_session__new would do this, but it doesn't have the * evlist. */ - if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) { + if (rec->tool.ordered_events && !evlist__sample_id_all(rec->evlist)) { pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); rec->tool.ordered_events = false; } diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 6415f97e2299..daae5c672344 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -537,7 +537,7 @@ struct evsel *perf_evlist__id2evsel(struct evlist *evlist, u64 id) if (sid) return container_of(sid->evsel, struct evsel, core); - if (!perf_evlist__sample_id_all(evlist)) + if (!evlist__sample_id_all(evlist)) return evlist__first(evlist); return NULL; @@ -1188,7 +1188,7 @@ out: return size; } -bool perf_evlist__valid_sample_id_all(struct evlist *evlist) +bool evlist__valid_sample_id_all(struct evlist *evlist) { struct evsel *first = evlist__first(evlist), *pos = first; @@ -1200,7 +1200,7 @@ bool perf_evlist__valid_sample_id_all(struct evlist *evlist) return true; } -bool perf_evlist__sample_id_all(struct evlist *evlist) +bool evlist__sample_id_all(struct evlist *evlist) { struct evsel *first = evlist__first(evlist); return first->core.attr.sample_id_all; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 2edc1512c443..6c7b865e435b 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -221,7 +221,7 @@ void perf_evlist__set_leader(struct evlist *evlist); u64 __evlist__combined_sample_type(struct evlist *evlist); u64 evlist__combined_sample_type(struct evlist *evlist); u64 perf_evlist__combined_branch_type(struct evlist *evlist); -bool perf_evlist__sample_id_all(struct evlist *evlist); +bool evlist__sample_id_all(struct evlist *evlist); u16 perf_evlist__id_hdr_size(struct evlist *evlist); int perf_evlist__parse_sample(struct evlist *evlist, union perf_event *event, @@ -232,7 +232,7 @@ int perf_evlist__parse_sample_timestamp(struct evlist *evlist, u64 *timestamp); bool evlist__valid_sample_type(struct evlist *evlist); -bool perf_evlist__valid_sample_id_all(struct evlist *evlist); +bool evlist__valid_sample_id_all(struct evlist *evlist); bool perf_evlist__valid_read_format(struct evlist *evlist); void perf_evlist__splice_list_tail(struct evlist *evlist, diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index cbc8c476c8d3..396424fcaadf 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -120,7 +120,7 @@ static int perf_session__open(struct perf_session *session) return -1; } - if (!perf_evlist__valid_sample_id_all(session->evlist)) { + if (!evlist__valid_sample_id_all(session->evlist)) { pr_err("non matching sample_id_all\n"); return -1; } @@ -252,10 +252,10 @@ struct perf_session *perf_session__new(struct perf_data *data, /* * In pipe-mode, evlist is empty until PERF_RECORD_HEADER_ATTR is - * processed, so perf_evlist__sample_id_all is not meaningful here. + * processed, so evlist__sample_id_all is not meaningful here. */ if ((!data || !data->is_pipe) && tool && tool->ordering_requires_timestamps && - tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) { + tool->ordered_events && !evlist__sample_id_all(session->evlist)) { dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); tool->ordered_events = false; } @@ -1163,7 +1163,7 @@ static void perf_evlist__print_tstamp(struct evlist *evlist, u64 sample_type = __evlist__combined_sample_type(evlist); if (event->header.type != PERF_RECORD_SAMPLE && - !perf_evlist__sample_id_all(evlist)) { + !evlist__sample_id_all(evlist)) { fputs("-1 -1 ", stdout); return; } @@ -1655,7 +1655,7 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset, return -1; if (session->header.needs_swap) - event_swap(event, perf_evlist__sample_id_all(session->evlist)); + event_swap(event, evlist__sample_id_all(session->evlist)); out_parse_sample: @@ -1704,7 +1704,7 @@ static s64 perf_session__process_event(struct perf_session *session, int ret; if (session->header.needs_swap) - event_swap(event, perf_evlist__sample_id_all(evlist)); + event_swap(event, evlist__sample_id_all(evlist)); if (event->header.type >= PERF_RECORD_HEADER_MAX) return -EINVAL; -- cgit From 92c7d7cdf490b1f906da04b6340ca8f56836f723 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 17 Jun 2020 09:31:25 -0300 Subject: perf evlist: Fix the class prefix for 'struct evlist' branch_type methods To differentiate from libperf's 'struct perf_evlist' methods. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 3 +-- tools/perf/builtin-script.c | 3 +-- tools/perf/util/evlist.c | 2 +- tools/perf/util/evlist.h | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 67e0692489fa..ece1cddfcd7c 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -410,8 +410,7 @@ static int report__setup_sample_type(struct report *rep) } /* ??? handle more cases than just ANY? */ - if (!(perf_evlist__combined_branch_type(session->evlist) & - PERF_SAMPLE_BRANCH_ANY)) + if (!(evlist__combined_branch_type(session->evlist) & PERF_SAMPLE_BRANCH_ANY)) rep->nonany_branch_mode = true; #if !defined(HAVE_LIBUNWIND_SUPPORT) && !defined(HAVE_DWARF_SUPPORT) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index a47d3386f4b4..6613e2bfef24 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -443,8 +443,7 @@ static int evsel__check_attr(struct evsel *evsel, struct perf_session *session) return -EINVAL; } if (PRINT_FIELD(BRSTACKINSN) && !allow_user_set && - !(perf_evlist__combined_branch_type(session->evlist) & - PERF_SAMPLE_BRANCH_ANY)) { + !(evlist__combined_branch_type(session->evlist) & PERF_SAMPLE_BRANCH_ANY)) { pr_err("Display of branch stack assembler requested, but non all-branch filter set\n" "Hint: run 'perf record -b ...'\n"); return -EINVAL; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index daae5c672344..1b884695b4d3 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1123,7 +1123,7 @@ u64 evlist__combined_sample_type(struct evlist *evlist) return __evlist__combined_sample_type(evlist); } -u64 perf_evlist__combined_branch_type(struct evlist *evlist) +u64 evlist__combined_branch_type(struct evlist *evlist) { struct evsel *evsel; u64 branch_type = 0; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 6c7b865e435b..38901c0d1599 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -220,7 +220,7 @@ void perf_evlist__set_leader(struct evlist *evlist); u64 __evlist__combined_sample_type(struct evlist *evlist); u64 evlist__combined_sample_type(struct evlist *evlist); -u64 perf_evlist__combined_branch_type(struct evlist *evlist); +u64 evlist__combined_branch_type(struct evlist *evlist); bool evlist__sample_id_all(struct evlist *evlist); u16 perf_evlist__id_hdr_size(struct evlist *evlist); -- cgit From 8d54c308c87f1b50ca088b12b89d7c0d96cf7dbf Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:47 -0700 Subject: perf parse-events: Use automatic variable for flex input This reduces the command line size slightly. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-2-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 8d18380ecd10..66cf009f78d8 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -193,7 +193,7 @@ CFLAGS_genelf_debug.o += -Wno-packed $(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) util/parse-events.l + $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/parse-events-bison.c: util/parse-events.y $(call rule_mkdir) @@ -201,7 +201,7 @@ $(OUTPUT)util/parse-events-bison.c: util/parse-events.y $(OUTPUT)util/expr-flex.c: util/expr.l $(OUTPUT)util/expr-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/expr-flex.h $(PARSER_DEBUG_FLEX) util/expr.l + $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/expr-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/expr-bison.c: util/expr.y $(call rule_mkdir) @@ -209,7 +209,7 @@ $(OUTPUT)util/expr-bison.c: util/expr.y $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h util/pmu.l + $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h $< $(OUTPUT)util/pmu-bison.c: util/pmu.y $(call rule_mkdir) -- cgit From da77a14db3a03562f70dbe4951042ff84f647d7b Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:48 -0700 Subject: perf parse-events: Use automatic variable for yacc input This reduces the command line size slightly. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-3-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 66cf009f78d8..4e1aa52d75a8 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -197,7 +197,7 @@ $(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-event $(OUTPUT)util/parse-events-bison.c: util/parse-events.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_ $(OUTPUT)util/expr-flex.c: util/expr.l $(OUTPUT)util/expr-bison.c $(call rule_mkdir) @@ -205,7 +205,7 @@ $(OUTPUT)util/expr-flex.c: util/expr.l $(OUTPUT)util/expr-bison.c $(OUTPUT)util/expr-bison.c: util/expr.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v util/expr.y -d $(PARSER_DEBUG_BISON) -o $@ -p expr_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p expr_ $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c $(call rule_mkdir) @@ -213,7 +213,7 @@ $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c $(OUTPUT)util/pmu-bison.c: util/pmu.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v util/pmu.y -d -o $@ -p perf_pmu_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d -o $@ -p perf_pmu_ CFLAGS_parse-events-flex.o += -w CFLAGS_pmu-flex.o += -w -- cgit From 5011a52fc53570b816f80b0543cb7260cffca1bd Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:49 -0700 Subject: perf pmu: Add bison debug build flag Allow pmu parser to be debugged as the parse-events and expr currently are. Enabling this requires the C code to set perf_pmu_debug. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-4-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 4e1aa52d75a8..3ae4adc8e966 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -213,7 +213,7 @@ $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c $(OUTPUT)util/pmu-bison.c: util/pmu.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d -o $@ -p perf_pmu_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p perf_pmu_ CFLAGS_parse-events-flex.o += -w CFLAGS_pmu-flex.o += -w -- cgit From 970a4a3418e626d0d4220edd4e981ecbf9d87758 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:50 -0700 Subject: perf pmu: Add flex debug build flag Allow pmu parser's flex to be debugged as the parse-events and expr currently are. Enabling this requires the C code to call perf_pmu__flex_debug. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-5-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 3ae4adc8e966..e63bfc46d50f 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -209,7 +209,7 @@ $(OUTPUT)util/expr-bison.c: util/expr.y $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h $< + $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/pmu-bison.c: util/pmu.y $(call rule_mkdir) -- cgit From 4b971df992fdf8e0d55ab3cbea9fca4ce62bcefc Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:51 -0700 Subject: perf parse-events: Declare flex header file output Declare flex header file output so that bison C files can depend upon them. As there are multiple output targets $@ is replaced by the target name. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: Jiri Olsa Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-6-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/Build b/tools/perf/util/Build index e63bfc46d50f..55c78ac53f04 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -191,25 +191,28 @@ CFLAGS_llvm-utils.o += -DPERF_INCLUDE_DIR="BUILD_STR($(perf_include_dir_SQ))" # avoid compiler warnings in 32-bit mode CFLAGS_genelf_debug.o += -Wno-packed -$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c +$(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-flex.h: util/parse-events.l $(OUTPUT)util/parse-events-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) $< + $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/parse-events-flex.c \ + --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/parse-events-bison.c: util/parse-events.y $(call rule_mkdir) $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_ -$(OUTPUT)util/expr-flex.c: util/expr.l $(OUTPUT)util/expr-bison.c +$(OUTPUT)util/expr-flex.c $(OUTPUT)util/expr-flex.h: util/expr.l $(OUTPUT)util/expr-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/expr-flex.h $(PARSER_DEBUG_FLEX) $< + $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/expr-flex.c \ + --header-file=$(OUTPUT)util/expr-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/expr-bison.c: util/expr.y $(call rule_mkdir) $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p expr_ -$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c +$(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-flex.h: util/pmu.l $(OUTPUT)util/pmu-bison.c $(call rule_mkdir) - $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h $(PARSER_DEBUG_FLEX) $< + $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/pmu-flex.c \ + --header-file=$(OUTPUT)util/pmu-flex.h $(PARSER_DEBUG_FLEX) $< $(OUTPUT)util/pmu-bison.c: util/pmu.y $(call rule_mkdir) -- cgit From 3744ca1e670e6155ead37d9123ff005b07108259 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 23 Jun 2020 10:09:03 -0300 Subject: perf expr: Add missing headers noticed when building with NO_LIBBPF=1 These will break the build as soon as we stop disabling all warnings when building flex and bison generated files, so add them before we do that to keep the tree bisectable. Noticed when building on centos:7 with NO_LIBBPF=1: util/expr.c: In function 'key_equal': util/expr.c:29:2: error: implicit declaration of function 'strcmp' [-Werror=implicit-function-declaration] return !strcmp((const char *)key1, (const char *)key2); ^ util/expr.c: In function 'expr__add_id': util/expr.c:40:3: error: implicit declaration of function 'malloc' [-Werror=implicit-function-declaration] val_ptr = malloc(sizeof(double)); ^ util/expr.c:40:13: error: incompatible implicit declaration of built-in function 'malloc' [-Werror] val_ptr = malloc(sizeof(double)); ^ util/expr.c:42:12: error: 'ENOMEM' undeclared (first use in this function) return -ENOMEM; ^ Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/expr.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tools') diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c index f64ab91c432b..e8f777830a23 100644 --- a/tools/perf/util/expr.c +++ b/tools/perf/util/expr.c @@ -1,6 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 #include #include +#include +#include +#include #include "expr.h" #include "expr-bison.h" #include "expr-flex.h" -- cgit From ef9894d9667786489f710199628e0bfffccf452a Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:52 -0700 Subject: perf parse-events: Declare bison header file output Declare bison header file output so that C files can depend upon them. As there are multiple output targets $@ is replaced by the target name. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-7-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 55c78ac53f04..504a6bb991ba 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -196,27 +196,30 @@ $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-flex.h: util/parse- $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/parse-events-flex.c \ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) $< -$(OUTPUT)util/parse-events-bison.c: util/parse-events.y +$(OUTPUT)util/parse-events-bison.c $(OUTPUT)util/parse-events-bison.h: util/parse-events.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) \ + -o $(OUTPUT)util/parse-events-bison.c -p parse_events_ $(OUTPUT)util/expr-flex.c $(OUTPUT)util/expr-flex.h: util/expr.l $(OUTPUT)util/expr-bison.c $(call rule_mkdir) $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/expr-flex.c \ --header-file=$(OUTPUT)util/expr-flex.h $(PARSER_DEBUG_FLEX) $< -$(OUTPUT)util/expr-bison.c: util/expr.y +$(OUTPUT)util/expr-bison.c $(OUTPUT)util/expr-bison.h: util/expr.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p expr_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) \ + -o $(OUTPUT)util/expr-bison.c -p expr_ $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-flex.h: util/pmu.l $(OUTPUT)util/pmu-bison.c $(call rule_mkdir) $(Q)$(call echo-cmd,flex)$(FLEX) -o $(OUTPUT)util/pmu-flex.c \ --header-file=$(OUTPUT)util/pmu-flex.h $(PARSER_DEBUG_FLEX) $< -$(OUTPUT)util/pmu-bison.c: util/pmu.y +$(OUTPUT)util/pmu-bison.c $(OUTPUT)util/pmu-bison.h: util/pmu.y $(call rule_mkdir) - $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) -o $@ -p perf_pmu_ + $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) \ + -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_ CFLAGS_parse-events-flex.o += -w CFLAGS_pmu-flex.o += -w -- cgit From 9dce29e65b38591eac0ce6786bdb725aea1eadeb Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 09:28:39 -0400 Subject: ktest.pl: Have config-bisect save each config used in the bisect When performing a automatic config bisect via ktest.pl, it is very useful to have a copy of each of the bisects used. This way, if a bisect were to go wrong, it is possible to retrace the steps and continue at the location before the error was made. The ktest.pl will make a copy of the good and bad configs, labeled as such, as well as a number attached to it that represents the iteration of the bisect. These files are saved in the ktest temp directory where it currently stores the good and bad config files. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 7570e36d636d..5f6f88911f5c 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -3188,6 +3188,8 @@ sub config_bisect_end { doprint "***************************************\n\n"; } +my $pass = 1; + sub run_config_bisect { my ($good, $bad, $last_result) = @_; my $reset = ""; @@ -3210,11 +3212,15 @@ sub run_config_bisect { $ret = run_config_bisect_test $config_bisect_type; if ($ret) { - doprint "NEW GOOD CONFIG\n"; + doprint "NEW GOOD CONFIG ($pass)\n"; + system("cp $output_config $tmpdir/good_config.tmp.$pass"); + $pass++; # Return 3 for good config return 3; } else { - doprint "NEW BAD CONFIG\n"; + doprint "NEW BAD CONFIG ($pass)\n"; + system("cp $output_config $tmpdir/bad_config.tmp.$pass"); + $pass++; # Return 4 for bad config return 4; } -- cgit From 2f059db0b8313f8964ac917394e7425d966a6884 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 10:28:23 -0400 Subject: ktest.pl: Always show log file location if defined even on success If a log file is defined and the test were to error, a print statement is made that shows the user where the log file is to examine it further. But this is not done if the test were to succeed. I find it annoying that it does not show where the log file is on success, as I run several different tests that place their log files in various locations, and even though the test pass, there's things I want to look at in the log file (like warnings). It is much easier to find where the log file is, if it is displayed at the end of a test. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 5f6f88911f5c..5d5cf3e1e81a 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -4441,6 +4441,10 @@ if ($opt{"POWEROFF_ON_SUCCESS"}) { } +if (defined($opt{"LOG_FILE"})) { + print "\n See $opt{LOG_FILE} for the record of results.\n"; +} + doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; if ($email_when_finished) { -- cgit From d53cdda3fda6e737151e091c7d9388c31a73c828 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 10:32:28 -0400 Subject: ktest.pl: Define PRE_TEST_DIE to kill the test if the PRE_TEST fails Currently, if a PRE_TEST is defined and ran, but fails, there's nothing currently available to make the test fail too. Add a PRE_TEST_DIE option that when set, if a PRE_TEST is defined and fails, the test will die too. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 8 +++++++- tools/testing/ktest/sample.conf | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 5d5cf3e1e81a..f99cf633ed84 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -98,6 +98,7 @@ my $final_post_ktest; my $pre_ktest; my $post_ktest; my $pre_test; +my $pre_test_die; my $post_test; my $pre_build; my $post_build; @@ -273,6 +274,7 @@ my %option_map = ( "PRE_KTEST" => \$pre_ktest, "POST_KTEST" => \$post_ktest, "PRE_TEST" => \$pre_test, + "PRE_TEST_DIE" => \$pre_test_die, "POST_TEST" => \$post_test, "BUILD_TYPE" => \$build_type, "BUILD_OPTIONS" => \$build_options, @@ -4347,7 +4349,11 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { doprint "RUNNING TEST $i of $opt{NUM_TESTS}$name with option $test_type $run_type$installme\n\n"; if (defined($pre_test)) { - run_command $pre_test; + my $ret = run_command $pre_test; + if (!$ret && defined($pre_test_die) && + $pre_test_die) { + dodie "failed to pre_test\n"; + } } unlink $dmesg; diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index 27666b8007ed..cb8227fbd01e 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -557,6 +557,11 @@ # default (undefined) #PRE_TEST = ${SSH} reboot_to_special_kernel +# To kill the entire test if PRE_TEST is defined but fails set this +# to 1. +# (default 0) +#PRE_TEST_DIE = 1 + # If there is a command you want to run after the individual test case # completes, then you can set this option. # -- cgit From 167234268cf6cb932ffb180586f3874ae3293a55 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 11:09:23 -0400 Subject: ktest.pl: Add a NOT operator There is a NOT DEFINED operator, but there is not an operator that can negate any other expression. For example: NOT (${FOO} == boot || ${BAR} == run) Add the keyword NOT to allow the ktest.pl config files to negate operators. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index f99cf633ed84..0d04b8a2b5a2 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -911,6 +911,12 @@ sub process_expression { } } + if ($val =~ s/^\s*NOT\s+(.*)//) { + my $express = $1; + my $ret = process_expression($name, $express); + return !$ret; + } + if ($val =~ /^\s*0\s*$/) { return 0; } elsif ($val =~ /^\s*\d+\s*$/) { -- cgit From d6bc29d987336927ff97219d5f661389f33f8f11 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 15:21:15 -0400 Subject: ktest.pl: Just open up the log file once Currently, every write to the log file is done by opening the file, writing to it, then closing the file. This rather expensive. Just open it at the beginning and close it at the end. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 0d04b8a2b5a2..f20a81bb3abe 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -509,9 +509,7 @@ EOF sub _logit { if (defined($opt{"LOG_FILE"})) { - open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; - print OUT @_; - close(OUT); + print LOG @_; } } @@ -1780,8 +1778,6 @@ sub run_command { (fail "unable to exec $command" and return 0); if (defined($opt{"LOG_FILE"})) { - open(LOG, ">>$opt{LOG_FILE}") or - dodie "failed to write to log"; $dolog = 1; } @@ -1829,7 +1825,6 @@ sub run_command { } close(CMD); - close(LOG) if ($dolog); close(RD) if ($dord); $end_time = time; @@ -4091,8 +4086,11 @@ if ($#new_configs >= 0) { } } -if ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) { - unlink $opt{"LOG_FILE"}; +if (defined($opt{"LOG_FILE"})) { + if ($opt{"CLEAR_LOG"}) { + unlink $opt{"LOG_FILE"}; + } + open(LOG, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; } doprint "\n\nSTARTING AUTOMATED TESTS\n\n"; @@ -4453,14 +4451,16 @@ if ($opt{"POWEROFF_ON_SUCCESS"}) { } -if (defined($opt{"LOG_FILE"})) { - print "\n See $opt{LOG_FILE} for the record of results.\n"; -} - doprint "\n $successes of $opt{NUM_TESTS} tests were successful\n\n"; if ($email_when_finished) { send_email("KTEST: Your test has finished!", "$successes of $opt{NUM_TESTS} tests started at $script_start_time were successful!"); } + +if (defined($opt{"LOG_FILE"})) { + print "\n See $opt{LOG_FILE} for the record of results.\n\n"; + close LOG; +} + exit 0; -- cgit From eefb9d2b8c6a781dd1026b18e37b4bcb50cff440 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 15:29:06 -0400 Subject: ktest.pl: Turn off buffering to the log file The log file should be up to date to whatever is happening in ktest. Disable buffering to the LOG output file handle. Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 2 ++ 1 file changed, 2 insertions(+) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index f20a81bb3abe..e90e2e7cb72c 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -11,6 +11,7 @@ use File::Path qw(mkpath); use File::Copy qw(cp); use FileHandle; use FindBin; +use IO::Handle; my $VERSION = "0.2"; @@ -4091,6 +4092,7 @@ if (defined($opt{"LOG_FILE"})) { unlink $opt{"LOG_FILE"}; } open(LOG, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; + LOG->autoflush(1); } doprint "\n\nSTARTING AUTOMATED TESTS\n\n"; -- cgit From 304d7a90c43f7471fb481e6b1e2b47fef2a02b8c Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:53 -0700 Subject: perf parse-events: Disable a subset of flex warnings Rather than disable all warnings with -w, disable specific warnings. Predicate enabling the warnings on more recent flex versions. Tested with GCC 9.3.0 and clang 9.0.1. Committer notes: The full set of compilers, gcc and clang that this will be tested on will be on the signed tag when this change goes upstream. Added -Wno-misleading-indentation to the flex_flags to overcome this on opensuse tumbleweed when building with clang: CC /tmp/build/perf/util/parse-events-flex.o CC /tmp/build/perf/util/pmu.o /tmp/build/perf/util/parse-events-flex.c:5038:13: error: misleading indentation; statement is not part of the previous 'if' [-Werror,-Wmisleading-indentation] if ( ! yyg->yy_state_buf ) ^ /tmp/build/perf/util/parse-events-flex.c:5036:9: note: previous statement is here if ( ! yyg->yy_state_buf ) ^ And we need to use this to redirect stderr to stdin and then grep in a way that is acceptable for BusyBox shell: 2>&1 | Previously I was using: |& Which seems to be bash specific. Added -Wno-sign-compare to overcome this on systems such as centos:7: CC /tmp/build/perf/util/parse-events-flex.o CC /tmp/build/perf/util/pmu.o CC /tmp/build/perf/util/pmu-flex.o util/parse-events.l: In function 'parse_events_lex': /tmp/build/perf/util/parse-events-flex.c:193:36: error: comparison between signed and unsigned integer expressions [-Werror=sign-compare] for ( yyl = n; yyl < yyleng; ++yyl )\ ^ /tmp/build/perf/util/parse-events-flex.c:204:9: note: in expansion of macro 'YY_LESS_LINENO' Added -Wno-unused-parameter to overcome this in systems such as centos:7: CC /tmp/build/perf/util/parse-events-flex.o CC /tmp/build/perf/util/pmu.o /tmp/build/perf/util/parse-events-flex.c: In function 'yy_fatal_error': /tmp/build/perf/util/parse-events-flex.c:6265:58: error: unused parameter 'yyscanner' [-Werror=unused-parameter] static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) ^ Added -Wno-missing-declarations to build in systems such as centos:6: /tmp/build/perf/util/parse-events-flex.c:6313: error: no previous prototype for 'parse_events_get_column' /tmp/build/perf/util/parse-events-flex.c:6389: error: no previous prototype for 'parse_events_set_column' And -Wno-missing-prototypes to cover older compilers: -Wmissing-prototypes (C only) Warn if a global function is defined without a previous prototype declaration. This warning is issued even if the definition itself provides a prototype. The aim is to detect global functions that fail to be declared in header files. -Wmissing-declarations (C only) Warn if a global function is defined without a previous declaration. Do so even if the definition itself provides a prototype. Use this option to detect global functions that are not declared in header files. Older C compilers lack -Wno-misleading-indentation, check if it is available before using it. Also needed to check just the first two levels of the flex version, as the patch was assuming that all versions were of the form x.y.z, and there are several cases where it is just x.y, breaking the build. Signed-off-by: Ian Rogers Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-8-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 504a6bb991ba..cd86a3068eab 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -221,9 +221,19 @@ $(OUTPUT)util/pmu-bison.c $(OUTPUT)util/pmu-bison.h: util/pmu.y $(Q)$(call echo-cmd,bison)$(BISON) -v $< -d $(PARSER_DEBUG_BISON) \ -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_ -CFLAGS_parse-events-flex.o += -w -CFLAGS_pmu-flex.o += -w -CFLAGS_expr-flex.o += -w +FLEX_GE_26 := $(shell expr $(shell $(FLEX) --version | sed -e 's/flex \([0-9]\+\).\([0-9]\+\)/\1\2/g') \>\= 26) +ifeq ($(FLEX_GE_26),1) + flex_flags := -Wno-switch-enum -Wno-switch-default -Wno-unused-function -Wno-redundant-decls -Wno-sign-compare -Wno-unused-parameter -Wno-missing-prototypes -Wno-missing-declarations + CC_HASNT_MISLEADING_INDENTATION := $(shell echo "int main(void) { return 0 }" | $(CC) -Werror -Wno-misleading-indentation -o /dev/null -xc - 2>&1 | grep -q -- -Wno-misleading-indentation ; echo $$?) + ifeq ($(CC_HASNT_MISLEADING_INDENTATION), 1) + flex_flags += -Wno-misleading-indentation + endif +else + flex_flags := -w +endif +CFLAGS_parse-events-flex.o += $(flex_flags) +CFLAGS_pmu-flex.o += $(flex_flags) +CFLAGS_expr-flex.o += $(flex_flags) CFLAGS_parse-events-bison.o += -DYYENABLE_NLS=0 -w CFLAGS_pmu-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w CFLAGS_expr-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w -- cgit From 1f16fcad688552d442ddf1c5d3d8d4152d9bf4af Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 18 Jun 2020 21:33:56 -0700 Subject: perf parse-events: Disable a subset of bison warnings Rather than disable all warnings with -w, disable specific warnings. Predicate enabling the warnings on a recent version of bison. Tested with GCC 9.3.0 and clang 9.0.1. Committer testing: The full set of compilers, gcc and clang that this will be tested on will be on the signed tag when this change goes upstream. Had to add -Wno-switch-enum to build on opensuse tumbleweed: /tmp/build/perf/util/parse-events-bison.c: In function 'yydestruct': /tmp/build/perf/util/parse-events-bison.c:1200:3: error: enumeration value 'YYSYMBOL_YYEMPTY' not handled in switch [-Werror=switch-enum] 1200 | switch (yykind) | ^~~~~~ /tmp/build/perf/util/parse-events-bison.c:1200:3: error: enumeration value 'YYSYMBOL_YYEOF' not handled in switch [-Werror=switch-enum] Also replace -Wno-error=implicit-function-declaration with -Wno-implicit-function-declaration. Also needed to check just the first two levels of the bison version, as the patch was assuming that all versions were of the form x.y.z, and there are several cases where it is just x.y, breaking the build. Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Jin Yao Cc: John Garry Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lore.kernel.org/lkml/20200619043356.90024-11-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/Build b/tools/perf/util/Build index cd86a3068eab..380e6a9f564d 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -234,9 +234,17 @@ endif CFLAGS_parse-events-flex.o += $(flex_flags) CFLAGS_pmu-flex.o += $(flex_flags) CFLAGS_expr-flex.o += $(flex_flags) -CFLAGS_parse-events-bison.o += -DYYENABLE_NLS=0 -w -CFLAGS_pmu-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w -CFLAGS_expr-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w + +bison_flags := -DYYENABLE_NLS=0 +BISON_GE_35 := $(shell expr $(shell $(BISON) --version | grep bison | sed -e 's/.\+ \([0-9]\+\).\([0-9]\+\)/\1\2/g') \>\= 35) +ifeq ($(BISON_GE_35),1) + bison_flags += -Wno-unused-parameter -Wno-nested-externs -Wno-implicit-function-declaration -Wno-switch-enum +else + bison_flags += -w +endif +CFLAGS_parse-events-bison.o += $(bison_flags) +CFLAGS_pmu-bison.o += -DYYLTYPE_IS_TRIVIAL=0 $(bison_flags) +CFLAGS_expr-bison.o += -DYYLTYPE_IS_TRIVIAL=0 $(bison_flags) $(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c $(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c -- cgit From 34148b13eec9c738327f8c8f84f468f4694b17a3 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 18:15:07 -0400 Subject: ktest.pl: Add the log of last test in email on failure If a failure happens and an email is sent, show the contents of the log of the last test that failed in the email. Link: http://lore.kernel.org/r/20200701231756.619246244@goodmis.org Reviewed-by: Greg Kroah-Hartman Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index e90e2e7cb72c..8a4a33492952 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -82,6 +82,8 @@ my %default = ( "IGNORE_UNUSED" => 0, ); +my $test_log_start = 0; + my $ktest_config = "ktest.conf"; my $version; my $have_version = 0; @@ -1492,8 +1494,21 @@ sub dodie { if ($email_on_error) { my $name = get_test_name; + my $log_file; + + if (defined($opt{"LOG_FILE"})) { + $log_file = "$tmpdir/log"; + open (L, "$opt{LOG_FILE}") or die "Can't open $opt{LOG_FILE} to read)"; + open (O, "> $tmpdir/log") or die "Can't open $tmpdir/log\n"; + seek(L, $test_log_start, 0); + while () { + print O; + } + close O; + close L; + } send_email("KTEST: critical failure for test $i [$name]", - "Your test started at $script_start_time has failed with:\n@_\n"); + "Your test started at $script_start_time has failed with:\n@_\n", $log_file); } if ($monitor_cnt) { @@ -4185,7 +4200,7 @@ sub find_mailer { } sub do_send_mail { - my ($subject, $message) = @_; + my ($subject, $message, $file) = @_; if (!defined($mail_path)) { # find the mailer @@ -4195,16 +4210,30 @@ sub do_send_mail { } } + my $header_file = "$tmpdir/header"; + open (HEAD, ">$header_file") or die "Can not create $header_file\n"; + print HEAD "To: $mailto\n"; + print HEAD "Subject: $subject\n\n"; + print HEAD "$message\n"; + close HEAD; + if (!defined($mail_command)) { if ($mailer eq "mail" || $mailer eq "mailx") { - $mail_command = "\$MAIL_PATH/\$MAILER -s \'\$SUBJECT\' \$MAILTO <<< \'\$MESSAGE\'"; + $mail_command = "cat \$HEADER_FILE \$BODY_FILE | \$MAIL_PATH/\$MAILER -s \'\$SUBJECT\' \$MAILTO"; } elsif ($mailer eq "sendmail" ) { - $mail_command = "echo \'Subject: \$SUBJECT\n\n\$MESSAGE\' | \$MAIL_PATH/\$MAILER -t \$MAILTO"; + $mail_command = "cat \$HEADER_FILE \$BODY_FILE | \$MAIL_PATH/\$MAILER -t \$MAILTO"; } else { die "\nYour mailer: $mailer is not supported.\n"; } } + if (defined($file)) { + $mail_command =~ s/\$BODY_FILE/$file/g; + } else { + $mail_command =~ s/\$BODY_FILE//g; + } + + $mail_command =~ s/\$HEADER_FILE/$header_file/g; $mail_command =~ s/\$MAILER/$mailer/g; $mail_command =~ s/\$MAIL_PATH/$mail_path/g; $mail_command =~ s/\$MAILTO/$mailto/g; @@ -4352,6 +4381,11 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { } doprint "\n\n"; + + if (defined($opt{"LOG_FILE"})) { + $test_log_start = tell(LOG); + } + doprint "RUNNING TEST $i of $opt{NUM_TESTS}$name with option $test_type $run_type$installme\n\n"; if (defined($pre_test)) { -- cgit From f986900209093f5de887d6c342139df6ebec04ac Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 1 Jul 2020 18:34:10 -0400 Subject: ktest.pl: Add MAIL_MAX_SIZE to limit the amount of log emailed Add the ktest config option MAIL_MAX_SIZE that will limit the size of the log file that is placed into the email on failure. Link: https://lore.kernel.org/r/20200701231756.790637968@goodmis.org Reviewed-by: Greg Kroah-Hartman Signed-off-by: Steven Rostedt (VMware) --- tools/testing/ktest/ktest.pl | 12 +++++++++++- tools/testing/ktest/sample.conf | 13 +++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 8a4a33492952..36db5b0b3647 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -227,6 +227,7 @@ my $dirname = $FindBin::Bin; my $mailto; my $mailer; my $mail_path; +my $mail_max_size; my $mail_command; my $email_on_error; my $email_when_finished; @@ -263,6 +264,7 @@ my %option_map = ( "MAILTO" => \$mailto, "MAILER" => \$mailer, "MAIL_PATH" => \$mail_path, + "MAIL_MAX_SIZE" => \$mail_max_size, "MAIL_COMMAND" => \$mail_command, "EMAIL_ON_ERROR" => \$email_on_error, "EMAIL_WHEN_FINISHED" => \$email_when_finished, @@ -1497,10 +1499,18 @@ sub dodie { my $log_file; if (defined($opt{"LOG_FILE"})) { + my $size = 0; + if (defined($mail_max_size)) { + my $log_size = tell LOG; + $log_size -= $test_log_start; + if ($log_size > $mail_max_size) { + $size = $log_size - $mail_max_size; + } + } $log_file = "$tmpdir/log"; open (L, "$opt{LOG_FILE}") or die "Can't open $opt{LOG_FILE} to read)"; open (O, "> $tmpdir/log") or die "Can't open $tmpdir/log\n"; - seek(L, $test_log_start, 0); + seek(L, $test_log_start + $size, 0); while () { print O; } diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index cb8227fbd01e..5e7d1d729752 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -442,6 +442,19 @@ # Users can cancel the test by Ctrl^C # (default 0) #EMAIL_WHEN_CANCELED = 1 +# +# If a test ends with an error and EMAIL_ON_ERROR is set as well +# as a LOG_FILE is defined, then the log of the failing test will +# be included in the email that is sent. +# It is possible that the log may be very large, in which case, +# only the last amount of the log should be sent. To limit how +# much of the log is sent, set MAIL_MAX_SIZE. This will be the +# size in bytes of the last portion of the log of the failed +# test file. That is, if this is set to 100000, then only the +# last 100 thousand bytes of the log file will be included in +# the email. +# (default undef) +#MAIL_MAX_SIZE = 1000000 # Start a test setup. If you leave this off, all options # will be default and the test will run once. -- cgit From 662081acfa25edf0d8fabd8021ac26f0d1e2d3a1 Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Thu, 2 Jul 2020 14:53:47 -0400 Subject: tools lib traceevent: Add tep_load_plugins_hook() API Add the API function tep_load_plugins_hook() to the traceevent API to allow tools a common method to load in the plugins that are part of the lib traceevent library. Link: http://lore.kernel.org/linux-trace-devel/20190802110101.14759-4-tz.stoyanov@gmail.com Link: http://lore.kernel.org/linux-trace-devel/20200625100516.365338-4-tz.stoyanov@gmail.com Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: linux-trace-devel@vger.kernel.org Link: http://lore.kernel.org/lkml/20200702185703.946652691@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 6 ++++++ tools/lib/traceevent/event-plugin.c | 19 +++++++++---------- 2 files changed, 15 insertions(+), 10 deletions(-) (limited to 'tools') diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index b77837f75a0d..776c7c24ee79 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -396,6 +396,12 @@ struct tep_plugin_list; struct tep_plugin_list *tep_load_plugins(struct tep_handle *tep); void tep_unload_plugins(struct tep_plugin_list *plugin_list, struct tep_handle *tep); +void tep_load_plugins_hook(struct tep_handle *tep, const char *suffix, + void (*load_plugin)(struct tep_handle *tep, + const char *path, + const char *name, + void *data), + void *data); char **tep_plugin_list_options(void); void tep_plugin_free_options_list(char **list); int tep_plugin_add_options(const char *name, diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c index e1f7ddd5a6cf..b53d9a53bcf9 100644 --- a/tools/lib/traceevent/event-plugin.c +++ b/tools/lib/traceevent/event-plugin.c @@ -365,20 +365,19 @@ load_plugins_dir(struct tep_handle *tep, const char *suffix, closedir(dir); } -static void -load_plugins(struct tep_handle *tep, const char *suffix, - void (*load_plugin)(struct tep_handle *tep, - const char *path, - const char *name, - void *data), - void *data) +void tep_load_plugins_hook(struct tep_handle *tep, const char *suffix, + void (*load_plugin)(struct tep_handle *tep, + const char *path, + const char *name, + void *data), + void *data) { char *home; char *path; char *envdir; int ret; - if (tep->flags & TEP_DISABLE_PLUGINS) + if (tep && tep->flags & TEP_DISABLE_PLUGINS) return; /* @@ -386,7 +385,7 @@ load_plugins(struct tep_handle *tep, const char *suffix, * check that first. */ #ifdef PLUGIN_DIR - if (!(tep->flags & TEP_DISABLE_SYS_PLUGINS)) + if (!tep || !(tep->flags & TEP_DISABLE_SYS_PLUGINS)) load_plugins_dir(tep, suffix, PLUGIN_DIR, load_plugin, data); #endif @@ -423,7 +422,7 @@ tep_load_plugins(struct tep_handle *tep) { struct tep_plugin_list *list = NULL; - load_plugins(tep, ".so", load_plugin, &list); + tep_load_plugins_hook(tep, ".so", load_plugin, &list); return list; } -- cgit From 74006289cfedbb2f922fcd6fef7efee232450550 Mon Sep 17 00:00:00 2001 From: "Tzvetomir Stoyanov (VMware)" Date: Thu, 2 Jul 2020 14:53:48 -0400 Subject: tools lib traceevent: Add interface for options to plugins Add tep_plugin_add_option() and tep_plugin_print_options() to lib traceevent library that allows plugins to have their own options. For example, the function plugin by default does not print the parent, as it uses the parent to do the indenting. The "parent" option is created by the function plugin that will print the parent of the function like it does in the trace file. The tep_plugin_print_options() will print out the list of options that a Cc: Tzvetomir Stoyanov (VMware) plugin has defined. Link: http://lore.kernel.org/linux-trace-devel/20190802110101.14759-3-tz.stoyanov@gmail.com Link: http://lore.kernel.org/linux-trace-devel/20200625100516.365338-5-tz.stoyanov@gmail.com Signed-off-by: Tzvetomir Stoyanov (VMware) Cc: Andrew Morton Cc: Jiri Olsa Cc: Namhyung Kim Cc: linux-trace-devel@vger.kernel.org Link: http://lore.kernel.org/lkml/20200702185704.092654084@goodmis.org Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 2 + tools/lib/traceevent/event-plugin.c | 172 ++++++++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+) (limited to 'tools') diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 776c7c24ee79..02c0438527de 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -406,7 +406,9 @@ char **tep_plugin_list_options(void); void tep_plugin_free_options_list(char **list); int tep_plugin_add_options(const char *name, struct tep_plugin_option *options); +int tep_plugin_add_option(const char *name, const char *val); void tep_plugin_remove_options(struct tep_plugin_option *options); +void tep_plugin_print_options(struct trace_seq *s); void tep_print_plugins(struct trace_seq *s, const char *prefix, const char *suffix, const struct tep_plugin_list *list); diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c index b53d9a53bcf9..e8f4329ba8e0 100644 --- a/tools/lib/traceevent/event-plugin.c +++ b/tools/lib/traceevent/event-plugin.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "event-parse.h" #include "event-parse-local.h" #include "event-utils.h" @@ -247,6 +248,166 @@ void tep_plugin_remove_options(struct tep_plugin_option *options) } } +static void parse_option_name(char **option, char **plugin) +{ + char *p; + + *plugin = NULL; + + if ((p = strstr(*option, ":"))) { + *plugin = *option; + *p = '\0'; + *option = strdup(p + 1); + if (!*option) + return; + } +} + +static struct tep_plugin_option * +find_registered_option(const char *plugin, const char *option) +{ + struct registered_plugin_options *reg; + struct tep_plugin_option *op; + const char *op_plugin; + + for (reg = registered_options; reg; reg = reg->next) { + for (op = reg->options; op->name; op++) { + if (op->plugin_alias) + op_plugin = op->plugin_alias; + else + op_plugin = op->file; + + if (plugin && strcmp(plugin, op_plugin) != 0) + continue; + if (strcmp(option, op->name) != 0) + continue; + + return op; + } + } + + return NULL; +} + +static int process_option(const char *plugin, const char *option, const char *val) +{ + struct tep_plugin_option *op; + + op = find_registered_option(plugin, option); + if (!op) + return 0; + + return update_option_value(op, val); +} + +/** + * tep_plugin_add_option - add an option/val pair to set plugin options + * @name: The name of the option (format: :