]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
powerpc/64s: Fix irq state management in runlatch functions
authorNicholas Piggin <npiggin@gmail.com>
Mon, 26 Sep 2022 05:43:02 +0000 (15:43 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Wed, 28 Sep 2022 09:22:11 +0000 (19:22 +1000)
When irqs are soft-disabled, MSR[EE] is volatile and can change from
1 to 0 asynchronously (if a PACA_IRQ_MUST_HARD_MASK interrupt hits).
So it can not be used to check hard IRQ enabled status, except to
confirm it is disabled.

ppc64_runlatch_on/off functions use MSR this way to decide whether to
re-enable MSR[EE] after disabling it, which leads to MSR[EE] being
enabled when it shouldn't be (when a PACA_IRQ_MUST_HARD_MASK had
disabled it between reading the MSR and clearing EE).

This has been tolerated in the kernel previously, and it doesn't seem
to cause a problem, but it is unexpected and may trip warnings or cause
other problems as we tighten up this state management. Fix this by only
re-enabling if PACA_IRQ_HARD_DIS is clear.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20220926054305.2671436-5-npiggin@gmail.com
arch/powerpc/include/asm/runlatch.h

index cfb390edf7d0112f6046e85c82fecaaa82c06b6f..ceb66d761fe1f7444317ec5797e2e0983da9e699 100644 (file)
@@ -19,10 +19,9 @@ extern void __ppc64_runlatch_off(void);
        do {                                                    \
                if (cpu_has_feature(CPU_FTR_CTRL) &&            \
                    test_thread_local_flags(_TLF_RUNLATCH)) {   \
-                       unsigned long msr = mfmsr();            \
                        __hard_irq_disable();                   \
                        __ppc64_runlatch_off();                 \
-                       if (msr & MSR_EE)                       \
+                       if (!(local_paca->irq_happened & PACA_IRQ_HARD_DIS)) \
                                __hard_irq_enable();            \
                }                                               \
        } while (0)
@@ -31,10 +30,9 @@ extern void __ppc64_runlatch_off(void);
        do {                                                    \
                if (cpu_has_feature(CPU_FTR_CTRL) &&            \
                    !test_thread_local_flags(_TLF_RUNLATCH)) {  \
-                       unsigned long msr = mfmsr();            \
                        __hard_irq_disable();                   \
                        __ppc64_runlatch_on();                  \
-                       if (msr & MSR_EE)                       \
+                       if (!(local_paca->irq_happened & PACA_IRQ_HARD_DIS)) \
                                __hard_irq_enable();            \
                }                                               \
        } while (0)