diff --git a/asm/head.S b/asm/head.S
index 4a00532df..696d168d4 100644
--- a/asm/head.S
+++ b/asm/head.S
@@ -119,6 +119,31 @@ hdat_entry:
 	li	%r27,0
 	b	boot_entry
 
+	.= 0x200
+	mtsprg0	%r3
+	mtsprg1 %r4
+	mfspr	%r3,SPR_SRR1
+	mfcr	%r4
+	rldicl.	%r3,%r3,48,62
+	bne	1f		/* powersave wakeup (CFAR not required) */
+	mtcr	%r4
+	mfspr	%r3,SPR_CFAR
+	li	%r4,0x200
+	b	_exception
+1:
+	LOAD_IMM64(%r30, SKIBOOT_BASE)
+	cmpdi	%r3,0x1
+	bne	2f		/* state loss */
+	LOAD_IMM32(%r3, reset_resume - __head)
+	b	3f
+2:
+	LOAD_IMM32(%r3, reset_wakeup - __head)
+3:
+	add	%r3,%r30,%r3
+	mtctr	%r3
+	li	%r3,0x200
+	bctr
+
 #define EXCEPTION(nr)		\
 	.= nr			;\
 	mtsprg0	%r3		;\
@@ -128,7 +153,6 @@ hdat_entry:
 	b	_exception
 
 	/* More exception stubs */
-	EXCEPTION(0x200)
 	EXCEPTION(0x300)
 	EXCEPTION(0x380)
 	EXCEPTION(0x400)
@@ -667,7 +691,8 @@ enter_p9_pm_state:
 	b	.
 
 /* This is a little piece of code that is copied down to
- * 0x100 for handling power management wakeups
+ * 0x100 for handling sresets and power management wakeups.
+ * This matches the 0x200 handler closely.
  */
 .global reset_patch_start
 reset_patch_start:
@@ -692,10 +717,12 @@ reset_patch_start:
 3:
 	add	%r3,%r30,%r3
 	mtctr	%r3
+	li	%r3,0x100
 	bctr
 .global reset_patch_end
 reset_patch_end:
 
+/* Wakeup vector in r3 */
 reset_wakeup:
 	/* Get PIR */
 	mfspr	%r31,SPR_PIR
@@ -708,14 +735,14 @@ reset_wakeup:
 	ld	%r1,CPUTHREAD_SAVE_R1(%r13)
 
 	/* Restore more stuff */
-	lwz	%r3,STACK_CR(%r1)
-	lwz	%r4,STACK_XER(%r1)
-	ld	%r5,STACK_GPR0(%r1)
-	ld	%r6,STACK_GPR1(%r1)
-	mtcr	%r3
-	mtxer	%r4
-	mtspr	SPR_HSPRG0,%r5
-	mtspr	SPR_HSPRG1,%r6
+	lwz	%r4,STACK_CR(%r1)
+	lwz	%r5,STACK_XER(%r1)
+	ld	%r6,STACK_GPR0(%r1)
+	ld	%r7,STACK_GPR1(%r1)
+	mtcr	%r4
+	mtxer	%r5
+	mtspr	SPR_HSPRG0,%r6
+	mtspr	SPR_HSPRG1,%r7
 	REST_GPR(2,%r1)
 	REST_GPR(14,%r1)
 	REST_GPR(15,%r1)
diff --git a/core/cpu.c b/core/cpu.c
index c1a0a0258..8e0513d4d 100644
--- a/core/cpu.c
+++ b/core/cpu.c
@@ -426,8 +426,7 @@ static unsigned int cpu_idle_p8(enum cpu_wake_cause wake_on)
 	isync();
 
 	/* Enter nap */
-	enter_p8_pm_state(false);
-	vec = 0x100;
+	vec = enter_p8_pm_state(false);
 
 skip_sleep:
 	/* Restore */
@@ -486,8 +485,7 @@ static unsigned int cpu_idle_p9(enum cpu_wake_cause wake_on)
 		/* PSSCR SD=0 ESL=1 EC=1 PSSL=0 TR=3 MTL=0 RL=1 */
 		psscr = PPC_BIT(42) | PPC_BIT(43) |
 			PPC_BITMASK(54, 55) | PPC_BIT(63);
-		enter_p9_pm_state(psscr);
-		vec = 0x100;
+		vec = enter_p9_pm_state(psscr);
 	} else {
 		/* stop with EC=0 (resumes) which does not require sreset. */
 		/* PSSCR SD=0 ESL=0 EC=0 PSSL=0 TR=3 MTL=0 RL=1 */
@@ -535,6 +533,11 @@ static void cpu_idle_pm(enum cpu_wake_cause wake_on)
 			break;
 		}
 		mtmsrd(MSR_RI, 1);
+
+	} else if (vec == 0x200) {
+		exception_entry_pm_mce();
+		enable_machine_check();
+		mtmsrd(MSR_RI, 1);
 	}
 }
 
diff --git a/core/exceptions.c b/core/exceptions.c
index 779cd620a..e15848ad3 100644
--- a/core/exceptions.c
+++ b/core/exceptions.c
@@ -127,6 +127,23 @@ void exception_entry_pm_sreset(void)
 	backtrace();
 }
 
+void __noreturn exception_entry_pm_mce(void)
+{
+	const size_t max = 320;
+	char buf[max];
+	size_t l;
+
+	prerror("***********************************************\n");
+	l = 0;
+	l += snprintf(buf + l, max - l,
+		"Fatal MCE in sleep");
+	prerror("%s\n", buf);
+	prerror("SRR0 : "REG" SRR1 : "REG"\n",
+			(uint64_t)mfspr(SPR_SRR0), (uint64_t)mfspr(SPR_SRR1));
+	prerror("DSISR: "REG32"         DAR  : "REG"\n",
+			(uint32_t)mfspr(SPR_DSISR), (uint64_t)mfspr(SPR_DAR));
+	abort();
+}
 
 static int64_t opal_register_exc_handler(uint64_t opal_exception __unused,
 					 uint64_t handler_address __unused,
diff --git a/include/processor.h b/include/processor.h
index 70991dfb0..2b398b46b 100644
--- a/include/processor.h
+++ b/include/processor.h
@@ -92,6 +92,7 @@
 
 #define SPR_SRR1_PM_WAKE_MASK	0x3c0000	/* PM wake reason for P8/9 */
 #define SPR_SRR1_PM_WAKE_SRESET	0x100000
+#define SPR_SRR1_PM_WAKE_MCE	0x3c0000	/* Use reserved value for MCE */
 
 /* Bits in LPCR */
 
diff --git a/include/skiboot.h b/include/skiboot.h
index c06146d06..6da62233a 100644
--- a/include/skiboot.h
+++ b/include/skiboot.h
@@ -289,12 +289,13 @@ extern void fake_rtc_init(void);
 struct stack_frame;
 extern void exception_entry(struct stack_frame *stack);
 extern void exception_entry_pm_sreset(void);
+extern void exception_entry_pm_mce(void);
 
 /* Assembly in head.S */
 extern void disable_machine_check(void);
 extern void enable_machine_check(void);
-extern void enter_p8_pm_state(bool winkle);
-extern void enter_p9_pm_state(uint64_t psscr);
+extern unsigned int enter_p8_pm_state(bool winkle);
+extern unsigned int enter_p9_pm_state(uint64_t psscr);
 extern void enter_p9_pm_lite_state(uint64_t psscr);
 extern uint32_t reset_patch_start;
 extern uint32_t reset_patch_end;
