forked from Minki/linux
perf tools: Add fake pmu support
Add a way to create a pmu event without the actual PMU being in place. This way we can test metrics defined for any processor. The interface is to define fake_pmu in struct parse_events_state data. It will be used only in tests via special interface function added in following changes. Signed-off-by: Jiri Olsa <jolsa@kernel.org> Acked-by: Ian Rogers <irogers@google.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Michael Petlan <mpetlan@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lore.kernel.org/lkml/20200602214741.1218986-2-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
a1f8bc95c3
commit
387ad33fe7
@ -1450,7 +1450,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
|
||||
fprintf(stderr, "' that may result in non-fatal errors\n");
|
||||
}
|
||||
|
||||
pmu = perf_pmu__find(name);
|
||||
pmu = parse_state->fake_pmu ?: perf_pmu__find(name);
|
||||
if (!pmu) {
|
||||
char *err_str;
|
||||
|
||||
@ -1483,7 +1483,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
|
||||
}
|
||||
}
|
||||
|
||||
if (perf_pmu__check_alias(pmu, head_config, &info))
|
||||
if (!parse_state->fake_pmu && perf_pmu__check_alias(pmu, head_config, &info))
|
||||
return -EINVAL;
|
||||
|
||||
if (verbose > 1) {
|
||||
@ -1516,7 +1516,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
|
||||
if (pmu->default_config && get_config_chgs(pmu, head_config, &config_terms))
|
||||
return -ENOMEM;
|
||||
|
||||
if (perf_pmu__config(pmu, &attr, head_config, parse_state->error)) {
|
||||
if (!parse_state->fake_pmu && perf_pmu__config(pmu, &attr, head_config, parse_state->error)) {
|
||||
struct evsel_config_term *pos, *tmp;
|
||||
|
||||
list_for_each_entry_safe(pos, tmp, &config_terms, list) {
|
||||
|
@ -127,9 +127,10 @@ struct parse_events_state {
|
||||
int idx;
|
||||
int nr_groups;
|
||||
struct parse_events_error *error;
|
||||
struct evlist *evlist;
|
||||
struct evlist *evlist;
|
||||
struct list_head *terms;
|
||||
int stoken;
|
||||
struct perf_pmu *fake_pmu;
|
||||
};
|
||||
|
||||
void parse_events__handle_error(struct parse_events_error *err, int idx,
|
||||
|
@ -129,12 +129,16 @@ do { \
|
||||
yyless(0); \
|
||||
} while (0)
|
||||
|
||||
static int pmu_str_check(yyscan_t scanner)
|
||||
static int pmu_str_check(yyscan_t scanner, struct parse_events_state *parse_state)
|
||||
{
|
||||
YYSTYPE *yylval = parse_events_get_lval(scanner);
|
||||
char *text = parse_events_get_text(scanner);
|
||||
|
||||
yylval->str = strdup(text);
|
||||
|
||||
if (parse_state->fake_pmu)
|
||||
return PE_PMU_EVENT_FAKE;
|
||||
|
||||
switch (perf_pmu__parse_check(text)) {
|
||||
case PMU_EVENT_SYMBOL_PREFIX:
|
||||
return PE_PMU_EVENT_PRE;
|
||||
@ -376,7 +380,7 @@ r{num_raw_hex} { return raw(yyscanner); }
|
||||
{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); }
|
||||
{bpf_object} { if (!isbpf(yyscanner)) { USER_REJECT }; return str(yyscanner, PE_BPF_OBJECT); }
|
||||
{bpf_source} { if (!isbpf(yyscanner)) { USER_REJECT }; return str(yyscanner, PE_BPF_SOURCE); }
|
||||
{name} { return pmu_str_check(yyscanner); }
|
||||
{name} { return pmu_str_check(yyscanner, _parse_state); }
|
||||
{name_tag} { return str(yyscanner, PE_NAME); }
|
||||
"/" { BEGIN(config); return '/'; }
|
||||
- { return '-'; }
|
||||
|
@ -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
|
||||
%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF 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
|
||||
%type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT PE_PMU_EVENT_FAKE
|
||||
%type <str> PE_DRV_CFG_TERM
|
||||
%destructor { free ($$); } <str>
|
||||
%type <term> event_term
|
||||
@ -356,6 +356,43 @@ PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc
|
||||
YYABORT;
|
||||
$$ = list;
|
||||
}
|
||||
|
|
||||
PE_PMU_EVENT_FAKE sep_dc
|
||||
{
|
||||
struct list_head *list;
|
||||
int err;
|
||||
|
||||
list = alloc_list();
|
||||
if (!list)
|
||||
YYABORT;
|
||||
|
||||
err = parse_events_add_pmu(_parse_state, list, $1, NULL, false, false);
|
||||
free($1);
|
||||
if (err < 0) {
|
||||
free(list);
|
||||
YYABORT;
|
||||
}
|
||||
$$ = list;
|
||||
}
|
||||
|
|
||||
PE_PMU_EVENT_FAKE opt_pmu_config
|
||||
{
|
||||
struct list_head *list;
|
||||
int err;
|
||||
|
||||
list = alloc_list();
|
||||
if (!list)
|
||||
YYABORT;
|
||||
|
||||
err = parse_events_add_pmu(_parse_state, list, $1, $2, false, false);
|
||||
free($1);
|
||||
parse_events_terms__delete($2);
|
||||
if (err < 0) {
|
||||
free(list);
|
||||
YYABORT;
|
||||
}
|
||||
$$ = list;
|
||||
}
|
||||
|
||||
value_sym:
|
||||
PE_VALUE_SYM_HW
|
||||
|
Loading…
Reference in New Issue
Block a user