Alexandre Julliard : ntdll: Use a single syscall dispatcher controlled by global flags on x86-64.

Alexandre Julliard julliard at winehq.org
Wed Jun 2 16:27:42 CDT 2021


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed Jun  2 12:02:41 2021 +0200

ntdll: Use a single syscall dispatcher controlled by global flags 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 | 23 +++++-----
 dlls/ntdll/unix/unix_private.h  |  1 +
 tools/winebuild/import.c        | 96 +++++++++++++++++++----------------------
 3 files changed, 56 insertions(+), 64 deletions(-)

diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c
index 75a49a753f2..0f74e55ce04 100644
--- a/dlls/ntdll/unix/signal_x86_64.c
+++ b/dlls/ntdll/unix/signal_x86_64.c
@@ -251,6 +251,10 @@ C_ASSERT((offsetof(struct stack_layout, xstate) == sizeof(struct stack_layout)))
 C_ASSERT( sizeof(XSTATE) == 0x140 );
 C_ASSERT( sizeof(struct stack_layout) == 0x590 ); /* Should match the size in call_user_exception_dispatcher(). */
 
+/* flags to control the behavior of the syscall dispatcher */
+#define SYSCALL_HAVE_XSAVE    1
+#define SYSCALL_HAVE_XSAVEC   2
+
 /* stack layout when calling an user apc function.
  * FIXME: match Windows ABI. */
 struct apc_stack_layout
@@ -2653,6 +2657,9 @@ void signal_init_process(void)
 {
     struct sigaction sig_act;
 
+    if (cpu_info.ProcessorFeatureBits & CPU_FEATURE_XSAVE) __wine_syscall_flags |= SYSCALL_HAVE_XSAVE;
+    if (xstate_compaction_enabled) __wine_syscall_flags |= SYSCALL_HAVE_XSAVEC;
+
     sig_act.sa_mask = server_block_set;
     sig_act.sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK;
 
@@ -2685,24 +2692,14 @@ void signal_init_process(void)
  */
 void *signal_init_syscalls(void)
 {
-    void *ptr, *syscall_dispatcher;
-
-    extern void __wine_syscall_dispatcher_xsave(void) DECLSPEC_HIDDEN;
-    extern void __wine_syscall_dispatcher_xsavec(void) DECLSPEC_HIDDEN;
-
-    if (xstate_compaction_enabled)
-        syscall_dispatcher = __wine_syscall_dispatcher_xsavec;
-    else if (cpu_info.ProcessorFeatureBits & CPU_FEATURE_XSAVE)
-        syscall_dispatcher = __wine_syscall_dispatcher_xsave;
-    else
-        syscall_dispatcher = __wine_syscall_dispatcher;
+    void *ptr;
 
     /* sneak in a syscall dispatcher pointer at a fixed address (7ffe1000) */
     ptr = (char *)user_shared_data + page_size;
     anon_mmap_fixed( ptr, page_size, PROT_READ | PROT_WRITE, 0 );
-    *(void **)ptr = syscall_dispatcher;
+    *(void **)ptr = __wine_syscall_dispatcher;
 
-    return syscall_dispatcher;
+    return __wine_syscall_dispatcher;
 }
 
 
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
index cf3b8280200..786bb035d0a 100644
--- a/dlls/ntdll/unix/unix_private.h
+++ b/dlls/ntdll/unix/unix_private.h
@@ -248,6 +248,7 @@ extern void DECLSPEC_NORETURN signal_start_thread( PRTL_THREAD_START_ROUTINE ent
                                                    BOOL suspend, void *thunk, TEB *teb ) DECLSPEC_HIDDEN;
 extern void DECLSPEC_NORETURN signal_exit_thread( int status, void (*func)(int) ) DECLSPEC_HIDDEN;
 extern void __wine_syscall_dispatcher(void) DECLSPEC_HIDDEN;
+extern unsigned int __wine_syscall_flags DECLSPEC_HIDDEN;
 extern void signal_restore_full_cpu_context(void) DECLSPEC_HIDDEN;
 extern NTSTATUS get_thread_wow64_context( HANDLE handle, void *ctx, ULONG size ) DECLSPEC_HIDDEN;
 extern NTSTATUS set_thread_wow64_context( HANDLE handle, const void *ctx, ULONG size ) DECLSPEC_HIDDEN;
diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c
index 7fdfe8d6f94..c89d00f65f3 100644
--- a/tools/winebuild/import.c
+++ b/tools/winebuild/import.c
@@ -1621,45 +1621,43 @@ static void output_syscall_dispatcher( const char *variant )
         output( "\tmovw %%ss,-0x8(%%rbp)\n" );
         output( "\tmovw %%gs,-0x6(%%rbp)\n" );
         output( "\tmovq %%rsp,%%r12\n" );
-        output( "\tmovq %%rax,%%r11\n" );
-        if (!*variant)
-        {
-            output( "\tfxsave64 (%%r12)\n" );
-        }
-        else
-        {
-            output( "\tmovl $7,%%eax\n" );
-            output( "\tmovq %%rdx,%%rsi\n" );
-            output( "\txorq %%rdx,%%rdx\n" );
-            output( "\tmovq %%rdx,0x200(%%r12)\n" );
-            output( "\tmovq %%rdx,0x208(%%r12)\n" );
-            output( "\tmovq %%rdx,0x210(%%r12)\n" );
-            if (!strcmp( variant, "_xsavec" ))
-            {
-                output( "\tmovq %%rdx,0x218(%%r12)\n" );
-                output( "\tmovq %%rdx,0x220(%%r12)\n" );
-                output( "\tmovq %%rdx,0x228(%%r12)\n" );
-                output( "\tmovq %%rdx,0x230(%%r12)\n" );
-                output( "\tmovq %%rdx,0x238(%%r12)\n" );
-                output( "\txsavec64 (%%r12)\n" );
-            }
-            else
-                output( "\txsave64 (%%r12)\n" );
-            output( "\tmovq %%rsi,%%rdx\n" );
-        }
-        output( "\tmovq %%gs:0x30,%%rcx\n" );
+        output( "\tmovq %%rax,%%r13\n" );
+        output( "\tmovl %s(%%rip),%%r14d\n", asm_name("__wine_syscall_flags") );
+        output( "\ttestl $3,%%r14d\n" );  /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
+        output( "\tjz 2f\n" );
+        output( "\tmovl $7,%%eax\n" );
+        output( "\tmovq %%rdx,%%rsi\n" );
+        output( "\txorq %%rdx,%%rdx\n" );
+        output( "\tmovq %%rdx,0x200(%%r12)\n" );
+        output( "\tmovq %%rdx,0x208(%%r12)\n" );
+        output( "\tmovq %%rdx,0x210(%%r12)\n" );
+        output( "\ttestl $2,%%r14d\n" );  /* SYSCALL_HAVE_XSAVEC */
+        output( "\tjz 1f\n" );
+        output( "\tmovq %%rdx,0x218(%%r12)\n" );
+        output( "\tmovq %%rdx,0x220(%%r12)\n" );
+        output( "\tmovq %%rdx,0x228(%%r12)\n" );
+        output( "\tmovq %%rdx,0x230(%%r12)\n" );
+        output( "\tmovq %%rdx,0x238(%%r12)\n" );
+        output( "\txsavec64 (%%r12)\n" );
+        output( "\tmovq %%rsi,%%rdx\n" );
+        output( "\tjmp 3f\n" );
+        output( "1:\txsave64 (%%r12)\n" );
+        output( "\tmovq %%rsi,%%rdx\n" );
+        output( "\tjmp 3f\n" );
+        output( "2:\tfxsave64 (%%r12)\n" );
+        output( "3:\tmovq %%gs:0x30,%%rcx\n" );
         output( "\tleaq -0x98(%%rbp),%%rbx\n" );
         output( "\tmovq %%rbx,0x328(%%rcx)\n" );  /* amd64_thread_data()->syscall_frame */
-        output( "\tmovq %%r11,%%rbx\n" );
+        output( "\tmovq %%r13,%%rbx\n" );
         output( "\tshrl $8,%%ebx\n" );
         output( "\tandl $0x30,%%ebx\n" );         /* syscall table number */
         output( "\tleaq %s(%%rip),%%rcx\n", asm_name("KeServiceDescriptorTable") );
         output( "\tleaq (%%rcx,%%rbx,2),%%rbx\n" );
-        output( "\tandq $0xfff,%%r11\n" );        /* syscall number */
-        output( "\tcmpq 16(%%rbx),%%r11\n" );     /* table->ServiceLimit */
-        output( "\tjae 3f\n" );
+        output( "\tandq $0xfff,%%r13\n" );        /* syscall number */
+        output( "\tcmpq 16(%%rbx),%%r13\n" );     /* table->ServiceLimit */
+        output( "\tjae 5f\n" );
         output( "\tmovq 24(%%rbx),%%rcx\n" );     /* table->ArgumentTable */
-        output( "\tmovzbl (%%rcx,%%r11),%%ecx\n" );
+        output( "\tmovzbl (%%rcx,%%r13),%%ecx\n" );
         output( "\tsubq $0x20,%%rcx\n" );
         output( "\tjbe 1f\n" );
         output( "\tsubq %%rcx,%%rsp\n" );
@@ -1672,22 +1670,19 @@ static void output_syscall_dispatcher( const char *variant )
         output( "1:\tmovq %%r10,%%rcx\n" );
         output( "\tsubq $0x20,%%rsp\n" );
         output( "\tmovq (%%rbx),%%r10\n" );      /* table->ServiceTable */
-        output( "\tcallq *(%%r10,%%r11,8)\n" );
+        output( "\tcallq *(%%r10,%%r13,8)\n" );
         output( "2:\tmovq %%gs:0x30,%%rcx\n" );
         output( "\tmovq $0,0x328(%%rcx)\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( "\ttestl $3,%%r14d\n" );  /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
+        output( "\tjz 3f\n" );
+        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( "\tjmp 4f\n" );
+        output( "3:\tfxrstor64 (%%r12)\n" );
+        output( "4:\tmovq -0x30(%%rbp),%%r15\n" );
         output( "\tmovq -0x38(%%rbp),%%r14\n" );
         output( "\tmovq -0x40(%%rbp),%%r13\n" );
         output( "\tmovq -0x48(%%rbp),%%r12\n" );
@@ -1704,7 +1699,7 @@ static void output_syscall_dispatcher( const char *variant )
         output( "\tmovq (%%rbp),%%rbp\n" );
         output_cfi( ".cfi_same_value %%rbp" );
         output( "\tiretq\n" );
-        output( "3:\tmovl $0x%x,%%eax\n", invalid_param );
+        output( "5:\tmovl $0x%x,%%eax\n", invalid_param );
         output( "\tjmp 2b\n" );
         break;
     case CPU_ARM:
@@ -1861,10 +1856,6 @@ void output_syscalls( DLLSPEC *spec )
             output_syscall_dispatcher( "_xsave" );
             output_syscall_dispatcher( "_xsavec" );
             break;
-        case CPU_x86_64:
-            output_syscall_dispatcher( "_xsave" );
-            output_syscall_dispatcher( "_xsavec" );
-            break;
         default:
             break;
         }
@@ -1881,6 +1872,9 @@ void output_syscalls( DLLSPEC *spec )
         output( ".Lsyscall_args:\n" );
         for (i = 0; i < count; i++)
             output( "\t.byte %u\n", get_args_size( syscalls[i] ));
+        output( "\t.align %d\n", get_alignment(4) );
+        output( "%s\n", asm_globl("__wine_syscall_flags") );
+        output( "\t.long 0\n" );
         return;
     }
 




More information about the wine-cvs mailing list