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

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2021-03-02 18:47:05 +01:00 committed by Alexandre Julliard
parent 8064d9786a
commit e990bd4676
1 changed files with 25 additions and 36 deletions

View File

@ -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();