mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-14 20:53:35 +00:00
ntdll: Support AVX registers for other thread in Nt{Get|Set}ContextThread().
Signed-off-by: Paul Gofman <pgofman@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
ec1ea1ea1b
commit
419abd49a1
|
@ -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
|
||||||
}
|
}
|
||||||
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
|
|
||||||
{
|
{
|
||||||
xcontext->xstate = NULL;
|
context_init_xstate( context, xs );
|
||||||
|
xcontext->host_compaction_mask = xs->CompactionMask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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
|
||||||
{
|
{
|
||||||
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 )
|
||||||
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 )
|
||||||
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 )
|
||||||
{
|
{
|
||||||
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 )
|
||||||
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 )
|
||||||
|
|
||||||
/* 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 )
|
||||||
}
|
}
|
||||||
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,
|
||||||
{
|
{
|
||||||
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))
|
||||||
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))
|
||||||
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
|
||||||
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->xstate = NULL;
|
/* xcontext and sigcontext are both on the signal stack, so we can
|
||||||
|
* just reference sigcontext without overflowing 32 bit XState.Offset */
|
||||||
|
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 )
|
||||||
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
|
||||||
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 )
|
||||||
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 )
|
||||||
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 )
|
||||||
{
|
{
|
||||||
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 )
|
||||||
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 )
|
||||||
|
|
||||||
/* 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
|
||||||
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
|
||||||
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
|
||||||
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
|
||||||
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
|
||||||
|
|
||||||
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
|
||||||
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
|
||||||
{
|
{
|
||||||
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
|
||||||
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 )
|
||||||
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 )
|
||||||
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 )
|
||||||
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
|
||||||
{
|
{
|
||||||
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
|
||||||
#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
|
||||||
{
|
{
|
||||||
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
|
||||||
#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
|
||||||
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 )
|
||||||
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 )
|
||||||
(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)
|
||||||
|
|
Loading…
Reference in a new issue