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>
This commit is contained in:
parent
68b30bb9f0
commit
75382aa72f
2 changed files with 30 additions and 22 deletions
|
@ -26,8 +26,13 @@
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
#include <asm/reg.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) \
|
#define perf_arch_fetch_caller_regs(regs, __ip) \
|
||||||
do { \
|
do { \
|
||||||
|
(regs)->result = 0; \
|
||||||
(regs)->nip = __ip; \
|
(regs)->nip = __ip; \
|
||||||
(regs)->gpr[1] = *(unsigned long *)__get_SP(); \
|
(regs)->gpr[1] = *(unsigned long *)__get_SP(); \
|
||||||
asm volatile("mfmsr %0" : "=r" ((regs)->msr)); \
|
asm volatile("mfmsr %0" : "=r" ((regs)->msr)); \
|
||||||
|
|
|
@ -73,7 +73,10 @@ static inline u32 perf_get_misc_flags(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
return 0;
|
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)
|
static inline int perf_intr_is_nmi(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
return 0;
|
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)
|
static inline u32 perf_get_misc_flags(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
unsigned long mmcra = regs->dsisr;
|
unsigned long mmcra = regs->dsisr;
|
||||||
|
unsigned long use_siar = regs->result;
|
||||||
|
|
||||||
/* Not a PMU interrupt: Make up flags from regs->msr */
|
if (!use_siar)
|
||||||
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))
|
|
||||||
return perf_flags_from_msr(regs);
|
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
|
* Overload regs->dsisr to store MMCRA so we only need to read it once
|
||||||
* on each interrupt.
|
* 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)
|
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 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))
|
|
||||||
return regs->nip;
|
|
||||||
|
|
||||||
|
if (use_siar)
|
||||||
return mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
|
return mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
|
||||||
|
else
|
||||||
|
return regs->nip;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool pmc_overflow(unsigned long val)
|
static bool pmc_overflow(unsigned long val)
|
||||||
|
|
Loading…
Add table
Reference in a new issue