mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 04:31:50 +00:00
perf pmu: Count sys and cpuid JSON events separately
Sys events are eagerly loaded as each event has a compat option that may
mean the event is or isn't associated with the PMU.
These shouldn't be counted as loaded_json_events as that is used for
JSON events matching the CPUID that may or may not have been loaded. The
mismatch causes issues on ARM64 that uses sys events.
Fixes: e6ff1eed35
("perf pmu: Lazily add JSON events")
Closes: https://lore.kernel.org/lkml/20240510024729.1075732-1-justin.he@arm.com/
Reported-by: Jia He <justin.he@arm.com>
Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: John Garry <john.g.garry@oracle.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20240511003601.2666907-1-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
193a9e3020
commit
d9c5f5f94c
@ -36,6 +36,18 @@ struct perf_pmu perf_pmu__fake = {
|
||||
|
||||
#define UNIT_MAX_LEN 31 /* max length for event unit name */
|
||||
|
||||
enum event_source {
|
||||
/* An event loaded from /sys/devices/<pmu>/events. */
|
||||
EVENT_SRC_SYSFS,
|
||||
/* An event loaded from a CPUID matched json file. */
|
||||
EVENT_SRC_CPU_JSON,
|
||||
/*
|
||||
* An event loaded from a /sys/devices/<pmu>/identifier matched json
|
||||
* file.
|
||||
*/
|
||||
EVENT_SRC_SYS_JSON,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct perf_pmu_alias - An event either read from sysfs or builtin in
|
||||
* pmu-events.c, created by parsing the pmu-events json files.
|
||||
@ -521,7 +533,7 @@ static int update_alias(const struct pmu_event *pe,
|
||||
|
||||
static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name,
|
||||
const char *desc, const char *val, FILE *val_fd,
|
||||
const struct pmu_event *pe)
|
||||
const struct pmu_event *pe, enum event_source src)
|
||||
{
|
||||
struct perf_pmu_alias *alias;
|
||||
int ret;
|
||||
@ -574,25 +586,30 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name,
|
||||
}
|
||||
snprintf(alias->unit, sizeof(alias->unit), "%s", unit);
|
||||
}
|
||||
if (!pe) {
|
||||
/* Update an event from sysfs with json data. */
|
||||
struct update_alias_data data = {
|
||||
.pmu = pmu,
|
||||
.alias = alias,
|
||||
};
|
||||
|
||||
switch (src) {
|
||||
default:
|
||||
case EVENT_SRC_SYSFS:
|
||||
alias->from_sysfs = true;
|
||||
if (pmu->events_table) {
|
||||
/* Update an event from sysfs with json data. */
|
||||
struct update_alias_data data = {
|
||||
.pmu = pmu,
|
||||
.alias = alias,
|
||||
};
|
||||
if (pmu_events_table__find_event(pmu->events_table, pmu, name,
|
||||
update_alias, &data) == 0)
|
||||
pmu->loaded_json_aliases++;
|
||||
pmu->cpu_json_aliases++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pe)
|
||||
pmu->sysfs_aliases++;
|
||||
else
|
||||
pmu->loaded_json_aliases++;
|
||||
break;
|
||||
case EVENT_SRC_CPU_JSON:
|
||||
pmu->cpu_json_aliases++;
|
||||
break;
|
||||
case EVENT_SRC_SYS_JSON:
|
||||
pmu->sys_json_aliases++;
|
||||
break;
|
||||
|
||||
}
|
||||
list_add_tail(&alias->list, &pmu->aliases);
|
||||
return 0;
|
||||
}
|
||||
@ -653,7 +670,8 @@ static int __pmu_aliases_parse(struct perf_pmu *pmu, int events_dir_fd)
|
||||
}
|
||||
|
||||
if (perf_pmu__new_alias(pmu, name, /*desc=*/ NULL,
|
||||
/*val=*/ NULL, file, /*pe=*/ NULL) < 0)
|
||||
/*val=*/ NULL, file, /*pe=*/ NULL,
|
||||
EVENT_SRC_SYSFS) < 0)
|
||||
pr_debug("Cannot set up %s\n", name);
|
||||
fclose(file);
|
||||
}
|
||||
@ -946,7 +964,8 @@ static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe,
|
||||
{
|
||||
struct perf_pmu *pmu = vdata;
|
||||
|
||||
perf_pmu__new_alias(pmu, pe->name, pe->desc, pe->event, /*val_fd=*/ NULL, pe);
|
||||
perf_pmu__new_alias(pmu, pe->name, pe->desc, pe->event, /*val_fd=*/ NULL,
|
||||
pe, EVENT_SRC_CPU_JSON);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -981,13 +1000,14 @@ static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe,
|
||||
return 0;
|
||||
|
||||
if (pmu_uncore_alias_match(pe->pmu, pmu->name) &&
|
||||
pmu_uncore_identifier_match(pe->compat, pmu->id)) {
|
||||
pmu_uncore_identifier_match(pe->compat, pmu->id)) {
|
||||
perf_pmu__new_alias(pmu,
|
||||
pe->name,
|
||||
pe->desc,
|
||||
pe->event,
|
||||
/*val_fd=*/ NULL,
|
||||
pe);
|
||||
pe,
|
||||
EVENT_SRC_SYS_JSON);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1082,6 +1102,12 @@ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char
|
||||
pmu->max_precise = pmu_max_precise(dirfd, pmu);
|
||||
pmu->alias_name = pmu_find_alias_name(pmu, dirfd);
|
||||
pmu->events_table = perf_pmu__find_events_table(pmu);
|
||||
/*
|
||||
* Load the sys json events/aliases when loading the PMU as each event
|
||||
* may have a different compat regular expression. We therefore can't
|
||||
* know the number of sys json events/aliases without computing the
|
||||
* regular expressions for them all.
|
||||
*/
|
||||
pmu_add_sys_aliases(pmu);
|
||||
list_add_tail(&pmu->list, pmus);
|
||||
|
||||
@ -1739,12 +1765,14 @@ size_t perf_pmu__num_events(struct perf_pmu *pmu)
|
||||
size_t nr;
|
||||
|
||||
pmu_aliases_parse(pmu);
|
||||
nr = pmu->sysfs_aliases;
|
||||
nr = pmu->sysfs_aliases + pmu->sys_json_aliases;;
|
||||
|
||||
if (pmu->cpu_aliases_added)
|
||||
nr += pmu->loaded_json_aliases;
|
||||
nr += pmu->cpu_json_aliases;
|
||||
else if (pmu->events_table)
|
||||
nr += pmu_events_table__num_events(pmu->events_table, pmu) - pmu->loaded_json_aliases;
|
||||
nr += pmu_events_table__num_events(pmu->events_table, pmu) - pmu->cpu_json_aliases;
|
||||
else
|
||||
assert(pmu->cpu_json_aliases == 0);
|
||||
|
||||
return pmu->selectable ? nr + 1 : nr;
|
||||
}
|
||||
|
@ -123,8 +123,10 @@ struct perf_pmu {
|
||||
const struct pmu_events_table *events_table;
|
||||
/** @sysfs_aliases: Number of sysfs aliases loaded. */
|
||||
uint32_t sysfs_aliases;
|
||||
/** @sysfs_aliases: Number of json event aliases loaded. */
|
||||
uint32_t loaded_json_aliases;
|
||||
/** @cpu_json_aliases: Number of json event aliases loaded specific to the CPUID. */
|
||||
uint32_t cpu_json_aliases;
|
||||
/** @sys_json_aliases: Number of json event aliases loaded matching the PMU's identifier. */
|
||||
uint32_t sys_json_aliases;
|
||||
/** @sysfs_aliases_loaded: Are sysfs aliases loaded from disk? */
|
||||
bool sysfs_aliases_loaded;
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user