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....@linaro.org>
---
 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

Reply via email to