From 437bef6ac15dea892904769b46a4cafb80ed9eb4 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Mon, 22 Feb 2021 18:04:16 +0100 Subject: [PATCH] ntdll: Use syscall dispatcher for restoring context in x86_64 NtSetContextThread implementation. Signed-off-by: Jacek Caban Signed-off-by: Alexandre Julliard --- dlls/ntdll/unix/server.c | 5 ++++- dlls/ntdll/unix/signal_arm.c | 10 ++++++++++ dlls/ntdll/unix/signal_arm64.c | 10 ++++++++++ dlls/ntdll/unix/signal_i386.c | 11 +++++++++++ dlls/ntdll/unix/signal_x86_64.c | 29 ++++++++++++++++++++++------- dlls/ntdll/unix/unix_private.h | 1 + tools/winebuild/import.c | 13 ++++++++++++- 7 files changed, 70 insertions(+), 9 deletions(-) diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index 6af8effe9e1..4f149c0f644 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -726,7 +726,10 @@ NTSTATUS WINAPI NtContinue( CONTEXT *context, BOOLEAN alertable ) status = server_select( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, 0, NULL, NULL, &apc ); if (status == STATUS_USER_APC) invoke_apc( context, &apc ); } - return NtSetContextThread( GetCurrentThread(), context ); + status = NtSetContextThread( GetCurrentThread(), context ); + if (!status && (context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) + signal_restore_full_cpu_context(); + return status; } diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c index 2de58925c84..cb4695939f5 100644 --- a/dlls/ntdll/unix/signal_arm.c +++ b/dlls/ntdll/unix/signal_arm.c @@ -332,6 +332,16 @@ __ASM_GLOBAL_FUNC( set_cpu_context, "pop {pc}" ) +/*********************************************************************** + * signal_restore_full_cpu_context + * + * Restore full context from syscall frame + */ +void signal_restore_full_cpu_context(void) +{ +} + + /*********************************************************************** * get_server_context_flags * diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c index 9a36746f5bc..80cc59d0743 100644 --- a/dlls/ntdll/unix/signal_arm64.c +++ b/dlls/ntdll/unix/signal_arm64.c @@ -406,6 +406,16 @@ static void restore_fpu( CONTEXT *context, ucontext_t *sigcontext ) } +/*********************************************************************** + * signal_restore_full_cpu_context + * + * Restore full context from syscall frame + */ +void signal_restore_full_cpu_context(void) +{ +} + + /*********************************************************************** * get_server_context_flags * diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index 09529a1ea96..4d03153bd1f 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -807,6 +807,17 @@ static inline void restore_xstate( const CONTEXT *context ) __asm__ volatile( "xrstor %0" : : "m"(*xrstor_base), "a" (4), "d" (0) ); } + +/*********************************************************************** + * signal_restore_full_cpu_context + * + * Restore full context from syscall frame + */ +void signal_restore_full_cpu_context(void) +{ +} + + /*********************************************************************** * fpux_to_fpu * diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index b5040852cbe..88e5eace003 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -1591,7 +1591,12 @@ __ASM_GLOBAL_FUNC( set_full_cpu_context, "leaq 0x70(%rsp),%rsp\n\t" "iretq" ) -static void signal_restore_full_cpu_context(void) +/*********************************************************************** + * signal_restore_full_cpu_context + * + * Restore full context from syscall frame + */ +void signal_restore_full_cpu_context(void) { struct syscall_xsave *xsave = get_syscall_xsave( get_syscall_frame() ); SYSTEM_CPU_INFORMATION cpu_info; @@ -1863,9 +1868,6 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context ) 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; } @@ -2614,11 +2616,24 @@ static void quit_handler( int signal, siginfo_t *siginfo, void *ucontext ) */ static void usr1_handler( int signal, siginfo_t *siginfo, void *ucontext ) { + struct syscall_frame *frame = amd64_thread_data()->syscall_frame; struct xcontext context; + if (frame) + { + DECLSPEC_ALIGN(64) XSTATE xs; + context.c.ContextFlags = CONTEXT_FULL; + context_init_xstate( &context.c, &xs ); - save_context( &context, ucontext ); - wait_suspend( &context.c ); - restore_context( &context, ucontext ); + NtGetContextThread( GetCurrentThread(), &context.c ); + wait_suspend( &context.c ); + NtSetContextThread( GetCurrentThread(), &context.c ); + } + else + { + save_context( &context, ucontext ); + wait_suspend( &context.c ); + restore_context( &context, ucontext ); + } } diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 65f526d0f7d..c98b11701e4 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -214,6 +214,7 @@ extern void DECLSPEC_NORETURN signal_start_thread( PRTL_THREAD_START_ROUTINE ent extern void DECLSPEC_NORETURN signal_exit_thread( int status, void (*func)(int) ) DECLSPEC_HIDDEN; extern void DECLSPEC_NORETURN exec_process( NTSTATUS status ) DECLSPEC_HIDDEN; extern void __wine_syscall_dispatcher(void) DECLSPEC_HIDDEN; +extern void signal_restore_full_cpu_context(void) DECLSPEC_HIDDEN; extern void fill_vm_counters( VM_COUNTERS_EX *pvmi, int unix_pid ) DECLSPEC_HIDDEN; extern NTSTATUS cdrom_DeviceIoControl( HANDLE device, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user, diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index 0fddbaf6134..a01694ffb9c 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -1559,7 +1559,18 @@ static void output_syscall_dispatcher( int count, const char *variant ) output( "\tcallq *(%%r10,%%r11,8)\n" ); output( "2:\tmovq %%gs:0x30,%%rcx\n" ); output( "\tmovq $0,0x328(%%rcx)\n" ); - output( "\tfxrstor64 (%%r12)\n" ); + if (!*variant) + { + output( "\tfxrstor64 (%%r12)\n" ); + } + else + { + output( "\tmovq %%rax,%%r11\n" ); + output( "\tmovl $7,%%eax\n" ); + output( "\txorq %%rdx,%%rdx\n" ); + output( "\txrstor64 (%%r12)\n" ); + output( "\tmovq %%r11,%%rax\n" ); + } output( "\tmovq -0x30(%%rbp),%%r15\n" ); output( "\tmovq -0x38(%%rbp),%%r14\n" ); output( "\tmovq -0x40(%%rbp),%%r13\n" );