Added fields for temporary storage of the debug registers dr6 and dr7 to the
arch_cpu_info structure. The actual registers are stored at the beginning of
x86_exit_user_debug_at_kernel_entry() and read in
x86_handle_debug_exception().
The problem was that x86_exit_user_debug_at_kernel_entry() itself overwrote
dr7 and, if kernel breakpoints were enabled, dr6 could be overwritten anytime
after. So x86_handle_debug_exception() would find incorrect values in the
registers (definitely in dr7) and thus interpret the detected debug condition
incorrectly. Usually watchpoints were recognized as breakpoints.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35951 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2010-03-26 00:03:53 +00:00
parent 9f018a4672
commit feddedab0c
2 changed files with 14 additions and 5 deletions

View File

@ -250,6 +250,9 @@ typedef struct arch_cpu_info {
struct vm_translation_map_arch_info* active_translation_map;
uint32 dr6; // temporary storage for debug registers (cf.
uint32 dr7; // x86_exit_user_debug_at_kernel_entry())
// local TSS for this cpu
struct tss tss;
struct tss double_fault_tss;

View File

@ -806,6 +806,12 @@ x86_exit_user_debug_at_kernel_entry()
if (!(thread->flags & THREAD_FLAGS_BREAKPOINTS_INSTALLED))
return;
// We need to save the current values of dr6 and dr7 in the CPU structure,
// since in case of a debug exception we might overwrite them before
// x86_handle_debug_exception() is called.
asm("movl %%dr6, %0" : "=r"(thread->cpu->arch.dr6));
asm("movl %%dr7, %0" : "=r"(thread->cpu->arch.dr7));
GRAB_THREAD_LOCK();
// disable user breakpoints
@ -829,10 +835,11 @@ x86_exit_user_debug_at_kernel_entry()
void
x86_handle_debug_exception(struct iframe *frame)
{
// get debug status and control registers
uint32 dr6, dr7;
asm("movl %%dr6, %0" : "=r"(dr6));
asm("movl %%dr7, %0" : "=r"(dr7));
// get debug status and control registers (saved earlier in
// x86_exit_user_debug_at_kernel_entry())
struct thread* thread = thread_get_current_thread();
uint32 dr6 = thread->cpu->arch.dr6;
uint32 dr7 = thread->cpu->arch.dr7;
TRACE(("i386_handle_debug_exception(): DR6: %lx, DR7: %lx\n", dr6, dr7));
@ -889,7 +896,6 @@ x86_handle_debug_exception(struct iframe *frame)
// Determine whether the exception occurred at a syscall/trap
// kernel entry or whether this is genuine kernel single-stepping.
bool inKernel = true;
struct thread* thread = thread_get_current_thread();
if (thread->team != team_get_kernel_team()
&& i386_get_user_iframe() == NULL) {
// TODO: This is not yet fully correct, since a newly created