summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMadhavan Srinivasan <maddy@linux.ibm.com>2020-10-21 14:23:29 +0530
committerMichael Ellerman <mpe@ellerman.id.au>2020-11-19 16:56:56 +1100
commit2ca13a4cc56c920a6c9fc8ee45d02bccacd7f46c (patch)
treef681c01bc4c81f76b0bcdd0b32f1fff0f31ef545
parentd9f7088dd6d8859f385565ca8acd2681e1f700f9 (diff)
powerpc/perf: Use regs->nip when SIAR is zero
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
-rw-r--r--arch/powerpc/perf/core-book3s.c21
1 files 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