[kvm-unit-tests PATCH v8 12/35] powerpc/sprs: Avoid taking PMU interrupts caused by register fuzzing

Nicholas Piggin
2024-04-05T08:36:35Z

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.

Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Nicholas Piggin <npiggin@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.43.0