|
|
@@ -768,146 +768,6 @@ kvmppc_skip_Hinterrupt:
|
|
|
|
|
|
STD_EXCEPTION_COMMON(0x100, system_reset, .system_reset_exception)
|
|
|
|
|
|
- /*
|
|
|
- * Machine check is different because we use a different
|
|
|
- * save area: PACA_EXMC instead of PACA_EXGEN.
|
|
|
- */
|
|
|
- .align 7
|
|
|
- .globl machine_check_common
|
|
|
-machine_check_common:
|
|
|
-
|
|
|
- mfspr r10,SPRN_DAR
|
|
|
- std r10,PACA_EXGEN+EX_DAR(r13)
|
|
|
- mfspr r10,SPRN_DSISR
|
|
|
- stw r10,PACA_EXGEN+EX_DSISR(r13)
|
|
|
- EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)
|
|
|
- FINISH_NAP
|
|
|
- DISABLE_INTS
|
|
|
- ld r3,PACA_EXGEN+EX_DAR(r13)
|
|
|
- lwz r4,PACA_EXGEN+EX_DSISR(r13)
|
|
|
- std r3,_DAR(r1)
|
|
|
- std r4,_DSISR(r1)
|
|
|
- bl .save_nvgprs
|
|
|
- addi r3,r1,STACK_FRAME_OVERHEAD
|
|
|
- bl .machine_check_exception
|
|
|
- b .ret_from_except
|
|
|
-
|
|
|
-#define MACHINE_CHECK_HANDLER_WINDUP \
|
|
|
- /* Clear MSR_RI before setting SRR0 and SRR1. */\
|
|
|
- li r0,MSR_RI; \
|
|
|
- mfmsr r9; /* get MSR value */ \
|
|
|
- andc r9,r9,r0; \
|
|
|
- mtmsrd r9,1; /* Clear MSR_RI */ \
|
|
|
- /* Move original SRR0 and SRR1 into the respective regs */ \
|
|
|
- ld r9,_MSR(r1); \
|
|
|
- mtspr SPRN_SRR1,r9; \
|
|
|
- ld r3,_NIP(r1); \
|
|
|
- mtspr SPRN_SRR0,r3; \
|
|
|
- ld r9,_CTR(r1); \
|
|
|
- mtctr r9; \
|
|
|
- ld r9,_XER(r1); \
|
|
|
- mtxer r9; \
|
|
|
- ld r9,_LINK(r1); \
|
|
|
- mtlr r9; \
|
|
|
- REST_GPR(0, r1); \
|
|
|
- REST_8GPRS(2, r1); \
|
|
|
- REST_GPR(10, r1); \
|
|
|
- ld r11,_CCR(r1); \
|
|
|
- mtcr r11; \
|
|
|
- /* Decrement paca->in_mce. */ \
|
|
|
- lhz r12,PACA_IN_MCE(r13); \
|
|
|
- subi r12,r12,1; \
|
|
|
- sth r12,PACA_IN_MCE(r13); \
|
|
|
- REST_GPR(11, r1); \
|
|
|
- REST_2GPRS(12, r1); \
|
|
|
- /* restore original r1. */ \
|
|
|
- ld r1,GPR1(r1)
|
|
|
-
|
|
|
- /*
|
|
|
- * Handle machine check early in real mode. We come here with
|
|
|
- * ME=1, MMU (IR=0 and DR=0) off and using MC emergency stack.
|
|
|
- */
|
|
|
- .align 7
|
|
|
- .globl machine_check_handle_early
|
|
|
-machine_check_handle_early:
|
|
|
-BEGIN_FTR_SECTION
|
|
|
- std r0,GPR0(r1) /* Save r0 */
|
|
|
- EXCEPTION_PROLOG_COMMON_3(0x200)
|
|
|
- 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: bl .machine_check_queue_event
|
|
|
- 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.
|
|
|
- * Queue up the MCE event so that we can log it later, while
|
|
|
- * returning from kernel or opal call.
|
|
|
- */
|
|
|
- bl .machine_check_queue_event
|
|
|
- MACHINE_CHECK_HANDLER_WINDUP
|
|
|
- rfid
|
|
|
-9:
|
|
|
- /* Deliver the machine check to host kernel in V mode. */
|
|
|
- MACHINE_CHECK_HANDLER_WINDUP
|
|
|
- b machine_check_pSeries
|
|
|
-END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
|
|
|
-
|
|
|
STD_EXCEPTION_COMMON_ASYNC(0x500, hardware_interrupt, do_IRQ)
|
|
|
STD_EXCEPTION_COMMON_ASYNC(0x900, decrementer, .timer_interrupt)
|
|
|
STD_EXCEPTION_COMMON(0x980, hdecrementer, .hdec_interrupt)
|
|
|
@@ -1276,6 +1136,30 @@ unrecov_user_slb:
|
|
|
#endif /* __DISABLED__ */
|
|
|
|
|
|
|
|
|
+ /*
|
|
|
+ * Machine check is different because we use a different
|
|
|
+ * save area: PACA_EXMC instead of PACA_EXGEN.
|
|
|
+ */
|
|
|
+ .align 7
|
|
|
+ .globl machine_check_common
|
|
|
+machine_check_common:
|
|
|
+
|
|
|
+ mfspr r10,SPRN_DAR
|
|
|
+ std r10,PACA_EXGEN+EX_DAR(r13)
|
|
|
+ mfspr r10,SPRN_DSISR
|
|
|
+ stw r10,PACA_EXGEN+EX_DSISR(r13)
|
|
|
+ EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)
|
|
|
+ FINISH_NAP
|
|
|
+ DISABLE_INTS
|
|
|
+ ld r3,PACA_EXGEN+EX_DAR(r13)
|
|
|
+ lwz r4,PACA_EXGEN+EX_DSISR(r13)
|
|
|
+ std r3,_DAR(r1)
|
|
|
+ std r4,_DSISR(r1)
|
|
|
+ bl .save_nvgprs
|
|
|
+ addi r3,r1,STACK_FRAME_OVERHEAD
|
|
|
+ bl .machine_check_exception
|
|
|
+ b .ret_from_except
|
|
|
+
|
|
|
.align 7
|
|
|
.globl alignment_common
|
|
|
alignment_common:
|
|
|
@@ -1459,6 +1343,120 @@ _GLOBAL(opal_mc_secondary_handler)
|
|
|
#endif /* CONFIG_PPC_POWERNV */
|
|
|
|
|
|
|
|
|
+#define MACHINE_CHECK_HANDLER_WINDUP \
|
|
|
+ /* Clear MSR_RI before setting SRR0 and SRR1. */\
|
|
|
+ li r0,MSR_RI; \
|
|
|
+ mfmsr r9; /* get MSR value */ \
|
|
|
+ andc r9,r9,r0; \
|
|
|
+ mtmsrd r9,1; /* Clear MSR_RI */ \
|
|
|
+ /* Move original SRR0 and SRR1 into the respective regs */ \
|
|
|
+ ld r9,_MSR(r1); \
|
|
|
+ mtspr SPRN_SRR1,r9; \
|
|
|
+ ld r3,_NIP(r1); \
|
|
|
+ mtspr SPRN_SRR0,r3; \
|
|
|
+ ld r9,_CTR(r1); \
|
|
|
+ mtctr r9; \
|
|
|
+ ld r9,_XER(r1); \
|
|
|
+ mtxer r9; \
|
|
|
+ ld r9,_LINK(r1); \
|
|
|
+ mtlr r9; \
|
|
|
+ REST_GPR(0, r1); \
|
|
|
+ REST_8GPRS(2, r1); \
|
|
|
+ REST_GPR(10, r1); \
|
|
|
+ ld r11,_CCR(r1); \
|
|
|
+ mtcr r11; \
|
|
|
+ /* Decrement paca->in_mce. */ \
|
|
|
+ lhz r12,PACA_IN_MCE(r13); \
|
|
|
+ subi r12,r12,1; \
|
|
|
+ sth r12,PACA_IN_MCE(r13); \
|
|
|
+ REST_GPR(11, r1); \
|
|
|
+ REST_2GPRS(12, r1); \
|
|
|
+ /* restore original r1. */ \
|
|
|
+ ld r1,GPR1(r1)
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Handle machine check early in real mode. We come here with
|
|
|
+ * ME=1, MMU (IR=0 and DR=0) off and using MC emergency stack.
|
|
|
+ */
|
|
|
+ .align 7
|
|
|
+ .globl machine_check_handle_early
|
|
|
+machine_check_handle_early:
|
|
|
+ std r0,GPR0(r1) /* Save r0 */
|
|
|
+ EXCEPTION_PROLOG_COMMON_3(0x200)
|
|
|
+ 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: bl .machine_check_queue_event
|
|
|
+ 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.
|
|
|
+ * Queue up the MCE event so that we can log it later, while
|
|
|
+ * returning from kernel or opal call.
|
|
|
+ */
|
|
|
+ bl .machine_check_queue_event
|
|
|
+ MACHINE_CHECK_HANDLER_WINDUP
|
|
|
+ rfid
|
|
|
+9:
|
|
|
+ /* Deliver the machine check to host kernel in V mode. */
|
|
|
+ MACHINE_CHECK_HANDLER_WINDUP
|
|
|
+ b machine_check_pSeries
|
|
|
+
|
|
|
/*
|
|
|
* r13 points to the PACA, r9 contains the saved CR,
|
|
|
* r12 contain the saved SRR1, SRR0 is still ready for return
|