Module: wine Branch: master Commit: 4de079bb7247c8b849558c0f27a280a9546c5570 URL: https://source.winehq.org/git/wine.git/?a=commit;h=4de079bb7247c8b849558c0f2...
Author: Jacek Caban jacek@codeweavers.com Date: Fri Feb 19 19:09:03 2021 +0100
ntdll: Use syscall frame for x86_64 YMM context in NtGetContextThread.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ntdll/unix/signal_x86_64.c | 82 +++++++++++++---------------------------- 1 file changed, 26 insertions(+), 56 deletions(-)
diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index ca0f9117cd5..8d3353e959d 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -1540,56 +1540,6 @@ static void save_context( struct xcontext *xcontext, const ucontext_t *sigcontex }
-/*********************************************************************** - * save_xstate - * - * Save the XState context - */ -static inline NTSTATUS save_xstate( CONTEXT *context ) -{ - CONTEXT_EX *context_ex = (CONTEXT_EX *)(context + 1); - DECLSPEC_ALIGN(64) struct - { - XSAVE_FORMAT xsave; - XSTATE xstate; - } - xsave_area; - XSTATE *xs; - - if (!(user_shared_data->XState.EnabledFeatures && (xs = xstate_from_context( context )))) - return STATUS_SUCCESS; - - if (context_ex->XState.Length < offsetof(XSTATE, YmmContext) - || context_ex->XState.Length > sizeof(XSTATE)) - return STATUS_INVALID_PARAMETER; - - if (user_shared_data->XState.CompactionEnabled) - { - /* xsavec doesn't use anything from the save area. */ - __asm__ volatile( "xsavec %0" : "=m"(xsave_area) - : "a" ((unsigned int)(xs->CompactionMask & (1 << XSTATE_AVX))), "d" (0) ); - } - else - { - /* xsave preserves those bits in the mask which are not in EDX:EAX, so zero it. */ - xsave_area.xstate.Mask = xsave_area.xstate.CompactionMask = 0; - __asm__ volatile( "xsave %0" : "=m"(xsave_area) - : "a" ((unsigned int)(xs->Mask & (1 << XSTATE_AVX))), "d" (0) ); - } - - memcpy(xs, &xsave_area.xstate, offsetof(XSTATE, YmmContext)); - if (xs->Mask & (1 << XSTATE_AVX)) - { - if (context_ex->XState.Length < sizeof(XSTATE)) - return STATUS_BUFFER_OVERFLOW; - - memcpy(&xs->YmmContext, &xsave_area.xstate.YmmContext, sizeof(xs->YmmContext)); - } - - return STATUS_SUCCESS; -} - - /*********************************************************************** * restore_context * @@ -1895,17 +1845,14 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context ) */ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) { - NTSTATUS ret, xsave_status; + NTSTATUS ret; DWORD needed_flags; struct syscall_frame *frame = amd64_thread_data()->syscall_frame; BOOL self = (handle == GetCurrentThread()); + XSTATE *xstate;
if (!context) return STATUS_INVALID_PARAMETER;
- /* Save xstate before any calls which can potentially change volatile ymm registers. - * E. g., debug output will clobber ymm registers. */ - xsave_status = self ? save_xstate( context ) : STATUS_SUCCESS; - needed_flags = context->ContextFlags & ~CONTEXT_AMD64;
/* debug registers require a server call */ @@ -1975,9 +1922,32 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) amd64_thread_data()->dr6 = context->Dr6; amd64_thread_data()->dr7 = context->Dr7; } + if (user_shared_data->XState.EnabledFeatures && (xstate = xstate_from_context( context ))) + { + struct syscall_xsave *xsave = get_syscall_xsave( frame ); + CONTEXT_EX *context_ex = (CONTEXT_EX *)(context + 1); + const BOOL compaction_enabled = user_shared_data->XState.CompactionEnabled; + unsigned int mask; + + if (context_ex->XState.Length < offsetof(XSTATE, YmmContext) + || context_ex->XState.Length > sizeof(XSTATE)) + return STATUS_INVALID_PARAMETER; + + mask = (compaction_enabled ? xstate->CompactionMask : xstate->Mask) & XSTATE_MASK_GSSE; + xstate->Mask = xsave->xstate.Mask & mask; + xstate->CompactionMask = compaction_enabled ? (0x8000000000000000 | mask) : 0; + memset( xstate->Reserved, 0, sizeof(xstate->Reserved) ); + if (xstate->Mask) + { + if (context_ex->XState.Length < sizeof(XSTATE)) + return STATUS_BUFFER_OVERFLOW; + + memcpy( &xstate->YmmContext, &xsave->xstate.YmmContext, sizeof(xstate->YmmContext) ); + } + } }
- return xsave_status; + return STATUS_SUCCESS; }
extern void CDECL raise_func_trampoline( void *dispatcher );