Commit 3ecd43dc authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

ntdll: Use syscall frames in x86_64 NtSetContextThread implementation.

parent e162e7ea
......@@ -1568,71 +1568,47 @@ static void restore_context( const struct xcontext *xcontext, ucontext_t *sigcon
*
* Set the new CPU context.
*/
extern void set_full_cpu_context( const CONTEXT *context );
extern void set_full_cpu_context(void);
__ASM_GLOBAL_FUNC( set_full_cpu_context,
"subq $40,%rsp\n\t"
__ASM_SEH(".seh_stackalloc 0x40\n\t")
__ASM_SEH(".seh_endprologue\n\t")
__ASM_CFI(".cfi_adjust_cfa_offset 40\n\t")
"movq %gs:0x30,%rdx\n\t"
"movw 0x38(%rdi),%ax\n\t" /* context->SegCs */
"movq %rax,8(%rsp)\n\t"
"movw 0x42(%rdi),%ax\n\t" /* context->SegSs */
"movq %rax,32(%rsp)\n\t"
"movq 0x44(%rdi),%rax\n\t" /* context->Eflags */
"movq %rax,16(%rsp)\n\t"
"movq $0,0x328(%rdx)\n\t" /* amd64_thread_data()->syscall_frame */
"movq 0x80(%rdi),%rcx\n\t" /* context->Rcx */
"movq 0x88(%rdi),%rdx\n\t" /* context->Rdx */
"movq 0x90(%rdi),%rbx\n\t" /* context->Rbx */
"movq 0x98(%rdi),%rax\n\t" /* context->Rsp */
"movq %rax,24(%rsp)\n\t"
"movq 0xa0(%rdi),%rbp\n\t" /* context->Rbp */
"movq 0xa8(%rdi),%rsi\n\t" /* context->Rsi */
"movq 0xb8(%rdi),%r8\n\t" /* context->R8 */
"movq 0xc0(%rdi),%r9\n\t" /* context->R9 */
"movq 0xc8(%rdi),%r10\n\t" /* context->R10 */
"movq 0xd0(%rdi),%r11\n\t" /* context->R11 */
"movq 0xd8(%rdi),%r12\n\t" /* context->R12 */
"movq 0xe0(%rdi),%r13\n\t" /* context->R13 */
"movq 0xe8(%rdi),%r14\n\t" /* context->R14 */
"movq 0xf0(%rdi),%r15\n\t" /* context->R15 */
"movq 0xf8(%rdi),%rax\n\t" /* context->Rip */
"movq %rax,(%rsp)\n\t"
"fxrstor 0x100(%rdi)\n\t" /* context->FltSave */
"movq 0x78(%rdi),%rax\n\t" /* context->Rax */
"movq 0xb0(%rdi),%rdi\n\t" /* context->Rdi */
"iretq" );
/***********************************************************************
* restore_xstate
*
* Restore the XState context.
*/
static void restore_xstate( const CONTEXT *context )
{
XSAVE_FORMAT *xrstor_base;
XSTATE *xs;
if (!(user_shared_data->XState.EnabledFeatures && (xs = xstate_from_context( context ))))
return;
xrstor_base = (XSAVE_FORMAT *)xs - 1;
"movq 0x328(%rdx),%rsp\n\t" /* amd64_thread_data()->syscall_frame */
"movq $0,0x328(%rdx)\n\t"
"movq 0x00(%rsp),%rax\n\t"
"movq 0x08(%rsp),%rbx\n\t"
"movq 0x10(%rsp),%rcx\n\t"
"movq 0x18(%rsp),%rdx\n\t"
"movq 0x20(%rsp),%rsi\n\t"
"movq 0x28(%rsp),%rdi\n\t"
"movq 0x30(%rsp),%r8\n\t"
"movq 0x38(%rsp),%r9\n\t"
"movq 0x40(%rsp),%r10\n\t"
"movq 0x48(%rsp),%r11\n\t"
"movq 0x50(%rsp),%r12\n\t"
"movq 0x58(%rsp),%r13\n\t"
"movq 0x60(%rsp),%r14\n\t"
"movq 0x68(%rsp),%r15\n\t"
"movq 0x98(%rsp),%rbp\n\t"
"leaq 0x70(%rsp),%rsp\n\t"
"iretq" )
static void signal_restore_full_cpu_context(void)
{
struct syscall_xsave *xsave = get_syscall_xsave( get_syscall_frame() );
SYSTEM_CPU_INFORMATION cpu_info;
if (!(xs->CompactionMask & ((ULONG64)1 << 63)))
NtQuerySystemInformation( SystemCpuInformation, &cpu_info, sizeof(cpu_info), NULL );
if (cpu_info.FeatureSet & CPU_FEATURE_XSAVE)
{
/* Non-compacted xrstor will load Mxcsr regardless of the specified mask. Loading garbage there
* may lead to fault. We have only padding, no more used EXCEPTION_RECORD or unused context fields
* at the MxCsr restore location, so just put it there. */
assert( (void *)&xrstor_base->MxCsr > (void *)context->VectorRegister );
xrstor_base->MxCsr = context->u.FltSave.MxCsr;
xrstor_base->MxCsr_Mask = context->u.FltSave.MxCsr_Mask;
__asm__ volatile( "xrstor64 %0" : : "m"(xsave->xsave), "a" (7), "d" (0) );
}
__asm__ volatile( "xrstor64 %0" : : "m"(*xrstor_base), "a" (4), "d" (0) );
else
{
__asm__ volatile( "fxrstor64 %0" : : "m"(xsave->xsave) );
}
set_full_cpu_context();
}
/***********************************************************************
* get_server_context_flags
*
......@@ -1798,6 +1774,9 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
NTSTATUS ret = STATUS_SUCCESS;
DWORD flags = context->ContextFlags & ~CONTEXT_AMD64;
BOOL self = (handle == GetCurrentThread());
struct syscall_frame *frame;
struct syscall_xsave *xsave;
XSTATE *xs;
/* debug registers require a server call */
if (self && (flags & CONTEXT_DEBUG_REGISTERS))
......@@ -1826,16 +1805,68 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
}
}
restore_xstate( context );
if (flags & CONTEXT_FULL)
frame = amd64_thread_data()->syscall_frame;
xsave = get_syscall_xsave( frame );
if (flags & CONTEXT_INTEGER)
{
if (!(flags & CONTEXT_CONTROL))
FIXME( "setting partial context (%x) not supported\n", flags );
else
set_full_cpu_context( context );
frame->rax = context->Rax;
frame->rbx = context->Rbx;
frame->rcx = context->Rcx;
frame->rdx = context->Rdx;
frame->rsi = context->Rsi;
frame->rdi = context->Rdi;
frame->r8 = context->R8;
frame->r9 = context->R9;
frame->r10 = context->R10;
frame->r11 = context->R11;
frame->r12 = context->R12;
frame->r13 = context->R13;
frame->r14 = context->R14;
frame->r15 = context->R15;
}
return ret;
if (flags & CONTEXT_CONTROL)
{
frame->rsp = context->Rsp;
frame->rbp = context->Rbp;
frame->rip = context->Rip;
frame->eflags = context->EFlags;
frame->cs = context->SegCs;
frame->ss = context->SegSs;
}
if (flags & CONTEXT_SEGMENTS)
{
frame->ds = context->SegDs;
frame->es = context->SegEs;
frame->fs = context->SegFs;
frame->gs = context->SegGs;
}
if (flags & CONTEXT_FLOATING_POINT)
{
xsave->xsave = context->u.FltSave;
}
if (user_shared_data->XState.EnabledFeatures && (xs = xstate_from_context( context )))
{
CONTEXT_EX *context_ex = (CONTEXT_EX *)(context + 1);
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.YmmContext, &xs->YmmContext, sizeof(xs->YmmContext) );
}
else if (xs->CompactionMask & XSTATE_MASK_GSSE)
xsave->xstate.Mask &= ~XSTATE_MASK_GSSE;
}
if (!(flags & CONTEXT_INTEGER)) frame->rax = STATUS_SUCCESS;
signal_restore_full_cpu_context();
return STATUS_SUCCESS;
}
......
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