From: Paul Gofman Subject: [PATCH v3 3/3] ntdll: Use cached debug registers in NtGetContextThread() if hw debug breakpoints are disabled. Message-Id: <20210527101600.348718-3-pgofman@codeweavers.com> Date: Thu, 27 May 2021 13:16:00 +0300 In-Reply-To: <20210527101600.348718-1-pgofman@codeweavers.com> References: <20210527101600.348718-1-pgofman@codeweavers.com> Signed-off-by: Paul Gofman --- dlls/ntdll/unix/signal_i386.c | 35 +++++++++++++++++++++-------- dlls/ntdll/unix/signal_x86_64.c | 39 +++++++++++++++++++++++---------- 2 files changed, 54 insertions(+), 20 deletions(-) diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index 28e95c084db..69bef162d64 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -1110,10 +1110,15 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) struct syscall_frame *frame = x86_thread_data()->syscall_frame; DWORD needed_flags = context->ContextFlags & ~CONTEXT_i386; BOOL self = (handle == GetCurrentThread()); + BOOL use_cached_debug_regs = FALSE; NTSTATUS ret; - /* debug registers require a server call */ - if (needed_flags & CONTEXT_DEBUG_REGISTERS) self = FALSE; + if (self && needed_flags & CONTEXT_DEBUG_REGISTERS) + { + /* debug registers require a server call if hw breakpoints are enabled */ + if (x86_thread_data()->dr7 & 0xff) self = FALSE; + else use_cached_debug_regs = TRUE; + } if (!self) { @@ -1204,15 +1209,27 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) context->ContextFlags |= CONTEXT_EXTENDED_REGISTERS; } - /* update the cached version of the debug registers */ if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386)) { - x86_thread_data()->dr0 = context->Dr0; - x86_thread_data()->dr1 = context->Dr1; - x86_thread_data()->dr2 = context->Dr2; - x86_thread_data()->dr3 = context->Dr3; - x86_thread_data()->dr6 = context->Dr6; - x86_thread_data()->dr7 = context->Dr7; + if (use_cached_debug_regs) + { + context->Dr0 = x86_thread_data()->dr0; + context->Dr1 = x86_thread_data()->dr1; + context->Dr2 = x86_thread_data()->dr2; + context->Dr3 = x86_thread_data()->dr3; + context->Dr6 = x86_thread_data()->dr6; + context->Dr7 = x86_thread_data()->dr7; + } + else + { + /* update the cached version of the debug registers */ + x86_thread_data()->dr0 = context->Dr0; + x86_thread_data()->dr1 = context->Dr1; + x86_thread_data()->dr2 = context->Dr2; + x86_thread_data()->dr3 = context->Dr3; + x86_thread_data()->dr6 = context->Dr6; + x86_thread_data()->dr7 = context->Dr7; + } } if ((cpu_info.ProcessorFeatureBits & CPU_FEATURE_AVX) && (xstate = xstate_from_context( context ))) { diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index 2332befdf40..448f45474b1 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -1718,18 +1718,23 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context ) */ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) { - NTSTATUS ret; - DWORD needed_flags; struct syscall_frame *frame = amd64_thread_data()->syscall_frame; BOOL self = (handle == GetCurrentThread()); + BOOL use_cached_debug_regs = FALSE; + DWORD needed_flags; XSTATE *xstate; + NTSTATUS ret; if (!context) return STATUS_INVALID_PARAMETER; needed_flags = context->ContextFlags & ~CONTEXT_AMD64; - /* debug registers require a server call */ - if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_AMD64)) self = FALSE; + if (self && needed_flags & CONTEXT_DEBUG_REGISTERS) + { + /* debug registers require a server call if hw breakpoints are enabled */ + if (amd64_thread_data()->dr7 & 0xff) self = FALSE; + else use_cached_debug_regs = TRUE; + } if (!self) { @@ -1812,15 +1817,27 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) context->MxCsr = context->u.FltSave.MxCsr; context->ContextFlags |= CONTEXT_FLOATING_POINT; } - /* update the cached version of the debug registers */ if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_AMD64)) { - amd64_thread_data()->dr0 = context->Dr0; - amd64_thread_data()->dr1 = context->Dr1; - amd64_thread_data()->dr2 = context->Dr2; - amd64_thread_data()->dr3 = context->Dr3; - amd64_thread_data()->dr6 = context->Dr6; - amd64_thread_data()->dr7 = context->Dr7; + if (use_cached_debug_regs) + { + context->Dr0 = amd64_thread_data()->dr0; + context->Dr1 = amd64_thread_data()->dr1; + context->Dr2 = amd64_thread_data()->dr2; + context->Dr3 = amd64_thread_data()->dr3; + context->Dr6 = amd64_thread_data()->dr6; + context->Dr7 = amd64_thread_data()->dr7; + } + else + { + /* update the cached version of the debug registers */ + amd64_thread_data()->dr0 = context->Dr0; + amd64_thread_data()->dr1 = context->Dr1; + amd64_thread_data()->dr2 = context->Dr2; + amd64_thread_data()->dr3 = context->Dr3; + amd64_thread_data()->dr6 = context->Dr6; + amd64_thread_data()->dr7 = context->Dr7; + } } if ((cpu_info.ProcessorFeatureBits & CPU_FEATURE_AVX) && (xstate = xstate_from_context( context ))) { -- 2.31.1