Skip to content

Commit 617824a

Browse files
captain5050acmel
authored andcommitted
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/[email protected]/ 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 <[email protected]> Reviewed-by: Kan Liang <[email protected]> Tested-by: Atish Patra <[email protected]> Cc: Adrian Hunter <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Beeman Strong <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: James Clark <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Peter Zijlstra <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 5ccc4ed commit 617824a

File tree

4 files changed

+103
-68
lines changed

4 files changed

+103
-68
lines changed

tools/perf/util/parse-events.c

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1543,16 +1543,16 @@ static int parse_events_add_pmu(struct parse_events_state *parse_state,
15431543
}
15441544

15451545
int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
1546-
const char *event_name,
1546+
const char *event_name, u64 hw_config,
15471547
const struct parse_events_terms *const_parsed_terms,
15481548
struct list_head **listp, void *loc_)
15491549
{
15501550
struct parse_events_term *term;
15511551
struct list_head *list = NULL;
15521552
struct perf_pmu *pmu = NULL;
15531553
YYLTYPE *loc = loc_;
1554-
int ok = 0;
1555-
const char *config;
1554+
int ok = 0, core_ok = 0;
1555+
const char *tmp;
15561556
struct parse_events_terms parsed_terms;
15571557

15581558
*listp = NULL;
@@ -1565,15 +1565,15 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
15651565
return ret;
15661566
}
15671567

1568-
config = strdup(event_name);
1569-
if (!config)
1568+
tmp = strdup(event_name);
1569+
if (!tmp)
15701570
goto out_err;
15711571

15721572
if (parse_events_term__num(&term,
15731573
PARSE_EVENTS__TERM_TYPE_USER,
1574-
config, /*num=*/1, /*novalue=*/true,
1574+
tmp, /*num=*/1, /*novalue=*/true,
15751575
loc, /*loc_val=*/NULL) < 0) {
1576-
zfree(&config);
1576+
zfree(&tmp);
15771577
goto out_err;
15781578
}
15791579
list_add_tail(&term->list, &parsed_terms.terms);
@@ -1604,6 +1604,8 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
16041604
pr_debug("%s -> %s/%s/\n", event_name, pmu->name, sb.buf);
16051605
strbuf_release(&sb);
16061606
ok++;
1607+
if (pmu->is_core)
1608+
core_ok++;
16071609
}
16081610
}
16091611

@@ -1620,6 +1622,18 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
16201622
}
16211623
}
16221624

1625+
if (hw_config != PERF_COUNT_HW_MAX && !core_ok) {
1626+
/*
1627+
* The event wasn't found on core PMUs but it has a hardware
1628+
* config version to try.
1629+
*/
1630+
if (!parse_events_add_numeric(parse_state, list,
1631+
PERF_TYPE_HARDWARE, hw_config,
1632+
const_parsed_terms,
1633+
/*wildcard=*/true))
1634+
ok++;
1635+
}
1636+
16231637
out_err:
16241638
parse_events_terms__exit(&parsed_terms);
16251639
if (ok)
@@ -1673,7 +1687,8 @@ int parse_events_multi_pmu_add_or_add_pmu(struct parse_events_state *parse_state
16731687

16741688
/* Failure to add, assume event_or_pmu is an event name. */
16751689
zfree(listp);
1676-
if (!parse_events_multi_pmu_add(parse_state, event_or_pmu, const_parsed_terms, listp, loc))
1690+
if (!parse_events_multi_pmu_add(parse_state, event_or_pmu, PERF_COUNT_HW_MAX,
1691+
const_parsed_terms, listp, loc))
16771692
return 0;
16781693

16791694
if (asprintf(&help, "Unable to find PMU or event on a PMU of '%s'", event_or_pmu) < 0)

tools/perf/util/parse-events.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ struct evsel *parse_events__add_event(int idx, struct perf_event_attr *attr,
215215
struct perf_pmu *pmu);
216216

217217
int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
218-
const char *event_name,
218+
const char *event_name, u64 hw_config,
219219
const struct parse_events_terms *const_parsed_terms,
220220
struct list_head **listp, void *loc);
221221

tools/perf/util/parse-events.l

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,12 @@ do { \
100100
yyless(0); \
101101
} while (0)
102102

103-
static int sym(yyscan_t scanner, int type, int config)
103+
static int sym(yyscan_t scanner, int config)
104104
{
105105
YYSTYPE *yylval = parse_events_get_lval(scanner);
106106

107-
yylval->num = (type << 16) + config;
108-
return type == PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW;
107+
yylval->num = config;
108+
return PE_VALUE_SYM_SW;
109109
}
110110

111111
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)
124124
return PE_TERM;
125125
}
126126

127-
static int hw_term(yyscan_t scanner, int config)
127+
static int hw(yyscan_t scanner, int config)
128128
{
129129
YYSTYPE *yylval = parse_events_get_lval(scanner);
130130
char *text = parse_events_get_text(scanner);
131131

132-
yylval->hardware_term.str = strdup(text);
133-
yylval->hardware_term.num = PERF_TYPE_HARDWARE + config;
132+
yylval->hardware_event.str = strdup(text);
133+
yylval->hardware_event.num = config;
134134
return PE_TERM_HW;
135135
}
136136

@@ -246,16 +246,16 @@ percore { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_PERCORE); }
246246
aux-output { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT); }
247247
aux-sample-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE); }
248248
metric-id { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_METRIC_ID); }
249-
cpu-cycles|cycles { return hw_term(yyscanner, PERF_COUNT_HW_CPU_CYCLES); }
250-
stalled-cycles-frontend|idle-cycles-frontend { return hw_term(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
251-
stalled-cycles-backend|idle-cycles-backend { return hw_term(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
252-
instructions { return hw_term(yyscanner, PERF_COUNT_HW_INSTRUCTIONS); }
253-
cache-references { return hw_term(yyscanner, PERF_COUNT_HW_CACHE_REFERENCES); }
254-
cache-misses { return hw_term(yyscanner, PERF_COUNT_HW_CACHE_MISSES); }
255-
branch-instructions|branches { return hw_term(yyscanner, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
256-
branch-misses { return hw_term(yyscanner, PERF_COUNT_HW_BRANCH_MISSES); }
257-
bus-cycles { return hw_term(yyscanner, PERF_COUNT_HW_BUS_CYCLES); }
258-
ref-cycles { return hw_term(yyscanner, PERF_COUNT_HW_REF_CPU_CYCLES); }
249+
cpu-cycles|cycles { return hw(yyscanner, PERF_COUNT_HW_CPU_CYCLES); }
250+
stalled-cycles-frontend|idle-cycles-frontend { return hw(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
251+
stalled-cycles-backend|idle-cycles-backend { return hw(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
252+
instructions { return hw(yyscanner, PERF_COUNT_HW_INSTRUCTIONS); }
253+
cache-references { return hw(yyscanner, PERF_COUNT_HW_CACHE_REFERENCES); }
254+
cache-misses { return hw(yyscanner, PERF_COUNT_HW_CACHE_MISSES); }
255+
branch-instructions|branches { return hw(yyscanner, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
256+
branch-misses { return hw(yyscanner, PERF_COUNT_HW_BRANCH_MISSES); }
257+
bus-cycles { return hw(yyscanner, PERF_COUNT_HW_BUS_CYCLES); }
258+
ref-cycles { return hw(yyscanner, PERF_COUNT_HW_REF_CPU_CYCLES); }
259259
r{num_raw_hex} { return str(yyscanner, PE_RAW); }
260260
r0x{num_raw_hex} { return str(yyscanner, PE_RAW); }
261261
, { return ','; }
@@ -299,31 +299,31 @@ r0x{num_raw_hex} { return str(yyscanner, PE_RAW); }
299299
<<EOF>> { BEGIN(INITIAL); }
300300
}
301301

302-
cpu-cycles|cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
303-
stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
304-
stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
305-
instructions { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); }
306-
cache-references { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); }
307-
cache-misses { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); }
308-
branch-instructions|branches { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
309-
branch-misses { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); }
310-
bus-cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); }
311-
ref-cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); }
312-
cpu-clock { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); }
313-
task-clock { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); }
314-
page-faults|faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); }
315-
minor-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN); }
316-
major-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ); }
317-
context-switches|cs { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES); }
318-
cpu-migrations|migrations { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS); }
319-
alignment-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); }
320-
emulation-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }
321-
dummy { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); }
302+
cpu-cycles|cycles { return hw(yyscanner, PERF_COUNT_HW_CPU_CYCLES); }
303+
stalled-cycles-frontend|idle-cycles-frontend { return hw(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
304+
stalled-cycles-backend|idle-cycles-backend { return hw(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
305+
instructions { return hw(yyscanner, PERF_COUNT_HW_INSTRUCTIONS); }
306+
cache-references { return hw(yyscanner, PERF_COUNT_HW_CACHE_REFERENCES); }
307+
cache-misses { return hw(yyscanner, PERF_COUNT_HW_CACHE_MISSES); }
308+
branch-instructions|branches { return hw(yyscanner, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
309+
branch-misses { return hw(yyscanner, PERF_COUNT_HW_BRANCH_MISSES); }
310+
bus-cycles { return hw(yyscanner, PERF_COUNT_HW_BUS_CYCLES); }
311+
ref-cycles { return hw(yyscanner, PERF_COUNT_HW_REF_CPU_CYCLES); }
312+
cpu-clock { return sym(yyscanner, PERF_COUNT_SW_CPU_CLOCK); }
313+
task-clock { return sym(yyscanner, PERF_COUNT_SW_TASK_CLOCK); }
314+
page-faults|faults { return sym(yyscanner, PERF_COUNT_SW_PAGE_FAULTS); }
315+
minor-faults { return sym(yyscanner, PERF_COUNT_SW_PAGE_FAULTS_MIN); }
316+
major-faults { return sym(yyscanner, PERF_COUNT_SW_PAGE_FAULTS_MAJ); }
317+
context-switches|cs { return sym(yyscanner, PERF_COUNT_SW_CONTEXT_SWITCHES); }
318+
cpu-migrations|migrations { return sym(yyscanner, PERF_COUNT_SW_CPU_MIGRATIONS); }
319+
alignment-faults { return sym(yyscanner, PERF_COUNT_SW_ALIGNMENT_FAULTS); }
320+
emulation-faults { return sym(yyscanner, PERF_COUNT_SW_EMULATION_FAULTS); }
321+
dummy { return sym(yyscanner, PERF_COUNT_SW_DUMMY); }
322322
duration_time { return tool(yyscanner, PERF_TOOL_DURATION_TIME); }
323323
user_time { return tool(yyscanner, PERF_TOOL_USER_TIME); }
324324
system_time { return tool(yyscanner, PERF_TOOL_SYSTEM_TIME); }
325-
bpf-output { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_BPF_OUTPUT); }
326-
cgroup-switches { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CGROUP_SWITCHES); }
325+
bpf-output { return sym(yyscanner, PERF_COUNT_SW_BPF_OUTPUT); }
326+
cgroup-switches { return sym(yyscanner, PERF_COUNT_SW_CGROUP_SWITCHES); }
327327

328328
{lc_type} { return str(yyscanner, PE_LEGACY_CACHE); }
329329
{lc_type}-{lc_op_result} { return str(yyscanner, PE_LEGACY_CACHE); }

tools/perf/util/parse-events.y

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ static void free_list_evsel(struct list_head* list_evsel)
5555
%}
5656

5757
%token PE_START_EVENTS PE_START_TERMS
58-
%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_TERM
58+
%token PE_VALUE PE_VALUE_SYM_SW PE_TERM
5959
%token PE_VALUE_SYM_TOOL
6060
%token PE_EVENT_NAME
6161
%token PE_RAW PE_NAME
@@ -66,11 +66,9 @@ static void free_list_evsel(struct list_head* list_evsel)
6666
%token PE_DRV_CFG_TERM
6767
%token PE_TERM_HW
6868
%type <num> PE_VALUE
69-
%type <num> PE_VALUE_SYM_HW
7069
%type <num> PE_VALUE_SYM_SW
7170
%type <num> PE_VALUE_SYM_TOOL
7271
%type <term_type> PE_TERM
73-
%type <num> value_sym
7472
%type <str> PE_RAW
7573
%type <str> PE_NAME
7674
%type <str> PE_LEGACY_CACHE
@@ -87,6 +85,7 @@ static void free_list_evsel(struct list_head* list_evsel)
8785
%type <list_terms> opt_pmu_config
8886
%destructor { parse_events_terms__delete ($$); } <list_terms>
8987
%type <list_evsel> event_pmu
88+
%type <list_evsel> event_legacy_hardware
9089
%type <list_evsel> event_legacy_symbol
9190
%type <list_evsel> event_legacy_cache
9291
%type <list_evsel> event_legacy_mem
@@ -104,8 +103,8 @@ static void free_list_evsel(struct list_head* list_evsel)
104103
%destructor { free_list_evsel ($$); } <list_evsel>
105104
%type <tracepoint_name> tracepoint_name
106105
%destructor { free ($$.sys); free ($$.event); } <tracepoint_name>
107-
%type <hardware_term> PE_TERM_HW
108-
%destructor { free ($$.str); } <hardware_term>
106+
%type <hardware_event> PE_TERM_HW
107+
%destructor { free ($$.str); } <hardware_event>
109108

110109
%union
111110
{
@@ -119,10 +118,10 @@ static void free_list_evsel(struct list_head* list_evsel)
119118
char *sys;
120119
char *event;
121120
} tracepoint_name;
122-
struct hardware_term {
121+
struct hardware_event {
123122
char *str;
124123
u64 num;
125-
} hardware_term;
124+
} hardware_event;
126125
}
127126
%%
128127

@@ -263,6 +262,7 @@ PE_EVENT_NAME event_def
263262
event_def
264263

265264
event_def: event_pmu |
265+
event_legacy_hardware |
266266
event_legacy_symbol |
267267
event_legacy_cache sep_dc |
268268
event_legacy_mem sep_dc |
@@ -289,7 +289,7 @@ PE_NAME sep_dc
289289
struct list_head *list;
290290
int err;
291291

292-
err = parse_events_multi_pmu_add(_parse_state, $1, NULL, &list, &@1);
292+
err = parse_events_multi_pmu_add(_parse_state, $1, PERF_COUNT_HW_MAX, NULL, &list, &@1);
293293
if (err < 0) {
294294
struct parse_events_state *parse_state = _parse_state;
295295
struct parse_events_error *error = parse_state->error;
@@ -305,24 +305,45 @@ PE_NAME sep_dc
305305
$$ = list;
306306
}
307307

308-
value_sym:
309-
PE_VALUE_SYM_HW
308+
event_legacy_hardware:
309+
PE_TERM_HW opt_pmu_config
310+
{
311+
/* List of created evsels. */
312+
struct list_head *list = NULL;
313+
int err = parse_events_multi_pmu_add(_parse_state, $1.str, $1.num, $2, &list, &@1);
314+
315+
free($1.str);
316+
parse_events_terms__delete($2);
317+
if (err)
318+
PE_ABORT(err);
319+
320+
$$ = list;
321+
}
310322
|
311-
PE_VALUE_SYM_SW
323+
PE_TERM_HW sep_dc
324+
{
325+
struct list_head *list;
326+
int err;
327+
328+
err = parse_events_multi_pmu_add(_parse_state, $1.str, $1.num, NULL, &list, &@1);
329+
free($1.str);
330+
if (err)
331+
PE_ABORT(err);
332+
$$ = list;
333+
}
312334

313335
event_legacy_symbol:
314-
value_sym '/' event_config '/'
336+
PE_VALUE_SYM_SW '/' event_config '/'
315337
{
316338
struct list_head *list;
317-
int type = $1 >> 16;
318-
int config = $1 & 255;
319339
int err;
320-
bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);
321340

322341
list = alloc_list();
323342
if (!list)
324343
YYNOMEM;
325-
err = parse_events_add_numeric(_parse_state, list, type, config, $3, wildcard);
344+
err = parse_events_add_numeric(_parse_state, list,
345+
/*type=*/PERF_TYPE_SOFTWARE, /*config=*/$1,
346+
$3, /*wildcard=*/false);
326347
parse_events_terms__delete($3);
327348
if (err) {
328349
free_list_evsel(list);
@@ -331,18 +352,17 @@ value_sym '/' event_config '/'
331352
$$ = list;
332353
}
333354
|
334-
value_sym sep_slash_slash_dc
355+
PE_VALUE_SYM_SW sep_slash_slash_dc
335356
{
336357
struct list_head *list;
337-
int type = $1 >> 16;
338-
int config = $1 & 255;
339-
bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);
340358
int err;
341359

342360
list = alloc_list();
343361
if (!list)
344362
YYNOMEM;
345-
err = parse_events_add_numeric(_parse_state, list, type, config, /*head_config=*/NULL, wildcard);
363+
err = parse_events_add_numeric(_parse_state, list,
364+
/*type=*/PERF_TYPE_SOFTWARE, /*config=*/$1,
365+
/*head_config=*/NULL, /*wildcard=*/false);
346366
if (err)
347367
PE_ABORT(err);
348368
$$ = list;

0 commit comments

Comments
 (0)