[PATCH v2 5/6] powerpc/perf: Use Instruction Counter value
Madhavan Srinivasan
maddy at linux.vnet.ibm.com
Mon Feb 13 04:03:14 AEDT 2017
Since PM_INST_DISP include speculative instruction,
based on the workload the dispatch count could vary
considerably. Hence as an alternative, for completed
instruction counting, program the PM_INST_DISP event
to the MMCR* but use Instruction Counter register value.
Signed-off-by: Madhavan Srinivasan <maddy at linux.vnet.ibm.com>
---
Changelog v1:
1)Removed the #ifdef and added changes for EBB count updates
arch/powerpc/perf/core-book3s.c | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 270eb9b74e2e..87d17a1f7168 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -57,6 +57,7 @@ struct cpu_hw_events {
void *bhrb_context;
struct perf_branch_stack bhrb_stack;
struct perf_branch_entry bhrb_entries[BHRB_MAX_ENTRIES];
+ u64 ic_init;
};
static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
@@ -127,6 +128,10 @@ static inline void power_pmu_bhrb_disable(struct perf_event *event) {}
static void power_pmu_sched_task(struct perf_event_context *ctx, bool sched_in) {}
static inline void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw) {}
static void pmao_restore_workaround(bool ebb) { }
+static bool use_ic(u64 event)
+{
+ return false;
+}
#endif /* CONFIG_PPC32 */
static bool regs_use_siar(struct pt_regs *regs)
@@ -688,6 +693,15 @@ static void pmao_restore_workaround(bool ebb)
mtspr(SPRN_PMC5, pmcs[4]);
mtspr(SPRN_PMC6, pmcs[5]);
}
+
+static bool use_ic(u64 event)
+{
+ if (cpu_has_feature(CPU_FTR_POWER9_DD1) &&
+ (event == 0x200f2 || event == 0x300f2))
+ return true;
+
+ return false;
+}
#endif /* CONFIG_PPC64 */
static void perf_event_interrupt(struct pt_regs *regs);
@@ -1007,6 +1021,7 @@ static u64 check_and_compute_delta(u64 prev, u64 val)
static void power_pmu_read(struct perf_event *event)
{
s64 val, delta, prev;
+ struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events);
if (event->hw.state & PERF_HES_STOPPED)
return;
@@ -1016,6 +1031,13 @@ static void power_pmu_read(struct perf_event *event)
if (is_ebb_event(event)) {
val = read_pmc(event->hw.idx);
+ if (use_ic(event->attr.config)) {
+ val = mfspr(SPRN_IC);
+ if (val > cpuhw->ic_init)
+ val = val - cpuhw->ic_init;
+ else
+ val = val + (0 - cpuhw->ic_init);
+ }
local64_set(&event->hw.prev_count, val);
return;
}
@@ -1029,6 +1051,13 @@ static void power_pmu_read(struct perf_event *event)
prev = local64_read(&event->hw.prev_count);
barrier();
val = read_pmc(event->hw.idx);
+ if (use_ic(event->attr.config)) {
+ val = mfspr(SPRN_IC);
+ if (val > cpuhw->ic_init)
+ val = val - cpuhw->ic_init;
+ else
+ val = val + (0 - cpuhw->ic_init);
+ }
delta = check_and_compute_delta(prev, val);
if (!delta)
return;
@@ -1466,6 +1495,13 @@ static int power_pmu_add(struct perf_event *event, int ef_flags)
event->attr.branch_sample_type);
}
+ /*
+ * Workaround for POWER9 DD1 to use the Instruction Counter
+ * register value for instruction counting
+ */
+ if (use_ic(event->attr.config))
+ cpuhw->ic_init = mfspr(SPRN_IC);
+
perf_pmu_enable(event->pmu);
local_irq_restore(flags);
return ret;
--
2.7.4
More information about the Linuxppc-dev
mailing list