Skip to content

Commit 2a9baf5

Browse files
Peter ZijlstraKAGA-KOKO
authored andcommitted
x86/debug: Fix BTF handling
The SDM states that #DB clears DEBUGCTLMSR_BTF, this means that when the bit is set for userspace (TIF_BLOCKSTEP) and a kernel #DB happens first, the BTF bit meant for userspace execution is lost. Have the kernel #DB handler restore the BTF bit when it was requested for userspace. Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Tested-by: Kyle Huey <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent ed8780e commit 2a9baf5

File tree

1 file changed

+21
-7
lines changed

1 file changed

+21
-7
lines changed

arch/x86/kernel/traps.c

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -799,13 +799,6 @@ static __always_inline unsigned long debug_read_clear_dr6(void)
799799
*/
800800
current->thread.virtual_dr6 = 0;
801801

802-
/*
803-
* The SDM says "The processor clears the BTF flag when it
804-
* generates a debug exception." Clear TIF_BLOCKSTEP to keep
805-
* TIF_BLOCKSTEP in sync with the hardware BTF flag.
806-
*/
807-
clear_thread_flag(TIF_BLOCKSTEP);
808-
809802
return dr6;
810803
}
811804

@@ -873,6 +866,20 @@ static __always_inline void exc_debug_kernel(struct pt_regs *regs,
873866
*/
874867
WARN_ON_ONCE(user_mode(regs));
875868

869+
if (test_thread_flag(TIF_BLOCKSTEP)) {
870+
/*
871+
* The SDM says "The processor clears the BTF flag when it
872+
* generates a debug exception." but PTRACE_BLOCKSTEP requested
873+
* it for userspace, but we just took a kernel #DB, so re-set
874+
* BTF.
875+
*/
876+
unsigned long debugctl;
877+
878+
rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
879+
debugctl |= DEBUGCTLMSR_BTF;
880+
wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
881+
}
882+
876883
/*
877884
* Catch SYSENTER with TF set and clear DR_STEP. If this hit a
878885
* watchpoint at the same time then that will still be handled.
@@ -935,6 +942,13 @@ static __always_inline void exc_debug_user(struct pt_regs *regs,
935942
irqentry_enter_from_user_mode(regs);
936943
instrumentation_begin();
937944

945+
/*
946+
* The SDM says "The processor clears the BTF flag when it
947+
* generates a debug exception." Clear TIF_BLOCKSTEP to keep
948+
* TIF_BLOCKSTEP in sync with the hardware BTF flag.
949+
*/
950+
clear_thread_flag(TIF_BLOCKSTEP);
951+
938952
/*
939953
* If dr6 has no reason to give us about the origin of this trap,
940954
* then it's very likely the result of an icebp/int01 trap.

0 commit comments

Comments
 (0)