Jacek Caban : ntdll: Use syscall frame for FPU and XMM contexts in NtSetContextThread.
Alexandre Julliard
julliard at winehq.org
Mon Mar 1 15:54:05 CST 2021
Module: wine
Branch: master
Commit: 6e03330a2124dfcdd631d43672f5ead46ce9f334
URL: https://source.winehq.org/git/wine.git/?a=commit;h=6e03330a2124dfcdd631d43672f5ead46ce9f334
Author: Jacek Caban <jacek at codeweavers.com>
Date: Mon Mar 1 16:52:15 2021 +0100
ntdll: Use syscall frame for FPU and XMM contexts 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 | 73 ++++++++++++++++++++++++++++++++-----------
1 file changed, 54 insertions(+), 19 deletions(-)
diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c
index cec2a89c7bf..cc1e1d24e2a 100644
--- a/dlls/ntdll/unix/signal_i386.c
+++ b/dlls/ntdll/unix/signal_i386.c
@@ -770,23 +770,6 @@ static inline void restore_fpu( const CONTEXT *context )
}
-/***********************************************************************
- * restore_fpux
- *
- * Restore the FPU extended context
- */
-static inline void restore_fpux( const CONTEXT *context )
-{
- /* we have to enforce alignment by hand */
- char buffer[sizeof(XSAVE_FORMAT) + 16];
- XSAVE_FORMAT *state = (XSAVE_FORMAT *)(((ULONG_PTR)buffer + 15) & ~15);
-
- memcpy( state, context->ExtendedRegisters, sizeof(*state) );
- /* reset the current interrupt status */
- state->StatusWord &= state->ControlWord | 0xff80;
- __asm__ __volatile__( "fxrstor %0" : : "m" (*state) );
-}
-
/***********************************************************************
* restore_xstate
*
@@ -867,6 +850,32 @@ static void fpux_to_fpu( FLOATING_SAVE_AREA *fpu, const XSAVE_FORMAT *fpux )
}
+/***********************************************************************
+ * fpu_to_fpux
+ *
+ * Fill extended FPU context from standard one.
+ */
+static void fpu_to_fpux( XSAVE_FORMAT *fpux, const FLOATING_SAVE_AREA *fpu )
+{
+ unsigned int i;
+
+ fpux->ControlWord = fpu->ControlWord;
+ fpux->StatusWord = fpu->StatusWord;
+ fpux->ErrorOffset = fpu->ErrorOffset;
+ fpux->ErrorSelector = fpu->ErrorSelector;
+ fpux->ErrorOpcode = fpu->ErrorSelector >> 16;
+ fpux->DataOffset = fpu->DataOffset;
+ fpux->DataSelector = fpu->DataSelector;
+ fpux->TagWord = 0;
+ for (i = 0; i < 8; i++)
+ {
+ if (((fpu->TagWord >> (i * 2)) & 3) != 3)
+ fpux->TagWord |= 1 << i;
+ memcpy( &fpux->FloatRegisters[i], &fpu->RegisterArea[10 * i], 10 );
+ }
+}
+
+
/***********************************************************************
* save_context
*
@@ -1041,6 +1050,16 @@ __ASM_GLOBAL_FUNC( set_full_cpu_context,
*/
void signal_restore_full_cpu_context(void)
{
+ struct syscall_xsave *xsave = get_syscall_xsave( get_syscall_frame() );
+
+ if (cpu_info.FeatureSet & CPU_FEATURE_FXSR)
+ {
+ __asm__ volatile( "fxrstor %0" : : "m"(xsave->u.xsave) );
+ }
+ else
+ {
+ __asm__ volatile( "frstor %0; fwait" : : "m" (xsave->u.fsave) );
+ }
set_full_cpu_context();
}
@@ -1272,8 +1291,24 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
frame->fs = context->SegFs;
frame->gs = context->SegGs;
}
- if (flags & CONTEXT_EXTENDED_REGISTERS) restore_fpux( context );
- else if (flags & CONTEXT_FLOATING_POINT) restore_fpu( context );
+ if (flags & CONTEXT_EXTENDED_REGISTERS)
+ {
+ struct syscall_xsave *xsave = get_syscall_xsave( frame );
+ memcpy( &xsave->u.xsave, context->ExtendedRegisters, sizeof(xsave->u.xsave) );
+ /* reset the current interrupt status */
+ xsave->u.xsave.StatusWord &= xsave->u.xsave.ControlWord | 0xff80;
+ }
+ else if (flags & CONTEXT_FLOATING_POINT)
+ {
+ if (cpu_info.FeatureSet & CPU_FEATURE_FXSR)
+ {
+ fpu_to_fpux( &get_syscall_xsave( frame )->u.xsave, &context->FloatSave );
+ }
+ else
+ {
+ get_syscall_xsave( frame )->u.fsave = context->FloatSave;
+ }
+ }
restore_xstate( context );
More information about the wine-cvs
mailing list