[PATCH v2 12/14] perf arm-spe: Synthesize memory event

From: Leo Yan
Date: Tue Sep 01 2020 - 04:39:16 EST


This patch is to synthesize memory event, it generates memory events for
all memory levels. The memory event can delivery two benefits for SPE:

- The first benefit is the memory event can give out global view for
memory accessing, rather than using scatter mode to organize events
(such as L1 cache, last level cache, remote accessing, etc) which can
only display a single memory type, memory events contain all memory
accessing so it's easier to review the memory behaviour cross
different memory levels;

- The second benefit is the samples generation might introduce big
overhead and need to wait for long time for Perf reporting, we can
specify itrace option '--itrace=M' to filter out other events and only
output memory events, this can significantly reduce the overhead
caused by generating samples.

Signed-off-by: Leo Yan <leo.yan@xxxxxxxxxx>
---
tools/perf/util/arm-spe.c | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)

diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c
index 44e73e0ff4e7..7f44ef8c89f1 100644
--- a/tools/perf/util/arm-spe.c
+++ b/tools/perf/util/arm-spe.c
@@ -55,6 +55,7 @@ struct arm_spe {
u8 sample_tlb;
u8 sample_branch;
u8 sample_remote_access;
+ u8 sample_memory;

u64 l1d_miss_id;
u64 l1d_access_id;
@@ -64,6 +65,7 @@ struct arm_spe {
u64 tlb_access_id;
u64 branch_miss_id;
u64 remote_access_id;
+ u64 memory_id;

u64 kernel_start;

@@ -296,6 +298,19 @@ static int arm_spe__synth_branch_sample(struct arm_spe_queue *speq,
return arm_spe_deliver_synth_event(spe, speq, event, &sample);
}

+static bool arm_spe__is_memory_event(enum arm_spe_sample_type type)
+{
+ int mem_type = ARM_SPE_L1D_ACCESS | ARM_SPE_L1D_MISS |
+ ARM_SPE_LLC_ACCESS | ARM_SPE_LLC_MISS |
+ ARM_SPE_TLB_ACCESS | ARM_SPE_TLB_MISS |
+ ARM_SPE_REMOTE_ACCESS;
+
+ if (type & mem_type)
+ return true;
+
+ return false;
+}
+
static int arm_spe_sample(struct arm_spe_queue *speq)
{
const struct arm_spe_record *record = &speq->decoder->record;
@@ -357,6 +372,12 @@ static int arm_spe_sample(struct arm_spe_queue *speq)
return err;
}

+ if (spe->sample_memory && arm_spe__is_memory_event(record->type)) {
+ err = arm_spe__synth_mem_sample(speq, spe->memory_id);
+ if (err)
+ return err;
+ }
+
return 0;
}

@@ -924,6 +945,18 @@ arm_spe_synth_events(struct arm_spe *spe, struct perf_session *session)
id += 1;
}

+ if (spe->synth_opts.mem) {
+ spe->sample_memory = true;
+
+ /* Remote access */
+ err = arm_spe_synth_event(session, &attr, id);
+ if (err)
+ return err;
+ spe->memory_id = id;
+ arm_spe_set_event_name(evlist, id, "memory");
+ id += 1;
+ }
+
return 0;
}

--
2.20.1