|
@@ -439,9 +439,9 @@ BEGIN_FTR_SECTION
|
|
|
* R9 = CR
|
|
|
* Original R9 to R13 is saved on PACA_EXMC
|
|
|
*
|
|
|
- * Switch to mc_emergency stack and handle re-entrancy (though we
|
|
|
- * currently don't test for overflow). Save MCE registers srr1,
|
|
|
- * srr0, dar and dsisr and then set ME=1
|
|
|
+ * Switch to mc_emergency stack and handle re-entrancy (we limit
|
|
|
+ * the nested MCE upto level 4 to avoid stack overflow).
|
|
|
+ * Save MCE registers srr1, srr0, dar and dsisr and then set ME=1
|
|
|
*
|
|
|
* We use paca->in_mce to check whether this is the first entry or
|
|
|
* nested machine check. We increment paca->in_mce to track nested
|
|
@@ -464,6 +464,9 @@ BEGIN_FTR_SECTION
|
|
|
0: subi r1,r1,INT_FRAME_SIZE /* alloc stack frame */
|
|
|
addi r10,r10,1 /* increment paca->in_mce */
|
|
|
sth r10,PACA_IN_MCE(r13)
|
|
|
+ /* Limit nested MCE to level 4 to avoid stack overflow */
|
|
|
+ cmpwi r10,4
|
|
|
+ bgt 2f /* Check if we hit limit of 4 */
|
|
|
std r11,GPR1(r1) /* Save r1 on the stack. */
|
|
|
std r11,0(r1) /* make stack chain pointer */
|
|
|
mfspr r11,SPRN_SRR0 /* Save SRR0 */
|
|
@@ -482,10 +485,23 @@ BEGIN_FTR_SECTION
|
|
|
ori r11,r11,MSR_RI /* turn on RI bit */
|
|
|
ld r12,PACAKBASE(r13) /* get high part of &label */
|
|
|
LOAD_HANDLER(r12, machine_check_handle_early)
|
|
|
- mtspr SPRN_SRR0,r12
|
|
|
+1: mtspr SPRN_SRR0,r12
|
|
|
mtspr SPRN_SRR1,r11
|
|
|
rfid
|
|
|
b . /* prevent speculative execution */
|
|
|
+2:
|
|
|
+ /* Stack overflow. Stay on emergency stack and panic.
|
|
|
+ * Keep the ME bit off while panic-ing, so that if we hit
|
|
|
+ * another machine check we checkstop.
|
|
|
+ */
|
|
|
+ addi r1,r1,INT_FRAME_SIZE /* go back to previous stack frame */
|
|
|
+ ld r11,PACAKMSR(r13)
|
|
|
+ ld r12,PACAKBASE(r13)
|
|
|
+ LOAD_HANDLER(r12, unrecover_mce)
|
|
|
+ li r10,MSR_ME
|
|
|
+ andc r11,r11,r10 /* Turn off MSR_ME */
|
|
|
+ b 1b
|
|
|
+ b . /* prevent speculative execution */
|
|
|
END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
|
|
|
|
|
|
machine_check_pSeries:
|