Skip to content

Commit f6f1198

Browse files
committed
perf parse-events: Avoid scanning PMUs that can't contain events
JIRA: https://issues.redhat.com/browse/RHEL-78200 upstream ======== commit e1ec69e Author: Ian Rogers <irogers@google.com> Date: Tue Jun 24 16:18:35 2025 -0700 description =========== Add perf_pmus__scan_for_event that only reads sysfs for pmus that could contain a given event. Signed-off-by: Ian Rogers <irogers@google.com> Link: https://lore.kernel.org/r/20250624231837.179536-2-irogers@google.com Signed-off-by: Namhyung Kim <namhyung@kernel.org> Signed-off-by: Anubhav Shelat <ashelat@redhat.com>
1 parent c3c703b commit f6f1198

File tree

3 files changed

+97
-15
lines changed

3 files changed

+97
-15
lines changed

tools/perf/util/parse-events.c

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ int parse_events_add_cache(struct list_head *list, int *idx, const char *name,
485485
int ret = 0;
486486
struct evsel *first_wildcard_match = NULL;
487487

488-
while ((pmu = perf_pmus__scan(pmu)) != NULL) {
488+
while ((pmu = perf_pmus__scan_for_event(pmu, name)) != NULL) {
489489
LIST_HEAD(config_terms);
490490
struct perf_event_attr attr;
491491

@@ -1676,7 +1676,8 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
16761676

16771677
INIT_LIST_HEAD(list);
16781678

1679-
while ((pmu = perf_pmus__scan(pmu)) != NULL) {
1679+
while ((pmu = perf_pmus__scan_for_event(pmu, event_name)) != NULL) {
1680+
16801681
if (parse_events__filter_pmu(parse_state, pmu))
16811682
continue;
16821683

@@ -1755,19 +1756,21 @@ int parse_events_multi_pmu_add_or_add_pmu(struct parse_events_state *parse_state
17551756

17561757
pmu = NULL;
17571758
/* Failed to add, try wildcard expansion of event_or_pmu as a PMU name. */
1758-
while ((pmu = perf_pmus__scan(pmu)) != NULL) {
1759-
if (!parse_events__filter_pmu(parse_state, pmu) &&
1760-
perf_pmu__wildcard_match(pmu, event_or_pmu)) {
1761-
if (!parse_events_add_pmu(parse_state, *listp, pmu,
1762-
const_parsed_terms,
1763-
first_wildcard_match,
1764-
/*alternate_hw_config=*/PERF_COUNT_HW_MAX)) {
1765-
ok++;
1766-
parse_state->wild_card_pmus = true;
1767-
}
1768-
if (first_wildcard_match == NULL)
1769-
first_wildcard_match =
1770-
container_of((*listp)->prev, struct evsel, core.node);
1759+
while ((pmu = perf_pmus__scan_matching_wildcard(pmu, event_or_pmu)) != NULL) {
1760+
1761+
if (parse_events__filter_pmu(parse_state, pmu))
1762+
continue;
1763+
1764+
if (!parse_events_add_pmu(parse_state, *listp, pmu,
1765+
const_parsed_terms,
1766+
first_wildcard_match,
1767+
/*alternate_hw_config=*/PERF_COUNT_HW_MAX)) {
1768+
ok++;
1769+
parse_state->wild_card_pmus = true;
1770+
}
1771+
if (first_wildcard_match == NULL) {
1772+
first_wildcard_match =
1773+
container_of((*listp)->prev, struct evsel, core.node);
17711774
}
17721775
}
17731776
if (ok)

tools/perf/util/pmus.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "tool_pmu.h"
2020
#include "print-events.h"
2121
#include "strbuf.h"
22+
#include "string2.h"
2223

2324
/*
2425
* core_pmus: A PMU belongs to core_pmus if it's name is "cpu" or it's sysfs
@@ -350,6 +351,82 @@ struct perf_pmu *perf_pmus__scan_core(struct perf_pmu *pmu)
350351
return NULL;
351352
}
352353

354+
struct perf_pmu *perf_pmus__scan_for_event(struct perf_pmu *pmu, const char *event)
355+
{
356+
bool use_core_pmus = !pmu || pmu->is_core;
357+
358+
if (!pmu) {
359+
/* Hwmon filename values that aren't used. */
360+
enum hwmon_type type;
361+
int number;
362+
/*
363+
* Core PMUs, other sysfs PMUs and tool PMU can take all event
364+
* types or aren't wother optimizing for.
365+
*/
366+
unsigned int to_read_pmus = PERF_TOOL_PMU_TYPE_PE_CORE_MASK |
367+
PERF_TOOL_PMU_TYPE_PE_OTHER_MASK |
368+
PERF_TOOL_PMU_TYPE_TOOL_MASK;
369+
370+
/* Could the event be a hwmon event? */
371+
if (parse_hwmon_filename(event, &type, &number, /*item=*/NULL, /*alarm=*/NULL))
372+
to_read_pmus |= PERF_TOOL_PMU_TYPE_HWMON_MASK;
373+
374+
pmu_read_sysfs(to_read_pmus);
375+
pmu = list_prepare_entry(pmu, &core_pmus, list);
376+
}
377+
if (use_core_pmus) {
378+
list_for_each_entry_continue(pmu, &core_pmus, list)
379+
return pmu;
380+
381+
pmu = NULL;
382+
pmu = list_prepare_entry(pmu, &other_pmus, list);
383+
}
384+
list_for_each_entry_continue(pmu, &other_pmus, list)
385+
return pmu;
386+
return NULL;
387+
}
388+
389+
struct perf_pmu *perf_pmus__scan_matching_wildcard(struct perf_pmu *pmu, const char *wildcard)
390+
{
391+
bool use_core_pmus = !pmu || pmu->is_core;
392+
393+
if (!pmu) {
394+
/*
395+
* Core PMUs, other sysfs PMUs and tool PMU can have any name or
396+
* aren't wother optimizing for.
397+
*/
398+
unsigned int to_read_pmus = PERF_TOOL_PMU_TYPE_PE_CORE_MASK |
399+
PERF_TOOL_PMU_TYPE_PE_OTHER_MASK |
400+
PERF_TOOL_PMU_TYPE_TOOL_MASK;
401+
402+
/*
403+
* Hwmon PMUs have an alias from a sysfs name like hwmon0,
404+
* hwmon1, etc. or have a name of hwmon_<name>. They therefore
405+
* can only have a wildcard match if the wildcard begins with
406+
* "hwmon".
407+
*/
408+
if (strisglob(wildcard) ||
409+
(strlen(wildcard) >= 5 && strncmp("hwmon", wildcard, 5) == 0))
410+
to_read_pmus |= PERF_TOOL_PMU_TYPE_HWMON_MASK;
411+
412+
pmu_read_sysfs(to_read_pmus);
413+
pmu = list_prepare_entry(pmu, &core_pmus, list);
414+
}
415+
if (use_core_pmus) {
416+
list_for_each_entry_continue(pmu, &core_pmus, list) {
417+
if (perf_pmu__wildcard_match(pmu, wildcard))
418+
return pmu;
419+
}
420+
pmu = NULL;
421+
pmu = list_prepare_entry(pmu, &other_pmus, list);
422+
}
423+
list_for_each_entry_continue(pmu, &other_pmus, list) {
424+
if (perf_pmu__wildcard_match(pmu, wildcard))
425+
return pmu;
426+
}
427+
return NULL;
428+
}
429+
353430
static struct perf_pmu *perf_pmus__scan_skip_duplicates(struct perf_pmu *pmu)
354431
{
355432
bool use_core_pmus = !pmu || pmu->is_core;

tools/perf/util/pmus.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ struct perf_pmu *perf_pmus__find_by_type(unsigned int type);
1919

2020
struct perf_pmu *perf_pmus__scan(struct perf_pmu *pmu);
2121
struct perf_pmu *perf_pmus__scan_core(struct perf_pmu *pmu);
22+
struct perf_pmu *perf_pmus__scan_for_event(struct perf_pmu *pmu, const char *event);
23+
struct perf_pmu *perf_pmus__scan_matching_wildcard(struct perf_pmu *pmu, const char *wildcard);
2224

2325
const struct perf_pmu *perf_pmus__pmu_for_pmu_filter(const char *str);
2426

0 commit comments

Comments
 (0)