aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2013-05-13 10:14:53 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-05-14 02:00:19 -0400
commit6cecf76b47ba6bea3c81d170afc2e0b244e5849c (patch)
treeff2d8e3516815071e4b46d56673699a5224fd9ed /arch/powerpc
parentdcb615aef988b57deef3d9b4557ff20f681a82b0 (diff)
powerpc/booke64: Fix kernel hangs at kernel_dbg_exc
MSR_DE is not cleared on entry to the kernel, and we don't clear it explicitly outside of debug code. If we have MSR_DE set in prime_debug_regs(), and the new thread has events enabled in DBCR0 (e.g. ICMP is set in thread->dbsr0, even though it was cleared in the real DBCR0 when the thread got scheduled out), we'll end up taking a debug exception in the kernel when DBCR0 is loaded. DSRR0 will not point to an exception vector, and the kernel ends up hanging at kernel_dbg_exc. Fix this by always clearing MSR_DE when we load new debug state. Another observed source of kernel_dbg_exc hangs is with the branch taken event. If this event is active, but we take a non-debug trap (e.g. a TLB miss or an asynchronous interrupt) before the next branch. We end up taking a branch-taken debug exception on the initial branch instruction of the exception vector, but because the debug exception is DBSR_BT rather than DBSR_IC we branch to kernel_dbg_exc before even checking the DSRR0 address. Fix this by checking for DBSR_BT as well as DBSR_IC, which is what 32-bit does and what the comments suggest was intended in the 64-bit code as well. Signed-off-by: Scott Wood <scottwood@freescale.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kernel/exceptions-64e.S8
-rw-r--r--arch/powerpc/kernel/process.c7
2 files changed, 11 insertions, 4 deletions
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index 42a756eec9ff..645170a07ada 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -489,7 +489,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
489 */ 489 */
490 490
491 mfspr r14,SPRN_DBSR /* check single-step/branch taken */ 491 mfspr r14,SPRN_DBSR /* check single-step/branch taken */
492 andis. r15,r14,DBSR_IC@h 492 andis. r15,r14,(DBSR_IC|DBSR_BT)@h
493 beq+ 1f 493 beq+ 1f
494 494
495 LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e) 495 LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e)
@@ -500,7 +500,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
500 bge+ cr1,1f 500 bge+ cr1,1f
501 501
502 /* here it looks like we got an inappropriate debug exception. */ 502 /* here it looks like we got an inappropriate debug exception. */
503 lis r14,DBSR_IC@h /* clear the IC event */ 503 lis r14,(DBSR_IC|DBSR_BT)@h /* clear the event */
504 rlwinm r11,r11,0,~MSR_DE /* clear DE in the CSRR1 value */ 504 rlwinm r11,r11,0,~MSR_DE /* clear DE in the CSRR1 value */
505 mtspr SPRN_DBSR,r14 505 mtspr SPRN_DBSR,r14
506 mtspr SPRN_CSRR1,r11 506 mtspr SPRN_CSRR1,r11
@@ -555,7 +555,7 @@ kernel_dbg_exc:
555 */ 555 */
556 556
557 mfspr r14,SPRN_DBSR /* check single-step/branch taken */ 557 mfspr r14,SPRN_DBSR /* check single-step/branch taken */
558 andis. r15,r14,DBSR_IC@h 558 andis. r15,r14,(DBSR_IC|DBSR_BT)@h
559 beq+ 1f 559 beq+ 1f
560 560
561 LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e) 561 LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e)
@@ -566,7 +566,7 @@ kernel_dbg_exc:
566 bge+ cr1,1f 566 bge+ cr1,1f
567 567
568 /* here it looks like we got an inappropriate debug exception. */ 568 /* here it looks like we got an inappropriate debug exception. */
569 lis r14,DBSR_IC@h /* clear the IC event */ 569 lis r14,(DBSR_IC|DBSR_BT)@h /* clear the event */
570 rlwinm r11,r11,0,~MSR_DE /* clear DE in the DSRR1 value */ 570 rlwinm r11,r11,0,~MSR_DE /* clear DE in the DSRR1 value */
571 mtspr SPRN_DBSR,r14 571 mtspr SPRN_DBSR,r14
572 mtspr SPRN_DSRR1,r11 572 mtspr SPRN_DSRR1,r11
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 21981a89e394..a902723fdc69 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -339,6 +339,13 @@ static void set_debug_reg_defaults(struct thread_struct *thread)
339 339
340static void prime_debug_regs(struct thread_struct *thread) 340static void prime_debug_regs(struct thread_struct *thread)
341{ 341{
342 /*
343 * We could have inherited MSR_DE from userspace, since
344 * it doesn't get cleared on exception entry. Make sure
345 * MSR_DE is clear before we enable any debug events.
346 */
347 mtmsr(mfmsr() & ~MSR_DE);
348
342 mtspr(SPRN_IAC1, thread->iac1); 349 mtspr(SPRN_IAC1, thread->iac1);
343 mtspr(SPRN_IAC2, thread->iac2); 350 mtspr(SPRN_IAC2, thread->iac2);
344#if CONFIG_PPC_ADV_DEBUG_IACS > 2 351#if CONFIG_PPC_ADV_DEBUG_IACS > 2