From: zhangqz 14294317+zwx1160575@user.noreply.gitee.com
1、Event aliasing for events whose name in the form foo-bar-baz is not supported, while foo-bar, foo_bar_baz, and other combinations are, i.e. two hyphens are not supported. 2、Add a test for aliases with hyphens in the name to ensure that the pmu-events tables are as expects. There should be no reason why these sort of aliases would be treated differently, but no harm in checking. 3、Add a test which allows us to test parsing an event alias with hyphens.
Since these events typically do not exist on most host systems, add the alias to the fake pmu.
Function perf_pmu__test_parse_init() has terms added to match known test aliases.
John Garry (3): perf parse-events: Support event alias in form foo-bar-baz perf test: Add pmu-events test for aliases with hyphens perf test: Add parse-events test for aliases with hyphens
Yushan Wang (1): perf parse-event bugfix merge
.../arch/test/test_soc/cpu/uncore.json | 16 ++ tools/perf/tests/parse-events.c | 49 ++++++ tools/perf/tests/pmu-events.c | 32 ++++ tools/perf/util/parse-events.c | 159 +++++++++++++----- tools/perf/util/parse-events.h | 7 +- tools/perf/util/parse-events.l | 2 + tools/perf/util/parse-events.y | 34 +++- 7 files changed, 253 insertions(+), 46 deletions(-)
From: John Garry john.garry@huawei.com
driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IAMH2B CVE: NA
----------------------------------------------------------------------
Upstream: Yes AR20220107954521 Bugfix or Feature: Bugfix DTS2024072721521
Event aliasing for events whose name in the form foo-bar-baz is not supported, while foo-bar, foo_bar_baz, and other combinations are, i.e. two hyphens are not supported.
The HiSilicon D06 platform has events in such form:
$ ./perf list sdir-home-migrate
List of pre-defined events (to be used in -e):
uncore hha: sdir-home-migrate [Unit: hisi_sccl,hha]
$ sudo ./perf stat -e sdir-home-migrate event syntax error: 'sdir-home-migrate' ___ parser error Run 'perf list' for a list of valid events
Usage: perf stat [<options>] [<command>]
-e, --event <event>event selector. use 'perf list' to list available events
To support, add an extra PMU event symbol type for "baz", and add a new rule in the bison file.
Signed-off-by: John Garry john.garry@huawei.com Signed-off-by: zhangqz 14294317+zwx1160575@user.noreply.gitee.com --- tools/perf/util/parse-events.c | 25 +++++++++++++++++++++++-- tools/perf/util/parse-events.h | 1 + tools/perf/util/parse-events.l | 2 ++ tools/perf/util/parse-events.y | 17 +++++++++++++++-- 4 files changed, 41 insertions(+), 4 deletions(-)
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 722aaf7a40c8..7146e29deed0 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -2004,8 +2004,17 @@ static void perf_pmu__parse_init(void) pmu = NULL; while ((pmu = perf_pmu__scan(pmu)) != NULL) { list_for_each_entry(alias, &pmu->aliases, list) { - if (strchr(alias->name, '-')) + char *tmp = strchr(alias->name, '-'); + + if (tmp) { + char *tmp2 = NULL; + + tmp2 = strchr(tmp + 1, '-'); len++; + if (tmp2) + len++; + } + len++; } } @@ -2025,8 +2034,20 @@ static void perf_pmu__parse_init(void) list_for_each_entry(alias, &pmu->aliases, list) { struct perf_pmu_event_symbol *p = perf_pmu_events_list + len; char *tmp = strchr(alias->name, '-'); + char *tmp2 = NULL;
- if (tmp != NULL) { + if (tmp) + tmp2 = strchr(tmp + 1, '-'); + if (tmp2) { + SET_SYMBOL(strndup(alias->name, tmp - alias->name), + PMU_EVENT_SYMBOL_PREFIX); + p++; + tmp++; + SET_SYMBOL(strndup(tmp, tmp2 - tmp), PMU_EVENT_SYMBOL_SUFFIX); + p++; + SET_SYMBOL(strdup(++tmp2), PMU_EVENT_SYMBOL_SUFFIX2); + len += 3; + } else if (tmp) { SET_SYMBOL(strndup(alias->name, tmp - alias->name), PMU_EVENT_SYMBOL_PREFIX); p++; diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index e80c9b74f2f2..a0c6f95b5683 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -53,6 +53,7 @@ enum perf_pmu_event_symbol_type { PMU_EVENT_SYMBOL, /* normal style PMU event */ PMU_EVENT_SYMBOL_PREFIX, /* prefix of pre-suf style event */ PMU_EVENT_SYMBOL_SUFFIX, /* suffix of pre-suf style event */ + PMU_EVENT_SYMBOL_SUFFIX2, /* suffix of pre-suf2 style event */ };
struct perf_pmu_event_symbol { diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 9db5097317f4..45b1aaf32e25 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l @@ -147,6 +147,8 @@ static int pmu_str_check(yyscan_t scanner, struct parse_events_state *parse_stat return PE_PMU_EVENT_PRE; case PMU_EVENT_SYMBOL_SUFFIX: return PE_PMU_EVENT_SUF; + case PMU_EVENT_SYMBOL_SUFFIX2: + return PE_PMU_EVENT_SUF2; case PMU_EVENT_SYMBOL: return PE_KERNEL_PMU_EVENT; default: diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index 3adbd2049c88..b6dd7f8b5a6c 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -69,7 +69,7 @@ static void inc_group_count(struct list_head *list, %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP %token PE_ERROR -%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE +%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_PMU_EVENT_SUF2 PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE %token PE_ARRAY_ALL PE_ARRAY_RANGE %token PE_DRV_CFG_TERM %type <num> PE_VALUE @@ -87,7 +87,7 @@ static void inc_group_count(struct list_head *list, %type <str> PE_MODIFIER_EVENT %type <str> PE_MODIFIER_BP %type <str> PE_EVENT_NAME -%type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE +%type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_PMU_EVENT_SUF2 PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE %type <str> PE_DRV_CFG_TERM %destructor { free ($$); } <str> %type <term> event_term @@ -344,6 +344,19 @@ PE_KERNEL_PMU_EVENT sep_dc $$ = list; } | +PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF '-' PE_PMU_EVENT_SUF2 sep_dc +{ + struct list_head *list; + char pmu_name[128]; + snprintf(pmu_name, sizeof(pmu_name), "%s-%s-%s", $1, $3, $5); + free($1); + free($3); + free($5); + if (parse_events_multi_pmu_add(_parse_state, pmu_name, NULL, &list) < 0) + YYABORT; + $$ = list; +} +| PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc { struct list_head *list;
From: John Garry john.garry@huawei.com
driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IAMH2B CVE: NA
----------------------------------------------------------------------
Upstream: Yes AR20220107954521 Bugfix or Feature: Bugfix DTS2024072721521
Add a test for aliases with hyphens in the name to ensure that the pmu-events tables are as expects. There should be no reason why these sort of aliases would be treated differently, but no harm in checking.
Signed-off-by: John Garry john.garry@huawei.com Signed-off-by: zhangqz 14294317+zwx1160575@user.noreply.gitee.com --- .../arch/test/test_soc/cpu/uncore.json | 16 ++++++++++ tools/perf/tests/pmu-events.c | 32 +++++++++++++++++++ 2 files changed, 48 insertions(+)
diff --git a/tools/perf/pmu-events/arch/test/test_soc/cpu/uncore.json b/tools/perf/pmu-events/arch/test/test_soc/cpu/uncore.json index 73089c682f80..41bac1c6a008 100644 --- a/tools/perf/pmu-events/arch/test/test_soc/cpu/uncore.json +++ b/tools/perf/pmu-events/arch/test/test_soc/cpu/uncore.json @@ -18,6 +18,22 @@ "Invert": "0", "EdgeDetect": "0" }, + { + "Unit": "CBO", + "EventCode": "0xE0", + "UMask": "0x00", + "EventName": "event-hyphen", + "BriefDescription": "UNC_CBO_HYPHEN", + "PublicDescription": "UNC_CBO_HYPHEN" + }, + { + "Unit": "CBO", + "EventCode": "0xC0", + "UMask": "0x00", + "EventName": "event-two-hyph", + "BriefDescription": "UNC_CBO_TWO_HYPH", + "PublicDescription": "UNC_CBO_TWO_HYPH" + }, { "EventCode": "0x7", "EventName": "uncore_hisi_l3c.rd_hit_cpipe", diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index a2b5879201ad..9d3c26a01a02 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -141,6 +141,34 @@ static const struct perf_pmu_test_event unc_cbo_xsnp_response_miss_eviction = { .matching_pmu = "uncore_cbox_0", };
+static const struct perf_pmu_test_event uncore_hyphen = { + .event = { + .name = "event-hyphen", + .event = "umask=0x00,event=0xe0", + .desc = "Unit: uncore_cbox UNC_CBO_HYPHEN", + .topic = "uncore", + .long_desc = "UNC_CBO_HYPHEN", + .pmu = "uncore_cbox", + }, + .alias_str = "umask=0,event=0xe0", + .alias_long_desc = "UNC_CBO_HYPHEN", + .matching_pmu = "uncore_cbox_0", +}; + +static const struct perf_pmu_test_event uncore_two_hyph = { + .event = { + .name = "event-two-hyph", + .event = "umask=0x00,event=0xc0", + .desc = "Unit: uncore_cbox UNC_CBO_TWO_HYPH", + .topic = "uncore", + .long_desc = "UNC_CBO_TWO_HYPH", + .pmu = "uncore_cbox", + }, + .alias_str = "umask=0,event=0xc0", + .alias_long_desc = "UNC_CBO_TWO_HYPH", + .matching_pmu = "uncore_cbox_0", +}; + static const struct perf_pmu_test_event uncore_hisi_l3c_rd_hit_cpipe = { .event = { .name = "uncore_hisi_l3c.rd_hit_cpipe", @@ -186,6 +214,8 @@ static const struct perf_pmu_test_event uncore_imc_cache_hits = { static const struct perf_pmu_test_event *uncore_events[] = { &uncore_hisi_ddrc_flux_wcmd, &unc_cbo_xsnp_response_miss_eviction, + &uncore_hyphen, + &uncore_two_hyph, &uncore_hisi_l3c_rd_hit_cpipe, &uncore_imc_free_running_cache_miss, &uncore_imc_cache_hits, @@ -652,6 +682,8 @@ static struct perf_pmu_test_pmu test_pmus[] = { }, .aliases = { &unc_cbo_xsnp_response_miss_eviction, + &uncore_hyphen, + &uncore_two_hyph, }, }, {
From: John Garry john.garry@huawei.com
driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IAMH2B CVE: NA
----------------------------------------------------------------------
Upstream: Yes AR20220107954521 Bugfix or Feature: Bugfix DTS2024072721521
Add a test which allows us to test parsing an event alias with hyphens.
Since these events typically do not exist on most host systems, add the alias to the fake pmu.
Function perf_pmu__test_parse_init() has terms added to match known test aliases.
Signed-off-by: John Garry john.garry@huawei.com Signed-off-by: zhangqz 14294317+zwx1160575@user.noreply.gitee.com --- tools/perf/tests/parse-events.c | 49 +++++++++++++++++++++++++++++++++ tools/perf/util/parse-events.c | 42 ++++++++++++++++++++++------ 2 files changed, 82 insertions(+), 9 deletions(-)
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index 39af9b744f49..9ae39cd857c8 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -1900,6 +1900,31 @@ static int test_event(struct evlist_test *e) return ret; }
+static int test_event_fake_pmu(const char *str) +{ + struct parse_events_error err; + struct evlist *evlist; + int ret; + + evlist = evlist__new(); + if (!evlist) + return -ENOMEM; + + parse_events_error__init(&err); + perf_pmu__test_parse_init(); + ret = __parse_events(evlist, str, &err, &perf_pmu__fake); + if (ret) { + pr_debug("failed to parse event '%s', err %d, str '%s'\n", + str, ret, err.str); + parse_events_error__print(&err, str); + } + + parse_events_error__exit(&err); + evlist__delete(evlist); + + return ret; +} + static int test_events(struct evlist_test *events, unsigned cnt) { int ret1, ret2 = 0; @@ -2025,6 +2050,26 @@ static int test_pmu_events(void) closedir(dir); return ret; } + +static int test_pmu_events_alias2(void) +{ + static const char events[][30] = { + "event-hyphen", + "event-two-hyph", + }; + unsigned long i; + int ret = 0; + + for (i = 0; i < ARRAY_SIZE(events); i++) { + ret = test_event_fake_pmu(&events[i][0]); + if (ret) { + pr_err("check_parse_fake %s failed\n", &events[i][0]); + break; + } + } + + return ret; +}
int test__parse_events(struct test *test __maybe_unused, int subtest __maybe_unused) { @@ -2048,6 +2093,10 @@ do { \ return ret; }
+ ret1 = test_pmu_events_alias2(); + if (!ret2) + ret2 = ret1; + ret1 = test_terms(test__terms, ARRAY_SIZE(test__terms)); if (!ret2) ret2 = ret1; diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 7146e29deed0..4005887dfda8 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -1617,6 +1617,15 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state, } } } + + if (parse_state->fake_pmu) { + if (!parse_events_add_pmu(parse_state, list, str, head, + true, true)) { + pr_debug("%s -> %s/%s/\n", str, "fake_pmu", str); + ok++; + } + } + if (!ok) { free(list); return -1; @@ -2074,23 +2083,38 @@ static void perf_pmu__parse_init(void) */ int perf_pmu__test_parse_init(void) { - struct perf_pmu_event_symbol *list; + struct perf_pmu_event_symbol *list, *tmp, symbols[] = { + {(char *)"read", PMU_EVENT_SYMBOL}, + {(char *)"event", PMU_EVENT_SYMBOL_PREFIX}, + {(char *)"two", PMU_EVENT_SYMBOL_SUFFIX}, + {(char *)"hyphen", PMU_EVENT_SYMBOL_SUFFIX}, + {(char *)"hyph", PMU_EVENT_SYMBOL_SUFFIX2}, + }; + unsigned long i, j;
- list = malloc(sizeof(*list) * 1); + tmp = list = malloc(sizeof(*list) * ARRAY_SIZE(symbols)); if (!list) return -ENOMEM;
- list->type = PMU_EVENT_SYMBOL; - list->symbol = strdup("read"); - - if (!list->symbol) { - free(list); - return -ENOMEM; + for (i = 0; i < ARRAY_SIZE(symbols); i++, tmp++) { + tmp->type = symbols[i].type; + tmp->symbol = strdup(symbols[i].symbol); + if (!list->symbol) + goto err_free; }
perf_pmu_events_list = list; - perf_pmu_events_list_num = 1; + perf_pmu_events_list_num = ARRAY_SIZE(symbols); + + qsort(perf_pmu_events_list, ARRAY_SIZE(symbols), + sizeof(struct perf_pmu_event_symbol), comp_pmu); return 0; + +err_free: + for (j = 0, tmp = list; j < i; j++, tmp++) + free(tmp->symbol); + free(list); + return -ENOMEM; }
enum perf_pmu_event_symbol_type
driver inclusion category: driver bugzilla: https://gitee.com/openeuler/kernel/issues/IAMH2B CVE: NA
----------------------------------------------------------------------
Upstream: Yes AR20220107954521 Bugfix or Feature: Bugfix DTS2024072721521
Mainstream version before @9bce13ea88f8 may have issue parsing perf events aliased with dashes (e.g. 'foo-bar-baz').
Fix patches of community has been merged to mainstream but not openeuler. This commit fixes some conflicts produced during applying above patches to openeuler.
The original commit is @fb0811535e92c, commit message is as follows.
perf parse-events: Allow config on kernel PMU events
An event like inst_retired.any on an Intel skylake is found in the pmu-events code created from the pipeline event JSON.
The event is an alias for cpu/event=0xc0,period=2000003/ and parse-events recognizes the event with the token PE_KERNEL_PMU_EVENT.
The parser doesn't currently allow extra configuration on such events, except for modifiers, so:
$ perf stat -e inst_retired.any// /bin/true event syntax error: 'inst_retired.any//' ___ parser error Run 'perf list' for a list of valid events
Usage: perf stat [<options>] [<command>]
-e, --event <event> event selector. use 'perf list' to list available events
This patch adds configuration to these events which can be useful for a number of parameters like name and call-graph:
$ sudo perf record -e inst_retired.any/call-graph=lbr/ -a sleep 1 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 1.856 MB perf.data (44 samples) ]
It is necessary for the metric code so that we may add metric-id values to these events before they are parsed.
Signed-off-by: Yushan Wang wangyushan12@huawei.com Signed-off-by: zhangqz 14294317+zwx1160575@user.noreply.gitee.com --- tools/perf/tests/parse-events.c | 2 +- tools/perf/util/parse-events.c | 92 ++++++++++++++++++++++----------- tools/perf/util/parse-events.h | 6 ++- tools/perf/util/parse-events.y | 17 +++++- 4 files changed, 83 insertions(+), 34 deletions(-)
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index 9ae39cd857c8..4ad0343f2ce9 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -2050,7 +2050,7 @@ static int test_pmu_events(void) closedir(dir); return ret; } - + static int test_pmu_events_alias2(void) { static const char events[][30] = { diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 4005887dfda8..4f988f768697 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -1567,44 +1567,48 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, }
int parse_events_multi_pmu_add(struct parse_events_state *parse_state, - char *str, struct list_head **listp) + char *str, struct list_head *head, + struct list_head **listp) { struct parse_events_term *term; - struct list_head *list; + struct list_head *list = NULL; struct perf_pmu *pmu = NULL; int ok = 0; + char *config;
*listp = NULL; + + if (!head) { + head = malloc(sizeof(struct list_head)); + if (!head) + goto out_err; + + INIT_LIST_HEAD(head); + } + config = strdup(str); + if (!config) + goto out_err; + + if (parse_events_term__num(&term, + PARSE_EVENTS__TERM_TYPE_USER, + config, 1, false, &config, + NULL) < 0) { + free(config); + goto out_err; + } + list_add_tail(&term->list, head); + /* Add it for all PMUs that support the alias */ list = malloc(sizeof(struct list_head)); if (!list) - return -1; + goto out_err; + INIT_LIST_HEAD(list); while ((pmu = perf_pmu__scan(pmu)) != NULL) { struct perf_pmu_alias *alias;
list_for_each_entry(alias, &pmu->aliases, list) { if (!strcasecmp(alias->name, str)) { - struct list_head *head; - char *config; - - head = malloc(sizeof(struct list_head)); - if (!head) - return -1; - INIT_LIST_HEAD(head); - config = strdup(str); - if (!config) - return -1; - if (parse_events_term__num(&term, - PARSE_EVENTS__TERM_TYPE_USER, - config, 1, false, &config, - NULL) < 0) { - free(list); - free(config); - return -1; - } - list_add_tail(&term->list, head); - if (!parse_events_add_pmu(parse_state, list, pmu->name, head, true, true)) { @@ -1612,8 +1616,6 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state, pmu->name, alias->str); ok++; } - - parse_events_terms__delete(head); } } } @@ -1626,12 +1628,14 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state, } }
- if (!ok) { +out_err: + if (ok) + *listp = list; + else free(list); - return -1; - } - *listp = list; - return 0; + + parse_events_terms__delete(head); + return ok ? 0 : -1; }
int parse_events__modifier_group(struct list_head *list, @@ -2234,6 +2238,19 @@ int __parse_events(struct evlist *evlist, const char *str, return ret; }
+void parse_events_error__init(struct parse_events_error *err) +{ + bzero(err, sizeof(*err)); +} + +void parse_events_error__exit(struct parse_events_error *err) +{ + zfree(&err->str); + zfree(&err->help); + zfree(&err->first_str); + zfree(&err->first_help); +} + #define MAX_WIDTH 1000 static int get_term_width(void) { @@ -2298,6 +2315,21 @@ static void __parse_events_print_error(int err_idx, const char *err_str, } }
+void parse_events_error__print(struct parse_events_error *err, + const char *event) +{ + if (!err->num_errors) + return; + + __parse_events_print_error(err->idx, err->str, err->help, event); + + if (err->num_errors > 1) { + fputs("\nInitial error:\n", stderr); + __parse_events_print_error(err->first_idx, err->first_str, + err->first_help, event); + } +} + void parse_events_print_error(struct parse_events_error *err, const char *event) { diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index a0c6f95b5683..014d268426e6 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -202,7 +202,7 @@ struct evsel *parse_events__add_event(int idx, struct perf_event_attr *attr, char *name, struct perf_pmu *pmu);
int parse_events_multi_pmu_add(struct parse_events_state *parse_state, - char *str, + char *str, struct list_head *head, struct list_head **listp);
int parse_events_copy_term_list(struct list_head *old, @@ -242,6 +242,10 @@ char *parse_events_formats_error_string(char *additional_terms);
void parse_events_print_error(struct parse_events_error *err, const char *event); +void parse_events_error__init(struct parse_events_error *err); +void parse_events_error__exit(struct parse_events_error *err); +void parse_events_error__print(struct parse_events_error *err, + const char *event);
#ifdef HAVE_LIBELF_SUPPORT /* diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index b6dd7f8b5a6c..15e3c90f1c27 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -337,7 +337,7 @@ PE_KERNEL_PMU_EVENT sep_dc struct list_head *list; int err;
- err = parse_events_multi_pmu_add(_parse_state, $1, &list); + err = parse_events_multi_pmu_add(_parse_state, $1, NULL, &list); free($1); if (err < 0) YYABORT; @@ -357,6 +357,19 @@ PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF '-' PE_PMU_EVENT_SUF2 sep_dc $$ = list; } | +PE_KERNEL_PMU_EVENT opt_pmu_config +{ + struct list_head *list; + int err; + + /* frees $2 */ + err = parse_events_multi_pmu_add(_parse_state, $1, $2, &list); + free($1); + if (err < 0) + YYABORT; + $$ = list; +} +| PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc { struct list_head *list; @@ -365,7 +378,7 @@ PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc snprintf(pmu_name, sizeof(pmu_name), "%s-%s", $1, $3); free($1); free($3); - if (parse_events_multi_pmu_add(_parse_state, pmu_name, &list) < 0) + if (parse_events_multi_pmu_add(_parse_state, pmu_name, NULL, &list) < 0) YYABORT; $$ = list; }