ntdll: Use a single syscall dispatcher controlled by global flags on i386.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
3d9cb5e4f8
commit
42e42e9085
|
@ -520,7 +520,10 @@ 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;
|
||||
/* flags to control the behavior of the syscall dispatcher */
|
||||
#define SYSCALL_HAVE_XSAVE 1
|
||||
#define SYSCALL_HAVE_XSAVEC 2
|
||||
#define SYSCALL_HAVE_FXSAVE 4
|
||||
|
||||
static inline struct x86_thread_data *x86_thread_data(void)
|
||||
{
|
||||
|
@ -2331,7 +2334,7 @@ NTSTATUS signal_alloc_thread( TEB *teb )
|
|||
}
|
||||
else thread_data->fs = gdt_fs_sel;
|
||||
|
||||
teb->WOW32Reserved = syscall_dispatcher;
|
||||
teb->WOW32Reserved = __wine_syscall_dispatcher;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -2374,6 +2377,10 @@ void signal_init_process(void)
|
|||
{
|
||||
struct sigaction sig_act;
|
||||
|
||||
if (cpu_info.ProcessorFeatureBits & CPU_FEATURE_FXSR) __wine_syscall_flags |= SYSCALL_HAVE_FXSAVE;
|
||||
if (cpu_info.ProcessorFeatureBits & CPU_FEATURE_XSAVE) __wine_syscall_flags |= SYSCALL_HAVE_XSAVE;
|
||||
if (xstate_compaction_enabled) __wine_syscall_flags |= SYSCALL_HAVE_XSAVEC;
|
||||
|
||||
sig_act.sa_mask = server_block_set;
|
||||
sig_act.sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK;
|
||||
#ifdef __ANDROID__
|
||||
|
@ -2409,20 +2416,7 @@ void signal_init_process(void)
|
|||
*/
|
||||
void *signal_init_syscalls(void)
|
||||
{
|
||||
extern void __wine_syscall_dispatcher_fxsave(void) DECLSPEC_HIDDEN;
|
||||
extern void __wine_syscall_dispatcher_xsave(void) DECLSPEC_HIDDEN;
|
||||
extern void __wine_syscall_dispatcher_xsavec(void) DECLSPEC_HIDDEN;
|
||||
|
||||
if (xstate_compaction_enabled)
|
||||
syscall_dispatcher = __wine_syscall_dispatcher_xsavec;
|
||||
else if (cpu_info.ProcessorFeatureBits & CPU_FEATURE_XSAVE)
|
||||
syscall_dispatcher = __wine_syscall_dispatcher_xsave;
|
||||
else if (cpu_info.ProcessorFeatureBits & CPU_FEATURE_FXSR)
|
||||
syscall_dispatcher = __wine_syscall_dispatcher_fxsave;
|
||||
else
|
||||
syscall_dispatcher = __wine_syscall_dispatcher;
|
||||
|
||||
return NtCurrentTeb()->WOW32Reserved = syscall_dispatcher;
|
||||
return NtCurrentTeb()->WOW32Reserved = __wine_syscall_dispatcher;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1421,15 +1421,14 @@ static int cmp_link_name( const void *e1, const void *e2 )
|
|||
|
||||
|
||||
/* output dispatcher for system calls */
|
||||
static void output_syscall_dispatcher( const char *variant )
|
||||
static void output_syscall_dispatcher(void)
|
||||
{
|
||||
const unsigned int invalid_param = 0xc000000d; /* STATUS_INVALID_PARAMETER */
|
||||
const char *symbol = strmake( "__wine_syscall_dispatcher%s", variant );
|
||||
unsigned int i;
|
||||
|
||||
output( "\t.align %d\n", get_alignment(4) );
|
||||
output( "\t%s\n", func_declaration(symbol) );
|
||||
output( "%s\n", asm_globl(symbol) );
|
||||
output( "\t%s\n", func_declaration("__wine_syscall_dispatcher") );
|
||||
output( "%s\n", asm_globl("__wine_syscall_dispatcher") );
|
||||
output_cfi( ".cfi_startproc" );
|
||||
switch (target_cpu)
|
||||
{
|
||||
|
@ -1459,37 +1458,6 @@ static void output_syscall_dispatcher( const char *variant )
|
|||
output( "\tmovl %%ecx,-0x2c(%%ebp)\n" ); /* frame->eip */
|
||||
output( "\tsubl $0x2c0,%%esp\n") ;
|
||||
output( "\tandl $~63,%%esp\n" );
|
||||
if (!*variant)
|
||||
{
|
||||
output( "\tfnsave (%%esp)\n" );
|
||||
output( "\tfwait\n" );
|
||||
}
|
||||
else if(!strcmp( variant, "_fxsave" ))
|
||||
{
|
||||
output( "\tfxsave (%%esp)\n" );
|
||||
}
|
||||
else if(!strcmp( variant, "_xsave" ))
|
||||
{
|
||||
output( "\tmovl %%eax,%%ecx\n ");
|
||||
output( "\tmovl $7,%%eax\n" );
|
||||
output( "\txorl %%edx,%%edx\n" );
|
||||
for (i = 0; i < 6; i++)
|
||||
output( "\tmovl %%edx,0x%x(%%esp)\n", 0x200 + i * 4 );
|
||||
output( "\txsave (%%esp)\n" );
|
||||
output( "\tmovl %%ecx,%%eax\n ");
|
||||
}
|
||||
else /* _xsavec */
|
||||
{
|
||||
output( "\tmovl %%eax,%%ecx\n ");
|
||||
output( "\tmovl $7,%%eax\n" );
|
||||
output( "\txorl %%edx,%%edx\n" );
|
||||
for (i = 0; i < 16; i++)
|
||||
output( "\tmovl %%edx,0x%x(%%esp)\n", 0x200 + i * 4 );
|
||||
output( "\txsavec (%%esp)\n" );
|
||||
output( "\tmovl %%ecx,%%eax\n ");
|
||||
}
|
||||
output( "\tleal -0x30(%%ebp),%%ecx\n" );
|
||||
output( "\tmovl %%ecx,%%fs:0x1f8\n" ); /* x86_thread_data()->syscall_frame */
|
||||
output( "\tmovl %%eax,%%ecx\n" );
|
||||
output( "\tshrl $8,%%ecx\n" );
|
||||
output( "\tandl $0x30,%%ecx\n" ); /* syscall table number */
|
||||
|
@ -1499,14 +1467,43 @@ static void output_syscall_dispatcher( const char *variant )
|
|||
{
|
||||
output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
|
||||
output( "1:\tleal %s-1b(%%eax,%%ecx),%%ebx\n", asm_name("KeServiceDescriptorTable") );
|
||||
output( "\tmovl %s-1b(%%eax),%%esi\n", asm_name("__wine_syscall_flags") );
|
||||
needs_get_pc_thunk = 1;
|
||||
}
|
||||
else output( "\tleal %s(%%ecx),%%ebx\n", asm_name("KeServiceDescriptorTable") );
|
||||
|
||||
else
|
||||
{
|
||||
output( "\tleal %s(%%ecx),%%ebx\n", asm_name("KeServiceDescriptorTable") );
|
||||
output( "\tmovl %s,%%esi\n", asm_name("__wine_syscall_flags") );
|
||||
}
|
||||
output( "\ttestl $3,%%esi\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
|
||||
output( "\tjz 2f\n" );
|
||||
output( "\tmovl %%edx,%%ecx\n ");
|
||||
output( "\tmovl $7,%%eax\n" );
|
||||
output( "\txorl %%edx,%%edx\n" );
|
||||
for (i = 0; i < 6; i++) output( "\tmovl %%edx,0x%x(%%esp)\n", 0x200 + i * 4 );
|
||||
output( "\ttestl $2,%%esi\n" ); /* SYSCALL_HAVE_XSAVEC */
|
||||
output( "\tjz 1f\n" );
|
||||
for (i = 6; i < 16; i++) output( "\tmovl %%edx,0x%x(%%esp)\n", 0x200 + i * 4 );
|
||||
output( "\txsavec (%%esp)\n" );
|
||||
output( "\tmovl %%ecx,%%edx\n ");
|
||||
output( "\tjmp 4f\n" );
|
||||
output( "1:\txsave (%%esp)\n" );
|
||||
output( "\tmovl %%ecx,%%edx\n ");
|
||||
output( "\tjmp 4f\n" );
|
||||
output( "2:\ttestl $4,%%esi\n" ); /* SYSCALL_HAVE_FXSAVE */
|
||||
output( "\tjz 3f\n" );
|
||||
output( "\tfxsave (%%esp)\n" );
|
||||
output( "\tjmp 4f\n" );
|
||||
output( "3:\tfnsave (%%esp)\n" );
|
||||
output( "\tfwait\n" );
|
||||
output( "4:\tleal -0x30(%%ebp),%%ecx\n" );
|
||||
output( "\tmovl %%ecx,%%fs:0x1f8\n" ); /* x86_thread_data()->syscall_frame */
|
||||
output( "\tcmpl 8(%%ebx),%%edx\n" ); /* table->ServiceLimit */
|
||||
output( "\tjae 4f\n" );
|
||||
output( "\tjae 6f\n" );
|
||||
output( "\tmovl 12(%%ebx),%%eax\n" ); /* table->ArgumentTable */
|
||||
output( "\tmovzbl (%%eax,%%edx,1),%%ecx\n" );
|
||||
output( "\tmovl (%%ebx),%%eax\n" ); /* table->ServiceTable */
|
||||
output( "\tmovl %%esi,%%ebx\n" );
|
||||
output( "\tsubl %%ecx,%%esp\n" );
|
||||
output( "\tshrl $2,%%ecx\n" );
|
||||
output( "\tleal 12(%%ebp),%%esi\n" );
|
||||
|
@ -1514,29 +1511,26 @@ static void output_syscall_dispatcher( const char *variant )
|
|||
output( "\tmovl %%esp,%%edi\n" );
|
||||
output( "\tcld\n" );
|
||||
output( "\trep; movsl\n" );
|
||||
output( "\tmovl (%%ebx),%%eax\n" ); /* table->ServiceTable */
|
||||
output( "\tmovl %%ebx,%%esi\n" );
|
||||
output( "\tcall *(%%eax,%%edx,4)\n" );
|
||||
output( "2:\tmovl $0,%%fs:0x1f8\n" );
|
||||
output( "5:\tmovl $0,%%fs:0x1f8\n" );
|
||||
output( "\tleal -0x2f0(%%ebp),%%ebx\n") ;
|
||||
output( "\tandl $~63,%%ebx\n" );
|
||||
if (!*variant)
|
||||
{
|
||||
output( "\tfrstor (%%ebx)\n" );
|
||||
output( "\tfwait\n" );
|
||||
}
|
||||
else if(!strcmp( variant, "_fxsave" ))
|
||||
{
|
||||
output( "\tfxrstor (%%ebx)\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
output( "\tmovl %%eax,%%ecx\n" );
|
||||
output( "\tmovl $7,%%eax\n" );
|
||||
output( "\txorl %%edx,%%edx\n" );
|
||||
output( "\txrstor (%%ebx)\n" );
|
||||
output( "\tmovl %%ecx,%%eax\n" );
|
||||
}
|
||||
output( "\tleal -0x30(%%ebp),%%ebx\n" );
|
||||
output( "\ttestl $3,%%esi\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
|
||||
output( "\tjz 1f\n" );
|
||||
output( "\tmovl %%eax,%%ecx\n" );
|
||||
output( "\tmovl $7,%%eax\n" );
|
||||
output( "\txorl %%edx,%%edx\n" );
|
||||
output( "\txrstor (%%ebx)\n" );
|
||||
output( "\tmovl %%ecx,%%eax\n" );
|
||||
output( "\tjmp 3f\n" );
|
||||
output( "1:\ttestl $4,%%esi\n" ); /* SYSCALL_HAVE_FXSAVE */
|
||||
output( "\tjz 2f\n" );
|
||||
output( "\tfxrstor (%%ebx)\n" );
|
||||
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" );
|
||||
|
@ -1583,8 +1577,8 @@ static void output_syscall_dispatcher( const char *variant )
|
|||
output( "\tmovl 0x1c(%%ebx),%%ebx\n" );
|
||||
output( "\tpopl %%ds\n" );
|
||||
output( "\tiret\n" );
|
||||
output( "4:\tmovl $0x%x,%%eax\n", invalid_param );
|
||||
output( "\tjmp 2b\n" );
|
||||
output( "6:\tmovl $0x%x,%%eax\n", invalid_param );
|
||||
output( "\tjmp 5b\n" );
|
||||
break;
|
||||
case CPU_x86_64:
|
||||
output( "\tpushq %%rbp\n" );
|
||||
|
@ -1822,7 +1816,7 @@ static void output_syscall_dispatcher( const char *variant )
|
|||
assert(0);
|
||||
}
|
||||
output_cfi( ".cfi_endproc" );
|
||||
output_function_size( symbol );
|
||||
output_function_size( "__wine_syscall_dispatcher" );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1847,18 +1841,8 @@ void output_syscalls( DLLSPEC *spec )
|
|||
|
||||
if (unix_lib)
|
||||
{
|
||||
output_syscall_dispatcher( "" );
|
||||
output_syscall_dispatcher();
|
||||
|
||||
switch( target_cpu )
|
||||
{
|
||||
case CPU_x86:
|
||||
output_syscall_dispatcher( "_fxsave" );
|
||||
output_syscall_dispatcher( "_xsave" );
|
||||
output_syscall_dispatcher( "_xsavec" );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
output( "\t.data\n" );
|
||||
output( "\t.align %d\n", get_alignment( get_ptr_size() ) );
|
||||
output( "%s\n", asm_globl("KeServiceDescriptorTable") );
|
||||
|
|
Loading…
Reference in New Issue