ntdll: Don't hardcode xstate size in syscall frame.
This commit is contained in:
parent
1e0728c5d4
commit
7ae488a2bb
5 changed files with 123 additions and 66 deletions
|
@ -508,10 +508,10 @@ struct syscall_frame
|
|||
/* Leave space for the whole set of YMM registers. They're not used in
|
||||
* 32-bit mode, but some processors fault if they're not in writable memory.
|
||||
*/
|
||||
DECLSPEC_ALIGN(64) XSTATE xstate; /* 240 */
|
||||
DECLSPEC_ALIGN(64) XSAVE_AREA_HEADER xstate; /* 240 */
|
||||
};
|
||||
|
||||
C_ASSERT( sizeof(struct syscall_frame) == 0x380 );
|
||||
C_ASSERT( sizeof(struct syscall_frame) == 0x280 );
|
||||
|
||||
struct x86_thread_data
|
||||
{
|
||||
|
@ -526,12 +526,14 @@ struct x86_thread_data
|
|||
SYSTEM_SERVICE_TABLE *syscall_table; /* 1f4 syscall table */
|
||||
struct syscall_frame *syscall_frame; /* 1f8 frame pointer on syscall entry */
|
||||
UINT64 xstate_features_mask; /* 1fc */
|
||||
UINT xstate_features_size; /* 204 */
|
||||
};
|
||||
|
||||
C_ASSERT( sizeof(struct x86_thread_data) <= sizeof(((struct ntdll_thread_data *)0)->cpu_data) );
|
||||
C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct x86_thread_data, gs ) == 0x1d8 );
|
||||
C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct x86_thread_data, syscall_table ) == 0x1f4 );
|
||||
C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct x86_thread_data, syscall_frame ) == 0x1f8 );
|
||||
C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct x86_thread_data, xstate_features_size ) == 0x204 );
|
||||
|
||||
/* flags to control the behavior of the syscall dispatcher */
|
||||
#define SYSCALL_HAVE_XSAVE 1
|
||||
|
@ -938,12 +940,13 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
|
|||
if ((flags & CONTEXT_XSTATE) && xstate_extended_features())
|
||||
{
|
||||
CONTEXT_EX *context_ex = (CONTEXT_EX *)(context + 1);
|
||||
XSTATE *xs = (XSTATE *)((char *)context_ex + context_ex->XState.Offset);
|
||||
XSAVE_AREA_HEADER *xs = (XSAVE_AREA_HEADER *)((char *)context_ex + context_ex->XState.Offset);
|
||||
|
||||
if (context_ex->XState.Length < offsetof(XSTATE, YmmContext) ||
|
||||
context_ex->XState.Length > sizeof(XSTATE))
|
||||
if (context_ex->XState.Length < sizeof(XSAVE_AREA_HEADER) ||
|
||||
context_ex->XState.Length > sizeof(XSAVE_AREA_HEADER) + xstate_features_size)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
if ((xs->Mask & xstate_extended_features()) && (context_ex->XState.Length < sizeof(XSTATE)))
|
||||
if ((xs->Mask & xstate_extended_features())
|
||||
&& (context_ex->XState.Length < xstate_get_size( xs->CompactionMask, xs->Mask )))
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
else flags &= ~CONTEXT_XSTATE;
|
||||
|
@ -1019,14 +1022,9 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
|
|||
if (flags & CONTEXT_XSTATE)
|
||||
{
|
||||
CONTEXT_EX *context_ex = (CONTEXT_EX *)(context + 1);
|
||||
XSTATE *xs = (XSTATE *)((char *)context_ex + context_ex->XState.Offset);
|
||||
XSAVE_AREA_HEADER *xs = (XSAVE_AREA_HEADER *)((char *)context_ex + context_ex->XState.Offset);
|
||||
|
||||
if (xs->Mask & XSTATE_MASK_GSSE)
|
||||
{
|
||||
frame->xstate.Mask |= XSTATE_MASK_GSSE;
|
||||
frame->xstate.YmmContext = xs->YmmContext;
|
||||
}
|
||||
else frame->xstate.Mask &= ~XSTATE_MASK_GSSE;
|
||||
copy_xstate( &frame->xstate, xs, xs->Mask );
|
||||
}
|
||||
|
||||
frame->restore_flags |= flags & ~CONTEXT_INTEGER;
|
||||
|
@ -1140,21 +1138,22 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
|
|||
if ((needed_flags & CONTEXT_XSTATE) && xstate_extended_features())
|
||||
{
|
||||
CONTEXT_EX *context_ex = (CONTEXT_EX *)(context + 1);
|
||||
XSTATE *xstate = (XSTATE *)((char *)context_ex + context_ex->XState.Offset);
|
||||
unsigned int mask;
|
||||
XSAVE_AREA_HEADER *xstate = (XSAVE_AREA_HEADER *)((char *)context_ex + context_ex->XState.Offset);
|
||||
UINT64 mask;
|
||||
|
||||
if (context_ex->XState.Length < offsetof(XSTATE, YmmContext)
|
||||
|| context_ex->XState.Length > sizeof(XSTATE))
|
||||
if (context_ex->XState.Length < sizeof(XSAVE_AREA_HEADER) ||
|
||||
context_ex->XState.Length > sizeof(XSAVE_AREA_HEADER) + xstate_features_size)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
mask = (xstate_compaction_enabled ? xstate->CompactionMask : xstate->Mask) & xstate_extended_features();
|
||||
xstate->Mask = frame->xstate.Mask & mask;
|
||||
xstate->CompactionMask = xstate_compaction_enabled ? (0x8000000000000000 | mask) : 0;
|
||||
memset( xstate->Reserved, 0, sizeof(xstate->Reserved) );
|
||||
memset( xstate->Reserved2, 0, sizeof(xstate->Reserved2) );
|
||||
if (xstate->Mask)
|
||||
{
|
||||
if (context_ex->XState.Length < sizeof(XSTATE)) return STATUS_BUFFER_OVERFLOW;
|
||||
xstate->YmmContext = frame->xstate.YmmContext;
|
||||
if (context_ex->XState.Length < xstate_get_size( xstate->CompactionMask, xstate->Mask ))
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
copy_xstate( xstate, &frame->xstate, xstate->Mask );
|
||||
}
|
||||
}
|
||||
/* update the cached version of the debug registers */
|
||||
|
@ -1483,7 +1482,7 @@ static void setup_raise_exception( ucontext_t *sigcontext, void *stack_ptr,
|
|||
XSTATE *dst_xs = (XSTATE *)(((ULONG_PTR)stack->xstate + 63) & ~63);
|
||||
|
||||
context_init_xstate( &stack->context, dst_xs );
|
||||
memset( dst_xs, 0, offsetof(XSTATE, YmmContext) );
|
||||
memset( dst_xs, 0, sizeof(XSAVE_AREA_HEADER) );
|
||||
dst_xs->CompactionMask = xstate_compaction_enabled ? 0x8000000000000000 | xstate_extended_features() : 0;
|
||||
if (src_xs->Mask & 4)
|
||||
{
|
||||
|
@ -1623,7 +1622,8 @@ __ASM_GLOBAL_FUNC( call_user_mode_callback,
|
|||
__ASM_CFI(".cfi_rel_offset %edi,-12\n\t")
|
||||
"movl 0x18(%ebp),%edx\n\t" /* teb */
|
||||
"pushl 0(%edx)\n\t" /* teb->Tib.ExceptionList */
|
||||
"subl $0x380,%esp\n\t" /* sizeof(struct syscall_frame) */
|
||||
"subl $0x280,%esp\n\t" /* sizeof(struct syscall_frame) */
|
||||
"subl %fs:0x204,%esp\n\t" /* x86_thread_data()->xstate_features_size */
|
||||
"andl $~63,%esp\n\t"
|
||||
"leal 8(%ebp),%eax\n\t"
|
||||
"movl %eax,0x38(%esp)\n\t" /* frame->syscall_cfa */
|
||||
|
@ -2403,6 +2403,7 @@ NTSTATUS signal_alloc_thread( TEB *teb )
|
|||
else thread_data->fs = gdt_fs_sel;
|
||||
|
||||
teb->WOW32Reserved = __wine_syscall_dispatcher;
|
||||
thread_data->xstate_features_size = xstate_features_size;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -2431,7 +2432,9 @@ void signal_init_process(void)
|
|||
struct sigaction sig_act;
|
||||
void *kernel_stack = (char *)ntdll_get_thread_data()->kernel_stack + kernel_stack_size;
|
||||
|
||||
x86_thread_data()->syscall_frame = (struct syscall_frame *)kernel_stack - 1;
|
||||
x86_thread_data()->syscall_frame = (struct syscall_frame *)((ULONG_PTR)((char *)kernel_stack
|
||||
- sizeof(struct syscall_frame) - xstate_features_size) & ~(ULONG_PTR)63);
|
||||
x86_thread_data()->xstate_features_size = xstate_features_size;
|
||||
|
||||
if (cpu_info.ProcessorFeatureBits & CPU_FEATURE_FXSR) syscall_flags |= SYSCALL_HAVE_FXSAVE;
|
||||
if (cpu_info.ProcessorFeatureBits & CPU_FEATURE_XSAVE) syscall_flags |= SYSCALL_HAVE_XSAVE;
|
||||
|
@ -2481,6 +2484,7 @@ void call_init_thunk( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend, TEB
|
|||
thread_data->gs = get_gs();
|
||||
thread_data->syscall_table = KeServiceDescriptorTable;
|
||||
thread_data->xstate_features_mask = xstate_supported_features_mask;
|
||||
assert( thread_data->xstate_features_size == xstate_features_size );
|
||||
|
||||
context.SegCs = get_cs();
|
||||
context.SegDs = get_ds();
|
||||
|
@ -2547,7 +2551,8 @@ __ASM_GLOBAL_FUNC( signal_start_thread,
|
|||
"movl 0x1f8(%ecx),%eax\n\t" /* x86_thread_data()->syscall_frame */
|
||||
"orl %eax,%eax\n\t"
|
||||
"jnz 1f\n\t"
|
||||
"leal -0x380(%esp),%eax\n\t" /* sizeof(struct syscall_frame) */
|
||||
"leal -0x280(%esp),%eax\n\t" /* sizeof(struct syscall_frame) */
|
||||
"subl %fs:0x204,%eax\n\t" /* x86_thread_data()->xstate_features_size */
|
||||
"andl $~63,%eax\n\t"
|
||||
"movl %eax,0x1f8(%ecx)\n" /* x86_thread_data()->syscall_frame */
|
||||
/* switch to kernel stack */
|
||||
|
|
|
@ -424,10 +424,12 @@ struct syscall_frame
|
|||
DWORD restore_flags; /* 00b4 */
|
||||
DWORD align[2]; /* 00b8 */
|
||||
XMM_SAVE_AREA32 xsave; /* 00c0 */
|
||||
DECLSPEC_ALIGN(64) XSTATE xstate; /* 02c0 */
|
||||
DECLSPEC_ALIGN(64) XSAVE_AREA_HEADER xstate; /* 02c0 */
|
||||
};
|
||||
|
||||
C_ASSERT( sizeof( struct syscall_frame ) == 0x400);
|
||||
C_ASSERT( offsetof( struct syscall_frame, xsave ) == 0xc0 );
|
||||
C_ASSERT( offsetof( struct syscall_frame, xstate ) == 0x2c0 );
|
||||
C_ASSERT( sizeof( struct syscall_frame ) == 0x300);
|
||||
|
||||
struct amd64_thread_data
|
||||
{
|
||||
|
@ -441,7 +443,7 @@ struct amd64_thread_data
|
|||
struct syscall_frame *syscall_frame; /* 0328 syscall frame pointer */
|
||||
SYSTEM_SERVICE_TABLE *syscall_table; /* 0330 syscall table */
|
||||
DWORD fs; /* 0338 WOW TEB selector */
|
||||
DWORD align;
|
||||
DWORD xstate_features_size; /* 033c */
|
||||
UINT64 xstate_features_mask; /* 0340 */
|
||||
};
|
||||
|
||||
|
@ -450,6 +452,7 @@ C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct amd64_thread_data, pth
|
|||
C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct amd64_thread_data, syscall_frame ) == 0x328 );
|
||||
C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct amd64_thread_data, syscall_table ) == 0x330 );
|
||||
C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct amd64_thread_data, fs ) == 0x338 );
|
||||
C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct amd64_thread_data, xstate_features_size ) == 0x33c );
|
||||
C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct amd64_thread_data, xstate_features_mask ) == 0x340 );
|
||||
|
||||
static inline struct amd64_thread_data *amd64_thread_data(void)
|
||||
|
@ -981,12 +984,13 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
|
|||
if ((flags & CONTEXT_XSTATE) && xstate_extended_features())
|
||||
{
|
||||
CONTEXT_EX *context_ex = (CONTEXT_EX *)(context + 1);
|
||||
XSTATE *xs = (XSTATE *)((char *)context_ex + context_ex->XState.Offset);
|
||||
XSAVE_AREA_HEADER *xs = (XSAVE_AREA_HEADER *)((char *)context_ex + context_ex->XState.Offset);
|
||||
|
||||
if (context_ex->XState.Length < offsetof(XSTATE, YmmContext) ||
|
||||
context_ex->XState.Length > sizeof(XSTATE))
|
||||
if (context_ex->XState.Length < sizeof(XSAVE_AREA_HEADER) ||
|
||||
context_ex->XState.Length > sizeof(XSAVE_AREA_HEADER) + xstate_features_size)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
if ((xs->Mask & xstate_extended_features()) && (context_ex->XState.Length < sizeof(XSTATE)))
|
||||
if ((xs->Mask & xstate_extended_features())
|
||||
&& (context_ex->XState.Length < xstate_get_size( xs->CompactionMask, xs->Mask )))
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
else flags &= ~CONTEXT_XSTATE;
|
||||
|
@ -1051,14 +1055,9 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
|
|||
if (flags & CONTEXT_XSTATE)
|
||||
{
|
||||
CONTEXT_EX *context_ex = (CONTEXT_EX *)(context + 1);
|
||||
XSTATE *xs = (XSTATE *)((char *)context_ex + context_ex->XState.Offset);
|
||||
XSAVE_AREA_HEADER *xs = (XSAVE_AREA_HEADER *)((char *)context_ex + context_ex->XState.Offset);
|
||||
|
||||
if (xs->Mask & XSTATE_MASK_GSSE)
|
||||
{
|
||||
frame->xstate.Mask |= XSTATE_MASK_GSSE;
|
||||
memcpy( &frame->xstate.YmmContext, &xs->YmmContext, sizeof(xs->YmmContext) );
|
||||
}
|
||||
else frame->xstate.Mask &= ~XSTATE_MASK_GSSE;
|
||||
copy_xstate( &frame->xstate, xs, xs->Mask );
|
||||
}
|
||||
|
||||
frame->restore_flags |= flags & ~CONTEXT_INTEGER;
|
||||
|
@ -1159,21 +1158,22 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
|
|||
if ((needed_flags & CONTEXT_XSTATE) && xstate_extended_features())
|
||||
{
|
||||
CONTEXT_EX *context_ex = (CONTEXT_EX *)(context + 1);
|
||||
XSTATE *xstate = (XSTATE *)((char *)context_ex + context_ex->XState.Offset);
|
||||
unsigned int mask;
|
||||
XSAVE_AREA_HEADER *xstate = (XSAVE_AREA_HEADER *)((char *)context_ex + context_ex->XState.Offset);
|
||||
UINT64 mask;
|
||||
|
||||
if (context_ex->XState.Length < offsetof(XSTATE, YmmContext)
|
||||
|| context_ex->XState.Length > sizeof(XSTATE))
|
||||
if (context_ex->XState.Length < sizeof(XSAVE_AREA_HEADER) ||
|
||||
context_ex->XState.Length > sizeof(XSAVE_AREA_HEADER) + xstate_features_size)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
mask = (xstate_compaction_enabled ? xstate->CompactionMask : xstate->Mask) & xstate_extended_features();
|
||||
xstate->Mask = frame->xstate.Mask & mask;
|
||||
xstate->CompactionMask = xstate_compaction_enabled ? (0x8000000000000000 | mask) : 0;
|
||||
memset( xstate->Reserved, 0, sizeof(xstate->Reserved) );
|
||||
memset( xstate->Reserved2, 0, sizeof(xstate->Reserved2) );
|
||||
if (xstate->Mask)
|
||||
{
|
||||
if (context_ex->XState.Length < sizeof(XSTATE)) return STATUS_BUFFER_OVERFLOW;
|
||||
memcpy( &xstate->YmmContext, &frame->xstate.YmmContext, sizeof(xstate->YmmContext) );
|
||||
if (context_ex->XState.Length < xstate_get_size( xstate->CompactionMask, xstate->Mask ))
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
copy_xstate( xstate, &frame->xstate, xstate->Mask );
|
||||
}
|
||||
}
|
||||
/* update the cached version of the debug registers */
|
||||
|
@ -1280,14 +1280,9 @@ NTSTATUS set_thread_wow64_context( HANDLE handle, const void *ctx, ULONG size )
|
|||
if (flags & CONTEXT_I386_XSTATE)
|
||||
{
|
||||
CONTEXT_EX *context_ex = (CONTEXT_EX *)(context + 1);
|
||||
XSTATE *xs = (XSTATE *)((char *)context_ex + context_ex->XState.Offset);
|
||||
XSAVE_AREA_HEADER *xs = (XSAVE_AREA_HEADER *)((char *)context_ex + context_ex->XState.Offset);
|
||||
|
||||
if (xs->Mask & XSTATE_MASK_GSSE)
|
||||
{
|
||||
frame->xstate.Mask |= XSTATE_MASK_GSSE;
|
||||
memcpy( &frame->xstate.YmmContext, &xs->YmmContext, sizeof(xs->YmmContext) );
|
||||
}
|
||||
else frame->xstate.Mask &= ~XSTATE_MASK_GSSE;
|
||||
copy_xstate( &frame->xstate, xs, xs->Mask );
|
||||
frame->restore_flags |= CONTEXT_XSTATE;
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
|
@ -1368,24 +1363,25 @@ NTSTATUS get_thread_wow64_context( HANDLE handle, void *ctx, ULONG size )
|
|||
fpux_to_fpu( &context->FloatSave, &frame->xsave );
|
||||
context->ContextFlags |= CONTEXT_I386_FLOATING_POINT;
|
||||
}
|
||||
if ((needed_flags & CONTEXT_I386_XSTATE) && (cpu_info.ProcessorFeatureBits & CPU_FEATURE_AVX))
|
||||
if ((needed_flags & CONTEXT_I386_XSTATE) && xstate_extended_features())
|
||||
{
|
||||
CONTEXT_EX *context_ex = (CONTEXT_EX *)(context + 1);
|
||||
XSTATE *xstate = (XSTATE *)((char *)context_ex + context_ex->XState.Offset);
|
||||
unsigned int mask;
|
||||
XSAVE_AREA_HEADER *xstate = (XSAVE_AREA_HEADER *)((char *)context_ex + context_ex->XState.Offset);
|
||||
UINT64 mask;
|
||||
|
||||
if (context_ex->XState.Length < offsetof(XSTATE, YmmContext) ||
|
||||
context_ex->XState.Length > sizeof(XSTATE))
|
||||
if (context_ex->XState.Length < sizeof(XSAVE_AREA_HEADER) ||
|
||||
context_ex->XState.Length > sizeof(XSAVE_AREA_HEADER) + xstate_features_size)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
mask = (xstate_compaction_enabled ? xstate->CompactionMask : xstate->Mask) & xstate_extended_features();
|
||||
xstate->Mask = frame->xstate.Mask & mask;
|
||||
xstate->CompactionMask = xstate_compaction_enabled ? (0x8000000000000000 | mask) : 0;
|
||||
memset( xstate->Reserved, 0, sizeof(xstate->Reserved) );
|
||||
memset( xstate->Reserved2, 0, sizeof(xstate->Reserved2) );
|
||||
if (xstate->Mask)
|
||||
{
|
||||
if (context_ex->XState.Length < sizeof(XSTATE)) return STATUS_BUFFER_OVERFLOW;
|
||||
memcpy( &xstate->YmmContext, &frame->xstate.YmmContext, sizeof(xstate->YmmContext) );
|
||||
if (context_ex->XState.Length < xstate_get_size( xstate->CompactionMask, xstate->Mask ))
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
copy_xstate( xstate, &frame->xstate, xstate->Mask );
|
||||
}
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
|
@ -1544,7 +1540,7 @@ NTSTATUS call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context
|
|||
{
|
||||
assert( !((ULONG_PTR)&stack->xstate & 63) );
|
||||
context_init_xstate( &stack->context, &stack->xstate );
|
||||
memcpy( &stack->xstate, &frame->xstate, sizeof(frame->xstate) );
|
||||
memcpy( &stack->xstate, &frame->xstate, sizeof(XSAVE_AREA_HEADER) + xstate_features_size );
|
||||
}
|
||||
else context_init_xstate( &stack->context, NULL );
|
||||
|
||||
|
@ -1586,13 +1582,20 @@ __ASM_GLOBAL_FUNC( call_user_mode_callback,
|
|||
"fnstcw -0x2c(%rbp)\n\t"
|
||||
"movq %rsi,-0x38(%rbp)\n\t" /* ret_ptr */
|
||||
"movq %rdx,-0x40(%rbp)\n\t" /* ret_len */
|
||||
"subq $0x408,%rsp\n\t" /* sizeof(struct syscall_frame) + exception */
|
||||
"subq $0x308,%rsp\n\t" /* sizeof(struct syscall_frame) + exception */
|
||||
#ifdef __APPLE__
|
||||
"movq %gs:0x30,%rsi\n\t"
|
||||
"movl 0x33c(%rsi),%esi\n\t"
|
||||
#else
|
||||
"movl %gs:0x33c,%esi\n\t" /* amd64_thread_data()->xstate_features_size */
|
||||
#endif
|
||||
"subq %rsi,%rsp\n\t"
|
||||
"andq $~63,%rsp\n\t"
|
||||
"leaq 0x10(%rbp),%rax\n\t"
|
||||
"movq %rax,0xa8(%rsp)\n\t" /* frame->syscall_cfa */
|
||||
"movq 0x328(%r8),%r10\n\t" /* amd64_thread_data()->syscall_frame */
|
||||
"movq (%r8),%rax\n\t" /* NtCurrentTeb()->Tib.ExceptionList */
|
||||
"movq %rax,0x400(%rsp)\n\t"
|
||||
"movq %rax,0x300(%rsp,%rsi)\n\t"
|
||||
"movl 0xb0(%r10),%r14d\n\t" /* prev_frame->syscall_flags */
|
||||
"movl %r14d,0xb0(%rsp)\n\t" /* frame->syscall_flags */
|
||||
"movq %r10,0xa0(%rsp)\n\t" /* frame->prev_frame */
|
||||
|
@ -1625,7 +1628,13 @@ __ASM_GLOBAL_FUNC( user_mode_callback_return,
|
|||
__ASM_CFI(".cfi_rel_offset %r13,-0x18\n\t")
|
||||
__ASM_CFI(".cfi_rel_offset %r14,-0x20\n\t")
|
||||
__ASM_CFI(".cfi_rel_offset %r15,-0x28\n\t")
|
||||
"movq 0x400(%r10),%rax\n\t" /* exception list */
|
||||
#ifdef __APPLE__
|
||||
"movq %gs:0x30,%rax\n\t"
|
||||
"movl 0x33c(%rax),%eax\n\t"
|
||||
#else
|
||||
"movl %gs:0x33c,%eax\n\t" /* amd64_thread_data()->xstate_features_size */
|
||||
#endif
|
||||
"movq 0x300(%r10,%rax),%rax\n\t" /* exception list */
|
||||
"movq %rax,0(%rcx)\n\t" /* teb->Tib.ExceptionList */
|
||||
"movq -0x38(%rbp),%r10\n\t" /* ret_ptr */
|
||||
"movq -0x40(%rbp),%r11\n\t" /* ret_len */
|
||||
|
@ -2303,6 +2312,7 @@ NTSTATUS signal_alloc_thread( TEB *teb )
|
|||
}
|
||||
else thread_data->fs = fs32_sel;
|
||||
}
|
||||
thread_data->xstate_features_size = xstate_features_size;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -2389,7 +2399,9 @@ void signal_init_process(void)
|
|||
WOW_TEB *wow_teb = get_wow_teb( NtCurrentTeb() );
|
||||
void *ptr, *kernel_stack = (char *)ntdll_get_thread_data()->kernel_stack + kernel_stack_size;
|
||||
|
||||
amd64_thread_data()->syscall_frame = (struct syscall_frame *)kernel_stack - 1;
|
||||
amd64_thread_data()->syscall_frame = (struct syscall_frame *)((ULONG_PTR)((char *)kernel_stack
|
||||
- sizeof(struct syscall_frame) - xstate_features_size) & ~(ULONG_PTR)63);
|
||||
amd64_thread_data()->xstate_features_size = xstate_features_size;
|
||||
|
||||
/* sneak in a syscall dispatcher pointer at a fixed address (7ffe1000) */
|
||||
ptr = (char *)user_shared_data + page_size;
|
||||
|
@ -2481,6 +2493,7 @@ void call_init_thunk( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend, TEB
|
|||
|
||||
thread_data->syscall_table = KeServiceDescriptorTable;
|
||||
thread_data->xstate_features_mask = xstate_supported_features_mask;
|
||||
assert( thread_data->xstate_features_size == xstate_features_size );
|
||||
|
||||
#if defined __linux__
|
||||
arch_prctl( ARCH_SET_GS, teb );
|
||||
|
@ -2585,7 +2598,14 @@ __ASM_GLOBAL_FUNC( signal_start_thread,
|
|||
"movq 0x328(%rcx),%r8\n\t" /* amd64_thread_data()->syscall_frame */
|
||||
"orq %r8,%r8\n\t"
|
||||
"jnz 1f\n\t"
|
||||
"leaq -0x400(%rsp),%r8\n\t" /* sizeof(struct syscall_frame) */
|
||||
"leaq -0x300(%rsp),%r8\n\t" /* sizeof(struct syscall_frame) */
|
||||
#ifdef __APPLE__
|
||||
"movq %gs:0x30,%rax\n\t"
|
||||
"movl 0x33c(%rax),%eax\n\t"
|
||||
#else
|
||||
"movl %gs:0x33c,%eax\n\t" /* amd64_thread_data()->xstate_features_size */
|
||||
#endif
|
||||
"subq %rax,%r8\n\t"
|
||||
"andq $~63,%r8\n\t"
|
||||
"movq %r8,0x328(%rcx)\n" /* amd64_thread_data()->syscall_frame */
|
||||
/* switch to kernel stack */
|
||||
|
|
|
@ -248,6 +248,23 @@ static pthread_mutex_t timezone_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|||
|
||||
BOOL xstate_compaction_enabled = FALSE;
|
||||
UINT64 xstate_supported_features_mask;
|
||||
UINT64 xstate_features_size;
|
||||
|
||||
unsigned int xstate_get_size( UINT64 compaction_mask, UINT64 mask )
|
||||
{
|
||||
if (!(mask & ((UINT64)1 << XSTATE_AVX))) return sizeof(XSAVE_AREA_HEADER);
|
||||
return sizeof(XSAVE_AREA_HEADER) + sizeof(YMMCONTEXT);
|
||||
}
|
||||
|
||||
void copy_xstate( XSAVE_AREA_HEADER *dst, XSAVE_AREA_HEADER *src, UINT64 mask )
|
||||
{
|
||||
mask &= xstate_extended_features() & src->Mask;
|
||||
if (src->CompactionMask) mask &= src->CompactionMask;
|
||||
if (dst->CompactionMask) mask &= dst->CompactionMask;
|
||||
dst->Mask = (dst->Mask & ~xstate_extended_features()) | mask;
|
||||
if (mask & ((UINT64)1 << XSTATE_AVX))
|
||||
*(YMMCONTEXT *)(dst + 1) = *(YMMCONTEXT *)(src + 1);
|
||||
}
|
||||
|
||||
#define AUTH 0x68747541 /* "Auth" */
|
||||
#define ENTI 0x69746e65 /* "enti" */
|
||||
|
@ -400,6 +417,10 @@ static void get_cpuinfo( SYSTEM_CPU_INFORMATION *info )
|
|||
xstate_supported_features_mask = 3;
|
||||
if (features & CPU_FEATURE_AVX)
|
||||
xstate_supported_features_mask |= (UINT64)1 << XSTATE_AVX;
|
||||
xstate_features_size = xstate_get_size( xstate_compaction_enabled ? 0x8000000000000000
|
||||
| xstate_supported_features_mask : 0, xstate_supported_features_mask )
|
||||
- sizeof(XSAVE_AREA_HEADER);
|
||||
xstate_features_size = (xstate_features_size + 15) & ~15;
|
||||
}
|
||||
|
||||
if (regs[1] == AUTH && regs[3] == ENTI && regs[2] == CAMD)
|
||||
|
|
|
@ -217,6 +217,9 @@ extern void fpu_to_fpux( XSAVE_FORMAT *fpux, const I386_FLOATING_SAVE_AREA *fpu
|
|||
|
||||
extern BOOL xstate_compaction_enabled;
|
||||
extern UINT64 xstate_supported_features_mask;
|
||||
extern UINT64 xstate_features_size;
|
||||
extern unsigned int xstate_get_size( UINT64 compaction_mask, UINT64 mask );
|
||||
extern void copy_xstate( XSAVE_AREA_HEADER *dst, XSAVE_AREA_HEADER *src, UINT64 mask );
|
||||
|
||||
static inline UINT64 xstate_extended_features(void)
|
||||
{
|
||||
|
|
|
@ -1483,6 +1483,14 @@ typedef struct _XSTATE_CONFIGURATION
|
|||
ULONG64 EnabledUserVisibleSupervisorFeatures;
|
||||
} XSTATE_CONFIGURATION, *PXSTATE_CONFIGURATION;
|
||||
|
||||
typedef struct _XSAVE_AREA_HEADER
|
||||
{
|
||||
DWORD64 Mask;
|
||||
DWORD64 CompactionMask;
|
||||
DWORD64 Reserved2[6];
|
||||
}
|
||||
XSAVE_AREA_HEADER, *PXSAVE_AREA_HEADER;
|
||||
|
||||
typedef struct _YMMCONTEXT
|
||||
{
|
||||
M128A Ymm0;
|
||||
|
|
Loading…
Add table
Reference in a new issue