Commit 08d68323 authored by K.Prasad's avatar K.Prasad Committed by Frederic Weisbecker

hw-breakpoints: modifying generic debug exception to use thread-specific debug registers

This patch modifies the breakpoint exception handler code to use the new
abstract debug register names.

[ fweisbec@gmail.com: fix conflict against kmemcheck ]

[ Impact: refactor and cleanup x86 debug exception handler ]
Original-patch-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarK.Prasad <prasad@linux.vnet.ibm.com>
Reviewed-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarFrederic Weisbecker <fweisbec@gmail.com>
parent 0067f129
...@@ -529,73 +529,52 @@ asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs) ...@@ -529,73 +529,52 @@ asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs)
dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code)
{ {
struct task_struct *tsk = current; struct task_struct *tsk = current;
unsigned long condition; unsigned long dr6;
int si_code; int si_code;
get_debugreg(condition, 6); get_debugreg(dr6, 6);
/* DR6 may or may not be cleared by the CPU */
set_debugreg(0, 6);
/* /*
* The processor cleared BTF, so don't mark that we need it set. * The processor cleared BTF, so don't mark that we need it set.
*/ */
clear_tsk_thread_flag(tsk, TIF_DEBUGCTLMSR); clear_tsk_thread_flag(tsk, TIF_DEBUGCTLMSR);
tsk->thread.debugctlmsr = 0; tsk->thread.debugctlmsr = 0;
if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code, /* Store the virtualized DR6 value */
tsk->thread.debugreg6 = dr6;
if (notify_die(DIE_DEBUG, "debug", regs, dr6, error_code,
SIGTRAP) == NOTIFY_STOP) SIGTRAP) == NOTIFY_STOP)
return; return;
/* It's safe to allow irq's after DR6 has been saved */ /* It's safe to allow irq's after DR6 has been saved */
preempt_conditional_sti(regs); preempt_conditional_sti(regs);
/* Mask out spurious debug traps due to lazy DR7 setting */ if (regs->flags & X86_VM_MASK) {
if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) { handle_vm86_trap((struct kernel_vm86_regs *) regs,
if (!tsk->thread.debugreg7) error_code, 1);
goto clear_dr7; return;
} }
#ifdef CONFIG_X86_32
if (regs->flags & X86_VM_MASK)
goto debug_vm86;
#endif
/* Save debug status register where ptrace can see it */
tsk->thread.debugreg6 = condition;
/* /*
* Single-stepping through TF: make sure we ignore any events in * Single-stepping through system calls: ignore any exceptions in
* kernel space (but re-enable TF when returning to user mode). * kernel space, but re-enable TF when returning to user mode.
*
* We already checked v86 mode above, so we can check for kernel mode
* by just checking the CPL of CS.
*/ */
if (condition & DR_STEP) { if ((dr6 & DR_STEP) && !user_mode(regs)) {
if (!user_mode(regs)) tsk->thread.debugreg6 &= ~DR_STEP;
goto clear_TF_reenable; set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
regs->flags &= ~X86_EFLAGS_TF;
} }
si_code = get_si_code(tsk->thread.debugreg6);
si_code = get_si_code(condition); if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS))
/* Ok, finally something we can handle */ send_sigtrap(tsk, regs, error_code, si_code);
send_sigtrap(tsk, regs, error_code, si_code);
/*
* Disable additional traps. They'll be re-enabled when
* the signal is delivered.
*/
clear_dr7:
set_debugreg(0, 7);
preempt_conditional_cli(regs); preempt_conditional_cli(regs);
return;
#ifdef CONFIG_X86_32
debug_vm86:
/* reenable preemption: handle_vm86_trap() might sleep */
dec_preempt_count();
handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
conditional_cli(regs);
return;
#endif
clear_TF_reenable:
set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
regs->flags &= ~X86_EFLAGS_TF;
preempt_conditional_cli(regs);
return; return;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment