]> www.infradead.org Git - users/hch/misc.git/commitdiff
perf arm_spe: Fill memory levels for FEAT_SPEv1p4
authorLeo Yan <leo.yan@arm.com>
Fri, 12 Sep 2025 15:42:16 +0000 (16:42 +0100)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 19 Sep 2025 15:14:28 +0000 (12:14 -0300)
Starting with FEAT_SPEv1p4, Arm SPE provides information on Level 2 data
cache and recently fetched events. This patch fills in the memory levels
for these new events.

The recently fetched events are matched to line-fill buffer (LFB). In
general, the latency for accessing LFB is higher than accessing L1 cache
but lower than accessing L2 cache. Thus, it locates in the memory
hierarchy information between L1 cache and L2 cache.

Reviewed-by: James Clark <james.clark@linaro.org>
Signed-off-by: Leo Yan <leo.yan@arm.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ali Saidi <alisaidi@amazon.com>
Cc: German Gomez <german.gomez@arm.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/arm-spe-decoder/arm-spe-decoder.h
tools/perf/util/arm-spe.c

index 03da55453da8fd2e7b9e2dcba3ddcf5243599e1c..3afa8703b21db9d231eef93fe981e0c20d562e83 100644 (file)
@@ -25,6 +25,9 @@
 #define ARM_SPE_SVE_PARTIAL_PRED       BIT(EV_PARTIAL_PREDICATE)
 #define ARM_SPE_SVE_EMPTY_PRED         BIT(EV_EMPTY_PREDICATE)
 #define ARM_SPE_IN_TXN                 BIT(EV_TRANSACTIONAL)
+#define ARM_SPE_L2D_ACCESS             BIT(EV_L2D_ACCESS)
+#define ARM_SPE_L2D_MISS               BIT(EV_L2D_MISS)
+#define ARM_SPE_RECENTLY_FETCHED       BIT(EV_RECENTLY_FETCHED)
 
 enum arm_spe_op_type {
        /* First level operation type */
index 433af83ec3d1f18bb1a8692d96232d200fe7a278..c5fd62534e0362dd69c69f6e836cef6f67b0d060 100644 (file)
@@ -833,6 +833,12 @@ static void arm_spe__synth_ld_memory_level(const struct arm_spe_record *record,
        if (arm_spe_is_cache_hit(record->type, L1D)) {
                data_src->mem_lvl = PERF_MEM_LVL_L1 | PERF_MEM_LVL_HIT;
                data_src->mem_lvl_num = PERF_MEM_LVLNUM_L1;
+       } else if (record->type & ARM_SPE_RECENTLY_FETCHED) {
+               data_src->mem_lvl = PERF_MEM_LVL_LFB | PERF_MEM_LVL_HIT;
+               data_src->mem_lvl_num = PERF_MEM_LVLNUM_LFB;
+       } else if (arm_spe_is_cache_hit(record->type, L2D)) {
+               data_src->mem_lvl = PERF_MEM_LVL_L2 | PERF_MEM_LVL_HIT;
+               data_src->mem_lvl_num = PERF_MEM_LVLNUM_L2;
        } else if (arm_spe_is_cache_hit(record->type, LLC)) {
                data_src->mem_lvl = PERF_MEM_LVL_L3 | PERF_MEM_LVL_HIT;
                data_src->mem_lvl_num = PERF_MEM_LVLNUM_L3;
@@ -844,6 +850,9 @@ static void arm_spe__synth_ld_memory_level(const struct arm_spe_record *record,
        } else if (arm_spe_is_cache_miss(record->type, LLC)) {
                data_src->mem_lvl = PERF_MEM_LVL_L3 | PERF_MEM_LVL_MISS;
                data_src->mem_lvl_num = PERF_MEM_LVLNUM_L3;
+       } else if (arm_spe_is_cache_miss(record->type, L2D)) {
+               data_src->mem_lvl = PERF_MEM_LVL_L2 | PERF_MEM_LVL_MISS;
+               data_src->mem_lvl_num = PERF_MEM_LVLNUM_L2;
        } else if (arm_spe_is_cache_miss(record->type, L1D)) {
                data_src->mem_lvl = PERF_MEM_LVL_L1 | PERF_MEM_LVL_MISS;
                data_src->mem_lvl_num = PERF_MEM_LVLNUM_L1;
@@ -859,6 +868,11 @@ static void arm_spe__synth_st_memory_level(const struct arm_spe_record *record,
                data_src->mem_lvl |= arm_spe_is_cache_miss(record->type, LLC) ?
                                     PERF_MEM_LVL_MISS : PERF_MEM_LVL_HIT;
                data_src->mem_lvl_num = PERF_MEM_LVLNUM_L3;
+       } else if (arm_spe_is_cache_level(record->type, L2D)) {
+               data_src->mem_lvl = PERF_MEM_LVL_L2;
+               data_src->mem_lvl |= arm_spe_is_cache_miss(record->type, L2D) ?
+                                    PERF_MEM_LVL_MISS : PERF_MEM_LVL_HIT;
+               data_src->mem_lvl_num = PERF_MEM_LVLNUM_L2;
        } else if (arm_spe_is_cache_level(record->type, L1D)) {
                data_src->mem_lvl = PERF_MEM_LVL_L1;
                data_src->mem_lvl |= arm_spe_is_cache_miss(record->type, L1D) ?