[PATCH v3 2/6] powerpc/perf: Export memory hierarchy info to user space

2017-04-10 Thread Madhavan Srinivasan
The LDST field and DATA_SRC in SIER identifies the memory hierarchy level
(eg: L1, L2 etc), from which a data-cache miss for a marked instruction
was satisfied. Use the 'perf_mem_data_src' object to export this
hierarchy level to user space.

Signed-off-by: Sukadev Bhattiprolu 
Signed-off-by: Madhavan Srinivasan 
---
 arch/powerpc/include/asm/perf_event_server.h |  2 +
 arch/powerpc/perf/core-book3s.c  |  4 ++
 arch/powerpc/perf/isa207-common.c| 74 
 arch/powerpc/perf/isa207-common.h| 16 +-
 4 files changed, 95 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/perf_event_server.h 
b/arch/powerpc/include/asm/perf_event_server.h
index ae0a23091a9b..446cdcd9b7f5 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -38,6 +38,8 @@ struct power_pmu {
unsigned long *valp);
int (*get_alternatives)(u64 event_id, unsigned int flags,
u64 alt[]);
+   void(*get_mem_data_src)(union perf_mem_data_src *dsrc,
+   u32 flags, struct pt_regs *regs);
u64 (*bhrb_filter_map)(u64 branch_sample_type);
void(*config_bhrb)(u64 pmu_bhrb_filter);
void(*disable_pmc)(unsigned int pmc, unsigned long mmcr[]);
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 2ff13249f87a..e241ebebab6f 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -2049,6 +2049,10 @@ static void record_and_restart(struct perf_event *event, 
unsigned long val,
data.br_stack = >bhrb_stack;
}
 
+   if (event->attr.sample_type & PERF_SAMPLE_DATA_SRC &&
+   ppmu->get_mem_data_src)
+   ppmu->get_mem_data_src(_src, ppmu->flags, 
regs);
+
if (perf_event_overflow(event, , regs))
power_pmu_stop(event, 0);
}
diff --git a/arch/powerpc/perf/isa207-common.c 
b/arch/powerpc/perf/isa207-common.c
index cd951fd231c4..a8b100ef8e6c 100644
--- a/arch/powerpc/perf/isa207-common.c
+++ b/arch/powerpc/perf/isa207-common.c
@@ -148,6 +148,80 @@ static bool is_thresh_cmp_valid(u64 event)
return true;
 }
 
+static inline u64 isa207_find_source(u64 idx, u32 sub_idx)
+{
+   u64 ret = PERF_MEM_NA;
+
+   switch(idx) {
+   case 0:
+   /* Nothing to do */
+   break;
+   case 1:
+   ret = PH(LVL, L1);
+   break;
+   case 2:
+   ret = PH(LVL, L2);
+   break;
+   case 3:
+   ret = PH(LVL, L3);
+   break;
+   case 4:
+   if (sub_idx <= 1)
+   ret = PH(LVL, LOC_RAM);
+   else if (sub_idx > 1 && sub_idx <= 2)
+   ret = PH(LVL, REM_RAM1);
+   else
+   ret = PH(LVL, REM_RAM2);
+   ret |= P(SNOOP, HIT);
+   break;
+   case 5:
+   ret = PH(LVL, REM_CCE1);
+   if ((sub_idx == 0) || (sub_idx == 2) || (sub_idx == 4))
+   ret |= P(SNOOP, HIT);
+   else if ((sub_idx == 1) || (sub_idx == 3) || (sub_idx == 5))
+   ret |= P(SNOOP, HITM);
+   break;
+   case 6:
+   ret = PH(LVL, REM_CCE2);
+   if ((sub_idx == 0) || (sub_idx == 2))
+   ret |= P(SNOOP, HIT);
+   else if ((sub_idx == 1) || (sub_idx == 3))
+   ret |= P(SNOOP, HITM);
+   break;
+   case 7:
+   ret = PM(LVL, L1);
+   break;
+   }
+
+   return ret;
+}
+
+void isa207_get_mem_data_src(union perf_mem_data_src *dsrc, u32 flags,
+   struct pt_regs *regs)
+{
+   u64 idx;
+   u32 sub_idx;
+   u64 sier;
+   u64 val;
+
+   /* Skip if no SIER support */
+   if (!(flags & PPMU_HAS_SIER)) {
+   dsrc->val = 0;
+   return;
+   }
+
+   sier = mfspr(SPRN_SIER);
+   val = (sier & ISA207_SIER_TYPE_MASK) >> ISA207_SIER_TYPE_SHIFT;
+   if (val == 1 || val == 2) {
+   idx = (sier & ISA207_SIER_LDST_MASK) >> ISA207_SIER_LDST_SHIFT;
+   sub_idx = (sier & ISA207_SIER_DATA_SRC_MASK) >> 
ISA207_SIER_DATA_SRC_SHIFT;
+
+   dsrc->val = isa207_find_source(idx, sub_idx);
+   dsrc->val |= (val == 1) ? P(OP, LOAD) : P(OP, STORE);
+   }
+}
+
+
 int isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp)
 {
unsigned int unit, pmc, cache, ebb;
diff --git a/arch/powerpc/perf/isa207-common.h 
b/arch/powerpc/perf/isa207-common.h
index 

[PATCH v3 2/6] powerpc/perf: Export memory hierarchy info to user space

2017-03-22 Thread Madhavan Srinivasan
The LDST field and DATA_SRC in SIER identifies the memory hierarchy level
(eg: L1, L2 etc), from which a data-cache miss for a marked instruction
was satisfied. Use the 'perf_mem_data_src' object to export this
hierarchy level to user space.

Cc: Benjamin Herrenschmidt 
Cc: Paul Mackerras 
Cc: Thomas Gleixner 
Cc: Sebastian Andrzej Siewior 
Cc: Anna-Maria Gleixner 
Cc: Daniel Axtens 
Cc: Peter Zijlstra 
Cc: Ingo Molnar 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexander Shishkin 
Cc: Wang Nan 
Cc: Alexei Starovoitov 
Cc: Stephane Eranian 
Signed-off-by: Sukadev Bhattiprolu 
Signed-off-by: Madhavan Srinivasan 
---
Changelog v2:
- Fixed isa207_find_source() to consider all the possible sier[ldst] values.


 arch/powerpc/include/asm/perf_event_server.h |  2 +
 arch/powerpc/perf/core-book3s.c  |  4 ++
 arch/powerpc/perf/isa207-common.c| 80 
 arch/powerpc/perf/isa207-common.h| 16 +-
 4 files changed, 101 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/perf_event_server.h 
b/arch/powerpc/include/asm/perf_event_server.h
index ae0a23091a9b..446cdcd9b7f5 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -38,6 +38,8 @@ struct power_pmu {
unsigned long *valp);
int (*get_alternatives)(u64 event_id, unsigned int flags,
u64 alt[]);
+   void(*get_mem_data_src)(union perf_mem_data_src *dsrc,
+   u32 flags, struct pt_regs *regs);
u64 (*bhrb_filter_map)(u64 branch_sample_type);
void(*config_bhrb)(u64 pmu_bhrb_filter);
void(*disable_pmc)(unsigned int pmc, unsigned long mmcr[]);
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 2ff13249f87a..e241ebebab6f 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -2049,6 +2049,10 @@ static void record_and_restart(struct perf_event *event, 
unsigned long val,
data.br_stack = >bhrb_stack;
}
 
+   if (event->attr.sample_type & PERF_SAMPLE_DATA_SRC &&
+   ppmu->get_mem_data_src)
+   ppmu->get_mem_data_src(_src, ppmu->flags, 
regs);
+
if (perf_event_overflow(event, , regs))
power_pmu_stop(event, 0);
}
diff --git a/arch/powerpc/perf/isa207-common.c 
b/arch/powerpc/perf/isa207-common.c
index cd951fd231c4..41cc053ee692 100644
--- a/arch/powerpc/perf/isa207-common.c
+++ b/arch/powerpc/perf/isa207-common.c
@@ -148,6 +148,86 @@ static bool is_thresh_cmp_valid(u64 event)
return true;
 }
 
+static inline u64 isa207_find_source(u64 idx, u32 sub_idx)
+{
+   u64 ret = PERF_MEM_NA;
+
+   switch(idx) {
+   case 0:
+   /* Nothing to do */
+   break;
+   case 1:
+   ret = PLH(LVL, L1);
+   break;
+   case 2:
+   ret = PLH(LVL, L2);
+   break;
+   case 3:
+   ret = PLH(LVL, L3);
+   break;
+   case 4:
+   if (sub_idx <= 1)
+   ret = PLH(LVL, LOC_RAM);
+   else if (sub_idx > 1 && sub_idx <= 2)
+   ret = PLH(LVL, REM_RAM1);
+   else
+   ret = PLH(LVL, REM_RAM2);
+   ret |= P(SNOOP, HIT);
+   break;
+   case 5:
+   ret = PLH(LVL, REM_CCE1);
+   if ((sub_idx == 0) || (sub_idx == 2) || (sub_idx == 4))
+   ret |= P(SNOOP, HIT);
+   else if ((sub_idx == 1) || (sub_idx == 3) || (sub_idx == 5))
+   ret |= P(SNOOP, HITM);
+   break;
+   case 6:
+   ret = PLH(LVL, REM_CCE2);
+   if ((sub_idx == 0) || (sub_idx == 2))
+   ret |= P(SNOOP, HIT);
+   else if ((sub_idx == 1) || (sub_idx == 3))
+   ret |= P(SNOOP, HITM);
+   break;
+   case 7:
+   ret = PSM(LVL, L1);
+   break;
+   }
+
+   return ret;
+}
+
+static inline bool is_load_store_inst(u64 sier)
+{
+   u64 val;
+   val = (sier & ISA207_SIER_TYPE_MASK) >> ISA207_SIER_TYPE_SHIFT;
+
+   /* 1 = load, 2 = store */
+   return val == 1 || val == 2;
+}
+
+void isa207_get_mem_data_src(union perf_mem_data_src *dsrc, u32 flags,
+   struct pt_regs *regs)
+{
+