System reset is a non-maskable interrupt from Linux's point of view
(occurs under local_irq_disable()), so it should use nmi_enter/exit.

Signed-off-by: Nicholas Piggin <npig...@gmail.com>
---
 arch/powerpc/kernel/traps.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 802aa6bbe97b..c65c88fb6482 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -278,6 +278,14 @@ void _exception(int signr, struct pt_regs *regs, int code, 
unsigned long addr)
 
 void system_reset_exception(struct pt_regs *regs)
 {
+       /*
+        * Avoid crashes in case of nested NMI exceptions. Recoverability
+        * is determined by RI and in_nmi
+        */
+       bool nested = in_nmi();
+       if (!nested)
+               nmi_enter();
+
        /* See if any machine dependent calls */
        if (ppc_md.system_reset_exception) {
                if (ppc_md.system_reset_exception(regs))
@@ -296,6 +304,9 @@ void system_reset_exception(struct pt_regs *regs)
        if (!(regs->msr & MSR_RI))
                panic("Unrecoverable System Reset");
 
+       if (!nested)
+               nmi_exit();
+
        /* What should we do here? We could issue a shutdown or hard reset. */
 }
 
-- 
2.11.0

Reply via email to