Jacek Caban : ntdll: Use syscall dispatcher for restoring context in x86_64 NtSetContextThread implementation.

Alexandre Julliard julliard at winehq.org
Mon Feb 22 15:43:22 CST 2021


Module: wine
Branch: master
Commit: 437bef6ac15dea892904769b46a4cafb80ed9eb4
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=437bef6ac15dea892904769b46a4cafb80ed9eb4

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Mon Feb 22 18:04:16 2021 +0100

ntdll: Use syscall dispatcher for restoring context in x86_64 NtSetContextThread implementation.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 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" );




More information about the wine-cvs mailing list