mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-01-02 07:11:12 +00:00
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>
This commit is contained in:
parent
10faa81e10
commit
1ecc798c67
@ -217,8 +217,21 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
|
|||||||
kcb->kprobe_saved_eflags &= ~IF_MASK;
|
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)
|
static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
|
clear_btf();
|
||||||
regs->eflags |= TF_MASK;
|
regs->eflags |= TF_MASK;
|
||||||
regs->eflags &= ~IF_MASK;
|
regs->eflags &= ~IF_MASK;
|
||||||
/*single step inline if the instruction is an int3*/
|
/*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);
|
regs->eip = orig_eip + (regs->eip - copy_eip);
|
||||||
|
|
||||||
no_change:
|
no_change:
|
||||||
|
restore_btf();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,8 +256,21 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
|
|||||||
kcb->kprobe_saved_rflags &= ~IF_MASK;
|
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)
|
static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
|
clear_btf();
|
||||||
regs->eflags |= TF_MASK;
|
regs->eflags |= TF_MASK;
|
||||||
regs->eflags &= ~IF_MASK;
|
regs->eflags &= ~IF_MASK;
|
||||||
/*single step inline if the instruction is an int3*/
|
/*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);
|
regs->rip = orig_rip + (regs->rip - copy_rip);
|
||||||
no_change:
|
no_change:
|
||||||
|
restore_btf();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user