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); |