bl      hdlr;                                           \
        b       ret
 
+/*
+ * Exception where stack is already set in r1, r1 is saved in r10, and it
+ * continues rather than returns.
+ */
+#define EXCEPTION_COMMON_NORET_STACK(area, trap, label, hdlr, additions) \
+       EXCEPTION_PROLOG_COMMON_1();                            \
+       EXCEPTION_PROLOG_COMMON_2(area);                        \
+       EXCEPTION_PROLOG_COMMON_3(trap);                        \
+       /* Volatile regs are potentially clobbered here */      \
+       additions;                                              \
+       addi    r3,r1,STACK_FRAME_OVERHEAD;                     \
+       bl      hdlr
+
 #define STD_EXCEPTION_COMMON(trap, label, hdlr)                        \
        EXCEPTION_COMMON(PACA_EXGEN, trap, label, hdlr,         \
                ret_from_except, ADD_NVGPRS;ADD_RECONCILE)
 
        u64 exmc[13];           /* used for machine checks */
 #endif
 #ifdef CONFIG_PPC_BOOK3S_64
-       /* Exclusive emergency stack pointer for machine check exception. */
+       /* Exclusive stacks for system reset and machine check exception. */
+       void *nmi_emergency_sp;
        void *mc_emergency_sp;
 
        u16 in_nmi;                     /* In nmi handler */
 
        OFFSET(PACAEMERGSP, paca_struct, emergency_sp);
 #ifdef CONFIG_PPC_BOOK3S_64
        OFFSET(PACAMCEMERGSP, paca_struct, mc_emergency_sp);
+       OFFSET(PACA_NMI_EMERG_SP, paca_struct, nmi_emergency_sp);
        OFFSET(PACA_IN_MCE, paca_struct, in_mce);
        OFFSET(PACA_IN_NMI, paca_struct, in_nmi);
 #endif
 
        li      r10,MSR_RI
        mtmsrd  r10,1
 
-       EXCEPTION_COMMON(PACA_EXNMI, 0x100,
-                       system_reset, system_reset_exception, 1f,
+       mr      r10,r1
+       ld      r1,PACA_NMI_EMERG_SP(r13)
+       subi    r1,r1,INT_FRAME_SIZE
+       EXCEPTION_COMMON_NORET_STACK(PACA_EXNMI, 0x100,
+                       system_reset, system_reset_exception,
                        ADD_NVGPRS;ADD_RECONCILE)
-1: /* EXCEPTION_COMMON continues here */
 
        /*
         * The stack is no longer in use, decrement in_nmi.
 
                paca[i].emergency_sp = (void *)ti + THREAD_SIZE;
 
 #ifdef CONFIG_PPC_BOOK3S_64
+               /* emergency stack for NMI exception handling. */
+               ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
+               klp_init_thread_info(ti);
+               paca[i].nmi_emergency_sp = (void *)ti + THREAD_SIZE;
+
                /* emergency stack for machine check exception handling. */
                ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
                klp_init_thread_info(ti);
 
        DUMP(p, kernel_msr, "lx");
        DUMP(p, emergency_sp, "p");
 #ifdef CONFIG_PPC_BOOK3S_64
+       DUMP(p, nmi_emergency_sp, "p");
        DUMP(p, mc_emergency_sp, "p");
        DUMP(p, in_nmi, "x");
        DUMP(p, in_mce, "x");