Module: wine Branch: master Commit: 3ecd43dc6fabe072857139d513ae8e3a44861662 URL: https://source.winehq.org/git/wine.git/?a=commit;h=3ecd43dc6fabe072857139d51...
Author: Jacek Caban jacek@codeweavers.com Date: Mon Feb 22 18:01:47 2021 +0100
ntdll: Use syscall frames in x86_64 NtSetContextThread implementation.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ntdll/unix/signal_x86_64.c | 163 ++++++++++++++++++++++++---------------- 1 file changed, 97 insertions(+), 66 deletions(-)
diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index 8d3353e959d..b5040852cbe 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -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; }