From: Anton Blanchard <anton@samba.org>
Subject: powerpc/perf: Move code to select SIAR or pt_regs into perf_read_regs
Git-commit: 75382aa72f06823db7312ad069c3bae2eb3f8548
Patch-mainline: yes
References: bnc#796891 
	    
    The logic to choose whether to use the SIAR or get the information
    out of pt_regs is going to get more complicated, so do it once in
    perf_read_regs.
    
    We overload regs->result which is gross but we are already doing it
    with regs->dsisr.
	    
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Acked-by: Torsten Duwe <duwe@suse.de>

Index: linux-3.0.53-83/arch/powerpc/include/asm/perf_event.h
===================================================================
--- linux-3.0.53-83.orig/arch/powerpc/include/asm/perf_event.h
+++ linux-3.0.53-83/arch/powerpc/include/asm/perf_event.h
@@ -28,6 +28,7 @@
 
 #define perf_arch_fetch_caller_regs(regs, __ip)			\
 	do {							\
+		(regs)->result = 0;				\
 		(regs)->nip = __ip;				\
 		(regs)->gpr[1] = *(unsigned long *)__get_SP();	\
 		asm volatile("mfmsr %0" : "=r" ((regs)->msr));	\
Index: linux-3.0.53-83/arch/powerpc/kernel/perf_event.c
===================================================================
--- linux-3.0.53-83.orig/arch/powerpc/kernel/perf_event.c
+++ linux-3.0.53-83/arch/powerpc/kernel/perf_event.c
@@ -73,7 +73,11 @@ static inline u32 perf_get_misc_flags(st
 {
 	return 0;
 }
-static inline void perf_read_regs(struct pt_regs *regs) { }
+static inline void perf_read_regs(struct pt_regs *regs)
+{
+	regs->result = 0;
+}
+
 static inline int perf_intr_is_nmi(struct pt_regs *regs)
 {
 	return 0;
@@ -159,17 +163,9 @@ static inline u32 perf_flags_from_msr(st
 static inline u32 perf_get_misc_flags(struct pt_regs *regs)
 {
 	unsigned long mmcra = regs->dsisr;
+	unsigned long use_siar = regs->result;
 
-	/* Not a PMU interrupt: Make up flags from regs->msr */
-	if (TRAP(regs) != 0xf00)
-		return perf_flags_from_msr(regs);
-
-	/*
-	 * If we don't support continuous sampling and this
-	 * is not a marked event, same deal
-	 */
-	if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) &&
-			!(mmcra & MMCRA_SAMPLE_ENABLE))
+	if (!use_siar)
 		return perf_flags_from_msr(regs);
 
 	/*
@@ -196,10 +192,24 @@ static inline u32 perf_get_misc_flags(st
 /*
  * Overload regs->dsisr to store MMCRA so we only need to read it once
  * on each interrupt.
+ * Overload regs->result to specify whether we should use the MSR (result
+ * is zero) or the SIAR (result is non zero).
  */
 static inline void perf_read_regs(struct pt_regs *regs)
 {
-	regs->dsisr = mfspr(SPRN_MMCRA);
+	unsigned long mmcra = mfspr(SPRN_MMCRA);
+	int marked = mmcra & MMCRA_SAMPLE_ENABLE;
+	int use_siar;
+
+	if (TRAP(regs) != 0xf00)
+		use_siar = 0;
+	else if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) && !marked)
+		use_siar = 0;
+	else
+		use_siar = 1;
+
+	regs->dsisr = mmcra;
+	regs->result = use_siar;
 }
 
 /*
@@ -1367,18 +1377,8 @@ unsigned long perf_misc_flags(struct pt_
  */
 unsigned long perf_instruction_pointer(struct pt_regs *regs)
 {
-	unsigned long mmcra = regs->dsisr;
 	unsigned long use_siar = regs->result;
 
-	/* Not a PMU interrupt */
-	if (TRAP(regs) != 0xf00)
-		return regs->nip;
-
-	/* Processor doesn't support sampling non marked events */
-	if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) &&
-			!(mmcra & MMCRA_SAMPLE_ENABLE))
-		return regs->nip;
-
 	if (use_siar && siar_valid(regs))
 		return mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
 	else if (use_siar)
