vm86 signal patch
Ove Kaaven
ovek at arcticnet.no
Fri Dec 28 04:20:53 CST 2001
Well, it looked like I got all the race conditions fixed in this thing a
few weeks ago, may as well submit it now. (I could have made this code a
lot simpler if the vm86 syscall would check for VIF|VIP on entry by
itself, but noo, so I still need to throw from the signal handler...)
For some reason DOS games still performed quite bad in my restructured
code last time I checked (possibly a number of SIGALRMs are just lost or
something), but perhaps I should just submit that DOS restructure anyway,
might be better than nothing?
Log:
Fixed vm86_enter race conditions.
Index: include/thread.h
===================================================================
RCS file: /home/wine/wine/include/thread.h,v
retrieving revision 1.56
diff -u -r1.56 thread.h
--- include/thread.h 2001/11/30 18:46:46 1.56
+++ include/thread.h 2001/12/28 08:23:52
@@ -101,11 +101,10 @@
DWORD alarms; /* --3 22c Data for vm86 mode */
DWORD vm86_pending; /* --3 230 Data for vm86 mode */
void *vm86_ptr; /* --3 234 Data for vm86 mode */
- void *vm86_ctx; /* --3 238 Data for vm86 mode */
/* here is plenty space for wine specific fields (don't forget to change pad6!!) */
/* the following are nt specific fields */
- DWORD pad6[623]; /* --n 23c */
+ DWORD pad6[624]; /* --n 23c */
UNICODE_STRING StaticUnicodeString; /* -2- bf8 used by advapi32 */
USHORT StaticUnicodeBuffer[261]; /* -2- c00 used by advapi32 */
DWORD pad7; /* --n e0c */
Index: dlls/ntdll/signal_i386.c
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/signal_i386.c,v
retrieving revision 1.30
diff -u -r1.30 signal_i386.c
--- dlls/ntdll/signal_i386.c 2001/10/28 21:16:22 1.30
+++ dlls/ntdll/signal_i386.c 2001/12/28 08:23:53
@@ -115,13 +115,16 @@
}
#endif
-int vm86_enter( struct vm86plus_struct *ptr );
-void vm86_return();
+#define VM86_EAX 0 /* the %eax value while vm86_enter is executing */
+
+int vm86_enter(void);
+void vm86_return(void);
+void vm86_return_end(void);
__ASM_GLOBAL_FUNC(vm86_enter,
"pushl %ebp\n\t"
"movl %esp, %ebp\n\t"
"movl $166,%eax\n\t" /*SYS_vm86*/
- "movl 8(%ebp),%ecx\n\t"
+ ".byte 0x64\n\tmovl (0x234),%ecx\n\t" /* vm86_ptr */
"pushl %ebx\n\t"
"movl $1,%ebx\n\t" /*VM86_ENTER*/
"pushl %ecx\n\t" /* put vm86plus_struct ptr somewhere we can find it */
@@ -134,6 +137,16 @@
"popl %ecx\n\t"
"popl %ebx\n\t"
"popl %ebp\n\t"
+ "testl %eax,%eax\n\t"
+ "jl 0f\n\t"
+ "cmpb $0,%al\n\t" /* VM86_SIGNAL */
+ "je " __ASM_NAME("vm86_enter") "\n\t"
+ "0:\n\t"
+ "xorl %ecx,%ecx\n\t"
+ ".byte 0x64\n\tmovl %ecx,(0x234)\n\t" /* vm86_ptr */
+ ".globl " __ASM_NAME("vm86_return_end") "\n\t"
+ ".type " __ASM_NAME("vm86_return_end") ", at function\n"
+ __ASM_NAME("vm86_return_end") ":\n\t"
"ret" );
#define __HAVE_VM86
@@ -474,14 +487,18 @@
#ifdef __HAVE_VM86
else if ((void *)EIP_sig(sigcontext) == vm86_return) /* vm86 mode */
{
- /* retrieve pointer to vm86plus struct that was stored in vm86_enter */
- struct vm86plus_struct *vm86 = *(struct vm86plus_struct **)(ESP_sig(sigcontext) + sizeof(int));
/* fetch the saved %fs on the stack */
fs = *(unsigned int *)ESP_sig(sigcontext);
- __set_fs(fs);
- /* get context from vm86 struct */
- save_vm86_context( context, vm86 );
- return;
+ if (EAX_sig(sigcontext) == VM86_EAX) {
+ struct vm86plus_struct *vm86;
+ __set_fs(fs);
+ /* retrieve pointer to vm86plus struct that was stored in vm86_enter
+ * (but we could also get if from teb->vm86_ptr) */
+ vm86 = *(struct vm86plus_struct **)(ESP_sig(sigcontext) + sizeof(int));
+ /* get context from vm86 struct */
+ save_vm86_context( context, vm86 );
+ return;
+ }
}
#endif /* __HAVE_VM86 */
@@ -519,9 +536,11 @@
#ifdef __HAVE_VM86
/* check if exception occurred in vm86 mode */
if ((void *)EIP_sig(sigcontext) == vm86_return &&
- IS_SELECTOR_SYSTEM(CS_sig(sigcontext)))
+ IS_SELECTOR_SYSTEM(CS_sig(sigcontext)) &&
+ EAX_sig(sigcontext) == VM86_EAX)
{
- /* 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) */
struct vm86plus_struct *vm86 = *(struct vm86plus_struct **)(ESP_sig(sigcontext) + sizeof(int));
restore_vm86_context( context, vm86 );
return;
@@ -807,8 +826,10 @@
if (context->EFlags & VIF_MASK) {
/* VIF is set, throw exception */
teb->vm86_pending = 0;
+ teb->vm86_ptr = NULL;
rec.ExceptionAddress = (LPVOID)context->Eip;
EXC_RtlRaiseException( &rec, context );
+ teb->vm86_ptr = vm86;
}
}
else if (vm86)
@@ -816,18 +837,22 @@
/* not in VM86, but possibly setting up for it */
if (vm86->regs.eflags & VIP_MASK) return;
vm86->regs.eflags |= VIP_MASK;
+ if (((char*)context->Eip >= (char*)vm86_return) &&
+ ((char*)context->Eip <= (char*)vm86_return_end) &&
+ (VM86_TYPE(context->Eax) != VM86_SIGNAL)) {
+ /* exiting from VM86, can't throw */
+ return;
+ }
if (vm86->regs.eflags & VIF_MASK) {
/* VIF is set, throw exception */
CONTEXT vcontext;
teb->vm86_pending = 0;
+ teb->vm86_ptr = NULL;
save_vm86_context( &vcontext, vm86 );
rec.ExceptionAddress = (LPVOID)vcontext.Eip;
EXC_RtlRaiseException( &rec, &vcontext );
+ teb->vm86_ptr = vm86;
restore_vm86_context( &vcontext, vm86 );
- if (teb->vm86_ctx) {
- /* must also save here */
- *(CONTEXT*)(teb->vm86_ctx) = vcontext;
- }
}
}
}
@@ -1065,7 +1090,7 @@
do
{
- res = vm86_enter( &vm86 );
+ res = vm86_enter(); /* uses and clears teb->vm86_ptr */
if (res < 0)
{
errno = -res;
@@ -1073,10 +1098,7 @@
}
} while (VM86_TYPE(res) == VM86_SIGNAL);
- teb->vm86_ctx = context;
save_vm86_context( context, &vm86 );
- teb->vm86_ptr = NULL;
- teb->vm86_ctx = NULL;
context->EFlags |= teb->vm86_pending;
switch(VM86_TYPE(res))
More information about the wine-patches
mailing list