Commit b333af066655c15031820a109b651c45adb7eccf
1 parent
76c8b771
removed trace - merged 2.4.20 vm86 patches
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@167 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
121 additions
and
63 deletions
linux-user/qemu.h
| @@ -54,6 +54,7 @@ typedef struct TaskState { | @@ -54,6 +54,7 @@ typedef struct TaskState { | ||
| 54 | struct TaskState *next; | 54 | struct TaskState *next; |
| 55 | struct target_vm86plus_struct *target_v86; | 55 | struct target_vm86plus_struct *target_v86; |
| 56 | struct vm86_saved_state vm86_saved_regs; | 56 | struct vm86_saved_state vm86_saved_regs; |
| 57 | + struct target_vm86plus_struct vm86plus; | ||
| 57 | uint32_t v86flags; | 58 | uint32_t v86flags; |
| 58 | uint32_t v86mask; | 59 | uint32_t v86mask; |
| 59 | int used; /* non zero if used */ | 60 | int used; /* non zero if used */ |
linux-user/vm86.c
| @@ -36,7 +36,7 @@ | @@ -36,7 +36,7 @@ | ||
| 36 | 36 | ||
| 37 | static inline int is_revectored(int nr, struct target_revectored_struct *bitmap) | 37 | static inline int is_revectored(int nr, struct target_revectored_struct *bitmap) |
| 38 | { | 38 | { |
| 39 | - return (tswap32(bitmap->__map[nr >> 5]) >> (nr & 0x1f)) & 1; | 39 | + return (((uint8_t *)bitmap)[nr >> 3] >> (nr & 7)) & 1; |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | static inline void vm_putw(uint8_t *segptr, unsigned int reg16, unsigned int val) | 42 | static inline void vm_putw(uint8_t *segptr, unsigned int reg16, unsigned int val) |
| @@ -194,17 +194,12 @@ static void do_int(CPUX86State *env, int intno) | @@ -194,17 +194,12 @@ static void do_int(CPUX86State *env, int intno) | ||
| 194 | uint8_t *ssp; | 194 | uint8_t *ssp; |
| 195 | unsigned int sp; | 195 | unsigned int sp; |
| 196 | 196 | ||
| 197 | -#if 1 | ||
| 198 | - if (intno == 0xe6 && (env->regs[R_EAX] & 0xffff) == 0x00c0) | ||
| 199 | - loglevel = 1; | ||
| 200 | -#endif | ||
| 201 | - | ||
| 202 | if (env->segs[R_CS] == TARGET_BIOSSEG) | 197 | if (env->segs[R_CS] == TARGET_BIOSSEG) |
| 203 | goto cannot_handle; | 198 | goto cannot_handle; |
| 204 | - if (is_revectored(intno, &ts->target_v86->int_revectored)) | 199 | + if (is_revectored(intno, &ts->vm86plus.int_revectored)) |
| 205 | goto cannot_handle; | 200 | goto cannot_handle; |
| 206 | if (intno == 0x21 && is_revectored((env->regs[R_EAX] >> 8) & 0xff, | 201 | if (intno == 0x21 && is_revectored((env->regs[R_EAX] >> 8) & 0xff, |
| 207 | - &ts->target_v86->int21_revectored)) | 202 | + &ts->vm86plus.int21_revectored)) |
| 208 | goto cannot_handle; | 203 | goto cannot_handle; |
| 209 | int_ptr = (uint32_t *)(intno << 2); | 204 | int_ptr = (uint32_t *)(intno << 2); |
| 210 | segoffs = tswap32(*int_ptr); | 205 | segoffs = tswap32(*int_ptr); |
| @@ -244,13 +239,13 @@ void handle_vm86_trap(CPUX86State *env, int trapno) | @@ -244,13 +239,13 @@ void handle_vm86_trap(CPUX86State *env, int trapno) | ||
| 244 | } | 239 | } |
| 245 | } | 240 | } |
| 246 | 241 | ||
| 247 | -#define CHECK_IF_IN_TRAP(disp) \ | ||
| 248 | - if ((tswap32(ts->target_v86->vm86plus.flags) & TARGET_vm86dbg_active) && \ | ||
| 249 | - (tswap32(ts->target_v86->vm86plus.flags) & TARGET_vm86dbg_TFpendig)) \ | ||
| 250 | - vm_putw(ssp,sp + disp,vm_getw(ssp,sp + disp) | TF_MASK) | 242 | +#define CHECK_IF_IN_TRAP() \ |
| 243 | + if ((ts->vm86plus.vm86plus.flags & TARGET_vm86dbg_active) && \ | ||
| 244 | + (ts->vm86plus.vm86plus.flags & TARGET_vm86dbg_TFpendig)) \ | ||
| 245 | + newflags |= TF_MASK | ||
| 251 | 246 | ||
| 252 | #define VM86_FAULT_RETURN \ | 247 | #define VM86_FAULT_RETURN \ |
| 253 | - if ((tswap32(ts->target_v86->vm86plus.flags) & TARGET_force_return_for_pic) && \ | 248 | + if ((ts->vm86plus.vm86plus.flags & TARGET_force_return_for_pic) && \ |
| 254 | (ts->v86flags & (IF_MASK | VIF_MASK))) \ | 249 | (ts->v86flags & (IF_MASK | VIF_MASK))) \ |
| 255 | return_to_32bit(env, TARGET_VM86_PICRETURN); \ | 250 | return_to_32bit(env, TARGET_VM86_PICRETURN); \ |
| 256 | return | 251 | return |
| @@ -259,7 +254,8 @@ void handle_vm86_fault(CPUX86State *env) | @@ -259,7 +254,8 @@ void handle_vm86_fault(CPUX86State *env) | ||
| 259 | { | 254 | { |
| 260 | TaskState *ts = env->opaque; | 255 | TaskState *ts = env->opaque; |
| 261 | uint8_t *csp, *pc, *ssp; | 256 | uint8_t *csp, *pc, *ssp; |
| 262 | - unsigned int ip, sp; | 257 | + unsigned int ip, sp, newflags, newip, newcs, opcode, intno; |
| 258 | + int data32, pref_done; | ||
| 263 | 259 | ||
| 264 | csp = (uint8_t *)(env->segs[R_CS] << 4); | 260 | csp = (uint8_t *)(env->segs[R_CS] << 4); |
| 265 | ip = env->eip & 0xffff; | 261 | ip = env->eip & 0xffff; |
| @@ -273,78 +269,109 @@ void handle_vm86_fault(CPUX86State *env) | @@ -273,78 +269,109 @@ void handle_vm86_fault(CPUX86State *env) | ||
| 273 | env->segs[R_CS], env->eip, pc[0], pc[1]); | 269 | env->segs[R_CS], env->eip, pc[0], pc[1]); |
| 274 | #endif | 270 | #endif |
| 275 | 271 | ||
| 272 | + data32 = 0; | ||
| 273 | + pref_done = 0; | ||
| 274 | + do { | ||
| 275 | + opcode = csp[ip]; | ||
| 276 | + ADD16(ip, 1); | ||
| 277 | + switch (opcode) { | ||
| 278 | + case 0x66: /* 32-bit data */ data32=1; break; | ||
| 279 | + case 0x67: /* 32-bit address */ break; | ||
| 280 | + case 0x2e: /* CS */ break; | ||
| 281 | + case 0x3e: /* DS */ break; | ||
| 282 | + case 0x26: /* ES */ break; | ||
| 283 | + case 0x36: /* SS */ break; | ||
| 284 | + case 0x65: /* GS */ break; | ||
| 285 | + case 0x64: /* FS */ break; | ||
| 286 | + case 0xf2: /* repnz */ break; | ||
| 287 | + case 0xf3: /* rep */ break; | ||
| 288 | + default: pref_done = 1; | ||
| 289 | + } | ||
| 290 | + } while (!pref_done); | ||
| 291 | + | ||
| 276 | /* VM86 mode */ | 292 | /* VM86 mode */ |
| 277 | - switch(pc[0]) { | ||
| 278 | - case 0x66: | ||
| 279 | - switch(pc[1]) { | ||
| 280 | - case 0x9c: /* pushfd */ | ||
| 281 | - ADD16(env->eip, 2); | ||
| 282 | - ADD16(env->regs[R_ESP], -4); | 293 | + switch(opcode) { |
| 294 | + case 0x9c: /* pushf */ | ||
| 295 | + ADD16(env->eip, 2); | ||
| 296 | + if (data32) { | ||
| 283 | vm_putl(ssp, sp - 4, get_vflags(env)); | 297 | vm_putl(ssp, sp - 4, get_vflags(env)); |
| 284 | - VM86_FAULT_RETURN; | 298 | + ADD16(env->regs[R_ESP], -4); |
| 299 | + } else { | ||
| 300 | + vm_putw(ssp, sp - 2, get_vflags(env)); | ||
| 301 | + ADD16(env->regs[R_ESP], -2); | ||
| 302 | + } | ||
| 303 | + env->eip = ip; | ||
| 304 | + VM86_FAULT_RETURN; | ||
| 285 | 305 | ||
| 286 | - case 0x9d: /* popfd */ | ||
| 287 | - ADD16(env->eip, 2); | 306 | + case 0x9d: /* popf */ |
| 307 | + if (data32) { | ||
| 308 | + newflags = vm_getl(ssp, sp); | ||
| 288 | ADD16(env->regs[R_ESP], 4); | 309 | ADD16(env->regs[R_ESP], 4); |
| 289 | - CHECK_IF_IN_TRAP(0); | ||
| 290 | - if (set_vflags_long(vm_getl(ssp, sp), env)) | 310 | + } else { |
| 311 | + newflags = vm_getw(ssp, sp); | ||
| 312 | + ADD16(env->regs[R_ESP], 2); | ||
| 313 | + } | ||
| 314 | + env->eip = ip; | ||
| 315 | + CHECK_IF_IN_TRAP(); | ||
| 316 | + if (data32) { | ||
| 317 | + if (set_vflags_long(newflags, env)) | ||
| 291 | return; | 318 | return; |
| 292 | - VM86_FAULT_RETURN; | ||
| 293 | - | ||
| 294 | - case 0xcf: /* iretd */ | ||
| 295 | - ADD16(env->regs[R_ESP], 12); | ||
| 296 | - env->eip = vm_getl(ssp, sp) & 0xffff; | ||
| 297 | - cpu_x86_load_seg(env, R_CS, vm_getl(ssp, sp + 4) & 0xffff); | ||
| 298 | - CHECK_IF_IN_TRAP(8); | ||
| 299 | - if (set_vflags_long(vm_getl(ssp, sp + 8), env)) | 319 | + } else { |
| 320 | + if (set_vflags_short(newflags, env)) | ||
| 300 | return; | 321 | return; |
| 301 | - VM86_FAULT_RETURN; | ||
| 302 | - | ||
| 303 | - default: | ||
| 304 | - goto vm86_gpf; | ||
| 305 | } | 322 | } |
| 306 | - break; | ||
| 307 | - case 0x9c: /* pushf */ | ||
| 308 | - ADD16(env->eip, 1); | ||
| 309 | - ADD16(env->regs[R_ESP], -2); | ||
| 310 | - vm_putw(ssp, sp - 2, get_vflags(env)); | ||
| 311 | - VM86_FAULT_RETURN; | ||
| 312 | - | ||
| 313 | - case 0x9d: /* popf */ | ||
| 314 | - ADD16(env->eip, 1); | ||
| 315 | - ADD16(env->regs[R_ESP], 2); | ||
| 316 | - CHECK_IF_IN_TRAP(0); | ||
| 317 | - if (set_vflags_short(vm_getw(ssp, sp), env)) | ||
| 318 | - return; | ||
| 319 | VM86_FAULT_RETURN; | 323 | VM86_FAULT_RETURN; |
| 320 | 324 | ||
| 321 | case 0xcd: /* int */ | 325 | case 0xcd: /* int */ |
| 322 | - ADD16(env->eip, 2); | ||
| 323 | - do_int(env, pc[1]); | 326 | + intno = csp[ip]; |
| 327 | + ADD16(ip, 1); | ||
| 328 | + env->eip = ip; | ||
| 329 | + if (ts->vm86plus.vm86plus.flags & TARGET_vm86dbg_active) { | ||
| 330 | + if ( (ts->vm86plus.vm86plus.vm86dbg_intxxtab[intno >> 3] >> | ||
| 331 | + (intno &7)) & 1) { | ||
| 332 | + return_to_32bit(env, TARGET_VM86_INTx + (intno << 8)); | ||
| 333 | + return; | ||
| 334 | + } | ||
| 335 | + } | ||
| 336 | + do_int(env, intno); | ||
| 324 | break; | 337 | break; |
| 325 | 338 | ||
| 326 | case 0xcf: /* iret */ | 339 | case 0xcf: /* iret */ |
| 327 | - ADD16(env->regs[R_ESP], 6); | ||
| 328 | - env->eip = vm_getw(ssp, sp); | ||
| 329 | - cpu_x86_load_seg(env, R_CS, vm_getw(ssp, sp + 2)); | ||
| 330 | - CHECK_IF_IN_TRAP(4); | ||
| 331 | - if (set_vflags_short(vm_getw(ssp, sp + 4), env)) | ||
| 332 | - return; | 340 | + if (data32) { |
| 341 | + newip = vm_getl(ssp, sp) & 0xffff; | ||
| 342 | + newcs = vm_getl(ssp, sp + 4) & 0xffff; | ||
| 343 | + newflags = vm_getl(ssp, sp + 8); | ||
| 344 | + ADD16(env->regs[R_ESP], 12); | ||
| 345 | + } else { | ||
| 346 | + newip = vm_getw(ssp, sp); | ||
| 347 | + newcs = vm_getw(ssp, sp + 2); | ||
| 348 | + newflags = vm_getw(ssp, sp + 4); | ||
| 349 | + ADD16(env->regs[R_ESP], 6); | ||
| 350 | + } | ||
| 351 | + env->eip = newip; | ||
| 352 | + cpu_x86_load_seg(env, R_CS, newcs); | ||
| 353 | + CHECK_IF_IN_TRAP(); | ||
| 354 | + if (data32) { | ||
| 355 | + if (set_vflags_long(newflags, env)) | ||
| 356 | + return; | ||
| 357 | + } else { | ||
| 358 | + if (set_vflags_short(newflags, env)) | ||
| 359 | + return; | ||
| 360 | + } | ||
| 333 | VM86_FAULT_RETURN; | 361 | VM86_FAULT_RETURN; |
| 334 | - | 362 | + |
| 335 | case 0xfa: /* cli */ | 363 | case 0xfa: /* cli */ |
| 336 | - ADD16(env->eip, 1); | 364 | + env->eip = ip; |
| 337 | clear_IF(env); | 365 | clear_IF(env); |
| 338 | VM86_FAULT_RETURN; | 366 | VM86_FAULT_RETURN; |
| 339 | 367 | ||
| 340 | case 0xfb: /* sti */ | 368 | case 0xfb: /* sti */ |
| 341 | - ADD16(env->eip, 1); | 369 | + env->eip = ip; |
| 342 | if (set_IF(env)) | 370 | if (set_IF(env)) |
| 343 | return; | 371 | return; |
| 344 | VM86_FAULT_RETURN; | 372 | VM86_FAULT_RETURN; |
| 345 | 373 | ||
| 346 | default: | 374 | default: |
| 347 | - vm86_gpf: | ||
| 348 | /* real VM86 GPF exception */ | 375 | /* real VM86 GPF exception */ |
| 349 | return_to_32bit(env, TARGET_VM86_UNKNOWN); | 376 | return_to_32bit(env, TARGET_VM86_UNKNOWN); |
| 350 | break; | 377 | break; |
| @@ -398,7 +425,22 @@ int do_vm86(CPUX86State *env, long subfunction, | @@ -398,7 +425,22 @@ int do_vm86(CPUX86State *env, long subfunction, | ||
| 398 | ts->v86flags = tswap32(target_v86->regs.eflags); | 425 | ts->v86flags = tswap32(target_v86->regs.eflags); |
| 399 | env->eflags = (env->eflags & ~SAFE_MASK) | | 426 | env->eflags = (env->eflags & ~SAFE_MASK) | |
| 400 | (tswap32(target_v86->regs.eflags) & SAFE_MASK) | VM_MASK; | 427 | (tswap32(target_v86->regs.eflags) & SAFE_MASK) | VM_MASK; |
| 401 | - ts->v86mask = ID_MASK | AC_MASK | NT_MASK | IOPL_MASK; | 428 | + |
| 429 | + ts->vm86plus.cpu_type = tswapl(target_v86->cpu_type); | ||
| 430 | + switch (ts->vm86plus.cpu_type) { | ||
| 431 | + case TARGET_CPU_286: | ||
| 432 | + ts->v86mask = 0; | ||
| 433 | + break; | ||
| 434 | + case TARGET_CPU_386: | ||
| 435 | + ts->v86mask = NT_MASK | IOPL_MASK; | ||
| 436 | + break; | ||
| 437 | + case TARGET_CPU_486: | ||
| 438 | + ts->v86mask = AC_MASK | NT_MASK | IOPL_MASK; | ||
| 439 | + break; | ||
| 440 | + default: | ||
| 441 | + ts->v86mask = ID_MASK | AC_MASK | NT_MASK | IOPL_MASK; | ||
| 442 | + break; | ||
| 443 | + } | ||
| 402 | 444 | ||
| 403 | env->regs[R_EBX] = tswap32(target_v86->regs.ebx); | 445 | env->regs[R_EBX] = tswap32(target_v86->regs.ebx); |
| 404 | env->regs[R_ECX] = tswap32(target_v86->regs.ecx); | 446 | env->regs[R_ECX] = tswap32(target_v86->regs.ecx); |
| @@ -416,6 +458,14 @@ int do_vm86(CPUX86State *env, long subfunction, | @@ -416,6 +458,14 @@ int do_vm86(CPUX86State *env, long subfunction, | ||
| 416 | cpu_x86_load_seg(env, R_GS, tswap16(target_v86->regs.gs)); | 458 | cpu_x86_load_seg(env, R_GS, tswap16(target_v86->regs.gs)); |
| 417 | ret = tswap32(target_v86->regs.eax); /* eax will be restored at | 459 | ret = tswap32(target_v86->regs.eax); /* eax will be restored at |
| 418 | the end of the syscall */ | 460 | the end of the syscall */ |
| 461 | + memcpy(&ts->vm86plus.int_revectored, | ||
| 462 | + &target_v86->int_revectored, 32); | ||
| 463 | + memcpy(&ts->vm86plus.int21_revectored, | ||
| 464 | + &target_v86->int21_revectored, 32); | ||
| 465 | + ts->vm86plus.vm86plus.flags = tswapl(target_v86->vm86plus.flags); | ||
| 466 | + memcpy(&ts->vm86plus.vm86plus.vm86dbg_intxxtab, | ||
| 467 | + target_v86->vm86plus.vm86dbg_intxxtab, 32); | ||
| 468 | + | ||
| 419 | #ifdef DEBUG_VM86 | 469 | #ifdef DEBUG_VM86 |
| 420 | fprintf(logfile, "do_vm86: cs:ip=%04x:%04x\n", env->segs[R_CS], env->eip); | 470 | fprintf(logfile, "do_vm86: cs:ip=%04x:%04x\n", env->segs[R_CS], env->eip); |
| 421 | #endif | 471 | #endif |
syscall-i386.h
| @@ -784,6 +784,13 @@ struct target_modify_ldt_ldt_s { | @@ -784,6 +784,13 @@ struct target_modify_ldt_ldt_s { | ||
| 784 | 784 | ||
| 785 | #define TARGET_BIOSSEG 0x0f000 | 785 | #define TARGET_BIOSSEG 0x0f000 |
| 786 | 786 | ||
| 787 | +#define TARGET_CPU_086 0 | ||
| 788 | +#define TARGET_CPU_186 1 | ||
| 789 | +#define TARGET_CPU_286 2 | ||
| 790 | +#define TARGET_CPU_386 3 | ||
| 791 | +#define TARGET_CPU_486 4 | ||
| 792 | +#define TARGET_CPU_586 5 | ||
| 793 | + | ||
| 787 | #define TARGET_VM86_SIGNAL 0 /* return due to signal */ | 794 | #define TARGET_VM86_SIGNAL 0 /* return due to signal */ |
| 788 | #define TARGET_VM86_UNKNOWN 1 /* unhandled GP fault - IO-instruction or similar */ | 795 | #define TARGET_VM86_UNKNOWN 1 /* unhandled GP fault - IO-instruction or similar */ |
| 789 | #define TARGET_VM86_INTx 2 /* int3/int x instruction (ARG = x) */ | 796 | #define TARGET_VM86_INTx 2 /* int3/int x instruction (ARG = x) */ |