mirror of https://gitee.com/openkylin/linux.git
powerpc/64: context tracking move to interrupt wrappers
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
This commit is contained in:
parent
a008f8f9fd
commit
540d4d34be
|
@ -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)
|
||||
|
|
|
@ -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 @@ static void do_program_check(struct pt_regs *regs)
|
|||
|
||||
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 @@ DEFINE_INTERRUPT_HANDLER(alignment_exception)
|
|||
_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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue