powerpc/64s/exception: Soft NMI interrupt should not use ret_from_except
authorNicholas Piggin <npiggin@gmail.com>
Tue, 25 Feb 2020 17:35:31 +0000 (03:35 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Wed, 1 Apr 2020 02:42:13 +0000 (13:42 +1100)
The soft NMI handler does not reconcile interrupt state, so it should
not return via the normal ret_from_except path. Return like other NMIs,
using the EXCEPTION_RESTORE_REGS macro.

This becomes important when the scv interrupt is implemented, which
must handle soft-masked interrupts that have r13 set to something
other than the PACA -- returning to kernel in this case must restore
r13.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200225173541.1549955-23-npiggin@gmail.com
arch/powerpc/kernel/exceptions-64s.S

index 3ddabac..d75df22 100644 (file)
@@ -2731,6 +2731,7 @@ EXC_VIRT_NONE(0x5800, 0x100)
 INT_DEFINE_BEGIN(soft_nmi)
        IVEC=0x900
        ISTACK=0
+       IRECONCILE=0    /* Soft-NMI may fire under local_irq_disable */
 INT_DEFINE_END(soft_nmi)
 
 /*
@@ -2749,9 +2750,36 @@ EXC_COMMON_BEGIN(soft_nmi_common)
        subi    r1,r1,INT_FRAME_SIZE
        __GEN_COMMON_BODY soft_nmi
        bl      save_nvgprs
+
+       /*
+        * Set IRQS_ALL_DISABLED and save PACAIRQHAPPENED (see
+        * system_reset_common)
+        */
+       li      r10,IRQS_ALL_DISABLED
+       stb     r10,PACAIRQSOFTMASK(r13)
+       lbz     r10,PACAIRQHAPPENED(r13)
+       std     r10,_DAR(r1)
+       ori     r10,r10,PACA_IRQ_HARD_DIS
+       stb     r10,PACAIRQHAPPENED(r13)
+
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      soft_nmi_interrupt
-       b       ret_from_except
+
+       /* Clear MSR_RI before setting SRR0 and SRR1. */
+       li      r9,0
+       mtmsrd  r9,1
+
+       /*
+        * Restore soft mask settings.
+        */
+       ld      r10,_DAR(r1)
+       stb     r10,PACAIRQHAPPENED(r13)
+       ld      r10,SOFTE(r1)
+       stb     r10,PACAIRQSOFTMASK(r13)
+
+       kuap_restore_amr r10
+       EXCEPTION_RESTORE_REGS hsrr=0
+       RFI_TO_KERNEL
 
 #endif /* CONFIG_PPC_WATCHDOG */