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: |
