Commit 60117582 authored by Paul Gofman's avatar Paul Gofman Committed by Alexandre Julliard

ntdll: Restore AVX registers in NtSetContextThread() on i386.

parent 9aa885bf
...@@ -5562,7 +5562,6 @@ static void test_extended_context(void) ...@@ -5562,7 +5562,6 @@ static void test_extended_context(void)
for (i = 0; i < 8; ++i) for (i = 0; i < 8; ++i)
{ {
/* Older Windows version do not reset AVX context to INIT_STATE on x86. */ /* Older Windows version do not reset AVX context to INIT_STATE on x86. */
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]), 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); "Got unexpected data %#x, i %u.\n", data[i], i);
} }
...@@ -5573,7 +5572,6 @@ static void test_extended_context(void) ...@@ -5573,7 +5572,6 @@ static void test_extended_context(void)
ARRAY_SIZE(except_code_set_ymm0), PAGE_EXECUTE_READ); ARRAY_SIZE(except_code_set_ymm0), PAGE_EXECUTE_READ);
for (i = 0; i < 8; ++i) for (i = 0; i < 8; ++i)
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); ok(data[i] == test_extended_context_data[i], "Got unexpected data %#x, i %u.\n", data[i], i);
} }
#endif #endif
......
...@@ -687,7 +687,7 @@ static inline void save_fpux( CONTEXT *context ) ...@@ -687,7 +687,7 @@ static inline void save_fpux( CONTEXT *context )
/*********************************************************************** /***********************************************************************
* restore_fpu * restore_fpu
* *
* Restore the FPU context to a sigcontext. * Restore the x87 FPU context
*/ */
static inline void restore_fpu( const CONTEXT *context ) static inline void restore_fpu( const CONTEXT *context )
{ {
...@@ -701,7 +701,7 @@ static inline void restore_fpu( const CONTEXT *context ) ...@@ -701,7 +701,7 @@ static inline void restore_fpu( const CONTEXT *context )
/*********************************************************************** /***********************************************************************
* restore_fpux * restore_fpux
* *
* Restore the FPU extended context to a sigcontext. * Restore the FPU extended context
*/ */
static inline void restore_fpux( const CONTEXT *context ) static inline void restore_fpux( const CONTEXT *context )
{ {
...@@ -715,6 +715,38 @@ static inline void restore_fpux( const CONTEXT *context ) ...@@ -715,6 +715,38 @@ static inline void restore_fpux( const CONTEXT *context )
__asm__ __volatile__( "fxrstor %0" : : "m" (*state) ); __asm__ __volatile__( "fxrstor %0" : : "m" (*state) );
} }
/***********************************************************************
* restore_xstate
*
* Restore the XState context
*/
static inline 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. 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 * fpux_to_fpu
...@@ -1129,6 +1161,8 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context ) ...@@ -1129,6 +1161,8 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
if (flags & CONTEXT_EXTENDED_REGISTERS) restore_fpux( context ); if (flags & CONTEXT_EXTENDED_REGISTERS) restore_fpux( context );
else if (flags & CONTEXT_FLOATING_POINT) restore_fpu( context ); else if (flags & CONTEXT_FLOATING_POINT) restore_fpu( context );
restore_xstate( context );
if (flags & CONTEXT_FULL) if (flags & CONTEXT_FULL)
{ {
if (!(flags & CONTEXT_CONTROL)) if (!(flags & CONTEXT_CONTROL))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment