From: Leo Yan Date: Fri, 12 Sep 2025 15:42:16 +0000 (+0100) Subject: perf arm_spe: Fill memory levels for FEAT_SPEv1p4 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=786e7e7a504634168c0287ad8de3f4fe34f1b1f6;p=users%2Fjedix%2Flinux-maple.git perf arm_spe: Fill memory levels for FEAT_SPEv1p4 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 Signed-off-by: Leo Yan Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ali Saidi Cc: German Gomez Cc: Ian Rogers Cc: Jiri Olsa Cc: Mark Rutland Cc: Namhyung Kim Cc: Will Deacon Signed-off-by: Arnaldo Carvalho de Melo --- diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h index 03da55453da8..3afa8703b21d 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h @@ -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 */ diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index 433af83ec3d1..c5fd62534e03 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -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) ?