mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-14 16:07:20 +00:00
ntdll: Only restore the modified parts of the syscall frame on i386.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
32f1bfd0f0
commit
050378d4d7
|
@ -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" )
|
||||
|
||||
/**********************************************************************
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in a new issue