Module: wine Branch: master Commit: 3d9cb5e4f8119e00ac26e4146905016bfd017d90 URL: https://source.winehq.org/git/wine.git/?a=commit;h=3d9cb5e4f8119e00ac26e4146...
Author: Alexandre Julliard julliard@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@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; }