Alexandre Julliard : ntdll: Only restore the modified parts of the syscall frame on x86-64.

Alexandre Julliard julliard at winehq.org
Mon Jun 7 16:30:35 CDT 2021


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Jun  7 13:17:15 2021 +0200

ntdll: Only restore the modified parts of the syscall frame on x86-64.

Based on a patch by Jacek Caban.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/unix/signal_x86_64.c | 92 +++++++++++++----------------------------
 tools/winebuild/import.c        | 23 ++++++++++-
 2 files changed, 50 insertions(+), 65 deletions(-)

diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c
index 086bfdfe066..524c9348ec2 100644
--- a/dlls/ntdll/unix/signal_x86_64.c
+++ b/dlls/ntdll/unix/signal_x86_64.c
@@ -281,31 +281,31 @@ C_ASSERT( sizeof(struct syscall_xsave) == 0x340 );
 
 struct syscall_frame
 {
-    ULONG64               rax;     /* 0000 */
-    ULONG64               rbx;     /* 0008 */
-    ULONG64               rcx;     /* 0010 */
-    ULONG64               rdx;     /* 0018 */
-    ULONG64               rsi;     /* 0020 */
-    ULONG64               rdi;     /* 0028 */
-    ULONG64               r8;      /* 0030 */
-    ULONG64               r9;      /* 0038 */
-    ULONG64               r10;     /* 0040 */
-    ULONG64               r11;     /* 0048 */
-    ULONG64               r12;     /* 0050 */
-    ULONG64               r13;     /* 0058 */
-    ULONG64               r14;     /* 0060 */
-    ULONG64               r15;     /* 0068 */
-    ULONG64               rip;     /* 0070 */
-    WORD                  cs;      /* 0078 */
-    WORD                  ds;      /* 007a */
-    WORD                  es;      /* 007c */
-    WORD                  fs;      /* 007e */
-    ULONG64               eflags;  /* 0080 */
-    ULONG64               rsp;     /* 0088 */
-    WORD                  ss;      /* 0090 */
-    WORD                  gs;      /* 0092 */
-    WORD                  pad[2];  /* 0094 */
-    ULONG64               rbp;     /* 0098 */
+    ULONG64               rax;           /* 0000 */
+    ULONG64               rbx;           /* 0008 */
+    ULONG64               rcx;           /* 0010 */
+    ULONG64               rdx;           /* 0018 */
+    ULONG64               rsi;           /* 0020 */
+    ULONG64               rdi;           /* 0028 */
+    ULONG64               r8;            /* 0030 */
+    ULONG64               r9;            /* 0038 */
+    ULONG64               r10;           /* 0040 */
+    ULONG64               r11;           /* 0048 */
+    ULONG64               r12;           /* 0050 */
+    ULONG64               r13;           /* 0058 */
+    ULONG64               r14;           /* 0060 */
+    ULONG64               r15;           /* 0068 */
+    ULONG64               rip;           /* 0070 */
+    WORD                  cs;            /* 0078 */
+    WORD                  ds;            /* 007a */
+    WORD                  es;            /* 007c */
+    WORD                  fs;            /* 007e */
+    ULONG64               eflags;        /* 0080 */
+    ULONG64               rsp;           /* 0088 */
+    WORD                  ss;            /* 0090 */
+    WORD                  gs;            /* 0092 */
+    DWORD                 restore_flags; /* 0094 */
+    ULONG64               rbp;           /* 0098 */
 };
 
 C_ASSERT( sizeof( struct syscall_frame ) == 0xa0);
@@ -1558,34 +1558,6 @@ static void restore_context( const struct xcontext *xcontext, ucontext_t *sigcon
 }
 
 
-/***********************************************************************
- *           set_full_cpu_context
- *
- * Set the new CPU context.
- */
-extern void set_full_cpu_context(void) DECLSPEC_HIDDEN;
-__ASM_GLOBAL_FUNC( set_full_cpu_context,
-                   "movq %gs:0x30,%rdx\n\t"
-                   "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" )
-
 /***********************************************************************
  *           signal_restore_full_cpu_context
  *
@@ -1593,17 +1565,7 @@ __ASM_GLOBAL_FUNC( set_full_cpu_context,
  */
 void signal_restore_full_cpu_context(void)
 {
-    struct syscall_xsave *xsave = get_syscall_xsave( amd64_thread_data()->syscall_frame );
-
-    if (cpu_info.ProcessorFeatureBits & CPU_FEATURE_XSAVE)
-    {
-        __asm__ volatile( "xrstor64 %0" : : "m"(xsave->xsave), "a" (7), "d" (0) );
-    }
-    else
-    {
-        __asm__ volatile( "fxrstor64 %0" : : "m"(xsave->xsave) );
-    }
-    set_full_cpu_context();
+    amd64_thread_data()->syscall_frame->restore_flags |= CONTEXT_INTEGER;
 }
 
 
@@ -1708,6 +1670,8 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
         }
         else xsave->xstate.Mask &= ~XSTATE_MASK_GSSE;
     }
+
+    frame->restore_flags |= flags & ~CONTEXT_INTEGER;
     return STATUS_SUCCESS;
 }
 
diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c
index 3acf720e1c6..3bd139a2b31 100644
--- a/tools/winebuild/import.c
+++ b/tools/winebuild/import.c
@@ -1614,6 +1614,7 @@ static void output_syscall_dispatcher(void)
         output( "\tmovw %%fs,-0x1a(%%rbp)\n" );
         output( "\tmovw %%ss,-0x8(%%rbp)\n" );
         output( "\tmovw %%gs,-0x6(%%rbp)\n" );
+        output( "\tmovl $0,-0x4(%%rbp)\n" );
         output( "\tmovq %%rsp,%%r12\n" );
         output( "\tmovq %%rax,%%r13\n" );
         output( "\tmovl %s(%%rip),%%r14d\n", asm_name("__wine_syscall_flags") );
@@ -1667,6 +1668,9 @@ static void output_syscall_dispatcher(void)
         output( "\tcallq *(%%r10,%%r13,8)\n" );
         output( "2:\tmovq %%gs:0x30,%%rcx\n" );
         output( "\tmovq $0,0x328(%%rcx)\n" );
+        output( "\tmovl -4(%%rbp),%%ecx\n" );    /* frame->restore_flags */
+        output( "\ttestl $0x48,%%ecx\n" );       /* CONTEXT_FLOATING_POINT | CONTEXT_XSTATE */
+        output( "\tjz 4f\n" );
         output( "\ttestl $3,%%r14d\n" );  /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
         output( "\tjz 3f\n" );
         output( "\tmovq %%rax,%%r11\n" );
@@ -1687,7 +1691,24 @@ static void output_syscall_dispatcher(void)
         output_cfi( ".cfi_same_value %%rsi" );
         output( "\tmovq -0x90(%%rbp),%%rbx\n" );
         output_cfi( ".cfi_same_value %%rbx" );
-        output( "\tleaq -0x28(%%rbp),%%rsp\n" );
+        output( "\ttestl $0x3,%%ecx\n" );        /* CONTEXT_CONTROL | CONTEXT_INTEGER */
+        output( "\tjnz 1f\n" );
+        output( "\tmovq -0x28(%%rbp),%%rcx\n" ); /* frame->rip */
+        output( "\tleaq -0x10(%%rbp),%%rsp\n" ); /* frame->rsp */
+        output( "\tmovq (%%rbp),%%rbp\n" );
+        output_cfi( ".cfi_same_value %%rbp" );
+        output( "\tpopq %%rsp\n" );
+        output( "\tjmpq *%%rcx\n" );
+        output( "1:\ttestl $0x2,%%ecx\n" );      /* CONTEXT_INTEGER */
+        output( "\tjz 1f\n" );
+        output( "\tmovq -0x98(%%rbp),%%rax\n" );
+        output( "\tmovq -0x88(%%rbp),%%rcx\n" );
+        output( "\tmovq -0x80(%%rbp),%%rdx\n" );
+        output( "\tmovq -0x68(%%rbp),%%r8\n" );
+        output( "\tmovq -0x60(%%rbp),%%r9\n" );
+        output( "\tmovq -0x58(%%rbp),%%r10\n" );
+        output( "\tmovq -0x50(%%rbp),%%r11\n" );
+        output( "1:\tleaq -0x28(%%rbp),%%rsp\n" );
         output_cfi( ".cfi_def_cfa_register %%rsp" );
         output_cfi( ".cfi_adjust_cfa_offset 40" );
         output( "\tmovq (%%rbp),%%rbp\n" );




More information about the wine-cvs mailing list