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