Blob Blame History Raw
From 2ca13a4cc56c920a6c9fc8ee45d02bccacd7f46c Mon Sep 17 00:00:00 2001
From: Madhavan Srinivasan <maddy@linux.ibm.com>
Date: Wed, 21 Oct 2020 14:23:29 +0530
Subject: [PATCH] powerpc/perf: Use regs->nip when SIAR is zero

References: bsc#1065729
Patch-mainline: v5.11-rc1
Git-commit: 2ca13a4cc56c920a6c9fc8ee45d02bccacd7f46c

In power10 DD1, there is an issue where the SIAR (Sampled Instruction
Address Register) is not latching to the sampled address during random
sampling. This results in value of 0s in the SIAR. Add a check to use
regs->nip when SIAR is zero.

Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20201021085329.384535-5-maddy@linux.ibm.com
Acked-by: Michal Suchanek <msuchanek@suse.de>
---
 arch/powerpc/perf/core-book3s.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 6be0349e01ad..3c8c6ce634c5 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -263,9 +263,16 @@ static inline u32 perf_get_misc_flags(struct pt_regs *regs)
 	 * DD1.
 	 */
 	if (marked && (ppmu->flags & PPMU_P10_DD1)) {
-		if (is_kernel_addr(mfspr(SPRN_SIAR)))
-			return PERF_RECORD_MISC_KERNEL;
-		return PERF_RECORD_MISC_USER;
+		unsigned long siar = mfspr(SPRN_SIAR);
+		if (siar) {
+			if (is_kernel_addr(siar))
+				return PERF_RECORD_MISC_KERNEL;
+			return PERF_RECORD_MISC_USER;
+		} else {
+			if (is_kernel_addr(regs->nip))
+				return PERF_RECORD_MISC_KERNEL;
+			return PERF_RECORD_MISC_USER;
+		}
 	}
 
 	/*
@@ -2199,8 +2206,14 @@ unsigned long perf_misc_flags(struct pt_regs *regs)
 unsigned long perf_instruction_pointer(struct pt_regs *regs)
 {
 	bool use_siar = regs_use_siar(regs);
+	unsigned long siar = mfspr(SPRN_SIAR);
 
-	if (use_siar && siar_valid(regs))
+	if (ppmu->flags & PPMU_P10_DD1) {
+		if (siar)
+			return siar;
+		else
+			return regs->nip;
+	} else if (use_siar && siar_valid(regs))
 		return mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
 	else if (use_siar)
 		return 0;		// no valid instruction pointer
-- 
2.31.1