powerpc/64s/exception: treat NIA below __end_interrupts as soft-masked
authorNicholas Piggin <npiggin@gmail.com>
Thu, 11 Jun 2020 08:12:02 +0000 (18:12 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Wed, 22 Jul 2020 13:00:23 +0000 (23:00 +1000)
The scv instruction causes an interrupt which can enter the kernel with
MSR[EE]=1, thus allowing interrupts to hit at any time. These must not
be taken as normal interrupts, because they come from MSR[PR]=0 context,
and yet the kernel stack is not yet set up and r13 is not set to the
PACA).

Treat this as a soft-masked interrupt regardless of the soft masked
state. This does not affect behaviour yet, because currently all
interrupts are taken with MSR[EE]=0.

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

index fa08069..f15307c 100644 (file)
@@ -508,8 +508,24 @@ DEFINE_FIXED_SYMBOL(\name\()_common_real)
 
 .macro __GEN_COMMON_BODY name
        .if IMASK
+               .if ! ISTACK
+               .error "No support for masked interrupt to use custom stack"
+               .endif
+
+               /* If coming from user, skip soft-mask tests. */
+               andi.   r10,r12,MSR_PR
+               bne     2f
+
+               /* Kernel code running below __end_interrupts is implicitly
+                * soft-masked */
+               LOAD_HANDLER(r10, __end_interrupts)
+               cmpld   r11,r10
+               li      r10,IMASK
+               blt-    1f
+
+               /* Test the soft mask state against our interrupt's bit */
                lbz     r10,PACAIRQSOFTMASK(r13)
-               andi.   r10,r10,IMASK
+1:             andi.   r10,r10,IMASK
                /* Associate vector numbers with bits in paca->irq_happened */
                .if IVEC == 0x500 || IVEC == 0xea0
                li      r10,PACA_IRQ_EE
@@ -540,7 +556,7 @@ DEFINE_FIXED_SYMBOL(\name\()_common_real)
 
        .if ISTACK
        andi.   r10,r12,MSR_PR          /* See if coming from user      */
-       mr      r10,r1                  /* Save r1                      */
+2:     mr      r10,r1                  /* Save r1                      */
        subi    r1,r1,INT_FRAME_SIZE    /* alloc frame on kernel stack  */
        beq-    100f
        ld      r1,PACAKSAVE(r13)       /* kernel stack to use          */
@@ -2838,7 +2854,8 @@ masked_interrupt:
        ld      r10,PACA_EXGEN+EX_R10(r13)
        ld      r11,PACA_EXGEN+EX_R11(r13)
        ld      r12,PACA_EXGEN+EX_R12(r13)
-       /* returns to kernel where r13 must be set up, so don't restore it */
+       ld      r13,PACA_EXGEN+EX_R13(r13)
+       /* May return to masked low address where r13 is not set up */
        .if \hsrr
        HRFI_TO_KERNEL
        .else
@@ -2997,6 +3014,10 @@ EXC_COMMON_BEGIN(ppc64_runlatch_on_trampoline)
 
 USE_FIXED_SECTION(virt_trampolines)
        /*
+        * All code below __end_interrupts is treated as soft-masked. If
+        * any code runs here with MSR[EE]=1, it must then cope with pending
+        * soft interrupt being raised (i.e., by ensuring it is replayed).
+        *
         * The __end_interrupts marker must be past the out-of-line (OOL)
         * handlers, so that they are copied to real address 0x100 when running
         * a relocatable kernel. This ensures they can be reached from the short