Commit 08cea4eef8e17114dcdbce93f95cb111c9d622f6
1 parent
883da8e2
fixed ljmp and iret to TSS
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@682 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
10 additions
and
12 deletions
target-i386/exec.h
| @@ -123,11 +123,11 @@ typedef struct CCTable { | @@ -123,11 +123,11 @@ typedef struct CCTable { | ||
| 123 | extern CCTable cc_table[]; | 123 | extern CCTable cc_table[]; |
| 124 | 124 | ||
| 125 | void load_seg(int seg_reg, int selector); | 125 | void load_seg(int seg_reg, int selector); |
| 126 | -void helper_ljmp_protected_T0_T1(void); | 126 | +void helper_ljmp_protected_T0_T1(int next_eip); |
| 127 | void helper_lcall_real_T0_T1(int shift, int next_eip); | 127 | void helper_lcall_real_T0_T1(int shift, int next_eip); |
| 128 | void helper_lcall_protected_T0_T1(int shift, int next_eip); | 128 | void helper_lcall_protected_T0_T1(int shift, int next_eip); |
| 129 | void helper_iret_real(int shift); | 129 | void helper_iret_real(int shift); |
| 130 | -void helper_iret_protected(int shift); | 130 | +void helper_iret_protected(int shift, int next_eip); |
| 131 | void helper_lret_protected(int shift, int addend); | 131 | void helper_lret_protected(int shift, int addend); |
| 132 | void helper_lldt_T0(void); | 132 | void helper_lldt_T0(void); |
| 133 | void helper_ltr_T0(void); | 133 | void helper_ltr_T0(void); |
target-i386/helper.c
| @@ -1219,7 +1219,7 @@ void load_seg(int seg_reg, int selector) | @@ -1219,7 +1219,7 @@ void load_seg(int seg_reg, int selector) | ||
| 1219 | } | 1219 | } |
| 1220 | 1220 | ||
| 1221 | /* protected mode jump */ | 1221 | /* protected mode jump */ |
| 1222 | -void helper_ljmp_protected_T0_T1(void) | 1222 | +void helper_ljmp_protected_T0_T1(int next_eip) |
| 1223 | { | 1223 | { |
| 1224 | int new_cs, new_eip, gate_cs, type; | 1224 | int new_cs, new_eip, gate_cs, type; |
| 1225 | uint32_t e1, e2, cpl, dpl, rpl, limit; | 1225 | uint32_t e1, e2, cpl, dpl, rpl, limit; |
| @@ -1267,8 +1267,7 @@ void helper_ljmp_protected_T0_T1(void) | @@ -1267,8 +1267,7 @@ void helper_ljmp_protected_T0_T1(void) | ||
| 1267 | case 5: /* task gate */ | 1267 | case 5: /* task gate */ |
| 1268 | if (dpl < cpl || dpl < rpl) | 1268 | if (dpl < cpl || dpl < rpl) |
| 1269 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | 1269 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
| 1270 | - /* XXX: check if it is really the current EIP */ | ||
| 1271 | - switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, env->eip); | 1270 | + switch_tss(new_cs, e1, e2, SWITCH_TSS_JMP, next_eip); |
| 1272 | break; | 1271 | break; |
| 1273 | case 4: /* 286 call gate */ | 1272 | case 4: /* 286 call gate */ |
| 1274 | case 12: /* 386 call gate */ | 1273 | case 12: /* 386 call gate */ |
| @@ -1732,7 +1731,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) | @@ -1732,7 +1731,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) | ||
| 1732 | ESP = new_esp; | 1731 | ESP = new_esp; |
| 1733 | } | 1732 | } |
| 1734 | 1733 | ||
| 1735 | -void helper_iret_protected(int shift) | 1734 | +void helper_iret_protected(int shift, int next_eip) |
| 1736 | { | 1735 | { |
| 1737 | int tss_selector, type; | 1736 | int tss_selector, type; |
| 1738 | uint32_t e1, e2; | 1737 | uint32_t e1, e2; |
| @@ -1748,8 +1747,7 @@ void helper_iret_protected(int shift) | @@ -1748,8 +1747,7 @@ void helper_iret_protected(int shift) | ||
| 1748 | /* NOTE: we check both segment and busy TSS */ | 1747 | /* NOTE: we check both segment and busy TSS */ |
| 1749 | if (type != 3) | 1748 | if (type != 3) |
| 1750 | raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc); | 1749 | raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc); |
| 1751 | - /* XXX: check if it is really the current EIP */ | ||
| 1752 | - switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, env->eip); | 1750 | + switch_tss(tss_selector, e1, e2, SWITCH_TSS_IRET, next_eip); |
| 1753 | } else { | 1751 | } else { |
| 1754 | helper_ret_protected(shift, 1, 0); | 1752 | helper_ret_protected(shift, 1, 0); |
| 1755 | } | 1753 | } |
target-i386/op.c
| @@ -918,7 +918,7 @@ void OPPROTO op_arpl_update(void) | @@ -918,7 +918,7 @@ void OPPROTO op_arpl_update(void) | ||
| 918 | /* T0: segment, T1:eip */ | 918 | /* T0: segment, T1:eip */ |
| 919 | void OPPROTO op_ljmp_protected_T0_T1(void) | 919 | void OPPROTO op_ljmp_protected_T0_T1(void) |
| 920 | { | 920 | { |
| 921 | - helper_ljmp_protected_T0_T1(); | 921 | + helper_ljmp_protected_T0_T1(PARAM1); |
| 922 | } | 922 | } |
| 923 | 923 | ||
| 924 | void OPPROTO op_lcall_real_T0_T1(void) | 924 | void OPPROTO op_lcall_real_T0_T1(void) |
| @@ -938,7 +938,7 @@ void OPPROTO op_iret_real(void) | @@ -938,7 +938,7 @@ void OPPROTO op_iret_real(void) | ||
| 938 | 938 | ||
| 939 | void OPPROTO op_iret_protected(void) | 939 | void OPPROTO op_iret_protected(void) |
| 940 | { | 940 | { |
| 941 | - helper_iret_protected(PARAM1); | 941 | + helper_iret_protected(PARAM1, PARAM2); |
| 942 | } | 942 | } |
| 943 | 943 | ||
| 944 | void OPPROTO op_lret_protected(void) | 944 | void OPPROTO op_lret_protected(void) |
target-i386/translate.c
| @@ -2172,7 +2172,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2172,7 +2172,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2172 | if (s->cc_op != CC_OP_DYNAMIC) | 2172 | if (s->cc_op != CC_OP_DYNAMIC) |
| 2173 | gen_op_set_cc_op(s->cc_op); | 2173 | gen_op_set_cc_op(s->cc_op); |
| 2174 | gen_op_jmp_im(pc_start - s->cs_base); | 2174 | gen_op_jmp_im(pc_start - s->cs_base); |
| 2175 | - gen_op_ljmp_protected_T0_T1(); | 2175 | + gen_op_ljmp_protected_T0_T1(s->pc - s->cs_base); |
| 2176 | } else { | 2176 | } else { |
| 2177 | gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS])); | 2177 | gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS])); |
| 2178 | gen_op_movl_T0_T1(); | 2178 | gen_op_movl_T0_T1(); |
| @@ -3453,7 +3453,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3453,7 +3453,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 3453 | if (s->cc_op != CC_OP_DYNAMIC) | 3453 | if (s->cc_op != CC_OP_DYNAMIC) |
| 3454 | gen_op_set_cc_op(s->cc_op); | 3454 | gen_op_set_cc_op(s->cc_op); |
| 3455 | gen_op_jmp_im(pc_start - s->cs_base); | 3455 | gen_op_jmp_im(pc_start - s->cs_base); |
| 3456 | - gen_op_iret_protected(s->dflag); | 3456 | + gen_op_iret_protected(s->dflag, s->pc - s->cs_base); |
| 3457 | s->cc_op = CC_OP_EFLAGS; | 3457 | s->cc_op = CC_OP_EFLAGS; |
| 3458 | } | 3458 | } |
| 3459 | gen_eob(s); | 3459 | gen_eob(s); |