Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ntdll/tests/exception.c | 2 -- dlls/ntdll/unix/signal_i386.c | 38 +++++++++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 4 deletions(-)
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index 860221366ce..9f93212acf6 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -5600,7 +5600,6 @@ 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 && 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 +5610,6 @@ 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 && 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_i386.c b/dlls/ntdll/unix/signal_i386.c index 791ffe90940..e03cb4a517b 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -687,7 +687,7 @@ static inline void save_fpux( CONTEXT *context ) /*********************************************************************** * restore_fpu * - * Restore the FPU context to a sigcontext. + * Restore the x87 FPU context */ static inline void restore_fpu( const CONTEXT *context ) { @@ -701,7 +701,7 @@ static inline void restore_fpu( const CONTEXT *context ) /*********************************************************************** * restore_fpux * - * Restore the FPU extended context to a sigcontext. + * Restore the FPU extended context */ 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) ); }
+/*********************************************************************** + * 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("xor %%edx,%%edx; mov $4,%%eax; xrstor %0" : : "m"(*xrstor_base) : "eax", "edx"); +}
/*********************************************************************** * fpux_to_fpu @@ -1129,6 +1161,8 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context ) if (flags & CONTEXT_EXTENDED_REGISTERS) restore_fpux( context ); else if (flags & CONTEXT_FLOATING_POINT) restore_fpu( context );
+ restore_xstate( context ); + if (flags & CONTEXT_FULL) { if (!(flags & CONTEXT_CONTROL))