aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorMahesh Salgaonkar <mahesh@linux.vnet.ibm.com>2014-06-11 04:48:02 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-06-11 05:15:13 -0400
commite75ad93afcd34a7ed472d64fb2944560ad9cad4e (patch)
treea5fe95a4867a0e8047872b6b792cf317477a56d1 /arch/powerpc
parent2749a2f26a7c7eb4c7e3901695c8977cdb6b826d (diff)
powerpc/book3s: Add stack overflow check in machine check handler.
Currently machine check handler does not check for stack overflow for nested machine check. If we hit another MCE while inside the machine check handler repeatedly from same address then we get into risk of stack overflow which can cause huge memory corruption. This patch limits the nested MCE level to 4 and panic when we cross level 4. Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S24
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
4640: subi r1,r1,INT_FRAME_SIZE /* alloc stack frame */ 4640: 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 4881: 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 */
4922:
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 */
489END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) 505END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
490 506
491machine_check_pSeries: 507machine_check_pSeries: