|
@@ -140,6 +140,9 @@ static bool regs_sihv(struct pt_regs *regs)
|
|
|
{
|
|
|
unsigned long sihv = MMCRA_SIHV;
|
|
|
|
|
|
+ if (ppmu->flags & PPMU_HAS_SIER)
|
|
|
+ return !!(regs->dar & SIER_SIHV);
|
|
|
+
|
|
|
if (ppmu->flags & PPMU_ALT_SIPR)
|
|
|
sihv = POWER6_MMCRA_SIHV;
|
|
|
|
|
@@ -150,6 +153,9 @@ static bool regs_sipr(struct pt_regs *regs)
|
|
|
{
|
|
|
unsigned long sipr = MMCRA_SIPR;
|
|
|
|
|
|
+ if (ppmu->flags & PPMU_HAS_SIER)
|
|
|
+ return !!(regs->dar & SIER_SIPR);
|
|
|
+
|
|
|
if (ppmu->flags & PPMU_ALT_SIPR)
|
|
|
sipr = POWER6_MMCRA_SIPR;
|
|
|
|
|
@@ -203,6 +209,7 @@ 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->dar to store SIER if we have it.
|
|
|
* Overload regs->result to specify whether we should use the MSR (result
|
|
|
* is zero) or the SIAR (result is non zero).
|
|
|
*/
|
|
@@ -218,6 +225,18 @@ static inline void perf_read_regs(struct pt_regs *regs)
|
|
|
if (ppmu->flags & PPMU_NO_SIPR)
|
|
|
regs->result |= 2;
|
|
|
|
|
|
+ /*
|
|
|
+ * On power8 if we're in random sampling mode, the SIER is updated.
|
|
|
+ * If we're in continuous sampling mode, we don't have SIPR.
|
|
|
+ */
|
|
|
+ if (ppmu->flags & PPMU_HAS_SIER) {
|
|
|
+ if (marked)
|
|
|
+ regs->dar = mfspr(SPRN_SIER);
|
|
|
+ else
|
|
|
+ regs->result |= 2;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
/*
|
|
|
* If this isn't a PMU exception (eg a software event) the SIAR is
|
|
|
* not valid. Use pt_regs.
|