[PATCH] powerpc/perf: set cpumode flags using sample address in the PPMU_ARCH_31 case
Anjali K
anjalik at linux.ibm.com
Sat May 11 17:53:44 AEST 2024
Currently in some cases, when the sampled instruction address register
latches to a specific address during sampling, there is an inconsistency
in the privilege bits captured in the sampled event register.
For example, a snippet from the perf report on a power10 system is:
Overhead Address Command Shared Object Symbol
........ .................. ............ ................. .......................
2.41% 0x7fff9f94a02c null_syscall [unknown] [k] 0x00007fff9f94a02c
2.20% 0x7fff9f94a02c null_syscall libc.so.6 [.] syscall
perf_get_misc_flags() function looks at the privilege bits to return
the corresponding flags to be used for the address symbol and this
privilege bit details are read from the sampled event register. In the
above snippet, address "0x00007fff9f94a02c" is shown as "k" (kernel) due
to the inconsistent privilege bits captured in the sampled event register.
To address this case, the proposed fix is to additionally check whether the
sampled address is in the kernel area. Also since this fix is to address a
specific case, the fix is included within the corresponding flag
(PPMU_ARCH_31).
Signed-off-by: Anjali K <anjalik at linux.ibm.com>
---
arch/powerpc/perf/core-book3s.c | 41 ++++++++++++++-------------------
1 file changed, 17 insertions(+), 24 deletions(-)
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 6b5f8a94e7d8..dd0c23ebaf5a 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -268,29 +268,12 @@ static inline u32 perf_get_misc_flags(struct pt_regs *regs)
bool use_siar = regs_use_siar(regs);
unsigned long mmcra = regs->dsisr;
int marked = mmcra & MMCRA_SAMPLE_ENABLE;
+ unsigned long siar = mfspr(SPRN_SIAR);
+ unsigned long addr;
if (!use_siar)
return perf_flags_from_msr(regs);
- /*
- * Check the address in SIAR to identify the
- * privilege levels since the SIER[MSR_HV, MSR_PR]
- * bits are not set for marked events in power10
- * DD1.
- */
- if (marked && (ppmu->flags & PPMU_P10_DD1)) {
- 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;
- }
- }
-
/*
* If we don't have flags in MMCRA, rather than using
* the MSR, we intuit the flags from the address in
@@ -298,19 +281,29 @@ static inline u32 perf_get_misc_flags(struct pt_regs *regs)
* results
*/
if (ppmu->flags & PPMU_NO_SIPR) {
- unsigned long siar = mfspr(SPRN_SIAR);
if (is_kernel_addr(siar))
return PERF_RECORD_MISC_KERNEL;
return PERF_RECORD_MISC_USER;
}
/* PR has priority over HV, so order below is important */
- if (regs_sipr(regs))
- return PERF_RECORD_MISC_USER;
-
- if (regs_sihv(regs) && (freeze_events_kernel != MMCR0_FCHV))
+ if (regs_sipr(regs)) {
+ if (!(ppmu->flags & PPMU_ARCH_31))
+ return PERF_RECORD_MISC_USER;
+ } else if (regs_sihv(regs) && (freeze_events_kernel != MMCR0_FCHV))
return PERF_RECORD_MISC_HYPERVISOR;
+ /*
+ * Check the address in SIAR to identify the
+ * privilege levels since the SIER[MSR_HV, MSR_PR]
+ * bits are not set correctly in power10 sometimes
+ */
+ if (ppmu->flags & PPMU_ARCH_31) {
+ addr = siar ? siar : regs->nip;
+ if (!is_kernel_addr(addr))
+ return PERF_RECORD_MISC_USER;
+ }
+
return PERF_RECORD_MISC_KERNEL;
}
base-commit: dd5a440a31fae6e459c0d6271dddd62825505361
--
2.39.3
More information about the Linuxppc-dev
mailing list