aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2008-01-30 07:30:54 -0500
committerIngo Molnar <mingo@elte.hu>2008-01-30 07:30:54 -0500
commit1ecc798c67645e0ee6eb028cb988b71b3edf4b40 (patch)
treea0456da7328d9b07212b5845003e67c88185f1f3 /arch/x86
parent10faa81e102e2b7695f386812055cd2ef9e44b4c (diff)
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 <roland@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/kernel/kprobes_32.c15
-rw-r--r--arch/x86/kernel/kprobes_64.c14
2 files changed, 29 insertions, 0 deletions
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,
217 kcb->kprobe_saved_eflags &= ~IF_MASK; 217 kcb->kprobe_saved_eflags &= ~IF_MASK;
218} 218}
219 219
220static __always_inline void clear_btf(void)
221{
222 if (test_thread_flag(TIF_DEBUGCTLMSR))
223 wrmsr(MSR_IA32_DEBUGCTLMSR, 0, 0);
224}
225
226static __always_inline void restore_btf(void)
227{
228 if (test_thread_flag(TIF_DEBUGCTLMSR))
229 wrmsr(MSR_IA32_DEBUGCTLMSR, current->thread.debugctlmsr, 0);
230}
231
220static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) 232static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
221{ 233{
234 clear_btf();
222 regs->eflags |= TF_MASK; 235 regs->eflags |= TF_MASK;
223 regs->eflags &= ~IF_MASK; 236 regs->eflags &= ~IF_MASK;
224 /*single step inline if the instruction is an int3*/ 237 /*single step inline if the instruction is an int3*/
@@ -542,6 +555,8 @@ static void __kprobes resume_execution(struct kprobe *p,
542 regs->eip = orig_eip + (regs->eip - copy_eip); 555 regs->eip = orig_eip + (regs->eip - copy_eip);
543 556
544no_change: 557no_change:
558 restore_btf();
559
545 return; 560 return;
546} 561}
547 562
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,
256 kcb->kprobe_saved_rflags &= ~IF_MASK; 256 kcb->kprobe_saved_rflags &= ~IF_MASK;
257} 257}
258 258
259static __always_inline void clear_btf(void)
260{
261 if (test_thread_flag(TIF_DEBUGCTLMSR))
262 wrmsrl(MSR_IA32_DEBUGCTLMSR, 0);
263}
264
265static __always_inline void restore_btf(void)
266{
267 if (test_thread_flag(TIF_DEBUGCTLMSR))
268 wrmsrl(MSR_IA32_DEBUGCTLMSR, current->thread.debugctlmsr);
269}
270
259static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) 271static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
260{ 272{
273 clear_btf();
261 regs->eflags |= TF_MASK; 274 regs->eflags |= TF_MASK;
262 regs->eflags &= ~IF_MASK; 275 regs->eflags &= ~IF_MASK;
263 /*single step inline if the instruction is an int3*/ 276 /*single step inline if the instruction is an int3*/
@@ -527,6 +540,7 @@ static void __kprobes resume_execution(struct kprobe *p,
527 540
528 regs->rip = orig_rip + (regs->rip - copy_rip); 541 regs->rip = orig_rip + (regs->rip - copy_rip);
529no_change: 542no_change:
543 restore_btf();
530 544
531 return; 545 return;
532} 546}