[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20240708144204.839486-2-dapeng1.mi@linux.intel.com>
Date: Mon, 8 Jul 2024 14:42:00 +0000
From: Dapeng Mi <dapeng1.mi@...ux.intel.com>
To: Peter Zijlstra <peterz@...radead.org>,
Ingo Molnar <mingo@...hat.com>,
Arnaldo Carvalho de Melo <acme@...nel.org>,
Namhyung Kim <namhyung@...nel.org>,
Ian Rogers <irogers@...gle.com>,
Adrian Hunter <adrian.hunter@...el.com>,
Alexander Shishkin <alexander.shishkin@...ux.intel.com>,
Kan Liang <kan.liang@...ux.intel.com>
Cc: linux-perf-users@...r.kernel.org,
linux-kernel@...r.kernel.org,
Yongwei Ma <yongwei.ma@...el.com>,
Dapeng Mi <dapeng1.mi@...el.com>,
Dapeng Mi <dapeng1.mi@...ux.intel.com>
Subject: [Patch v2 1/5] 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.
Signed-off-by: Dapeng Mi <dapeng1.mi@...ux.intel.com>
---
tools/perf/arch/x86/util/evlist.c | 8 +++---
tools/perf/arch/x86/util/evsel.c | 3 ++-
tools/perf/arch/x86/util/topdown.c | 43 +++++++++++++++++++++++++++++-
tools/perf/arch/x86/util/topdown.h | 2 ++
4 files changed, 50 insertions(+), 6 deletions(-)
diff --git a/tools/perf/arch/x86/util/evlist.c b/tools/perf/arch/x86/util/evlist.c
index b1ce0c52d88d..332e8907f43e 100644
--- a/tools/perf/arch/x86/util/evlist.c
+++ b/tools/perf/arch/x86/util/evlist.c
@@ -78,14 +78,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;
}
diff --git a/tools/perf/arch/x86/util/evsel.c b/tools/perf/arch/x86/util/evsel.c
index 090d0f371891..181f2ba0bb2a 100644
--- a/tools/perf/arch/x86/util/evsel.c
+++ b/tools/perf/arch/x86/util/evsel.c
@@ -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"
@@ -44,7 +45,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)
diff --git a/tools/perf/arch/x86/util/topdown.c b/tools/perf/arch/x86/util/topdown.c
index 3f9a267d4501..e805065bb7e1 100644
--- a/tools/perf/arch/x86/util/topdown.c
+++ b/tools/perf/arch/x86/util/topdown.c
@@ -32,6 +32,47 @@ 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;
+
+ 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 (strcasestr(info->name, "topdown") && 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 && 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 +85,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;
diff --git a/tools/perf/arch/x86/util/topdown.h b/tools/perf/arch/x86/util/topdown.h
index 46bf9273e572..1bae9b1822d7 100644
--- a/tools/perf/arch/x86/util/topdown.h
+++ b/tools/perf/arch/x86/util/topdown.h
@@ -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
--
2.40.1
Powered by blists - more mailing lists