perf parse-events: Track all user changed config bits

Currently we only track which bits were set by the user in attr->config.
But all configN fields should be treated equally as they can all have
default and user overridden values.

Track them all by making get_config_chgs() generic and calling it once
for each config value.

Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: James Clark <james.clark@linaro.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: John Garry <john.g.garry@oracle.com>
Cc: Leo Yan <leo.yan@linux.dev>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Mike Leach <mike.leach@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Suzuki Poulouse <suzuki.poulose@arm.com>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
James Clark
2026-01-14 15:57:17 +00:00
committed by Arnaldo Carvalho de Melo
parent 5b5e01304f
commit a2441cf3a5
5 changed files with 70 additions and 51 deletions

View File

@@ -1243,7 +1243,11 @@ static void evsel__apply_config_terms(struct evsel *evsel,
case EVSEL__CONFIG_TERM_AUX_SAMPLE_SIZE:
/* Already applied by auxtrace */
break;
case EVSEL__CONFIG_TERM_CFG_CHG:
case EVSEL__CONFIG_TERM_USR_CHG_CONFIG:
case EVSEL__CONFIG_TERM_USR_CHG_CONFIG1:
case EVSEL__CONFIG_TERM_USR_CHG_CONFIG2:
case EVSEL__CONFIG_TERM_USR_CHG_CONFIG3:
case EVSEL__CONFIG_TERM_USR_CHG_CONFIG4:
break;
case EVSEL__CONFIG_TERM_RATIO_TO_PREV:
rtp_buf = term->val.str;
@@ -1327,7 +1331,8 @@ void evsel__set_config_if_unset(struct evsel *evsel, const char *config_name,
u64 val)
{
u64 user_bits = 0;
struct evsel_config_term *term = evsel__get_config_term(evsel, CFG_CHG);
struct evsel_config_term *term = evsel__get_config_term(evsel,
USR_CHG_CONFIG);
struct perf_pmu_format *format = pmu_find_format(&evsel->pmu->format,
config_name);
int fbit;

View File

@@ -27,7 +27,11 @@ enum evsel_term_type {
EVSEL__CONFIG_TERM_AUX_OUTPUT,
EVSEL__CONFIG_TERM_AUX_ACTION,
EVSEL__CONFIG_TERM_AUX_SAMPLE_SIZE,
EVSEL__CONFIG_TERM_CFG_CHG,
EVSEL__CONFIG_TERM_USR_CHG_CONFIG,
EVSEL__CONFIG_TERM_USR_CHG_CONFIG1,
EVSEL__CONFIG_TERM_USR_CHG_CONFIG2,
EVSEL__CONFIG_TERM_USR_CHG_CONFIG3,
EVSEL__CONFIG_TERM_USR_CHG_CONFIG4,
EVSEL__CONFIG_TERM_RATIO_TO_PREV,
};

View File

@@ -1253,66 +1253,32 @@ static int get_config_terms(const struct parse_events_terms *head_config,
return 0;
}
/*
* Add EVSEL__CONFIG_TERM_CFG_CHG where cfg_chg will have a bit set for
* each bit of attr->config that the user has changed.
*/
static int get_config_chgs(struct perf_pmu *pmu, struct parse_events_terms *head_config,
struct list_head *head_terms)
static int add_cfg_chg(const struct perf_pmu *pmu,
const struct parse_events_terms *head_config,
struct list_head *head_terms,
int format_type,
enum parse_events__term_type term_type,
enum evsel_term_type new_term_type)
{
struct parse_events_term *term;
u64 bits = 0;
int type;
list_for_each_entry(term, &head_config->terms, list) {
switch (term->type_term) {
case PARSE_EVENTS__TERM_TYPE_USER:
if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER) {
type = perf_pmu__format_type(pmu, term->config);
if (type != PERF_PMU_FORMAT_VALUE_CONFIG)
if (type != format_type)
continue;
bits |= perf_pmu__format_bits(pmu, term->config);
break;
case PARSE_EVENTS__TERM_TYPE_CONFIG:
} else if (term->type_term == term_type) {
bits = ~(u64)0;
break;
case PARSE_EVENTS__TERM_TYPE_CONFIG1:
case PARSE_EVENTS__TERM_TYPE_CONFIG2:
case PARSE_EVENTS__TERM_TYPE_CONFIG3:
case PARSE_EVENTS__TERM_TYPE_CONFIG4:
case PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG:
case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG:
case PARSE_EVENTS__TERM_TYPE_NAME:
case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ:
case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE:
case PARSE_EVENTS__TERM_TYPE_TIME:
case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
case PARSE_EVENTS__TERM_TYPE_INHERIT:
case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS:
case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:
case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
case PARSE_EVENTS__TERM_TYPE_DRV_CFG:
case PARSE_EVENTS__TERM_TYPE_PERCORE:
case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT:
case PARSE_EVENTS__TERM_TYPE_AUX_ACTION:
case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE:
case PARSE_EVENTS__TERM_TYPE_METRIC_ID:
case PARSE_EVENTS__TERM_TYPE_RAW:
case PARSE_EVENTS__TERM_TYPE_CPU:
case PARSE_EVENTS__TERM_TYPE_RATIO_TO_PREV:
default:
break;
}
}
if (bits) {
struct evsel_config_term *new_term;
new_term = add_config_term(EVSEL__CONFIG_TERM_CFG_CHG,
head_terms, false);
new_term = add_config_term(new_term_type, head_terms, false);
if (!new_term)
return -ENOMEM;
new_term->val.cfg_chg = bits;
@@ -1321,6 +1287,50 @@ static int get_config_chgs(struct perf_pmu *pmu, struct parse_events_terms *head
return 0;
}
/*
* Add EVSEL__CONFIG_TERM_USR_CFG_CONFIGn where cfg_chg will have a bit set for
* each bit of attr->configN that the user has changed.
*/
static int get_config_chgs(const struct perf_pmu *pmu,
const struct parse_events_terms *head_config,
struct list_head *head_terms)
{
int ret;
ret = add_cfg_chg(pmu, head_config, head_terms,
PERF_PMU_FORMAT_VALUE_CONFIG,
PARSE_EVENTS__TERM_TYPE_CONFIG,
EVSEL__CONFIG_TERM_USR_CHG_CONFIG);
if (ret)
return ret;
ret = add_cfg_chg(pmu, head_config, head_terms,
PERF_PMU_FORMAT_VALUE_CONFIG1,
PARSE_EVENTS__TERM_TYPE_CONFIG1,
EVSEL__CONFIG_TERM_USR_CHG_CONFIG1);
if (ret)
return ret;
ret = add_cfg_chg(pmu, head_config, head_terms,
PERF_PMU_FORMAT_VALUE_CONFIG2,
PARSE_EVENTS__TERM_TYPE_CONFIG2,
EVSEL__CONFIG_TERM_USR_CHG_CONFIG2);
if (ret)
return ret;
ret = add_cfg_chg(pmu, head_config, head_terms,
PERF_PMU_FORMAT_VALUE_CONFIG3,
PARSE_EVENTS__TERM_TYPE_CONFIG3,
EVSEL__CONFIG_TERM_USR_CHG_CONFIG3);
if (ret)
return ret;
return add_cfg_chg(pmu, head_config, head_terms,
PERF_PMU_FORMAT_VALUE_CONFIG4,
PARSE_EVENTS__TERM_TYPE_CONFIG4,
EVSEL__CONFIG_TERM_USR_CHG_CONFIG4);
}
int parse_events_add_tracepoint(struct parse_events_state *parse_state,
struct list_head *list,
const char *sys, const char *event,

View File

@@ -1349,7 +1349,7 @@ struct perf_pmu_format *pmu_find_format(const struct list_head *formats,
return NULL;
}
__u64 perf_pmu__format_bits(struct perf_pmu *pmu, const char *name)
__u64 perf_pmu__format_bits(const struct perf_pmu *pmu, const char *name)
{
struct perf_pmu_format *format = pmu_find_format(&pmu->format, name);
__u64 bits = 0;
@@ -1364,7 +1364,7 @@ __u64 perf_pmu__format_bits(struct perf_pmu *pmu, const char *name)
return bits;
}
int perf_pmu__format_type(struct perf_pmu *pmu, const char *name)
int perf_pmu__format_type(const struct perf_pmu *pmu, const char *name)
{
struct perf_pmu_format *format = pmu_find_format(&pmu->format, name);

View File

@@ -272,8 +272,8 @@ int perf_pmu__config_terms(const struct perf_pmu *pmu,
struct parse_events_terms *terms,
bool zero, bool apply_hardcoded,
struct parse_events_error *error);
__u64 perf_pmu__format_bits(struct perf_pmu *pmu, const char *name);
int perf_pmu__format_type(struct perf_pmu *pmu, const char *name);
__u64 perf_pmu__format_bits(const struct perf_pmu *pmu, const char *name);
int perf_pmu__format_type(const struct perf_pmu *pmu, const char *name);
int perf_pmu__check_alias(struct perf_pmu *pmu, struct parse_events_terms *head_terms,
struct perf_pmu_info *info, bool *rewrote_terms,
u64 *alternate_hw_config, struct parse_events_error *err);