[PATCH 3/5] ntdll: Restore AVX registers in NtSetContextThread() on x64.

Paul Gofman pgofman at codeweavers.com
Thu Aug 20 18:42:13 CDT 2020


Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
 dlls/ntdll/tests/exception.c    |  4 ++--
 dlls/ntdll/unix/signal_x86_64.c | 30 ++++++++++++++++++++++++++++++
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index cf704093fce..1bbf9f4f912 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -5600,7 +5600,7 @@ static void test_extended_context(void)
     for (i = 0; i < 8; ++i)
     {
         /* Older Windows version do not reset AVX context to INIT_STATE on x86. */
-        todo_wine_if(i >= 4)
+        todo_wine_if(i >= 4 && sizeof(void *) == 4)
         ok(!data[i] || broken(i >= 4 && sizeof(void *) == 4 && data[i] == test_extended_context_spoil_data2[i]),
                 "Got unexpected data %#x, i %u.\n", data[i], i);
     }
@@ -5611,7 +5611,7 @@ static void test_extended_context(void)
             ARRAY_SIZE(except_code_set_ymm0), PAGE_EXECUTE_READ);
 
     for (i = 0; i < 8; ++i)
-        todo_wine_if(i >= 4)
+        todo_wine_if(i >= 4 && sizeof(void *) == 4)
         ok(data[i] == test_extended_context_data[i], "Got unexpected data %#x, i %u.\n", data[i], i);
 }
 #endif
diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c
index 370f1f36fd7..53b9d98e80c 100644
--- a/dlls/ntdll/unix/signal_x86_64.c
+++ b/dlls/ntdll/unix/signal_x86_64.c
@@ -1543,6 +1543,34 @@ __ASM_GLOBAL_FUNC( set_full_cpu_context,
                    "iretq" );
 
 
+/***********************************************************************
+ *           restore_xstate
+ *
+ * Restore the XState context.
+ */
+static void restore_xstate( const CONTEXT *context )
+{
+    XSAVE_FORMAT *xrstor_base;
+    XSTATE *xs;
+
+    if (!(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. We have only padding, no more used EXCEPTION_RECORD or unused context fields
+         * at the MxCsr restore location, so just put it there. */
+        assert( (void *)&xrstor_base->MxCsr > (void *)context->VectorRegister );
+        xrstor_base->MxCsr = context->u.FltSave.MxCsr;
+        xrstor_base->MxCsr_Mask = context->u.FltSave.MxCsr_Mask;
+    }
+
+    __asm__ volatile("xor %%edx,%%edx; mov $4,%%eax; xrstor64 %0" : : "m"(*xrstor_base) : "eax", "edx");
+}
+
 /***********************************************************************
  *           get_server_context_flags
  *
@@ -1733,6 +1761,8 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
         }
     }
 
+    restore_xstate( context );
+
     if (flags & CONTEXT_FULL)
     {
         if (!(flags & CONTEXT_CONTROL))
-- 
2.26.2




More information about the wine-devel mailing list