|
@@ -155,6 +155,24 @@ machine_check_pSeries_1:
|
|
|
*/
|
|
|
HMT_MEDIUM_PPR_DISCARD
|
|
|
SET_SCRATCH0(r13) /* save r13 */
|
|
|
+#ifdef CONFIG_PPC_P7_NAP
|
|
|
+BEGIN_FTR_SECTION
|
|
|
+ /* Running native on arch 2.06 or later, check if we are
|
|
|
+ * waking up from nap. We only handle no state loss and
|
|
|
+ * supervisor state loss. We do -not- handle hypervisor
|
|
|
+ * state loss at this time.
|
|
|
+ */
|
|
|
+ mfspr r13,SPRN_SRR1
|
|
|
+ rlwinm. r13,r13,47-31,30,31
|
|
|
+ beq 9f
|
|
|
+
|
|
|
+ /* waking up from powersave (nap) state */
|
|
|
+ cmpwi cr1,r13,2
|
|
|
+ /* Total loss of HV state is fatal. let's just stay stuck here */
|
|
|
+ bgt cr1,.
|
|
|
+9:
|
|
|
+END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
|
|
|
+#endif /* CONFIG_PPC_P7_NAP */
|
|
|
EXCEPTION_PROLOG_0(PACA_EXMC)
|
|
|
BEGIN_FTR_SECTION
|
|
|
b machine_check_pSeries_early
|
|
@@ -818,6 +836,70 @@ BEGIN_FTR_SECTION
|
|
|
bl .save_nvgprs
|
|
|
addi r3,r1,STACK_FRAME_OVERHEAD
|
|
|
bl .machine_check_early
|
|
|
+ ld r12,_MSR(r1)
|
|
|
+#ifdef CONFIG_PPC_P7_NAP
|
|
|
+ /*
|
|
|
+ * Check if thread was in power saving mode. We come here when any
|
|
|
+ * of the following is true:
|
|
|
+ * a. thread wasn't in power saving mode
|
|
|
+ * b. thread was in power saving mode with no state loss or
|
|
|
+ * supervisor state loss
|
|
|
+ *
|
|
|
+ * Go back to nap again if (b) is true.
|
|
|
+ */
|
|
|
+ rlwinm. r11,r12,47-31,30,31 /* Was it in power saving mode? */
|
|
|
+ beq 4f /* No, it wasn;t */
|
|
|
+ /* Thread was in power saving mode. Go back to nap again. */
|
|
|
+ cmpwi r11,2
|
|
|
+ bne 3f
|
|
|
+ /* Supervisor state loss */
|
|
|
+ li r0,1
|
|
|
+ stb r0,PACA_NAPSTATELOST(r13)
|
|
|
+3: MACHINE_CHECK_HANDLER_WINDUP
|
|
|
+ GET_PACA(r13)
|
|
|
+ ld r1,PACAR1(r13)
|
|
|
+ b .power7_enter_nap_mode
|
|
|
+4:
|
|
|
+#endif
|
|
|
+ /*
|
|
|
+ * Check if we are coming from hypervisor userspace. If yes then we
|
|
|
+ * continue in host kernel in V mode to deliver the MC event.
|
|
|
+ */
|
|
|
+ rldicl. r11,r12,4,63 /* See if MC hit while in HV mode. */
|
|
|
+ beq 5f
|
|
|
+ andi. r11,r12,MSR_PR /* See if coming from user. */
|
|
|
+ bne 9f /* continue in V mode if we are. */
|
|
|
+
|
|
|
+5:
|
|
|
+#ifdef CONFIG_KVM_BOOK3S_64_HV
|
|
|
+ /*
|
|
|
+ * We are coming from kernel context. Check if we are coming from
|
|
|
+ * guest. if yes, then we can continue. We will fall through
|
|
|
+ * do_kvm_200->kvmppc_interrupt to deliver the MC event to guest.
|
|
|
+ */
|
|
|
+ lbz r11,HSTATE_IN_GUEST(r13)
|
|
|
+ cmpwi r11,0 /* Check if coming from guest */
|
|
|
+ bne 9f /* continue if we are. */
|
|
|
+#endif
|
|
|
+ /*
|
|
|
+ * At this point we are not sure about what context we come from.
|
|
|
+ * Queue up the MCE event and return from the interrupt.
|
|
|
+ * But before that, check if this is an un-recoverable exception.
|
|
|
+ * If yes, then stay on emergency stack and panic.
|
|
|
+ */
|
|
|
+ andi. r11,r12,MSR_RI
|
|
|
+ bne 2f
|
|
|
+1: addi r3,r1,STACK_FRAME_OVERHEAD
|
|
|
+ bl .unrecoverable_exception
|
|
|
+ b 1b
|
|
|
+2:
|
|
|
+ /*
|
|
|
+ * Return from MC interrupt.
|
|
|
+ * TODO: Queue up the MCE event so that we can log it later.
|
|
|
+ */
|
|
|
+ MACHINE_CHECK_HANDLER_WINDUP
|
|
|
+ rfid
|
|
|
+9:
|
|
|
/* Deliver the machine check to host kernel in V mode. */
|
|
|
MACHINE_CHECK_HANDLER_WINDUP
|
|
|
b machine_check_pSeries
|