powerpc/64: treat low kernel text as irqs soft-masked
authorNicholas Piggin <npiggin@gmail.com>
Thu, 17 Jun 2021 15:51:10 +0000 (01:51 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Thu, 24 Jun 2021 14:06:56 +0000 (00:06 +1000)
Treat code below __end_soft_masked as soft-masked for the purpose
of alternate return. 64s already mostly does this for scv entry.

This will be used to exit from interrupts without disabling MSR[EE].

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20210617155116.2167984-12-npiggin@gmail.com
arch/powerpc/include/asm/interrupt.h
arch/powerpc/kernel/exceptions-64e.S
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/interrupt_64.S

index a4bf6c0013bb1d967694ade8241b24837e113b74..832079e824bdc6dd76cfc6cab8f6aa3fbc03d80b 100644 (file)
@@ -146,8 +146,13 @@ static inline void interrupt_enter_prepare(struct pt_regs *regs, struct interrup
                 * CT_WARN_ON comes here via program_check_exception,
                 * so avoid recursion.
                 */
-               if (TRAP(regs) != INTERRUPT_PROGRAM)
+               if (TRAP(regs) != INTERRUPT_PROGRAM) {
                        CT_WARN_ON(ct_state() != CONTEXT_KERNEL);
+                       BUG_ON(regs->nip < (unsigned long)__end_soft_masked);
+               }
+               /* Move this under a debugging check */
+               if (arch_irq_disabled_regs(regs))
+                       BUG_ON(search_kernel_restart_table(regs->nip));
        }
 #endif
 
@@ -238,8 +243,8 @@ static inline void interrupt_nmi_enter_prepare(struct pt_regs *regs, struct inte
        local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
 
        if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && !(regs->msr & MSR_PR) &&
-                               regs->nip < (unsigned long)__end_interrupts) {
-               // Kernel code running below __end_interrupts is
+                               regs->nip < (unsigned long)__end_soft_masked) {
+               // Kernel code running below __end_soft_masked is
                // implicitly soft-masked.
                regs->softe = IRQS_ALL_DISABLED;
        }
index 1b79f8a75298e6c31a8e87dbd4a0f025fe14d09d..22fcd95dd8dc9928a0b3ecb6fb4104da6409eeb7 100644 (file)
@@ -342,7 +342,17 @@ ret_from_mc_except:
 #define PROLOG_ADDITION_MASKABLE_GEN(n)                                            \
        lbz     r10,PACAIRQSOFTMASK(r13);       /* are irqs soft-masked? */ \
        andi.   r10,r10,IRQS_DISABLED;  /* yes -> go out of line */ \
-       bne     masked_interrupt_book3e_##n
+       bne     masked_interrupt_book3e_##n;                                \
+       /* Kernel code below __end_soft_masked is implicitly masked */      \
+       andi.   r10,r11,MSR_PR;                                             \
+       bne     1f;                     /* user -> not masked */            \
+       std     r14,PACA_EXGEN+EX_R14(r13);                                 \
+       LOAD_REG_IMMEDIATE_SYM(r14, r10, __end_soft_masked);                \
+       mfspr   r10,SPRN_SRR0;                                              \
+       cmpld   r10,r14;                                                    \
+       ld      r14,PACA_EXGEN+EX_R14(r13);                                 \
+       blt     masked_interrupt_book3e_##n;                                \
+1:
 
 /*
  * Additional regs must be re-loaded from paca before EXCEPTION_COMMON* is
index b8ed1ce8c34718b7aad0ee7755ededa2d4d37c95..ecd07bf604c58fef805aec4b70b7dea5a10df89b 100644 (file)
@@ -430,10 +430,13 @@ DEFINE_FIXED_SYMBOL(\name\()_common_real)
                andi.   r10,r12,MSR_PR
                bne     2f
 
-               /* Kernel code running below __end_interrupts is implicitly
-                * soft-masked */
-               LOAD_HANDLER(r10, __end_interrupts)
+               /*
+                * Kernel code running below __end_soft_masked is implicitly
+                * soft-masked
+                */
+               LOAD_HANDLER(r10, __end_soft_masked)
                cmpld   r11,r10
+
                li      r10,IMASK
                blt-    1f
 
@@ -751,17 +754,17 @@ __start_interrupts:
  * scv instructions enter the kernel without changing EE, RI, ME, or HV.
  * In particular, this means we can take a maskable interrupt at any point
  * in the scv handler, which is unlike any other interrupt. This is solved
- * by treating the instruction addresses below __end_interrupts as being
+ * by treating the instruction addresses below __end_soft_masked as being
  * soft-masked.
  *
  * AIL-0 mode scv exceptions go to 0x17000-0x17fff, but we set AIL-3 and
  * ensure scv is never executed with relocation off, which means AIL-0
  * should never happen.
  *
- * Before leaving the below __end_interrupts text, at least of the following
- * must be true:
+ * Before leaving the following inside-__end_soft_masked text, at least of the
+ * following must be true:
  * - MSR[PR]=1 (i.e., return to userspace)
- * - MSR_EE|MSR_RI is set (no reentrant exceptions)
+ * - MSR_EE|MSR_RI is clear (no reentrant exceptions)
  * - Standard kernel environment is set up (stack, paca, etc)
  *
  * Call convention:
@@ -2957,7 +2960,7 @@ MASKED_INTERRUPT hsrr=1
 
 USE_FIXED_SECTION(virt_trampolines)
        /*
-        * All code below __end_interrupts is treated as soft-masked. If
+        * All code below __end_soft_masked 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).
         *
index ab6b99609d0ec8ead77769ad37aa665797341c31..33ee83791487b33e3ada6cec387f7e28c4a9df46 100644 (file)
@@ -632,4 +632,8 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
 interrupt_return_macro srr
 #ifdef CONFIG_PPC_BOOK3S
 interrupt_return_macro hsrr
-#endif
+#endif /* CONFIG_PPC_BOOK3S */
+
+       .globl __end_soft_masked
+__end_soft_masked:
+DEFINE_FIXED_SYMBOL(__end_soft_masked)