diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index 2ef28d83c4..aa6e49afe0 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -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; diff --git a/src/system/kernel/arch/x86/arch_user_debugger.cpp b/src/system/kernel/arch/x86/arch_user_debugger.cpp index 2c784069a4..b4861bc3bd 100644 --- a/src/system/kernel/arch/x86/arch_user_debugger.cpp +++ b/src/system/kernel/arch/x86/arch_user_debugger.cpp @@ -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