static int parse_events_add_pmu(struct parse_events_state *parse_state,
struct list_head *list, struct perf_pmu *pmu,
const struct parse_events_terms *const_parsed_terms,
- struct evsel *first_wildcard_match, u64 alternate_hw_config);
-
-int parse_events_add_cache(struct list_head *list, int *idx, const char *name,
- struct parse_events_state *parse_state,
- struct parse_events_terms *parsed_terms,
- void *loc_)
-{
- YYLTYPE *loc = loc_;
- struct perf_pmu *pmu = NULL;
- bool found_supported = false;
- const char *config_name = get_config_name(parsed_terms);
- const char *metric_id = get_config_metric_id(parsed_terms);
- struct perf_cpu_map *cpus = get_config_cpu(parsed_terms, parse_state->fake_pmu);
- int ret = 0;
- struct evsel *first_wildcard_match = NULL;
-
- while ((pmu = perf_pmus__scan_for_event(pmu, name)) != NULL) {
- LIST_HEAD(config_terms);
- struct perf_event_attr attr;
-
- if (parse_events__filter_pmu(parse_state, pmu))
- continue;
-
- if (perf_pmu__have_event(pmu, name)) {
- /*
- * The PMU has the event so add as not a legacy cache
- * event.
- */
- struct parse_events_terms temp_terms;
- struct parse_events_term *term;
- char *config = strdup(name);
-
- if (!config)
- goto out_err;
-
- parse_events_terms__init(&temp_terms);
- if (!parsed_terms)
- parsed_terms = &temp_terms;
-
- if (parse_events_term__num(&term,
- PARSE_EVENTS__TERM_TYPE_USER,
- config, /*num=*/1, /*novalue=*/true,
- loc, /*loc_val=*/NULL) < 0) {
- zfree(&config);
- goto out_err;
- }
- list_add(&term->list, &parsed_terms->terms);
-
- ret = parse_events_add_pmu(parse_state, list, pmu,
- parsed_terms,
- first_wildcard_match,
- /*alternate_hw_config=*/PERF_COUNT_HW_MAX);
- list_del_init(&term->list);
- parse_events_term__delete(term);
- parse_events_terms__exit(&temp_terms);
- if (ret)
- goto out_err;
- found_supported = true;
- if (first_wildcard_match == NULL)
- first_wildcard_match =
- container_of(list->prev, struct evsel, core.node);
- continue;
- }
-
- if (!pmu->is_core) {
- /* Legacy cache events are only supported by core PMUs. */
- continue;
- }
-
- memset(&attr, 0, sizeof(attr));
- attr.type = PERF_TYPE_HW_CACHE;
-
- ret = parse_events__decode_legacy_cache(name, pmu->type, &attr.config);
- if (ret)
- return ret;
-
- found_supported = true;
-
- if (parsed_terms) {
- if (config_attr(&attr, parsed_terms, parse_state, config_term_common)) {
- ret = -EINVAL;
- goto out_err;
- }
- if (get_config_terms(parsed_terms, &config_terms)) {
- ret = -ENOMEM;
- goto out_err;
- }
- }
-
- if (__add_event(list, idx, &attr, /*init_attr*/true, config_name ?: name,
- metric_id, pmu, &config_terms, first_wildcard_match,
- cpus, /*alternate_hw_config=*/PERF_COUNT_HW_MAX) == NULL)
- ret = -ENOMEM;
-
- if (first_wildcard_match == NULL)
- first_wildcard_match = container_of(list->prev, struct evsel, core.node);
- free_config_terms(&config_terms);
- if (ret)
- goto out_err;
- }
-out_err:
- perf_cpu_map__put(cpus);
- return found_supported ? 0 : -EINVAL;
-}
+ struct evsel *first_wildcard_match);
static void tracepoint_error(struct parse_events_error *e, int err,
const char *sys, const char *name, int column)
[PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE] = "aux-sample-size",
[PARSE_EVENTS__TERM_TYPE_METRIC_ID] = "metric-id",
[PARSE_EVENTS__TERM_TYPE_RAW] = "raw",
- [PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE] = "legacy-cache",
- [PARSE_EVENTS__TERM_TYPE_HARDWARE] = "hardware",
[PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG] = "legacy-hardware-config",
[PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG] = "legacy-cache-config",
[PARSE_EVENTS__TERM_TYPE_CPU] = "cpu",
case PARSE_EVENTS__TERM_TYPE_AUX_ACTION:
case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE:
case PARSE_EVENTS__TERM_TYPE_RAW:
- case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE:
- case PARSE_EVENTS__TERM_TYPE_HARDWARE:
case PARSE_EVENTS__TERM_TYPE_RATIO_TO_PREV:
case PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG:
case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG:
break;
case PARSE_EVENTS__TERM_TYPE_DRV_CFG:
case PARSE_EVENTS__TERM_TYPE_USER:
- case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE:
- case PARSE_EVENTS__TERM_TYPE_HARDWARE:
case PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG:
case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG:
default:
attr->type = PERF_TYPE_HW_CACHE;
return 0;
}
- if (term->type_term == PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE) {
- struct perf_pmu *pmu = perf_pmus__find_by_type(attr->type);
-
- if (!pmu) {
- char *err_str;
-
- if (asprintf(&err_str, "Failed to find PMU for type %d", attr->type) >= 0)
- parse_events_error__handle(parse_state->error, term->err_term,
- err_str, /*help=*/NULL);
- return -EINVAL;
- }
- /*
- * Rewrite the PMU event to a legacy cache one unless the PMU
- * doesn't support legacy cache events or the event is present
- * within the PMU.
- */
- if (perf_pmu__supports_legacy_cache(pmu) &&
- !perf_pmu__have_event(pmu, term->config)) {
- attr->type = PERF_TYPE_HW_CACHE;
- return parse_events__decode_legacy_cache(term->config, pmu->type,
- &attr->config);
- } else {
- term->type_term = PARSE_EVENTS__TERM_TYPE_USER;
- term->no_value = true;
- }
- }
- if (term->type_term == PARSE_EVENTS__TERM_TYPE_HARDWARE) {
- struct perf_pmu *pmu = perf_pmus__find_by_type(attr->type);
-
- if (!pmu) {
- char *err_str;
-
- if (asprintf(&err_str, "Failed to find PMU for type %d", attr->type) >= 0)
- parse_events_error__handle(parse_state->error, term->err_term,
- err_str, /*help=*/NULL);
- return -EINVAL;
- }
- /*
- * If the PMU has a sysfs or json event prefer it over
- * legacy. ARM requires this.
- */
- if (perf_pmu__have_event(pmu, term->config)) {
- term->type_term = PARSE_EVENTS__TERM_TYPE_USER;
- term->no_value = true;
- term->alternate_hw_config = true;
- } else {
- attr->type = PERF_TYPE_HARDWARE;
- attr->config = term->val.num;
- if (perf_pmus__supports_extended_type())
- attr->config |= (__u64)pmu->type << PERF_PMU_TYPE_SHIFT;
- }
- return 0;
- }
if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER ||
term->type_term == PARSE_EVENTS__TERM_TYPE_DRV_CFG) {
/*
case PARSE_EVENTS__TERM_TYPE_PERCORE:
case PARSE_EVENTS__TERM_TYPE_METRIC_ID:
case PARSE_EVENTS__TERM_TYPE_RAW:
- case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE:
- case PARSE_EVENTS__TERM_TYPE_HARDWARE:
case PARSE_EVENTS__TERM_TYPE_CPU:
case PARSE_EVENTS__TERM_TYPE_RATIO_TO_PREV:
default:
case PARSE_EVENTS__TERM_TYPE_NAME:
case PARSE_EVENTS__TERM_TYPE_METRIC_ID:
case PARSE_EVENTS__TERM_TYPE_RAW:
- case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE:
- case PARSE_EVENTS__TERM_TYPE_HARDWARE:
case PARSE_EVENTS__TERM_TYPE_CPU:
default:
break;
case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE:
case PARSE_EVENTS__TERM_TYPE_METRIC_ID:
case PARSE_EVENTS__TERM_TYPE_RAW:
- case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE:
- case PARSE_EVENTS__TERM_TYPE_HARDWARE:
case PARSE_EVENTS__TERM_TYPE_CPU:
case PARSE_EVENTS__TERM_TYPE_RATIO_TO_PREV:
default:
static int parse_events_add_pmu(struct parse_events_state *parse_state,
struct list_head *list, struct perf_pmu *pmu,
const struct parse_events_terms *const_parsed_terms,
- struct evsel *first_wildcard_match, u64 alternate_hw_config)
+ struct evsel *first_wildcard_match)
{
+ u64 alternate_hw_config = PERF_COUNT_HW_MAX;
struct perf_event_attr attr;
struct perf_pmu_info info;
struct evsel *evsel;
}
int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
- const char *event_name, u64 hw_config,
+ const char *event_name,
const struct parse_events_terms *const_parsed_terms,
struct list_head **listp, void *loc_)
{
continue;
if (!parse_events_add_pmu(parse_state, list, pmu,
- &parsed_terms, first_wildcard_match, hw_config)) {
+ &parsed_terms, first_wildcard_match)) {
struct strbuf sb;
strbuf_init(&sb, /*hint=*/ 0);
if (parse_state->fake_pmu) {
if (!parse_events_add_pmu(parse_state, list, perf_pmus__fake_pmu(), &parsed_terms,
- first_wildcard_match, hw_config)) {
+ first_wildcard_match)) {
struct strbuf sb;
strbuf_init(&sb, /*hint=*/ 0);
/* Attempt to add to list assuming event_or_pmu is a PMU name. */
pmu = perf_pmus__find(event_or_pmu);
if (pmu && !parse_events_add_pmu(parse_state, *listp, pmu, const_parsed_terms,
- first_wildcard_match,
- /*alternate_hw_config=*/PERF_COUNT_HW_MAX))
+ first_wildcard_match))
return 0;
if (parse_state->fake_pmu) {
if (!parse_events_add_pmu(parse_state, *listp, perf_pmus__fake_pmu(),
const_parsed_terms,
- first_wildcard_match,
- /*alternate_hw_config=*/PERF_COUNT_HW_MAX))
+ first_wildcard_match))
return 0;
}
if (!parse_events_add_pmu(parse_state, *listp, pmu,
const_parsed_terms,
- first_wildcard_match,
- /*alternate_hw_config=*/PERF_COUNT_HW_MAX)) {
+ first_wildcard_match)) {
ok++;
parse_state->wild_card_pmus = true;
}
/* Failure to add, assume event_or_pmu is an event name. */
zfree(listp);
- if (!parse_events_multi_pmu_add(parse_state, event_or_pmu, PERF_COUNT_HW_MAX,
+ if (!parse_events_multi_pmu_add(parse_state, event_or_pmu,
const_parsed_terms, listp, loc))
return 0;
return token;
}
-static int lc_str(yyscan_t scanner, const struct parse_events_state *state)
-{
- return str(scanner, state->match_legacy_cache_terms ? PE_LEGACY_CACHE : PE_NAME);
-}
-
/*
* This function is called when the parser gets two kind of input:
*
yyless(0); \
} while (0)
-static int sym(yyscan_t scanner, int config)
-{
- YYSTYPE *yylval = parse_events_get_lval(scanner);
-
- yylval->num = config;
- return PE_VALUE_SYM_HW;
-}
-
static int term(yyscan_t scanner, enum parse_events__term_type type)
{
YYSTYPE *yylval = parse_events_get_lval(scanner);
return PE_TERM;
}
-static int hw_term(yyscan_t scanner, int config)
-{
- YYSTYPE *yylval = parse_events_get_lval(scanner);
- char *text = parse_events_get_text(scanner);
-
- yylval->hardware_term.str = strdup(text);
- yylval->hardware_term.num = PERF_TYPE_HARDWARE + config;
- return PE_TERM_HW;
-}
-
static void modifiers_error(struct parse_events_state *parse_state, yyscan_t scanner,
int pos, char mod_char, const char *mod_name)
{
*/
modifier_event [ukhpPGHSDIWebRX]{1,17}
modifier_bp [rwx]{1,3}
-lc_type (L1-dcache|l1-d|l1d|L1-data|L1-icache|l1-i|l1i|L1-instruction|LLC|L2|dTLB|d-tlb|Data-TLB|iTLB|i-tlb|Instruction-TLB|branch|branches|bpu|btb|bpc|node)
-lc_op_result (load|loads|read|store|stores|write|prefetch|prefetches|speculative-read|speculative-load|refs|Reference|ops|access|misses|miss)
digit [0-9]
non_digit [^0-9]
ratio-to-prev { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_RATIO_TO_PREV); }
legacy-hardware-config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG); }
legacy-cache-config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE_CONFIG); }
-cpu-cycles|cycles { return hw_term(yyscanner, PERF_COUNT_HW_CPU_CYCLES); }
-stalled-cycles-frontend|idle-cycles-frontend { return hw_term(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
-stalled-cycles-backend|idle-cycles-backend { return hw_term(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
-instructions { return hw_term(yyscanner, PERF_COUNT_HW_INSTRUCTIONS); }
-cache-references { return hw_term(yyscanner, PERF_COUNT_HW_CACHE_REFERENCES); }
-cache-misses { return hw_term(yyscanner, PERF_COUNT_HW_CACHE_MISSES); }
-branch-instructions|branches { return hw_term(yyscanner, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
-branch-misses { return hw_term(yyscanner, PERF_COUNT_HW_BRANCH_MISSES); }
-bus-cycles { return hw_term(yyscanner, PERF_COUNT_HW_BUS_CYCLES); }
-ref-cycles { return hw_term(yyscanner, PERF_COUNT_HW_REF_CPU_CYCLES); }
r{num_raw_hex} { return str(yyscanner, PE_RAW); }
r0x{num_raw_hex} { return str(yyscanner, PE_RAW); }
, { return ','; }
"/" { BEGIN(INITIAL); return '/'; }
-{lc_type} { return lc_str(yyscanner, _parse_state); }
-{lc_type}-{lc_op_result} { return lc_str(yyscanner, _parse_state); }
-{lc_type}-{lc_op_result}-{lc_op_result} { return lc_str(yyscanner, _parse_state); }
{num_dec} { return value(_parse_state, yyscanner, 10); }
{num_hex} { return value(_parse_state, yyscanner, 16); }
{term_name} { return str(yyscanner, PE_NAME); }
<<EOF>> { BEGIN(INITIAL); }
}
-cpu-cycles|cycles { return sym(yyscanner, PERF_COUNT_HW_CPU_CYCLES); }
-stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
-stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
-instructions { return sym(yyscanner, PERF_COUNT_HW_INSTRUCTIONS); }
-cache-references { return sym(yyscanner, PERF_COUNT_HW_CACHE_REFERENCES); }
-cache-misses { return sym(yyscanner, PERF_COUNT_HW_CACHE_MISSES); }
-branch-instructions|branches { return sym(yyscanner, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
-branch-misses { return sym(yyscanner, PERF_COUNT_HW_BRANCH_MISSES); }
-bus-cycles { return sym(yyscanner, PERF_COUNT_HW_BUS_CYCLES); }
-ref-cycles { return sym(yyscanner, PERF_COUNT_HW_REF_CPU_CYCLES); }
-
-{lc_type} { return str(yyscanner, PE_LEGACY_CACHE); }
-{lc_type}-{lc_op_result} { return str(yyscanner, PE_LEGACY_CACHE); }
-{lc_type}-{lc_op_result}-{lc_op_result} { return str(yyscanner, PE_LEGACY_CACHE); }
mem: { BEGIN(mem); return PE_PREFIX_MEM; }
r{num_raw_hex} { return str(yyscanner, PE_RAW); }
{num_dec} { return value(_parse_state, yyscanner, 10); }
%}
%token PE_START_EVENTS PE_START_TERMS
-%token PE_VALUE PE_VALUE_SYM_HW PE_TERM
+%token PE_VALUE PE_TERM
%token PE_EVENT_NAME
%token PE_RAW PE_NAME
%token PE_MODIFIER_EVENT PE_MODIFIER_BP PE_BP_COLON PE_BP_SLASH
-%token PE_LEGACY_CACHE
%token PE_PREFIX_MEM
%token PE_ERROR
%token PE_DRV_CFG_TERM
-%token PE_TERM_HW
%type <num> PE_VALUE
-%type <num> PE_VALUE_SYM_HW
%type <mod> PE_MODIFIER_EVENT
%type <term_type> PE_TERM
%type <str> PE_RAW
%type <str> PE_NAME
-%type <str> PE_LEGACY_CACHE
%type <str> PE_MODIFIER_BP
%type <str> PE_EVENT_NAME
%type <str> PE_DRV_CFG_TERM
%type <list_terms> opt_pmu_config
%destructor { parse_events_terms__delete ($$); } <list_terms>
%type <list_evsel> event_pmu
-%type <list_evsel> event_legacy_symbol
-%type <list_evsel> event_legacy_cache
%type <list_evsel> event_legacy_mem
%type <list_evsel> event_legacy_tracepoint
%type <list_evsel> event_legacy_numeric
%destructor { free_list_evsel ($$); } <list_evsel>
%type <tracepoint_name> tracepoint_name
%destructor { free ($$.sys); free ($$.event); } <tracepoint_name>
-%type <hardware_term> PE_TERM_HW
-%destructor { free ($$.str); } <hardware_term>
%union
{
char *sys;
char *event;
} tracepoint_name;
- struct hardware_term {
- char *str;
- u64 num;
- } hardware_term;
}
%%
event_def
event_def: event_pmu |
- event_legacy_symbol |
- event_legacy_cache sep_dc |
event_legacy_mem sep_dc |
event_legacy_tracepoint sep_dc |
event_legacy_numeric sep_dc |
struct list_head *list;
int err;
- err = parse_events_multi_pmu_add(_parse_state, $1, PERF_COUNT_HW_MAX, NULL, &list, &@1);
+ err = parse_events_multi_pmu_add(_parse_state, $1, /*const_parsed_terms*/NULL, &list, &@1);
if (err < 0) {
struct parse_events_state *parse_state = _parse_state;
struct parse_events_error *error = parse_state->error;
$$ = list;
}
-event_legacy_symbol:
-PE_VALUE_SYM_HW '/' event_config '/'
-{
- struct list_head *list;
- int err;
-
- list = alloc_list();
- if (!list)
- YYNOMEM;
- err = parse_events_add_numeric(_parse_state, list,
- PERF_TYPE_HARDWARE, $1,
- $3,
- /*wildcard=*/true);
- parse_events_terms__delete($3);
- if (err) {
- free_list_evsel(list);
- PE_ABORT(err);
- }
- $$ = list;
-}
-|
-PE_VALUE_SYM_HW sep_slash_slash_dc
-{
- struct list_head *list;
- int err;
-
- list = alloc_list();
- if (!list)
- YYNOMEM;
- err = parse_events_add_numeric(_parse_state, list,
- PERF_TYPE_HARDWARE, $1,
- /*head_config=*/NULL,
- /*wildcard=*/true);
- if (err)
- PE_ABORT(err);
- $$ = list;
-}
-
-event_legacy_cache:
-PE_LEGACY_CACHE opt_event_config
-{
- struct parse_events_state *parse_state = _parse_state;
- struct list_head *list;
- int err;
-
- list = alloc_list();
- if (!list)
- YYNOMEM;
-
- err = parse_events_add_cache(list, &parse_state->idx, $1, parse_state, $2, &@1);
-
- parse_events_terms__delete($2);
- free($1);
- if (err) {
- free_list_evsel(list);
- PE_ABORT(err);
- }
- $$ = list;
-}
-
event_legacy_mem:
PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config
{
$$ = head;
}
-name_or_raw: PE_RAW | PE_NAME | PE_LEGACY_CACHE
-|
-PE_TERM_HW
-{
- $$ = $1.str;
-}
+name_or_raw: PE_RAW | PE_NAME
event_term:
PE_RAW
$$ = term;
}
|
-PE_LEGACY_CACHE
-{
- struct parse_events_term *term;
- int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE,
- $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL);
-
- if (err) {
- free($1);
- PE_ABORT(err);
- }
- $$ = term;
-}
-|
PE_NAME
{
struct parse_events_term *term;
$$ = term;
}
|
-PE_TERM_HW
-{
- struct parse_events_term *term;
- int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_HARDWARE,
- $1.str, $1.num & 255, /*novalue=*/false,
- &@1, /*loc_val=*/NULL);
-
- if (err) {
- free($1.str);
- PE_ABORT(err);
- }
- $$ = term;
-}
-|
PE_TERM '=' name_or_raw
{
struct parse_events_term *term;
sep_dc: ':' |
-sep_slash_slash_dc: '/' '/' | ':' |
-
%%
void parse_events_error(YYLTYPE *loc, void *_parse_state,