Commit b7b76f60 authored by Ian Rogers's avatar Ian Rogers Committed by Namhyung Kim
Browse files

perf parse-events: Fix legacy cache events if event is duplicated in a PMU



The term list when adding an event to a PMU is expected to have the
event name for the alias lookup. Also, set found_supported so that
-EINVAL isn't returned.

Fixes: 62593394 ("perf parse-events: Legacy cache names on all
PMUs and lower priority")

Tested-by: default avatarThomas Richter <tmricht@linux.ibm.com>
Signed-off-by: default avatarIan Rogers <irogers@google.com>
Tested-by: default avatarJames Clark <james.clark@linaro.org>
Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
parent 2a67955d
Loading
Loading
Loading
Loading
+27 −1
Original line number Diff line number Diff line
@@ -475,8 +475,10 @@ static int parse_events_add_pmu(struct parse_events_state *parse_state,

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)
			   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);
@@ -497,12 +499,36 @@ int parse_events_add_cache(struct list_head *list, int *idx, const char *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);
+2 −1
Original line number Diff line number Diff line
@@ -237,7 +237,8 @@ int parse_events_add_numeric(struct parse_events_state *parse_state,
			     bool wildcard);
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);
			   struct parse_events_terms *parsed_terms,
			   void *loc);
int parse_events__decode_legacy_cache(const char *name, int pmu_type, __u64 *config);
int parse_events_add_breakpoint(struct parse_events_state *parse_state,
				struct list_head *list,
+1 −1
Original line number Diff line number Diff line
@@ -353,7 +353,7 @@ PE_LEGACY_CACHE opt_event_config
	if (!list)
		YYNOMEM;

	err = parse_events_add_cache(list, &parse_state->idx, $1, parse_state, $2);
	err = parse_events_add_cache(list, &parse_state->idx, $1, parse_state, $2, &@1);

	parse_events_terms__delete($2);
	free($1);