Storing certain values in MMCR0 can cause PMU interrupts when msleep
enables MSR[EE], and this crashes the test. Freeze the PMU counters
and clear any PMU exception before calling msleep.

Signed-off-by: Nicholas Piggin <npig...@gmail.com>
---
 lib/powerpc/asm/reg.h |  4 ++++
 powerpc/sprs.c        | 17 +++++++++++------
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/lib/powerpc/asm/reg.h b/lib/powerpc/asm/reg.h
index 1f991288e..c80b32059 100644
--- a/lib/powerpc/asm/reg.h
+++ b/lib/powerpc/asm/reg.h
@@ -24,6 +24,10 @@
 #define   PVR_VER_POWER10      UL(0x00800000)
 #define SPR_HSRR0      0x13a
 #define SPR_HSRR1      0x13b
+#define SPR_MMCR0      0x31b
+#define   MMCR0_FC             UL(0x80000000)
+#define   MMCR0_PMAE           UL(0x04000000)
+#define   MMCR0_PMAO           UL(0x00000080)
 
 /* Machine State Register definitions: */
 #define MSR_EE_BIT     15                      /* External Interrupts Enable */
diff --git a/powerpc/sprs.c b/powerpc/sprs.c
index 44edd0d7b..cb1d6c980 100644
--- a/powerpc/sprs.c
+++ b/powerpc/sprs.c
@@ -476,12 +476,7 @@ static void set_sprs(uint64_t val)
                        continue;
                if (sprs[i].type & SPR_HARNESS)
                        continue;
-               if (!strcmp(sprs[i].name, "MMCR0")) {
-                       /* XXX: could use a comment or better abstraction! */
-                       __mtspr(i, (val & 0xfffffffffbab3fffULL) | 0xfa0b2070);
-               } else {
-                       __mtspr(i, val);
-               }
+               __mtspr(i, val);
        }
 }
 
@@ -538,6 +533,16 @@ int main(int argc, char **argv)
                if (sprs[895].name)
                        before[895] = mfspr(895);
        } else {
+               /*
+                * msleep will enable MSR[EE] and take a decrementer
+                * interrupt. Must account for changed registers and
+                * prevent taking unhandled interrupts.
+                */
+               /* Prevent PMU interrupt */
+               mtspr(SPR_MMCR0, (mfspr(SPR_MMCR0) | MMCR0_FC) &
+                                       ~(MMCR0_PMAO | MMCR0_PMAE));
+               before[SPR_MMCR0] = mfspr(SPR_MMCR0);
+               before[779] = mfspr(SPR_MMCR0);
                msleep(2000);
 
                /* Reload regs changed by dec interrupt */
-- 
2.42.0

Reply via email to