Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/perf: Set cpumode flags using sample address

Currently in some cases, when the sampled instruction address register
latches to a specific address during sampling, the privilege bits
captured in the sampled event register are incorrect.

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 these
privilege bit details are read from the sampled event register. In the
above snippet, address "0x00007fff9f94a02c" is shown as "k" (kernel) due
to the incorrect privilege bits captured in the sampled event register.

To address this case check whether the sampled address is in the kernel
area. Since this is specific to the latest platform, a new pmu flag
is added called "PPMU_P10" and is used to contain the proposed fix.
PPMU_P10_DD1 marked events are also included under PPMU_P10, hence
remove the code specific to PPMU_P10_DD1 marked events.

Signed-off-by: Anjali K <anjalik@linux.ibm.com>
Reviewed-by: Athira Rajeev <atrajeev@linux.vnet.ibm.com <mailto:atrajeev@linux.vnet.ibm.com>>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20240528040356.2722275-1-anjalik@linux.ibm.com

authored by

Anjali K and committed by
Michael Ellerman
0300a92e 2bac6cae

+23 -28
+2 -1
arch/powerpc/include/asm/perf_event_server.h
··· 89 89 #define PPMU_NO_SIAR 0x00000100 /* Do not use SIAR */ 90 90 #define PPMU_ARCH_31 0x00000200 /* Has MMCR3, SIER2 and SIER3 */ 91 91 #define PPMU_P10_DD1 0x00000400 /* Is power10 DD1 processor version */ 92 - #define PPMU_HAS_ATTR_CONFIG1 0x00000800 /* Using config1 attribute */ 92 + #define PPMU_P10 0x00000800 /* For power10 pmu */ 93 + #define PPMU_HAS_ATTR_CONFIG1 0x00001000 /* Using config1 attribute */ 93 94 94 95 /* 95 96 * Values for flags to get_alternatives()
+19 -26
arch/powerpc/perf/core-book3s.c
··· 266 266 static inline u32 perf_get_misc_flags(struct pt_regs *regs) 267 267 { 268 268 bool use_siar = regs_use_siar(regs); 269 - unsigned long mmcra = regs->dsisr; 270 - int marked = mmcra & MMCRA_SAMPLE_ENABLE; 269 + unsigned long siar; 270 + unsigned long addr; 271 271 272 272 if (!use_siar) 273 273 return perf_flags_from_msr(regs); 274 - 275 - /* 276 - * Check the address in SIAR to identify the 277 - * privilege levels since the SIER[MSR_HV, MSR_PR] 278 - * bits are not set for marked events in power10 279 - * DD1. 280 - */ 281 - if (marked && (ppmu->flags & PPMU_P10_DD1)) { 282 - unsigned long siar = mfspr(SPRN_SIAR); 283 - if (siar) { 284 - if (is_kernel_addr(siar)) 285 - return PERF_RECORD_MISC_KERNEL; 286 - return PERF_RECORD_MISC_USER; 287 - } else { 288 - if (is_kernel_addr(regs->nip)) 289 - return PERF_RECORD_MISC_KERNEL; 290 - return PERF_RECORD_MISC_USER; 291 - } 292 - } 293 274 294 275 /* 295 276 * If we don't have flags in MMCRA, rather than using ··· 279 298 * results 280 299 */ 281 300 if (ppmu->flags & PPMU_NO_SIPR) { 282 - unsigned long siar = mfspr(SPRN_SIAR); 301 + siar = mfspr(SPRN_SIAR); 283 302 if (is_kernel_addr(siar)) 284 303 return PERF_RECORD_MISC_KERNEL; 285 304 return PERF_RECORD_MISC_USER; 286 305 } 287 306 288 307 /* PR has priority over HV, so order below is important */ 289 - if (regs_sipr(regs)) 290 - return PERF_RECORD_MISC_USER; 291 - 292 - if (regs_sihv(regs) && (freeze_events_kernel != MMCR0_FCHV)) 308 + if (regs_sipr(regs)) { 309 + if (!(ppmu->flags & PPMU_P10)) 310 + return PERF_RECORD_MISC_USER; 311 + } else if (regs_sihv(regs) && (freeze_events_kernel != MMCR0_FCHV)) 293 312 return PERF_RECORD_MISC_HYPERVISOR; 313 + 314 + /* 315 + * Check the address in SIAR to identify the 316 + * privilege levels since the SIER[MSR_HV, MSR_PR] 317 + * bits are not set correctly in power10 sometimes 318 + */ 319 + if (ppmu->flags & PPMU_P10) { 320 + siar = mfspr(SPRN_SIAR); 321 + addr = siar ? siar : regs->nip; 322 + if (!is_kernel_addr(addr)) 323 + return PERF_RECORD_MISC_USER; 324 + } 294 325 295 326 return PERF_RECORD_MISC_KERNEL; 296 327 }
+2 -1
arch/powerpc/perf/power10-pmu.c
··· 593 593 .get_mem_weight = isa207_get_mem_weight, 594 594 .disable_pmc = isa207_disable_pmc, 595 595 .flags = PPMU_HAS_SIER | PPMU_ARCH_207S | 596 - PPMU_ARCH_31 | PPMU_HAS_ATTR_CONFIG1, 596 + PPMU_ARCH_31 | PPMU_HAS_ATTR_CONFIG1 | 597 + PPMU_P10, 597 598 .n_generic = ARRAY_SIZE(power10_generic_events), 598 599 .generic_events = power10_generic_events, 599 600 .cache_events = &power10_cache_events,