Commit bc8a22cc307ebd9a2577c8fffcb90000724f72f3
1 parent
f631ef9b
better vm86 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@69 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
7 changed files
with
239 additions
and
89 deletions
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 | 33 | version 0.1.1: |
| 2 | 34 | |
| 3 | 35 | - glibc 2.2 compilation fixes |
| 4 | 36 | - added -s and -L options |
| 5 | 37 | - binary distribution of x86 glibc and wine |
| 38 | + - big endian fixes in ELF loader and getdents. | |
| 6 | 39 | |
| 7 | 40 | version 0.1: |
| 8 | 41 | ... | ... |
TODO
| 1 | +- fix thread locks | |
| 2 | +- fix thread stack liberation | |
| 3 | +- fix x86 stack allocation | |
| 1 | 4 | - optimize translated cache chaining (DLL PLT-like system) |
| 2 | 5 | - more syscalls (in particular all 64 bit ones, IPCs, fix 64 bit |
| 3 | 6 | issues, fix 16 bit uid issues) |
| 4 | 7 | - finish signal handing (fp87 state, more siginfo conversions) |
| 5 | 8 | - verify thread support (clone() and various locks) |
| 6 | -- vm86 syscall support | |
| 7 | 9 | - overrides/16bit for string ops |
| 8 | 10 | - make it self runnable (use same trick as ld.so : include its own relocator and libc) |
| 9 | -- improved 16 bit support | |
| 10 | 11 | - fix FPU exceptions (in particular: gen_op_fpush not before mem load) | ... | ... |
cpu-i386.h
| ... | ... | @@ -68,24 +68,24 @@ |
| 68 | 68 | #define VIP_MASK 0x00100000 |
| 69 | 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 | 90 | #define EXCP_INTERRUPT 256 /* async interruption */ |
| 91 | 91 | ... | ... |
linux-user/main.c
| ... | ... | @@ -106,77 +106,172 @@ uint64_t gdt_table[6]; |
| 106 | 106 | |
| 107 | 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 | 229 | void cpu_loop(struct CPUX86State *env) |
| 110 | 230 | { |
| 111 | - int err; | |
| 231 | + int trapnr; | |
| 112 | 232 | uint8_t *pc; |
| 113 | 233 | target_siginfo_t info; |
| 114 | 234 | |
| 115 | 235 | for(;;) { |
| 116 | - err = cpu_x86_exec(env); | |
| 236 | + trapnr = cpu_x86_exec(env); | |
| 117 | 237 | pc = env->seg_cache[R_CS].base + env->eip; |
| 118 | - switch(err) { | |
| 238 | + switch(trapnr) { | |
| 119 | 239 | case EXCP0D_GPF: |
| 120 | 240 | if (env->eflags & VM_MASK) { |
| 121 | - TaskState *ts; | |
| 122 | - int ret; | |
| 123 | 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 | 244 | #endif |
| 127 | 245 | /* VM86 mode */ |
| 128 | - ts = env->opaque; | |
| 129 | - | |
| 130 | - /* XXX: add all cases */ | |
| 131 | 246 | switch(pc[0]) { |
| 132 | 247 | case 0xcd: /* int */ |
| 133 | 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 | 268 | break; |
| 136 | 269 | default: |
| 270 | + vm86_gpf: | |
| 137 | 271 | /* real VM86 GPF exception */ |
| 138 | - ret = TARGET_VM86_UNKNOWN; | |
| 272 | + return_to_32bit(env, TARGET_VM86_UNKNOWN); | |
| 139 | 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 | 275 | } else { |
| 181 | 276 | if (pc[0] == 0xcd && pc[1] == 0x80) { |
| 182 | 277 | /* syscall */ |
| ... | ... | @@ -200,20 +295,28 @@ void cpu_loop(struct CPUX86State *env) |
| 200 | 295 | } |
| 201 | 296 | break; |
| 202 | 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 | 308 | break; |
| 210 | 309 | case EXCP04_INTO: |
| 211 | 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 | 320 | break; |
| 218 | 321 | case EXCP06_ILLOP: |
| 219 | 322 | info.si_signo = SIGILL; |
| ... | ... | @@ -226,8 +329,8 @@ void cpu_loop(struct CPUX86State *env) |
| 226 | 329 | /* just indicate that signals should be handled asap */ |
| 227 | 330 | break; |
| 228 | 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 | 334 | abort(); |
| 232 | 335 | } |
| 233 | 336 | process_pending_signals(env); | ... | ... |
linux-user/qemu.h
linux-user/signal.c
| ... | ... | @@ -198,7 +198,7 @@ void __attribute((noreturn)) force_sig(int sig) |
| 198 | 198 | { |
| 199 | 199 | int host_sig; |
| 200 | 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 | 202 | sig, strsignal(host_sig)); |
| 203 | 203 | #if 1 |
| 204 | 204 | _exit(-host_sig); |
| ... | ... | @@ -223,7 +223,7 @@ int queue_signal(int sig, target_siginfo_t *info) |
| 223 | 223 | target_ulong handler; |
| 224 | 224 | |
| 225 | 225 | #if defined(DEBUG_SIGNAL) |
| 226 | - fprintf(stderr, "queue_sigal: sig=%d\n", | |
| 226 | + fprintf(stderr, "queue_signal: sig=%d\n", | |
| 227 | 227 | sig); |
| 228 | 228 | #endif |
| 229 | 229 | k = &sigact_table[sig - 1]; |
| ... | ... | @@ -317,7 +317,7 @@ static void host_signal_handler(int host_signum, siginfo_t *info, |
| 317 | 317 | if (sig < 1 || sig > TARGET_NSIG) |
| 318 | 318 | return; |
| 319 | 319 | #if defined(DEBUG_SIGNAL) |
| 320 | - fprintf(stderr, "gemu: got signal %d\n", sig); | |
| 320 | + fprintf(stderr, "qemu: got signal %d\n", sig); | |
| 321 | 321 | dump_regs(puc); |
| 322 | 322 | #endif |
| 323 | 323 | host_to_target_siginfo_noswap(&tinfo, info); |
| ... | ... | @@ -538,7 +538,6 @@ setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate, |
| 538 | 538 | /* non-iBCS2 extensions.. */ |
| 539 | 539 | err |= __put_user(mask, &sc->oldmask); |
| 540 | 540 | err |= __put_user(/*current->thread.cr2*/ 0, &sc->cr2); |
| 541 | - | |
| 542 | 541 | return err; |
| 543 | 542 | } |
| 544 | 543 | |
| ... | ... | @@ -859,7 +858,7 @@ void process_pending_signals(void *cpu_env) |
| 859 | 858 | |
| 860 | 859 | handle_signal: |
| 861 | 860 | #ifdef DEBUG_SIGNAL |
| 862 | - fprintf(stderr, "gemu: process signal %d\n", sig); | |
| 861 | + fprintf(stderr, "qemu: process signal %d\n", sig); | |
| 863 | 862 | #endif |
| 864 | 863 | /* dequeue signal */ |
| 865 | 864 | q = k->first; |
| ... | ... | @@ -893,6 +892,14 @@ void process_pending_signals(void *cpu_env) |
| 893 | 892 | end of the signal execution (see do_sigreturn) */ |
| 894 | 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 | 903 | /* prepare the stack frame of the virtual CPU */ |
| 897 | 904 | if (k->sa.sa_flags & TARGET_SA_SIGINFO) |
| 898 | 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 | 755 | unsigned int flags; |
| 756 | 756 | }; |
| 757 | 757 | |
| 758 | + | |
| 759 | +/* vm86 defines */ | |
| 760 | + | |
| 761 | +#define TARGET_BIOSSEG 0x0f000 | |
| 762 | + | |
| 758 | 763 | #define TARGET_VM86_SIGNAL 0 /* return due to signal */ |
| 759 | 764 | #define TARGET_VM86_UNKNOWN 1 /* unhandled GP fault - IO-instruction or similar */ |
| 760 | 765 | #define TARGET_VM86_INTx 2 /* int3/int x instruction (ARG = x) */ | ... | ... |