diff options
-rw-r--r-- | arch/powerpc/kernel/exceptions-64s.S | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 274a86d001c7..8a0292dbb5fc 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
@@ -439,9 +439,9 @@ BEGIN_FTR_SECTION | |||
439 | * R9 = CR | 439 | * R9 = CR |
440 | * Original R9 to R13 is saved on PACA_EXMC | 440 | * Original R9 to R13 is saved on PACA_EXMC |
441 | * | 441 | * |
442 | * Switch to mc_emergency stack and handle re-entrancy (though we | 442 | * Switch to mc_emergency stack and handle re-entrancy (we limit |
443 | * currently don't test for overflow). Save MCE registers srr1, | 443 | * the nested MCE upto level 4 to avoid stack overflow). |
444 | * srr0, dar and dsisr and then set ME=1 | 444 | * Save MCE registers srr1, srr0, dar and dsisr and then set ME=1 |
445 | * | 445 | * |
446 | * We use paca->in_mce to check whether this is the first entry or | 446 | * We use paca->in_mce to check whether this is the first entry or |
447 | * nested machine check. We increment paca->in_mce to track nested | 447 | * nested machine check. We increment paca->in_mce to track nested |
@@ -464,6 +464,9 @@ BEGIN_FTR_SECTION | |||
464 | 0: subi r1,r1,INT_FRAME_SIZE /* alloc stack frame */ | 464 | 0: subi r1,r1,INT_FRAME_SIZE /* alloc stack frame */ |
465 | addi r10,r10,1 /* increment paca->in_mce */ | 465 | addi r10,r10,1 /* increment paca->in_mce */ |
466 | sth r10,PACA_IN_MCE(r13) | 466 | sth r10,PACA_IN_MCE(r13) |
467 | /* Limit nested MCE to level 4 to avoid stack overflow */ | ||
468 | cmpwi r10,4 | ||
469 | bgt 2f /* Check if we hit limit of 4 */ | ||
467 | std r11,GPR1(r1) /* Save r1 on the stack. */ | 470 | std r11,GPR1(r1) /* Save r1 on the stack. */ |
468 | std r11,0(r1) /* make stack chain pointer */ | 471 | std r11,0(r1) /* make stack chain pointer */ |
469 | mfspr r11,SPRN_SRR0 /* Save SRR0 */ | 472 | mfspr r11,SPRN_SRR0 /* Save SRR0 */ |
@@ -482,10 +485,23 @@ BEGIN_FTR_SECTION | |||
482 | ori r11,r11,MSR_RI /* turn on RI bit */ | 485 | ori r11,r11,MSR_RI /* turn on RI bit */ |
483 | ld r12,PACAKBASE(r13) /* get high part of &label */ | 486 | ld r12,PACAKBASE(r13) /* get high part of &label */ |
484 | LOAD_HANDLER(r12, machine_check_handle_early) | 487 | LOAD_HANDLER(r12, machine_check_handle_early) |
485 | mtspr SPRN_SRR0,r12 | 488 | 1: mtspr SPRN_SRR0,r12 |
486 | mtspr SPRN_SRR1,r11 | 489 | mtspr SPRN_SRR1,r11 |
487 | rfid | 490 | rfid |
488 | b . /* prevent speculative execution */ | 491 | b . /* prevent speculative execution */ |
492 | 2: | ||
493 | /* Stack overflow. Stay on emergency stack and panic. | ||
494 | * Keep the ME bit off while panic-ing, so that if we hit | ||
495 | * another machine check we checkstop. | ||
496 | */ | ||
497 | addi r1,r1,INT_FRAME_SIZE /* go back to previous stack frame */ | ||
498 | ld r11,PACAKMSR(r13) | ||
499 | ld r12,PACAKBASE(r13) | ||
500 | LOAD_HANDLER(r12, unrecover_mce) | ||
501 | li r10,MSR_ME | ||
502 | andc r11,r11,r10 /* Turn off MSR_ME */ | ||
503 | b 1b | ||
504 | b . /* prevent speculative execution */ | ||
489 | END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) | 505 | END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) |
490 | 506 | ||
491 | machine_check_pSeries: | 507 | machine_check_pSeries: |