perf pmu: Add #slots literal support for arm64
authorJing Zhang <renyu.zj@linux.alibaba.com>
Tue, 17 Jan 2023 07:29:25 +0000 (15:29 +0800)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 19 Jan 2023 12:38:55 +0000 (09:38 -0300)
The slots in each architecture may be different, so add #slots literal
to obtain the slots of different architectures, and the #slots can be
applied in the metric. Currently, The #slots just support for arm64,
and other architectures will return NAN.

On arm64, the value of slots is from the register PMMIR_EL1.SLOT, which
I can read in /sys/bus/event_source/device/armv8_pmuv3_*/caps/slots.
PMMIR_EL1.SLOT might read as zero if the PMU version is lower than
ID_AA64DFR0_EL1_PMUVer_V3P4 or the STALL_SLOT event is not implemented.

Reviewed-by: John Garry <john.g.garry@oracle.com>
Signed-off-by: Jing Zhang <renyu.zj@linux.alibaba.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andrew Kilroy <andrew.kilroy@arm.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Mike Leach <mike.leach@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Shuai Xue <xueshuai@linux.alibaba.com>
Cc: Will Deacon <will@kernel.org>
Cc: Xing Zhengjun <zhengjun.xing@linux.intel.com>
Cc: Zhuo Song <zhuo.song@linux.alibaba.com>
Cc: linux-arm-kernel@lists.infradead.org
Link: https://lore.kernel.org/r/1673940573-90503-2-git-send-email-renyu.zj@linux.alibaba.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/arch/arm64/util/pmu.c
tools/perf/util/expr.c
tools/perf/util/pmu.c
tools/perf/util/pmu.h

index 477e513972a4049ffb786e560d830de06cef2e13..9e674cac5a73e37336db4aa90923cc37ec9ce458 100644 (file)
@@ -3,8 +3,10 @@
 #include <internal/cpumap.h>
 #include "../../../util/cpumap.h"
 #include "../../../util/pmu.h"
+#include <api/fs/fs.h>
+#include <math.h>
 
-const struct pmu_events_table *pmu_events_table__find(void)
+static struct perf_pmu *pmu__find_core_pmu(void)
 {
        struct perf_pmu *pmu = NULL;
 
@@ -19,8 +21,37 @@ const struct pmu_events_table *pmu_events_table__find(void)
                if (pmu->cpus->nr != cpu__max_cpu().cpu)
                        return NULL;
 
-               return perf_pmu__find_table(pmu);
+               return pmu;
        }
 
        return NULL;
 }
+
+const struct pmu_events_table *pmu_events_table__find(void)
+{
+       struct perf_pmu *pmu = pmu__find_core_pmu();
+
+       if (pmu)
+               return perf_pmu__find_table(pmu);
+
+       return NULL;
+}
+
+double perf_pmu__cpu_slots_per_cycle(void)
+{
+       char path[PATH_MAX];
+       unsigned long long slots = 0;
+       struct perf_pmu *pmu = pmu__find_core_pmu();
+
+       if (pmu) {
+               scnprintf(path, PATH_MAX,
+                       EVENT_SOURCE_DEVICE_PATH "%s/caps/slots", pmu->name);
+               /*
+                * The value of slots is not greater than 32 bits, but sysfs__read_int
+                * can't read value with 0x prefix, so use sysfs__read_ull instead.
+                */
+               sysfs__read_ull(path, &slots);
+       }
+
+       return slots ? (double)slots : NAN;
+}
index 00dcde35e0d31089b5c1c35dc8f383bcc6c3e0f6..c1da20b868db1182f166d3d72da3626eab74c253 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/zalloc.h>
 #include <ctype.h>
 #include <math.h>
+#include "pmu.h"
 
 #ifdef PARSER_DEBUG
 extern int expr_debug;
@@ -448,6 +449,10 @@ double expr__get_literal(const char *literal, const struct expr_scanner_ctx *ctx
                result = topology->core_cpus_lists;
                goto out;
        }
+       if (!strcmp("#slots", literal)) {
+               result = perf_pmu__cpu_slots_per_cycle();
+               goto out;
+       }
 
        pr_err("Unrecognized literal '%s'", literal);
 out:
index 2bdeb89352e7ad2dac23d17c7984a07ae76a03f1..cbb4fbf124bdd51af953965e6b8c7eb52da97c5c 100644 (file)
@@ -19,6 +19,7 @@
 #include <regex.h>
 #include <perf/cpumap.h>
 #include <fnmatch.h>
+#include <math.h>
 #include "debug.h"
 #include "evsel.h"
 #include "pmu.h"
@@ -1993,3 +1994,8 @@ int perf_pmu__cpus_match(struct perf_pmu *pmu, struct perf_cpu_map *cpus,
        *ucpus_ptr = unmatched_cpus;
        return 0;
 }
+
+double __weak perf_pmu__cpu_slots_per_cycle(void)
+{
+       return NAN;
+}
index 69ca0004f94f6b08ed0d4002ac1b4b666aeb2949..fd414ba1d776d3449bc828dfcb48478cfbcf1386 100644 (file)
@@ -259,4 +259,5 @@ int perf_pmu__cpus_match(struct perf_pmu *pmu, struct perf_cpu_map *cpus,
 
 char *pmu_find_real_name(const char *name);
 char *pmu_find_alias_name(const char *name);
+double perf_pmu__cpu_slots_per_cycle(void);
 #endif /* __PMU_H */