Store %gs in the TEB on every call to 16-bit code, and don't restore
it from the TEB for signals that did not happen in 16-bit code.
This commit is contained in:
parent
c342de17b8
commit
78675ba234
|
@ -147,12 +147,14 @@ __ASM_GLOBAL_FUNC(vm86_enter,
|
||||||
"pushl %ebx\n\t"
|
"pushl %ebx\n\t"
|
||||||
"movl $1,%ebx\n\t" /*VM86_ENTER*/
|
"movl $1,%ebx\n\t" /*VM86_ENTER*/
|
||||||
"pushl %ecx\n\t" /* put vm86plus_struct ptr somewhere we can find it */
|
"pushl %ecx\n\t" /* put vm86plus_struct ptr somewhere we can find it */
|
||||||
|
"pushl %gs\n\t"
|
||||||
"pushl %fs\n\t"
|
"pushl %fs\n\t"
|
||||||
"int $0x80\n"
|
"int $0x80\n"
|
||||||
".globl " __ASM_NAME("vm86_return") "\n\t"
|
".globl " __ASM_NAME("vm86_return") "\n\t"
|
||||||
__ASM_FUNC("vm86_return") "\n"
|
__ASM_FUNC("vm86_return") "\n"
|
||||||
__ASM_NAME("vm86_return") ":\n\t"
|
__ASM_NAME("vm86_return") ":\n\t"
|
||||||
"popl %fs\n\t"
|
"popl %fs\n\t"
|
||||||
|
"popl %gs\n\t"
|
||||||
"popl %ecx\n\t"
|
"popl %ecx\n\t"
|
||||||
"popl %ebx\n\t"
|
"popl %ebx\n\t"
|
||||||
"popl %ebp\n\t"
|
"popl %ebp\n\t"
|
||||||
|
@ -538,14 +540,17 @@ static void restore_vm86_context( const CONTEXT *context, struct vm86plus_struct
|
||||||
*/
|
*/
|
||||||
static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
|
static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
|
||||||
{
|
{
|
||||||
WORD fs;
|
/* get %fs and %gs at time of the fault */
|
||||||
/* get %fs at time of the fault */
|
|
||||||
#ifdef FS_sig
|
#ifdef FS_sig
|
||||||
fs = FS_sig(sigcontext);
|
context->SegFs = LOWORD(FS_sig(sigcontext));
|
||||||
#else
|
#else
|
||||||
fs = wine_get_fs();
|
context->SegFs = wine_get_fs();
|
||||||
|
#endif
|
||||||
|
#ifdef GS_sig
|
||||||
|
context->SegGs = LOWORD(GS_sig(sigcontext));
|
||||||
|
#else
|
||||||
|
context->SegGs = wine_get_gs();
|
||||||
#endif
|
#endif
|
||||||
context->SegFs = fs;
|
|
||||||
|
|
||||||
/* now restore a proper %fs for the fault handler */
|
/* now restore a proper %fs for the fault handler */
|
||||||
if (!IS_SELECTOR_SYSTEM(CS_sig(sigcontext)) ||
|
if (!IS_SELECTOR_SYSTEM(CS_sig(sigcontext)) ||
|
||||||
|
@ -558,28 +563,36 @@ static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
|
||||||
* SS is still non-system segment. This is why both CS and SS
|
* SS is still non-system segment. This is why both CS and SS
|
||||||
* are checked.
|
* are checked.
|
||||||
*/
|
*/
|
||||||
fs = SYSLEVEL_Win16CurrentTeb;
|
wine_set_fs( SYSLEVEL_Win16CurrentTeb );
|
||||||
|
wine_set_gs( NtCurrentTeb()->gs_sel );
|
||||||
}
|
}
|
||||||
#ifdef __HAVE_VM86
|
#ifdef __HAVE_VM86
|
||||||
else if ((void *)EIP_sig(sigcontext) == vm86_return) /* vm86 mode */
|
else if ((void *)EIP_sig(sigcontext) == vm86_return) /* vm86 mode */
|
||||||
{
|
{
|
||||||
|
unsigned int *stack = (unsigned int *)ESP_sig(sigcontext);
|
||||||
|
|
||||||
/* fetch the saved %fs on the stack */
|
/* fetch the saved %fs on the stack */
|
||||||
fs = *(unsigned int *)ESP_sig(sigcontext);
|
wine_set_fs( stack[0] );
|
||||||
|
wine_set_gs( stack[1] );
|
||||||
if (EAX_sig(sigcontext) == VM86_EAX) {
|
if (EAX_sig(sigcontext) == VM86_EAX) {
|
||||||
struct vm86plus_struct *vm86;
|
|
||||||
wine_set_fs(fs);
|
|
||||||
/* retrieve pointer to vm86plus struct that was stored in vm86_enter
|
/* retrieve pointer to vm86plus struct that was stored in vm86_enter
|
||||||
* (but we could also get if from teb->vm86_ptr) */
|
* (but we could also get if from teb->vm86_ptr) */
|
||||||
vm86 = *(struct vm86plus_struct **)(ESP_sig(sigcontext) + sizeof(int));
|
struct vm86plus_struct *vm86 = (struct vm86plus_struct *)stack[2];
|
||||||
/* get context from vm86 struct */
|
/* get context from vm86 struct */
|
||||||
save_vm86_context( context, vm86 );
|
save_vm86_context( context, vm86 );
|
||||||
wine_set_gs( NtCurrentTeb()->gs_sel );
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* __HAVE_VM86 */
|
#endif /* __HAVE_VM86 */
|
||||||
|
else /* 32-bit mode */
|
||||||
wine_set_fs(fs);
|
{
|
||||||
|
#ifdef FS_sig
|
||||||
|
wine_set_fs( FS_sig(sigcontext) );
|
||||||
|
#endif
|
||||||
|
#ifdef GS_sig
|
||||||
|
wine_set_gs( GS_sig(sigcontext) );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
context->Eax = EAX_sig(sigcontext);
|
context->Eax = EAX_sig(sigcontext);
|
||||||
context->Ebx = EBX_sig(sigcontext);
|
context->Ebx = EBX_sig(sigcontext);
|
||||||
|
@ -595,12 +608,6 @@ static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext )
|
||||||
context->SegDs = LOWORD(DS_sig(sigcontext));
|
context->SegDs = LOWORD(DS_sig(sigcontext));
|
||||||
context->SegEs = LOWORD(ES_sig(sigcontext));
|
context->SegEs = LOWORD(ES_sig(sigcontext));
|
||||||
context->SegSs = LOWORD(SS_sig(sigcontext));
|
context->SegSs = LOWORD(SS_sig(sigcontext));
|
||||||
#ifdef GS_sig
|
|
||||||
context->SegGs = LOWORD(GS_sig(sigcontext));
|
|
||||||
#else
|
|
||||||
context->SegGs = wine_get_gs();
|
|
||||||
#endif
|
|
||||||
wine_set_gs( NtCurrentTeb()->gs_sel );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -617,9 +624,10 @@ static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
|
||||||
IS_SELECTOR_SYSTEM(CS_sig(sigcontext)) &&
|
IS_SELECTOR_SYSTEM(CS_sig(sigcontext)) &&
|
||||||
EAX_sig(sigcontext) == VM86_EAX)
|
EAX_sig(sigcontext) == VM86_EAX)
|
||||||
{
|
{
|
||||||
|
unsigned int *stack = (unsigned int *)ESP_sig(sigcontext);
|
||||||
/* retrieve pointer to vm86plus struct that was stored in vm86_enter
|
/* retrieve pointer to vm86plus struct that was stored in vm86_enter
|
||||||
* (but we could also get it from teb->vm86_ptr) */
|
* (but we could also get it from teb->vm86_ptr) */
|
||||||
struct vm86plus_struct *vm86 = *(struct vm86plus_struct **)(ESP_sig(sigcontext) + sizeof(int));
|
struct vm86plus_struct *vm86 = (struct vm86plus_struct *)stack[2];
|
||||||
restore_vm86_context( context, vm86 );
|
restore_vm86_context( context, vm86 );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -664,21 +672,25 @@ static void init_handler( const SIGCONTEXT *sigcontext )
|
||||||
!IS_SELECTOR_SYSTEM(SS_sig(sigcontext))) /* 16-bit mode */
|
!IS_SELECTOR_SYSTEM(SS_sig(sigcontext))) /* 16-bit mode */
|
||||||
{
|
{
|
||||||
wine_set_fs( SYSLEVEL_Win16CurrentTeb );
|
wine_set_fs( SYSLEVEL_Win16CurrentTeb );
|
||||||
|
wine_set_gs( NtCurrentTeb()->gs_sel );
|
||||||
}
|
}
|
||||||
#ifdef __HAVE_VM86
|
#ifdef __HAVE_VM86
|
||||||
else if ((void *)EIP_sig(sigcontext) == vm86_return) /* vm86 mode */
|
else if ((void *)EIP_sig(sigcontext) == vm86_return) /* vm86 mode */
|
||||||
{
|
{
|
||||||
/* fetch the saved %fs on the stack */
|
/* fetch the saved %fs on the stack */
|
||||||
wine_set_fs( *(unsigned int *)ESP_sig(sigcontext) );
|
wine_set_fs( *(unsigned int *)ESP_sig(sigcontext) );
|
||||||
|
wine_set_gs( NtCurrentTeb()->gs_sel );
|
||||||
}
|
}
|
||||||
#endif /* __HAVE_VM86 */
|
#endif /* __HAVE_VM86 */
|
||||||
#ifdef FS_sig
|
|
||||||
else /* 32-bit mode, get %fs at time of the fault */
|
else /* 32-bit mode, get %fs at time of the fault */
|
||||||
{
|
{
|
||||||
|
#ifdef FS_sig
|
||||||
wine_set_fs( FS_sig(sigcontext) );
|
wine_set_fs( FS_sig(sigcontext) );
|
||||||
|
#endif
|
||||||
|
#ifdef GS_sig
|
||||||
|
wine_set_gs( GS_sig(sigcontext) );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif /* FS_sig */
|
|
||||||
wine_set_gs( NtCurrentTeb()->gs_sel );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,6 @@ void SYSDEPS_SetCurThread( TEB *teb )
|
||||||
wine_ldt_set_limit( &fs_entry, 0xfff );
|
wine_ldt_set_limit( &fs_entry, 0xfff );
|
||||||
wine_ldt_set_flags( &fs_entry, WINE_LDT_FLAGS_DATA|WINE_LDT_FLAGS_32BIT );
|
wine_ldt_set_flags( &fs_entry, WINE_LDT_FLAGS_DATA|WINE_LDT_FLAGS_32BIT );
|
||||||
wine_ldt_init_fs( teb->teb_sel, &fs_entry );
|
wine_ldt_init_fs( teb->teb_sel, &fs_entry );
|
||||||
teb->gs_sel = wine_get_gs();
|
|
||||||
#elif defined(__powerpc__)
|
#elif defined(__powerpc__)
|
||||||
/* On PowerPC, the current TEB is in the gpr13 register */
|
/* On PowerPC, the current TEB is in the gpr13 register */
|
||||||
__asm__ __volatile__("mr 2, %0" : : "r" (teb));
|
__asm__ __volatile__("mr 2, %0" : : "r" (teb));
|
||||||
|
|
|
@ -489,6 +489,7 @@ static void BuildCallTo16Core( FILE *outfile, int reg_func )
|
||||||
fprintf( outfile, "\tpushl %%edx\n" );
|
fprintf( outfile, "\tpushl %%edx\n" );
|
||||||
fprintf( outfile, "\tpushl %%esi\n" );
|
fprintf( outfile, "\tpushl %%esi\n" );
|
||||||
fprintf( outfile, "\tpushl %%edi\n" );
|
fprintf( outfile, "\tpushl %%edi\n" );
|
||||||
|
fprintf( outfile, "\t.byte 0x64\n\tmovl %%gs,(%d)\n", STRUCTOFFSET(TEB,gs_sel) );
|
||||||
|
|
||||||
if ( UsePIC )
|
if ( UsePIC )
|
||||||
{
|
{
|
||||||
|
@ -672,6 +673,8 @@ static void BuildCallTo16Core( FILE *outfile, int reg_func )
|
||||||
fprintf( outfile, "\tmovw %%ax,%%es\n" );
|
fprintf( outfile, "\tmovw %%ax,%%es\n" );
|
||||||
fprintf( outfile, "\tmovl %d(%%edx),%%eax\n", CONTEXTOFFSET(SegFs) );
|
fprintf( outfile, "\tmovl %d(%%edx),%%eax\n", CONTEXTOFFSET(SegFs) );
|
||||||
fprintf( outfile, "\tmovw %%ax,%%fs\n" );
|
fprintf( outfile, "\tmovw %%ax,%%fs\n" );
|
||||||
|
fprintf( outfile, "\tmovl %d(%%edx),%%eax\n", CONTEXTOFFSET(SegGs) );
|
||||||
|
fprintf( outfile, "\tmovw %%ax,%%gs\n" );
|
||||||
fprintf( outfile, "\tmovl %d(%%edx),%%ebp\n", CONTEXTOFFSET(Ebp) );
|
fprintf( outfile, "\tmovl %d(%%edx),%%ebp\n", CONTEXTOFFSET(Ebp) );
|
||||||
fprintf( outfile, "\tmovl %d(%%edx),%%esi\n", CONTEXTOFFSET(Esi) );
|
fprintf( outfile, "\tmovl %d(%%edx),%%esi\n", CONTEXTOFFSET(Esi) );
|
||||||
fprintf( outfile, "\tmovl %d(%%edx),%%edi\n", CONTEXTOFFSET(Edi) );
|
fprintf( outfile, "\tmovl %d(%%edx),%%edi\n", CONTEXTOFFSET(Edi) );
|
||||||
|
@ -688,9 +691,11 @@ static void BuildCallTo16Core( FILE *outfile, int reg_func )
|
||||||
/* Push the called routine address */
|
/* Push the called routine address */
|
||||||
fprintf( outfile, "\tpushl %d(%%edx)\n", STACK32OFFSET(target) );
|
fprintf( outfile, "\tpushl %d(%%edx)\n", STACK32OFFSET(target) );
|
||||||
|
|
||||||
/* Set %fs to the value saved by the last CallFrom16 */
|
/* Set %fs and %gs to the value saved by the last CallFrom16 */
|
||||||
fprintf( outfile, "\tmovw %d(%%ebp),%%ax\n", STACK16OFFSET(fs)-STACK16OFFSET(bp) );
|
fprintf( outfile, "\tmovw %d(%%ebp),%%ax\n", STACK16OFFSET(fs)-STACK16OFFSET(bp) );
|
||||||
fprintf( outfile, "\tmovw %%ax,%%fs\n" );
|
fprintf( outfile, "\tmovw %%ax,%%fs\n" );
|
||||||
|
fprintf( outfile, "\tmovw %d(%%ebp),%%ax\n", STACK16OFFSET(gs)-STACK16OFFSET(bp) );
|
||||||
|
fprintf( outfile, "\tmovw %%ax,%%gs\n" );
|
||||||
|
|
||||||
/* Set %ds and %es (and %ax just in case) equal to %ss */
|
/* Set %ds and %es (and %ax just in case) equal to %ss */
|
||||||
fprintf( outfile, "\tmovw %%ss,%%ax\n" );
|
fprintf( outfile, "\tmovw %%ss,%%ax\n" );
|
||||||
|
|
Loading…
Reference in New Issue