Commit b6d78bfa0dc11a7a23cb7ccc9b00b217e6fb68fe
1 parent
c33a346e
correct CPL support (should fix flat real mode support)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@343 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
27 additions
and
31 deletions
cpu-exec.c
| @@ -244,13 +244,8 @@ int cpu_exec(CPUState *env1) | @@ -244,13 +244,8 @@ int cpu_exec(CPUState *env1) | ||
| 244 | (unsigned long)env->segs[R_ES].base | | 244 | (unsigned long)env->segs[R_ES].base | |
| 245 | (unsigned long)env->segs[R_SS].base) != 0) << | 245 | (unsigned long)env->segs[R_SS].base) != 0) << |
| 246 | GEN_FLAG_ADDSEG_SHIFT; | 246 | GEN_FLAG_ADDSEG_SHIFT; |
| 247 | - if (env->cr[0] & CR0_PE_MASK) { | ||
| 248 | - if (!(env->eflags & VM_MASK)) | ||
| 249 | - flags |= (env->segs[R_CS].selector & 3) << | ||
| 250 | - GEN_FLAG_CPL_SHIFT; | ||
| 251 | - else | ||
| 252 | - flags |= (1 << GEN_FLAG_VM_SHIFT); | ||
| 253 | - } | 247 | + flags |= env->cpl << GEN_FLAG_CPL_SHIFT; |
| 248 | + flags |= (env->eflags & VM_MASK) >> (17 - GEN_FLAG_VM_SHIFT); | ||
| 254 | flags |= (env->eflags & (IOPL_MASK | TF_MASK)); | 249 | flags |= (env->eflags & (IOPL_MASK | TF_MASK)); |
| 255 | cs_base = env->segs[R_CS].base; | 250 | cs_base = env->segs[R_CS].base; |
| 256 | pc = cs_base + env->eip; | 251 | pc = cs_base + env->eip; |
cpu-i386.h
| @@ -256,6 +256,7 @@ typedef struct CPUX86State { | @@ -256,6 +256,7 @@ typedef struct CPUX86State { | ||
| 256 | SegmentCache tr; | 256 | SegmentCache tr; |
| 257 | SegmentCache gdt; /* only base and limit are used */ | 257 | SegmentCache gdt; /* only base and limit are used */ |
| 258 | SegmentCache idt; /* only base and limit are used */ | 258 | SegmentCache idt; /* only base and limit are used */ |
| 259 | + int cpl; /* current cpl */ | ||
| 259 | 260 | ||
| 260 | /* sysenter registers */ | 261 | /* sysenter registers */ |
| 261 | uint32_t sysenter_cs; | 262 | uint32_t sysenter_cs; |
| @@ -276,6 +277,7 @@ typedef struct CPUX86State { | @@ -276,6 +277,7 @@ typedef struct CPUX86State { | ||
| 276 | 277 | ||
| 277 | uint32_t breakpoints[MAX_BREAKPOINTS]; | 278 | uint32_t breakpoints[MAX_BREAKPOINTS]; |
| 278 | int nb_breakpoints; | 279 | int nb_breakpoints; |
| 280 | + int singlestep_enabled; | ||
| 279 | 281 | ||
| 280 | /* user data */ | 282 | /* user data */ |
| 281 | void *opaque; | 283 | void *opaque; |
| @@ -298,6 +300,12 @@ int cpu_x86_get_pic_interrupt(CPUX86State *s); | @@ -298,6 +300,12 @@ int cpu_x86_get_pic_interrupt(CPUX86State *s); | ||
| 298 | /* needed to load some predefinied segment registers */ | 300 | /* needed to load some predefinied segment registers */ |
| 299 | void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector); | 301 | void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector); |
| 300 | 302 | ||
| 303 | +/* wrapper, just in case memory mappings must be changed */ | ||
| 304 | +static inline void cpu_x86_set_cpl(CPUX86State *s, int cpl) | ||
| 305 | +{ | ||
| 306 | + s->cpl = cpl; | ||
| 307 | +} | ||
| 308 | + | ||
| 301 | /* simulate fsave/frstor */ | 309 | /* simulate fsave/frstor */ |
| 302 | void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32); | 310 | void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32); |
| 303 | void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32); | 311 | void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32); |
helper-i386.c
| @@ -189,7 +189,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, | @@ -189,7 +189,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, | ||
| 189 | { | 189 | { |
| 190 | SegmentCache *dt; | 190 | SegmentCache *dt; |
| 191 | uint8_t *ptr, *ssp; | 191 | uint8_t *ptr, *ssp; |
| 192 | - int type, dpl, cpl, selector, ss_dpl; | 192 | + int type, dpl, selector, ss_dpl; |
| 193 | int has_error_code, new_stack, shift; | 193 | int has_error_code, new_stack, shift; |
| 194 | uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2, push_size; | 194 | uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2, push_size; |
| 195 | uint32_t old_cs, old_ss, old_esp, old_eip; | 195 | uint32_t old_cs, old_ss, old_esp, old_eip; |
| @@ -216,12 +216,8 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, | @@ -216,12 +216,8 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, | ||
| 216 | break; | 216 | break; |
| 217 | } | 217 | } |
| 218 | dpl = (e2 >> DESC_DPL_SHIFT) & 3; | 218 | dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
| 219 | - if (env->eflags & VM_MASK) | ||
| 220 | - cpl = 3; | ||
| 221 | - else | ||
| 222 | - cpl = env->segs[R_CS].selector & 3; | ||
| 223 | /* check privledge if software int */ | 219 | /* check privledge if software int */ |
| 224 | - if (is_int && dpl < cpl) | 220 | + if (is_int && dpl < env->cpl) |
| 225 | raise_exception_err(EXCP0D_GPF, intno * 8 + 2); | 221 | raise_exception_err(EXCP0D_GPF, intno * 8 + 2); |
| 226 | /* check valid bit */ | 222 | /* check valid bit */ |
| 227 | if (!(e2 & DESC_P_MASK)) | 223 | if (!(e2 & DESC_P_MASK)) |
| @@ -236,11 +232,11 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, | @@ -236,11 +232,11 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, | ||
| 236 | if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) | 232 | if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) |
| 237 | raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | 233 | raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
| 238 | dpl = (e2 >> DESC_DPL_SHIFT) & 3; | 234 | dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
| 239 | - if (dpl > cpl) | 235 | + if (dpl > env->cpl) |
| 240 | raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | 236 | raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
| 241 | if (!(e2 & DESC_P_MASK)) | 237 | if (!(e2 & DESC_P_MASK)) |
| 242 | raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); | 238 | raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); |
| 243 | - if (!(e2 & DESC_C_MASK) && dpl < cpl) { | 239 | + if (!(e2 & DESC_C_MASK) && dpl < env->cpl) { |
| 244 | /* to inner priviledge */ | 240 | /* to inner priviledge */ |
| 245 | get_ss_esp_from_tss(&ss, &esp, dpl); | 241 | get_ss_esp_from_tss(&ss, &esp, dpl); |
| 246 | if ((ss & 0xfffc) == 0) | 242 | if ((ss & 0xfffc) == 0) |
| @@ -259,7 +255,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, | @@ -259,7 +255,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, | ||
| 259 | if (!(ss_e2 & DESC_P_MASK)) | 255 | if (!(ss_e2 & DESC_P_MASK)) |
| 260 | raise_exception_err(EXCP0A_TSS, ss & 0xfffc); | 256 | raise_exception_err(EXCP0A_TSS, ss & 0xfffc); |
| 261 | new_stack = 1; | 257 | new_stack = 1; |
| 262 | - } else if ((e2 & DESC_C_MASK) || dpl == cpl) { | 258 | + } else if ((e2 & DESC_C_MASK) || dpl == env->cpl) { |
| 263 | /* to same priviledge */ | 259 | /* to same priviledge */ |
| 264 | new_stack = 0; | 260 | new_stack = 0; |
| 265 | } else { | 261 | } else { |
| @@ -406,7 +402,7 @@ void do_interrupt_user(int intno, int is_int, int error_code, | @@ -406,7 +402,7 @@ void do_interrupt_user(int intno, int is_int, int error_code, | ||
| 406 | { | 402 | { |
| 407 | SegmentCache *dt; | 403 | SegmentCache *dt; |
| 408 | uint8_t *ptr; | 404 | uint8_t *ptr; |
| 409 | - int dpl, cpl; | 405 | + int dpl; |
| 410 | uint32_t e2; | 406 | uint32_t e2; |
| 411 | 407 | ||
| 412 | dt = &env->idt; | 408 | dt = &env->idt; |
| @@ -414,9 +410,8 @@ void do_interrupt_user(int intno, int is_int, int error_code, | @@ -414,9 +410,8 @@ void do_interrupt_user(int intno, int is_int, int error_code, | ||
| 414 | e2 = ldl(ptr + 4); | 410 | e2 = ldl(ptr + 4); |
| 415 | 411 | ||
| 416 | dpl = (e2 >> DESC_DPL_SHIFT) & 3; | 412 | dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
| 417 | - cpl = 3; | ||
| 418 | /* check privledge if software int */ | 413 | /* check privledge if software int */ |
| 419 | - if (is_int && dpl < cpl) | 414 | + if (is_int && dpl < env->cpl) |
| 420 | raise_exception_err(EXCP0D_GPF, intno * 8 + 2); | 415 | raise_exception_err(EXCP0D_GPF, intno * 8 + 2); |
| 421 | 416 | ||
| 422 | /* Since we emulate only user space, we cannot do more than | 417 | /* Since we emulate only user space, we cannot do more than |
| @@ -728,6 +723,9 @@ void load_seg(int seg_reg, int selector, unsigned int cur_eip) | @@ -728,6 +723,9 @@ void load_seg(int seg_reg, int selector, unsigned int cur_eip) | ||
| 728 | selector, (unsigned long)sc->base, sc->limit, sc->flags); | 723 | selector, (unsigned long)sc->base, sc->limit, sc->flags); |
| 729 | #endif | 724 | #endif |
| 730 | } | 725 | } |
| 726 | + if (seg_reg == R_CS) { | ||
| 727 | + cpu_x86_set_cpl(env, selector & 3); | ||
| 728 | + } | ||
| 731 | sc->selector = selector; | 729 | sc->selector = selector; |
| 732 | } | 730 | } |
| 733 | 731 | ||
| @@ -744,7 +742,7 @@ void helper_ljmp_protected_T0_T1(void) | @@ -744,7 +742,7 @@ void helper_ljmp_protected_T0_T1(void) | ||
| 744 | raise_exception_err(EXCP0D_GPF, 0); | 742 | raise_exception_err(EXCP0D_GPF, 0); |
| 745 | if (load_segment(&e1, &e2, new_cs) != 0) | 743 | if (load_segment(&e1, &e2, new_cs) != 0) |
| 746 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | 744 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
| 747 | - cpl = env->segs[R_CS].selector & 3; | 745 | + cpl = env->cpl; |
| 748 | if (e2 & DESC_S_MASK) { | 746 | if (e2 & DESC_S_MASK) { |
| 749 | if (!(e2 & DESC_CS_MASK)) | 747 | if (!(e2 & DESC_CS_MASK)) |
| 750 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | 748 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
| @@ -828,7 +826,7 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip) | @@ -828,7 +826,7 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip) | ||
| 828 | raise_exception_err(EXCP0D_GPF, 0); | 826 | raise_exception_err(EXCP0D_GPF, 0); |
| 829 | if (load_segment(&e1, &e2, new_cs) != 0) | 827 | if (load_segment(&e1, &e2, new_cs) != 0) |
| 830 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | 828 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
| 831 | - cpl = env->segs[R_CS].selector & 3; | 829 | + cpl = env->cpl; |
| 832 | if (e2 & DESC_S_MASK) { | 830 | if (e2 & DESC_S_MASK) { |
| 833 | if (!(e2 & DESC_CS_MASK)) | 831 | if (!(e2 & DESC_CS_MASK)) |
| 834 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | 832 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
| @@ -1081,7 +1079,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) | @@ -1081,7 +1079,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) | ||
| 1081 | if (!(e2 & DESC_S_MASK) || | 1079 | if (!(e2 & DESC_S_MASK) || |
| 1082 | !(e2 & DESC_CS_MASK)) | 1080 | !(e2 & DESC_CS_MASK)) |
| 1083 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | 1081 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
| 1084 | - cpl = env->segs[R_CS].selector & 3; | 1082 | + cpl = env->cpl; |
| 1085 | rpl = new_cs & 3; | 1083 | rpl = new_cs & 3; |
| 1086 | if (rpl < cpl) | 1084 | if (rpl < cpl) |
| 1087 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | 1085 | raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
| @@ -1158,12 +1156,13 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) | @@ -1158,12 +1156,13 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) | ||
| 1158 | /* modify processor state */ | 1156 | /* modify processor state */ |
| 1159 | load_eflags(new_eflags, FL_UPDATE_CPL0_MASK | VM_MASK | VIF_MASK | VIP_MASK); | 1157 | load_eflags(new_eflags, FL_UPDATE_CPL0_MASK | VM_MASK | VIF_MASK | VIP_MASK); |
| 1160 | load_seg_vm(R_CS, new_cs); | 1158 | load_seg_vm(R_CS, new_cs); |
| 1159 | + cpu_x86_set_cpl(env, 3); | ||
| 1161 | load_seg_vm(R_SS, new_ss); | 1160 | load_seg_vm(R_SS, new_ss); |
| 1162 | load_seg_vm(R_ES, new_es); | 1161 | load_seg_vm(R_ES, new_es); |
| 1163 | load_seg_vm(R_DS, new_ds); | 1162 | load_seg_vm(R_DS, new_ds); |
| 1164 | load_seg_vm(R_FS, new_fs); | 1163 | load_seg_vm(R_FS, new_fs); |
| 1165 | load_seg_vm(R_GS, new_gs); | 1164 | load_seg_vm(R_GS, new_gs); |
| 1166 | - | 1165 | + |
| 1167 | env->eip = new_eip; | 1166 | env->eip = new_eip; |
| 1168 | env->regs[R_ESP] = new_esp; | 1167 | env->regs[R_ESP] = new_esp; |
| 1169 | } | 1168 | } |
translate-i386.c
| @@ -4113,13 +4113,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, | @@ -4113,13 +4113,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, | ||
| 4113 | dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1; | 4113 | dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1; |
| 4114 | dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7; | 4114 | dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7; |
| 4115 | dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1; | 4115 | dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1; |
| 4116 | - /* CPL is implicit if real mode or vm86 mode */ | ||
| 4117 | - if (!dc->pe) | ||
| 4118 | - dc->cpl = 0; | ||
| 4119 | - else if (dc->vm86) | ||
| 4120 | - dc->cpl = 3; | ||
| 4121 | - else | ||
| 4122 | - dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3; | 4116 | + dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3; |
| 4123 | dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3; | 4117 | dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3; |
| 4124 | dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1; | 4118 | dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1; |
| 4125 | dc->cc_op = CC_OP_DYNAMIC; | 4119 | dc->cc_op = CC_OP_DYNAMIC; |
| @@ -4362,7 +4356,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write) | @@ -4362,7 +4356,7 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write) | ||
| 4362 | int cpl, error_code, is_dirty, is_user, prot, page_size; | 4356 | int cpl, error_code, is_dirty, is_user, prot, page_size; |
| 4363 | void *map_addr; | 4357 | void *map_addr; |
| 4364 | 4358 | ||
| 4365 | - cpl = env->segs[R_CS].selector & 3; | 4359 | + cpl = env->cpl; |
| 4366 | is_user = (cpl == 3); | 4360 | is_user = (cpl == 3); |
| 4367 | 4361 | ||
| 4368 | #ifdef DEBUG_MMU | 4362 | #ifdef DEBUG_MMU |