summaryrefslogtreecommitdiff
path: root/tools/perf/util/pmu.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/pmu.c')
-rw-r--r--tools/perf/util/pmu.c319
1 files changed, 242 insertions, 77 deletions
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 3d1f975e8db9..956ea273c2c7 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -67,8 +67,13 @@ struct perf_pmu_alias {
* json events.
*/
char *topic;
- /** @terms: Owned list of the original parsed parameters. */
- struct parse_events_terms terms;
+ /** @terms: Owned copy of the event terms. */
+ char *terms;
+ /**
+ * @legacy_terms: If the event aliases a legacy event, holds a copy
+ * ofthe legacy event string.
+ */
+ char *legacy_terms;
/**
* @pmu_name: The name copied from the json struct pmu_event. This can
* differ from the PMU name as it won't have suffixes.
@@ -101,6 +106,12 @@ struct perf_pmu_alias {
* default.
*/
bool deprecated;
+ /**
+ * @legacy_deprecated_checked: Legacy events may not be supported by the
+ * PMU need to be checked. If they aren't supported they are marked
+ * deprecated.
+ */
+ bool legacy_deprecated_checked;
/** @from_sysfs: Was the alias from sysfs or a json event? */
bool from_sysfs;
/** @info_loaded: Have the scale, unit and other values been read from disk? */
@@ -429,7 +440,8 @@ static void perf_pmu_free_alias(struct perf_pmu_alias *alias)
zfree(&alias->long_desc);
zfree(&alias->topic);
zfree(&alias->pmu_name);
- parse_events_terms__exit(&alias->terms);
+ zfree(&alias->terms);
+ zfree(&alias->legacy_terms);
free(alias);
}
@@ -522,6 +534,7 @@ static void read_alias_info(struct perf_pmu *pmu, struct perf_pmu_alias *alias)
struct update_alias_data {
struct perf_pmu *pmu;
struct perf_pmu_alias *alias;
+ bool legacy;
};
static int update_alias(const struct pmu_event *pe,
@@ -537,8 +550,13 @@ static int update_alias(const struct pmu_event *pe,
assign_str(pe->name, "topic", &data->alias->topic, pe->topic);
data->alias->per_pkg = pe->perpkg;
if (pe->event) {
- parse_events_terms__exit(&data->alias->terms);
- ret = parse_events_terms(&data->alias->terms, pe->event, /*input=*/NULL);
+ if (data->legacy) {
+ zfree(&data->alias->legacy_terms);
+ data->alias->legacy_terms = strdup(pe->event);
+ } else {
+ zfree(&data->alias->terms);
+ data->alias->terms = strdup(pe->event);
+ }
}
if (!ret && pe->unit) {
char *unit;
@@ -563,7 +581,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 char *desc, const char *val, int val_fd,
const struct pmu_event *pe, enum event_source src)
{
struct perf_pmu_alias *alias, *old_alias;
@@ -590,7 +608,6 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name,
if (!alias)
return -ENOMEM;
- parse_events_terms__init(&alias->terms);
alias->scale = 1.0;
alias->unit[0] = '\0';
alias->per_pkg = perpkg;
@@ -615,13 +632,22 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name,
if (ret)
return ret;
- ret = parse_events_terms(&alias->terms, val, val_fd);
- if (ret) {
- pr_err("Cannot parse alias %s: %d\n", val, ret);
- free(alias);
- return ret;
- }
+ if (val_fd < 0) {
+ alias->terms = strdup(val);
+ } else {
+ char buf[256];
+ struct io io;
+ size_t line_len;
+ io__init(&io, val_fd, buf, sizeof(buf));
+ ret = io__getline(&io, &alias->terms, &line_len) < 0 ? -errno : 0;
+ if (ret) {
+ pr_err("Failed to read alias %s\n", name);
+ return ret;
+ }
+ if (line_len >= 1 && alias->terms[line_len - 1] == '\n')
+ alias->terms[line_len - 1] = '\0';
+ }
alias->name = strdup(name);
alias->desc = desc ? strdup(desc) : NULL;
alias->long_desc = long_desc ? strdup(long_desc) : NULL;
@@ -638,15 +664,29 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name,
default:
case EVENT_SRC_SYSFS:
alias->from_sysfs = true;
- if (pmu->events_table) {
+ if (pmu->events_table || pmu->is_core) {
/* Update an event from sysfs with json data. */
struct update_alias_data data = {
.pmu = pmu,
.alias = alias,
+ .legacy = false,
};
- if (pmu_events_table__find_event(pmu->events_table, pmu, name,
- update_alias, &data) == 0)
+ if ((pmu_events_table__find_event(pmu->events_table, pmu, name,
+ update_alias, &data) == 0)) {
+ /*
+ * Override sysfs encodings with json encodings
+ * specific to the cpuid.
+ */
pmu->cpu_common_json_aliases++;
+ }
+ if (pmu->is_core) {
+ /* Add in legacy encodings. */
+ data.legacy = true;
+ if (pmu_events_table__find_event(
+ perf_pmu__default_core_events_table(),
+ pmu, name, update_alias, &data) == 0)
+ pmu->cpu_common_json_aliases++;
+ }
}
pmu->sysfs_aliases++;
break;
@@ -694,7 +734,6 @@ static int __pmu_aliases_parse(struct perf_pmu *pmu, int events_dir_fd)
while ((evt_ent = io_dir__readdir(&event_dir))) {
char *name = evt_ent->d_name;
int fd;
- FILE *file;
if (!strcmp(name, ".") || !strcmp(name, ".."))
continue;
@@ -710,17 +749,12 @@ static int __pmu_aliases_parse(struct perf_pmu *pmu, int events_dir_fd)
pr_debug("Cannot open %s\n", name);
continue;
}
- file = fdopen(fd, "r");
- if (!file) {
- close(fd);
- continue;
- }
if (perf_pmu__new_alias(pmu, name, /*desc=*/ NULL,
- /*val=*/ NULL, file, /*pe=*/ NULL,
+ /*val=*/ NULL, fd, /*pe=*/ NULL,
EVENT_SRC_SYSFS) < 0)
pr_debug("Cannot set up %s\n", name);
- fclose(file);
+ close(fd);
}
pmu->sysfs_aliases_loaded = true;
@@ -767,29 +801,29 @@ static int pmu_aliases_parse_eager(struct perf_pmu *pmu, int sysfs_fd)
return ret;
}
-static int pmu_alias_terms(struct perf_pmu_alias *alias, int err_loc, struct list_head *terms)
+static int pmu_alias_terms(struct perf_pmu_alias *alias, struct list_head *terms)
{
- struct parse_events_term *term, *cloned;
- struct parse_events_terms clone_terms;
-
- parse_events_terms__init(&clone_terms);
- list_for_each_entry(term, &alias->terms.terms, list) {
- int ret = parse_events_term__clone(&cloned, term);
+ struct parse_events_terms alias_terms;
+ struct parse_events_term *term;
+ int ret;
- if (ret) {
- parse_events_terms__exit(&clone_terms);
- return ret;
- }
+ parse_events_terms__init(&alias_terms);
+ ret = parse_events_terms(&alias_terms, alias->terms);
+ if (ret) {
+ pr_err("Cannot parse '%s' terms '%s': %d\n",
+ alias->name, alias->terms, ret);
+ parse_events_terms__exit(&alias_terms);
+ return ret;
+ }
+ list_for_each_entry(term, &alias_terms.terms, list) {
/*
* Weak terms don't override command line options,
* which we don't want for implicit terms in aliases.
*/
- cloned->weak = true;
- cloned->err_term = cloned->err_val = err_loc;
- list_add_tail(&cloned->list, &clone_terms.terms);
+ term->weak = true;
}
- list_splice_init(&clone_terms.terms, terms);
- parse_events_terms__exit(&clone_terms);
+ list_splice_init(&alias_terms.terms, terms);
+ parse_events_terms__exit(&alias_terms);
return 0;
}
@@ -1045,7 +1079,7 @@ 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,
+ perf_pmu__new_alias(pmu, pe->name, pe->desc, pe->event, /*val_fd=*/ -1,
pe, EVENT_SRC_CPU_JSON);
return 0;
}
@@ -1061,13 +1095,16 @@ void pmu_add_cpu_aliases_table(struct perf_pmu *pmu, const struct pmu_events_tab
static void pmu_add_cpu_aliases(struct perf_pmu *pmu)
{
- if (!pmu->events_table)
+ if (!pmu->events_table && !pmu->is_core)
return;
if (pmu->cpu_aliases_added)
return;
pmu_add_cpu_aliases_table(pmu, pmu->events_table);
+ if (pmu->is_core)
+ pmu_add_cpu_aliases_table(pmu, perf_pmu__default_core_events_table());
+
pmu->cpu_aliases_added = true;
}
@@ -1094,7 +1131,7 @@ static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe,
pe->name,
pe->desc,
pe->event,
- /*val_fd=*/ NULL,
+ /*val_fd=*/ -1,
pe,
EVENT_SRC_SYS_JSON);
}
@@ -1539,6 +1576,38 @@ static int pmu_config_term(const struct perf_pmu *pmu,
assert(term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
pmu_format_value(bits, term->val.num, &attr->config3, zero);
break;
+ case PARSE_EVENTS__TERM_TYPE_CONFIG4:
+ assert(term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
+ pmu_format_value(bits, term->val.num, &attr->config4, zero);
+ break;
+ case PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG:
+ assert(term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
+ assert(term->val.num < PERF_COUNT_HW_MAX);
+ assert(pmu->is_core);
+ attr->config = term->val.num;
+ if (perf_pmus__supports_extended_type())
+ attr->config |= (__u64)pmu->type << PERF_PMU_TYPE_SHIFT;
+ attr->type = PERF_TYPE_HARDWARE;
+ break;
+ case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG: {
+#ifndef NDEBUG
+ int cache_type = term->val.num & 0xFF;
+ int cache_op = (term->val.num >> 8) & 0xFF;
+ int cache_result = (term->val.num >> 16) & 0xFF;
+
+ assert(cache_type < PERF_COUNT_HW_CACHE_MAX);
+ assert(cache_op < PERF_COUNT_HW_CACHE_OP_MAX);
+ assert(cache_result < PERF_COUNT_HW_CACHE_RESULT_MAX);
+#endif
+ assert(term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
+ assert((term->val.num & ~0xFFFFFF) == 0);
+ assert(pmu->is_core);
+ attr->config = term->val.num;
+ if (perf_pmus__supports_extended_type())
+ attr->config |= (__u64)pmu->type << PERF_PMU_TYPE_SHIFT;
+ attr->type = PERF_TYPE_HW_CACHE;
+ break;
+ }
case PARSE_EVENTS__TERM_TYPE_USER: /* Not hardcoded. */
return -EINVAL;
case PARSE_EVENTS__TERM_TYPE_NAME ... PARSE_EVENTS__TERM_TYPE_RATIO_TO_PREV:
@@ -1586,6 +1655,9 @@ static int pmu_config_term(const struct perf_pmu *pmu,
case PERF_PMU_FORMAT_VALUE_CONFIG3:
vp = &attr->config3;
break;
+ case PERF_PMU_FORMAT_VALUE_CONFIG4:
+ vp = &attr->config4;
+ break;
default:
return -EINVAL;
}
@@ -1717,10 +1789,14 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
return alias;
/* Alias doesn't exist, try to get it from the json events. */
- if (pmu->events_table &&
- pmu_events_table__find_event(pmu->events_table, pmu, name,
- pmu_add_cpu_aliases_map_callback,
- pmu) == 0) {
+ if ((pmu_events_table__find_event(pmu->events_table, pmu, name,
+ pmu_add_cpu_aliases_map_callback,
+ pmu) == 0) ||
+ (pmu->is_core &&
+ pmu_events_table__find_event(perf_pmu__default_core_events_table(),
+ pmu, name,
+ pmu_add_cpu_aliases_map_callback,
+ pmu) == 0)) {
alias = perf_pmu__find_alias(pmu, name, /*load=*/ false);
}
return alias;
@@ -1770,6 +1846,24 @@ static int check_info_data(struct perf_pmu *pmu,
return 0;
}
+static int perf_pmu__parse_terms_to_attr(struct perf_pmu *pmu, const char *terms_str,
+ struct perf_event_attr *attr)
+{
+ struct parse_events_terms terms;
+ int ret;
+
+ parse_events_terms__init(&terms);
+ ret = parse_events_terms(&terms, terms_str);
+ if (ret) {
+ pr_debug("Failed to parse terms '%s': %d\n", terms_str, ret);
+ parse_events_terms__exit(&terms);
+ return ret;
+ }
+ ret = perf_pmu__config(pmu, attr, &terms, /*apply_hardcoded=*/true, /*err=*/NULL);
+ parse_events_terms__exit(&terms);
+ return ret;
+}
+
/*
* Find alias in the terms list and replace it with the terms
* defined for the alias
@@ -1813,10 +1907,10 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct parse_events_terms *head_
alias = pmu_find_alias(pmu, term);
if (!alias)
continue;
- ret = pmu_alias_terms(alias, term->err_term, &term->list);
+ ret = pmu_alias_terms(alias, &term->list);
if (ret) {
parse_events_error__handle(err, term->err_term,
- strdup("Failure to duplicate terms"),
+ strdup("Failed to parse terms"),
NULL);
return ret;
}
@@ -1826,12 +1920,23 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct parse_events_terms *head_
if (ret)
return ret;
+ if (alias->legacy_terms) {
+ struct perf_event_attr attr = {.config = 0,};
+
+ ret = perf_pmu__parse_terms_to_attr(pmu, alias->legacy_terms, &attr);
+ if (ret) {
+ parse_events_error__handle(err, term->err_term,
+ strdup("Error evaluating legacy terms"),
+ NULL);
+ return ret;
+ }
+ if (attr.type == PERF_TYPE_HARDWARE)
+ *alternate_hw_config = attr.config & PERF_HW_EVENT_MASK;
+ }
+
if (alias->per_pkg)
info->per_pkg = true;
- if (term->alternate_hw_config)
- *alternate_hw_config = term->val.num;
-
info->retirement_latency_mean = alias->retirement_latency_mean;
info->retirement_latency_min = alias->retirement_latency_min;
info->retirement_latency_max = alias->retirement_latency_max;
@@ -1912,6 +2017,9 @@ int perf_pmu__for_each_format(struct perf_pmu *pmu, void *state, pmu_format_call
"config1=0..0xffffffffffffffff",
"config2=0..0xffffffffffffffff",
"config3=0..0xffffffffffffffff",
+ "config4=0..0xffffffffffffffff",
+ "legacy-hardware-config=0..9,",
+ "legacy-cache-config=0..0xffffff,",
"name=string",
"period=number",
"freq=number",
@@ -1937,10 +2045,10 @@ int perf_pmu__for_each_format(struct perf_pmu *pmu, void *state, pmu_format_call
/*
* max-events and driver-config are missing above as are the internal
- * types user, metric-id, raw, legacy cache and hardware. Assert against
- * the enum parse_events__term_type so they are kept in sync.
+ * types user, metric-id, and raw. Assert against the enum
+ * parse_events__term_type so they are kept in sync.
*/
- _Static_assert(ARRAY_SIZE(terms) == __PARSE_EVENTS__TERM_TYPE_NR - 6,
+ _Static_assert(ARRAY_SIZE(terms) == __PARSE_EVENTS__TERM_TYPE_NR - 4,
"perf_pmu__for_each_format()'s terms must be kept in sync with enum parse_events__term_type");
list_for_each_entry(format, &pmu->format, list) {
perf_pmu_format__load(pmu, format);
@@ -1993,9 +2101,13 @@ bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name)
return drm_pmu__have_event(pmu, name);
if (perf_pmu__find_alias(pmu, name, /*load=*/ true) != NULL)
return true;
- if (pmu->cpu_aliases_added || !pmu->events_table)
+ if (pmu->cpu_aliases_added || (!pmu->events_table && !pmu->is_core))
return false;
- return pmu_events_table__find_event(pmu->events_table, pmu, name, NULL, NULL) == 0;
+ if (pmu_events_table__find_event(pmu->events_table, pmu, name, NULL, NULL) == 0)
+ return true;
+ return pmu->is_core &&
+ pmu_events_table__find_event(perf_pmu__default_core_events_table(),
+ pmu, name, NULL, NULL) == 0;
}
size_t perf_pmu__num_events(struct perf_pmu *pmu)
@@ -2012,13 +2124,18 @@ size_t perf_pmu__num_events(struct perf_pmu *pmu)
pmu_aliases_parse(pmu);
nr = pmu->sysfs_aliases + pmu->sys_json_aliases;
- if (pmu->cpu_aliases_added)
- nr += pmu->cpu_json_aliases;
- else if (pmu->events_table)
- nr += pmu_events_table__num_events(pmu->events_table, pmu) -
- pmu->cpu_common_json_aliases;
- else
+ if (pmu->cpu_aliases_added) {
+ nr += pmu->cpu_json_aliases;
+ } else if (pmu->events_table || pmu->is_core) {
+ nr += pmu_events_table__num_events(pmu->events_table, pmu);
+ if (pmu->is_core) {
+ nr += pmu_events_table__num_events(
+ perf_pmu__default_core_events_table(), pmu);
+ }
+ nr -= pmu->cpu_common_json_aliases;
+ } else {
assert(pmu->cpu_json_aliases == 0 && pmu->cpu_common_json_aliases == 0);
+ }
if (perf_pmu__is_tool(pmu))
nr -= tool_pmu__num_skip_events();
@@ -2036,18 +2153,37 @@ static int sub_non_neg(int a, int b)
static char *format_alias(char *buf, int len, const struct perf_pmu *pmu,
const struct perf_pmu_alias *alias, bool skip_duplicate_pmus)
{
+ struct parse_events_terms terms;
struct parse_events_term *term;
+ int ret, used;
size_t pmu_name_len = pmu_deduped_name_len(pmu, pmu->name,
skip_duplicate_pmus);
- int used = snprintf(buf, len, "%.*s/%s", (int)pmu_name_len, pmu->name, alias->name);
- list_for_each_entry(term, &alias->terms.terms, list) {
+ /* Paramemterized events have the parameters shown. */
+ if (strstr(alias->terms, "=?")) {
+ /* No parameters. */
+ snprintf(buf, len, "%.*s/%s/", (int)pmu_name_len, pmu->name, alias->name);
+ return buf;
+ }
+
+ parse_events_terms__init(&terms);
+ ret = parse_events_terms(&terms, alias->terms);
+ if (ret) {
+ pr_err("Failure to parse '%s' terms '%s': %d\n",
+ alias->name, alias->terms, ret);
+ parse_events_terms__exit(&terms);
+ snprintf(buf, len, "%.*s/%s/", (int)pmu_name_len, pmu->name, alias->name);
+ return buf;
+ }
+ used = snprintf(buf, len, "%.*s/%s", (int)pmu_name_len, pmu->name, alias->name);
+
+ list_for_each_entry(term, &terms.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);
}
-
+ parse_events_terms__exit(&terms);
if (sub_non_neg(len, used) > 0) {
buf[used] = '/';
used++;
@@ -2061,6 +2197,42 @@ static char *format_alias(char *buf, int len, const struct perf_pmu *pmu,
return buf;
}
+static bool perf_pmu_alias__check_deprecated(struct perf_pmu *pmu, struct perf_pmu_alias *alias)
+{
+ struct perf_event_attr attr = {.config = 0,};
+ const char *check_terms;
+ bool has_legacy_config;
+
+ if (alias->legacy_deprecated_checked)
+ return alias->deprecated;
+
+ alias->legacy_deprecated_checked = true;
+ if (alias->deprecated)
+ return true;
+
+ check_terms = alias->terms;
+ has_legacy_config =
+ strstr(check_terms, "legacy-hardware-config=") != NULL ||
+ strstr(check_terms, "legacy-cache-config=") != NULL;
+ if (!has_legacy_config && alias->legacy_terms) {
+ check_terms = alias->legacy_terms;
+ has_legacy_config =
+ strstr(check_terms, "legacy-hardware-config=") != NULL ||
+ strstr(check_terms, "legacy-cache-config=") != NULL;
+ }
+ if (!has_legacy_config)
+ return false;
+
+ if (perf_pmu__parse_terms_to_attr(pmu, check_terms, &attr) != 0) {
+ /* Parsing failed, set as deprecated. */
+ alias->deprecated = true;
+ } else if (attr.type < PERF_TYPE_MAX) {
+ /* Flag unsupported legacy events as deprecated. */
+ alias->deprecated = !is_event_supported(attr.type, attr.config);
+ }
+ return alias->deprecated;
+}
+
int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus,
void *state, pmu_event_callback cb)
{
@@ -2070,7 +2242,6 @@ int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus,
.event_type_desc = "Kernel PMU event",
};
int ret = 0;
- struct strbuf sb;
struct hashmap_entry *entry;
size_t bkt;
@@ -2081,7 +2252,6 @@ int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus,
if (perf_pmu__is_drm(pmu))
return drm_pmu__for_each_event(pmu, state, cb);
- strbuf_init(&sb, /*hint=*/ 0);
pmu_aliases_parse(pmu);
pmu_add_cpu_aliases(pmu);
hashmap__for_each_entry(pmu->aliases, entry, bkt) {
@@ -2116,16 +2286,14 @@ int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus,
info.desc = event->desc;
info.long_desc = event->long_desc;
info.encoding_desc = buf + buf_used;
- parse_events_terms__to_strbuf(&event->terms, &sb);
buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used,
- "%.*s/%s/", (int)pmu_name_len, info.pmu_name, sb.buf) + 1;
+ "%.*s/%s/", (int)pmu_name_len, info.pmu_name, event->terms) + 1;
+ info.str = event->terms;
info.topic = event->topic;
- info.str = sb.buf;
- info.deprecated = event->deprecated;
+ info.deprecated = perf_pmu_alias__check_deprecated(pmu, event);
ret = cb(state, &info);
if (ret)
goto out;
- strbuf_setlen(&sb, /*len=*/ 0);
}
if (pmu->selectable) {
info.name = buf;
@@ -2141,7 +2309,6 @@ int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus,
ret = cb(state, &info);
}
out:
- strbuf_release(&sb);
return ret;
}
@@ -2589,9 +2756,7 @@ const char *perf_pmu__name_from_config(struct perf_pmu *pmu, u64 config)
hashmap__for_each_entry(pmu->aliases, entry, bkt) {
struct perf_pmu_alias *event = entry->pvalue;
struct perf_event_attr attr = {.config = 0,};
-
- int ret = perf_pmu__config(pmu, &attr, &event->terms, /*apply_hardcoded=*/true,
- /*err=*/NULL);
+ int ret = perf_pmu__parse_terms_to_attr(pmu, event->terms, &attr);
if (ret == 0 && config == attr.config)
return event->name;