diff options
author | 2023-05-02 15:38:25 -0700 | |
---|---|---|
committer | 2023-05-15 09:12:13 -0300 | |
commit | 70c90e4a6b2fbe775b662eafefae51f64d627790 (patch) | |
tree | 3c1764b6fd08a710825b0c6f51a76af1a2757407 /tools/perf/util/parse-events.y | |
parent | perf print-events: Avoid unnecessary strlist (diff) | |
download | linux-70c90e4a6b2fbe775b662eafefae51f64d627790.tar.gz linux-70c90e4a6b2fbe775b662eafefae51f64d627790.tar.bz2 linux-70c90e4a6b2fbe775b662eafefae51f64d627790.zip |
perf parse-events: Avoid scanning PMUs before parsing
The event parser needs to handle two special cases:
1) legacy events like L1-dcache-load-miss. These event names don't
appear in JSON or sysfs, and lookup tables are used for the config
value.
2) raw events where 'r0xead' is the same as 'read' unless the PMU has
an event called 'read' in which case the event has priority.
The previous parser to handle these cases would scan all PMUs for
components of event names. These components would then be used to
classify in the lexer whether the token should be part of a legacy
event, a raw event or an event. The grammar would handle legacy event
tokens or recombining the tokens back into a regular event name. The
code wasn't PMU specific and had issues around events like AMD's
branch-brs that would fail to parse as it expects brs to be a suffix
on a legacy event style name:
$ perf stat -e branch-brs true
event syntax error: 'branch-brs'
\___ parser error
This change removes processing all PMUs by using the lexer in the form
of a regular expression matcher. The lexer will return the token for
the longest matched sequence of characters, and in the event of a tie
the first. The legacy events are a fixed number of regular
expressions, and by matching these before a name token its possible to
generate an accurate legacy event token with everything else matching
as a name. Because of the lexer change the handling of hyphens in the
grammar can be removed as hyphens just become a part of the name.
To handle raw events and terms the parser is changed to defer trying
to evaluate whether something is a raw event until the PMU is known in
the grammar. Once the PMU is known, the events of the PMU can be
scanned for the 'read' style problem. A new term type is added for
these raw terms, used to enable deferring the evaluation.
While this change is large, it has stats of:
170 insertions(+), 436 deletions(-)
the bulk of the change is deleting the old approach. It isn't possible
to break apart the code added due to the dependencies on how the parts
of the parsing work.
Signed-off-by: Ian Rogers <irogers@google.com>
Tested-by: Kan Liang <kan.liang@linux.intel.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ahmad Yasin <ahmad.yasin@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
Cc: Caleb Biggers <caleb.biggers@intel.com>
Cc: Edward Baker <edward.baker@intel.com>
Cc: Florian Fischer <florian.fischer@muhq.space>
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: Kajol Jain <kjain@linux.ibm.com>
Cc: Kang Minchul <tegongkang@gmail.com>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Perry Taylor <perry.taylor@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Samantha Alt <samantha.alt@intel.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Sumanth Korikkar <sumanthk@linux.ibm.com>
Cc: Suzuki Poulouse <suzuki.poulose@arm.com>
Cc: Thomas Richter <tmricht@linux.ibm.com>
Cc: Tiezhu Yang <yangtiezhu@loongson.cn>
Cc: Weilin Wang <weilin.wang@intel.com>
Cc: Xing Zhengjun <zhengjun.xing@linux.intel.com>
Cc: Yang Jihong <yangjihong1@huawei.com>
Link: https://lore.kernel.org/r/20230502223851.2234828-19-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/parse-events.y')
-rw-r--r-- | tools/perf/util/parse-events.y | 143 |
1 files changed, 45 insertions, 98 deletions
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index 4488443e506e..e7072b5601c5 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -8,6 +8,7 @@ #define YYDEBUG 1 +#include <errno.h> #include <fnmatch.h> #include <stdio.h> #include <linux/compiler.h> @@ -52,36 +53,35 @@ static void free_list_evsel(struct list_head* list_evsel) %} %token PE_START_EVENTS PE_START_TERMS -%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM +%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_TERM %token PE_VALUE_SYM_TOOL %token PE_EVENT_NAME -%token PE_NAME +%token PE_RAW PE_NAME %token PE_BPF_OBJECT PE_BPF_SOURCE %token PE_MODIFIER_EVENT PE_MODIFIER_BP -%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT +%token PE_LEGACY_CACHE %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP %token PE_ERROR -%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_PMU_EVENT_SUF2 PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE +%token PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE %token PE_ARRAY_ALL PE_ARRAY_RANGE %token PE_DRV_CFG_TERM %type <num> PE_VALUE %type <num> PE_VALUE_SYM_HW %type <num> PE_VALUE_SYM_SW %type <num> PE_VALUE_SYM_TOOL -%type <num> PE_RAW %type <num> PE_TERM %type <num> value_sym +%type <str> PE_RAW %type <str> PE_NAME %type <str> PE_BPF_OBJECT %type <str> PE_BPF_SOURCE -%type <str> PE_NAME_CACHE_TYPE -%type <str> PE_NAME_CACHE_OP_RESULT +%type <str> PE_LEGACY_CACHE %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_PMU_EVENT_SUF2 PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE +%type <str> PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE %type <str> PE_DRV_CFG_TERM -%type <str> event_pmu_name +%type <str> name_or_raw %destructor { free ($$); } <str> %type <term> event_term %destructor { parse_events_term__delete ($$); } <term> @@ -273,11 +273,8 @@ event_def: event_pmu | event_legacy_raw sep_dc | event_bpf_file -event_pmu_name: -PE_NAME | PE_PMU_EVENT_PRE - event_pmu: -event_pmu_name opt_pmu_config +PE_NAME opt_pmu_config { struct parse_events_state *parse_state = _parse_state; struct parse_events_error *error = parse_state->error; @@ -303,10 +300,12 @@ event_pmu_name opt_pmu_config list = alloc_list(); if (!list) CLEANUP_YYABORT; + /* Attempt to add to list assuming $1 is a PMU name. */ if (parse_events_add_pmu(_parse_state, list, $1, $2, /*auto_merge_stats=*/false)) { struct perf_pmu *pmu = NULL; int ok = 0; + /* Failure to add, try wildcard expansion of $1 as a PMU name. */ if (asprintf(&pattern, "%s*", $1) < 0) CLEANUP_YYABORT; @@ -329,6 +328,12 @@ event_pmu_name opt_pmu_config } } + if (!ok) { + /* Failure to add, assume $1 is an event name. */ + zfree(&list); + ok = !parse_events_multi_pmu_add(_parse_state, $1, $2, &list); + $2 = NULL; + } if (!ok) CLEANUP_YYABORT; } @@ -352,41 +357,27 @@ PE_KERNEL_PMU_EVENT sep_dc $$ = list; } | -PE_KERNEL_PMU_EVENT opt_pmu_config +PE_NAME sep_dc { struct list_head *list; int err; - /* frees $2 */ - err = parse_events_multi_pmu_add(_parse_state, $1, $2, &list); + err = parse_events_multi_pmu_add(_parse_state, $1, NULL, &list); free($1); if (err < 0) YYABORT; $$ = 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 +PE_KERNEL_PMU_EVENT opt_pmu_config { struct list_head *list; - char pmu_name[128]; + int err; - snprintf(pmu_name, sizeof(pmu_name), "%s-%s", $1, $3); + /* frees $2 */ + err = parse_events_multi_pmu_add(_parse_state, $1, $2, &list); free($1); - free($3); - if (parse_events_multi_pmu_add(_parse_state, pmu_name, NULL, &list) < 0) + if (err < 0) YYABORT; $$ = list; } @@ -476,7 +467,7 @@ PE_VALUE_SYM_TOOL sep_slash_slash_dc } event_legacy_cache: -PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT opt_event_config +PE_LEGACY_CACHE opt_event_config { struct parse_events_state *parse_state = _parse_state; struct parse_events_error *error = parse_state->error; @@ -485,51 +476,8 @@ PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT opt_e list = alloc_list(); ABORT_ON(!list); - err = parse_events_add_cache(list, &parse_state->idx, $1, $3, $5, error, $6, - parse_state); - parse_events_terms__delete($6); - free($1); - free($3); - free($5); - if (err) { - free_list_evsel(list); - YYABORT; - } - $$ = list; -} -| -PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT opt_event_config -{ - struct parse_events_state *parse_state = _parse_state; - struct parse_events_error *error = parse_state->error; - struct list_head *list; - int err; + err = parse_events_add_cache(list, &parse_state->idx, $1, error, $2, parse_state); - list = alloc_list(); - ABORT_ON(!list); - err = parse_events_add_cache(list, &parse_state->idx, $1, $3, NULL, error, $4, - parse_state); - parse_events_terms__delete($4); - free($1); - free($3); - if (err) { - free_list_evsel(list); - YYABORT; - } - $$ = list; -} -| -PE_NAME_CACHE_TYPE opt_event_config -{ - struct parse_events_state *parse_state = _parse_state; - struct parse_events_error *error = parse_state->error; - struct list_head *list; - int err; - - list = alloc_list(); - ABORT_ON(!list); - err = parse_events_add_cache(list, &parse_state->idx, $1, NULL, NULL, error, $2, - parse_state); parse_events_terms__delete($2); free($1); if (err) { @@ -633,17 +581,6 @@ tracepoint_name opt_event_config } tracepoint_name: -PE_NAME '-' PE_NAME ':' PE_NAME -{ - struct tracepoint_name tracepoint; - - ABORT_ON(asprintf(&tracepoint.sys, "%s-%s", $1, $3) < 0); - tracepoint.event = $5; - free($1); - free($3); - $$ = tracepoint; -} -| PE_NAME ':' PE_NAME { struct tracepoint_name tracepoint = {$1, $3}; @@ -673,10 +610,15 @@ PE_RAW opt_event_config { struct list_head *list; int err; + u64 num; list = alloc_list(); ABORT_ON(!list); - err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, $1, $2); + errno = 0; + num = strtoull($1 + 1, NULL, 16); + ABORT_ON(errno); + free($1); + err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, num, $2); parse_events_terms__delete($2); if (err) { free(list); @@ -781,17 +723,22 @@ event_term $$ = head; } +name_or_raw: PE_RAW | PE_NAME + event_term: PE_RAW { struct parse_events_term *term; - ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_CONFIG, - NULL, $1, false, &@1, NULL)); + if (parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_RAW, + strdup("raw"), $1, &@1, &@1)) { + free($1); + YYABORT; + } $$ = term; } | -PE_NAME '=' PE_NAME +name_or_raw '=' PE_NAME { struct parse_events_term *term; @@ -804,7 +751,7 @@ PE_NAME '=' PE_NAME $$ = term; } | -PE_NAME '=' PE_VALUE +name_or_raw '=' PE_VALUE { struct parse_events_term *term; @@ -816,7 +763,7 @@ PE_NAME '=' PE_VALUE $$ = term; } | -PE_NAME '=' PE_VALUE_SYM_HW +name_or_raw '=' PE_VALUE_SYM_HW { struct parse_events_term *term; int config = $3 & 255; @@ -876,7 +823,7 @@ PE_TERM $$ = term; } | -PE_NAME array '=' PE_NAME +name_or_raw array '=' PE_NAME { struct parse_events_term *term; @@ -891,7 +838,7 @@ PE_NAME array '=' PE_NAME $$ = term; } | -PE_NAME array '=' PE_VALUE +name_or_raw array '=' PE_VALUE { struct parse_events_term *term; |