From 411ad22ecf0281d666a82aa7f4de90c70365da7d Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Tue, 2 May 2023 15:38:36 -0700 Subject: perf parse-events: Add pmu filter To support the cputype argument added to "perf stat" for hybrid it is necessary to filter events during wildcard matching. Add a scanner argument for the filter and checking it when wildcard matching. Signed-off-by: Ian Rogers Tested-by: Kan Liang Cc: Adrian Hunter Cc: Ahmad Yasin Cc: Alexander Shishkin Cc: Andi Kleen Cc: Athira Rajeev Cc: Caleb Biggers Cc: Edward Baker Cc: Florian Fischer Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: John Garry Cc: Kajol Jain Cc: Kang Minchul Cc: Leo Yan Cc: Mark Rutland Cc: Namhyung Kim Cc: Perry Taylor Cc: Peter Zijlstra Cc: Ravi Bangoria Cc: Rob Herring Cc: Samantha Alt Cc: Stephane Eranian Cc: Sumanth Korikkar Cc: Suzuki Poulouse Cc: Thomas Richter Cc: Tiezhu Yang Cc: Weilin Wang Cc: Xing Zhengjun Cc: Yang Jihong Link: https://lore.kernel.org/r/20230502223851.2234828-30-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'tools/perf/builtin-record.c') diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index efa03e4ac2c9..ec0f2d5f189f 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -3335,6 +3335,14 @@ const char record_callchain_help[] = CALLCHAIN_RECORD_HELP static bool dry_run; +static struct parse_events_option_args parse_events_option_args = { + .evlistp = &record.evlist, +}; + +static struct parse_events_option_args switch_output_parse_events_option_args = { + .evlistp = &record.sb_evlist, +}; + /* * XXX Will stay a global variable till we fix builtin-script.c to stop messing * with it and switch to use the library functions in perf_evlist that came @@ -3343,7 +3351,7 @@ static bool dry_run; * using pipes, etc. */ static struct option __record_options[] = { - OPT_CALLBACK('e', "event", &record.evlist, "event", + OPT_CALLBACK('e', "event", &parse_events_option_args, "event", "event selector. use 'perf list' to list available events", parse_events_option), OPT_CALLBACK(0, "filter", &record.evlist, "filter", @@ -3496,7 +3504,8 @@ static struct option __record_options[] = { &record.switch_output.set, "signal or size[BKMG] or time[smhd]", "Switch output when receiving SIGUSR2 (signal) or cross a size or time threshold", "signal"), - OPT_CALLBACK_SET(0, "switch-output-event", &record.sb_evlist, &record.switch_output_event_set, "switch output event", + OPT_CALLBACK_SET(0, "switch-output-event", &switch_output_parse_events_option_args, + &record.switch_output_event_set, "switch output event", "switch output event selector. use 'perf list' to list available events", parse_events_option_new_evlist), OPT_INTEGER(0, "switch-max-files", &record.switch_output.num_files, -- cgit v1.2.3 From 8ec984d53714dfa538f3f5b1e22a309ac18edf63 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 27 May 2023 00:21:46 -0700 Subject: perf target: Remove unused hybrid value Previously this was used to modify CPU map propagation, but it is now unnecessary as map propagation ensure core PMUs only have valid PMUs in the CPU map from user requested CPUs. Reviewed-by: Kan Liang Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ali Saidi Cc: Athira Rajeev Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Huacai Chen Cc: Ingo Molnar Cc: James Clark Cc: Jing Zhang Cc: Jiri Olsa Cc: John Garry Cc: Kajol Jain Cc: Kang Minchul Cc: Leo Yan Cc: Madhavan Srinivasan Cc: Mark Rutland Cc: Mike Leach Cc: Ming Wang Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Ravi Bangoria Cc: Rob Herring Cc: Sandipan Das Cc: Sean Christopherson Cc: Suzuki Poulouse Cc: Thomas Richter Cc: Will Deacon Cc: Xing Zhengjun Cc: coresight@lists.linaro.org Cc: linux-arm-kernel@lists.infradead.org Link: https://lore.kernel.org/r/20230527072210.2900565-11-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 2 -- tools/perf/builtin-stat.c | 1 - tools/perf/util/target.h | 1 - 3 files changed, 4 deletions(-) (limited to 'tools/perf/builtin-record.c') diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index ec0f2d5f189f..d152ab04a209 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -4204,8 +4204,6 @@ int cmd_record(int argc, const char **argv) goto out; } - rec->opts.target.hybrid = perf_pmu__has_hybrid(); - if (callchain_param.enabled && callchain_param.record_mode == CALLCHAIN_FP) arch__add_leaf_frame_record_opts(&rec->opts); diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 176deeb8ee66..8d4c4f4ca8ea 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -2730,7 +2730,6 @@ int cmd_stat(int argc, const char **argv) goto out; } - target.hybrid = perf_pmu__has_hybrid(); if (evlist__create_maps(evsel_list, &target) < 0) { if (target__has_task(&target)) { pr_err("Problems finding threads of monitor\n"); diff --git a/tools/perf/util/target.h b/tools/perf/util/target.h index 880f1af7f6ad..d582cae8e105 100644 --- a/tools/perf/util/target.h +++ b/tools/perf/util/target.h @@ -17,7 +17,6 @@ struct target { bool default_per_cpu; bool per_thread; bool use_bpf; - bool hybrid; int initial_delay; const char *attr_map; }; -- cgit v1.2.3 From 5ac72634482143a8be5e04e5d09a2026f6a94315 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 27 May 2023 00:21:47 -0700 Subject: perf tools: Warn if no user requested CPUs match PMU's CPUs In commit 1d3351e631fc ("perf tools: Enable on a list of CPUs for hybrid") perf on hybrid will warn if a user requested CPU doesn't match the PMU of the given event but only for hybrid PMUs. Make the logic generic for all PMUs and remove the hybrid logic. Warn if a CPU is requested that isn't present/offline for events not on the core. Warn if a CPU is requested for a core PMU, but the CPU isn't within the cpu map of that PMU. For example on a 16 (0-15) CPU system: ``` $ perf stat -e imc_free_running/data_read/,cycles -C 16 true WARNING: A requested CPU in '16' is not supported by PMU 'uncore_imc_free_running_1' (CPUs 0-15) for event 'imc_free_running/data_read/' WARNING: A requested CPU in '16' is not supported by PMU 'uncore_imc_free_running_0' (CPUs 0-15) for event 'imc_free_running/data_read/' WARNING: A requested CPU in '16' is not supported by PMU 'cpu' (CPUs 0-15) for event 'cycles' Performance counter stats for 'CPU(s) 16': MiB imc_free_running/data_read/ cycles 0.000575312 seconds time elapsed ``` Remove evlist__fix_hybrid_cpus that previously produced the warnings and also perf_pmu__cpus_match that worked with evlist__fix_hybrid_cpus to change CPU maps for hybrid CPUs, something that is no longer necessary as CPU map propagation properly intersects user requested CPUs with the core PMU's CPU map. Reviewed-by: Kan Liang Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ali Saidi Cc: Athira Rajeev Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Huacai Chen Cc: Ingo Molnar Cc: James Clark Cc: Jing Zhang Cc: Jiri Olsa Cc: John Garry Cc: Kajol Jain Cc: Kang Minchul Cc: Leo Yan Cc: Madhavan Srinivasan Cc: Mark Rutland Cc: Mike Leach Cc: Ming Wang Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Ravi Bangoria Cc: Rob Herring Cc: Sandipan Das Cc: Sean Christopherson Cc: Suzuki Poulouse Cc: Thomas Richter Cc: Will Deacon Cc: Xing Zhengjun Cc: coresight@lists.linaro.org Cc: linux-arm-kernel@lists.infradead.org Link: https://lore.kernel.org/r/20230527072210.2900565-12-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 6 +--- tools/perf/builtin-stat.c | 5 +-- tools/perf/util/evlist-hybrid.c | 74 ----------------------------------------- tools/perf/util/evlist-hybrid.h | 1 - tools/perf/util/evlist.c | 39 ++++++++++++++++++++++ tools/perf/util/evlist.h | 2 ++ tools/perf/util/pmu.c | 33 ------------------ tools/perf/util/pmu.h | 4 --- 8 files changed, 43 insertions(+), 121 deletions(-) (limited to 'tools/perf/builtin-record.c') diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index d152ab04a209..88f7b4241153 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -4198,11 +4198,7 @@ int cmd_record(int argc, const char **argv) /* Enable ignoring missing threads when -u/-p option is defined. */ rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX || rec->opts.target.pid; - if (evlist__fix_hybrid_cpus(rec->evlist, rec->opts.target.cpu_list)) { - pr_err("failed to use cpu list %s\n", - rec->opts.target.cpu_list); - goto out; - } + evlist__warn_user_requested_cpus(rec->evlist, rec->opts.target.cpu_list); if (callchain_param.enabled && callchain_param.record_mode == CALLCHAIN_FP) arch__add_leaf_frame_record_opts(&rec->opts); diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 8d4c4f4ca8ea..84d304cffd2c 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -2725,10 +2725,7 @@ int cmd_stat(int argc, const char **argv) } } - if (evlist__fix_hybrid_cpus(evsel_list, target.cpu_list)) { - pr_err("failed to use cpu list %s\n", target.cpu_list); - goto out; - } + evlist__warn_user_requested_cpus(evsel_list, target.cpu_list); if (evlist__create_maps(evsel_list, &target) < 0) { if (target__has_task(&target)) { diff --git a/tools/perf/util/evlist-hybrid.c b/tools/perf/util/evlist-hybrid.c index 57f02beef023..db3f5fbdebe1 100644 --- a/tools/perf/util/evlist-hybrid.c +++ b/tools/perf/util/evlist-hybrid.c @@ -86,77 +86,3 @@ bool evlist__has_hybrid(struct evlist *evlist) return false; } - -int evlist__fix_hybrid_cpus(struct evlist *evlist, const char *cpu_list) -{ - struct perf_cpu_map *cpus; - struct evsel *evsel, *tmp; - struct perf_pmu *pmu; - int ret, unmatched_count = 0, events_nr = 0; - - if (!perf_pmu__has_hybrid() || !cpu_list) - return 0; - - cpus = perf_cpu_map__new(cpu_list); - if (!cpus) - return -1; - - /* - * The evsels are created with hybrid pmu's cpus. But now we - * need to check and adjust the cpus of evsel by cpu_list because - * cpu_list may cause conflicts with cpus of evsel. For example, - * cpus of evsel is cpu0-7, but the cpu_list is cpu6-8, we need - * to adjust the cpus of evsel to cpu6-7. And then propatate maps - * in evlist__create_maps(). - */ - evlist__for_each_entry_safe(evlist, tmp, evsel) { - struct perf_cpu_map *matched_cpus, *unmatched_cpus; - char buf1[128], buf2[128]; - - pmu = perf_pmu__find_hybrid_pmu(evsel->pmu_name); - if (!pmu) - continue; - - ret = perf_pmu__cpus_match(pmu, cpus, &matched_cpus, - &unmatched_cpus); - if (ret) - goto out; - - events_nr++; - - if (perf_cpu_map__nr(matched_cpus) > 0 && - (perf_cpu_map__nr(unmatched_cpus) > 0 || - perf_cpu_map__nr(matched_cpus) < perf_cpu_map__nr(cpus) || - perf_cpu_map__nr(matched_cpus) < perf_cpu_map__nr(pmu->cpus))) { - perf_cpu_map__put(evsel->core.cpus); - perf_cpu_map__put(evsel->core.own_cpus); - evsel->core.cpus = perf_cpu_map__get(matched_cpus); - evsel->core.own_cpus = perf_cpu_map__get(matched_cpus); - - if (perf_cpu_map__nr(unmatched_cpus) > 0) { - cpu_map__snprint(matched_cpus, buf1, sizeof(buf1)); - pr_warning("WARNING: use %s in '%s' for '%s', skip other cpus in list.\n", - buf1, pmu->name, evsel->name); - } - } - - if (perf_cpu_map__nr(matched_cpus) == 0) { - evlist__remove(evlist, evsel); - evsel__delete(evsel); - - cpu_map__snprint(cpus, buf1, sizeof(buf1)); - cpu_map__snprint(pmu->cpus, buf2, sizeof(buf2)); - pr_warning("WARNING: %s isn't a '%s', please use a CPU list in the '%s' range (%s)\n", - buf1, pmu->name, pmu->name, buf2); - unmatched_count++; - } - - perf_cpu_map__put(matched_cpus); - perf_cpu_map__put(unmatched_cpus); - } - if (events_nr) - ret = (unmatched_count == events_nr) ? -1 : 0; -out: - perf_cpu_map__put(cpus); - return ret; -} diff --git a/tools/perf/util/evlist-hybrid.h b/tools/perf/util/evlist-hybrid.h index aacdb1b0f948..19f74b4c340a 100644 --- a/tools/perf/util/evlist-hybrid.h +++ b/tools/perf/util/evlist-hybrid.h @@ -10,6 +10,5 @@ int evlist__add_default_hybrid(struct evlist *evlist, bool precise); void evlist__warn_hybrid_group(struct evlist *evlist); bool evlist__has_hybrid(struct evlist *evlist); -int evlist__fix_hybrid_cpus(struct evlist *evlist, const char *cpu_list); #endif /* __PERF_EVLIST_HYBRID_H */ diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 2e2c3509bec3..9dfa977193b3 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -2465,3 +2465,42 @@ void evlist__check_mem_load_aux(struct evlist *evlist) } } } + +/** + * evlist__warn_user_requested_cpus() - Check each evsel against requested CPUs + * and warn if the user CPU list is inapplicable for the event's PMU's + * CPUs. Not core PMUs list a CPU in sysfs, but this may be overwritten by a + * user requested CPU and so any online CPU is applicable. Core PMUs handle + * events on the CPUs in their list and otherwise the event isn't supported. + * @evlist: The list of events being checked. + * @cpu_list: The user provided list of CPUs. + */ +void evlist__warn_user_requested_cpus(struct evlist *evlist, const char *cpu_list) +{ + struct perf_cpu_map *user_requested_cpus; + struct evsel *pos; + + if (!cpu_list) + return; + + user_requested_cpus = perf_cpu_map__new(cpu_list); + if (!user_requested_cpus) + return; + + evlist__for_each_entry(evlist, pos) { + struct perf_cpu_map *intersect, *to_test; + const struct perf_pmu *pmu = evsel__find_pmu(pos); + + to_test = pmu && pmu->is_core ? pmu->cpus : cpu_map__online(); + intersect = perf_cpu_map__intersect(to_test, user_requested_cpus); + if (!perf_cpu_map__equal(intersect, user_requested_cpus)) { + char buf[128]; + + cpu_map__snprint(to_test, buf, sizeof(buf)); + pr_warning("WARNING: A requested CPU in '%s' is not supported by PMU '%s' (CPUs %s) for event '%s'\n", + cpu_list, pmu ? pmu->name : "cpu", buf, evsel__name(pos)); + } + perf_cpu_map__put(intersect); + } + perf_cpu_map__put(user_requested_cpus); +} diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index e7e5540cc970..5e7ff44f3043 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -447,4 +447,6 @@ struct evsel *evlist__find_evsel(struct evlist *evlist, int idx); int evlist__scnprintf_evsels(struct evlist *evlist, size_t size, char *bf); void evlist__check_mem_load_aux(struct evlist *evlist); +void evlist__warn_user_requested_cpus(struct evlist *evlist, const char *cpu_list); + #endif /* __PERF_EVLIST_H */ diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index d992f5242d99..cd94abe7a87a 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -2046,39 +2046,6 @@ int perf_pmu__match(char *pattern, char *name, char *tok) return 0; } -int perf_pmu__cpus_match(struct perf_pmu *pmu, struct perf_cpu_map *cpus, - struct perf_cpu_map **mcpus_ptr, - struct perf_cpu_map **ucpus_ptr) -{ - struct perf_cpu_map *pmu_cpus = pmu->cpus; - struct perf_cpu_map *matched_cpus, *unmatched_cpus; - struct perf_cpu cpu; - int i, matched_nr = 0, unmatched_nr = 0; - - matched_cpus = perf_cpu_map__default_new(); - if (!matched_cpus) - return -1; - - unmatched_cpus = perf_cpu_map__default_new(); - if (!unmatched_cpus) { - perf_cpu_map__put(matched_cpus); - return -1; - } - - perf_cpu_map__for_each_cpu(cpu, i, cpus) { - if (!perf_cpu_map__has(pmu_cpus, cpu)) - RC_CHK_ACCESS(unmatched_cpus)->map[unmatched_nr++] = cpu; - else - RC_CHK_ACCESS(matched_cpus)->map[matched_nr++] = cpu; - } - - perf_cpu_map__set_nr(unmatched_cpus, unmatched_nr); - perf_cpu_map__set_nr(matched_cpus, matched_nr); - *mcpus_ptr = matched_cpus; - *ucpus_ptr = unmatched_cpus; - return 0; -} - double __weak perf_pmu__cpu_slots_per_cycle(void) { return NAN; diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index 96236a79c6fd..af10d137e2b5 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -265,10 +265,6 @@ void perf_pmu__warn_invalid_formats(struct perf_pmu *pmu); bool perf_pmu__has_hybrid(void); int perf_pmu__match(char *pattern, char *name, char *tok); -int perf_pmu__cpus_match(struct perf_pmu *pmu, struct perf_cpu_map *cpus, - struct perf_cpu_map **mcpus_ptr, - struct perf_cpu_map **ucpus_ptr); - char *pmu_find_real_name(const char *name); char *pmu_find_alias_name(const char *name); double perf_pmu__cpu_slots_per_cycle(void); -- cgit v1.2.3 From 7b100989b4f6bce7090ef89badf4091b1730d14c Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 27 May 2023 00:21:49 -0700 Subject: perf evlist: Remove __evlist__add_default __evlist__add_default adds a cycles event to a typically empty evlist and was extended for hybrid with evlist__add_default_hybrid, as more than 1 PMU was necessary. Rather than have dedicated logic for the cycles event, this change switches to parsing 'cycles:P' which will handle wildcarding the PMUs appropriately for hybrid. Reviewed-by: Kan Liang Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ali Saidi Cc: Athira Rajeev Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Huacai Chen Cc: Ingo Molnar Cc: James Clark Cc: Jing Zhang Cc: Jiri Olsa Cc: John Garry Cc: Kajol Jain Cc: Kang Minchul Cc: Leo Yan Cc: Madhavan Srinivasan Cc: Mark Rutland Cc: Mike Leach Cc: Ming Wang Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Ravi Bangoria Cc: Rob Herring Cc: Sandipan Das Cc: Sean Christopherson Cc: Suzuki Poulouse Cc: Thomas Richter Cc: Will Deacon Cc: Xing Zhengjun Cc: coresight@lists.linaro.org Cc: linux-arm-kernel@lists.infradead.org Link: https://lore.kernel.org/r/20230527072210.2900565-14-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/util/evsel.c | 20 ----------------- tools/perf/builtin-record.c | 13 +++--------- tools/perf/builtin-top.c | 10 +++++---- tools/perf/util/evlist-hybrid.c | 25 ---------------------- tools/perf/util/evlist-hybrid.h | 1 - tools/perf/util/evlist.c | 22 +++++++------------ tools/perf/util/evlist.h | 7 ------ tools/perf/util/evsel.c | 46 ---------------------------------------- tools/perf/util/evsel.h | 3 --- tools/perf/util/python.c | 8 +++++++ 10 files changed, 25 insertions(+), 130 deletions(-) (limited to 'tools/perf/builtin-record.c') diff --git a/tools/perf/arch/x86/util/evsel.c b/tools/perf/arch/x86/util/evsel.c index ea3972d785d1..153cdca94cd4 100644 --- a/tools/perf/arch/x86/util/evsel.c +++ b/tools/perf/arch/x86/util/evsel.c @@ -16,26 +16,6 @@ void arch_evsel__set_sample_weight(struct evsel *evsel) evsel__set_sample_bit(evsel, WEIGHT_STRUCT); } -void arch_evsel__fixup_new_cycles(struct perf_event_attr *attr) -{ - struct perf_env env = { .total_mem = 0, } ; - - if (!perf_env__cpuid(&env)) - return; - - /* - * On AMD, precise cycles event sampling internally uses IBS pmu. - * But IBS does not have filtering capabilities and perf by default - * sets exclude_guest = 1. This makes IBS pmu event init fail and - * thus perf ends up doing non-precise sampling. Avoid it by clearing - * exclude_guest. - */ - if (env.cpuid && strstarts(env.cpuid, "AuthenticAMD")) - attr->exclude_guest = 0; - - free(env.cpuid); -} - /* Check whether the evsel's PMU supports the perf metrics */ bool evsel__sys_has_perf_metrics(const struct evsel *evsel) { diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 88f7b4241153..d80b54a6f450 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -4161,18 +4161,11 @@ int cmd_record(int argc, const char **argv) record.opts.tail_synthesize = true; if (rec->evlist->core.nr_entries == 0) { - if (perf_pmu__has_hybrid()) { - err = evlist__add_default_hybrid(rec->evlist, - !record.opts.no_samples); - } else { - err = __evlist__add_default(rec->evlist, - !record.opts.no_samples); - } + bool can_profile_kernel = perf_event_paranoid_check(1); - if (err < 0) { - pr_err("Not enough memory for event selector list\n"); + err = parse_event(rec->evlist, can_profile_kernel ? "cycles:P" : "cycles:Pu"); + if (err) goto out; - } } if (rec->opts.target.tid && !rec->opts.no_inherit_set) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 48ee49e95c5e..27a7f068207d 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1653,10 +1653,12 @@ int cmd_top(int argc, const char **argv) if (annotate_check_args(&top.annotation_opts) < 0) goto out_delete_evlist; - if (!top.evlist->core.nr_entries && - evlist__add_default(top.evlist) < 0) { - pr_err("Not enough memory for event selector list\n"); - goto out_delete_evlist; + if (!top.evlist->core.nr_entries) { + bool can_profile_kernel = perf_event_paranoid_check(1); + int err = parse_event(top.evlist, can_profile_kernel ? "cycles:P" : "cycles:Pu"); + + if (err) + goto out_delete_evlist; } status = evswitch__init(&top.evswitch, top.evlist, stderr); diff --git a/tools/perf/util/evlist-hybrid.c b/tools/perf/util/evlist-hybrid.c index 0f59c80f27b2..64f78d06fe19 100644 --- a/tools/perf/util/evlist-hybrid.c +++ b/tools/perf/util/evlist-hybrid.c @@ -16,31 +16,6 @@ #include #include -int evlist__add_default_hybrid(struct evlist *evlist, bool precise) -{ - struct evsel *evsel; - struct perf_pmu *pmu; - __u64 config; - struct perf_cpu_map *cpus; - - perf_pmu__for_each_hybrid_pmu(pmu) { - config = PERF_COUNT_HW_CPU_CYCLES | - ((__u64)pmu->type << PERF_PMU_TYPE_SHIFT); - evsel = evsel__new_cycles(precise, PERF_TYPE_HARDWARE, - config); - if (!evsel) - return -ENOMEM; - - cpus = perf_cpu_map__get(pmu->cpus); - evsel->core.cpus = cpus; - evsel->core.own_cpus = perf_cpu_map__get(cpus); - evsel->pmu_name = strdup(pmu->name); - evlist__add(evlist, evsel); - } - - return 0; -} - bool evlist__has_hybrid(struct evlist *evlist) { struct evsel *evsel; diff --git a/tools/perf/util/evlist-hybrid.h b/tools/perf/util/evlist-hybrid.h index 4b000eda6626..0cded76eb344 100644 --- a/tools/perf/util/evlist-hybrid.h +++ b/tools/perf/util/evlist-hybrid.h @@ -7,7 +7,6 @@ #include "evlist.h" #include -int evlist__add_default_hybrid(struct evlist *evlist, bool precise); bool evlist__has_hybrid(struct evlist *evlist); #endif /* __PERF_EVLIST_HYBRID_H */ diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 9dfa977193b3..63f8821a5395 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -93,8 +93,15 @@ struct evlist *evlist__new(void) struct evlist *evlist__new_default(void) { struct evlist *evlist = evlist__new(); + bool can_profile_kernel; + int err; + + if (!evlist) + return NULL; - if (evlist && evlist__add_default(evlist)) { + can_profile_kernel = perf_event_paranoid_check(1); + err = parse_event(evlist, can_profile_kernel ? "cycles:P" : "cycles:Pu"); + if (err) { evlist__delete(evlist); evlist = NULL; } @@ -237,19 +244,6 @@ static void evlist__set_leader(struct evlist *evlist) perf_evlist__set_leader(&evlist->core); } -int __evlist__add_default(struct evlist *evlist, bool precise) -{ - struct evsel *evsel; - - evsel = evsel__new_cycles(precise, PERF_TYPE_HARDWARE, - PERF_COUNT_HW_CPU_CYCLES); - if (evsel == NULL) - return -ENOMEM; - - evlist__add(evlist, evsel); - return 0; -} - static struct evsel *evlist__dummy_event(struct evlist *evlist) { struct perf_event_attr attr = { diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 5e7ff44f3043..664c6bf7b3e0 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -100,13 +100,6 @@ 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 __evlist__add_default(struct evlist *evlist, bool precise); - -static inline int evlist__add_default(struct evlist *evlist) -{ - return __evlist__add_default(evlist, true); -} - int evlist__add_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs); int __evlist__add_default_attrs(struct evlist *evlist, diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 8c8f371ea2b5..1df8f967d2eb 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -316,48 +316,6 @@ struct evsel *evsel__new_idx(struct perf_event_attr *attr, int idx) return evsel; } -static bool perf_event_can_profile_kernel(void) -{ - return perf_event_paranoid_check(1); -} - -struct evsel *evsel__new_cycles(bool precise __maybe_unused, __u32 type, __u64 config) -{ - struct perf_event_attr attr = { - .type = type, - .config = config, - .exclude_kernel = !perf_event_can_profile_kernel(), - }; - struct evsel *evsel; - - event_attr_init(&attr); - - /* - * Now let the usual logic to set up the perf_event_attr defaults - * to kick in when we return and before perf_evsel__open() is called. - */ - evsel = evsel__new(&attr); - if (evsel == NULL) - goto out; - - arch_evsel__fixup_new_cycles(&evsel->core.attr); - - evsel->precise_max = true; - - /* use asprintf() because free(evsel) assumes name is allocated */ - if (asprintf(&evsel->name, "cycles%s%s%.*s", - (attr.precise_ip || attr.exclude_kernel) ? ":" : "", - attr.exclude_kernel ? "u" : "", - attr.precise_ip ? attr.precise_ip + 1 : 0, "ppp") < 0) - goto error_free; -out: - return evsel; -error_free: - evsel__delete(evsel); - evsel = NULL; - goto out; -} - int copy_config_terms(struct list_head *dst, struct list_head *src) { struct evsel_config_term *pos, *tmp; @@ -1131,10 +1089,6 @@ void __weak arch_evsel__set_sample_weight(struct evsel *evsel) evsel__set_sample_bit(evsel, WEIGHT); } -void __weak arch_evsel__fixup_new_cycles(struct perf_event_attr *attr __maybe_unused) -{ -} - void __weak arch__post_evsel_config(struct evsel *evsel __maybe_unused, struct perf_event_attr *attr __maybe_unused) { diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index df8928745fc6..429b172cc94d 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -243,8 +243,6 @@ static inline struct evsel *evsel__newtp(const char *sys, const char *name) } #endif -struct evsel *evsel__new_cycles(bool precise, __u32 type, __u64 config); - #ifdef HAVE_LIBTRACEEVENT struct tep_event *event_format__new(const char *sys, const char *name); #endif @@ -312,7 +310,6 @@ void __evsel__reset_sample_bit(struct evsel *evsel, enum perf_event_sample_forma void evsel__set_sample_id(struct evsel *evsel, bool use_sample_identifier); void arch_evsel__set_sample_weight(struct evsel *evsel); -void arch_evsel__fixup_new_cycles(struct perf_event_attr *attr); void arch__post_evsel_config(struct evsel *evsel, struct perf_event_attr *attr); int evsel__set_filter(struct evsel *evsel, const char *filter); diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 0faea4c75eed..3c1f4c979c9e 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -49,6 +49,14 @@ #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) #endif +/* + * Avoid bringing in event parsing. + */ +int parse_event(struct evlist *evlist __maybe_unused, const char *str __maybe_unused) +{ + return 0; +} + /* * Provide these two so that we don't have to link against callchain.c and * start dragging hist.c, etc. -- cgit v1.2.3 From b167b530eb83dfd791061e1d312236bffde772a4 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 27 May 2023 00:21:50 -0700 Subject: perf evlist: Reduce scope of evlist__has_hybrid Function is only used in printout, reduce scope to stat-display.c. Remove the now empty evlist-hybrid.c and evlist-hybrid.h. Reviewed-by: Kan Liang Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ali Saidi Cc: Athira Rajeev Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Huacai Chen Cc: Ingo Molnar Cc: James Clark Cc: Jing Zhang Cc: Jiri Olsa Cc: John Garry Cc: Kajol Jain Cc: Kang Minchul Cc: Leo Yan Cc: Madhavan Srinivasan Cc: Mark Rutland Cc: Mike Leach Cc: Ming Wang Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Ravi Bangoria Cc: Rob Herring Cc: Sandipan Das Cc: Sean Christopherson Cc: Suzuki Poulouse Cc: Thomas Richter Cc: Will Deacon Cc: Xing Zhengjun Cc: coresight@lists.linaro.org Cc: linux-arm-kernel@lists.infradead.org Link: https://lore.kernel.org/r/20230527072210.2900565-15-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 1 - tools/perf/builtin-stat.c | 1 - tools/perf/util/Build | 1 - tools/perf/util/evlist-hybrid.c | 31 ------------------------------- tools/perf/util/evlist-hybrid.h | 12 ------------ tools/perf/util/evlist.c | 1 - tools/perf/util/stat-display.c | 15 ++++++++++++++- 7 files changed, 14 insertions(+), 48 deletions(-) delete mode 100644 tools/perf/util/evlist-hybrid.c delete mode 100644 tools/perf/util/evlist-hybrid.h (limited to 'tools/perf/builtin-record.c') diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index d80b54a6f450..e30e8d6a6575 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -50,7 +50,6 @@ #include "util/pfm.h" #include "util/clockid.h" #include "util/pmu-hybrid.h" -#include "util/evlist-hybrid.h" #include "util/off_cpu.h" #include "util/bpf-filter.h" #include "asm/bug.h" diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index d414ee30dcf9..62bbeea93bf3 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -48,7 +48,6 @@ #include "util/pmu.h" #include "util/event.h" #include "util/evlist.h" -#include "util/evlist-hybrid.h" #include "util/evsel.h" #include "util/debug.h" #include "util/color.h" diff --git a/tools/perf/util/Build b/tools/perf/util/Build index c146736ead19..21e4cdcba504 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -11,7 +11,6 @@ perf-y += db-export.o perf-y += env.o perf-y += event.o perf-y += evlist.o -perf-y += evlist-hybrid.o perf-y += sideband_evlist.o perf-y += evsel.o perf-y += evsel_fprintf.o diff --git a/tools/perf/util/evlist-hybrid.c b/tools/perf/util/evlist-hybrid.c deleted file mode 100644 index 64f78d06fe19..000000000000 --- a/tools/perf/util/evlist-hybrid.c +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -#include -#include -#include "cpumap.h" -#include "evlist.h" -#include "evsel.h" -#include "../perf.h" -#include "util/pmu-hybrid.h" -#include "util/evlist-hybrid.h" -#include "debug.h" -#include -#include -#include -#include -#include -#include -#include - -bool evlist__has_hybrid(struct evlist *evlist) -{ - struct evsel *evsel; - - evlist__for_each_entry(evlist, evsel) { - if (evsel->pmu_name && - perf_pmu__is_hybrid(evsel->pmu_name)) { - return true; - } - } - - return false; -} diff --git a/tools/perf/util/evlist-hybrid.h b/tools/perf/util/evlist-hybrid.h deleted file mode 100644 index 0cded76eb344..000000000000 --- a/tools/perf/util/evlist-hybrid.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __PERF_EVLIST_HYBRID_H -#define __PERF_EVLIST_HYBRID_H - -#include -#include -#include "evlist.h" -#include - -bool evlist__has_hybrid(struct evlist *evlist); - -#endif /* __PERF_EVLIST_HYBRID_H */ diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 63f8821a5395..82c0b3d0c822 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -28,7 +28,6 @@ #include "util/string2.h" #include "util/perf_api_probe.h" #include "util/evsel_fprintf.h" -#include "util/evlist-hybrid.h" #include "util/pmu.h" #include "util/sample.h" #include "util/bpf-filter.h" diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index 319f456f0673..4cce7d3c5e52 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -20,7 +20,6 @@ #include "util.h" #include "iostat.h" #include "pmu-hybrid.h" -#include "evlist-hybrid.h" #define CNTR_NOT_SUPPORTED "" #define CNTR_NOT_COUNTED "" @@ -692,6 +691,20 @@ static bool is_mixed_hw_group(struct evsel *counter) return false; } +static bool evlist__has_hybrid(struct evlist *evlist) +{ + struct evsel *evsel; + + evlist__for_each_entry(evlist, evsel) { + if (evsel->pmu_name && + perf_pmu__is_hybrid(evsel->pmu_name)) { + return true; + } + } + + return false; +} + static void printout(struct perf_stat_config *config, struct outstate *os, double uval, u64 run, u64 ena, double noise, int aggr_idx) { -- cgit v1.2.3 From 597a4276fb326163b90754ef7b2a550a6b2b4054 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 27 May 2023 00:22:00 -0700 Subject: perf pmu: Remove perf_pmu__hybrid_pmus list Rather than iterate hybrid PMUs, inhererently Intel specific, iterate all PMUs checking whether they are core. To only get hybrid cores, first call perf_pmu__has_hybrid. Reviewed-by: Kan Liang Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ali Saidi Cc: Athira Rajeev Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Huacai Chen Cc: Ingo Molnar Cc: James Clark Cc: Jing Zhang Cc: Jiri Olsa Cc: John Garry Cc: Kajol Jain Cc: Kang Minchul Cc: Leo Yan Cc: Madhavan Srinivasan Cc: Mark Rutland Cc: Mike Leach Cc: Ming Wang Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Ravi Bangoria Cc: Rob Herring Cc: Sandipan Das Cc: Sean Christopherson Cc: Suzuki Poulouse Cc: Thomas Richter Cc: Will Deacon Cc: Xing Zhengjun Cc: coresight@lists.linaro.org Cc: linux-arm-kernel@lists.infradead.org Link: https://lore.kernel.org/r/20230527072210.2900565-25-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 1 - tools/perf/util/Build | 1 - tools/perf/util/pmu-hybrid.c | 39 -------------------------------------- tools/perf/util/pmu-hybrid.h | 29 ---------------------------- tools/perf/util/pmu.c | 7 ------- tools/perf/util/pmu.h | 2 -- tools/perf/util/print-events.c | 1 - tools/perf/util/python-ext-sources | 1 - 8 files changed, 81 deletions(-) delete mode 100644 tools/perf/util/pmu-hybrid.c delete mode 100644 tools/perf/util/pmu-hybrid.h (limited to 'tools/perf/builtin-record.c') diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index e30e8d6a6575..2abcad2998f6 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -49,7 +49,6 @@ #include "util/util.h" #include "util/pfm.h" #include "util/clockid.h" -#include "util/pmu-hybrid.h" #include "util/off_cpu.h" #include "util/bpf-filter.h" #include "asm/bug.h" diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 21e4cdcba504..0d68be51a739 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -73,7 +73,6 @@ perf-y += pmu.o perf-y += pmus.o perf-y += pmu-flex.o perf-y += pmu-bison.o -perf-y += pmu-hybrid.o perf-y += svghelper.o perf-$(CONFIG_LIBTRACEEVENT) += trace-event-info.o perf-y += trace-event-scripting.o diff --git a/tools/perf/util/pmu-hybrid.c b/tools/perf/util/pmu-hybrid.c deleted file mode 100644 index 7fe943dd3217..000000000000 --- a/tools/perf/util/pmu-hybrid.c +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "fncache.h" -#include "pmu-hybrid.h" - -LIST_HEAD(perf_pmu__hybrid_pmus); - -static struct perf_pmu *perf_pmu__find_hybrid_pmu(const char *name) -{ - struct perf_pmu *pmu; - - if (!name) - return NULL; - - perf_pmu__for_each_hybrid_pmu(pmu) { - if (!strcmp(name, pmu->name)) - return pmu; - } - - return NULL; -} - -bool perf_pmu__is_hybrid(const char *name) -{ - return perf_pmu__find_hybrid_pmu(name) != NULL; -} diff --git a/tools/perf/util/pmu-hybrid.h b/tools/perf/util/pmu-hybrid.h deleted file mode 100644 index 8dbcae935020..000000000000 --- a/tools/perf/util/pmu-hybrid.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __PMU_HYBRID_H -#define __PMU_HYBRID_H - -#include -#include -#include -#include -#include "pmu.h" - -extern struct list_head perf_pmu__hybrid_pmus; - -#define perf_pmu__for_each_hybrid_pmu(pmu) \ - list_for_each_entry(pmu, &perf_pmu__hybrid_pmus, hybrid_list) - -bool perf_pmu__is_hybrid(const char *name); - -static inline int perf_pmu__hybrid_pmu_num(void) -{ - struct perf_pmu *pmu; - int num = 0; - - perf_pmu__for_each_hybrid_pmu(pmu) - num++; - - return num; -} - -#endif /* __PMU_HYBRID_H */ diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 65daa0cc71d6..21ee23b78f5a 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -32,7 +32,6 @@ #include "string2.h" #include "strbuf.h" #include "fncache.h" -#include "pmu-hybrid.h" #include "util/evsel_config.h" struct perf_pmu perf_pmu__fake; @@ -954,11 +953,6 @@ static struct perf_pmu *pmu_lookup(int dirfd, const char *lookup_name) list_splice(&aliases, &pmu->aliases); list_add_tail(&pmu->list, &pmus); - if (!strcmp(name, "cpu_core") || !strcmp(name, "cpu_atom")) - list_add_tail(&pmu->hybrid_list, &perf_pmu__hybrid_pmus); - else - INIT_LIST_HEAD(&pmu->hybrid_list); - pmu->default_config = perf_pmu__get_default_config(pmu); return pmu; @@ -2131,7 +2125,6 @@ void perf_pmu__destroy(void) list_for_each_entry_safe(pmu, tmp, &pmus, list) { list_del(&pmu->list); - list_del(&pmu->hybrid_list); perf_pmu__delete(pmu); } diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index 5f5de7c20ab6..cb51ad6e40fa 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -119,8 +119,6 @@ struct perf_pmu { struct list_head caps; /** @list: Element on pmus list in pmu.c. */ struct list_head list; - /** @hybrid_list: Element on perf_pmu__hybrid_pmus. */ - struct list_head hybrid_list; /** * @missing_features: Features to inhibit when events on this PMU are diff --git a/tools/perf/util/print-events.c b/tools/perf/util/print-events.c index 69492cbd6921..8d823bc906e6 100644 --- a/tools/perf/util/print-events.c +++ b/tools/perf/util/print-events.c @@ -26,7 +26,6 @@ #include "strlist.h" #include "tracepoint.h" #include "pfm.h" -#include "pmu-hybrid.h" #include "thread_map.h" #define MAX_NAME_LEN 100 diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources index aa5156c2bcff..d4c9b4cd35ef 100644 --- a/tools/perf/util/python-ext-sources +++ b/tools/perf/util/python-ext-sources @@ -39,5 +39,4 @@ util/affinity.c util/rwsem.c util/hashmap.c util/perf_regs.c -util/pmu-hybrid.c util/fncache.c -- cgit v1.2.3 From 1eaf496ed386934f1c2439a120fe84a05194f91a Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 27 May 2023 00:22:03 -0700 Subject: perf pmu: Separate pmu and pmus Separate and hide the pmus list in pmus.[ch]. Move pmus functionality out of pmu.[ch] into pmus.[ch] renaming pmus functions which were prefixed perf_pmu__ to perf_pmus__. Reviewed-by: Kan Liang Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ali Saidi Cc: Athira Rajeev Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Huacai Chen Cc: Ingo Molnar Cc: James Clark Cc: Jing Zhang Cc: Jiri Olsa Cc: John Garry Cc: Kajol Jain Cc: Kang Minchul Cc: Leo Yan Cc: Madhavan Srinivasan Cc: Mark Rutland Cc: Mike Leach Cc: Ming Wang Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Ravi Bangoria Cc: Rob Herring Cc: Sandipan Das Cc: Sean Christopherson Cc: Suzuki Poulouse Cc: Thomas Richter Cc: Will Deacon Cc: Xing Zhengjun Cc: coresight@lists.linaro.org Cc: linux-arm-kernel@lists.infradead.org Link: https://lore.kernel.org/r/20230527072210.2900565-28-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/arm/util/auxtrace.c | 7 +- tools/perf/arch/arm/util/cs-etm.c | 4 +- tools/perf/arch/arm64/util/pmu.c | 3 +- tools/perf/arch/x86/tests/hybrid.c | 5 +- tools/perf/arch/x86/util/auxtrace.c | 5 +- tools/perf/arch/x86/util/evlist.c | 5 +- tools/perf/arch/x86/util/evsel.c | 7 +- tools/perf/arch/x86/util/intel-bts.c | 4 +- tools/perf/arch/x86/util/intel-pt.c | 4 +- tools/perf/arch/x86/util/mem-events.c | 9 +- tools/perf/arch/x86/util/perf_regs.c | 5 +- tools/perf/arch/x86/util/topdown.c | 5 +- tools/perf/bench/pmu-scan.c | 10 +- tools/perf/builtin-c2c.c | 4 +- tools/perf/builtin-list.c | 4 +- tools/perf/builtin-mem.c | 4 +- tools/perf/builtin-record.c | 6 +- tools/perf/builtin-stat.c | 4 +- tools/perf/tests/attr.c | 4 +- tools/perf/tests/event_groups.c | 2 +- tools/perf/tests/parse-events.c | 8 +- tools/perf/tests/parse-metric.c | 4 +- tools/perf/tests/pmu-events.c | 3 +- tools/perf/tests/switch-tracking.c | 4 +- tools/perf/tests/topology.c | 4 +- tools/perf/util/cputopo.c | 7 +- tools/perf/util/env.c | 5 +- tools/perf/util/evsel.c | 3 +- tools/perf/util/header.c | 15 +- tools/perf/util/mem-events.c | 11 +- tools/perf/util/metricgroup.c | 5 +- tools/perf/util/parse-events.c | 15 +- tools/perf/util/parse-events.y | 3 +- tools/perf/util/pfm.c | 6 +- tools/perf/util/pmu.c | 411 +--------------------------------- tools/perf/util/pmu.h | 13 +- tools/perf/util/pmus.c | 396 +++++++++++++++++++++++++++++++- tools/perf/util/pmus.h | 14 +- tools/perf/util/print-events.c | 5 +- tools/perf/util/python.c | 3 +- tools/perf/util/stat-display.c | 3 +- 41 files changed, 533 insertions(+), 506 deletions(-) (limited to 'tools/perf/builtin-record.c') diff --git a/tools/perf/arch/arm/util/auxtrace.c b/tools/perf/arch/arm/util/auxtrace.c index adec6c9ee11d..3b8eca0ffb17 100644 --- a/tools/perf/arch/arm/util/auxtrace.c +++ b/tools/perf/arch/arm/util/auxtrace.c @@ -14,6 +14,7 @@ #include "../../../util/debug.h" #include "../../../util/evlist.h" #include "../../../util/pmu.h" +#include "../../../util/pmus.h" #include "cs-etm.h" #include "arm-spe.h" #include "hisi-ptt.h" @@ -40,7 +41,7 @@ static struct perf_pmu **find_all_arm_spe_pmus(int *nr_spes, int *err) return NULL; } - arm_spe_pmus[*nr_spes] = perf_pmu__find(arm_spe_pmu_name); + arm_spe_pmus[*nr_spes] = perf_pmus__find(arm_spe_pmu_name); if (arm_spe_pmus[*nr_spes]) { pr_debug2("%s %d: arm_spe_pmu %d type %d name %s\n", __func__, __LINE__, *nr_spes, @@ -87,7 +88,7 @@ static struct perf_pmu **find_all_hisi_ptt_pmus(int *nr_ptts, int *err) rewinddir(dir); while ((dent = readdir(dir))) { if (strstr(dent->d_name, HISI_PTT_PMU_NAME) && idx < *nr_ptts) { - hisi_ptt_pmus[idx] = perf_pmu__find(dent->d_name); + hisi_ptt_pmus[idx] = perf_pmus__find(dent->d_name); if (hisi_ptt_pmus[idx]) idx++; } @@ -131,7 +132,7 @@ struct auxtrace_record if (!evlist) return NULL; - cs_etm_pmu = perf_pmu__find(CORESIGHT_ETM_PMU_NAME); + cs_etm_pmu = perf_pmus__find(CORESIGHT_ETM_PMU_NAME); arm_spe_pmus = find_all_arm_spe_pmus(&nr_spes, err); hisi_ptt_pmus = find_all_hisi_ptt_pmus(&nr_ptts, err); diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c index 9ca040bfb1aa..7c51fa182b51 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -25,7 +25,7 @@ #include "../../../util/evsel.h" #include "../../../util/perf_api_probe.h" #include "../../../util/evsel_config.h" -#include "../../../util/pmu.h" +#include "../../../util/pmus.h" #include "../../../util/cs-etm.h" #include // page_size #include "../../../util/session.h" @@ -881,7 +881,7 @@ struct auxtrace_record *cs_etm_record_init(int *err) struct perf_pmu *cs_etm_pmu; struct cs_etm_recording *ptr; - cs_etm_pmu = perf_pmu__find(CORESIGHT_ETM_PMU_NAME); + cs_etm_pmu = perf_pmus__find(CORESIGHT_ETM_PMU_NAME); if (!cs_etm_pmu) { *err = -EINVAL; diff --git a/tools/perf/arch/arm64/util/pmu.c b/tools/perf/arch/arm64/util/pmu.c index ef1ed645097c..2504d43a39a7 100644 --- a/tools/perf/arch/arm64/util/pmu.c +++ b/tools/perf/arch/arm64/util/pmu.c @@ -3,6 +3,7 @@ #include #include "../../../util/cpumap.h" #include "../../../util/pmu.h" +#include "../../../util/pmus.h" #include #include @@ -10,7 +11,7 @@ static struct perf_pmu *pmu__find_core_pmu(void) { struct perf_pmu *pmu = NULL; - while ((pmu = perf_pmu__scan(pmu))) { + while ((pmu = perf_pmus__scan(pmu))) { if (!is_pmu_core(pmu->name)) continue; diff --git a/tools/perf/arch/x86/tests/hybrid.c b/tools/perf/arch/x86/tests/hybrid.c index 944bd1b4bab6..e466735d68d5 100644 --- a/tools/perf/arch/x86/tests/hybrid.c +++ b/tools/perf/arch/x86/tests/hybrid.c @@ -4,6 +4,7 @@ #include "evlist.h" #include "evsel.h" #include "pmu.h" +#include "pmus.h" #include "tests/tests.h" static bool test_config(const struct evsel *evsel, __u64 expected_config) @@ -113,7 +114,7 @@ static int test__hybrid_raw1(struct evlist *evlist) struct perf_evsel *evsel; perf_evlist__for_each_evsel(&evlist->core, evsel) { - struct perf_pmu *pmu = perf_pmu__find_by_type(evsel->attr.type); + struct perf_pmu *pmu = perf_pmus__find_by_type(evsel->attr.type); TEST_ASSERT_VAL("missing pmu", pmu); TEST_ASSERT_VAL("unexpected pmu", !strncmp(pmu->name, "cpu_", 4)); @@ -280,7 +281,7 @@ static int test_events(const struct evlist_test *events, int cnt) int test__hybrid(struct test_suite *test __maybe_unused, int subtest __maybe_unused) { - if (!perf_pmu__has_hybrid()) + if (!perf_pmus__has_hybrid()) return TEST_SKIP; return test_events(test__hybrid_events, ARRAY_SIZE(test__hybrid_events)); diff --git a/tools/perf/arch/x86/util/auxtrace.c b/tools/perf/arch/x86/util/auxtrace.c index 330d03216b0e..354780ff1605 100644 --- a/tools/perf/arch/x86/util/auxtrace.c +++ b/tools/perf/arch/x86/util/auxtrace.c @@ -10,6 +10,7 @@ #include "../../../util/header.h" #include "../../../util/debug.h" #include "../../../util/pmu.h" +#include "../../../util/pmus.h" #include "../../../util/auxtrace.h" #include "../../../util/intel-pt.h" #include "../../../util/intel-bts.h" @@ -25,8 +26,8 @@ struct auxtrace_record *auxtrace_record__init_intel(struct evlist *evlist, bool found_pt = false; bool found_bts = false; - intel_pt_pmu = perf_pmu__find(INTEL_PT_PMU_NAME); - intel_bts_pmu = perf_pmu__find(INTEL_BTS_PMU_NAME); + intel_pt_pmu = perf_pmus__find(INTEL_PT_PMU_NAME); + intel_bts_pmu = perf_pmus__find(INTEL_BTS_PMU_NAME); evlist__for_each_entry(evlist, evsel) { if (intel_pt_pmu && evsel->core.attr.type == intel_pt_pmu->type) diff --git a/tools/perf/arch/x86/util/evlist.c b/tools/perf/arch/x86/util/evlist.c index 03f7eb4cf0a4..03240c640c7f 100644 --- a/tools/perf/arch/x86/util/evlist.c +++ b/tools/perf/arch/x86/util/evlist.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include #include "util/pmu.h" +#include "util/pmus.h" #include "util/evlist.h" #include "util/parse-events.h" #include "util/event.h" @@ -17,7 +18,7 @@ static int ___evlist__add_default_attrs(struct evlist *evlist, for (i = 0; i < nr_attrs; i++) event_attr_init(attrs + i); - if (!perf_pmu__has_hybrid()) + if (!perf_pmus__has_hybrid()) return evlist__add_attrs(evlist, attrs, nr_attrs); for (i = 0; i < nr_attrs; i++) { @@ -32,7 +33,7 @@ static int ___evlist__add_default_attrs(struct evlist *evlist, continue; } - while ((pmu = perf_pmu__scan(pmu)) != NULL) { + while ((pmu = perf_pmus__scan(pmu)) != NULL) { struct perf_cpu_map *cpus; struct evsel *evsel; diff --git a/tools/perf/arch/x86/util/evsel.c b/tools/perf/arch/x86/util/evsel.c index 153cdca94cd4..25da46c8cca9 100644 --- a/tools/perf/arch/x86/util/evsel.c +++ b/tools/perf/arch/x86/util/evsel.c @@ -4,6 +4,7 @@ #include "util/evsel.h" #include "util/env.h" #include "util/pmu.h" +#include "util/pmus.h" #include "linux/string.h" #include "evsel.h" #include "util/debug.h" @@ -30,7 +31,7 @@ bool evsel__sys_has_perf_metrics(const struct evsel *evsel) * should be good enough to detect the perf metrics feature. */ if ((evsel->core.attr.type == PERF_TYPE_RAW) && - pmu_have_event(pmu_name, "slots")) + perf_pmus__have_event(pmu_name, "slots")) return true; return false; @@ -98,8 +99,8 @@ void arch__post_evsel_config(struct evsel *evsel, struct perf_event_attr *attr) if (!evsel_pmu) return; - ibs_fetch_pmu = perf_pmu__find("ibs_fetch"); - ibs_op_pmu = perf_pmu__find("ibs_op"); + ibs_fetch_pmu = perf_pmus__find("ibs_fetch"); + ibs_op_pmu = perf_pmus__find("ibs_op"); if (ibs_fetch_pmu && ibs_fetch_pmu->type == evsel_pmu->type) { if (attr->config & IBS_FETCH_L3MISSONLY) { diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c index 439c2956f3e7..d2c8cac11470 100644 --- a/tools/perf/arch/x86/util/intel-bts.c +++ b/tools/perf/arch/x86/util/intel-bts.c @@ -17,7 +17,7 @@ #include "../../../util/evlist.h" #include "../../../util/mmap.h" #include "../../../util/session.h" -#include "../../../util/pmu.h" +#include "../../../util/pmus.h" #include "../../../util/debug.h" #include "../../../util/record.h" #include "../../../util/tsc.h" @@ -416,7 +416,7 @@ out_err: struct auxtrace_record *intel_bts_recording_init(int *err) { - struct perf_pmu *intel_bts_pmu = perf_pmu__find(INTEL_BTS_PMU_NAME); + struct perf_pmu *intel_bts_pmu = perf_pmus__find(INTEL_BTS_PMU_NAME); struct intel_bts_recording *btsr; if (!intel_bts_pmu) diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index 17336da08b58..74b70fd379df 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c @@ -23,7 +23,7 @@ #include "../../../util/mmap.h" #include #include "../../../util/parse-events.h" -#include "../../../util/pmu.h" +#include "../../../util/pmus.h" #include "../../../util/debug.h" #include "../../../util/auxtrace.h" #include "../../../util/perf_api_probe.h" @@ -1185,7 +1185,7 @@ static u64 intel_pt_reference(struct auxtrace_record *itr __maybe_unused) struct auxtrace_record *intel_pt_recording_init(int *err) { - struct perf_pmu *intel_pt_pmu = perf_pmu__find(INTEL_PT_PMU_NAME); + struct perf_pmu *intel_pt_pmu = perf_pmus__find(INTEL_PT_PMU_NAME); struct intel_pt_recording *ptr; if (!intel_pt_pmu) diff --git a/tools/perf/arch/x86/util/mem-events.c b/tools/perf/arch/x86/util/mem-events.c index 02d65e446f46..32879d12a8d5 100644 --- a/tools/perf/arch/x86/util/mem-events.c +++ b/tools/perf/arch/x86/util/mem-events.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include "util/pmu.h" +#include "util/pmus.h" #include "util/env.h" #include "map_symbol.h" #include "mem-events.h" @@ -55,12 +56,12 @@ struct perf_mem_event *perf_mem_events__ptr(int i) bool is_mem_loads_aux_event(struct evsel *leader) { - struct perf_pmu *pmu = perf_pmu__find("cpu"); + struct perf_pmu *pmu = perf_pmus__find("cpu"); if (!pmu) - pmu = perf_pmu__find("cpu_core"); + pmu = perf_pmus__find("cpu_core"); - if (pmu && !pmu_have_event(pmu->name, "mem-loads-aux")) + if (pmu && !perf_pmu__have_event(pmu, "mem-loads-aux")) return false; return leader->core.attr.config == MEM_LOADS_AUX; @@ -82,7 +83,7 @@ char *perf_mem_events__name(int i, char *pmu_name) pmu_name = (char *)"cpu"; } - if (pmu_have_event(pmu_name, "mem-loads-aux")) { + if (perf_pmus__have_event(pmu_name, "mem-loads-aux")) { scnprintf(mem_loads_name, sizeof(mem_loads_name), MEM_LOADS_AUX_NAME, pmu_name, pmu_name, perf_mem_events__loads_ldlat); diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c index 26abc159fc0e..befa7f3659b9 100644 --- a/tools/perf/arch/x86/util/perf_regs.c +++ b/tools/perf/arch/x86/util/perf_regs.c @@ -10,6 +10,7 @@ #include "../../../util/debug.h" #include "../../../util/event.h" #include "../../../util/pmu.h" +#include "../../../util/pmus.h" const struct sample_reg sample_reg_masks[] = { SMPL_REG(AX, PERF_REG_X86_AX), @@ -291,7 +292,7 @@ uint64_t arch__intr_reg_mask(void) */ attr.sample_period = 1; - if (perf_pmu__has_hybrid()) { + if (perf_pmus__has_hybrid()) { struct perf_pmu *pmu = NULL; __u64 type = PERF_TYPE_RAW; @@ -299,7 +300,7 @@ uint64_t arch__intr_reg_mask(void) * The same register set is supported among different hybrid PMUs. * Only check the first available one. */ - while ((pmu = perf_pmu__scan(pmu)) != NULL) { + while ((pmu = perf_pmus__scan(pmu)) != NULL) { if (pmu->is_core) { type = pmu->type; break; diff --git a/tools/perf/arch/x86/util/topdown.c b/tools/perf/arch/x86/util/topdown.c index 9ad5e5c7bd27..3f9a267d4501 100644 --- a/tools/perf/arch/x86/util/topdown.c +++ b/tools/perf/arch/x86/util/topdown.c @@ -2,6 +2,7 @@ #include "api/fs/fs.h" #include "util/evsel.h" #include "util/pmu.h" +#include "util/pmus.h" #include "util/topdown.h" #include "topdown.h" #include "evsel.h" @@ -22,8 +23,8 @@ bool topdown_sys_has_perf_metrics(void) * The slots event is only available when the core PMU * supports the perf metrics feature. */ - pmu = perf_pmu__find_by_type(PERF_TYPE_RAW); - if (pmu && pmu_have_event(pmu->name, "slots")) + pmu = perf_pmus__find_by_type(PERF_TYPE_RAW); + if (pmu && perf_pmu__have_event(pmu, "slots")) has_perf_metrics = true; cached = true; diff --git a/tools/perf/bench/pmu-scan.c b/tools/perf/bench/pmu-scan.c index f4a6c37cbe27..51cae2d03353 100644 --- a/tools/perf/bench/pmu-scan.c +++ b/tools/perf/bench/pmu-scan.c @@ -44,7 +44,7 @@ static int save_result(void) struct list_head *list; struct pmu_scan_result *r; - while ((pmu = perf_pmu__scan(pmu)) != NULL) { + while ((pmu = perf_pmus__scan(pmu)) != NULL) { r = realloc(results, (nr_pmus + 1) * sizeof(*r)); if (r == NULL) return -ENOMEM; @@ -68,7 +68,7 @@ static int save_result(void) nr_pmus++; } - perf_pmu__destroy(); + perf_pmus__destroy(); return 0; } @@ -81,7 +81,7 @@ static int check_result(void) for (int i = 0; i < nr_pmus; i++) { r = &results[i]; - pmu = perf_pmu__find(r->name); + pmu = perf_pmus__find(r->name); if (pmu == NULL) { pr_err("Cannot find PMU %s\n", r->name); return -1; @@ -144,7 +144,7 @@ static int run_pmu_scan(void) for (i = 0; i < iterations; i++) { gettimeofday(&start, NULL); - perf_pmu__scan(NULL); + perf_pmus__scan(NULL); gettimeofday(&end, NULL); timersub(&end, &start, &diff); @@ -152,7 +152,7 @@ static int run_pmu_scan(void) update_stats(&stats, runtime_us); ret = check_result(); - perf_pmu__destroy(); + perf_pmus__destroy(); if (ret < 0) break; } diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index 2757ccc19c5e..05dfd98af170 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -41,7 +41,7 @@ #include "symbol.h" #include "ui/ui.h" #include "ui/progress.h" -#include "pmu.h" +#include "pmus.h" #include "string2.h" #include "util/util.h" @@ -3259,7 +3259,7 @@ static int perf_c2c__record(int argc, const char **argv) PARSE_OPT_KEEP_UNKNOWN); /* Max number of arguments multiplied by number of PMUs that can support them. */ - rec_argc = argc + 11 * perf_pmu__num_mem_pmus(); + rec_argc = argc + 11 * perf_pmus__num_mem_pmus(); rec_argv = calloc(rec_argc + 1, sizeof(char *)); if (!rec_argv) diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c index e8520a027b45..03b5d26b2489 100644 --- a/tools/perf/builtin-list.c +++ b/tools/perf/builtin-list.c @@ -527,7 +527,7 @@ int cmd_list(int argc, const char **argv) strcmp(argv[i], "hwcache") == 0) print_hwcache_events(&print_cb, ps); else if (strcmp(argv[i], "pmu") == 0) - print_pmu_events(&print_cb, ps); + perf_pmus__print_pmu_events(&print_cb, ps); else if (strcmp(argv[i], "sdt") == 0) print_sdt_events(&print_cb, ps); else if (strcmp(argv[i], "metric") == 0 || strcmp(argv[i], "metrics") == 0) { @@ -567,7 +567,7 @@ int cmd_list(int argc, const char **argv) event_symbols_sw, PERF_COUNT_SW_MAX); print_tool_events(&print_cb, ps); print_hwcache_events(&print_cb, ps); - print_pmu_events(&print_cb, ps); + perf_pmus__print_pmu_events(&print_cb, ps); print_tracepoint_events(&print_cb, ps); print_sdt_events(&print_cb, ps); default_ps.metrics = true; diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c index f4f1ff76d49d..960bfd4b732a 100644 --- a/tools/perf/builtin-mem.c +++ b/tools/perf/builtin-mem.c @@ -17,7 +17,7 @@ #include "util/dso.h" #include "util/map.h" #include "util/symbol.h" -#include "util/pmu.h" +#include "util/pmus.h" #include "util/sample.h" #include "util/string2.h" #include "util/util.h" @@ -93,7 +93,7 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem) PARSE_OPT_KEEP_UNKNOWN); /* Max number of arguments multiplied by number of PMUs that can support them. */ - rec_argc = argc + 9 * perf_pmu__num_mem_pmus(); + rec_argc = argc + 9 * perf_pmus__num_mem_pmus(); if (mem->cpu_list) rec_argc += 2; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 2abcad2998f6..4b9212f75493 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -48,6 +48,8 @@ #include "util/bpf-event.h" #include "util/util.h" #include "util/pfm.h" +#include "util/pmu.h" +#include "util/pmus.h" #include "util/clockid.h" #include "util/off_cpu.h" #include "util/bpf-filter.h" @@ -1292,7 +1294,7 @@ static int record__open(struct record *rec) * of waiting or event synthesis. */ if (opts->target.initial_delay || target__has_cpu(&opts->target) || - perf_pmu__has_hybrid()) { + perf_pmus__has_hybrid()) { pos = evlist__get_tracking_event(evlist); if (!evsel__is_dummy_event(pos)) { /* Set up dummy event. */ @@ -2191,7 +2193,7 @@ static void record__uniquify_name(struct record *rec) char *new_name; int ret; - if (!perf_pmu__has_hybrid()) + if (!perf_pmus__has_hybrid()) return; evlist__for_each_entry(evlist, pos) { diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 62bbeea93bf3..c87c6897edc9 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -2140,11 +2140,11 @@ static int add_default_attributes(void) if (evlist__add_default_attrs(evsel_list, default_attrs0) < 0) return -1; - if (pmu_have_event("cpu", "stalled-cycles-frontend")) { + if (perf_pmus__have_event("cpu", "stalled-cycles-frontend")) { if (evlist__add_default_attrs(evsel_list, frontend_attrs) < 0) return -1; } - if (pmu_have_event("cpu", "stalled-cycles-backend")) { + if (perf_pmus__have_event("cpu", "stalled-cycles-backend")) { if (evlist__add_default_attrs(evsel_list, backend_attrs) < 0) return -1; } diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c index 56fba08a3037..674876e6c8e6 100644 --- a/tools/perf/tests/attr.c +++ b/tools/perf/tests/attr.c @@ -34,7 +34,7 @@ #include "event.h" #include "util.h" #include "tests.h" -#include "pmu.h" +#include "pmus.h" #define ENV "PERF_TEST_ATTR" @@ -185,7 +185,7 @@ static int test__attr(struct test_suite *test __maybe_unused, int subtest __mayb char path_dir[PATH_MAX]; char *exec_path; - if (perf_pmu__has_hybrid()) + if (perf_pmus__has_hybrid()) return TEST_SKIP; /* First try development tree tests. */ diff --git a/tools/perf/tests/event_groups.c b/tools/perf/tests/event_groups.c index 3d9a2b524bba..ccd9d8b2903f 100644 --- a/tools/perf/tests/event_groups.c +++ b/tools/perf/tests/event_groups.c @@ -53,7 +53,7 @@ static int setup_uncore_event(void) struct perf_pmu *pmu = NULL; int i, fd; - while ((pmu = perf_pmu__scan(pmu)) != NULL) { + while ((pmu = perf_pmus__scan(pmu)) != NULL) { for (i = 0; i < NR_UNCORE_PMUS; i++) { if (!strcmp(uncore_pmus[i].name, pmu->name)) { pr_debug("Using %s for uncore pmu event\n", pmu->name); diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index 277607ede060..9d05bc551791 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -112,7 +112,7 @@ static int test__checkevent_raw(struct evlist *evlist) bool type_matched = false; TEST_ASSERT_VAL("wrong config", test_perf_config(evsel, 0x1a)); - while ((pmu = perf_pmu__scan(pmu)) != NULL) { + while ((pmu = perf_pmus__scan(pmu)) != NULL) { if (pmu->type == evsel->attr.type) { TEST_ASSERT_VAL("PMU type expected once", !type_matched); type_matched = true; @@ -1443,12 +1443,12 @@ static int test__checkevent_config_cache(struct evlist *evlist) static bool test__pmu_cpu_valid(void) { - return !!perf_pmu__find("cpu"); + return !!perf_pmus__find("cpu"); } static bool test__intel_pt_valid(void) { - return !!perf_pmu__find("intel_pt"); + return !!perf_pmus__find("intel_pt"); } static int test__intel_pt(struct evlist *evlist) @@ -2246,7 +2246,7 @@ static int test__pmu_events(struct test_suite *test __maybe_unused, int subtest struct perf_pmu *pmu = NULL; int ret = TEST_OK; - while ((pmu = perf_pmu__scan(pmu)) != NULL) { + while ((pmu = perf_pmus__scan(pmu)) != NULL) { struct stat st; char path[PATH_MAX]; struct dirent *ent; diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c index c05148ea400c..1d6493a5a956 100644 --- a/tools/perf/tests/parse-metric.c +++ b/tools/perf/tests/parse-metric.c @@ -11,7 +11,7 @@ #include "debug.h" #include "expr.h" #include "stat.h" -#include "pmu.h" +#include "pmus.h" struct value { const char *event; @@ -303,7 +303,7 @@ static int test__parse_metric(struct test_suite *test __maybe_unused, int subtes TEST_ASSERT_VAL("recursion fail failed", test_recursion_fail() == 0); TEST_ASSERT_VAL("Memory bandwidth", test_memory_bandwidth() == 0); - if (!perf_pmu__has_hybrid()) { + if (!perf_pmus__has_hybrid()) { TEST_ASSERT_VAL("cache_miss_cycles failed", test_cache_miss_cycles() == 0); TEST_ASSERT_VAL("test metric group", test_metric_group() == 0); } diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index 734004f1a37d..64ecb7845af4 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -2,6 +2,7 @@ #include "math.h" #include "parse-events.h" #include "pmu.h" +#include "pmus.h" #include "tests.h" #include #include @@ -708,7 +709,7 @@ static int test__aliases(struct test_suite *test __maybe_unused, struct perf_pmu *pmu = NULL; unsigned long i; - while ((pmu = perf_pmu__scan(pmu)) != NULL) { + while ((pmu = perf_pmus__scan(pmu)) != NULL) { int count = 0; if (!is_pmu_core(pmu->name)) diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index b3bd14b025a8..cff6ab87b2f6 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -20,7 +20,7 @@ #include "tests.h" #include "util/mmap.h" #include "util/sample.h" -#include "pmu.h" +#include "pmus.h" static int spin_sleep(void) { @@ -375,7 +375,7 @@ static int test__switch_tracking(struct test_suite *test __maybe_unused, int sub cpu_clocks_evsel = evlist__last(evlist); /* Second event */ - if (perf_pmu__has_hybrid()) { + if (perf_pmus__has_hybrid()) { cycles = "cpu_core/cycles/u"; err = parse_event(evlist, cycles); if (err) { diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c index c4630cfc80ea..49e80d15420b 100644 --- a/tools/perf/tests/topology.c +++ b/tools/perf/tests/topology.c @@ -8,7 +8,7 @@ #include "session.h" #include "evlist.h" #include "debug.h" -#include "pmu.h" +#include "pmus.h" #include #define TEMPL "/tmp/perf-test-XXXXXX" @@ -41,7 +41,7 @@ static int session_write_header(char *path) session = perf_session__new(&data, NULL); TEST_ASSERT_VAL("can't get session", !IS_ERR(session)); - if (!perf_pmu__has_hybrid()) { + if (!perf_pmus__has_hybrid()) { session->evlist = evlist__new_default(); TEST_ASSERT_VAL("can't get evlist", session->evlist); } else { diff --git a/tools/perf/util/cputopo.c b/tools/perf/util/cputopo.c index a5c259bd5cc0..4578c26747e1 100644 --- a/tools/perf/util/cputopo.c +++ b/tools/perf/util/cputopo.c @@ -13,6 +13,7 @@ #include "debug.h" #include "env.h" #include "pmu.h" +#include "pmus.h" #define PACKAGE_CPUS_FMT \ "%s/devices/system/cpu/cpu%d/topology/package_cpus_list" @@ -473,10 +474,10 @@ struct hybrid_topology *hybrid_topology__new(void) struct hybrid_topology *tp = NULL; u32 nr = 0, i = 0; - if (!perf_pmu__has_hybrid()) + if (!perf_pmus__has_hybrid()) return NULL; - while ((pmu = perf_pmu__scan(pmu)) != NULL) { + while ((pmu = perf_pmus__scan(pmu)) != NULL) { if (pmu->is_core) nr++; } @@ -488,7 +489,7 @@ struct hybrid_topology *hybrid_topology__new(void) return NULL; tp->nr = nr; - while ((pmu = perf_pmu__scan(pmu)) != NULL) { + while ((pmu = perf_pmus__scan(pmu)) != NULL) { if (!pmu->is_core) continue; diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c index 4a4fdad820d6..9eabf3ec56e9 100644 --- a/tools/perf/util/env.c +++ b/tools/perf/util/env.c @@ -10,6 +10,7 @@ #include #include #include +#include "pmus.h" #include "strbuf.h" struct perf_env perf_env; @@ -323,7 +324,7 @@ int perf_env__read_pmu_mappings(struct perf_env *env) u32 pmu_num = 0; struct strbuf sb; - while ((pmu = perf_pmu__scan(pmu))) { + while ((pmu = perf_pmus__scan(pmu))) { if (!pmu->name) continue; pmu_num++; @@ -337,7 +338,7 @@ int perf_env__read_pmu_mappings(struct perf_env *env) if (strbuf_init(&sb, 128 * pmu_num) < 0) return -ENOMEM; - while ((pmu = perf_pmu__scan(pmu))) { + while ((pmu = perf_pmus__scan(pmu))) { if (!pmu->name) continue; if (strbuf_addf(&sb, "%u:%s", pmu->type, pmu->name) < 0) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 1c6e22e3f345..b4237fc713d5 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -48,6 +48,7 @@ #include "util/hashmap.h" #include "off_cpu.h" #include "pmu.h" +#include "pmus.h" #include "../perf-sys.h" #include "util/parse-branch-options.h" #include "util/bpf-filter.h" @@ -3139,7 +3140,7 @@ void evsel__zero_per_pkg(struct evsel *evsel) */ bool evsel__is_hybrid(const struct evsel *evsel) { - if (!perf_pmu__has_hybrid()) + if (!perf_pmus__has_hybrid()) return false; return evsel->core.is_pmu_core; diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 37fa66b1ca77..e6d8ecd7a08e 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -37,6 +37,7 @@ #include "debug.h" #include "cpumap.h" #include "pmu.h" +#include "pmus.h" #include "vdso.h" #include "strbuf.h" #include "build-id.h" @@ -744,7 +745,7 @@ static int write_pmu_mappings(struct feat_fd *ff, * Do a first pass to count number of pmu to avoid lseek so this * works in pipe mode as well. */ - while ((pmu = perf_pmu__scan(pmu))) { + while ((pmu = perf_pmus__scan(pmu))) { if (!pmu->name) continue; pmu_num++; @@ -754,7 +755,7 @@ static int write_pmu_mappings(struct feat_fd *ff, if (ret < 0) return ret; - while ((pmu = perf_pmu__scan(pmu))) { + while ((pmu = perf_pmus__scan(pmu))) { if (!pmu->name) continue; @@ -1566,7 +1567,7 @@ static int __write_pmu_caps(struct feat_fd *ff, struct perf_pmu *pmu, static int write_cpu_pmu_caps(struct feat_fd *ff, struct evlist *evlist __maybe_unused) { - struct perf_pmu *cpu_pmu = perf_pmu__find("cpu"); + struct perf_pmu *cpu_pmu = perf_pmus__find("cpu"); int ret; if (!cpu_pmu) @@ -1586,7 +1587,7 @@ static int write_pmu_caps(struct feat_fd *ff, int nr_pmu = 0; int ret; - while ((pmu = perf_pmu__scan(pmu))) { + while ((pmu = perf_pmus__scan(pmu))) { if (!pmu->name || !strcmp(pmu->name, "cpu") || perf_pmu__caps_parse(pmu) <= 0) continue; @@ -1604,9 +1605,9 @@ static int write_pmu_caps(struct feat_fd *ff, * Write hybrid pmu caps first to maintain compatibility with * older perf tool. */ - if (perf_pmu__has_hybrid()) { + if (perf_pmus__has_hybrid()) { pmu = NULL; - while ((pmu = perf_pmu__scan(pmu))) { + while ((pmu = perf_pmus__scan(pmu))) { if (!pmu->is_core) continue; @@ -1617,7 +1618,7 @@ static int write_pmu_caps(struct feat_fd *ff, } pmu = NULL; - while ((pmu = perf_pmu__scan(pmu))) { + while ((pmu = perf_pmus__scan(pmu))) { if (pmu->is_core || !pmu->nr_caps) continue; diff --git a/tools/perf/util/mem-events.c b/tools/perf/util/mem-events.c index c9e422a38258..08ac3ea2e366 100644 --- a/tools/perf/util/mem-events.c +++ b/tools/perf/util/mem-events.c @@ -13,6 +13,7 @@ #include "debug.h" #include "symbol.h" #include "pmu.h" +#include "pmus.h" unsigned int perf_mem_events__loads_ldlat = 30; @@ -128,14 +129,14 @@ int perf_mem_events__init(void) if (!e->tag) continue; - if (!perf_pmu__has_hybrid()) { + if (!perf_pmus__has_hybrid()) { scnprintf(sysfs_name, sizeof(sysfs_name), e->sysfs_name, "cpu"); e->supported = perf_mem_event__supported(mnt, sysfs_name); } else { struct perf_pmu *pmu = NULL; - while ((pmu = perf_pmu__scan(pmu)) != NULL) { + while ((pmu = perf_pmus__scan(pmu)) != NULL) { if (!pmu->is_core) continue; @@ -175,7 +176,7 @@ static void perf_mem_events__print_unsupport_hybrid(struct perf_mem_event *e, char sysfs_name[100]; struct perf_pmu *pmu = NULL; - while ((pmu = perf_pmu__scan(pmu)) != NULL) { + while ((pmu = perf_pmus__scan(pmu)) != NULL) { if (!pmu->is_core) continue; @@ -201,7 +202,7 @@ int perf_mem_events__record_args(const char **rec_argv, int *argv_nr, if (!e->record) continue; - if (!perf_pmu__has_hybrid()) { + if (!perf_pmus__has_hybrid()) { if (!e->supported) { pr_err("failed: event '%s' not supported\n", perf_mem_events__name(j, NULL)); @@ -216,7 +217,7 @@ int perf_mem_events__record_args(const char **rec_argv, int *argv_nr, return -1; } - while ((pmu = perf_pmu__scan(pmu)) != NULL) { + while ((pmu = perf_pmus__scan(pmu)) != NULL) { if (!pmu->is_core) continue; rec_argv[i++] = "-e"; diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 3f04a686d1cd..092ed6386a39 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -11,6 +11,7 @@ #include "evsel.h" #include "strbuf.h" #include "pmu.h" +#include "pmus.h" #include "print-events.h" #include "smt.h" #include "expr.h" @@ -273,7 +274,7 @@ static int setup_metric_events(const char *pmu, struct hashmap *ids, const char *metric_id; struct evsel *ev; size_t ids_size, matched_events, i; - bool all_pmus = !strcmp(pmu, "all") || !perf_pmu__has_hybrid() || !is_pmu_hybrid(pmu); + bool all_pmus = !strcmp(pmu, "all") || !perf_pmus__has_hybrid() || !is_pmu_hybrid(pmu); *out_metric_events = NULL; ids_size = hashmap__size(ids); @@ -488,7 +489,7 @@ static int metricgroup__sys_event_iter(const struct pmu_metric *pm, if (!pm->metric_expr || !pm->compat) return 0; - while ((pmu = perf_pmu__scan(pmu))) { + while ((pmu = perf_pmus__scan(pmu))) { if (!pmu->id || strcmp(pmu->id, pm->compat)) continue; diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 1a0be395c887..be544f948be2 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -21,6 +21,7 @@ #include "parse-events-bison.h" #include "parse-events-flex.h" #include "pmu.h" +#include "pmus.h" #include "asm/bug.h" #include "util/parse-branch-options.h" #include "util/evsel_config.h" @@ -452,7 +453,7 @@ int parse_events_add_cache(struct list_head *list, int *idx, const char *name, const char *config_name = get_config_name(head_config); const char *metric_id = get_config_metric_id(head_config); - while ((pmu = perf_pmu__scan(pmu)) != NULL) { + while ((pmu = perf_pmus__scan(pmu)) != NULL) { LIST_HEAD(config_terms); struct perf_event_attr attr; int ret; @@ -1193,7 +1194,7 @@ static int config_term_pmu(struct perf_event_attr *attr, struct parse_events_error *err) { if (term->type_term == PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE) { - const struct perf_pmu *pmu = perf_pmu__find_by_type(attr->type); + const struct perf_pmu *pmu = perf_pmus__find_by_type(attr->type); if (perf_pmu__supports_legacy_cache(pmu)) { attr->type = PERF_TYPE_HW_CACHE; @@ -1203,7 +1204,7 @@ static int config_term_pmu(struct perf_event_attr *attr, term->type_term = PARSE_EVENTS__TERM_TYPE_USER; } if (term->type_term == PARSE_EVENTS__TERM_TYPE_HARDWARE) { - const struct perf_pmu *pmu = perf_pmu__find_by_type(attr->type); + const struct perf_pmu *pmu = perf_pmus__find_by_type(attr->type); if (!pmu) { pr_debug("Failed to find PMU for type %d", attr->type); @@ -1480,7 +1481,7 @@ int parse_events_add_numeric(struct parse_events_state *parse_state, return __parse_events_add_numeric(parse_state, list, /*pmu=*/NULL, type, config, head_config); - while ((pmu = perf_pmu__scan(pmu)) != NULL) { + while ((pmu = perf_pmus__scan(pmu)) != NULL) { int ret; if (!perf_pmu__supports_wildcard_numeric(pmu)) @@ -1529,7 +1530,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, struct parse_events_error *err = parse_state->error; LIST_HEAD(config_terms); - pmu = parse_state->fake_pmu ?: perf_pmu__find(name); + pmu = parse_state->fake_pmu ?: perf_pmus__find(name); if (verbose > 1 && !(pmu && pmu->selectable)) { fprintf(stderr, "Attempting to add event pmu '%s' with '", @@ -1674,7 +1675,7 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state, INIT_LIST_HEAD(list); - while ((pmu = perf_pmu__scan(pmu)) != NULL) { + while ((pmu = perf_pmus__scan(pmu)) != NULL) { struct perf_pmu_alias *alias; bool auto_merge_stats; @@ -2410,7 +2411,7 @@ static int set_filter(struct evsel *evsel, const void *arg) return 0; } - while ((pmu = perf_pmu__scan(pmu)) != NULL) + while ((pmu = perf_pmus__scan(pmu)) != NULL) if (pmu->type == evsel->core.attr.type) { found = true; break; diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index 4e1f5de35be8..abd6ab460e12 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -15,6 +15,7 @@ #include #include #include "pmu.h" +#include "pmus.h" #include "evsel.h" #include "parse-events.h" #include "parse-events-bison.h" @@ -316,7 +317,7 @@ PE_NAME opt_pmu_config if (asprintf(&pattern, "%s*", $1) < 0) CLEANUP_YYABORT; - while ((pmu = perf_pmu__scan(pmu)) != NULL) { + while ((pmu = perf_pmus__scan(pmu)) != NULL) { char *name = pmu->name; if (parse_events__filter_pmu(parse_state, pmu)) diff --git a/tools/perf/util/pfm.c b/tools/perf/util/pfm.c index 6c11914c179f..076aecc22c16 100644 --- a/tools/perf/util/pfm.c +++ b/tools/perf/util/pfm.c @@ -10,7 +10,7 @@ #include "util/evlist.h" #include "util/evsel.h" #include "util/parse-events.h" -#include "util/pmu.h" +#include "util/pmus.h" #include "util/pfm.h" #include "util/strbuf.h" @@ -49,7 +49,7 @@ int parse_libpfm_events_option(const struct option *opt, const char *str, /* * force loading of the PMU list */ - perf_pmu__scan(NULL); + perf_pmus__scan(NULL); for (q = p; strsep(&p, ",{}"); q = p) { sep = p ? str + (p - p_orig - 1) : ""; @@ -86,7 +86,7 @@ int parse_libpfm_events_option(const struct option *opt, const char *str, goto error; } - pmu = perf_pmu__find_by_type((unsigned int)attr.type); + pmu = perf_pmus__find_by_type((unsigned int)attr.type); evsel = parse_events__add_event(evlist->core.nr_entries, &attr, q, /*metric_id=*/NULL, pmu); diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 21ee23b78f5a..05056305fb58 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -4,20 +4,15 @@ #include #include #include -#include #include -#include #include #include #include #include #include -#include #include #include #include -#include -#include #include #include #include "debug.h" @@ -59,8 +54,6 @@ struct perf_pmu_format { struct list_head list; }; -static struct perf_pmu *perf_pmu__find2(int dirfd, const char *name); - /* * Parse & process all the sysfs attributes located under * the directory specified in 'dir' parameter. @@ -554,31 +547,6 @@ static int pmu_alias_terms(struct perf_pmu_alias *alias, return 0; } -/* Add all pmus in sysfs to pmu list: */ -static void pmu_read_sysfs(void) -{ - int fd; - DIR *dir; - struct dirent *dent; - - fd = perf_pmu__event_source_devices_fd(); - if (fd < 0) - return; - - dir = fdopendir(fd); - if (!dir) - return; - - while ((dent = readdir(dir))) { - if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) - continue; - /* add to static LIST_HEAD(pmus): */ - perf_pmu__find2(fd, dent->d_name); - } - - closedir(dir); -} - /* * Uncore PMUs have a "cpumask" file under sysfs. CPU PMUs (e.g. on arm/arm64) * may have a "cpus" file. @@ -894,7 +862,7 @@ static int pmu_max_precise(int dirfd, struct perf_pmu *pmu) return max_precise; } -static struct perf_pmu *pmu_lookup(int dirfd, const char *lookup_name) +struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char *lookup_name) { struct perf_pmu *pmu; LIST_HEAD(format); @@ -951,7 +919,7 @@ static struct perf_pmu *pmu_lookup(int dirfd, const char *lookup_name) INIT_LIST_HEAD(&pmu->caps); list_splice(&format, &pmu->format); list_splice(&aliases, &pmu->aliases); - list_add_tail(&pmu->list, &pmus); + list_add_tail(&pmu->list, pmus); pmu->default_config = perf_pmu__get_default_config(pmu); @@ -979,61 +947,6 @@ void perf_pmu__warn_invalid_formats(struct perf_pmu *pmu) } } -static struct perf_pmu *pmu_find(const char *name) -{ - struct perf_pmu *pmu; - - list_for_each_entry(pmu, &pmus, list) { - if (!strcmp(pmu->name, name) || - (pmu->alias_name && !strcmp(pmu->alias_name, name))) - return pmu; - } - - return NULL; -} - -struct perf_pmu *perf_pmu__find_by_type(unsigned int type) -{ - struct perf_pmu *pmu; - - list_for_each_entry(pmu, &pmus, list) - if (pmu->type == type) - return pmu; - - return NULL; -} - -struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu) -{ - /* - * pmu iterator: If pmu is NULL, we start at the begin, - * otherwise return the next pmu. Returns NULL on end. - */ - if (!pmu) { - pmu_read_sysfs(); - pmu = list_prepare_entry(pmu, &pmus, list); - } - list_for_each_entry_continue(pmu, &pmus, list) - return pmu; - return NULL; -} - -struct perf_pmu *evsel__find_pmu(const struct evsel *evsel) -{ - struct perf_pmu *pmu = NULL; - - if (evsel->pmu) - return evsel->pmu; - - while ((pmu = perf_pmu__scan(pmu)) != NULL) { - if (pmu->type == evsel->core.attr.type) - break; - } - - ((struct evsel *)evsel)->pmu = pmu; - return pmu; -} - bool evsel__is_aux_event(const struct evsel *evsel) { struct perf_pmu *pmu = evsel__find_pmu(evsel); @@ -1070,43 +983,6 @@ void evsel__set_config_if_unset(struct perf_pmu *pmu, struct evsel *evsel, evsel->core.attr.config |= field_prep(bits, val); } -struct perf_pmu *perf_pmu__find(const char *name) -{ - struct perf_pmu *pmu; - int dirfd; - - /* - * Once PMU is loaded it stays in the list, - * so we keep us from multiple reading/parsing - * the pmu format definitions. - */ - pmu = pmu_find(name); - if (pmu) - return pmu; - - dirfd = perf_pmu__event_source_devices_fd(); - pmu = pmu_lookup(dirfd, name); - close(dirfd); - - return pmu; -} - -static struct perf_pmu *perf_pmu__find2(int dirfd, const char *name) -{ - struct perf_pmu *pmu; - - /* - * Once PMU is loaded it stays in the list, - * so we keep us from multiple reading/parsing - * the pmu format definitions. - */ - pmu = pmu_find(name); - if (pmu) - return pmu; - - return pmu_lookup(dirfd, name); -} - static struct perf_pmu_format * pmu_find_format(struct list_head *formats, const char *name) { @@ -1536,99 +1412,6 @@ void perf_pmu__del_formats(struct list_head *formats) } } -static int sub_non_neg(int a, int b) -{ - if (b > a) - return 0; - return a - b; -} - -static char *format_alias(char *buf, int len, const struct perf_pmu *pmu, - const struct perf_pmu_alias *alias) -{ - struct parse_events_term *term; - int used = snprintf(buf, len, "%s/%s", pmu->name, alias->name); - - list_for_each_entry(term, &alias->terms, list) { - if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) - used += snprintf(buf + used, sub_non_neg(len, used), - ",%s=%s", term->config, - term->val.str); - } - - if (sub_non_neg(len, used) > 0) { - buf[used] = '/'; - used++; - } - if (sub_non_neg(len, used) > 0) { - buf[used] = '\0'; - used++; - } else - buf[len - 1] = '\0'; - - return buf; -} - -/** Struct for ordering events as output in perf list. */ -struct sevent { - /** PMU for event. */ - const struct perf_pmu *pmu; - /** - * Optional event for name, desc, etc. If not present then this is a - * selectable PMU and the event name is shown as "//". - */ - const struct perf_pmu_alias *event; - /** Is the PMU for the CPU? */ - bool is_cpu; -}; - -static int cmp_sevent(const void *a, const void *b) -{ - const struct sevent *as = a; - const struct sevent *bs = b; - const char *a_pmu_name = NULL, *b_pmu_name = NULL; - const char *a_name = "//", *a_desc = NULL, *a_topic = ""; - const char *b_name = "//", *b_desc = NULL, *b_topic = ""; - int ret; - - if (as->event) { - a_name = as->event->name; - a_desc = as->event->desc; - a_topic = as->event->topic ?: ""; - a_pmu_name = as->event->pmu_name; - } - if (bs->event) { - b_name = bs->event->name; - b_desc = bs->event->desc; - b_topic = bs->event->topic ?: ""; - b_pmu_name = bs->event->pmu_name; - } - /* Put extra events last. */ - if (!!a_desc != !!b_desc) - return !!a_desc - !!b_desc; - - /* Order by topics. */ - ret = strcmp(a_topic, b_topic); - if (ret) - return ret; - - /* Order CPU core events to be first */ - if (as->is_cpu != bs->is_cpu) - return as->is_cpu ? -1 : 1; - - /* Order by PMU name. */ - if (as->pmu != bs->pmu) { - a_pmu_name = a_pmu_name ?: (as->pmu->name ?: ""); - b_pmu_name = b_pmu_name ?: (bs->pmu->name ?: ""); - ret = strcmp(a_pmu_name, b_pmu_name); - if (ret) - return ret; - } - - /* Order by event name. */ - return strcmp(a_name, b_name); -} - bool is_pmu_core(const char *name) { return !strcmp(name, "cpu") || is_sysfs_pmu_core(name); @@ -1654,167 +1437,18 @@ bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu) return !is_pmu_hybrid(pmu->name); } -static bool perf_pmu__is_mem_pmu(const struct perf_pmu *pmu) +bool perf_pmu__is_mem_pmu(const struct perf_pmu *pmu) { return pmu->is_core; } -int perf_pmu__num_mem_pmus(void) -{ - struct perf_pmu *pmu = NULL; - int count = 0; - - while ((pmu = perf_pmu__scan(pmu)) != NULL) { - if (perf_pmu__is_mem_pmu(pmu)) - count++; - } - return count; -} - -static bool pmu_alias_is_duplicate(struct sevent *alias_a, - struct sevent *alias_b) -{ - const char *a_pmu_name = NULL, *b_pmu_name = NULL; - const char *a_name = "//", *b_name = "//"; - - - if (alias_a->event) { - a_name = alias_a->event->name; - a_pmu_name = alias_a->event->pmu_name; - } - if (alias_b->event) { - b_name = alias_b->event->name; - b_pmu_name = alias_b->event->pmu_name; - } - - /* Different names -> never duplicates */ - if (strcmp(a_name, b_name)) - return false; - - /* Don't remove duplicates for different PMUs */ - a_pmu_name = a_pmu_name ?: (alias_a->pmu->name ?: ""); - b_pmu_name = b_pmu_name ?: (alias_b->pmu->name ?: ""); - return strcmp(a_pmu_name, b_pmu_name) == 0; -} - -void print_pmu_events(const struct print_callbacks *print_cb, void *print_state) -{ - struct perf_pmu *pmu; - struct perf_pmu_alias *event; - char buf[1024]; - int printed = 0; - int len, j; - struct sevent *aliases; - - pmu = NULL; - len = 0; - while ((pmu = perf_pmu__scan(pmu)) != NULL) { - list_for_each_entry(event, &pmu->aliases, list) - len++; - if (pmu->selectable) - len++; - } - aliases = zalloc(sizeof(struct sevent) * len); - if (!aliases) { - pr_err("FATAL: not enough memory to print PMU events\n"); - return; - } - pmu = NULL; - j = 0; - while ((pmu = perf_pmu__scan(pmu)) != NULL) { - bool is_cpu = pmu->is_core; - - list_for_each_entry(event, &pmu->aliases, list) { - aliases[j].event = event; - aliases[j].pmu = pmu; - aliases[j].is_cpu = is_cpu; - j++; - } - if (pmu->selectable) { - aliases[j].event = NULL; - aliases[j].pmu = pmu; - aliases[j].is_cpu = is_cpu; - j++; - } - } - len = j; - qsort(aliases, len, sizeof(struct sevent), cmp_sevent); - for (j = 0; j < len; j++) { - const char *name, *alias = NULL, *scale_unit = NULL, - *desc = NULL, *long_desc = NULL, - *encoding_desc = NULL, *topic = NULL, - *pmu_name = NULL; - bool deprecated = false; - size_t buf_used; - - /* Skip duplicates */ - if (j > 0 && pmu_alias_is_duplicate(&aliases[j], &aliases[j - 1])) - continue; - - if (!aliases[j].event) { - /* A selectable event. */ - pmu_name = aliases[j].pmu->name; - buf_used = snprintf(buf, sizeof(buf), "%s//", pmu_name) + 1; - name = buf; - } else { - if (aliases[j].event->desc) { - name = aliases[j].event->name; - buf_used = 0; - } else { - name = format_alias(buf, sizeof(buf), aliases[j].pmu, - aliases[j].event); - if (aliases[j].is_cpu) { - alias = name; - name = aliases[j].event->name; - } - buf_used = strlen(buf) + 1; - } - pmu_name = aliases[j].event->pmu_name ?: (aliases[j].pmu->name ?: ""); - if (strlen(aliases[j].event->unit) || aliases[j].event->scale != 1.0) { - scale_unit = buf + buf_used; - buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used, - "%G%s", aliases[j].event->scale, - aliases[j].event->unit) + 1; - } - desc = aliases[j].event->desc; - long_desc = aliases[j].event->long_desc; - topic = aliases[j].event->topic; - encoding_desc = buf + buf_used; - buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used, - "%s/%s/", pmu_name, aliases[j].event->str) + 1; - deprecated = aliases[j].event->deprecated; - } - print_cb->print_event(print_state, - pmu_name, - topic, - name, - alias, - scale_unit, - deprecated, - "Kernel PMU event", - desc, - long_desc, - encoding_desc); - } - if (printed && pager_in_use()) - printf("\n"); - - zfree(&aliases); - return; -} - -bool pmu_have_event(const char *pname, const char *name) +bool perf_pmu__have_event(const struct perf_pmu *pmu, const char *name) { - struct perf_pmu *pmu; struct perf_pmu_alias *alias; - pmu = NULL; - while ((pmu = perf_pmu__scan(pmu)) != NULL) { - if (strcmp(pname, pmu->name)) - continue; - list_for_each_entry(alias, &pmu->aliases, list) - if (!strcmp(alias->name, name)) - return true; + list_for_each_entry(alias, &pmu->aliases, list) { + if (!strcmp(alias->name, name)) + return true; } return false; } @@ -2020,24 +1654,6 @@ void perf_pmu__warn_invalid_config(struct perf_pmu *pmu, __u64 config, name ?: "N/A", buf, config); } -bool perf_pmu__has_hybrid(void) -{ - static bool hybrid_scanned, has_hybrid; - - if (!hybrid_scanned) { - struct perf_pmu *pmu = NULL; - - while ((pmu = perf_pmu__scan(pmu)) != NULL) { - if (pmu->is_core && is_pmu_hybrid(pmu->name)) { - has_hybrid = true; - break; - } - } - hybrid_scanned = true; - } - return has_hybrid; -} - int perf_pmu__match(char *pattern, char *name, char *tok) { if (!name) @@ -2105,7 +1721,7 @@ int perf_pmu__pathname_fd(int dirfd, const char *pmu_name, const char *filename, return openat(dirfd, path, flags); } -static void perf_pmu__delete(struct perf_pmu *pmu) +void perf_pmu__delete(struct perf_pmu *pmu) { perf_pmu__del_formats(&pmu->format); perf_pmu__del_aliases(pmu); @@ -2118,14 +1734,3 @@ static void perf_pmu__delete(struct perf_pmu *pmu) zfree(&pmu->alias_name); free(pmu); } - -void perf_pmu__destroy(void) -{ - struct perf_pmu *pmu, *tmp; - - list_for_each_entry_safe(pmu, tmp, &pmus, list) { - list_del(&pmu->list); - - perf_pmu__delete(pmu); - } -} diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index cb51ad6e40fa..f1f3e8a2e00e 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -198,8 +198,6 @@ struct perf_pmu_alias { char *pmu_name; }; -struct perf_pmu *perf_pmu__find(const char *name); -struct perf_pmu *perf_pmu__find_by_type(unsigned int type); void pmu_add_sys_aliases(struct list_head *head, struct perf_pmu *pmu); int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, struct list_head *head_terms, @@ -222,16 +220,13 @@ void perf_pmu__set_format(unsigned long *bits, long from, long to); int perf_pmu__format_parse(int dirfd, struct list_head *head); void perf_pmu__del_formats(struct list_head *formats); -struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu); - bool is_pmu_core(const char *name); bool is_pmu_hybrid(const char *name); bool perf_pmu__supports_legacy_cache(const struct perf_pmu *pmu); bool perf_pmu__supports_wildcard_numeric(const struct perf_pmu *pmu); bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu); -int perf_pmu__num_mem_pmus(void); -void print_pmu_events(const struct print_callbacks *print_cb, void *print_state); -bool pmu_have_event(const char *pname, const char *name); +bool perf_pmu__is_mem_pmu(const struct perf_pmu *pmu); +bool perf_pmu__have_event(const struct perf_pmu *pmu, const char *name); FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name); FILE *perf_pmu__open_file_at(struct perf_pmu *pmu, int dirfd, const char *name); @@ -261,7 +256,6 @@ void perf_pmu__warn_invalid_config(struct perf_pmu *pmu, __u64 config, const char *name); void perf_pmu__warn_invalid_formats(struct perf_pmu *pmu); -bool perf_pmu__has_hybrid(void); int perf_pmu__match(char *pattern, char *name, char *tok); char *pmu_find_real_name(const char *name); @@ -273,6 +267,7 @@ int perf_pmu__pathname_scnprintf(char *buf, size_t size, int perf_pmu__event_source_devices_fd(void); int perf_pmu__pathname_fd(int dirfd, const char *pmu_name, const char *filename, int flags); -void perf_pmu__destroy(void); +struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char *lookup_name); +void perf_pmu__delete(struct perf_pmu *pmu); #endif /* __PMU_H */ diff --git a/tools/perf/util/pmus.c b/tools/perf/util/pmus.c index 140e11f00b29..58ff7937e9b7 100644 --- a/tools/perf/util/pmus.c +++ b/tools/perf/util/pmus.c @@ -1,16 +1,136 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include +#include +#include +#include #include +#include +#include "debug.h" +#include "evsel.h" #include "pmus.h" #include "pmu.h" +#include "print-events.h" -LIST_HEAD(pmus); +static LIST_HEAD(pmus); + +void perf_pmus__destroy(void) +{ + struct perf_pmu *pmu, *tmp; + + list_for_each_entry_safe(pmu, tmp, &pmus, list) { + list_del(&pmu->list); + + perf_pmu__delete(pmu); + } +} + +static struct perf_pmu *pmu_find(const char *name) +{ + struct perf_pmu *pmu; + + list_for_each_entry(pmu, &pmus, list) { + if (!strcmp(pmu->name, name) || + (pmu->alias_name && !strcmp(pmu->alias_name, name))) + return pmu; + } + + return NULL; +} + +struct perf_pmu *perf_pmus__find(const char *name) +{ + struct perf_pmu *pmu; + int dirfd; + + /* + * Once PMU is loaded it stays in the list, + * so we keep us from multiple reading/parsing + * the pmu format definitions. + */ + pmu = pmu_find(name); + if (pmu) + return pmu; + + dirfd = perf_pmu__event_source_devices_fd(); + pmu = perf_pmu__lookup(&pmus, dirfd, name); + close(dirfd); + + return pmu; +} + +static struct perf_pmu *perf_pmu__find2(int dirfd, const char *name) +{ + struct perf_pmu *pmu; + + /* + * Once PMU is loaded it stays in the list, + * so we keep us from multiple reading/parsing + * the pmu format definitions. + */ + pmu = pmu_find(name); + if (pmu) + return pmu; + + return perf_pmu__lookup(&pmus, dirfd, name); +} + +/* Add all pmus in sysfs to pmu list: */ +static void pmu_read_sysfs(void) +{ + int fd; + DIR *dir; + struct dirent *dent; + + fd = perf_pmu__event_source_devices_fd(); + if (fd < 0) + return; + + dir = fdopendir(fd); + if (!dir) + return; + + while ((dent = readdir(dir))) { + if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) + continue; + /* add to static LIST_HEAD(pmus): */ + perf_pmu__find2(fd, dent->d_name); + } + + closedir(dir); +} + +struct perf_pmu *perf_pmus__find_by_type(unsigned int type) +{ + struct perf_pmu *pmu; + + list_for_each_entry(pmu, &pmus, list) + if (pmu->type == type) + return pmu; + + return NULL; +} + +struct perf_pmu *perf_pmus__scan(struct perf_pmu *pmu) +{ + /* + * pmu iterator: If pmu is NULL, we start at the begin, + * otherwise return the next pmu. Returns NULL on end. + */ + if (!pmu) { + pmu_read_sysfs(); + pmu = list_prepare_entry(pmu, &pmus, list); + } + list_for_each_entry_continue(pmu, &pmus, list) + return pmu; + return NULL; +} const struct perf_pmu *perf_pmus__pmu_for_pmu_filter(const char *str) { struct perf_pmu *pmu = NULL; - while ((pmu = perf_pmu__scan(pmu)) != NULL) { + while ((pmu = perf_pmus__scan(pmu)) != NULL) { if (!strcmp(pmu->name, str)) return pmu; /* Ignore "uncore_" prefix. */ @@ -26,3 +146,275 @@ const struct perf_pmu *perf_pmus__pmu_for_pmu_filter(const char *str) } return NULL; } + +int perf_pmus__num_mem_pmus(void) +{ + struct perf_pmu *pmu = NULL; + int count = 0; + + while ((pmu = perf_pmus__scan(pmu)) != NULL) { + if (perf_pmu__is_mem_pmu(pmu)) + count++; + } + return count; +} + +/** Struct for ordering events as output in perf list. */ +struct sevent { + /** PMU for event. */ + const struct perf_pmu *pmu; + /** + * Optional event for name, desc, etc. If not present then this is a + * selectable PMU and the event name is shown as "//". + */ + const struct perf_pmu_alias *event; + /** Is the PMU for the CPU? */ + bool is_cpu; +}; + +static int cmp_sevent(const void *a, const void *b) +{ + const struct sevent *as = a; + const struct sevent *bs = b; + const char *a_pmu_name = NULL, *b_pmu_name = NULL; + const char *a_name = "//", *a_desc = NULL, *a_topic = ""; + const char *b_name = "//", *b_desc = NULL, *b_topic = ""; + int ret; + + if (as->event) { + a_name = as->event->name; + a_desc = as->event->desc; + a_topic = as->event->topic ?: ""; + a_pmu_name = as->event->pmu_name; + } + if (bs->event) { + b_name = bs->event->name; + b_desc = bs->event->desc; + b_topic = bs->event->topic ?: ""; + b_pmu_name = bs->event->pmu_name; + } + /* Put extra events last. */ + if (!!a_desc != !!b_desc) + return !!a_desc - !!b_desc; + + /* Order by topics. */ + ret = strcmp(a_topic, b_topic); + if (ret) + return ret; + + /* Order CPU core events to be first */ + if (as->is_cpu != bs->is_cpu) + return as->is_cpu ? -1 : 1; + + /* Order by PMU name. */ + if (as->pmu != bs->pmu) { + a_pmu_name = a_pmu_name ?: (as->pmu->name ?: ""); + b_pmu_name = b_pmu_name ?: (bs->pmu->name ?: ""); + ret = strcmp(a_pmu_name, b_pmu_name); + if (ret) + return ret; + } + + /* Order by event name. */ + return strcmp(a_name, b_name); +} + +static bool pmu_alias_is_duplicate(struct sevent *alias_a, + struct sevent *alias_b) +{ + const char *a_pmu_name = NULL, *b_pmu_name = NULL; + const char *a_name = "//", *b_name = "//"; + + + if (alias_a->event) { + a_name = alias_a->event->name; + a_pmu_name = alias_a->event->pmu_name; + } + if (alias_b->event) { + b_name = alias_b->event->name; + b_pmu_name = alias_b->event->pmu_name; + } + + /* Different names -> never duplicates */ + if (strcmp(a_name, b_name)) + return false; + + /* Don't remove duplicates for different PMUs */ + a_pmu_name = a_pmu_name ?: (alias_a->pmu->name ?: ""); + b_pmu_name = b_pmu_name ?: (alias_b->pmu->name ?: ""); + return strcmp(a_pmu_name, b_pmu_name) == 0; +} + +static int sub_non_neg(int a, int b) +{ + if (b > a) + return 0; + return a - b; +} + +static char *format_alias(char *buf, int len, const struct perf_pmu *pmu, + const struct perf_pmu_alias *alias) +{ + struct parse_events_term *term; + int used = snprintf(buf, len, "%s/%s", pmu->name, alias->name); + + list_for_each_entry(term, &alias->terms, list) { + if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) + used += snprintf(buf + used, sub_non_neg(len, used), + ",%s=%s", term->config, + term->val.str); + } + + if (sub_non_neg(len, used) > 0) { + buf[used] = '/'; + used++; + } + if (sub_non_neg(len, used) > 0) { + buf[used] = '\0'; + used++; + } else + buf[len - 1] = '\0'; + + return buf; +} + +void perf_pmus__print_pmu_events(const struct print_callbacks *print_cb, void *print_state) +{ + struct perf_pmu *pmu; + struct perf_pmu_alias *event; + char buf[1024]; + int printed = 0; + int len, j; + struct sevent *aliases; + + pmu = NULL; + len = 0; + while ((pmu = perf_pmus__scan(pmu)) != NULL) { + list_for_each_entry(event, &pmu->aliases, list) + len++; + if (pmu->selectable) + len++; + } + aliases = zalloc(sizeof(struct sevent) * len); + if (!aliases) { + pr_err("FATAL: not enough memory to print PMU events\n"); + return; + } + pmu = NULL; + j = 0; + while ((pmu = perf_pmus__scan(pmu)) != NULL) { + bool is_cpu = pmu->is_core; + + list_for_each_entry(event, &pmu->aliases, list) { + aliases[j].event = event; + aliases[j].pmu = pmu; + aliases[j].is_cpu = is_cpu; + j++; + } + if (pmu->selectable) { + aliases[j].event = NULL; + aliases[j].pmu = pmu; + aliases[j].is_cpu = is_cpu; + j++; + } + } + len = j; + qsort(aliases, len, sizeof(struct sevent), cmp_sevent); + for (j = 0; j < len; j++) { + const char *name, *alias = NULL, *scale_unit = NULL, + *desc = NULL, *long_desc = NULL, + *encoding_desc = NULL, *topic = NULL, + *pmu_name = NULL; + bool deprecated = false; + size_t buf_used; + + /* Skip duplicates */ + if (j > 0 && pmu_alias_is_duplicate(&aliases[j], &aliases[j - 1])) + continue; + + if (!aliases[j].event) { + /* A selectable event. */ + pmu_name = aliases[j].pmu->name; + buf_used = snprintf(buf, sizeof(buf), "%s//", pmu_name) + 1; + name = buf; + } else { + if (aliases[j].event->desc) { + name = aliases[j].event->name; + buf_used = 0; + } else { + name = format_alias(buf, sizeof(buf), aliases[j].pmu, + aliases[j].event); + if (aliases[j].is_cpu) { + alias = name; + name = aliases[j].event->name; + } + buf_used = strlen(buf) + 1; + } + pmu_name = aliases[j].event->pmu_name ?: (aliases[j].pmu->name ?: ""); + if (strlen(aliases[j].event->unit) || aliases[j].event->scale != 1.0) { + scale_unit = buf + buf_used; + buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used, + "%G%s", aliases[j].event->scale, + aliases[j].event->unit) + 1; + } + desc = aliases[j].event->desc; + long_desc = aliases[j].event->long_desc; + topic = aliases[j].event->topic; + encoding_desc = buf + buf_used; + buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used, + "%s/%s/", pmu_name, aliases[j].event->str) + 1; + deprecated = aliases[j].event->deprecated; + } + print_cb->print_event(print_state, + pmu_name, + topic, + name, + alias, + scale_unit, + deprecated, + "Kernel PMU event", + desc, + long_desc, + encoding_desc); + } + if (printed && pager_in_use()) + printf("\n"); + + zfree(&aliases); +} + +bool perf_pmus__have_event(const char *pname, const char *name) +{ + struct perf_pmu *pmu = perf_pmus__find(pname); + + return pmu && perf_pmu__have_event(pmu, name); +} + +bool perf_pmus__has_hybrid(void) +{ + static bool hybrid_scanned, has_hybrid; + + if (!hybrid_scanned) { + struct perf_pmu *pmu = NULL; + + while ((pmu = perf_pmus__scan(pmu)) != NULL) { + if (pmu->is_core && is_pmu_hybrid(pmu->name)) { + has_hybrid = true; + break; + } + } + hybrid_scanned = true; + } + return has_hybrid; +} + +struct perf_pmu *evsel__find_pmu(const struct evsel *evsel) +{ + struct perf_pmu *pmu = evsel->pmu; + + if (!pmu) { + pmu = perf_pmus__find_by_type(evsel->core.attr.type); + ((struct evsel *)evsel)->pmu = pmu; + } + return pmu; +} diff --git a/tools/perf/util/pmus.h b/tools/perf/util/pmus.h index 257de10788e8..2a771d9f8da7 100644 --- a/tools/perf/util/pmus.h +++ b/tools/perf/util/pmus.h @@ -2,9 +2,21 @@ #ifndef __PMUS_H #define __PMUS_H -extern struct list_head pmus; struct perf_pmu; +struct print_callbacks; + +void perf_pmus__destroy(void); + +struct perf_pmu *perf_pmus__find(const char *name); +struct perf_pmu *perf_pmus__find_by_type(unsigned int type); + +struct perf_pmu *perf_pmus__scan(struct perf_pmu *pmu); const struct perf_pmu *perf_pmus__pmu_for_pmu_filter(const char *str); +int perf_pmus__num_mem_pmus(void); +void perf_pmus__print_pmu_events(const struct print_callbacks *print_cb, void *print_state); +bool perf_pmus__have_event(const char *pname, const char *name); +bool perf_pmus__has_hybrid(void); + #endif /* __PMUS_H */ diff --git a/tools/perf/util/print-events.c b/tools/perf/util/print-events.c index 8d823bc906e6..9cee7bb7a561 100644 --- a/tools/perf/util/print-events.c +++ b/tools/perf/util/print-events.c @@ -20,6 +20,7 @@ #include "metricgroup.h" #include "parse-events.h" #include "pmu.h" +#include "pmus.h" #include "print-events.h" #include "probe-file.h" #include "string2.h" @@ -271,7 +272,7 @@ int print_hwcache_events(const struct print_callbacks *print_cb, void *print_sta struct perf_pmu *pmu = NULL; const char *event_type_descriptor = event_type_descriptors[PERF_TYPE_HW_CACHE]; - while ((pmu = perf_pmu__scan(pmu)) != NULL) { + while ((pmu = perf_pmus__scan(pmu)) != NULL) { /* * Skip uncore PMUs for performance. PERF_TYPE_HW_CACHE type * attributes can accept software PMUs in the extended type, so @@ -404,7 +405,7 @@ void print_events(const struct print_callbacks *print_cb, void *print_state) print_hwcache_events(print_cb, print_state); - print_pmu_events(print_cb, print_state); + perf_pmus__print_pmu_events(print_cb, print_state); print_cb->print_event(print_state, /*topic=*/NULL, diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index b27b27086422..7173f6fcdc11 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -22,6 +22,7 @@ #include "util/bpf-filter.h" #include "util/env.h" #include "util/pmu.h" +#include "util/pmus.h" #include #include "util.h" @@ -102,7 +103,7 @@ int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, return EOF; } -bool perf_pmu__has_hybrid(void) +bool perf_pmus__has_hybrid(void) { return false; } diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index a3e184e0b5ba..7ca69151136b 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -20,6 +20,7 @@ #include "util.h" #include "iostat.h" #include "pmu.h" +#include "pmus.h" #define CNTR_NOT_SUPPORTED "" #define CNTR_NOT_COUNTED "" @@ -695,7 +696,7 @@ static bool evlist__has_hybrid(struct evlist *evlist) { struct evsel *evsel; - if (!perf_pmu__has_hybrid()) + if (!perf_pmus__has_hybrid()) return false; evlist__for_each_entry(evlist, evsel) { -- cgit v1.2.3 From 94f9eb95d954bee0149fd1ce84c239c9e09ae9d8 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Sat, 27 May 2023 00:22:09 -0700 Subject: perf pmus: Remove perf_pmus__has_hybrid perf_pmus__has_hybrid was used to detect when there was >1 core PMU, this can be achieved with perf_pmus__num_core_pmus that doesn't depend upon is_pmu_hybrid and PMU name comparisons. When modifying the function calls take the opportunity to improve comments, enable/simplify tests that were previously failing for hybrid but now pass and to simplify generic code. Reviewed-by: Kan Liang Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ali Saidi Cc: Athira Rajeev Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: Huacai Chen Cc: Ingo Molnar Cc: James Clark Cc: Jing Zhang Cc: Jiri Olsa Cc: John Garry Cc: Kajol Jain Cc: Kang Minchul Cc: Leo Yan Cc: Madhavan Srinivasan Cc: Mark Rutland Cc: Mike Leach Cc: Ming Wang Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Ravi Bangoria Cc: Rob Herring Cc: Sandipan Das Cc: Sean Christopherson Cc: Suzuki Poulouse Cc: Thomas Richter Cc: Will Deacon Cc: Xing Zhengjun Cc: coresight@lists.linaro.org Cc: linux-arm-kernel@lists.infradead.org Link: https://lore.kernel.org/r/20230527072210.2900565-34-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/tests/hybrid.c | 2 +- tools/perf/arch/x86/util/evlist.c | 2 +- tools/perf/arch/x86/util/perf_regs.c | 2 +- tools/perf/builtin-record.c | 4 ++-- tools/perf/tests/attr.c | 9 ++++++++- tools/perf/tests/parse-metric.c | 7 ++----- tools/perf/tests/switch-tracking.c | 12 +----------- tools/perf/tests/topology.c | 14 ++------------ tools/perf/util/cputopo.c | 10 ++-------- tools/perf/util/evsel.c | 2 +- tools/perf/util/header.c | 2 +- tools/perf/util/mem-events.c | 18 +++++------------- tools/perf/util/metricgroup.c | 2 +- tools/perf/util/pmus.c | 18 ------------------ tools/perf/util/pmus.h | 1 - tools/perf/util/python.c | 4 ++-- tools/perf/util/stat-display.c | 2 +- 17 files changed, 31 insertions(+), 80 deletions(-) (limited to 'tools/perf/builtin-record.c') diff --git a/tools/perf/arch/x86/tests/hybrid.c b/tools/perf/arch/x86/tests/hybrid.c index e466735d68d5..eb152770f148 100644 --- a/tools/perf/arch/x86/tests/hybrid.c +++ b/tools/perf/arch/x86/tests/hybrid.c @@ -281,7 +281,7 @@ static int test_events(const struct evlist_test *events, int cnt) int test__hybrid(struct test_suite *test __maybe_unused, int subtest __maybe_unused) { - if (!perf_pmus__has_hybrid()) + if (perf_pmus__num_core_pmus() == 1) return TEST_SKIP; return test_events(test__hybrid_events, ARRAY_SIZE(test__hybrid_events)); diff --git a/tools/perf/arch/x86/util/evlist.c b/tools/perf/arch/x86/util/evlist.c index 8a6a0b98b976..cbd582182932 100644 --- a/tools/perf/arch/x86/util/evlist.c +++ b/tools/perf/arch/x86/util/evlist.c @@ -18,7 +18,7 @@ static int ___evlist__add_default_attrs(struct evlist *evlist, for (i = 0; i < nr_attrs; i++) event_attr_init(attrs + i); - if (!perf_pmus__has_hybrid()) + if (perf_pmus__num_core_pmus() == 1) return evlist__add_attrs(evlist, attrs, nr_attrs); for (i = 0; i < nr_attrs; i++) { diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c index 116384f19baf..8ad4112ad10c 100644 --- a/tools/perf/arch/x86/util/perf_regs.c +++ b/tools/perf/arch/x86/util/perf_regs.c @@ -292,7 +292,7 @@ uint64_t arch__intr_reg_mask(void) */ attr.sample_period = 1; - if (perf_pmus__has_hybrid()) { + if (perf_pmus__num_core_pmus() > 1) { struct perf_pmu *pmu = NULL; __u64 type = PERF_TYPE_RAW; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 4b9212f75493..aec18db7ff23 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1294,7 +1294,7 @@ static int record__open(struct record *rec) * of waiting or event synthesis. */ if (opts->target.initial_delay || target__has_cpu(&opts->target) || - perf_pmus__has_hybrid()) { + perf_pmus__num_core_pmus() > 1) { pos = evlist__get_tracking_event(evlist); if (!evsel__is_dummy_event(pos)) { /* Set up dummy event. */ @@ -2193,7 +2193,7 @@ static void record__uniquify_name(struct record *rec) char *new_name; int ret; - if (!perf_pmus__has_hybrid()) + if (perf_pmus__num_core_pmus() == 1) return; evlist__for_each_entry(evlist, pos) { diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c index 674876e6c8e6..61186d0d1cfa 100644 --- a/tools/perf/tests/attr.c +++ b/tools/perf/tests/attr.c @@ -185,8 +185,15 @@ static int test__attr(struct test_suite *test __maybe_unused, int subtest __mayb char path_dir[PATH_MAX]; char *exec_path; - if (perf_pmus__has_hybrid()) + if (perf_pmus__num_core_pmus() > 1) { + /* + * TODO: Attribute tests hard code the PMU type. If there are >1 + * core PMU then each PMU will have a different type whic + * requires additional support. + */ + pr_debug("Skip test on hybrid systems"); return TEST_SKIP; + } /* First try development tree tests. */ if (!lstat("./tests", &st)) diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c index 1d6493a5a956..2c28fb50dc24 100644 --- a/tools/perf/tests/parse-metric.c +++ b/tools/perf/tests/parse-metric.c @@ -302,11 +302,8 @@ static int test__parse_metric(struct test_suite *test __maybe_unused, int subtes TEST_ASSERT_VAL("DCache_L2 failed", test_dcache_l2() == 0); TEST_ASSERT_VAL("recursion fail failed", test_recursion_fail() == 0); TEST_ASSERT_VAL("Memory bandwidth", test_memory_bandwidth() == 0); - - if (!perf_pmus__has_hybrid()) { - TEST_ASSERT_VAL("cache_miss_cycles failed", test_cache_miss_cycles() == 0); - TEST_ASSERT_VAL("test metric group", test_metric_group() == 0); - } + TEST_ASSERT_VAL("cache_miss_cycles failed", test_cache_miss_cycles() == 0); + TEST_ASSERT_VAL("test metric group", test_metric_group() == 0); return 0; } diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index cff6ab87b2f6..e52b031bedc5 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -375,17 +375,7 @@ static int test__switch_tracking(struct test_suite *test __maybe_unused, int sub cpu_clocks_evsel = evlist__last(evlist); /* Second event */ - if (perf_pmus__has_hybrid()) { - cycles = "cpu_core/cycles/u"; - err = parse_event(evlist, cycles); - if (err) { - cycles = "cpu_atom/cycles/u"; - pr_debug("Trying %s\n", cycles); - err = parse_event(evlist, cycles); - } - } else { - err = parse_event(evlist, cycles); - } + err = parse_event(evlist, cycles); if (err) { pr_debug("Failed to parse event %s\n", cycles); goto out_err; diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c index 49e80d15420b..9dee63734e66 100644 --- a/tools/perf/tests/topology.c +++ b/tools/perf/tests/topology.c @@ -41,18 +41,8 @@ static int session_write_header(char *path) session = perf_session__new(&data, NULL); TEST_ASSERT_VAL("can't get session", !IS_ERR(session)); - if (!perf_pmus__has_hybrid()) { - session->evlist = evlist__new_default(); - TEST_ASSERT_VAL("can't get evlist", session->evlist); - } else { - struct parse_events_error err; - - session->evlist = evlist__new(); - TEST_ASSERT_VAL("can't get evlist", session->evlist); - parse_events_error__init(&err); - parse_events(session->evlist, "cpu_core/cycles/", &err); - parse_events_error__exit(&err); - } + session->evlist = evlist__new_default(); + TEST_ASSERT_VAL("can't get evlist", session->evlist); perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY); perf_header__set_feat(&session->header, HEADER_NRCPUS); diff --git a/tools/perf/util/cputopo.c b/tools/perf/util/cputopo.c index 729142ec9a9a..81cfc85f4668 100644 --- a/tools/perf/util/cputopo.c +++ b/tools/perf/util/cputopo.c @@ -472,15 +472,9 @@ struct hybrid_topology *hybrid_topology__new(void) { struct perf_pmu *pmu = NULL; struct hybrid_topology *tp = NULL; - u32 nr = 0, i = 0; + int nr = perf_pmus__num_core_pmus(), i = 0; - if (!perf_pmus__has_hybrid()) - return NULL; - - while ((pmu = perf_pmus__scan_core(pmu)) != NULL) - nr++; - - if (nr == 0) + if (nr <= 1) return NULL; tp = zalloc(sizeof(*tp) + sizeof(tp->nodes[0]) * nr); diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index b4237fc713d5..ec2ce39d66d8 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -3140,7 +3140,7 @@ void evsel__zero_per_pkg(struct evsel *evsel) */ bool evsel__is_hybrid(const struct evsel *evsel) { - if (!perf_pmus__has_hybrid()) + if (perf_pmus__num_core_pmus() == 1) return false; return evsel->core.is_pmu_core; diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 2dde3ca20de5..0c69109c0a3b 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1605,7 +1605,7 @@ static int write_pmu_caps(struct feat_fd *ff, * Write hybrid pmu caps first to maintain compatibility with * older perf tool. */ - if (perf_pmus__has_hybrid()) { + if (perf_pmus__num_core_pmus() > 1) { pmu = NULL; while ((pmu = perf_pmus__scan_core(pmu))) { ret = __write_pmu_caps(ff, pmu, true); diff --git a/tools/perf/util/mem-events.c b/tools/perf/util/mem-events.c index c5596230a308..be15aadb6b14 100644 --- a/tools/perf/util/mem-events.c +++ b/tools/perf/util/mem-events.c @@ -121,6 +121,7 @@ int perf_mem_events__init(void) for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) { struct perf_mem_event *e = perf_mem_events__ptr(j); char sysfs_name[100]; + struct perf_pmu *pmu = NULL; /* * If the event entry isn't valid, skip initialization @@ -129,18 +130,9 @@ int perf_mem_events__init(void) if (!e->tag) continue; - if (!perf_pmus__has_hybrid()) { - scnprintf(sysfs_name, sizeof(sysfs_name), - e->sysfs_name, "cpu"); - e->supported = perf_mem_event__supported(mnt, sysfs_name); - } else { - struct perf_pmu *pmu = NULL; - - while ((pmu = perf_pmus__scan_core(pmu)) != NULL) { - scnprintf(sysfs_name, sizeof(sysfs_name), - e->sysfs_name, pmu->name); - e->supported |= perf_mem_event__supported(mnt, sysfs_name); - } + while ((pmu = perf_pmus__scan_core(pmu)) != NULL) { + scnprintf(sysfs_name, sizeof(sysfs_name), e->sysfs_name, pmu->name); + e->supported |= perf_mem_event__supported(mnt, sysfs_name); } if (e->supported) @@ -196,7 +188,7 @@ int perf_mem_events__record_args(const char **rec_argv, int *argv_nr, if (!e->record) continue; - if (!perf_pmus__has_hybrid()) { + if (perf_pmus__num_core_pmus() == 1) { if (!e->supported) { pr_err("failed: event '%s' not supported\n", perf_mem_events__name(j, NULL)); diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 092ed6386a39..70ef2e23a710 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -274,7 +274,7 @@ static int setup_metric_events(const char *pmu, struct hashmap *ids, const char *metric_id; struct evsel *ev; size_t ids_size, matched_events, i; - bool all_pmus = !strcmp(pmu, "all") || !perf_pmus__has_hybrid() || !is_pmu_hybrid(pmu); + bool all_pmus = !strcmp(pmu, "all") || perf_pmus__num_core_pmus() == 1 || !is_pmu_core(pmu); *out_metric_events = NULL; ids_size = hashmap__size(ids); diff --git a/tools/perf/util/pmus.c b/tools/perf/util/pmus.c index bf927aed162e..53f11f6ce878 100644 --- a/tools/perf/util/pmus.c +++ b/tools/perf/util/pmus.c @@ -464,24 +464,6 @@ bool perf_pmus__have_event(const char *pname, const char *name) return pmu && perf_pmu__have_event(pmu, name); } -bool perf_pmus__has_hybrid(void) -{ - static bool hybrid_scanned, has_hybrid; - - if (!hybrid_scanned) { - struct perf_pmu *pmu = NULL; - - while ((pmu = perf_pmus__scan_core(pmu)) != NULL) { - if (is_pmu_hybrid(pmu->name)) { - has_hybrid = true; - break; - } - } - hybrid_scanned = true; - } - return has_hybrid; -} - int perf_pmus__num_core_pmus(void) { static int count; diff --git a/tools/perf/util/pmus.h b/tools/perf/util/pmus.h index 27400a027d41..1e710720aec7 100644 --- a/tools/perf/util/pmus.h +++ b/tools/perf/util/pmus.h @@ -18,7 +18,6 @@ const struct perf_pmu *perf_pmus__pmu_for_pmu_filter(const char *str); int perf_pmus__num_mem_pmus(void); void perf_pmus__print_pmu_events(const struct print_callbacks *print_cb, void *print_state); bool perf_pmus__have_event(const char *pname, const char *name); -bool perf_pmus__has_hybrid(void); int perf_pmus__num_core_pmus(void); #endif /* __PMUS_H */ diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 7173f6fcdc11..8de1b759bbaa 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -103,9 +103,9 @@ int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, return EOF; } -bool perf_pmus__has_hybrid(void) +int perf_pmus__num_core_pmus(void) { - return false; + return 1; } bool evsel__is_aux_event(const struct evsel *evsel __maybe_unused) diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c index 7ca69151136b..a2bbdc25d979 100644 --- a/tools/perf/util/stat-display.c +++ b/tools/perf/util/stat-display.c @@ -696,7 +696,7 @@ static bool evlist__has_hybrid(struct evlist *evlist) { struct evsel *evsel; - if (!perf_pmus__has_hybrid()) + if (perf_pmus__num_core_pmus() == 1) return false; evlist__for_each_entry(evlist, evsel) { -- cgit v1.2.3