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