Subject: [PATCH] powerpc, perf: Define perf_event_print_debug() to print PMU register values

From: Anshuman Khandual <[email-masked]>
Date: Wed, 15 Jan 2014 12:20:37 +0530

As of now "echo p > /proc/sysrq-trigger" command does not print anything on
the console as we have a blank perf_event_print_debug function. This patch
defines perf_event_print_debug function to print various PMU registers.

With this patch, "echo p > /proc/sysrq-trigger" command on a POWER8 system
generates this sample output on the console.

echo p > /proc/sysrq-trigger
SysRq : Show Regs
CPU#5 PMC#1:  00000000 PMC#2:  00000000
CPU#5 PMC#3:  00000000 PMC#4:  00000000
CPU#5 PMC#5:  d03737ba PMC#6:  843aaf8c
CPU#5 MMCR0:  0000000000000000 MMCR1:  0000000000000000
CPU#5 MMCRA:  0000000000000000 SIAR:   0000000000000000
CPU#5 SDAR:   0000000000000000
CPU#5 SIER:   0000000000000000
CPU#5 MMCR2:  0000000000000000 EBBHR:  0000000000000000
CPU#5 EBBRR:  0000000000000000 BESCR:  0000000000000000

Signed-off-by: Anshuman Khandual <[email-masked]>
---
 arch/powerpc/perf/core-book3s.c | 54 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 29b89e8..ac35aae 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -562,9 +562,63 @@ out:
 #endif /* CONFIG_PPC64 */
 
 static void perf_event_interrupt(struct pt_regs *regs);
+static unsigned long read_pmc(int idx);
 
+/* Called from generic sysrq dump register handler */
 void perf_event_print_debug(void)
 {
+	unsigned long flags;
+	int cpu, idx;
+
+	if (!ppmu->n_counter)
+		return;
+
+	local_irq_save(flags);
+
+	cpu = smp_processor_id();
+
+	/* General PMU counters */
+	for (idx = 1; idx <= ppmu->n_counter; idx = idx + 2)
+		pr_info("CPU#%d PMC#%d:  %08lx PMC#%d:  %08lx\n",
+			cpu, idx, read_pmc(idx), idx + 1, read_pmc(idx + 1));
+
+	/* General PMU config registers */
+	pr_info("CPU#%d MMCR0:  %016lx MMCR1:  %016lx\n", cpu,
+					mfspr(SPRN_MMCR0), mfspr(SPRN_MMCR1));
+	pr_info("CPU#%d MMCRA:  %016lx SIAR:   %016lx\n", cpu,
+					mfspr(SPRN_MMCRA), mfspr(SPRN_SIAR));
+
+#ifdef CONFIG_PPC64
+	pr_info("CPU#%d SDAR:   %016lx\n", cpu, mfspr(SPRN_SDAR));
+#endif /* CONFIG_PPC64 */
+
+	/* PMU specific config registers */
+	if (ppmu->flags & PPMU_HAS_SIER)
+		pr_info("CPU#%d SIER:   %016lx\n", cpu, mfspr(SPRN_SIER));
+
+
+	if (ppmu->flags & PPMU_EBB) {
+		pr_info("CPU#%d MMCR2:  %016lx EBBHR:  %016lx\n", cpu,
+					mfspr(SPRN_MMCR2), mfspr(SPRN_EBBHR));
+		pr_info("CPU#%d EBBRR:  %016lx BESCR:  %016lx\n", cpu,
+					mfspr(SPRN_EBBRR), mfspr(SPRN_BESCR));
+	}
+
+	if (ppmu->flags & PPMU_BHRB) {
+		u64 val;
+
+		for (idx = 0; idx < ppmu->bhrb_nr; idx++) {
+			val = read_bhrb(idx);
+
+			/* BHRB terminal marker */
+			if (!val)
+				break;
+
+			pr_info("CPU#%d BHRBE[%d]:  %016llx\n", cpu, idx, val);
+		}
+	}
+
+	local_irq_restore(flags);
 }
 
 /*
-- 
1.7.11.7