powerpc/64s: move NMI soft-mask handling to C
authorNicholas Piggin <npiggin@gmail.com>
Sat, 30 Jan 2021 13:08:50 +0000 (23:08 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Mon, 8 Feb 2021 13:10:50 +0000 (00:10 +1100)
Saving and restoring soft-mask state can now be done in C using the
interrupt handler wrapper functions.

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

index cd819d4..72a5850 100644 (file)
@@ -95,6 +95,10 @@ static inline void interrupt_async_exit_prepare(struct pt_regs *regs, struct int
 
 struct interrupt_nmi_state {
 #ifdef CONFIG_PPC64
+#ifdef CONFIG_PPC_BOOK3S_64
+       u8 irq_soft_mask;
+       u8 irq_happened;
+#endif
        u8 ftrace_enabled;
 #endif
 };
@@ -102,6 +106,20 @@ struct interrupt_nmi_state {
 static inline void interrupt_nmi_enter_prepare(struct pt_regs *regs, struct interrupt_nmi_state *state)
 {
 #ifdef CONFIG_PPC64
+#ifdef CONFIG_PPC_BOOK3S_64
+       state->irq_soft_mask = local_paca->irq_soft_mask;
+       state->irq_happened = local_paca->irq_happened;
+
+       /*
+        * Set IRQS_ALL_DISABLED unconditionally so irqs_disabled() does
+        * the right thing, and set IRQ_HARD_DIS. We do not want to reconcile
+        * because that goes through irq tracing which we don't want in NMI.
+        */
+       local_paca->irq_soft_mask = IRQS_ALL_DISABLED;
+       local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
+
+       /* Don't do any per-CPU operations until interrupt state is fixed */
+#endif
        /* Allow DEC and PMI to be traced when they are soft-NMI */
        if (TRAP(regs) != 0x900 && TRAP(regs) != 0xf00 && TRAP(regs) != 0x260) {
                state->ftrace_enabled = this_cpu_get_ftrace_enabled();
@@ -129,6 +147,13 @@ static inline void interrupt_nmi_exit_prepare(struct pt_regs *regs, struct inter
 #ifdef CONFIG_PPC64
        if (TRAP(regs) != 0x900 && TRAP(regs) != 0xf00 && TRAP(regs) != 0x260)
                this_cpu_set_ftrace_enabled(state->ftrace_enabled);
+
+#ifdef CONFIG_PPC_BOOK3S_64
+       /* Check we didn't change the pending interrupt mask. */
+       WARN_ON_ONCE((state->irq_happened | PACA_IRQ_HARD_DIS) != local_paca->irq_happened);
+       local_paca->irq_happened = state->irq_happened;
+       local_paca->irq_soft_mask = state->irq_soft_mask;
+#endif
 #endif
 }
 
index 898698c..ec3e834 100644 (file)
@@ -1008,20 +1008,6 @@ EXC_COMMON_BEGIN(system_reset_common)
        ld      r1,PACA_NMI_EMERG_SP(r13)
        subi    r1,r1,INT_FRAME_SIZE
        __GEN_COMMON_BODY system_reset
-       /*
-        * Set IRQS_ALL_DISABLED unconditionally so irqs_disabled() does
-        * the right thing. We do not want to reconcile because that goes
-        * through irq tracing which we don't want in NMI.
-        *
-        * Save PACAIRQHAPPENED to RESULT (otherwise unused), and set HARD_DIS
-        * as we are running with MSR[EE]=0.
-        */
-       li      r10,IRQS_ALL_DISABLED
-       stb     r10,PACAIRQSOFTMASK(r13)
-       lbz     r10,PACAIRQHAPPENED(r13)
-       std     r10,RESULT(r1)
-       ori     r10,r10,PACA_IRQ_HARD_DIS
-       stb     r10,PACAIRQHAPPENED(r13)
 
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      system_reset_exception
@@ -1037,14 +1023,6 @@ EXC_COMMON_BEGIN(system_reset_common)
        subi    r10,r10,1
        sth     r10,PACA_IN_NMI(r13)
 
-       /*
-        * Restore soft mask settings.
-        */
-       ld      r10,RESULT(r1)
-       stb     r10,PACAIRQHAPPENED(r13)
-       ld      r10,SOFTE(r1)
-       stb     r10,PACAIRQSOFTMASK(r13)
-
        kuap_kernel_restore r9, r10
        EXCEPTION_RESTORE_REGS
        RFI_TO_USER_OR_KERNEL
@@ -1190,30 +1168,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
        li      r10,MSR_RI
        mtmsrd  r10,1
 
-       /*
-        * 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,RESULT(r1)
-       ori     r10,r10,PACA_IRQ_HARD_DIS
-       stb     r10,PACAIRQHAPPENED(r13)
-
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      machine_check_early
        std     r3,RESULT(r1)   /* Save result */
        ld      r12,_MSR(r1)
 
-       /*
-        * Restore soft mask settings.
-        */
-       ld      r10,RESULT(r1)
-       stb     r10,PACAIRQHAPPENED(r13)
-       ld      r10,SOFTE(r1)
-       stb     r10,PACAIRQSOFTMASK(r13)
-
 #ifdef CONFIG_PPC_P7_NAP
        /*
         * Check if thread was in power saving mode. We come here when any
@@ -2818,17 +2777,6 @@ EXC_COMMON_BEGIN(soft_nmi_common)
        subi    r1,r1,INT_FRAME_SIZE
        __GEN_COMMON_BODY soft_nmi
 
-       /*
-        * 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,RESULT(r1)
-       ori     r10,r10,PACA_IRQ_HARD_DIS
-       stb     r10,PACAIRQHAPPENED(r13)
-
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      soft_nmi_interrupt
 
@@ -2836,14 +2784,6 @@ EXC_COMMON_BEGIN(soft_nmi_common)
        li      r9,0
        mtmsrd  r9,1
 
-       /*
-        * Restore soft mask settings.
-        */
-       ld      r10,RESULT(r1)
-       stb     r10,PACAIRQHAPPENED(r13)
-       ld      r10,SOFTE(r1)
-       stb     r10,PACAIRQSOFTMASK(r13)
-
        kuap_kernel_restore r9, r10
        EXCEPTION_RESTORE_REGS hsrr=0
        RFI_TO_KERNEL