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

powerpc/perf: Move code to select SIAR or pt_regs into perf_read_regs

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>

authored by

Anton Blanchard and committed by
Benjamin Herrenschmidt
75382aa7 68b30bb9

+30 -22
+5
arch/powerpc/include/asm/perf_event.h
··· 26 26 #include <asm/ptrace.h> 27 27 #include <asm/reg.h> 28 28 29 + /* 30 + * Overload regs->result to specify whether we should use the MSR (result 31 + * is zero) or the SIAR (result is non zero). 32 + */ 29 33 #define perf_arch_fetch_caller_regs(regs, __ip) \ 30 34 do { \ 35 + (regs)->result = 0; \ 31 36 (regs)->nip = __ip; \ 32 37 (regs)->gpr[1] = *(unsigned long *)__get_SP(); \ 33 38 asm volatile("mfmsr %0" : "=r" ((regs)->msr)); \
+25 -22
arch/powerpc/perf/core-book3s.c
··· 73 73 { 74 74 return 0; 75 75 } 76 - static inline void perf_read_regs(struct pt_regs *regs) { } 76 + static inline void perf_read_regs(struct pt_regs *regs) 77 + { 78 + regs->result = 0; 79 + } 77 80 static inline int perf_intr_is_nmi(struct pt_regs *regs) 78 81 { 79 82 return 0; ··· 151 148 static inline u32 perf_get_misc_flags(struct pt_regs *regs) 152 149 { 153 150 unsigned long mmcra = regs->dsisr; 151 + unsigned long use_siar = regs->result; 154 152 155 - /* Not a PMU interrupt: Make up flags from regs->msr */ 156 - if (TRAP(regs) != 0xf00) 157 - return perf_flags_from_msr(regs); 158 - 159 - /* 160 - * If we don't support continuous sampling and this 161 - * is not a marked event, same deal 162 - */ 163 - if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) && 164 - !(mmcra & MMCRA_SAMPLE_ENABLE)) 153 + if (!use_siar) 165 154 return perf_flags_from_msr(regs); 166 155 167 156 /* ··· 180 185 /* 181 186 * Overload regs->dsisr to store MMCRA so we only need to read it once 182 187 * on each interrupt. 188 + * Overload regs->result to specify whether we should use the MSR (result 189 + * is zero) or the SIAR (result is non zero). 183 190 */ 184 191 static inline void perf_read_regs(struct pt_regs *regs) 185 192 { 186 - regs->dsisr = mfspr(SPRN_MMCRA); 193 + unsigned long mmcra = mfspr(SPRN_MMCRA); 194 + int marked = mmcra & MMCRA_SAMPLE_ENABLE; 195 + int use_siar; 196 + 197 + if (TRAP(regs) != 0xf00) 198 + use_siar = 0; 199 + else if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) && !marked) 200 + use_siar = 0; 201 + else 202 + use_siar = 1; 203 + 204 + regs->dsisr = mmcra; 205 + regs->result = use_siar; 187 206 } 188 207 189 208 /* ··· 1351 1342 */ 1352 1343 unsigned long perf_instruction_pointer(struct pt_regs *regs) 1353 1344 { 1354 - unsigned long mmcra = regs->dsisr; 1345 + unsigned long use_siar = regs->result; 1355 1346 1356 - /* Not a PMU interrupt */ 1357 - if (TRAP(regs) != 0xf00) 1347 + if (use_siar) 1348 + return mfspr(SPRN_SIAR) + perf_ip_adjust(regs); 1349 + else 1358 1350 return regs->nip; 1359 - 1360 - /* Processor doesn't support sampling non marked events */ 1361 - if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) && 1362 - !(mmcra & MMCRA_SAMPLE_ENABLE)) 1363 - return regs->nip; 1364 - 1365 - return mfspr(SPRN_SIAR) + perf_ip_adjust(regs); 1366 1351 } 1367 1352 1368 1353 static bool pmc_overflow(unsigned long val)