diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index b66a7bd8995..7aba553216f 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -481,25 +481,26 @@ C_ASSERT( sizeof(struct syscall_xsave) == 0x2c0 ); struct syscall_frame { - DWORD eflags; /* 00 */ - DWORD eip; /* 04 */ - DWORD esp; /* 08 */ - WORD cs; /* 0c */ - WORD ss; /* 0e */ - WORD ds; /* 10 */ - WORD es; /* 12 */ - WORD fs; /* 14 */ - WORD gs; /* 16 */ - DWORD eax; /* 18 */ - DWORD ebx; /* 1c */ - DWORD ecx; /* 20 */ - DWORD edx; /* 24 */ - DWORD edi; /* 28 */ - DWORD esi; /* 2c */ - DWORD ebp; /* 30 */ + DWORD restore_flags; /* 00 */ + DWORD eflags; /* 04 */ + DWORD eip; /* 08 */ + DWORD esp; /* 0c */ + WORD cs; /* 10 */ + WORD ss; /* 12 */ + WORD ds; /* 14 */ + WORD es; /* 16 */ + WORD fs; /* 18 */ + WORD gs; /* 1a */ + DWORD eax; /* 1c */ + DWORD ebx; /* 20 */ + DWORD ecx; /* 24 */ + DWORD edx; /* 28 */ + DWORD edi; /* 2c */ + DWORD esi; /* 30 */ + DWORD ebp; /* 34 */ }; -C_ASSERT( sizeof(struct syscall_frame) == 0x34 ); +C_ASSERT( sizeof(struct syscall_frame) == 0x38 ); struct x86_thread_data { @@ -902,63 +903,6 @@ static inline void restore_context( const struct xcontext *xcontext, ucontext_t } -/*********************************************************************** - * set_full_cpu_context - * - * Set the new CPU context. - */ -extern void set_full_cpu_context(void) DECLSPEC_HIDDEN; -__ASM_GLOBAL_FUNC( set_full_cpu_context, - "movl %fs:0x1f8,%ecx\n\t" - "movl $0,%fs:0x1f8\n\t" /* x86_thread_data()->syscall_frame = NULL */ - "movw 0x16(%ecx),%gs\n\t" /* SegGs */ - "movw 0x14(%ecx),%fs\n\t" /* SegFs */ - "movw 0x12(%ecx),%es\n\t" /* SegEs */ - "movl 0x1c(%ecx),%ebx\n\t" /* Ebx */ - "movl 0x28(%ecx),%edi\n\t" /* Edi */ - "movl 0x2c(%ecx),%esi\n\t" /* Esi */ - "movl 0x30(%ecx),%ebp\n\t" /* Ebp */ - "movw %ss,%ax\n\t" - "cmpw 0x0e(%ecx),%ax\n\t" /* SegSs */ - "jne 1f\n\t" - /* As soon as we have switched stacks the context structure could - * be invalid (when signal handlers are executed for example). Copy - * values on the target stack before changing ESP. */ - "movl 0x08(%ecx),%eax\n\t" /* Esp */ - "leal -4*4(%eax),%eax\n\t" - "movl (%ecx),%edx\n\t" /* EFlags */ - "movl %edx,3*4(%eax)\n\t" - "movl 0x0c(%ecx),%edx\n\t" /* SegCs */ - "movl %edx,2*4(%eax)\n\t" - "movl 0x04(%ecx),%edx\n\t" /* Eip */ - "movl %edx,1*4(%eax)\n\t" - "movl 0x18(%ecx),%edx\n\t" /* Eax */ - "movl %edx,0*4(%eax)\n\t" - "pushl 0x10(%ecx)\n\t" /* SegDs */ - "movl 0x24(%ecx),%edx\n\t" /* Edx */ - "movl 0x20(%ecx),%ecx\n\t" /* Ecx */ - "popl %ds\n\t" - "movl %eax,%esp\n\t" - "popl %eax\n\t" - "iret\n" - /* Restore the context when the stack segment changes. We can't use - * the same code as above because we do not know if the stack segment - * is 16 or 32 bit, and 'movl' will throw an exception when we try to - * access memory above the limit. */ - "1:\n\t" - "movl 0x24(%ecx),%edx\n\t" /* Edx */ - "movl 0x18(%ecx),%eax\n\t" /* Eax */ - "movw 0x0e(%ecx),%ss\n\t" /* SegSs */ - "movl 0x08(%ecx),%esp\n\t" /* Esp */ - "pushl 0x00(%ecx)\n\t" /* EFlags */ - "pushl 0x0c(%ecx)\n\t" /* SegCs */ - "pushl 0x04(%ecx)\n\t" /* Eip */ - "pushl 0x10(%ecx)\n\t" /* SegDs */ - "movl 0x20(%ecx),%ecx\n\t" /* Ecx */ - "popl %ds\n\t" - "iret" ) - - /*********************************************************************** * signal_restore_full_cpu_context * @@ -966,21 +910,7 @@ __ASM_GLOBAL_FUNC( set_full_cpu_context, */ void signal_restore_full_cpu_context(void) { - struct syscall_xsave *xsave = get_syscall_xsave( x86_thread_data()->syscall_frame ); - - if (cpu_info.ProcessorFeatureBits & CPU_FEATURE_XSAVE) - { - __asm__ volatile( "xrstor %0" : : "m"(*xsave), "a" (7), "d" (0) ); - } - else if (cpu_info.ProcessorFeatureBits & CPU_FEATURE_FXSR) - { - __asm__ volatile( "fxrstor %0" : : "m"(xsave->u.xsave) ); - } - else - { - __asm__ volatile( "frstor %0; fwait" : : "m" (xsave->u.fsave) ); - } - set_full_cpu_context(); + x86_thread_data()->syscall_frame->restore_flags |= CONTEXT_INTEGER; } @@ -1092,6 +1022,7 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context ) else xsave->xstate.mask &= ~XSTATE_MASK_GSSE; } + frame->restore_flags |= flags & ~CONTEXT_INTEGER; return STATUS_SUCCESS; } @@ -1660,7 +1591,7 @@ __ASM_GLOBAL_FUNC( call_user_apc_dispatcher, "movl 0xc4(%esi),%eax\n\t" /* context_ptr->Esp */ "jmp 2f\n\t" "1:\tmovl %fs:0x1f8,%eax\n\t" /* x86_thread_data()->syscall_frame */ - "leal 0x38(%eax),%eax\n\t" /* &x86_thread_data()->syscall_frame->ret_addr */ + "leal 0x3c(%eax),%eax\n\t" /* &x86_thread_data()->syscall_frame->ret_addr */ "2:\tsubl $0x2e0,%eax\n\t" /* sizeof(struct apc_stack_layout) */ "movl %ebp,%esp\n\t" /* pop return address */ "cmpl %esp,%eax\n\t" @@ -1700,15 +1631,15 @@ __ASM_GLOBAL_FUNC( call_user_exception_dispatcher, "jne 1f\n\t" "decl 0xb8(%ecx)\n" /* context->Eip */ "1:\tmovl %fs:0x1f8,%eax\n\t" /* x86_thread_data()->syscall_frame */ - "movl 0x1c(%eax),%ebx\n\t" /* frame->ebx */ - "movl 0x28(%eax),%edi\n\t" /* frame->edi */ - "movl 0x2c(%eax),%esi\n\t" /* frame->esi */ - "movl 0x30(%eax),%ebp\n\t" /* frame->ebp */ - "movl %edx,0x30(%eax)\n\t" - "movl %ecx,0x34(%eax)\n\t" + "movl 0x20(%eax),%ebx\n\t" /* frame->ebx */ + "movl 0x2c(%eax),%edi\n\t" /* frame->edi */ + "movl 0x30(%eax),%esi\n\t" /* frame->esi */ + "movl 0x34(%eax),%ebp\n\t" /* frame->ebp */ + "movl %edx,0x34(%eax)\n\t" + "movl %ecx,0x38(%eax)\n\t" "movl 12(%esp),%edx\n\t" /* dispatcher */ "movl $0,%fs:0x1f8\n\t" - "leal 0x30(%eax),%esp\n\t" + "leal 0x34(%eax),%esp\n\t" "jmp *%edx" ) /********************************************************************** diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index 3bd139a2b31..ab2a6f8f315 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -1446,6 +1446,7 @@ static void output_syscall_dispatcher(void) output( "\tmovl %%esi,-0x04(%%ebp)\n" ); output_cfi( ".cfi_rel_offset %%esi,-0x04\n" ); output( "\tpushfl\n" ); + output( "\tpushl $0\n" ); output( "\tmovw %%gs,-0x1a(%%ebp)\n" ); output( "\tmovw %%fs,-0x1c(%%ebp)\n" ); output( "\tmovw %%es,-0x1e(%%ebp)\n" ); @@ -1496,7 +1497,7 @@ static void output_syscall_dispatcher(void) output( "\tjmp 4f\n" ); output( "3:\tfnsave (%%esp)\n" ); output( "\tfwait\n" ); - output( "4:\tleal -0x30(%%ebp),%%ecx\n" ); + output( "4:\tleal -0x34(%%ebp),%%ecx\n" ); output( "\tmovl %%ecx,%%fs:0x1f8\n" ); /* x86_thread_data()->syscall_frame */ output( "\tcmpl 8(%%ebx),%%edx\n" ); /* table->ServiceLimit */ output( "\tjae 6f\n" ); @@ -1514,15 +1515,18 @@ static void output_syscall_dispatcher(void) output( "\tmovl %%ebx,%%esi\n" ); output( "\tcall *(%%eax,%%edx,4)\n" ); output( "5:\tmovl $0,%%fs:0x1f8\n" ); - output( "\tleal -0x2f0(%%ebp),%%ebx\n") ; + output( "\tmovl -0x34(%%ebp),%%ecx\n" ); /* syscall_frame->restore_flags */ + output( "\ttestl $0x68,%%ecx\n" ); /* CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS | CONTEXT_XSAVE */ + output( "\tjz 3f\n" ); + output( "\tleal -0x2f4(%%ebp),%%ebx\n") ; output( "\tandl $~63,%%ebx\n" ); output( "\ttestl $3,%%esi\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */ output( "\tjz 1f\n" ); - output( "\tmovl %%eax,%%ecx\n" ); + output( "\tmovl %%eax,%%edi\n" ); output( "\tmovl $7,%%eax\n" ); output( "\txorl %%edx,%%edx\n" ); output( "\txrstor (%%ebx)\n" ); - output( "\tmovl %%ecx,%%eax\n" ); + output( "\tmovl %%edi,%%eax\n" ); output( "\tjmp 3f\n" ); output( "1:\ttestl $4,%%esi\n" ); /* SYSCALL_HAVE_FXSAVE */ output( "\tjz 2f\n" ); @@ -1530,51 +1534,69 @@ static void output_syscall_dispatcher(void) output( "\tjmp 3f\n" ); output( "2:\tfrstor (%%ebx)\n" ); output( "\tfwait\n" ); - output( "3:\tleal -0x30(%%ebp),%%ebx\n" ); - output_cfi( ".cfi_def_cfa_register %%ebx" ); - output_cfi( ".cfi_adjust_cfa_offset 0x30\n" ); - output( "\tmovl %%eax,0x18(%%ebx)\n" ); - output( "\tmovw 0x16(%%ebx),%%gs\n" ); - output( "\tmovw 0x14(%%ebx),%%fs\n" ); - output( "\tmovw 0x12(%%ebx),%%es\n" ); - output( "\tmovl 0x28(%%ebx),%%edi\n" ); + output( "3:\tmovl -0x08(%%ebp),%%edi\n" ); output_cfi( ".cfi_same_value %%edi" ); - output( "\tmovl 0x2c(%%ebx),%%esi\n" ); + output( "\tmovl -0x04(%%ebp),%%esi\n" ); output_cfi( ".cfi_same_value %%esi" ); + output( "\tmovl -0x14(%%ebp),%%ebx\n" ); + output_cfi( ".cfi_same_value %%ebx" ); + output( "\ttestl $0x7,%%ecx\n" ); /* CONTEXT_CONTROL | CONTEXT_SEGMENTS | CONTEXT_INTEGER */ + output( "\tjnz 1f\n" ); + output( "\tmovl -0x2c(%%ebp),%%ecx\n" ); /* frame->eip */ + output( "\tleal -0x28(%%ebp),%%esp\n" ); /* frame->esp */ output( "\tmovl (%%ebp),%%ebp\n" ); output_cfi( ".cfi_same_value %%ebp" ); - output( "\tmovw %%ss,%%cx\n" ); - output( "\tcmpw 0x0e(%%ebx),%%cx\n" ); + output( "\tpopl %%esp\n" ); + output( "\tjmpl *%%ecx\n" ); + output( "1:\ttestl $0x2,%%ecx\n" ); /* CONTEXT_INTEGER */ + output( "\tjnz 1f\n" ); + output( "\tmovl %%eax,-0x18(%%ebp)\n" ); + output( "\tmovl $0,-0x10(%%ebp)\n" ); + output( "\tmovl $0,-0x0c(%%ebp)\n" ); + output( "1:\tmovw -0x1a(%%ebp),%%gs\n" ); + output( "\tmovw -0x1c(%%ebp),%%fs\n" ); + output( "\tmovw -0x1e(%%ebp),%%es\n" ); + output( "\tleal -0x34(%%ebp),%%ecx\n" ); + output_cfi( ".cfi_def_cfa_register %%ecx" ); + output_cfi( ".cfi_adjust_cfa_offset 0x34\n" ); + output( "\tmovl (%%ebp),%%ebp\n" ); + output_cfi( ".cfi_same_value %%ebp" ); + output( "\tmovw %%ss,%%ax\n" ); + output( "\tcmpw 0x12(%%ecx),%%ax\n" ); output( "\tjne 3f\n" ); /* As soon as we have switched stacks the context structure could * be invalid (when signal handlers are executed for example). Copy * values on the target stack before changing ESP. */ - output( "\tmovl 0x08(%%ebx),%%ecx\n" ); - output( "\tleal -3*4(%%ecx),%%ecx\n" ); - output( "\tmovl (%%ebx),%%edx\n" ); - output( "\tmovl %%edx,2*4(%%ecx)\n" ); - output( "\tmovl 0x0c(%%ebx),%%edx\n" ); - output( "\tmovl %%edx,1*4(%%ecx)\n" ); - output( "\tmovl 0x04(%%ebx),%%edx\n" ); - output( "\tmovl %%edx,0*4(%%ecx)\n" ); - output( "\tpushl 0x10(%%ebx)\n" ); - output( "\tmovl 0x1c(%%ebx),%%ebx\n" ); - output_cfi( ".cfi_same_value %%ebx" ); + output( "\tmovl 0x0c(%%ecx),%%eax\n" ); + output( "\tleal -4*4(%%eax),%%eax\n" ); + output( "\tmovl 0x04(%%ecx),%%edx\n" ); + output( "\tmovl %%edx,3*4(%%eax)\n" ); + output( "\tmovl 0x10(%%ecx),%%edx\n" ); + output( "\tmovl %%edx,2*4(%%eax)\n" ); + output( "\tmovl 0x08(%%ecx),%%edx\n" ); + output( "\tmovl %%edx,1*4(%%eax)\n" ); + output( "\tmovl 0x1c(%%ecx),%%edx\n" ); + output( "\tmovl %%edx,0*4(%%eax)\n" ); + output( "\tpushl 0x14(%%ecx)\n" ); + output( "\tmovl 0x28(%%ecx),%%edx\n" ); + output( "\tmovl 0x24(%%ecx),%%ecx\n" ); output( "\tpopl %%ds\n" ); - output( "\tmovl %%ecx,%%esp\n" ); + output( "\tmovl %%eax,%%esp\n" ); + output( "\tpopl %%eax\n" ); output( "\tiret\n" ); /* Restore the context when the stack segment changes. We can't use * the same code as above because we do not know if the stack segment * is 16 or 32 bit, and 'movl' will throw an exception when we try to * access memory above the limit. */ - output( "\t3:\tmovl 0x18(%%ebx),%%ecx\n" ); - output( "\tmovw 0x0e(%%ebx),%%ss\n" ); - output( "\tmovl 0x08(%%ebx),%%esp\n" ); - output( "\tpushl 0x00(%%ebx)\n" ); - output( "\tpushl 0x0c(%%ebx)\n" ); - output( "\tpushl 0x04(%%ebx)\n" ); - output( "\tpushl 0x10(%%ebx)\n" ); - output( "\tmovl 0x1c(%%ebx),%%ebx\n" ); + output( "3:\tmovl 0x28(%%ecx),%%edx\n" ); + output( "\tmovl 0x1c(%%ecx),%%eax\n" ); + output( "\tmovw 0x12(%%ecx),%%ss\n" ); + output( "\tmovl 0x0c(%%ecx),%%esp\n" ); + output( "\tpushl 0x04(%%ecx)\n" ); + output( "\tpushl 0x10(%%ecx)\n" ); + output( "\tpushl 0x08(%%ecx)\n" ); + output( "\tpushl 0x14(%%ecx)\n" ); + output( "\tmovl 0x24(%%ecx),%%ecx\n" ); output( "\tpopl %%ds\n" ); output( "\tiret\n" ); output( "6:\tmovl $0x%x,%%eax\n", invalid_param );