diff options
| author | Ian Rogers <irogers@google.com> | 2026-06-22 18:27:46 -0700 |
|---|---|---|
| committer | Namhyung Kim <namhyung@kernel.org> | 2026-06-30 17:09:13 -0700 |
| commit | e6ad1fb3458f9e77f63bcd555baf7a08008ecc2e (patch) | |
| tree | 394c3fac58f5b1fc5202040034687621edc8d281 /tools/perf/util | |
| parent | 5437e98903897246e3f223ab68f1f8bda8b5ed7e (diff) | |
| download | linux-next-e6ad1fb3458f9e77f63bcd555baf7a08008ecc2e.tar.gz linux-next-e6ad1fb3458f9e77f63bcd555baf7a08008ecc2e.zip | |
perf parse-events: Restrict core PMU bypass to --cputype option
Commit b1c5efbfd92e ("perf parse-events: Remove hard coded legacy hardware
and cache parsing") introduced a bypass to PMU filtering to prevent uncore
PMUs from being filtered out during event parsing, which was required for
resolving `duration_time` and `uncore_freq` when running with `--cputype`.
However, this bypass was active whenever `pmu_filter` was set, which also
incorrectly bypassed filtering for the `--pmu-filter` option.
Introduce a `cputype_filter` boolean flag in `parse_events_state` and
`parse_events_option_args` to distinguish filtering initiated by
`--cputype` from that initiated by `--pmu-filter`. Restrict the core-only
check in `parse_events__filter_pmu()` to when `cputype_filter` is true.
Fixes: b1c5efbfd92e ("perf parse-events: Remove hard coded legacy hardware and cache parsing")
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Diffstat (limited to 'tools/perf/util')
| -rw-r--r-- | tools/perf/util/metricgroup.c | 26 | ||||
| -rw-r--r-- | tools/perf/util/metricgroup.h | 4 | ||||
| -rw-r--r-- | tools/perf/util/parse-events.c | 32 | ||||
| -rw-r--r-- | tools/perf/util/parse-events.h | 17 | ||||
| -rw-r--r-- | tools/perf/util/python.c | 3 |
5 files changed, 53 insertions, 29 deletions
diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 8c7b299a55db..69bfa2a723b2 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -1262,7 +1262,8 @@ static int parse_ids(bool metric_no_merge, bool fake_pmu, struct expr_parse_ctx *ids, const char *modifier, bool group_events, const bool tool_events[TOOL_PMU__EVENT_MAX], struct evlist **out_evlist, - const char *filter_pmu) + const char *filter_pmu, + bool cputype_filter) { struct parse_events_error parse_error; struct evlist *parsed_evlist; @@ -1317,7 +1318,9 @@ static int parse_ids(bool metric_no_merge, bool fake_pmu, pr_debug("Parsing metric events '%s'\n", events.buf); parse_events_error__init(&parse_error); ret = __parse_events(parsed_evlist, events.buf, filter_pmu, - &parse_error, fake_pmu, /*warn_if_reordered=*/false, + cputype_filter, + &parse_error, fake_pmu, + /*warn_if_reordered=*/false, /*fake_tp=*/false); if (ret) { parse_events_error__print(&parse_error, events.buf); @@ -1382,7 +1385,7 @@ static struct evsel *pick_display_evsel(struct list_head *metric_list, } static int parse_groups(struct evlist *perf_evlist, - const char *pmu, const char *str, + const char *pmu, bool cputype_filter, const char *str, bool metric_no_group, bool metric_no_merge, bool metric_no_threshold, @@ -1420,7 +1423,8 @@ static int parse_groups(struct evlist *perf_evlist, /*group_events=*/false, tool_events, &combined_evlist, - (pmu && strcmp(pmu, "all") == 0) ? NULL : pmu); + (pmu && strcmp(pmu, "all") == 0) ? NULL : pmu, + cputype_filter); } if (combined) expr__ctx_free(combined); @@ -1476,7 +1480,8 @@ static int parse_groups(struct evlist *perf_evlist, if (!metric_evlist) { ret = parse_ids(metric_no_merge, fake_pmu, m->pctx, m->modifier, m->group_events, tool_events, &m->evlist, - (pmu && strcmp(pmu, "all") == 0) ? NULL : pmu); + (pmu && strcmp(pmu, "all") == 0) ? NULL : pmu, + cputype_filter); if (ret) goto out; @@ -1543,6 +1548,7 @@ static int parse_groups(struct evlist *perf_evlist, if (combined_evlist) { evlist__splice_list_tail(perf_evlist, &evlist__core(combined_evlist)->entries); evlist__put(combined_evlist); + combined_evlist = NULL; } list_for_each_entry(m, &metric_list, nd) { @@ -1551,12 +1557,15 @@ static int parse_groups(struct evlist *perf_evlist, } out: + if (combined_evlist) + evlist__put(combined_evlist); metricgroup__free_metrics(&metric_list); return ret; } int metricgroup__parse_groups(struct evlist *perf_evlist, const char *pmu, + bool cputype_filter, const char *str, bool metric_no_group, bool metric_no_merge, @@ -1570,16 +1579,17 @@ int metricgroup__parse_groups(struct evlist *perf_evlist, if (hardware_aware_grouping) pr_debug("Use hardware aware grouping instead of traditional metric grouping method\n"); - return parse_groups(perf_evlist, pmu, str, metric_no_group, metric_no_merge, + return parse_groups(perf_evlist, pmu, cputype_filter, str, metric_no_group, metric_no_merge, metric_no_threshold, user_requested_cpu_list, system_wide, /*fake_pmu=*/false, table); } int metricgroup__parse_groups_test(struct evlist *evlist, const struct pmu_metrics_table *table, - const char *str) + const char *str, + bool cputype_filter) { - return parse_groups(evlist, "all", str, + return parse_groups(evlist, "all", cputype_filter, str, /*metric_no_group=*/false, /*metric_no_merge=*/false, /*metric_no_threshold=*/false, diff --git a/tools/perf/util/metricgroup.h b/tools/perf/util/metricgroup.h index 4be6bfc13c46..6a66f14dd01b 100644 --- a/tools/perf/util/metricgroup.h +++ b/tools/perf/util/metricgroup.h @@ -71,6 +71,7 @@ struct metric_event *metricgroup__lookup(struct rblist *metric_events, bool create); int metricgroup__parse_groups(struct evlist *perf_evlist, const char *pmu, + bool cputype_filter, const char *str, bool metric_no_group, bool metric_no_merge, @@ -80,7 +81,8 @@ int metricgroup__parse_groups(struct evlist *perf_evlist, bool hardware_aware_grouping); int metricgroup__parse_groups_test(struct evlist *evlist, const struct pmu_metrics_table *table, - const char *str); + const char *str, + bool cputype_filter); int metricgroup__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn, void *data); diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 194bc94dfc1e..cc7ad331a49f 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -429,6 +429,9 @@ bool parse_events__filter_pmu(const struct parse_events_state *parse_state, if (parse_state->pmu_filter == NULL) return false; + if (parse_state->cputype_filter && !pmu->is_core) + return false; + return perf_pmu__wildcard_match(pmu, parse_state->pmu_filter) == 0; } @@ -2288,18 +2291,20 @@ static int parse_events__sort_events_and_fix_groups(struct list_head *list) return (idx_changed || num_leaders != orig_num_leaders) ? 1 : 0; } -int __parse_events(struct evlist *evlist, const char *str, const char *pmu_filter, +int __parse_events(struct evlist *evlist, const char *str, + const char *pmu_filter, bool cputype_filter, struct parse_events_error *err, bool fake_pmu, bool warn_if_reordered, bool fake_tp) { struct parse_events_state parse_state = { - .list = LIST_HEAD_INIT(parse_state.list), - .idx = evlist__nr_entries(evlist), - .error = err, - .stoken = PE_START_EVENTS, - .fake_pmu = fake_pmu, - .fake_tp = fake_tp, - .pmu_filter = pmu_filter, + .list = LIST_HEAD_INIT(parse_state.list), + .idx = evlist__nr_entries(evlist), + .error = err, + .stoken = PE_START_EVENTS, + .fake_pmu = fake_pmu, + .fake_tp = fake_tp, + .pmu_filter = pmu_filter, + .cputype_filter = cputype_filter, .match_legacy_cache_terms = true, }; int ret, ret2; @@ -2312,15 +2317,15 @@ int __parse_events(struct evlist *evlist, const char *str, const char *pmu_filte } ret2 = parse_events__sort_events_and_fix_groups(&parse_state.list); - if (ret2 < 0) - return ret; + if (ret2 < 0 && !ret) + ret = ret2; /* * Add list to the evlist even with errors to allow callers to clean up. */ evlist__splice_list_tail(evlist, &parse_state.list); - if (ret2 && warn_if_reordered && !parse_state.wild_card_pmus) { + if (ret2 > 0 && warn_if_reordered && !parse_state.wild_card_pmus) { evlist__uniquify_evsel_names(evlist, &stat_config); pr_warning("WARNING: events were regrouped to match PMUs\n"); @@ -2518,8 +2523,9 @@ int parse_events_option(const struct option *opt, const char *str, int ret; parse_events_error__init(&err); - ret = __parse_events(*args->evlistp, str, args->pmu_filter, &err, - /*fake_pmu=*/false, /*warn_if_reordered=*/true, + ret = __parse_events(*args->evlistp, str, args->pmu_filter, + args->cputype_filter, &err, /*fake_pmu=*/false, + /*warn_if_reordered=*/true, /*fake_tp=*/false); if (ret) { diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index 3577ab213730..b14c832b03a1 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -26,20 +26,23 @@ const char *event_type(size_t type); struct parse_events_option_args { struct evlist **evlistp; const char *pmu_filter; + bool cputype_filter; }; int parse_events_option(const struct option *opt, const char *str, int unset); int parse_events_option_new_evlist(const struct option *opt, const char *str, int unset); -__attribute__((nonnull(1, 2, 4))) -int __parse_events(struct evlist *evlist, const char *str, const char *pmu_filter, - struct parse_events_error *error, bool fake_pmu, - bool warn_if_reordered, bool fake_tp); +__attribute__((nonnull(1, 2, 5))) int +__parse_events(struct evlist *evlist, const char *str, const char *pmu_filter, + bool cputype_filter, struct parse_events_error *error, + bool fake_pmu, bool warn_if_reordered, bool fake_tp); __attribute__((nonnull(1, 2, 3))) static inline int parse_events(struct evlist *evlist, const char *str, struct parse_events_error *err) { - return __parse_events(evlist, str, /*pmu_filter=*/NULL, err, /*fake_pmu=*/false, - /*warn_if_reordered=*/true, /*fake_tp=*/false); + return __parse_events(evlist, str, /*pmu_filter=*/NULL, + /*cputype_filter=*/false, err, /*fake_pmu=*/false, + /*warn_if_reordered=*/true, + /*fake_tp=*/false); } int parse_event(struct evlist *evlist, const char *str); @@ -161,6 +164,8 @@ struct parse_events_state { bool fake_tp; /* If non-null, when wildcard matching only match the given PMU. */ const char *pmu_filter; + /* If true, the pmu_filter was set by --cputype option. */ + bool cputype_filter; /* Should PE_LEGACY_NAME tokens be generated for config terms? */ bool match_legacy_cache_terms; /* Were multiple PMUs scanned to find events? */ diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 11e1f39c1bea..af85c0771c44 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -3411,7 +3411,8 @@ static PyObject *pyrf__parse_metrics(PyObject *self, PyObject *args) ((struct pyrf_cpu_map *)pcpus)->cpus : NULL; perf_evlist__set_maps(evlist__core(evlist), cpus, threads); - ret = metricgroup__parse_groups(evlist, pmu ?: "all", input, + ret = metricgroup__parse_groups(evlist, pmu ?: "all", + /*cputype_filter=*/false, input, /*metric_no_group=*/ false, /*metric_no_merge=*/ false, /*metric_no_threshold=*/ true, |
