From: Leo Yan Date: Fri, 12 Sep 2025 15:42:19 +0000 (+0100) Subject: perf arm_spe: Allow parsing both data source and events X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=d120cb34c9c75cf49d8ef821215d26d6e22fe8a9;p=users%2Fhch%2Fmisc.git perf arm_spe: Allow parsing both data source and events Current code skips to parse events after generating data source. The reason is the data source packets have cache and snooping related info, the afterwards event packets might contain duplicate info. This commit changes to continue parsing the events after data source analysis. If data source does not give out memory level and snooping types, then the event info is used to synthesize the related fields. As a result, both the peer snoop option ('-d peer') and hitm options ('-d tot/lcl/rmt') are supported by Arm SPE in 'perf c2c'. 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.c b/tools/perf/util/arm-spe.c index 08cb493c3265..71be979f5077 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -900,40 +900,56 @@ static void arm_spe__synth_memory_level(struct arm_spe_queue *speq, { struct arm_spe *spe = speq->spe; - if (data_src->mem_op == PERF_MEM_OP_LOAD) - arm_spe__synth_ld_memory_level(record, data_src); - if (data_src->mem_op == PERF_MEM_OP_STORE) - arm_spe__synth_st_memory_level(record, data_src); + /* + * The data source packet contains more info for cache levels for + * peer snooping. So respect the memory level if has been set by + * data source parsing. + */ + if (!data_src->mem_lvl) { + if (data_src->mem_op == PERF_MEM_OP_LOAD) + arm_spe__synth_ld_memory_level(record, data_src); + if (data_src->mem_op == PERF_MEM_OP_STORE) + arm_spe__synth_st_memory_level(record, data_src); + } if (!data_src->mem_lvl) { data_src->mem_lvl = PERF_MEM_LVL_NA; data_src->mem_lvl_num = PERF_MEM_LVLNUM_NA; } - if (record->type & ARM_SPE_DATA_SNOOPED) { - if (record->type & ARM_SPE_HITM) - data_src->mem_snoop = PERF_MEM_SNOOP_HITM; - else - data_src->mem_snoop = PERF_MEM_SNOOP_HIT; - } else { - u64 *metadata = arm_spe__get_metadata_by_cpu(spe, speq->cpu); - - /* - * Set NA ("Not available") mode if no meta data or the - * SNOOPED event is not supported. - */ - if (!metadata || - !(metadata[ARM_SPE_CAP_EVENT_FILTER] & ARM_SPE_DATA_SNOOPED)) - data_src->mem_snoop = PERF_MEM_SNOOP_NA; - else - data_src->mem_snoop = PERF_MEM_SNOOP_NONE; + /* + * If 'mem_snoop' has been set by data source packet, skip to set + * it at here. + */ + if (!data_src->mem_snoop) { + if (record->type & ARM_SPE_DATA_SNOOPED) { + if (record->type & ARM_SPE_HITM) + data_src->mem_snoop = PERF_MEM_SNOOP_HITM; + else + data_src->mem_snoop = PERF_MEM_SNOOP_HIT; + } else { + u64 *metadata = + arm_spe__get_metadata_by_cpu(spe, speq->cpu); + + /* + * Set NA ("Not available") mode if no meta data or the + * SNOOPED event is not supported. + */ + if (!metadata || + !(metadata[ARM_SPE_CAP_EVENT_FILTER] & ARM_SPE_DATA_SNOOPED)) + data_src->mem_snoop = PERF_MEM_SNOOP_NA; + else + data_src->mem_snoop = PERF_MEM_SNOOP_NONE; + } } - if (record->type & ARM_SPE_REMOTE_ACCESS) - data_src->mem_remote = PERF_MEM_REMOTE_REMOTE; + if (!data_src->mem_remote) { + if (record->type & ARM_SPE_REMOTE_ACCESS) + data_src->mem_remote = PERF_MEM_REMOTE_REMOTE; + } } -static bool arm_spe__synth_ds(struct arm_spe_queue *speq, +static void arm_spe__synth_ds(struct arm_spe_queue *speq, const struct arm_spe_record *record, union perf_mem_data_src *data_src) { @@ -952,19 +968,18 @@ static bool arm_spe__synth_ds(struct arm_spe_queue *speq, } else { metadata = arm_spe__get_metadata_by_cpu(spe, speq->cpu); if (!metadata) - return false; + return; midr = metadata[ARM_SPE_CPU_MIDR]; } for (i = 0; i < ARRAY_SIZE(data_source_handles); i++) { if (is_midr_in_range_list(midr, data_source_handles[i].midr_ranges)) { - data_source_handles[i].ds_synth(record, data_src); - return true; + return data_source_handles[i].ds_synth(record, data_src); } } - return false; + return; } static union perf_mem_data_src @@ -984,8 +999,8 @@ arm_spe__synth_data_source(struct arm_spe_queue *speq, else return data_src; - if (!arm_spe__synth_ds(speq, record, &data_src)) - arm_spe__synth_memory_level(speq, record, &data_src); + arm_spe__synth_ds(speq, record, &data_src); + arm_spe__synth_memory_level(speq, record, &data_src); if (record->type & (ARM_SPE_TLB_ACCESS | ARM_SPE_TLB_MISS)) { data_src.mem_dtlb = PERF_MEM_TLB_WK;