diff options
author | Anton Blanchard <anton@samba.org> | 2012-06-26 01:01:36 (GMT) |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2012-07-10 09:18:41 (GMT) |
commit | 75382aa72f06823db7312ad069c3bae2eb3f8548 (patch) | |
tree | d345dbb162b14375d20a622a0801fd9a93cf1c1c | |
parent | 68b30bb9f0fed8281fe8a1ac818d6d07c803fa7b (diff) | |
download | linux-fsl-qoriq-75382aa72f06823db7312ad069c3bae2eb3f8548.tar.xz |
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>
-rw-r--r-- | arch/powerpc/include/asm/perf_event.h | 5 | ||||
-rw-r--r-- | arch/powerpc/perf/core-book3s.c | 47 |
2 files changed, 30 insertions, 22 deletions
diff --git a/arch/powerpc/include/asm/perf_event.h b/arch/powerpc/include/asm/perf_event.h index 5c16b89..0bb2372 100644 --- a/arch/powerpc/include/asm/perf_event.h +++ b/arch/powerpc/include/asm/perf_event.h @@ -26,8 +26,13 @@ #include <asm/ptrace.h> #include <asm/reg.h> +/* + * Overload regs->result to specify whether we should use the MSR (result + * is zero) or the SIAR (result is non zero). + */ #define perf_arch_fetch_caller_regs(regs, __ip) \ do { \ + (regs)->result = 0; \ (regs)->nip = __ip; \ (regs)->gpr[1] = *(unsigned long *)__get_SP(); \ asm volatile("mfmsr %0" : "=r" ((regs)->msr)); \ diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c index 1818f63..dcb6a79 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c @@ -73,7 +73,10 @@ static inline u32 perf_get_misc_flags(struct pt_regs *regs) { return 0; } -static inline void perf_read_regs(struct pt_regs *regs) { } +static inline void perf_read_regs(struct pt_regs *regs) +{ + regs->result = 0; +} static inline int perf_intr_is_nmi(struct pt_regs *regs) { return 0; @@ -148,17 +151,9 @@ static inline u32 perf_flags_from_msr(struct pt_regs *regs) static inline u32 perf_get_misc_flags(struct pt_regs *regs) { unsigned long mmcra = regs->dsisr; + unsigned long use_siar = regs->result; - /* Not a PMU interrupt: Make up flags from regs->msr */ - if (TRAP(regs) != 0xf00) - return perf_flags_from_msr(regs); - - /* - * If we don't support continuous sampling and this - * is not a marked event, same deal - */ - if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) && - !(mmcra & MMCRA_SAMPLE_ENABLE)) + if (!use_siar) return perf_flags_from_msr(regs); /* @@ -185,10 +180,24 @@ static inline u32 perf_get_misc_flags(struct pt_regs *regs) /* * Overload regs->dsisr to store MMCRA so we only need to read it once * on each interrupt. + * Overload regs->result to specify whether we should use the MSR (result + * is zero) or the SIAR (result is non zero). */ static inline void perf_read_regs(struct pt_regs *regs) { - regs->dsisr = mfspr(SPRN_MMCRA); + unsigned long mmcra = mfspr(SPRN_MMCRA); + int marked = mmcra & MMCRA_SAMPLE_ENABLE; + int use_siar; + + if (TRAP(regs) != 0xf00) + use_siar = 0; + else if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) && !marked) + use_siar = 0; + else + use_siar = 1; + + regs->dsisr = mmcra; + regs->result = use_siar; } /* @@ -1342,18 +1351,12 @@ unsigned long perf_misc_flags(struct pt_regs *regs) */ unsigned long perf_instruction_pointer(struct pt_regs *regs) { - unsigned long mmcra = regs->dsisr; + unsigned long use_siar = regs->result; - /* Not a PMU interrupt */ - if (TRAP(regs) != 0xf00) - return regs->nip; - - /* Processor doesn't support sampling non marked events */ - if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) && - !(mmcra & MMCRA_SAMPLE_ENABLE)) + if (use_siar) + return mfspr(SPRN_SIAR) + perf_ip_adjust(regs); + else return regs->nip; - - return mfspr(SPRN_SIAR) + perf_ip_adjust(regs); } static bool pmc_overflow(unsigned long val) |