Commit 419abd49 authored by Paul Gofman's avatar Paul Gofman Committed by Alexandre Julliard

ntdll: Support AVX registers for other thread in Nt{Get|Set}ContextThread().

parent ec1ea1ea
...@@ -631,8 +631,15 @@ unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT ...@@ -631,8 +631,15 @@ unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT
if (wine_server_reply_size( reply )) if (wine_server_reply_size( reply ))
{ {
DWORD context_flags = context->ContextFlags; /* unchanged registers are still available */ DWORD context_flags = context->ContextFlags; /* unchanged registers are still available */
XSTATE *xs = xstate_from_context( context );
ULONG64 mask;
if (xs)
mask = xs->Mask;
context_from_server( context, &server_context ); context_from_server( context, &server_context );
context->ContextFlags |= context_flags; context->ContextFlags |= context_flags;
if (xs)
xs->Mask |= mask;
} }
} }
SERVER_END_REQ; SERVER_END_REQ;
......
...@@ -886,14 +886,16 @@ static inline void save_context( struct xcontext *xcontext, const ucontext_t *si ...@@ -886,14 +886,16 @@ static inline void save_context( struct xcontext *xcontext, const ucontext_t *si
} }
if (fpux) if (fpux)
{ {
XSTATE *xs;
context->ContextFlags |= CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS; context->ContextFlags |= CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS;
memcpy( context->ExtendedRegisters, fpux, sizeof(*fpux) ); memcpy( context->ExtendedRegisters, fpux, sizeof(*fpux) );
if (!fpu) fpux_to_fpu( &context->FloatSave, fpux ); if (!fpu) fpux_to_fpu( &context->FloatSave, fpux );
xcontext->xstate = XState_sig(fpux); if ((xs = XState_sig(fpux)))
} {
else context_init_xstate( context, xs );
{ xcontext->host_compaction_mask = xs->CompactionMask;
xcontext->xstate = NULL; }
} }
if (!fpu && !fpux) save_fpu( context ); if (!fpu && !fpux) save_fpu( context );
} }
...@@ -944,6 +946,7 @@ static inline void restore_context( const struct xcontext *xcontext, ucontext_t ...@@ -944,6 +946,7 @@ static inline void restore_context( const struct xcontext *xcontext, ucontext_t
{ {
memcpy( &dst_xs->YmmContext, &src_xs->YmmContext, sizeof(dst_xs->YmmContext) ); memcpy( &dst_xs->YmmContext, &src_xs->YmmContext, sizeof(dst_xs->YmmContext) );
dst_xs->Mask |= src_xs->Mask; dst_xs->Mask |= src_xs->Mask;
dst_xs->CompactionMask = xcontext->host_compaction_mask;
} }
} }
if (!fpu && !fpux) restore_fpu( context ); if (!fpu && !fpux) restore_fpu( context );
...@@ -1023,6 +1026,7 @@ static unsigned int get_server_context_flags( DWORD flags ) ...@@ -1023,6 +1026,7 @@ static unsigned int get_server_context_flags( DWORD flags )
if (flags & CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT; if (flags & CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT;
if (flags & CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS; if (flags & CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS;
if (flags & CONTEXT_EXTENDED_REGISTERS) ret |= SERVER_CTX_EXTENDED_REGISTERS; if (flags & CONTEXT_EXTENDED_REGISTERS) ret |= SERVER_CTX_EXTENDED_REGISTERS;
if (flags & CONTEXT_XSTATE) ret |= SERVER_CTX_YMM_REGISTERS;
return ret; return ret;
} }
...@@ -1095,6 +1099,7 @@ NTSTATUS context_to_server( context_t *to, const CONTEXT *from ) ...@@ -1095,6 +1099,7 @@ NTSTATUS context_to_server( context_t *to, const CONTEXT *from )
to->flags |= SERVER_CTX_EXTENDED_REGISTERS; to->flags |= SERVER_CTX_EXTENDED_REGISTERS;
memcpy( to->ext.i386_regs, from->ExtendedRegisters, sizeof(to->ext.i386_regs) ); memcpy( to->ext.i386_regs, from->ExtendedRegisters, sizeof(to->ext.i386_regs) );
} }
xstate_to_server( to, xstate_from_context( from ) );
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
...@@ -1108,7 +1113,7 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from ) ...@@ -1108,7 +1113,7 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
{ {
if (from->cpu != CPU_x86) return STATUS_INVALID_PARAMETER; if (from->cpu != CPU_x86) return STATUS_INVALID_PARAMETER;
to->ContextFlags = CONTEXT_i386; to->ContextFlags = CONTEXT_i386 | (to->ContextFlags & 0x40);
if (from->flags & SERVER_CTX_CONTROL) if (from->flags & SERVER_CTX_CONTROL)
{ {
to->ContextFlags |= CONTEXT_CONTROL; to->ContextFlags |= CONTEXT_CONTROL;
...@@ -1165,6 +1170,7 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from ) ...@@ -1165,6 +1170,7 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
to->ContextFlags |= CONTEXT_EXTENDED_REGISTERS; to->ContextFlags |= CONTEXT_EXTENDED_REGISTERS;
memcpy( to->ExtendedRegisters, from->ext.i386_regs, sizeof(to->ExtendedRegisters) ); memcpy( to->ExtendedRegisters, from->ext.i386_regs, sizeof(to->ExtendedRegisters) );
} }
xstate_from_server( xstate_from_context( to ), from );
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
...@@ -1246,7 +1252,7 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) ...@@ -1246,7 +1252,7 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
/* Save xstate before any calls which can potentially change volatile ymm registers. /* Save xstate before any calls which can potentially change volatile ymm registers.
* E. g., debug output will clobber ymm registers. */ * E. g., debug output will clobber ymm registers. */
xsave_status = self ? save_xstate( context ) : STATUS_SUCCESS; /* FIXME: other thread. */ xsave_status = self ? save_xstate( context ) : STATUS_SUCCESS;
/* debug registers require a server call */ /* debug registers require a server call */
if (needed_flags & CONTEXT_DEBUG_REGISTERS) self = FALSE; if (needed_flags & CONTEXT_DEBUG_REGISTERS) self = FALSE;
...@@ -1293,7 +1299,6 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) ...@@ -1293,7 +1299,6 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
} }
if (needed_flags & CONTEXT_FLOATING_POINT) save_fpu( context ); if (needed_flags & CONTEXT_FLOATING_POINT) save_fpu( context );
if (needed_flags & CONTEXT_EXTENDED_REGISTERS) save_fpux( context ); if (needed_flags & CONTEXT_EXTENDED_REGISTERS) save_fpux( context );
/* FIXME: xstate */
/* update the cached version of the debug registers */ /* update the cached version of the debug registers */
if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386)) if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386))
{ {
...@@ -1579,6 +1584,7 @@ static void setup_raise_exception( ucontext_t *sigcontext, void *stack_ptr, ...@@ -1579,6 +1584,7 @@ static void setup_raise_exception( ucontext_t *sigcontext, void *stack_ptr,
{ {
CONTEXT *context = &xcontext->c; CONTEXT *context = &xcontext->c;
size_t stack_size; size_t stack_size;
XSTATE *src_xs;
struct stack_layout struct stack_layout
{ {
...@@ -1606,7 +1612,7 @@ C_ASSERT( (offsetof(struct stack_layout, xstate) == sizeof(struct stack_layout)) ...@@ -1606,7 +1612,7 @@ C_ASSERT( (offsetof(struct stack_layout, xstate) == sizeof(struct stack_layout))
if (rec->ExceptionCode == EXCEPTION_BREAKPOINT) context->Eip--; if (rec->ExceptionCode == EXCEPTION_BREAKPOINT) context->Eip--;
stack_size = sizeof(*stack); stack_size = sizeof(*stack);
if (xcontext->xstate) if ((src_xs = xstate_from_context( context )))
{ {
stack_size += (ULONG_PTR)stack_ptr - (((ULONG_PTR)stack_ptr stack_size += (ULONG_PTR)stack_ptr - (((ULONG_PTR)stack_ptr
- sizeof(XSTATE)) & ~(ULONG_PTR)63); - sizeof(XSTATE)) & ~(ULONG_PTR)63);
...@@ -1616,17 +1622,18 @@ C_ASSERT( (offsetof(struct stack_layout, xstate) == sizeof(struct stack_layout)) ...@@ -1616,17 +1622,18 @@ C_ASSERT( (offsetof(struct stack_layout, xstate) == sizeof(struct stack_layout))
stack->rec = *rec; stack->rec = *rec;
stack->context = *context; stack->context = *context;
if (xcontext->xstate) if (src_xs)
{ {
XSTATE *dst_xs = (XSTATE *)stack->xstate; XSTATE *dst_xs = (XSTATE *)stack->xstate;
assert(!((ULONG_PTR)dst_xs & 63)); assert(!((ULONG_PTR)dst_xs & 63));
context_init_xstate( &stack->context, stack->xstate ); context_init_xstate( &stack->context, stack->xstate );
memset( dst_xs, 0, offsetof(XSTATE, YmmContext) );
dst_xs->CompactionMask = user_shared_data->XState.CompactionEnabled ? 0x8000000000000004 : 0; dst_xs->CompactionMask = user_shared_data->XState.CompactionEnabled ? 0x8000000000000004 : 0;
if (xcontext->xstate->Mask & 4) if (src_xs->Mask & 4)
{ {
dst_xs->Mask = 4; dst_xs->Mask = 4;
memcpy( &dst_xs->YmmContext, &xcontext->xstate->YmmContext, sizeof(dst_xs->YmmContext) ); memcpy( &dst_xs->YmmContext, &src_xs->YmmContext, sizeof(dst_xs->YmmContext) );
} }
} }
......
...@@ -1461,14 +1461,19 @@ static void save_context( struct xcontext *xcontext, const ucontext_t *sigcontex ...@@ -1461,14 +1461,19 @@ static void save_context( struct xcontext *xcontext, const ucontext_t *sigcontex
context->Dr7 = amd64_thread_data()->dr7; context->Dr7 = amd64_thread_data()->dr7;
if (FPU_sig(sigcontext)) if (FPU_sig(sigcontext))
{ {
XSTATE *xs;
context->ContextFlags |= CONTEXT_FLOATING_POINT; context->ContextFlags |= CONTEXT_FLOATING_POINT;
context->u.FltSave = *FPU_sig(sigcontext); context->u.FltSave = *FPU_sig(sigcontext);
context->MxCsr = context->u.FltSave.MxCsr; context->MxCsr = context->u.FltSave.MxCsr;
xcontext->xstate = XState_sig(FPU_sig(sigcontext)); if ((xs = XState_sig(FPU_sig(sigcontext))))
} {
else /* xcontext and sigcontext are both on the signal stack, so we can
{ * just reference sigcontext without overflowing 32 bit XState.Offset */
xcontext->xstate = NULL; context_init_xstate( context, xs );
assert( xcontext->c_ex.XState.Offset == (BYTE *)xs - (BYTE *)&xcontext->c_ex );
xcontext->host_compaction_mask = xs->CompactionMask;
}
} }
} }
...@@ -1531,6 +1536,7 @@ static inline NTSTATUS save_xstate( CONTEXT *context ) ...@@ -1531,6 +1536,7 @@ static inline NTSTATUS save_xstate( CONTEXT *context )
static void restore_context( const struct xcontext *xcontext, ucontext_t *sigcontext ) static void restore_context( const struct xcontext *xcontext, ucontext_t *sigcontext )
{ {
const CONTEXT *context = &xcontext->c; const CONTEXT *context = &xcontext->c;
XSTATE *xs;
amd64_thread_data()->dr0 = context->Dr0; amd64_thread_data()->dr0 = context->Dr0;
amd64_thread_data()->dr1 = context->Dr1; amd64_thread_data()->dr1 = context->Dr1;
...@@ -1540,6 +1546,8 @@ static void restore_context( const struct xcontext *xcontext, ucontext_t *sigcon ...@@ -1540,6 +1546,8 @@ static void restore_context( const struct xcontext *xcontext, ucontext_t *sigcon
amd64_thread_data()->dr7 = context->Dr7; amd64_thread_data()->dr7 = context->Dr7;
set_sigcontext( context, sigcontext ); set_sigcontext( context, sigcontext );
if (FPU_sig(sigcontext)) *FPU_sig(sigcontext) = context->u.FltSave; if (FPU_sig(sigcontext)) *FPU_sig(sigcontext) = context->u.FltSave;
if ((xs = XState_sig(FPU_sig(sigcontext))))
xs->CompactionMask = xcontext->host_compaction_mask;
} }
...@@ -1628,6 +1636,7 @@ static unsigned int get_server_context_flags( DWORD flags ) ...@@ -1628,6 +1636,7 @@ static unsigned int get_server_context_flags( DWORD flags )
if (flags & CONTEXT_SEGMENTS) ret |= SERVER_CTX_SEGMENTS; if (flags & CONTEXT_SEGMENTS) ret |= SERVER_CTX_SEGMENTS;
if (flags & CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT; if (flags & CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT;
if (flags & CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS; if (flags & CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS;
if (flags & CONTEXT_XSTATE) ret |= SERVER_CTX_YMM_REGISTERS;
return ret; return ret;
} }
...@@ -1695,6 +1704,7 @@ NTSTATUS context_to_server( context_t *to, const CONTEXT *from ) ...@@ -1695,6 +1704,7 @@ NTSTATUS context_to_server( context_t *to, const CONTEXT *from )
to->debug.x86_64_regs.dr6 = from->Dr6; to->debug.x86_64_regs.dr6 = from->Dr6;
to->debug.x86_64_regs.dr7 = from->Dr7; to->debug.x86_64_regs.dr7 = from->Dr7;
} }
xstate_to_server( to, xstate_from_context( from ) );
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
...@@ -1708,7 +1718,7 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from ) ...@@ -1708,7 +1718,7 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
{ {
if (from->cpu != CPU_x86_64) return STATUS_INVALID_PARAMETER; if (from->cpu != CPU_x86_64) return STATUS_INVALID_PARAMETER;
to->ContextFlags = CONTEXT_AMD64; to->ContextFlags = CONTEXT_AMD64 | (to->ContextFlags & 0x40);
if (from->flags & SERVER_CTX_CONTROL) if (from->flags & SERVER_CTX_CONTROL)
{ {
to->ContextFlags |= CONTEXT_CONTROL; to->ContextFlags |= CONTEXT_CONTROL;
...@@ -1762,6 +1772,7 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from ) ...@@ -1762,6 +1772,7 @@ NTSTATUS context_from_server( CONTEXT *to, const context_t *from )
to->Dr6 = from->debug.x86_64_regs.dr6; to->Dr6 = from->debug.x86_64_regs.dr6;
to->Dr7 = from->debug.x86_64_regs.dr7; to->Dr7 = from->debug.x86_64_regs.dr7;
} }
xstate_from_server( xstate_from_context( to ), from );
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
...@@ -1831,7 +1842,7 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) ...@@ -1831,7 +1842,7 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
/* Save xstate before any calls which can potentially change volatile ymm registers. /* Save xstate before any calls which can potentially change volatile ymm registers.
* E. g., debug output will clobber ymm registers. */ * E. g., debug output will clobber ymm registers. */
xsave_status = self ? save_xstate( context ) : STATUS_SUCCESS; /* FIXME: other thread. */ xsave_status = self ? save_xstate( context ) : STATUS_SUCCESS;
needed_flags = context->ContextFlags & ~CONTEXT_AMD64; needed_flags = context->ContextFlags & ~CONTEXT_AMD64;
...@@ -1924,6 +1935,7 @@ static void setup_raise_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec ...@@ -1924,6 +1935,7 @@ static void setup_raise_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec
struct stack_layout *stack; struct stack_layout *stack;
size_t stack_size; size_t stack_size;
NTSTATUS status; NTSTATUS status;
XSTATE *src_xs;
if (rec->ExceptionCode == EXCEPTION_SINGLE_STEP) if (rec->ExceptionCode == EXCEPTION_SINGLE_STEP)
{ {
...@@ -1953,7 +1965,7 @@ static void setup_raise_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec ...@@ -1953,7 +1965,7 @@ static void setup_raise_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec
if (rec->ExceptionCode == EXCEPTION_BREAKPOINT) context->Rip--; if (rec->ExceptionCode == EXCEPTION_BREAKPOINT) context->Rip--;
stack_size = sizeof(*stack); stack_size = sizeof(*stack);
if (xcontext->xstate) if ((src_xs = xstate_from_context( context )))
{ {
stack_size += (ULONG_PTR)stack_ptr - (((ULONG_PTR)stack_ptr stack_size += (ULONG_PTR)stack_ptr - (((ULONG_PTR)stack_ptr
- sizeof(XSTATE)) & ~(ULONG_PTR)63); - sizeof(XSTATE)) & ~(ULONG_PTR)63);
...@@ -1962,17 +1974,18 @@ static void setup_raise_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec ...@@ -1962,17 +1974,18 @@ static void setup_raise_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec
stack = virtual_setup_exception( stack_ptr, stack_size, rec ); stack = virtual_setup_exception( stack_ptr, stack_size, rec );
stack->rec = *rec; stack->rec = *rec;
stack->context = *context; stack->context = *context;
if (xcontext->xstate) if (src_xs)
{ {
XSTATE *dst_xs = (XSTATE *)stack->xstate; XSTATE *dst_xs = (XSTATE *)stack->xstate;
assert( !((ULONG_PTR)dst_xs & 63) ); assert( !((ULONG_PTR)dst_xs & 63) );
context_init_xstate( &stack->context, stack->xstate ); context_init_xstate( &stack->context, stack->xstate );
memset( dst_xs, 0, offsetof(XSTATE, YmmContext) );
dst_xs->CompactionMask = user_shared_data->XState.CompactionEnabled ? 0x8000000000000004 : 0; dst_xs->CompactionMask = user_shared_data->XState.CompactionEnabled ? 0x8000000000000004 : 0;
if (xcontext->xstate->Mask & 4) if (src_xs->Mask & 4)
{ {
dst_xs->Mask = 4; dst_xs->Mask = 4;
memcpy( &dst_xs->YmmContext, &xcontext->xstate->YmmContext, sizeof(dst_xs->YmmContext) ); memcpy( &dst_xs->YmmContext, &src_xs->YmmContext, sizeof(dst_xs->YmmContext) );
} }
} }
......
...@@ -344,7 +344,6 @@ NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_c ...@@ -344,7 +344,6 @@ NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_c
DWORD i; DWORD i;
obj_handle_t handle = 0; obj_handle_t handle = 0;
client_ptr_t params[EXCEPTION_MAXIMUM_PARAMETERS]; client_ptr_t params[EXCEPTION_MAXIMUM_PARAMETERS];
CONTEXT exception_context = *context;
select_op_t select_op; select_op_t select_op;
sigset_t old_set; sigset_t old_set;
...@@ -370,10 +369,22 @@ NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_c ...@@ -370,10 +369,22 @@ NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_c
if (handle) if (handle)
{ {
struct xcontext exception_context;
DECLSPEC_ALIGN(64) XSTATE xs;
XSTATE *src_xs;
select_op.wait.op = SELECT_WAIT; select_op.wait.op = SELECT_WAIT;
select_op.wait.handles[0] = handle; select_op.wait.handles[0] = handle;
exception_context.c = *context;
if ((src_xs = xstate_from_context( context )))
{
context_init_xstate( &exception_context.c, &xs );
memcpy( &xs, src_xs, sizeof(xs) );
}
server_select( &select_op, offsetof( select_op_t, wait.handles[1] ), SELECT_INTERRUPTIBLE, server_select( &select_op, offsetof( select_op_t, wait.handles[1] ), SELECT_INTERRUPTIBLE,
TIMEOUT_INFINITE, &exception_context, NULL, NULL ); TIMEOUT_INFINITE, &exception_context.c, NULL, NULL );
SERVER_START_REQ( get_exception_status ) SERVER_START_REQ( get_exception_status )
{ {
...@@ -381,7 +392,12 @@ NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_c ...@@ -381,7 +392,12 @@ NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_c
ret = wine_server_call( req ); ret = wine_server_call( req );
} }
SERVER_END_REQ; SERVER_END_REQ;
if (ret >= 0) *context = exception_context; if (ret >= 0)
{
*context = exception_context.c;
if (src_xs)
memcpy( src_xs, &xs, sizeof(xs) );
}
} }
pthread_sigmask( SIG_SETMASK, &old_set, NULL ); pthread_sigmask( SIG_SETMASK, &old_set, NULL );
...@@ -632,7 +648,7 @@ static NTSTATUS wow64_context_from_server( WOW64_CONTEXT *to, const context_t *f ...@@ -632,7 +648,7 @@ static NTSTATUS wow64_context_from_server( WOW64_CONTEXT *to, const context_t *f
{ {
if (from->cpu != CPU_x86) return STATUS_INVALID_PARAMETER; if (from->cpu != CPU_x86) return STATUS_INVALID_PARAMETER;
to->ContextFlags = WOW64_CONTEXT_i386; to->ContextFlags = WOW64_CONTEXT_i386 | (to->ContextFlags & 0x40);
if (from->flags & SERVER_CTX_CONTROL) if (from->flags & SERVER_CTX_CONTROL)
{ {
to->ContextFlags |= WOW64_CONTEXT_CONTROL; to->ContextFlags |= WOW64_CONTEXT_CONTROL;
...@@ -689,6 +705,12 @@ static NTSTATUS wow64_context_from_server( WOW64_CONTEXT *to, const context_t *f ...@@ -689,6 +705,12 @@ static NTSTATUS wow64_context_from_server( WOW64_CONTEXT *to, const context_t *f
to->ContextFlags |= WOW64_CONTEXT_EXTENDED_REGISTERS; to->ContextFlags |= WOW64_CONTEXT_EXTENDED_REGISTERS;
memcpy( to->ExtendedRegisters, from->ext.i386_regs, sizeof(to->ExtendedRegisters) ); memcpy( to->ExtendedRegisters, from->ext.i386_regs, sizeof(to->ExtendedRegisters) );
} }
if ((to->ContextFlags & WOW64_CONTEXT_XSTATE) == WOW64_CONTEXT_XSTATE)
{
CONTEXT_EX *c_ex = (CONTEXT_EX *)(to + 1);
xstate_from_server( (XSTATE *)((BYTE *)c_ex + c_ex->XState.Offset), from );
}
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
...@@ -758,6 +780,12 @@ static void wow64_context_to_server( context_t *to, const WOW64_CONTEXT *from ) ...@@ -758,6 +780,12 @@ static void wow64_context_to_server( context_t *to, const WOW64_CONTEXT *from )
to->flags |= SERVER_CTX_EXTENDED_REGISTERS; to->flags |= SERVER_CTX_EXTENDED_REGISTERS;
memcpy( to->ext.i386_regs, from->ExtendedRegisters, sizeof(to->ext.i386_regs) ); memcpy( to->ext.i386_regs, from->ExtendedRegisters, sizeof(to->ext.i386_regs) );
} }
if (flags & WOW64_CONTEXT_XSTATE)
{
CONTEXT_EX *c_ex = (CONTEXT_EX *)(from + 1);
xstate_to_server( to, (XSTATE *)((BYTE *)c_ex + c_ex->XState.Offset) );
}
} }
#endif /* __x86_64__ */ #endif /* __x86_64__ */
......
...@@ -288,13 +288,14 @@ static inline void mutex_unlock( pthread_mutex_t *mutex ) ...@@ -288,13 +288,14 @@ static inline void mutex_unlock( pthread_mutex_t *mutex )
static inline TEB64 *NtCurrentTeb64(void) { return (TEB64 *)NtCurrentTeb()->GdiBatchCount; } static inline TEB64 *NtCurrentTeb64(void) { return (TEB64 *)NtCurrentTeb()->GdiBatchCount; }
#endif #endif
#if defined(__i386__) || defined(__x86_64__)
struct xcontext struct xcontext
{ {
CONTEXT c; CONTEXT c;
XSTATE *xstate; /* points to xstate in sigcontext */ CONTEXT_EX c_ex;
ULONG64 host_compaction_mask;
}; };
#if defined(__i386__) || defined(__x86_64__)
static inline XSTATE *xstate_from_context( const CONTEXT *context ) static inline XSTATE *xstate_from_context( const CONTEXT *context )
{ {
CONTEXT_EX *xctx = (CONTEXT_EX *)(context + 1); CONTEXT_EX *xctx = (CONTEXT_EX *)(context + 1);
...@@ -308,21 +309,62 @@ static inline XSTATE *xstate_from_context( const CONTEXT *context ) ...@@ -308,21 +309,62 @@ static inline XSTATE *xstate_from_context( const CONTEXT *context )
static inline void context_init_xstate( CONTEXT *context, void *xstate_buffer ) static inline void context_init_xstate( CONTEXT *context, void *xstate_buffer )
{ {
CONTEXT_EX *xctx; CONTEXT_EX *xctx;
XSTATE *xs;
xctx = (CONTEXT_EX *)(context + 1); xctx = (CONTEXT_EX *)(context + 1);
xctx->Legacy.Length = sizeof(CONTEXT); xctx->Legacy.Length = sizeof(CONTEXT);
xctx->Legacy.Offset = -(LONG)sizeof(CONTEXT); xctx->Legacy.Offset = -(LONG)sizeof(CONTEXT);
xctx->XState.Length = sizeof(XSTATE); xctx->XState.Length = sizeof(XSTATE);
xctx->XState.Offset = xstate_buffer ? (((ULONG_PTR)xstate_buffer + 63) & ~63) - (ULONG_PTR)xctx xctx->XState.Offset = (BYTE *)xstate_buffer - (BYTE *)xctx;
: (((ULONG_PTR)context + sizeof(CONTEXT) + sizeof(CONTEXT_EX) + 63) & ~63) - (ULONG_PTR)xctx;
xctx->All.Length = sizeof(CONTEXT) + xctx->XState.Offset + xctx->XState.Length; xctx->All.Length = sizeof(CONTEXT) + xctx->XState.Offset + xctx->XState.Length;
xctx->All.Offset = -(LONG)sizeof(CONTEXT); xctx->All.Offset = -(LONG)sizeof(CONTEXT);
context->ContextFlags |= 0x40; context->ContextFlags |= 0x40;
}
xs = xstate_from_context(context); static inline void xstate_to_server( context_t *to, const XSTATE *xs )
memset( xs, 0, offsetof(XSTATE, YmmContext) ); {
if (!xs)
return;
to->flags |= SERVER_CTX_YMM_REGISTERS;
if (xs->Mask & 4)
memcpy(&to->ymm.ymm_high_regs.ymm_high, &xs->YmmContext, sizeof(xs->YmmContext));
else
memset(&to->ymm.ymm_high_regs.ymm_high, 0, sizeof(xs->YmmContext));
}
static inline void xstate_from_server_( XSTATE *xs, const context_t *from, BOOL compaction_enabled)
{
if (!xs)
return;
xs->Mask = 0;
xs->CompactionMask = compaction_enabled ? 0x8000000000000004 : 0;
if (from->flags & SERVER_CTX_YMM_REGISTERS)
{
unsigned long *src = (unsigned long *)&from->ymm.ymm_high_regs.ymm_high;
unsigned int i;
for (i = 0; i < sizeof(xs->YmmContext) / sizeof(unsigned long); ++i)
if (src[i])
{
memcpy( &xs->YmmContext, &from->ymm.ymm_high_regs.ymm_high, sizeof(xs->YmmContext) );
xs->Mask = 4;
break;
}
}
}
#define xstate_from_server( xs, from ) xstate_from_server_( xs, from, user_shared_data->XState.CompactionEnabled )
#else
static inline XSTATE *xstate_from_context( const CONTEXT *context )
{
return NULL;
}
static inline void context_init_xstate( CONTEXT *context, void *xstate_buffer )
{
} }
#endif #endif
......
...@@ -170,6 +170,10 @@ typedef struct ...@@ -170,6 +170,10 @@ typedef struct
{ {
unsigned char i386_regs[512]; unsigned char i386_regs[512];
} ext; } ext;
union
{
struct { struct { unsigned __int64 low, high; } ymm_high[16]; } ymm_high_regs;
} ymm;
} context_t; } context_t;
#define SERVER_CTX_CONTROL 0x01 #define SERVER_CTX_CONTROL 0x01
...@@ -178,6 +182,7 @@ typedef struct ...@@ -178,6 +182,7 @@ typedef struct
#define SERVER_CTX_FLOATING_POINT 0x08 #define SERVER_CTX_FLOATING_POINT 0x08
#define SERVER_CTX_DEBUG_REGISTERS 0x10 #define SERVER_CTX_DEBUG_REGISTERS 0x10
#define SERVER_CTX_EXTENDED_REGISTERS 0x20 #define SERVER_CTX_EXTENDED_REGISTERS 0x20
#define SERVER_CTX_YMM_REGISTERS 0x40
struct send_fd struct send_fd
......
...@@ -186,6 +186,10 @@ typedef struct ...@@ -186,6 +186,10 @@ typedef struct
{ {
unsigned char i386_regs[512]; unsigned char i386_regs[512];
} ext; /* selected by SERVER_CTX_EXTENDED_REGISTERS */ } ext; /* selected by SERVER_CTX_EXTENDED_REGISTERS */
union
{
struct { struct { unsigned __int64 low, high; } ymm_high[16]; } ymm_high_regs;
} ymm; /* selected by SERVER_CTX_YMM_REGISTERS */
} context_t; } context_t;
#define SERVER_CTX_CONTROL 0x01 #define SERVER_CTX_CONTROL 0x01
...@@ -194,6 +198,7 @@ typedef struct ...@@ -194,6 +198,7 @@ typedef struct
#define SERVER_CTX_FLOATING_POINT 0x08 #define SERVER_CTX_FLOATING_POINT 0x08
#define SERVER_CTX_DEBUG_REGISTERS 0x10 #define SERVER_CTX_DEBUG_REGISTERS 0x10
#define SERVER_CTX_EXTENDED_REGISTERS 0x20 #define SERVER_CTX_EXTENDED_REGISTERS 0x20
#define SERVER_CTX_YMM_REGISTERS 0x40
/* structure used in sending an fd from client to server */ /* structure used in sending an fd from client to server */
struct send_fd struct send_fd
......
...@@ -1285,6 +1285,7 @@ static void copy_context( context_t *to, const context_t *from, unsigned int fla ...@@ -1285,6 +1285,7 @@ static void copy_context( context_t *to, const context_t *from, unsigned int fla
if (flags & SERVER_CTX_FLOATING_POINT) to->fp = from->fp; if (flags & SERVER_CTX_FLOATING_POINT) to->fp = from->fp;
if (flags & SERVER_CTX_DEBUG_REGISTERS) to->debug = from->debug; if (flags & SERVER_CTX_DEBUG_REGISTERS) to->debug = from->debug;
if (flags & SERVER_CTX_EXTENDED_REGISTERS) to->ext = from->ext; if (flags & SERVER_CTX_EXTENDED_REGISTERS) to->ext = from->ext;
if (flags & SERVER_CTX_YMM_REGISTERS) to->ymm = from->ymm;
} }
/* return the context flags that correspond to system regs */ /* return the context flags that correspond to system regs */
......
...@@ -620,6 +620,9 @@ static void dump_varargs_context( const char *prefix, data_size_t size ) ...@@ -620,6 +620,9 @@ static void dump_varargs_context( const char *prefix, data_size_t size )
if (ctx.flags & SERVER_CTX_EXTENDED_REGISTERS) if (ctx.flags & SERVER_CTX_EXTENDED_REGISTERS)
dump_uints( ",extended=", (const unsigned int *)ctx.ext.i386_regs, dump_uints( ",extended=", (const unsigned int *)ctx.ext.i386_regs,
sizeof(ctx.ext.i386_regs) / sizeof(int) ); sizeof(ctx.ext.i386_regs) / sizeof(int) );
if (ctx.flags & SERVER_CTX_YMM_REGISTERS)
dump_uints( ",ymm_high=", (const unsigned int *)ctx.ymm.ymm_high_regs.ymm_high,
sizeof(ctx.ymm.ymm_high_regs) / sizeof(int) );
break; break;
case CPU_x86_64: case CPU_x86_64:
if (ctx.flags & SERVER_CTX_CONTROL) if (ctx.flags & SERVER_CTX_CONTROL)
...@@ -669,6 +672,9 @@ static void dump_varargs_context( const char *prefix, data_size_t size ) ...@@ -669,6 +672,9 @@ static void dump_varargs_context( const char *prefix, data_size_t size )
(unsigned int)(ctx.fp.x86_64_regs.fpregs[i].low >> 32), (unsigned int)(ctx.fp.x86_64_regs.fpregs[i].low >> 32),
(unsigned int)ctx.fp.x86_64_regs.fpregs[i].low ); (unsigned int)ctx.fp.x86_64_regs.fpregs[i].low );
} }
if (ctx.flags & SERVER_CTX_YMM_REGISTERS)
dump_uints( ",ymm_high=", (const unsigned int *)ctx.ymm.ymm_high_regs.ymm_high,
sizeof(ctx.ymm.ymm_high_regs) / sizeof(int) );
break; break;
case CPU_POWERPC: case CPU_POWERPC:
if (ctx.flags & SERVER_CTX_CONTROL) if (ctx.flags & SERVER_CTX_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