Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc: Clear branch trap (MSR.BE) before delivering SIGTRAP

When using SIG_DBG_BRANCH_TRACING, MSR.BE is left enabled in the
user context when single_step_exception() prepares the SIGTRAP
delivery. The resulting branch-trap-within-the-SIGTRAP-handler
isn't healthy.

Commit 2538c2d08f46141550a1e68819efa8fe31c6e3dc broke this, by
replacing an MSR mask operation of ~(MSR_SE | MSR_BE) with a call
to clear_single_step() which only clears MSR_SE.

This patch adds a new helper, clear_br_trace(), which clears the
debug trap before invoking the signal handler. This helper is a
NOP for BookE as SIG_DBG_BRANCH_TRACING isn't supported on BookE.

Signed-off-by: Matt Evans <matt@ozlabs.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

authored by

Matt Evans and committed by
Michael Ellerman
0e524e76 4b7e5532

+3 -1
+3 -1
arch/powerpc/kernel/traps.c
··· 471 471 /* single-step stuff */ 472 472 #define single_stepping(regs) (current->thread.debug.dbcr0 & DBCR0_IC) 473 473 #define clear_single_step(regs) (current->thread.debug.dbcr0 &= ~DBCR0_IC) 474 - 474 + #define clear_br_trace(regs) do {} while(0) 475 475 #else 476 476 /* On non-4xx, the reason for the machine check or program 477 477 exception is in the MSR. */ ··· 484 484 485 485 #define single_stepping(regs) ((regs)->msr & MSR_SE) 486 486 #define clear_single_step(regs) ((regs)->msr &= ~MSR_SE) 487 + #define clear_br_trace(regs) ((regs)->msr &= ~MSR_BE) 487 488 #endif 488 489 489 490 #if defined(CONFIG_E500) ··· 1000 999 enum ctx_state prev_state = exception_enter(); 1001 1000 1002 1001 clear_single_step(regs); 1002 + clear_br_trace(regs); 1003 1003 1004 1004 if (kprobe_post_handler(regs)) 1005 1005 return;