[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