Skip to content

Commit

Permalink
perf tools: Fix pattern matching for same substring in different PMU …
Browse files Browse the repository at this point in the history
…type

Some different PMU types may have the same substring. For example, on
Icelake server we have PMU types "uncore_imc" and
"uncore_imc_free_running". Both PMU types have the substring
"uncore_imc".  But the parser wrongly thinks they are the same PMU type.

We enable an imc event,
perf stat -e uncore_imc/event=0xe3/ -a -- sleep 1

Perf actually expands the event to:

  uncore_imc_0/event=0xe3/
  uncore_imc_1/event=0xe3/
  uncore_imc_2/event=0xe3/
  uncore_imc_3/event=0xe3/
  uncore_imc_4/event=0xe3/
  uncore_imc_5/event=0xe3/
  uncore_imc_6/event=0xe3/
  uncore_imc_7/event=0xe3/
  uncore_imc_free_running_0/event=0xe3/
  uncore_imc_free_running_1/event=0xe3/
  uncore_imc_free_running_3/event=0xe3/
  uncore_imc_free_running_4/event=0xe3/

That's because the "uncore_imc_free_running" matches the
pattern "uncore_imc*".

Now we check that the last characters of PMU name is '_<digit>'.

For example, for pattern "uncore_imc*", "uncore_imc_0" is parsed ok, but
"uncore_imc_free_running_0" fails.

Fixes: b2b9d3a ("perf pmu: Support wildcards on pmu name in dynamic pmu events")
Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Cc: Agustin Vega-Frias <agustinv@codeaurora.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lore.kernel.org/lkml/20210701064253.1175-1-yao.jin@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
  • Loading branch information
Jin Yao authored and acmel committed Jul 9, 2021
1 parent b91e549 commit c47a559
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 2 deletions.
2 changes: 1 addition & 1 deletion tools/perf/util/parse-events.y
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ event_pmu_name opt_pmu_config
if (!strncmp(name, "uncore_", 7) &&
strncmp($1, "uncore_", 7))
name += 7;
if (!fnmatch(pattern, name, 0)) {
if (!perf_pmu__match(pattern, name, $1)) {
if (parse_events_copy_term_list(orig_terms, &terms))
CLEANUP_YYABORT;
if (!parse_events_add_pmu(_parse_state, list, pmu->name, terms, true, false))
Expand Down
36 changes: 35 additions & 1 deletion tools/perf/util/pmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <linux/compiler.h>
#include <linux/string.h>
#include <linux/zalloc.h>
#include <linux/ctype.h>
#include <subcmd/pager.h>
#include <sys/types.h>
#include <errno.h>
Expand All @@ -17,6 +18,7 @@
#include <locale.h>
#include <regex.h>
#include <perf/cpumap.h>
#include <fnmatch.h>
#include "debug.h"
#include "evsel.h"
#include "pmu.h"
Expand Down Expand Up @@ -740,6 +742,27 @@ struct pmu_events_map *__weak pmu_events_map__find(void)
return perf_pmu__find_map(NULL);
}

static bool perf_pmu__valid_suffix(char *pmu_name, char *tok)
{
char *p;

if (strncmp(pmu_name, tok, strlen(tok)))
return false;

p = pmu_name + strlen(tok);
if (*p == 0)
return true;

if (*p != '_')
return false;

++p;
if (*p == 0 || !isdigit(*p))
return false;

return true;
}

bool pmu_uncore_alias_match(const char *pmu_name, const char *name)
{
char *tmp = NULL, *tok, *str;
Expand Down Expand Up @@ -768,7 +791,7 @@ bool pmu_uncore_alias_match(const char *pmu_name, const char *name)
*/
for (; tok; name += strlen(tok), tok = strtok_r(NULL, ",", &tmp)) {
name = strstr(name, tok);
if (!name) {
if (!name || !perf_pmu__valid_suffix((char *)name, tok)) {
res = false;
goto out;
}
Expand Down Expand Up @@ -1872,3 +1895,14 @@ bool perf_pmu__has_hybrid(void)

return !list_empty(&perf_pmu__hybrid_pmus);
}

int perf_pmu__match(char *pattern, char *name, char *tok)
{
if (fnmatch(pattern, name, 0))
return -1;

if (tok && !perf_pmu__valid_suffix(name, tok))
return -1;

return 0;
}
1 change: 1 addition & 0 deletions tools/perf/util/pmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,5 +133,6 @@ void perf_pmu__warn_invalid_config(struct perf_pmu *pmu, __u64 config,
char *name);

bool perf_pmu__has_hybrid(void);
int perf_pmu__match(char *pattern, char *name, char *tok);

#endif /* __PMU_H */

0 comments on commit c47a559

Please sign in to comment.