summaryrefslogtreecommitdiff
path: root/arch/powerpc/kernel/traps.c
diff options
context:
space:
mode:
authorNicholas Piggin <npiggin@gmail.com>2021-01-30 23:08:33 +1000
committerMichael Ellerman <mpe@ellerman.id.au>2021-02-09 00:02:11 +1100
commit209e9d500e25eada096b2c09a34093bc458166f3 (patch)
treef2f9b5484471d2f641c25ea289ca4e398a02657f /arch/powerpc/kernel/traps.c
parentdcdb4f12963f3f4200e24e1dad78564a98736f67 (diff)
powerpc: introduce die_mce
As explained by commit daf00ae71dad ("powerpc/traps: restore recoverability of machine_check interrupts"), die() can't be called from within nmi_enter to nicely kill a process context that was interrupted. nmi_exit must be called first. This adds a function die_mce which takes care of this for machine check handlers. 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-24-npiggin@gmail.com
Diffstat (limited to 'arch/powerpc/kernel/traps.c')
-rw-r--r--arch/powerpc/kernel/traps.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 6691774fe1fb..f9ef183a5454 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -789,6 +789,19 @@ int machine_check_generic(struct pt_regs *regs)
}
#endif /* everything else */
+void die_mce(const char *str, struct pt_regs *regs, long err)
+{
+ /*
+ * The machine check wants to kill the interrupted context, but
+ * do_exit() checks for in_interrupt() and panics in that case, so
+ * exit the irq/nmi before calling die.
+ */
+ if (!IS_ENABLED(CONFIG_PPC_BOOK3S_64))
+ nmi_exit();
+ die(str, regs, err);
+}
+NOKPROBE_SYMBOL(die_mce);
+
void machine_check_exception(struct pt_regs *regs)
{
int recover = 0;
@@ -831,15 +844,11 @@ void machine_check_exception(struct pt_regs *regs)
if (check_io_access(regs))
goto bail;
- if (nmi) nmi_exit();
-
- die("Machine check", regs, SIGBUS);
+ die_mce("Machine check", regs, SIGBUS);
/* Must die if the interrupt is not recoverable */
if (!(regs->msr & MSR_RI))
- die("Unrecoverable Machine check", regs, SIGBUS);
-
- return;
+ die_mce("Unrecoverable Machine check", regs, SIGBUS);
bail:
if (nmi) nmi_exit();