powerpc/64: context tracking move to interrupt wrappers
authorNicholas Piggin <npiggin@gmail.com>
Sat, 30 Jan 2021 13:08:42 +0000 (23:08 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Mon, 8 Feb 2021 13:10:46 +0000 (00:10 +1100)
This moves exception_enter/exit calls to wrapper functions for
synchronous interrupts. More interrupt handlers are covered by
this than previously.

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-33-npiggin@gmail.com
arch/powerpc/include/asm/interrupt.h
arch/powerpc/kernel/traps.c
arch/powerpc/mm/book3s64/hash_utils.c
arch/powerpc/mm/fault.c

index 488bdd5..e65ce3e 100644 (file)
@@ -7,10 +7,16 @@
 #include <asm/ftrace.h>
 
 struct interrupt_state {
+#ifdef CONFIG_PPC64
+       enum ctx_state ctx_state;
+#endif
 };
 
 static inline void interrupt_enter_prepare(struct pt_regs *regs, struct interrupt_state *state)
 {
+#ifdef CONFIG_PPC64
+       state->ctx_state = exception_enter();
+#endif
 }
 
 /*
@@ -29,6 +35,9 @@ static inline void interrupt_enter_prepare(struct pt_regs *regs, struct interrup
  */
 static inline void interrupt_exit_prepare(struct pt_regs *regs, struct interrupt_state *state)
 {
+#ifdef CONFIG_PPC64
+       exception_exit(state->ctx_state);
+#endif
 }
 
 static inline void interrupt_async_enter_prepare(struct pt_regs *regs, struct interrupt_state *state)
index 20c90a3..9c26fb4 100644 (file)
@@ -1087,41 +1087,28 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(handle_hmi_exception)
 
 DEFINE_INTERRUPT_HANDLER(unknown_exception)
 {
-       enum ctx_state prev_state = exception_enter();
-
        printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
               regs->nip, regs->msr, regs->trap);
 
        _exception(SIGTRAP, regs, TRAP_UNK, 0);
-
-       exception_exit(prev_state);
 }
 
 DEFINE_INTERRUPT_HANDLER_ASYNC(unknown_async_exception)
 {
-       enum ctx_state prev_state = exception_enter();
-
        printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
               regs->nip, regs->msr, regs->trap);
 
        _exception(SIGTRAP, regs, TRAP_UNK, 0);
-
-       exception_exit(prev_state);
 }
 
 DEFINE_INTERRUPT_HANDLER(instruction_breakpoint_exception)
 {
-       enum ctx_state prev_state = exception_enter();
-
        if (notify_die(DIE_IABR_MATCH, "iabr_match", regs, 5,
                                        5, SIGTRAP) == NOTIFY_STOP)
-               goto bail;
+               return;
        if (debugger_iabr_match(regs))
-               goto bail;
+               return;
        _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
-
-bail:
-       exception_exit(prev_state);
 }
 
 DEFINE_INTERRUPT_HANDLER(RunModeException)
@@ -1131,8 +1118,6 @@ DEFINE_INTERRUPT_HANDLER(RunModeException)
 
 DEFINE_INTERRUPT_HANDLER(single_step_exception)
 {
-       enum ctx_state prev_state = exception_enter();
-
        clear_single_step(regs);
        clear_br_trace(regs);
 
@@ -1141,14 +1126,11 @@ DEFINE_INTERRUPT_HANDLER(single_step_exception)
 
        if (notify_die(DIE_SSTEP, "single_step", regs, 5,
                                        5, SIGTRAP) == NOTIFY_STOP)
-               goto bail;
+               return;
        if (debugger_sstep(regs))
-               goto bail;
+               return;
 
        _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
-
-bail:
-       exception_exit(prev_state);
 }
 NOKPROBE_SYMBOL(single_step_exception);
 
@@ -1591,11 +1573,7 @@ sigill:
 
 DEFINE_INTERRUPT_HANDLER(program_check_exception)
 {
-       enum ctx_state prev_state = exception_enter();
-
        do_program_check(regs);
-
-       exception_exit(prev_state);
 }
 NOKPROBE_SYMBOL(program_check_exception);
 
@@ -1605,25 +1583,19 @@ NOKPROBE_SYMBOL(program_check_exception);
  */
 DEFINE_INTERRUPT_HANDLER(emulation_assist_interrupt)
 {
-       enum ctx_state prev_state = exception_enter();
-
        regs->msr |= REASON_ILLEGAL;
        do_program_check(regs);
-
-       exception_exit(prev_state);
 }
 NOKPROBE_SYMBOL(emulation_assist_interrupt);
 
 DEFINE_INTERRUPT_HANDLER(alignment_exception)
 {
-       enum ctx_state prev_state = exception_enter();
        int sig, code, fixed = 0;
        unsigned long  reason;
 
        interrupt_cond_local_irq_enable(regs);
 
        reason = get_reason(regs);
-
        if (reason & REASON_BOUNDARY) {
                sig = SIGBUS;
                code = BUS_ADRALN;
@@ -1631,7 +1603,7 @@ DEFINE_INTERRUPT_HANDLER(alignment_exception)
        }
 
        if (tm_abort_check(regs, TM_CAUSE_ALIGNMENT | TM_CAUSE_PERSISTENT))
-               goto bail;
+               return;
 
        /* we don't implement logging of alignment exceptions */
        if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS))
@@ -1641,7 +1613,7 @@ DEFINE_INTERRUPT_HANDLER(alignment_exception)
                /* skip over emulated instruction */
                regs->nip += inst_length(reason);
                emulate_single_step(regs);
-               goto bail;
+               return;
        }
 
        /* Operand address was bad */
@@ -1657,9 +1629,6 @@ bad:
                _exception(sig, regs, code, regs->dar);
        else
                bad_page_fault(regs, sig);
-
-bail:
-       exception_exit(prev_state);
 }
 
 DEFINE_INTERRUPT_HANDLER(StackOverflow)
@@ -1673,41 +1642,28 @@ DEFINE_INTERRUPT_HANDLER(StackOverflow)
 
 DEFINE_INTERRUPT_HANDLER(stack_overflow_exception)
 {
-       enum ctx_state prev_state = exception_enter();
-
        die("Kernel stack overflow", regs, SIGSEGV);
-
-       exception_exit(prev_state);
 }
 
 DEFINE_INTERRUPT_HANDLER(kernel_fp_unavailable_exception)
 {
-       enum ctx_state prev_state = exception_enter();
-
        printk(KERN_EMERG "Unrecoverable FP Unavailable Exception "
                          "%lx at %lx\n", regs->trap, regs->nip);
        die("Unrecoverable FP Unavailable Exception", regs, SIGABRT);
-
-       exception_exit(prev_state);
 }
 
 DEFINE_INTERRUPT_HANDLER(altivec_unavailable_exception)
 {
-       enum ctx_state prev_state = exception_enter();
-
        if (user_mode(regs)) {
                /* A user program has executed an altivec instruction,
                   but this kernel doesn't support altivec. */
                _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
-               goto bail;
+               return;
        }
 
        printk(KERN_EMERG "Unrecoverable VMX/Altivec Unavailable Exception "
                        "%lx at %lx\n", regs->trap, regs->nip);
        die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT);
-
-bail:
-       exception_exit(prev_state);
 }
 
 DEFINE_INTERRUPT_HANDLER(vsx_unavailable_exception)
index d681dc5..fb7c105 100644 (file)
@@ -1514,7 +1514,6 @@ EXPORT_SYMBOL_GPL(hash_page);
 DECLARE_INTERRUPT_HANDLER_RET(__do_hash_fault);
 DEFINE_INTERRUPT_HANDLER_RET(__do_hash_fault)
 {
-       enum ctx_state prev_state = exception_enter();
        unsigned long ea = regs->dar;
        unsigned long dsisr = regs->dsisr;
        unsigned long access = _PAGE_PRESENT | _PAGE_READ;
@@ -1563,8 +1562,6 @@ DEFINE_INTERRUPT_HANDLER_RET(__do_hash_fault)
                err = 0;
        }
 
-       exception_exit(prev_state);
-
        return err;
 }
 
index 9c4220e..b26a764 100644 (file)
@@ -564,14 +564,7 @@ NOKPROBE_SYMBOL(__do_page_fault);
 
 DEFINE_INTERRUPT_HANDLER_RET(do_page_fault)
 {
-       enum ctx_state prev_state = exception_enter();
-       long err;
-
-       err = __do_page_fault(regs);
-
-       exception_exit(prev_state);
-
-       return err;
+       return __do_page_fault(regs);
 }
 NOKPROBE_SYMBOL(do_page_fault);