From 11e3d43c264bf24657b20c1435cbabfa78e0b1f0 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Fri, 19 Feb 2021 19:08:59 +0100 Subject: [PATCH] ntdll: Store x86_64 YMM context in syscall frame. Signed-off-by: Jacek Caban Signed-off-by: Alexandre Julliard --- dlls/ntdll/unix/signal_x86_64.c | 20 +++++++++++---- tools/winebuild/import.c | 45 +++++++++++++++++++++++++-------- 2 files changed, 50 insertions(+), 15 deletions(-) diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index bed4958f251..ca0f9117cd5 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -270,9 +270,10 @@ C_ASSERT( sizeof(struct apc_stack_layout) == 0x510 ); struct syscall_xsave { XMM_SAVE_AREA32 xsave; + XSTATE xstate; }; -C_ASSERT( sizeof(struct syscall_xsave) == 0x200 ); +C_ASSERT( sizeof(struct syscall_xsave) == 0x340 ); struct syscall_frame { @@ -2147,7 +2148,7 @@ __ASM_GLOBAL_FUNC( call_user_apc_dispatcher, __ASM_GLOBAL_FUNC( call_raise_user_exception_dispatcher, "movq %gs:0x30,%rdx\n\t" "movq 0x328(%rdx),%rax\n\t" /* amd64_thread_data()->syscall_frame */ - "leaq -0x200(%rax),%r8\n\t" + "leaq -0x340(%rax),%r8\n\t" "andq $~63,%r8\n\t" "fxrstor64 (%r8)\n\t" "movq 0x8(%rax),%rbx\n\t" /* frame->rbx */ @@ -2793,14 +2794,23 @@ void signal_init_process(void) */ void *signal_init_syscalls(void) { - void *ptr; + SYSTEM_CPU_INFORMATION cpu_info; + void *ptr, *syscall_dispatcher; + + extern void __wine_syscall_dispatcher_xsave(void) DECLSPEC_HIDDEN; + + NtQuerySystemInformation( SystemCpuInformation, &cpu_info, sizeof(cpu_info), NULL ); + if (cpu_info.FeatureSet & CPU_FEATURE_XSAVE) + syscall_dispatcher = __wine_syscall_dispatcher_xsave; + else + syscall_dispatcher = __wine_syscall_dispatcher; /* 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 = __wine_syscall_dispatcher; + *(void **)ptr = syscall_dispatcher; - return __wine_syscall_dispatcher; + return syscall_dispatcher; } diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index 85bd31b8e08..0fddbaf6134 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -1426,13 +1426,14 @@ static int cmp_link_name( const void *e1, const void *e2 ) /* output dispatcher for system calls */ -static void output_syscall_dispatcher( int count ) +static void output_syscall_dispatcher( int count, const char *variant ) { const unsigned int invalid_param = 0xc000000d; /* STATUS_INVALID_PARAMETER */ + const char *symbol = strmake( "__wine_syscall_dispatcher%s", variant ); output( "\t.align %d\n", get_alignment(4) ); - output( "\t%s\n", func_declaration("__wine_syscall_dispatcher") ); - output( "%s\n", asm_globl("__wine_syscall_dispatcher") ); + output( "\t%s\n", func_declaration(symbol) ); + output( "%s\n", asm_globl(symbol) ); output_cfi( ".cfi_startproc" ); switch (target_cpu) { @@ -1493,7 +1494,7 @@ static void output_syscall_dispatcher( int count ) output_cfi( ".cfi_def_cfa_register %%rbp" ); output( "\tleaq -0x10(%%rbp),%%rsp\n" ); output( "\tpushfq\n" ); - output( "\tsubq $0x280,%%rsp\n" ); + output( "\tsubq $0x3c0,%%rsp\n" ); output( "\tandq $~63,%%rsp\n" ); output( "\tmovq %%rbx,-0x90(%%rbp)\n" ); output_cfi( ".cfi_rel_offset %%rbx,-144" ); @@ -1520,14 +1521,29 @@ static void output_syscall_dispatcher( int count ) output( "\tmovw %%ss,-0x8(%%rbp)\n" ); output( "\tmovw %%gs,-0x6(%%rbp)\n" ); output( "\tmovq %%rsp,%%r12\n" ); - output( "\tfxsave64 (%%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" ); + output( "\txsave64 (%%r12)\n" ); + output( "\tmovq %%rsi,%%rdx\n" ); + } output( "\tmovq %%gs:0x30,%%rcx\n" ); output( "\tleaq -0x98(%%rbp),%%rbx\n" ); output( "\tmovq %%rbx,0x328(%%rcx)\n" ); /* amd64_thread_data()->syscall_frame */ - output( "\tcmpq $%u,%%rax\n", count ); + output( "\tcmpq $%u,%%r11\n", count ); output( "\tjae 3f\n" ); output( "\tleaq .Lsyscall_args(%%rip),%%rcx\n" ); - output( "\tmovzbl (%%rcx,%%rax),%%ecx\n" ); + output( "\tmovzbl (%%rcx,%%r11),%%ecx\n" ); output( "\tsubq $0x20,%%rcx\n" ); output( "\tjbe 1f\n" ); output( "\tsubq %%rcx,%%rsp\n" ); @@ -1540,7 +1556,7 @@ static void output_syscall_dispatcher( int count ) output( "1:\tmovq %%r10,%%rcx\n" ); output( "\tsubq $0x20,%%rsp\n" ); output( "\tleaq .Lsyscall_table(%%rip),%%r10\n" ); - output( "\tcallq *(%%r10,%%rax,8)\n" ); + output( "\tcallq *(%%r10,%%r11,8)\n" ); output( "2:\tmovq %%gs:0x30,%%rcx\n" ); output( "\tmovq $0,0x328(%%rcx)\n" ); output( "\tfxrstor64 (%%r12)\n" ); @@ -1682,7 +1698,7 @@ static void output_syscall_dispatcher( int count ) assert(0); } output_cfi( ".cfi_endproc" ); - output_function_size( "__wine_syscall_dispatcher" ); + output_function_size( symbol ); } @@ -1707,7 +1723,16 @@ void output_syscalls( DLLSPEC *spec ) if (unix_lib) { - output_syscall_dispatcher( count ); + output_syscall_dispatcher( count, "" ); + + switch( target_cpu ) + { + case CPU_x86_64: + output_syscall_dispatcher( count, "_xsave" ); + break; + default: + break; + } output( "\t.data\n" ); output( "\t.align %d\n", get_alignment( get_ptr_size() ) );