perf x86/topdown: Complete topdown slots/metrics events check
It's not complete to check whether an event is a topdown slots or
topdown metrics event by only comparing the event name since user
may assign the event by RAW format, e.g.
perf stat -e '{instructions,cpu/r400/,cpu/r8300/}' sleep 1
Performance counter stats for 'sleep 1':
<not counted> instructions
<not counted> cpu/r400/
<not supported> cpu/r8300/
1.002917796 seconds time elapsed
0.002955000 seconds user
0.000000000 seconds sys
The RAW format slots and topdown-be-bound events are not recognized and
not regroup the events, and eventually cause error.
Thus add two helpers arch_is_topdown_slots()/arch_is_topdown_metrics()
to detect whether an event is topdown slots/metrics event by comparing
the event config directly, and use these two helpers to replace the
original event name comparisons.
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Cc: Yongwei Ma <yongwei.ma@intel.com>
Link: https://lore.kernel.org/r/20240913084712.13861-2-dapeng1.mi@linux.intel.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
This commit is contained in:
@@ -10,14 +10,14 @@ int arch_evlist__cmp(const struct evsel *lhs, const struct evsel *rhs)
|
||||
if (topdown_sys_has_perf_metrics() &&
|
||||
(arch_evsel__must_be_in_group(lhs) || arch_evsel__must_be_in_group(rhs))) {
|
||||
/* Ensure the topdown slots comes first. */
|
||||
if (strcasestr(lhs->name, "slots") && !strcasestr(lhs->name, "uops_retired.slots"))
|
||||
if (arch_is_topdown_slots(lhs))
|
||||
return -1;
|
||||
if (strcasestr(rhs->name, "slots") && !strcasestr(rhs->name, "uops_retired.slots"))
|
||||
if (arch_is_topdown_slots(rhs))
|
||||
return 1;
|
||||
/* Followed by topdown events. */
|
||||
if (strcasestr(lhs->name, "topdown") && !strcasestr(rhs->name, "topdown"))
|
||||
if (arch_is_topdown_metrics(lhs) && !arch_is_topdown_metrics(rhs))
|
||||
return -1;
|
||||
if (!strcasestr(lhs->name, "topdown") && strcasestr(rhs->name, "topdown"))
|
||||
if (!arch_is_topdown_metrics(lhs) && arch_is_topdown_metrics(rhs))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "util/pmu.h"
|
||||
#include "util/pmus.h"
|
||||
#include "linux/string.h"
|
||||
#include "topdown.h"
|
||||
#include "evsel.h"
|
||||
#include "util/debug.h"
|
||||
#include "env.h"
|
||||
@@ -65,7 +66,7 @@ bool arch_evsel__must_be_in_group(const struct evsel *evsel)
|
||||
strcasestr(evsel->name, "uops_retired.slots"))
|
||||
return false;
|
||||
|
||||
return strcasestr(evsel->name, "topdown") || strcasestr(evsel->name, "slots");
|
||||
return arch_is_topdown_metrics(evsel) || arch_is_topdown_slots(evsel);
|
||||
}
|
||||
|
||||
int arch_evsel__hw_name(struct evsel *evsel, char *bf, size_t size)
|
||||
|
||||
@@ -32,6 +32,52 @@ bool topdown_sys_has_perf_metrics(void)
|
||||
}
|
||||
|
||||
#define TOPDOWN_SLOTS 0x0400
|
||||
bool arch_is_topdown_slots(const struct evsel *evsel)
|
||||
{
|
||||
if (evsel->core.attr.config == TOPDOWN_SLOTS)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int compare_topdown_event(void *vstate, struct pmu_event_info *info)
|
||||
{
|
||||
int *config = vstate;
|
||||
int event = 0;
|
||||
int umask = 0;
|
||||
char *str;
|
||||
|
||||
if (!strcasestr(info->name, "topdown"))
|
||||
return 0;
|
||||
|
||||
str = strcasestr(info->str, "event=");
|
||||
if (str)
|
||||
sscanf(str, "event=%x", &event);
|
||||
|
||||
str = strcasestr(info->str, "umask=");
|
||||
if (str)
|
||||
sscanf(str, "umask=%x", &umask);
|
||||
|
||||
if (event == 0 && *config == (event | umask << 8))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool arch_is_topdown_metrics(const struct evsel *evsel)
|
||||
{
|
||||
struct perf_pmu *pmu = evsel__find_pmu(evsel);
|
||||
int config = evsel->core.attr.config;
|
||||
|
||||
if (!pmu || !pmu->is_core)
|
||||
return false;
|
||||
|
||||
if (perf_pmu__for_each_event(pmu, false, &config,
|
||||
compare_topdown_event))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether a topdown group supports sample-read.
|
||||
@@ -44,7 +90,7 @@ bool arch_topdown_sample_read(struct evsel *leader)
|
||||
if (!evsel__sys_has_perf_metrics(leader))
|
||||
return false;
|
||||
|
||||
if (leader->core.attr.config == TOPDOWN_SLOTS)
|
||||
if (arch_is_topdown_slots(leader))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
||||
@@ -3,5 +3,7 @@
|
||||
#define _TOPDOWN_H 1
|
||||
|
||||
bool topdown_sys_has_perf_metrics(void);
|
||||
bool arch_is_topdown_slots(const struct evsel *evsel);
|
||||
bool arch_is_topdown_metrics(const struct evsel *evsel);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user