[PATCH 09/12] perf arm_spe: Fill memory levels for FEAT_SPEv1p4
James Clark
james.clark at linaro.org
Fri Jun 20 03:37:10 PDT 2025
On 13/06/2025 4:53 pm, Leo Yan wrote:
> 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.
>
> Signed-off-by: Leo Yan <leo.yan at arm.com>
> ---
> tools/perf/util/arm-spe-decoder/arm-spe-decoder.h | 3 +++
> tools/perf/util/arm-spe.c | 14 ++++++++++++++
> 2 files changed, 17 insertions(+)
>
> 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 03da55453da8fd2e7b9e2dcba3ddcf5243599e1c..90c76928c7bf1b35cec538abdb0e88d6083fe81b 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_FETCH BIT(EV_RECENTLY_FETCHED)
FETCH -> FETCHED
Reviewed-by: James Clark <james.clark at linaro.org>
>
> 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 8f18af7336db53b00b450eb4299feee350d0ecb9..2ab38d21d52f73617451a6a79f9d5ae931a34f49 100644
> --- a/tools/perf/util/arm-spe.c
> +++ b/tools/perf/util/arm-spe.c
> @@ -842,6 +842,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_FETCH) {
> + 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;
> @@ -853,6 +859,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;
> @@ -868,6 +877,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) ?
>
More information about the linux-arm-kernel
mailing list