mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
perf parse-events: Prefer sysfs/JSON hardware events over legacy
It was requested that RISC-V be able to add events to the perf tool so the PMU driver didn't need to map legacy events to config encodings: https://lore.kernel.org/lkml/20240217005738.3744121-1-atishp@rivosinc.com/ This change makes the priority of events specified without a PMU the same as those specified with a PMU, namely sysfs and JSON events are checked first before using the legacy encoding. The hw_term is made more generic as a hardware_event that encodes a pair of string and int value, allowing parse_events_multi_pmu_add to fall back on a known encoding when the sysfs/JSON adding fails for core events. As this covers PE_VALUE_SYM_HW, that token is removed and related code simplified. Signed-off-by: Ian Rogers <irogers@google.com> Reviewed-by: Kan Liang <kan.liang@linux.intel.com> Tested-by: Atish Patra <atishp@rivosinc.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Beeman Strong <beeman@rivosinc.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: James Clark <james.clark@arm.com> Cc: Jiri Olsa <jolsa@kernel.org> 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/20240416061533.921723-10-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
5ccc4edfc2
commit
617824a7f0
4 changed files with 105 additions and 70 deletions
|
@ -1543,7 +1543,7 @@ static int parse_events_add_pmu(struct parse_events_state *parse_state,
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
|
int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
|
||||||
const char *event_name,
|
const char *event_name, u64 hw_config,
|
||||||
const struct parse_events_terms *const_parsed_terms,
|
const struct parse_events_terms *const_parsed_terms,
|
||||||
struct list_head **listp, void *loc_)
|
struct list_head **listp, void *loc_)
|
||||||
{
|
{
|
||||||
|
@ -1551,8 +1551,8 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
|
||||||
struct list_head *list = NULL;
|
struct list_head *list = NULL;
|
||||||
struct perf_pmu *pmu = NULL;
|
struct perf_pmu *pmu = NULL;
|
||||||
YYLTYPE *loc = loc_;
|
YYLTYPE *loc = loc_;
|
||||||
int ok = 0;
|
int ok = 0, core_ok = 0;
|
||||||
const char *config;
|
const char *tmp;
|
||||||
struct parse_events_terms parsed_terms;
|
struct parse_events_terms parsed_terms;
|
||||||
|
|
||||||
*listp = NULL;
|
*listp = NULL;
|
||||||
|
@ -1565,15 +1565,15 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
config = strdup(event_name);
|
tmp = strdup(event_name);
|
||||||
if (!config)
|
if (!tmp)
|
||||||
goto out_err;
|
goto out_err;
|
||||||
|
|
||||||
if (parse_events_term__num(&term,
|
if (parse_events_term__num(&term,
|
||||||
PARSE_EVENTS__TERM_TYPE_USER,
|
PARSE_EVENTS__TERM_TYPE_USER,
|
||||||
config, /*num=*/1, /*novalue=*/true,
|
tmp, /*num=*/1, /*novalue=*/true,
|
||||||
loc, /*loc_val=*/NULL) < 0) {
|
loc, /*loc_val=*/NULL) < 0) {
|
||||||
zfree(&config);
|
zfree(&tmp);
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
list_add_tail(&term->list, &parsed_terms.terms);
|
list_add_tail(&term->list, &parsed_terms.terms);
|
||||||
|
@ -1604,6 +1604,8 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
|
||||||
pr_debug("%s -> %s/%s/\n", event_name, pmu->name, sb.buf);
|
pr_debug("%s -> %s/%s/\n", event_name, pmu->name, sb.buf);
|
||||||
strbuf_release(&sb);
|
strbuf_release(&sb);
|
||||||
ok++;
|
ok++;
|
||||||
|
if (pmu->is_core)
|
||||||
|
core_ok++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1620,6 +1622,18 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hw_config != PERF_COUNT_HW_MAX && !core_ok) {
|
||||||
|
/*
|
||||||
|
* The event wasn't found on core PMUs but it has a hardware
|
||||||
|
* config version to try.
|
||||||
|
*/
|
||||||
|
if (!parse_events_add_numeric(parse_state, list,
|
||||||
|
PERF_TYPE_HARDWARE, hw_config,
|
||||||
|
const_parsed_terms,
|
||||||
|
/*wildcard=*/true))
|
||||||
|
ok++;
|
||||||
|
}
|
||||||
|
|
||||||
out_err:
|
out_err:
|
||||||
parse_events_terms__exit(&parsed_terms);
|
parse_events_terms__exit(&parsed_terms);
|
||||||
if (ok)
|
if (ok)
|
||||||
|
@ -1673,7 +1687,8 @@ int parse_events_multi_pmu_add_or_add_pmu(struct parse_events_state *parse_state
|
||||||
|
|
||||||
/* Failure to add, assume event_or_pmu is an event name. */
|
/* Failure to add, assume event_or_pmu is an event name. */
|
||||||
zfree(listp);
|
zfree(listp);
|
||||||
if (!parse_events_multi_pmu_add(parse_state, event_or_pmu, const_parsed_terms, listp, loc))
|
if (!parse_events_multi_pmu_add(parse_state, event_or_pmu, PERF_COUNT_HW_MAX,
|
||||||
|
const_parsed_terms, listp, loc))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (asprintf(&help, "Unable to find PMU or event on a PMU of '%s'", event_or_pmu) < 0)
|
if (asprintf(&help, "Unable to find PMU or event on a PMU of '%s'", event_or_pmu) < 0)
|
||||||
|
|
|
@ -215,7 +215,7 @@ struct evsel *parse_events__add_event(int idx, struct perf_event_attr *attr,
|
||||||
struct perf_pmu *pmu);
|
struct perf_pmu *pmu);
|
||||||
|
|
||||||
int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
|
int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
|
||||||
const char *event_name,
|
const char *event_name, u64 hw_config,
|
||||||
const struct parse_events_terms *const_parsed_terms,
|
const struct parse_events_terms *const_parsed_terms,
|
||||||
struct list_head **listp, void *loc);
|
struct list_head **listp, void *loc);
|
||||||
|
|
||||||
|
|
|
@ -100,12 +100,12 @@ do { \
|
||||||
yyless(0); \
|
yyless(0); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static int sym(yyscan_t scanner, int type, int config)
|
static int sym(yyscan_t scanner, int config)
|
||||||
{
|
{
|
||||||
YYSTYPE *yylval = parse_events_get_lval(scanner);
|
YYSTYPE *yylval = parse_events_get_lval(scanner);
|
||||||
|
|
||||||
yylval->num = (type << 16) + config;
|
yylval->num = config;
|
||||||
return type == PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW;
|
return PE_VALUE_SYM_SW;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tool(yyscan_t scanner, enum perf_tool_event event)
|
static int tool(yyscan_t scanner, enum perf_tool_event event)
|
||||||
|
@ -124,13 +124,13 @@ static int term(yyscan_t scanner, enum parse_events__term_type type)
|
||||||
return PE_TERM;
|
return PE_TERM;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hw_term(yyscan_t scanner, int config)
|
static int hw(yyscan_t scanner, int config)
|
||||||
{
|
{
|
||||||
YYSTYPE *yylval = parse_events_get_lval(scanner);
|
YYSTYPE *yylval = parse_events_get_lval(scanner);
|
||||||
char *text = parse_events_get_text(scanner);
|
char *text = parse_events_get_text(scanner);
|
||||||
|
|
||||||
yylval->hardware_term.str = strdup(text);
|
yylval->hardware_event.str = strdup(text);
|
||||||
yylval->hardware_term.num = PERF_TYPE_HARDWARE + config;
|
yylval->hardware_event.num = config;
|
||||||
return PE_TERM_HW;
|
return PE_TERM_HW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,16 +246,16 @@ percore { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_PERCORE); }
|
||||||
aux-output { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT); }
|
aux-output { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT); }
|
||||||
aux-sample-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE); }
|
aux-sample-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE); }
|
||||||
metric-id { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_METRIC_ID); }
|
metric-id { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_METRIC_ID); }
|
||||||
cpu-cycles|cycles { return hw_term(yyscanner, PERF_COUNT_HW_CPU_CYCLES); }
|
cpu-cycles|cycles { return hw(yyscanner, PERF_COUNT_HW_CPU_CYCLES); }
|
||||||
stalled-cycles-frontend|idle-cycles-frontend { return hw_term(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
|
stalled-cycles-frontend|idle-cycles-frontend { return hw(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
|
||||||
stalled-cycles-backend|idle-cycles-backend { return hw_term(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
|
stalled-cycles-backend|idle-cycles-backend { return hw(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
|
||||||
instructions { return hw_term(yyscanner, PERF_COUNT_HW_INSTRUCTIONS); }
|
instructions { return hw(yyscanner, PERF_COUNT_HW_INSTRUCTIONS); }
|
||||||
cache-references { return hw_term(yyscanner, PERF_COUNT_HW_CACHE_REFERENCES); }
|
cache-references { return hw(yyscanner, PERF_COUNT_HW_CACHE_REFERENCES); }
|
||||||
cache-misses { return hw_term(yyscanner, PERF_COUNT_HW_CACHE_MISSES); }
|
cache-misses { return hw(yyscanner, PERF_COUNT_HW_CACHE_MISSES); }
|
||||||
branch-instructions|branches { return hw_term(yyscanner, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
|
branch-instructions|branches { return hw(yyscanner, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
|
||||||
branch-misses { return hw_term(yyscanner, PERF_COUNT_HW_BRANCH_MISSES); }
|
branch-misses { return hw(yyscanner, PERF_COUNT_HW_BRANCH_MISSES); }
|
||||||
bus-cycles { return hw_term(yyscanner, PERF_COUNT_HW_BUS_CYCLES); }
|
bus-cycles { return hw(yyscanner, PERF_COUNT_HW_BUS_CYCLES); }
|
||||||
ref-cycles { return hw_term(yyscanner, PERF_COUNT_HW_REF_CPU_CYCLES); }
|
ref-cycles { return hw(yyscanner, PERF_COUNT_HW_REF_CPU_CYCLES); }
|
||||||
r{num_raw_hex} { return str(yyscanner, PE_RAW); }
|
r{num_raw_hex} { return str(yyscanner, PE_RAW); }
|
||||||
r0x{num_raw_hex} { return str(yyscanner, PE_RAW); }
|
r0x{num_raw_hex} { return str(yyscanner, PE_RAW); }
|
||||||
, { return ','; }
|
, { return ','; }
|
||||||
|
@ -299,31 +299,31 @@ r0x{num_raw_hex} { return str(yyscanner, PE_RAW); }
|
||||||
<<EOF>> { BEGIN(INITIAL); }
|
<<EOF>> { BEGIN(INITIAL); }
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu-cycles|cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
|
cpu-cycles|cycles { return hw(yyscanner, PERF_COUNT_HW_CPU_CYCLES); }
|
||||||
stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
|
stalled-cycles-frontend|idle-cycles-frontend { return hw(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
|
||||||
stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
|
stalled-cycles-backend|idle-cycles-backend { return hw(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
|
||||||
instructions { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); }
|
instructions { return hw(yyscanner, PERF_COUNT_HW_INSTRUCTIONS); }
|
||||||
cache-references { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); }
|
cache-references { return hw(yyscanner, PERF_COUNT_HW_CACHE_REFERENCES); }
|
||||||
cache-misses { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); }
|
cache-misses { return hw(yyscanner, PERF_COUNT_HW_CACHE_MISSES); }
|
||||||
branch-instructions|branches { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
|
branch-instructions|branches { return hw(yyscanner, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
|
||||||
branch-misses { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); }
|
branch-misses { return hw(yyscanner, PERF_COUNT_HW_BRANCH_MISSES); }
|
||||||
bus-cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); }
|
bus-cycles { return hw(yyscanner, PERF_COUNT_HW_BUS_CYCLES); }
|
||||||
ref-cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); }
|
ref-cycles { return hw(yyscanner, PERF_COUNT_HW_REF_CPU_CYCLES); }
|
||||||
cpu-clock { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); }
|
cpu-clock { return sym(yyscanner, PERF_COUNT_SW_CPU_CLOCK); }
|
||||||
task-clock { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); }
|
task-clock { return sym(yyscanner, PERF_COUNT_SW_TASK_CLOCK); }
|
||||||
page-faults|faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); }
|
page-faults|faults { return sym(yyscanner, PERF_COUNT_SW_PAGE_FAULTS); }
|
||||||
minor-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN); }
|
minor-faults { return sym(yyscanner, PERF_COUNT_SW_PAGE_FAULTS_MIN); }
|
||||||
major-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ); }
|
major-faults { return sym(yyscanner, PERF_COUNT_SW_PAGE_FAULTS_MAJ); }
|
||||||
context-switches|cs { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES); }
|
context-switches|cs { return sym(yyscanner, PERF_COUNT_SW_CONTEXT_SWITCHES); }
|
||||||
cpu-migrations|migrations { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS); }
|
cpu-migrations|migrations { return sym(yyscanner, PERF_COUNT_SW_CPU_MIGRATIONS); }
|
||||||
alignment-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); }
|
alignment-faults { return sym(yyscanner, PERF_COUNT_SW_ALIGNMENT_FAULTS); }
|
||||||
emulation-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }
|
emulation-faults { return sym(yyscanner, PERF_COUNT_SW_EMULATION_FAULTS); }
|
||||||
dummy { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); }
|
dummy { return sym(yyscanner, PERF_COUNT_SW_DUMMY); }
|
||||||
duration_time { return tool(yyscanner, PERF_TOOL_DURATION_TIME); }
|
duration_time { return tool(yyscanner, PERF_TOOL_DURATION_TIME); }
|
||||||
user_time { return tool(yyscanner, PERF_TOOL_USER_TIME); }
|
user_time { return tool(yyscanner, PERF_TOOL_USER_TIME); }
|
||||||
system_time { return tool(yyscanner, PERF_TOOL_SYSTEM_TIME); }
|
system_time { return tool(yyscanner, PERF_TOOL_SYSTEM_TIME); }
|
||||||
bpf-output { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_BPF_OUTPUT); }
|
bpf-output { return sym(yyscanner, PERF_COUNT_SW_BPF_OUTPUT); }
|
||||||
cgroup-switches { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CGROUP_SWITCHES); }
|
cgroup-switches { return sym(yyscanner, PERF_COUNT_SW_CGROUP_SWITCHES); }
|
||||||
|
|
||||||
{lc_type} { return str(yyscanner, PE_LEGACY_CACHE); }
|
{lc_type} { return str(yyscanner, PE_LEGACY_CACHE); }
|
||||||
{lc_type}-{lc_op_result} { return str(yyscanner, PE_LEGACY_CACHE); }
|
{lc_type}-{lc_op_result} { return str(yyscanner, PE_LEGACY_CACHE); }
|
||||||
|
|
|
@ -55,7 +55,7 @@ static void free_list_evsel(struct list_head* list_evsel)
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%token PE_START_EVENTS PE_START_TERMS
|
%token PE_START_EVENTS PE_START_TERMS
|
||||||
%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_TERM
|
%token PE_VALUE PE_VALUE_SYM_SW PE_TERM
|
||||||
%token PE_VALUE_SYM_TOOL
|
%token PE_VALUE_SYM_TOOL
|
||||||
%token PE_EVENT_NAME
|
%token PE_EVENT_NAME
|
||||||
%token PE_RAW PE_NAME
|
%token PE_RAW PE_NAME
|
||||||
|
@ -66,11 +66,9 @@ static void free_list_evsel(struct list_head* list_evsel)
|
||||||
%token PE_DRV_CFG_TERM
|
%token PE_DRV_CFG_TERM
|
||||||
%token PE_TERM_HW
|
%token PE_TERM_HW
|
||||||
%type <num> PE_VALUE
|
%type <num> PE_VALUE
|
||||||
%type <num> PE_VALUE_SYM_HW
|
|
||||||
%type <num> PE_VALUE_SYM_SW
|
%type <num> PE_VALUE_SYM_SW
|
||||||
%type <num> PE_VALUE_SYM_TOOL
|
%type <num> PE_VALUE_SYM_TOOL
|
||||||
%type <term_type> PE_TERM
|
%type <term_type> PE_TERM
|
||||||
%type <num> value_sym
|
|
||||||
%type <str> PE_RAW
|
%type <str> PE_RAW
|
||||||
%type <str> PE_NAME
|
%type <str> PE_NAME
|
||||||
%type <str> PE_LEGACY_CACHE
|
%type <str> PE_LEGACY_CACHE
|
||||||
|
@ -87,6 +85,7 @@ static void free_list_evsel(struct list_head* list_evsel)
|
||||||
%type <list_terms> opt_pmu_config
|
%type <list_terms> opt_pmu_config
|
||||||
%destructor { parse_events_terms__delete ($$); } <list_terms>
|
%destructor { parse_events_terms__delete ($$); } <list_terms>
|
||||||
%type <list_evsel> event_pmu
|
%type <list_evsel> event_pmu
|
||||||
|
%type <list_evsel> event_legacy_hardware
|
||||||
%type <list_evsel> event_legacy_symbol
|
%type <list_evsel> event_legacy_symbol
|
||||||
%type <list_evsel> event_legacy_cache
|
%type <list_evsel> event_legacy_cache
|
||||||
%type <list_evsel> event_legacy_mem
|
%type <list_evsel> event_legacy_mem
|
||||||
|
@ -104,8 +103,8 @@ static void free_list_evsel(struct list_head* list_evsel)
|
||||||
%destructor { free_list_evsel ($$); } <list_evsel>
|
%destructor { free_list_evsel ($$); } <list_evsel>
|
||||||
%type <tracepoint_name> tracepoint_name
|
%type <tracepoint_name> tracepoint_name
|
||||||
%destructor { free ($$.sys); free ($$.event); } <tracepoint_name>
|
%destructor { free ($$.sys); free ($$.event); } <tracepoint_name>
|
||||||
%type <hardware_term> PE_TERM_HW
|
%type <hardware_event> PE_TERM_HW
|
||||||
%destructor { free ($$.str); } <hardware_term>
|
%destructor { free ($$.str); } <hardware_event>
|
||||||
|
|
||||||
%union
|
%union
|
||||||
{
|
{
|
||||||
|
@ -119,10 +118,10 @@ static void free_list_evsel(struct list_head* list_evsel)
|
||||||
char *sys;
|
char *sys;
|
||||||
char *event;
|
char *event;
|
||||||
} tracepoint_name;
|
} tracepoint_name;
|
||||||
struct hardware_term {
|
struct hardware_event {
|
||||||
char *str;
|
char *str;
|
||||||
u64 num;
|
u64 num;
|
||||||
} hardware_term;
|
} hardware_event;
|
||||||
}
|
}
|
||||||
%%
|
%%
|
||||||
|
|
||||||
|
@ -263,6 +262,7 @@ PE_EVENT_NAME event_def
|
||||||
event_def
|
event_def
|
||||||
|
|
||||||
event_def: event_pmu |
|
event_def: event_pmu |
|
||||||
|
event_legacy_hardware |
|
||||||
event_legacy_symbol |
|
event_legacy_symbol |
|
||||||
event_legacy_cache sep_dc |
|
event_legacy_cache sep_dc |
|
||||||
event_legacy_mem sep_dc |
|
event_legacy_mem sep_dc |
|
||||||
|
@ -289,7 +289,7 @@ PE_NAME sep_dc
|
||||||
struct list_head *list;
|
struct list_head *list;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = parse_events_multi_pmu_add(_parse_state, $1, NULL, &list, &@1);
|
err = parse_events_multi_pmu_add(_parse_state, $1, PERF_COUNT_HW_MAX, NULL, &list, &@1);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
struct parse_events_state *parse_state = _parse_state;
|
struct parse_events_state *parse_state = _parse_state;
|
||||||
struct parse_events_error *error = parse_state->error;
|
struct parse_events_error *error = parse_state->error;
|
||||||
|
@ -305,24 +305,45 @@ PE_NAME sep_dc
|
||||||
$$ = list;
|
$$ = list;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_sym:
|
event_legacy_hardware:
|
||||||
PE_VALUE_SYM_HW
|
PE_TERM_HW opt_pmu_config
|
||||||
|
|
{
|
||||||
PE_VALUE_SYM_SW
|
/* List of created evsels. */
|
||||||
|
struct list_head *list = NULL;
|
||||||
|
int err = parse_events_multi_pmu_add(_parse_state, $1.str, $1.num, $2, &list, &@1);
|
||||||
|
|
||||||
event_legacy_symbol:
|
free($1.str);
|
||||||
value_sym '/' event_config '/'
|
parse_events_terms__delete($2);
|
||||||
|
if (err)
|
||||||
|
PE_ABORT(err);
|
||||||
|
|
||||||
|
$$ = list;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
PE_TERM_HW sep_dc
|
||||||
|
{
|
||||||
|
struct list_head *list;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = parse_events_multi_pmu_add(_parse_state, $1.str, $1.num, NULL, &list, &@1);
|
||||||
|
free($1.str);
|
||||||
|
if (err)
|
||||||
|
PE_ABORT(err);
|
||||||
|
$$ = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
event_legacy_symbol:
|
||||||
|
PE_VALUE_SYM_SW '/' event_config '/'
|
||||||
{
|
{
|
||||||
struct list_head *list;
|
struct list_head *list;
|
||||||
int type = $1 >> 16;
|
|
||||||
int config = $1 & 255;
|
|
||||||
int err;
|
int err;
|
||||||
bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);
|
|
||||||
|
|
||||||
list = alloc_list();
|
list = alloc_list();
|
||||||
if (!list)
|
if (!list)
|
||||||
YYNOMEM;
|
YYNOMEM;
|
||||||
err = parse_events_add_numeric(_parse_state, list, type, config, $3, wildcard);
|
err = parse_events_add_numeric(_parse_state, list,
|
||||||
|
/*type=*/PERF_TYPE_SOFTWARE, /*config=*/$1,
|
||||||
|
$3, /*wildcard=*/false);
|
||||||
parse_events_terms__delete($3);
|
parse_events_terms__delete($3);
|
||||||
if (err) {
|
if (err) {
|
||||||
free_list_evsel(list);
|
free_list_evsel(list);
|
||||||
|
@ -331,18 +352,17 @@ value_sym '/' event_config '/'
|
||||||
$$ = list;
|
$$ = list;
|
||||||
}
|
}
|
||||||
|
|
|
|
||||||
value_sym sep_slash_slash_dc
|
PE_VALUE_SYM_SW sep_slash_slash_dc
|
||||||
{
|
{
|
||||||
struct list_head *list;
|
struct list_head *list;
|
||||||
int type = $1 >> 16;
|
|
||||||
int config = $1 & 255;
|
|
||||||
bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
list = alloc_list();
|
list = alloc_list();
|
||||||
if (!list)
|
if (!list)
|
||||||
YYNOMEM;
|
YYNOMEM;
|
||||||
err = parse_events_add_numeric(_parse_state, list, type, config, /*head_config=*/NULL, wildcard);
|
err = parse_events_add_numeric(_parse_state, list,
|
||||||
|
/*type=*/PERF_TYPE_SOFTWARE, /*config=*/$1,
|
||||||
|
/*head_config=*/NULL, /*wildcard=*/false);
|
||||||
if (err)
|
if (err)
|
||||||
PE_ABORT(err);
|
PE_ABORT(err);
|
||||||
$$ = list;
|
$$ = list;
|
||||||
|
|
Loading…
Add table
Reference in a new issue