]> www.infradead.org Git - users/hch/misc.git/commitdiff
perf arm_spe: Allow parsing both data source and events
authorLeo Yan <leo.yan@arm.com>
Fri, 12 Sep 2025 15:42:19 +0000 (16:42 +0100)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 19 Sep 2025 15:14:29 +0000 (12:14 -0300)
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 <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.c

index 08cb493c3265ade3093c84a90fa5e47dcd77c8f1..71be979f507718caadc091714c40bcee073c1d60 100644 (file)
@@ -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;