|
@@ -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)
|