diff options
author | Nicholas Piggin <npiggin@gmail.com> | 2021-02-07 22:56:43 +1000 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2021-02-09 00:02:12 +1100 |
commit | fd3f1e0f139f1314ff97438eebaa1f9d216e10a2 (patch) | |
tree | 218e5c1fd5d3397d8f08fa67eeedac296612d5ed /arch/powerpc/kernel/traps.c | |
parent | 25b7e6bb743ca5a375bb89522a2c2bec840d5fc3 (diff) | |
download | linux-fd3f1e0f139f1314ff97438eebaa1f9d216e10a2.tar.gz |
powerpc/traps: factor common code from program check and emulation assist
Move the program check handling into a function called by both, rather
than have the emulation assist handler call the program check handler.
This allows each of these handlers to be implemented with "interrupt
wrappers" in a later change.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/1612702475.d6qyt6qtfy.astroid@bobo.none
Diffstat (limited to 'arch/powerpc/kernel/traps.c')
-rw-r--r-- | arch/powerpc/kernel/traps.c | 38 |
1 files changed, 24 insertions, 14 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index f70d3f6174c8ad..2c598610941209 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -1462,9 +1462,8 @@ static int emulate_math(struct pt_regs *regs) static inline int emulate_math(struct pt_regs *regs) { return -1; } #endif -void program_check_exception(struct pt_regs *regs) +static void do_program_check(struct pt_regs *regs) { - enum ctx_state prev_state = exception_enter(); unsigned int reason = get_reason(regs); /* We can now get here via a FP Unavailable exception if the core @@ -1473,22 +1472,22 @@ void program_check_exception(struct pt_regs *regs) if (reason & REASON_FP) { /* IEEE FP exception */ parse_fpe(regs); - goto bail; + return; } if (reason & REASON_TRAP) { unsigned long bugaddr; /* Debugger is first in line to stop recursive faults in * rcu_lock, notify_die, or atomic_notifier_call_chain */ if (debugger_bpt(regs)) - goto bail; + return; if (kprobe_handler(regs)) - goto bail; + return; /* trap exception */ if (notify_die(DIE_BPT, "breakpoint", regs, 5, 5, SIGTRAP) == NOTIFY_STOP) - goto bail; + return; bugaddr = regs->nip; /* @@ -1500,10 +1499,10 @@ void program_check_exception(struct pt_regs *regs) if (!(regs->msr & MSR_PR) && /* not user-mode */ report_bug(bugaddr, regs) == BUG_TRAP_TYPE_WARN) { regs->nip += 4; - goto bail; + return; } _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip); - goto bail; + return; } #ifdef CONFIG_PPC_TRANSACTIONAL_MEM if (reason & REASON_TM) { @@ -1524,7 +1523,7 @@ void program_check_exception(struct pt_regs *regs) */ if (user_mode(regs)) { _exception(SIGILL, regs, ILL_ILLOPN, regs->nip); - goto bail; + return; } else { printk(KERN_EMERG "Unexpected TM Bad Thing exception " "at %lx (msr 0x%lx) tm_scratch=%llx\n", @@ -1557,7 +1556,7 @@ void program_check_exception(struct pt_regs *regs) * pattern to occurrences etc. -dgibson 31/Mar/2003 */ if (!emulate_math(regs)) - goto bail; + return; /* Try to emulate it if we should. */ if (reason & (REASON_ILLEGAL | REASON_PRIVILEGED)) { @@ -1565,10 +1564,10 @@ void program_check_exception(struct pt_regs *regs) case 0: regs->nip += 4; emulate_single_step(regs); - goto bail; + return; case -EFAULT: _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip); - goto bail; + return; } } @@ -1578,7 +1577,14 @@ sigill: else _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); -bail: +} + +void program_check_exception(struct pt_regs *regs) +{ + enum ctx_state prev_state = exception_enter(); + + do_program_check(regs); + exception_exit(prev_state); } NOKPROBE_SYMBOL(program_check_exception); @@ -1589,8 +1595,12 @@ NOKPROBE_SYMBOL(program_check_exception); */ void emulation_assist_interrupt(struct pt_regs *regs) { + enum ctx_state prev_state = exception_enter(); + regs->msr |= REASON_ILLEGAL; - program_check_exception(regs); + do_program_check(regs); + + exception_exit(prev_state); } NOKPROBE_SYMBOL(emulation_assist_interrupt); |