From 1ecc798c67645e0ee6eb028cb988b71b3edf4b40 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Wed, 30 Jan 2008 13:30:54 +0100 Subject: [PATCH] x86: debugctlmsr kprobes This adjusts the x86 kprobes implementation to cope with per-thread MSR_IA32_DEBUGCTLMSR being set for user mode. I haven't delved deep enough into the kprobes code to be really sure this covers all the cases where the user-mode BTF setting needs to be cleared or restored. It looks about right to me. Signed-off-by: Roland McGrath Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- arch/x86/kernel/kprobes_32.c | 15 +++++++++++++++ arch/x86/kernel/kprobes_64.c | 14 ++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/arch/x86/kernel/kprobes_32.c b/arch/x86/kernel/kprobes_32.c index 3a020f79f82b..bc4a68367cd0 100644 --- a/arch/x86/kernel/kprobes_32.c +++ b/arch/x86/kernel/kprobes_32.c @@ -217,8 +217,21 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs, kcb->kprobe_saved_eflags &= ~IF_MASK; } +static __always_inline void clear_btf(void) +{ + if (test_thread_flag(TIF_DEBUGCTLMSR)) + wrmsr(MSR_IA32_DEBUGCTLMSR, 0, 0); +} + +static __always_inline void restore_btf(void) +{ + if (test_thread_flag(TIF_DEBUGCTLMSR)) + wrmsr(MSR_IA32_DEBUGCTLMSR, current->thread.debugctlmsr, 0); +} + static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) { + clear_btf(); regs->eflags |= TF_MASK; regs->eflags &= ~IF_MASK; /*single step inline if the instruction is an int3*/ @@ -542,6 +555,8 @@ static void __kprobes resume_execution(struct kprobe *p, regs->eip = orig_eip + (regs->eip - copy_eip); no_change: + restore_btf(); + return; } diff --git a/arch/x86/kernel/kprobes_64.c b/arch/x86/kernel/kprobes_64.c index 5df19a9f9239..10d66e323c7d 100644 --- a/arch/x86/kernel/kprobes_64.c +++ b/arch/x86/kernel/kprobes_64.c @@ -256,8 +256,21 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs, kcb->kprobe_saved_rflags &= ~IF_MASK; } +static __always_inline void clear_btf(void) +{ + if (test_thread_flag(TIF_DEBUGCTLMSR)) + wrmsrl(MSR_IA32_DEBUGCTLMSR, 0); +} + +static __always_inline void restore_btf(void) +{ + if (test_thread_flag(TIF_DEBUGCTLMSR)) + wrmsrl(MSR_IA32_DEBUGCTLMSR, current->thread.debugctlmsr); +} + static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) { + clear_btf(); regs->eflags |= TF_MASK; regs->eflags &= ~IF_MASK; /*single step inline if the instruction is an int3*/ @@ -527,6 +540,7 @@ static void __kprobes resume_execution(struct kprobe *p, regs->rip = orig_rip + (regs->rip - copy_rip); no_change: + restore_btf(); return; }