Jacek Caban : ntdll: Store x86_64 YMM context in syscall frame.

Alexandre Julliard julliard at winehq.org
Fri Feb 19 17:20:10 CST 2021


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Fri Feb 19 19:08:59 2021 +0100

ntdll: Store x86_64 YMM context in syscall frame.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 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() ) );




More information about the wine-cvs mailing list