Jacek Caban : ntdll: Store FPU and XMM contexts in x86 syscall frame.

Alexandre Julliard julliard at winehq.org
Mon Mar 1 15:54:05 CST 2021


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Mon Mar  1 16:51:32 2021 +0100

ntdll: Store FPU and XMM contexts in x86 syscall frame.

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

---

 dlls/ntdll/unix/signal_arm.c  |  1 +
 dlls/ntdll/unix/signal_i386.c | 23 ++++++++++++++++++++++-
 dlls/ntdll/unix/virtual.c     |  1 -
 tools/winebuild/import.c      | 28 +++++++++++++++++++++++++++-
 4 files changed, 50 insertions(+), 3 deletions(-)

diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c
index cb4695939f5..5c96521e55e 100644
--- a/dlls/ntdll/unix/signal_arm.c
+++ b/dlls/ntdll/unix/signal_arm.c
@@ -918,6 +918,7 @@ void signal_init_threading(void)
  */
 NTSTATUS signal_alloc_thread( TEB *teb )
 {
+    teb->WOW32Reserved = __wine_syscall_dispatcher;
     return STATUS_SUCCESS;
 }
 
diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c
index 0234c7aa6f7..7e383bdcaba 100644
--- a/dlls/ntdll/unix/signal_i386.c
+++ b/dlls/ntdll/unix/signal_i386.c
@@ -461,6 +461,17 @@ enum i386_trap_code
 #endif
 };
 
+struct syscall_xsave
+{
+    union
+    {
+        XSAVE_FORMAT       xsave;
+        FLOATING_SAVE_AREA fsave;
+    } u;
+};
+
+C_ASSERT( sizeof(struct syscall_xsave) == 0x200 );
+
 struct syscall_frame
 {
     DWORD              eflags;  /* 00 */
@@ -502,6 +513,8 @@ C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct x86_thread_data, gs )
 C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct x86_thread_data, exit_frame ) == 0x1f4 );
 C_ASSERT( offsetof( TEB, GdiTebBatch ) + offsetof( struct x86_thread_data, syscall_frame ) == 0x1f8 );
 
+static void *syscall_dispatcher;
+
 static inline struct x86_thread_data *x86_thread_data(void)
 {
     return (struct x86_thread_data *)ntdll_get_thread_data()->cpu_data;
@@ -2424,6 +2437,7 @@ NTSTATUS signal_alloc_thread( TEB *teb )
     }
     else thread_data->fs = gdt_fs_sel;
 
+    teb->WOW32Reserved = syscall_dispatcher;
     return STATUS_SUCCESS;
 }
 
@@ -2501,7 +2515,14 @@ void signal_init_process(void)
  */
 void *signal_init_syscalls(void)
 {
-    return __wine_syscall_dispatcher;
+    extern void __wine_syscall_dispatcher_fxsave(void) DECLSPEC_HIDDEN;
+
+    if (cpu_info.FeatureSet & CPU_FEATURE_FXSR)
+        syscall_dispatcher = __wine_syscall_dispatcher_fxsave;
+    else
+        syscall_dispatcher = __wine_syscall_dispatcher;
+
+    return NtCurrentTeb()->WOW32Reserved = syscall_dispatcher;
 }
 
 
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
index 3350dc665c1..a707faae2a5 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -2556,7 +2556,6 @@ static void init_teb( TEB *teb, PEB *peb )
             PtrToUlong( &teb64->ActivationContextStack.FrameListCache );
     teb64->StaticUnicodeString.Buffer = PtrToUlong( teb64->StaticUnicodeBuffer );
     teb64->StaticUnicodeString.MaximumLength = sizeof( teb64->StaticUnicodeBuffer );
-    teb->WOW32Reserved = __wine_syscall_dispatcher;
 #endif
     teb->Peb = peb;
     teb->Tib.Self = &teb->Tib;
diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c
index c760903dbd1..53d77a19e23 100644
--- a/tools/winebuild/import.c
+++ b/tools/winebuild/import.c
@@ -1456,7 +1456,19 @@ static void output_syscall_dispatcher( int count, const char *variant )
         output( "\tmovl %%ecx,-0x28(%%ebp)\n" ); /* frame->esp */
         output( "\tmovl 4(%%ebp),%%ecx\n" );
         output( "\tmovl %%ecx,-0x2c(%%ebp)\n" ); /* frame->eip */
-        output( "\tmovl %%esp,%%fs:0x1f8\n" );  /* x86_thread_data()->syscall_frame */
+        output( "\tsubl $0x200,%%esp\n") ;
+        output( "\tandl $~63,%%esp\n" );
+        if (!*variant)
+        {
+            output( "\tfnsave (%%esp)\n" );
+            output( "\tfwait\n" );
+        }
+        else
+        {
+            output( "\tfxsave (%%esp)\n" );
+        }
+        output( "\tleal -0x30(%%ebp),%%ecx\n" );
+        output( "\tmovl %%ecx,%%fs:0x1f8\n" );  /* x86_thread_data()->syscall_frame */
         output( "\tcmpl $%u,%%eax\n", count );
         output( "\tjae 4f\n" );
         if (UsePIC)
@@ -1479,6 +1491,17 @@ static void output_syscall_dispatcher( int count, const char *variant )
         else
             output( "\tcall *.Lsyscall_table(,%%eax,4)\n" );
         output( "2:\tmovl $0,%%fs:0x1f8\n" );
+        output( "\tleal -0x230(%%ebp),%%ebx\n") ;
+        output( "\tandl $~63,%%ebx\n" );
+        if (!*variant)
+        {
+            output( "\tfrstor (%%ebx)\n" );
+            output( "\tfwait\n" );
+        }
+        else
+        {
+            output( "\tfxrstor (%%ebx)\n" );
+        }
         output( "\tleal -0x30(%%ebp),%%ebx\n" );
         output_cfi( ".cfi_def_cfa_register %%ebx" );
         output_cfi( ".cfi_adjust_cfa_offset 0x30\n" );
@@ -1792,6 +1815,9 @@ void output_syscalls( DLLSPEC *spec )
 
         switch( target_cpu )
         {
+        case CPU_x86:
+            output_syscall_dispatcher( count, "_fxsave" );
+            break;
         case CPU_x86_64:
             output_syscall_dispatcher( count, "_xsave" );
             output_syscall_dispatcher( count, "_xsavec" );




More information about the wine-cvs mailing list