Commit bc8a22cc307ebd9a2577c8fffcb90000724f72f3

Authored by bellard
1 parent f631ef9b

better vm86 support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@69 c046a42c-6fe2-441c-8c8c-71466251a162
Changelog
  1 +version 0.1.4:
  2 +
  3 + - more accurate VM86 emulation (can launch small DOS 16 bit
  4 + executables in wine).
  5 + - fixed push/pop fs/gs
  6 + - added iret instruction.
  7 +
  8 +version 0.1.3:
  9 +
  10 + - S390 support (Ulrich Weigand)
  11 + - glibc 2.3.x compile fix (Ulrich Weigand)
  12 + - socketcall endian fix (Ulrich Weigand)
  13 + - struct sockaddr endian fix (Ulrich Weigand)
  14 + - sendmsg/recvmsg endian fix (Ulrich Weigand)
  15 + - execve endian fix (Ulrich Weigand)
  16 + - fdset endian fix (Ulrich Weigand)
  17 + - partial setsockopt syscall support (Ulrich Weigand)
  18 + - more accurate pushf/popf emulation
  19 + - first partial vm86() syscall support (can be used with runcom example).
  20 + - added bound, cmpxchg8b, cpuid instructions
  21 + - added 16 bit addressing support/override for string operations
  22 + - poll() fix
  23 +
  24 +version 0.1.2:
  25 +
  26 + - compile fixes
  27 + - xlat instruction
  28 + - xchg instruction memory lock
  29 + - added simple vm86 example (not working with QEMU yet). The 54 byte
  30 + DOS executable 'pi_10.com' program was released by Bertram
  31 + Felgenhauer (more information at http://www.boo.net/~jasonp/pipage.html).
  32 +
1 version 0.1.1: 33 version 0.1.1:
2 34
3 - glibc 2.2 compilation fixes 35 - glibc 2.2 compilation fixes
4 - added -s and -L options 36 - added -s and -L options
5 - binary distribution of x86 glibc and wine 37 - binary distribution of x86 glibc and wine
  38 + - big endian fixes in ELF loader and getdents.
6 39
7 version 0.1: 40 version 0.1:
8 41
  1 +- fix thread locks
  2 +- fix thread stack liberation
  3 +- fix x86 stack allocation
1 - optimize translated cache chaining (DLL PLT-like system) 4 - optimize translated cache chaining (DLL PLT-like system)
2 - more syscalls (in particular all 64 bit ones, IPCs, fix 64 bit 5 - more syscalls (in particular all 64 bit ones, IPCs, fix 64 bit
3 issues, fix 16 bit uid issues) 6 issues, fix 16 bit uid issues)
4 - finish signal handing (fp87 state, more siginfo conversions) 7 - finish signal handing (fp87 state, more siginfo conversions)
5 - verify thread support (clone() and various locks) 8 - verify thread support (clone() and various locks)
6 -- vm86 syscall support  
7 - overrides/16bit for string ops 9 - overrides/16bit for string ops
8 - make it self runnable (use same trick as ld.so : include its own relocator and libc) 10 - make it self runnable (use same trick as ld.so : include its own relocator and libc)
9 -- improved 16 bit support  
10 - fix FPU exceptions (in particular: gen_op_fpush not before mem load) 11 - fix FPU exceptions (in particular: gen_op_fpush not before mem load)
cpu-i386.h
@@ -68,24 +68,24 @@ @@ -68,24 +68,24 @@
68 #define VIP_MASK 0x00100000 68 #define VIP_MASK 0x00100000
69 #define ID_MASK 0x00200000 69 #define ID_MASK 0x00200000
70 70
71 -#define EXCP00_DIVZ 1  
72 -#define EXCP01_SSTP 2  
73 -#define EXCP02_NMI 3  
74 -#define EXCP03_INT3 4  
75 -#define EXCP04_INTO 5  
76 -#define EXCP05_BOUND 6  
77 -#define EXCP06_ILLOP 7  
78 -#define EXCP07_PREX 8  
79 -#define EXCP08_DBLE 9  
80 -#define EXCP09_XERR 10  
81 -#define EXCP0A_TSS 11  
82 -#define EXCP0B_NOSEG 12  
83 -#define EXCP0C_STACK 13  
84 -#define EXCP0D_GPF 14  
85 -#define EXCP0E_PAGE 15  
86 -#define EXCP10_COPR 17  
87 -#define EXCP11_ALGN 18  
88 -#define EXCP12_MCHK 19 71 +#define EXCP00_DIVZ 0
  72 +#define EXCP01_SSTP 1
  73 +#define EXCP02_NMI 2
  74 +#define EXCP03_INT3 3
  75 +#define EXCP04_INTO 4
  76 +#define EXCP05_BOUND 5
  77 +#define EXCP06_ILLOP 6
  78 +#define EXCP07_PREX 7
  79 +#define EXCP08_DBLE 8
  80 +#define EXCP09_XERR 9
  81 +#define EXCP0A_TSS 10
  82 +#define EXCP0B_NOSEG 11
  83 +#define EXCP0C_STACK 12
  84 +#define EXCP0D_GPF 13
  85 +#define EXCP0E_PAGE 14
  86 +#define EXCP10_COPR 16
  87 +#define EXCP11_ALGN 17
  88 +#define EXCP12_MCHK 18
89 89
90 #define EXCP_INTERRUPT 256 /* async interruption */ 90 #define EXCP_INTERRUPT 256 /* async interruption */
91 91
linux-user/main.c
@@ -106,77 +106,172 @@ uint64_t gdt_table[6]; @@ -106,77 +106,172 @@ uint64_t gdt_table[6];
106 106
107 //#define DEBUG_VM86 107 //#define DEBUG_VM86
108 108
  109 +static inline int is_revectored(int nr, struct target_revectored_struct *bitmap)
  110 +{
  111 + return (tswap32(bitmap->__map[nr >> 5]) >> (nr & 0x1f)) & 1;
  112 +}
  113 +
  114 +static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg)
  115 +{
  116 + return (uint8_t *)((seg << 4) + (reg & 0xffff));
  117 +}
  118 +
  119 +static inline void pushw(CPUX86State *env, int val)
  120 +{
  121 + env->regs[R_ESP] = (env->regs[R_ESP] & ~0xffff) |
  122 + ((env->regs[R_ESP] - 2) & 0xffff);
  123 + *(uint16_t *)seg_to_linear(env->segs[R_SS], env->regs[R_ESP]) = val;
  124 +}
  125 +
  126 +static inline unsigned int get_vflags(CPUX86State *env)
  127 +{
  128 + unsigned int eflags;
  129 + eflags = env->eflags & ~(VM_MASK | RF_MASK | IF_MASK);
  130 + if (eflags & VIF_MASK)
  131 + eflags |= IF_MASK;
  132 + return eflags;
  133 +}
  134 +
  135 +void save_v86_state(CPUX86State *env)
  136 +{
  137 + TaskState *ts = env->opaque;
  138 +#ifdef DEBUG_VM86
  139 + printf("save_v86_state\n");
  140 +#endif
  141 +
  142 + /* put the VM86 registers in the userspace register structure */
  143 + ts->target_v86->regs.eax = tswap32(env->regs[R_EAX]);
  144 + ts->target_v86->regs.ebx = tswap32(env->regs[R_EBX]);
  145 + ts->target_v86->regs.ecx = tswap32(env->regs[R_ECX]);
  146 + ts->target_v86->regs.edx = tswap32(env->regs[R_EDX]);
  147 + ts->target_v86->regs.esi = tswap32(env->regs[R_ESI]);
  148 + ts->target_v86->regs.edi = tswap32(env->regs[R_EDI]);
  149 + ts->target_v86->regs.ebp = tswap32(env->regs[R_EBP]);
  150 + ts->target_v86->regs.esp = tswap32(env->regs[R_ESP]);
  151 + ts->target_v86->regs.eip = tswap32(env->eip);
  152 + ts->target_v86->regs.cs = tswap16(env->segs[R_CS]);
  153 + ts->target_v86->regs.ss = tswap16(env->segs[R_SS]);
  154 + ts->target_v86->regs.ds = tswap16(env->segs[R_DS]);
  155 + ts->target_v86->regs.es = tswap16(env->segs[R_ES]);
  156 + ts->target_v86->regs.fs = tswap16(env->segs[R_FS]);
  157 + ts->target_v86->regs.gs = tswap16(env->segs[R_GS]);
  158 + ts->target_v86->regs.eflags = tswap32(env->eflags);
  159 +
  160 + /* restore 32 bit registers */
  161 + env->regs[R_EAX] = ts->vm86_saved_regs.eax;
  162 + env->regs[R_EBX] = ts->vm86_saved_regs.ebx;
  163 + env->regs[R_ECX] = ts->vm86_saved_regs.ecx;
  164 + env->regs[R_EDX] = ts->vm86_saved_regs.edx;
  165 + env->regs[R_ESI] = ts->vm86_saved_regs.esi;
  166 + env->regs[R_EDI] = ts->vm86_saved_regs.edi;
  167 + env->regs[R_EBP] = ts->vm86_saved_regs.ebp;
  168 + env->regs[R_ESP] = ts->vm86_saved_regs.esp;
  169 + env->eflags = ts->vm86_saved_regs.eflags;
  170 + env->eip = ts->vm86_saved_regs.eip;
  171 +
  172 + cpu_x86_load_seg(env, R_CS, ts->vm86_saved_regs.cs);
  173 + cpu_x86_load_seg(env, R_SS, ts->vm86_saved_regs.ss);
  174 + cpu_x86_load_seg(env, R_DS, ts->vm86_saved_regs.ds);
  175 + cpu_x86_load_seg(env, R_ES, ts->vm86_saved_regs.es);
  176 + cpu_x86_load_seg(env, R_FS, ts->vm86_saved_regs.fs);
  177 + cpu_x86_load_seg(env, R_GS, ts->vm86_saved_regs.gs);
  178 +}
  179 +
  180 +/* return from vm86 mode to 32 bit. The vm86() syscall will return
  181 + 'retval' */
  182 +static inline void return_to_32bit(CPUX86State *env, int retval)
  183 +{
  184 +#ifdef DEBUG_VM86
  185 + printf("return_to_32bit: ret=0x%x\n", retval);
  186 +#endif
  187 + save_v86_state(env);
  188 + env->regs[R_EAX] = retval;
  189 +}
  190 +
  191 +/* handle VM86 interrupt (NOTE: the CPU core currently does not
  192 + support TSS interrupt revectoring, so this code is always executed) */
  193 +static void do_int(CPUX86State *env, int intno)
  194 +{
  195 + TaskState *ts = env->opaque;
  196 + uint32_t *int_ptr, segoffs;
  197 +
  198 + if (env->segs[R_CS] == TARGET_BIOSSEG)
  199 + goto cannot_handle; /* XXX: I am not sure this is really useful */
  200 + if (is_revectored(intno, &ts->target_v86->int_revectored))
  201 + goto cannot_handle;
  202 + if (intno == 0x21 && is_revectored((env->regs[R_EAX] >> 8) & 0xff,
  203 + &ts->target_v86->int21_revectored))
  204 + goto cannot_handle;
  205 + int_ptr = (uint32_t *)(intno << 2);
  206 + segoffs = tswap32(*int_ptr);
  207 + if ((segoffs >> 16) == TARGET_BIOSSEG)
  208 + goto cannot_handle;
  209 +#ifdef DEBUG_VM86
  210 + printf("VM86: emulating int 0x%x. CS:IP=%04x:%04x\n",
  211 + intno, segoffs >> 16, segoffs & 0xffff);
  212 +#endif
  213 + /* save old state */
  214 + pushw(env, get_vflags(env));
  215 + pushw(env, env->segs[R_CS]);
  216 + pushw(env, env->eip);
  217 + /* goto interrupt handler */
  218 + env->eip = segoffs & 0xffff;
  219 + cpu_x86_load_seg(env, R_CS, segoffs >> 16);
  220 + env->eflags &= ~(VIF_MASK | TF_MASK);
  221 + return;
  222 + cannot_handle:
  223 +#ifdef DEBUG_VM86
  224 + printf("VM86: return to 32 bits int 0x%x\n", intno);
  225 +#endif
  226 + return_to_32bit(env, TARGET_VM86_INTx | (intno << 8));
  227 +}
  228 +
109 void cpu_loop(struct CPUX86State *env) 229 void cpu_loop(struct CPUX86State *env)
110 { 230 {
111 - int err; 231 + int trapnr;
112 uint8_t *pc; 232 uint8_t *pc;
113 target_siginfo_t info; 233 target_siginfo_t info;
114 234
115 for(;;) { 235 for(;;) {
116 - err = cpu_x86_exec(env); 236 + trapnr = cpu_x86_exec(env);
117 pc = env->seg_cache[R_CS].base + env->eip; 237 pc = env->seg_cache[R_CS].base + env->eip;
118 - switch(err) { 238 + switch(trapnr) {
119 case EXCP0D_GPF: 239 case EXCP0D_GPF:
120 if (env->eflags & VM_MASK) { 240 if (env->eflags & VM_MASK) {
121 - TaskState *ts;  
122 - int ret;  
123 #ifdef DEBUG_VM86 241 #ifdef DEBUG_VM86
124 - printf("VM86 exception %04x:%08x %02x\n",  
125 - env->segs[R_CS], env->eip, pc[0]); 242 + printf("VM86 exception %04x:%08x %02x %02x\n",
  243 + env->segs[R_CS], env->eip, pc[0], pc[1]);
126 #endif 244 #endif
127 /* VM86 mode */ 245 /* VM86 mode */
128 - ts = env->opaque;  
129 -  
130 - /* XXX: add all cases */  
131 switch(pc[0]) { 246 switch(pc[0]) {
132 case 0xcd: /* int */ 247 case 0xcd: /* int */
133 env->eip += 2; 248 env->eip += 2;
134 - ret = TARGET_VM86_INTx | (pc[1] << 8); 249 + do_int(env, pc[1]);
  250 + break;
  251 + case 0x66:
  252 + switch(pc[1]) {
  253 + case 0xfb: /* sti */
  254 + case 0x9d: /* popf */
  255 + case 0xcf: /* iret */
  256 + env->eip += 2;
  257 + return_to_32bit(env, TARGET_VM86_STI);
  258 + break;
  259 + default:
  260 + goto vm86_gpf;
  261 + }
  262 + break;
  263 + case 0xfb: /* sti */
  264 + case 0x9d: /* popf */
  265 + case 0xcf: /* iret */
  266 + env->eip++;
  267 + return_to_32bit(env, TARGET_VM86_STI);
135 break; 268 break;
136 default: 269 default:
  270 + vm86_gpf:
137 /* real VM86 GPF exception */ 271 /* real VM86 GPF exception */
138 - ret = TARGET_VM86_UNKNOWN; 272 + return_to_32bit(env, TARGET_VM86_UNKNOWN);
139 break; 273 break;
140 } 274 }
141 -#ifdef DEBUG_VM86  
142 - printf("ret=0x%x\n", ret);  
143 -#endif  
144 - /* put the VM86 registers in the userspace register structure */  
145 - ts->target_v86->regs.eax = tswap32(env->regs[R_EAX]);  
146 - ts->target_v86->regs.ebx = tswap32(env->regs[R_EBX]);  
147 - ts->target_v86->regs.ecx = tswap32(env->regs[R_ECX]);  
148 - ts->target_v86->regs.edx = tswap32(env->regs[R_EDX]);  
149 - ts->target_v86->regs.esi = tswap32(env->regs[R_ESI]);  
150 - ts->target_v86->regs.edi = tswap32(env->regs[R_EDI]);  
151 - ts->target_v86->regs.ebp = tswap32(env->regs[R_EBP]);  
152 - ts->target_v86->regs.esp = tswap32(env->regs[R_ESP]);  
153 - ts->target_v86->regs.eip = tswap32(env->eip);  
154 - ts->target_v86->regs.cs = tswap16(env->segs[R_CS]);  
155 - ts->target_v86->regs.ss = tswap16(env->segs[R_SS]);  
156 - ts->target_v86->regs.ds = tswap16(env->segs[R_DS]);  
157 - ts->target_v86->regs.es = tswap16(env->segs[R_ES]);  
158 - ts->target_v86->regs.fs = tswap16(env->segs[R_FS]);  
159 - ts->target_v86->regs.gs = tswap16(env->segs[R_GS]);  
160 -  
161 - /* restore 32 bit registers */  
162 - env->regs[R_EBX] = ts->vm86_saved_regs.ebx;  
163 - env->regs[R_ECX] = ts->vm86_saved_regs.ecx;  
164 - env->regs[R_EDX] = ts->vm86_saved_regs.edx;  
165 - env->regs[R_ESI] = ts->vm86_saved_regs.esi;  
166 - env->regs[R_EDI] = ts->vm86_saved_regs.edi;  
167 - env->regs[R_EBP] = ts->vm86_saved_regs.ebp;  
168 - env->regs[R_ESP] = ts->vm86_saved_regs.esp;  
169 - env->eflags = ts->vm86_saved_regs.eflags;  
170 - env->eip = ts->vm86_saved_regs.eip;  
171 -  
172 - cpu_x86_load_seg(env, R_CS, ts->vm86_saved_regs.cs);  
173 - cpu_x86_load_seg(env, R_SS, ts->vm86_saved_regs.ss);  
174 - cpu_x86_load_seg(env, R_DS, ts->vm86_saved_regs.ds);  
175 - cpu_x86_load_seg(env, R_ES, ts->vm86_saved_regs.es);  
176 - cpu_x86_load_seg(env, R_FS, ts->vm86_saved_regs.fs);  
177 - cpu_x86_load_seg(env, R_GS, ts->vm86_saved_regs.gs);  
178 -  
179 - env->regs[R_EAX] = ret;  
180 } else { 275 } else {
181 if (pc[0] == 0xcd && pc[1] == 0x80) { 276 if (pc[0] == 0xcd && pc[1] == 0x80) {
182 /* syscall */ 277 /* syscall */
@@ -200,20 +295,28 @@ void cpu_loop(struct CPUX86State *env) @@ -200,20 +295,28 @@ void cpu_loop(struct CPUX86State *env)
200 } 295 }
201 break; 296 break;
202 case EXCP00_DIVZ: 297 case EXCP00_DIVZ:
203 - /* division by zero */  
204 - info.si_signo = SIGFPE;  
205 - info.si_errno = 0;  
206 - info.si_code = TARGET_FPE_INTDIV;  
207 - info._sifields._sigfault._addr = env->eip;  
208 - queue_signal(info.si_signo, &info); 298 + if (env->eflags & VM_MASK) {
  299 + do_int(env, trapnr);
  300 + } else {
  301 + /* division by zero */
  302 + info.si_signo = SIGFPE;
  303 + info.si_errno = 0;
  304 + info.si_code = TARGET_FPE_INTDIV;
  305 + info._sifields._sigfault._addr = env->eip;
  306 + queue_signal(info.si_signo, &info);
  307 + }
209 break; 308 break;
210 case EXCP04_INTO: 309 case EXCP04_INTO:
211 case EXCP05_BOUND: 310 case EXCP05_BOUND:
212 - info.si_signo = SIGSEGV;  
213 - info.si_errno = 0;  
214 - info.si_code = 0;  
215 - info._sifields._sigfault._addr = 0;  
216 - queue_signal(info.si_signo, &info); 311 + if (env->eflags & VM_MASK) {
  312 + do_int(env, trapnr);
  313 + } else {
  314 + info.si_signo = SIGSEGV;
  315 + info.si_errno = 0;
  316 + info.si_code = 0;
  317 + info._sifields._sigfault._addr = 0;
  318 + queue_signal(info.si_signo, &info);
  319 + }
217 break; 320 break;
218 case EXCP06_ILLOP: 321 case EXCP06_ILLOP:
219 info.si_signo = SIGILL; 322 info.si_signo = SIGILL;
@@ -226,8 +329,8 @@ void cpu_loop(struct CPUX86State *env) @@ -226,8 +329,8 @@ void cpu_loop(struct CPUX86State *env)
226 /* just indicate that signals should be handled asap */ 329 /* just indicate that signals should be handled asap */
227 break; 330 break;
228 default: 331 default:
229 - fprintf(stderr, "0x%08lx: Unknown exception CPU %d, aborting\n",  
230 - (long)pc, err); 332 + fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
  333 + (long)pc, trapnr);
231 abort(); 334 abort();
232 } 335 }
233 process_pending_signals(env); 336 process_pending_signals(env);
linux-user/qemu.h
@@ -74,5 +74,6 @@ void cpu_loop(CPUX86State *env); @@ -74,5 +74,6 @@ void cpu_loop(CPUX86State *env);
74 void process_pending_signals(void *cpu_env); 74 void process_pending_signals(void *cpu_env);
75 void signal_init(void); 75 void signal_init(void);
76 int queue_signal(int sig, target_siginfo_t *info); 76 int queue_signal(int sig, target_siginfo_t *info);
  77 +void save_v86_state(CPUX86State *env);
77 78
78 #endif 79 #endif
linux-user/signal.c
@@ -198,7 +198,7 @@ void __attribute((noreturn)) force_sig(int sig) @@ -198,7 +198,7 @@ void __attribute((noreturn)) force_sig(int sig)
198 { 198 {
199 int host_sig; 199 int host_sig;
200 host_sig = target_to_host_signal(sig); 200 host_sig = target_to_host_signal(sig);
201 - fprintf(stderr, "gemu: uncaught target signal %d (%s) - exiting\n", 201 + fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n",
202 sig, strsignal(host_sig)); 202 sig, strsignal(host_sig));
203 #if 1 203 #if 1
204 _exit(-host_sig); 204 _exit(-host_sig);
@@ -223,7 +223,7 @@ int queue_signal(int sig, target_siginfo_t *info) @@ -223,7 +223,7 @@ int queue_signal(int sig, target_siginfo_t *info)
223 target_ulong handler; 223 target_ulong handler;
224 224
225 #if defined(DEBUG_SIGNAL) 225 #if defined(DEBUG_SIGNAL)
226 - fprintf(stderr, "queue_sigal: sig=%d\n", 226 + fprintf(stderr, "queue_signal: sig=%d\n",
227 sig); 227 sig);
228 #endif 228 #endif
229 k = &sigact_table[sig - 1]; 229 k = &sigact_table[sig - 1];
@@ -317,7 +317,7 @@ static void host_signal_handler(int host_signum, siginfo_t *info, @@ -317,7 +317,7 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
317 if (sig < 1 || sig > TARGET_NSIG) 317 if (sig < 1 || sig > TARGET_NSIG)
318 return; 318 return;
319 #if defined(DEBUG_SIGNAL) 319 #if defined(DEBUG_SIGNAL)
320 - fprintf(stderr, "gemu: got signal %d\n", sig); 320 + fprintf(stderr, "qemu: got signal %d\n", sig);
321 dump_regs(puc); 321 dump_regs(puc);
322 #endif 322 #endif
323 host_to_target_siginfo_noswap(&tinfo, info); 323 host_to_target_siginfo_noswap(&tinfo, info);
@@ -538,7 +538,6 @@ setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate, @@ -538,7 +538,6 @@ setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate,
538 /* non-iBCS2 extensions.. */ 538 /* non-iBCS2 extensions.. */
539 err |= __put_user(mask, &sc->oldmask); 539 err |= __put_user(mask, &sc->oldmask);
540 err |= __put_user(/*current->thread.cr2*/ 0, &sc->cr2); 540 err |= __put_user(/*current->thread.cr2*/ 0, &sc->cr2);
541 -  
542 return err; 541 return err;
543 } 542 }
544 543
@@ -859,7 +858,7 @@ void process_pending_signals(void *cpu_env) @@ -859,7 +858,7 @@ void process_pending_signals(void *cpu_env)
859 858
860 handle_signal: 859 handle_signal:
861 #ifdef DEBUG_SIGNAL 860 #ifdef DEBUG_SIGNAL
862 - fprintf(stderr, "gemu: process signal %d\n", sig); 861 + fprintf(stderr, "qemu: process signal %d\n", sig);
863 #endif 862 #endif
864 /* dequeue signal */ 863 /* dequeue signal */
865 q = k->first; 864 q = k->first;
@@ -893,6 +892,14 @@ void process_pending_signals(void *cpu_env) @@ -893,6 +892,14 @@ void process_pending_signals(void *cpu_env)
893 end of the signal execution (see do_sigreturn) */ 892 end of the signal execution (see do_sigreturn) */
894 host_to_target_sigset(&target_old_set, &old_set); 893 host_to_target_sigset(&target_old_set, &old_set);
895 894
  895 + /* if the CPU is in VM86 mode, we restore the 32 bit values */
  896 +#ifdef TARGET_I386
  897 + {
  898 + CPUX86State *env = cpu_env;
  899 + if (env->eflags & VM_MASK)
  900 + save_v86_state(env);
  901 + }
  902 +#endif
896 /* prepare the stack frame of the virtual CPU */ 903 /* prepare the stack frame of the virtual CPU */
897 if (k->sa.sa_flags & TARGET_SA_SIGINFO) 904 if (k->sa.sa_flags & TARGET_SA_SIGINFO)
898 setup_rt_frame(sig, k, &q->info, &target_old_set, cpu_env); 905 setup_rt_frame(sig, k, &q->info, &target_old_set, cpu_env);
syscall-i386.h
@@ -755,6 +755,11 @@ struct target_modify_ldt_ldt_s { @@ -755,6 +755,11 @@ struct target_modify_ldt_ldt_s {
755 unsigned int flags; 755 unsigned int flags;
756 }; 756 };
757 757
  758 +
  759 +/* vm86 defines */
  760 +
  761 +#define TARGET_BIOSSEG 0x0f000
  762 +
758 #define TARGET_VM86_SIGNAL 0 /* return due to signal */ 763 #define TARGET_VM86_SIGNAL 0 /* return due to signal */
759 #define TARGET_VM86_UNKNOWN 1 /* unhandled GP fault - IO-instruction or similar */ 764 #define TARGET_VM86_UNKNOWN 1 /* unhandled GP fault - IO-instruction or similar */
760 #define TARGET_VM86_INTx 2 /* int3/int x instruction (ARG = x) */ 765 #define TARGET_VM86_INTx 2 /* int3/int x instruction (ARG = x) */