|
@@ -153,15 +153,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
|
|
|
stb r0, HSTATE_HWTHREAD_REQ(r13)
|
|
|
|
|
|
/*
|
|
|
- * For external and machine check interrupts, we need
|
|
|
- * to call the Linux handler to process the interrupt.
|
|
|
- * We do that by jumping to absolute address 0x500 for
|
|
|
- * external interrupts, or the machine_check_fwnmi label
|
|
|
- * for machine checks (since firmware might have patched
|
|
|
- * the vector area at 0x200). The [h]rfid at the end of the
|
|
|
- * handler will return to the book3s_hv_interrupts.S code.
|
|
|
- * For other interrupts we do the rfid to get back
|
|
|
- * to the book3s_hv_interrupts.S code here.
|
|
|
+ * For external interrupts we need to call the Linux
|
|
|
+ * handler to process the interrupt. We do that by jumping
|
|
|
+ * to absolute address 0x500 for external interrupts.
|
|
|
+ * The [h]rfid at the end of the handler will return to
|
|
|
+ * the book3s_hv_interrupts.S code. For other interrupts
|
|
|
+ * we do the rfid to get back to the book3s_hv_interrupts.S
|
|
|
+ * code here.
|
|
|
*/
|
|
|
ld r8, 112+PPC_LR_STKOFF(r1)
|
|
|
addi r1, r1, 112
|
|
@@ -176,7 +174,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
|
|
|
andi. r0, r0, MSR_IR /* in real mode? */
|
|
|
bne .Lvirt_return
|
|
|
|
|
|
- cmpwi cr1, r12, BOOK3S_INTERRUPT_MACHINE_CHECK
|
|
|
cmpwi r12, BOOK3S_INTERRUPT_EXTERNAL
|
|
|
beq 11f
|
|
|
cmpwi r12, BOOK3S_INTERRUPT_H_DOORBELL
|
|
@@ -191,7 +188,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
|
|
|
mtmsrd r6, 1 /* Clear RI in MSR */
|
|
|
mtsrr0 r8
|
|
|
mtsrr1 r7
|
|
|
- beq cr1, 13f /* machine check */
|
|
|
+ /*
|
|
|
+ * BOOK3S_INTERRUPT_MACHINE_CHECK is handled at the
|
|
|
+ * time of guest exit
|
|
|
+ */
|
|
|
RFI
|
|
|
|
|
|
/* On POWER7, we have external interrupts set to use HSRR0/1 */
|
|
@@ -199,8 +199,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
|
|
|
mtspr SPRN_HSRR1, r7
|
|
|
ba 0x500
|
|
|
|
|
|
-13: b machine_check_fwnmi
|
|
|
-
|
|
|
14: mtspr SPRN_HSRR0, r8
|
|
|
mtspr SPRN_HSRR1, r7
|
|
|
b hmi_exception_after_realmode
|
|
@@ -2640,22 +2638,32 @@ machine_check_realmode:
|
|
|
ld r9, HSTATE_KVM_VCPU(r13)
|
|
|
li r12, BOOK3S_INTERRUPT_MACHINE_CHECK
|
|
|
/*
|
|
|
- * Deliver unhandled/fatal (e.g. UE) MCE errors to guest through
|
|
|
- * machine check interrupt (set HSRR0 to 0x200). And for handled
|
|
|
- * errors (no-fatal), just go back to guest execution with current
|
|
|
- * HSRR0 instead of exiting guest. This new approach will inject
|
|
|
- * machine check to guest for fatal error causing guest to crash.
|
|
|
- *
|
|
|
- * The old code used to return to host for unhandled errors which
|
|
|
- * was causing guest to hang with soft lockups inside guest and
|
|
|
- * makes it difficult to recover guest instance.
|
|
|
+ * For the guest that is FWNMI capable, deliver all the MCE errors
|
|
|
+ * (handled/unhandled) by exiting the guest with KVM_EXIT_NMI exit
|
|
|
+ * reason. This new approach injects machine check errors in guest
|
|
|
+ * address space to guest with additional information in the form
|
|
|
+ * of RTAS event, thus enabling guest kernel to suitably handle
|
|
|
+ * such errors.
|
|
|
*
|
|
|
+ * For the guest that is not FWNMI capable (old QEMU) fallback
|
|
|
+ * to old behaviour for backward compatibility:
|
|
|
+ * Deliver unhandled/fatal (e.g. UE) MCE errors to guest either
|
|
|
+ * through machine check interrupt (set HSRR0 to 0x200).
|
|
|
+ * For handled errors (no-fatal), just go back to guest execution
|
|
|
+ * with current HSRR0.
|
|
|
* if we receive machine check with MSR(RI=0) then deliver it to
|
|
|
* guest as machine check causing guest to crash.
|
|
|
*/
|
|
|
ld r11, VCPU_MSR(r9)
|
|
|
rldicl. r0, r11, 64-MSR_HV_LG, 63 /* check if it happened in HV mode */
|
|
|
bne mc_cont /* if so, exit to host */
|
|
|
+ /* Check if guest is capable of handling NMI exit */
|
|
|
+ ld r10, VCPU_KVM(r9)
|
|
|
+ lbz r10, KVM_FWNMI(r10)
|
|
|
+ cmpdi r10, 1 /* FWNMI capable? */
|
|
|
+ beq mc_cont /* if so, exit with KVM_EXIT_NMI. */
|
|
|
+
|
|
|
+ /* if not, fall through for backward compatibility. */
|
|
|
andi. r10, r11, MSR_RI /* check for unrecoverable exception */
|
|
|
beq 1f /* Deliver a machine check to guest */
|
|
|
ld r10, VCPU_PC(r9)
|