Commit 8145122b0862ff307ebb4c50ffd0207c675685dc
1 parent
7399c5a9
correct NT flag behavior - zero ldt task switch bug fix - task switch thru call insn bug fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@586 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
47 additions
and
24 deletions
target-i386/helper.c
| @@ -21,6 +21,14 @@ | @@ -21,6 +21,14 @@ | ||
| 21 | 21 | ||
| 22 | //#define DEBUG_PCALL | 22 | //#define DEBUG_PCALL |
| 23 | 23 | ||
| 24 | +#if 0 | ||
| 25 | +#define raise_exception_err(a, b)\ | ||
| 26 | +do {\ | ||
| 27 | + printf("raise_exception line=%d\n", __LINE__);\ | ||
| 28 | + (raise_exception_err)(a, b);\ | ||
| 29 | +} while (0) | ||
| 30 | +#endif | ||
| 31 | + | ||
| 24 | const uint8_t parity_table[256] = { | 32 | const uint8_t parity_table[256] = { |
| 25 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | 33 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, |
| 26 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | 34 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, |
| @@ -424,7 +432,7 @@ static void switch_tss(int tss_selector, | @@ -424,7 +432,7 @@ static void switch_tss(int tss_selector, | ||
| 424 | possible exception */ | 432 | possible exception */ |
| 425 | env->eip = new_eip; | 433 | env->eip = new_eip; |
| 426 | eflags_mask = TF_MASK | AC_MASK | ID_MASK | | 434 | eflags_mask = TF_MASK | AC_MASK | ID_MASK | |
| 427 | - IF_MASK | IOPL_MASK | VM_MASK | RF_MASK; | 435 | + IF_MASK | IOPL_MASK | VM_MASK | RF_MASK | NT_MASK; |
| 428 | if (!(type & 8)) | 436 | if (!(type & 8)) |
| 429 | eflags_mask &= 0xffff; | 437 | eflags_mask &= 0xffff; |
| 430 | load_eflags(new_eflags, eflags_mask); | 438 | load_eflags(new_eflags, eflags_mask); |
| @@ -452,18 +460,20 @@ static void switch_tss(int tss_selector, | @@ -452,18 +460,20 @@ static void switch_tss(int tss_selector, | ||
| 452 | if (new_ldt & 4) | 460 | if (new_ldt & 4) |
| 453 | raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc); | 461 | raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc); |
| 454 | 462 | ||
| 455 | - dt = &env->gdt; | ||
| 456 | - index = new_ldt & ~7; | ||
| 457 | - if ((index + 7) > dt->limit) | ||
| 458 | - raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc); | ||
| 459 | - ptr = dt->base + index; | ||
| 460 | - e1 = ldl_kernel(ptr); | ||
| 461 | - e2 = ldl_kernel(ptr + 4); | ||
| 462 | - if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2) | ||
| 463 | - raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc); | ||
| 464 | - if (!(e2 & DESC_P_MASK)) | ||
| 465 | - raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc); | ||
| 466 | - load_seg_cache_raw_dt(&env->ldt, e1, e2); | 463 | + if ((new_ldt & 0xfffc) != 0) { |
| 464 | + dt = &env->gdt; | ||
| 465 | + index = new_ldt & ~7; | ||
| 466 | + if ((index + 7) > dt->limit) | ||
| 467 | + raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc); | ||
| 468 | + ptr = dt->base + index; | ||
| 469 | + e1 = ldl_kernel(ptr); | ||
| 470 | + e2 = ldl_kernel(ptr + 4); | ||
| 471 | + if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2) | ||
| 472 | + raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc); | ||
| 473 | + if (!(e2 & DESC_P_MASK)) | ||
| 474 | + raise_exception_err(EXCP0A_TSS, new_ldt & 0xfffc); | ||
| 475 | + load_seg_cache_raw_dt(&env->ldt, e1, e2); | ||
| 476 | + } | ||
| 467 | 477 | ||
| 468 | /* load the segments */ | 478 | /* load the segments */ |
| 469 | if (!(new_eflags & VM_MASK)) { | 479 | if (!(new_eflags & VM_MASK)) { |
| @@ -748,6 +758,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, | @@ -748,6 +758,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, | ||
| 748 | if (env->eflags & VM_MASK) { | 758 | if (env->eflags & VM_MASK) { |
| 749 | /* XXX: explain me why W2K hangs if the whole segment cache is | 759 | /* XXX: explain me why W2K hangs if the whole segment cache is |
| 750 | reset ? */ | 760 | reset ? */ |
| 761 | +#if 1 | ||
| 751 | env->segs[R_ES].selector = 0; | 762 | env->segs[R_ES].selector = 0; |
| 752 | env->segs[R_ES].flags = 0; | 763 | env->segs[R_ES].flags = 0; |
| 753 | env->segs[R_DS].selector = 0; | 764 | env->segs[R_DS].selector = 0; |
| @@ -756,6 +767,12 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, | @@ -756,6 +767,12 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, | ||
| 756 | env->segs[R_FS].flags = 0; | 767 | env->segs[R_FS].flags = 0; |
| 757 | env->segs[R_GS].selector = 0; | 768 | env->segs[R_GS].selector = 0; |
| 758 | env->segs[R_GS].flags = 0; | 769 | env->segs[R_GS].flags = 0; |
| 770 | +#else | ||
| 771 | + cpu_x86_load_seg_cache(env, R_ES, 0, NULL, 0, 0); | ||
| 772 | + cpu_x86_load_seg_cache(env, R_DS, 0, NULL, 0, 0); | ||
| 773 | + cpu_x86_load_seg_cache(env, R_FS, 0, NULL, 0, 0); | ||
| 774 | + cpu_x86_load_seg_cache(env, R_GS, 0, NULL, 0, 0); | ||
| 775 | +#endif | ||
| 759 | } | 776 | } |
| 760 | ss = (ss & ~3) | dpl; | 777 | ss = (ss & ~3) | dpl; |
| 761 | cpu_x86_load_seg_cache(env, R_SS, ss, | 778 | cpu_x86_load_seg_cache(env, R_SS, ss, |
| @@ -853,13 +870,19 @@ void do_interrupt(int intno, int is_int, int error_code, | @@ -853,13 +870,19 @@ void do_interrupt(int intno, int is_int, int error_code, | ||
| 853 | { | 870 | { |
| 854 | extern FILE *stdout; | 871 | extern FILE *stdout; |
| 855 | static int count; | 872 | static int count; |
| 856 | - if ((env->cr[0] && CR0_PE_MASK)) { | ||
| 857 | - fprintf(stdout, "%d: interrupt: vector=%02x error_code=%04x int=%d CPL=%d CS:EIP=%04x:%08x SS:ESP=%04x:%08x EAX=%08x\n", | 873 | + if (env->cr[0] & CR0_PE_MASK) { |
| 874 | + fprintf(stdout, "%d: v=%02x e=%04x i=%d CPL=%d CS:EIP=%04x:%08x SS:ESP=%04x:%08x", | ||
| 858 | count, intno, error_code, is_int, | 875 | count, intno, error_code, is_int, |
| 859 | env->hflags & HF_CPL_MASK, | 876 | env->hflags & HF_CPL_MASK, |
| 860 | env->segs[R_CS].selector, EIP, | 877 | env->segs[R_CS].selector, EIP, |
| 861 | - env->segs[R_SS].selector, ESP, | ||
| 862 | - EAX); | 878 | + env->segs[R_SS].selector, ESP); |
| 879 | + if (intno == 0x0e) { | ||
| 880 | + fprintf(stdout, " CR2=%08x", env->cr[2]); | ||
| 881 | + } else { | ||
| 882 | + fprintf(stdout, " EAX=%08x", env->regs[R_EAX]); | ||
| 883 | + } | ||
| 884 | + fprintf(stdout, "\n"); | ||
| 885 | + | ||
| 863 | if (0) { | 886 | if (0) { |
| 864 | cpu_x86_dump_state(env, stdout, X86_DUMP_CCOP); | 887 | cpu_x86_dump_state(env, stdout, X86_DUMP_CCOP); |
| 865 | #if 0 | 888 | #if 0 |
| @@ -879,7 +902,6 @@ void do_interrupt(int intno, int is_int, int error_code, | @@ -879,7 +902,6 @@ void do_interrupt(int intno, int is_int, int error_code, | ||
| 879 | } | 902 | } |
| 880 | } | 903 | } |
| 881 | #endif | 904 | #endif |
| 882 | - | ||
| 883 | #ifdef DEBUG_PCALL | 905 | #ifdef DEBUG_PCALL |
| 884 | if (loglevel) { | 906 | if (loglevel) { |
| 885 | static int count; | 907 | static int count; |
| @@ -925,7 +947,8 @@ void raise_interrupt(int intno, int is_int, int error_code, | @@ -925,7 +947,8 @@ void raise_interrupt(int intno, int is_int, int error_code, | ||
| 925 | } | 947 | } |
| 926 | 948 | ||
| 927 | /* shortcuts to generate exceptions */ | 949 | /* shortcuts to generate exceptions */ |
| 928 | -void raise_exception_err(int exception_index, int error_code) | 950 | + |
| 951 | +void (raise_exception_err)(int exception_index, int error_code) | ||
| 929 | { | 952 | { |
| 930 | raise_interrupt(exception_index, 0, error_code, 0); | 953 | raise_interrupt(exception_index, 0, error_code, 0); |
| 931 | } | 954 | } |
| @@ -1409,7 +1432,7 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip) | @@ -1409,7 +1432,7 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip) | ||
| 1409 | if (dpl < cpl || dpl < rpl) | 1432 | if (dpl < cpl || dpl < rpl) |
| 1410 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | 1433 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
| 1411 | switch_tss(new_cs, e1, e2, SWITCH_TSS_CALL); | 1434 | switch_tss(new_cs, e1, e2, SWITCH_TSS_CALL); |
| 1412 | - break; | 1435 | + return; |
| 1413 | case 4: /* 286 call gate */ | 1436 | case 4: /* 286 call gate */ |
| 1414 | case 12: /* 386 call gate */ | 1437 | case 12: /* 386 call gate */ |
| 1415 | break; | 1438 | break; |
| @@ -1551,9 +1574,9 @@ void helper_iret_real(int shift) | @@ -1551,9 +1574,9 @@ void helper_iret_real(int shift) | ||
| 1551 | load_seg_vm(R_CS, new_cs); | 1574 | load_seg_vm(R_CS, new_cs); |
| 1552 | env->eip = new_eip; | 1575 | env->eip = new_eip; |
| 1553 | if (env->eflags & VM_MASK) | 1576 | if (env->eflags & VM_MASK) |
| 1554 | - eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK; | 1577 | + eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK | NT_MASK; |
| 1555 | else | 1578 | else |
| 1556 | - eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK; | 1579 | + eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK | NT_MASK; |
| 1557 | if (shift == 0) | 1580 | if (shift == 0) |
| 1558 | eflags_mask &= 0xffff; | 1581 | eflags_mask &= 0xffff; |
| 1559 | load_eflags(new_eflags, eflags_mask); | 1582 | load_eflags(new_eflags, eflags_mask); |
| @@ -1688,7 +1711,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) | @@ -1688,7 +1711,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) | ||
| 1688 | env->eip = new_eip; | 1711 | env->eip = new_eip; |
| 1689 | if (is_iret) { | 1712 | if (is_iret) { |
| 1690 | /* NOTE: 'cpl' is the _old_ CPL */ | 1713 | /* NOTE: 'cpl' is the _old_ CPL */ |
| 1691 | - eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK; | 1714 | + eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK; |
| 1692 | if (cpl == 0) | 1715 | if (cpl == 0) |
| 1693 | eflags_mask |= IOPL_MASK; | 1716 | eflags_mask |= IOPL_MASK; |
| 1694 | iopl = (env->eflags >> IOPL_SHIFT) & 3; | 1717 | iopl = (env->eflags >> IOPL_SHIFT) & 3; |
| @@ -1710,7 +1733,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) | @@ -1710,7 +1733,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) | ||
| 1710 | 1733 | ||
| 1711 | /* modify processor state */ | 1734 | /* modify processor state */ |
| 1712 | load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK | | 1735 | load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK | |
| 1713 | - IF_MASK | IOPL_MASK | VM_MASK | VIF_MASK | VIP_MASK); | 1736 | + IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK | VIP_MASK); |
| 1714 | load_seg_vm(R_CS, new_cs & 0xffff); | 1737 | load_seg_vm(R_CS, new_cs & 0xffff); |
| 1715 | cpu_x86_set_cpl(env, 3); | 1738 | cpu_x86_set_cpl(env, 3); |
| 1716 | load_seg_vm(R_SS, new_ss & 0xffff); | 1739 | load_seg_vm(R_SS, new_ss & 0xffff); |