Jacek Caban : ntdll: Use syscall frame for handling x86 YMM context in NtSetContextThread.

Alexandre Julliard julliard at winehq.org
Tue Mar 2 15:35:59 CST 2021


Module: wine
Branch: master
Commit: e990bd4676d7ecef302f36ad0896ddba5efdedd9
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=e990bd4676d7ecef302f36ad0896ddba5efdedd9

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Tue Mar  2 18:47:05 2021 +0100

ntdll: Use syscall frame for handling x86 YMM context in NtSetContextThread.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/unix/signal_i386.c | 61 ++++++++++++++++++-------------------------
 1 file changed, 25 insertions(+), 36 deletions(-)

diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c
index 129d719a96c..fd3c42c571c 100644
--- a/dlls/ntdll/unix/signal_i386.c
+++ b/dlls/ntdll/unix/signal_i386.c
@@ -727,40 +727,6 @@ static inline void restore_fpu( const CONTEXT *context )
 }
 
 
-/***********************************************************************
- *           restore_xstate
- *
- * Restore the XState context
- */
-static inline void restore_xstate( const CONTEXT *context )
-{
-    XSAVE_FORMAT *xrstor_base;
-    XSTATE *xs;
-
-    if (!(cpu_info.FeatureSet & CPU_FEATURE_AVX) || !(xs = xstate_from_context( context )))
-        return;
-
-    xrstor_base = (XSAVE_FORMAT *)xs - 1;
-
-    if (!(xs->CompactionMask & ((ULONG64)1 << 63)))
-    {
-        /* Non-compacted xrstor will load Mxcsr regardless of the specified mask. Loading garbage there
-         * may lead to fault. FPUX state should be restored by now, so we can reuse some space in
-         * ExtendedRegisters. */
-        XSAVE_FORMAT *fpux = (XSAVE_FORMAT *)context->ExtendedRegisters;
-        DWORD mxcsr, mxcsr_mask;
-
-        mxcsr = fpux->MxCsr;
-        mxcsr_mask = fpux->MxCsr_Mask;
-
-        assert( (void *)&xrstor_base->MxCsr > (void *)context->ExtendedRegisters );
-        xrstor_base->MxCsr = mxcsr;
-        xrstor_base->MxCsr_Mask = mxcsr_mask;
-    }
-    __asm__ volatile( "xrstor %0" : : "m"(*xrstor_base), "a" (4), "d" (0) );
-}
-
-
 /***********************************************************************
  *           fpux_to_fpu
  *
@@ -1009,7 +975,11 @@ void signal_restore_full_cpu_context(void)
 {
     struct syscall_xsave *xsave = get_syscall_xsave( get_syscall_frame() );
 
-    if (cpu_info.FeatureSet & CPU_FEATURE_FXSR)
+    if (cpu_info.FeatureSet & CPU_FEATURE_XSAVE)
+    {
+        __asm__ volatile( "xrstor %0" : : "m"(*xsave), "a" (7), "d" (0) );
+    }
+    else if (cpu_info.FeatureSet & CPU_FEATURE_FXSR)
     {
         __asm__ volatile( "fxrstor %0" : : "m"(xsave->u.xsave) );
     }
@@ -1196,6 +1166,7 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
     struct syscall_frame *frame = x86_thread_data()->syscall_frame;
     DWORD flags = context->ContextFlags & ~CONTEXT_i386;
     BOOL self = (handle == GetCurrentThread());
+    XSTATE *xs;
 
     /* debug registers require a server call */
     if (self && (flags & CONTEXT_DEBUG_REGISTERS))
@@ -1266,8 +1237,26 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
             get_syscall_xsave( frame )->u.fsave = context->FloatSave;
         }
     }
+    if ((cpu_info.FeatureSet & CPU_FEATURE_AVX) && (xs = xstate_from_context( context )))
+    {
+        struct syscall_xsave *xsave = get_syscall_xsave( frame );
+        CONTEXT_EX *context_ex = (CONTEXT_EX *)(context + 1);
 
-    restore_xstate( context );
+        if (context_ex->XState.Length < offsetof(XSTATE, YmmContext)
+            || context_ex->XState.Length > sizeof(XSTATE))
+            return STATUS_INVALID_PARAMETER;
+
+        if (xs->Mask & XSTATE_MASK_GSSE)
+        {
+            if (context_ex->XState.Length < sizeof(XSTATE))
+                return STATUS_BUFFER_OVERFLOW;
+
+            xsave->xstate.mask |= XSTATE_MASK_GSSE;
+            memcpy( &xsave->xstate.ymm_high, &xs->YmmContext, sizeof(xsave->xstate.ymm_high) );
+        }
+        else if (xs->CompactionMask & XSTATE_MASK_GSSE)
+            xsave->xstate.mask &= ~XSTATE_MASK_GSSE;
+    }
 
     if (!(flags & CONTEXT_INTEGER)) frame->eax = STATUS_SUCCESS;
     signal_restore_full_cpu_context();




More information about the wine-cvs mailing list