189 |
{ |
{ |
190 |
SegmentCache *dt; |
SegmentCache *dt; |
191 |
uint8_t *ptr, *ssp; |
uint8_t *ptr, *ssp; |
192 |
int type, dpl, cpl, selector, ss_dpl; |
int type, dpl, selector, ss_dpl; |
193 |
int has_error_code, new_stack, shift; |
int has_error_code, new_stack, shift; |
194 |
uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2, push_size; |
uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2, push_size; |
195 |
uint32_t old_cs, old_ss, old_esp, old_eip; |
uint32_t old_cs, old_ss, old_esp, old_eip; |
216 |
break; |
break; |
217 |
} |
} |
218 |
dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
|
if (env->eflags & VM_MASK) |
|
|
cpl = 3; |
|
|
else |
|
|
cpl = env->segs[R_CS].selector & 3; |
|
219 |
/* check privledge if software int */ |
/* check privledge if software int */ |
220 |
if (is_int && dpl < cpl) |
if (is_int && dpl < env->cpl) |
221 |
raise_exception_err(EXCP0D_GPF, intno * 8 + 2); |
raise_exception_err(EXCP0D_GPF, intno * 8 + 2); |
222 |
/* check valid bit */ |
/* check valid bit */ |
223 |
if (!(e2 & DESC_P_MASK)) |
if (!(e2 & DESC_P_MASK)) |
232 |
if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) |
if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) |
233 |
raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
234 |
dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
235 |
if (dpl > cpl) |
if (dpl > env->cpl) |
236 |
raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
237 |
if (!(e2 & DESC_P_MASK)) |
if (!(e2 & DESC_P_MASK)) |
238 |
raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); |
raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); |
239 |
if (!(e2 & DESC_C_MASK) && dpl < cpl) { |
if (!(e2 & DESC_C_MASK) && dpl < env->cpl) { |
240 |
/* to inner priviledge */ |
/* to inner priviledge */ |
241 |
get_ss_esp_from_tss(&ss, &esp, dpl); |
get_ss_esp_from_tss(&ss, &esp, dpl); |
242 |
if ((ss & 0xfffc) == 0) |
if ((ss & 0xfffc) == 0) |
255 |
if (!(ss_e2 & DESC_P_MASK)) |
if (!(ss_e2 & DESC_P_MASK)) |
256 |
raise_exception_err(EXCP0A_TSS, ss & 0xfffc); |
raise_exception_err(EXCP0A_TSS, ss & 0xfffc); |
257 |
new_stack = 1; |
new_stack = 1; |
258 |
} else if ((e2 & DESC_C_MASK) || dpl == cpl) { |
} else if ((e2 & DESC_C_MASK) || dpl == env->cpl) { |
259 |
/* to same priviledge */ |
/* to same priviledge */ |
260 |
new_stack = 0; |
new_stack = 0; |
261 |
} else { |
} else { |
402 |
{ |
{ |
403 |
SegmentCache *dt; |
SegmentCache *dt; |
404 |
uint8_t *ptr; |
uint8_t *ptr; |
405 |
int dpl, cpl; |
int dpl; |
406 |
uint32_t e2; |
uint32_t e2; |
407 |
|
|
408 |
dt = &env->idt; |
dt = &env->idt; |
410 |
e2 = ldl(ptr + 4); |
e2 = ldl(ptr + 4); |
411 |
|
|
412 |
dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
|
cpl = 3; |
|
413 |
/* check privledge if software int */ |
/* check privledge if software int */ |
414 |
if (is_int && dpl < cpl) |
if (is_int && dpl < env->cpl) |
415 |
raise_exception_err(EXCP0D_GPF, intno * 8 + 2); |
raise_exception_err(EXCP0D_GPF, intno * 8 + 2); |
416 |
|
|
417 |
/* Since we emulate only user space, we cannot do more than |
/* Since we emulate only user space, we cannot do more than |
723 |
selector, (unsigned long)sc->base, sc->limit, sc->flags); |
selector, (unsigned long)sc->base, sc->limit, sc->flags); |
724 |
#endif |
#endif |
725 |
} |
} |
726 |
|
if (seg_reg == R_CS) { |
727 |
|
cpu_x86_set_cpl(env, selector & 3); |
728 |
|
} |
729 |
sc->selector = selector; |
sc->selector = selector; |
730 |
} |
} |
731 |
|
|
742 |
raise_exception_err(EXCP0D_GPF, 0); |
raise_exception_err(EXCP0D_GPF, 0); |
743 |
if (load_segment(&e1, &e2, new_cs) != 0) |
if (load_segment(&e1, &e2, new_cs) != 0) |
744 |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
745 |
cpl = env->segs[R_CS].selector & 3; |
cpl = env->cpl; |
746 |
if (e2 & DESC_S_MASK) { |
if (e2 & DESC_S_MASK) { |
747 |
if (!(e2 & DESC_CS_MASK)) |
if (!(e2 & DESC_CS_MASK)) |
748 |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
826 |
raise_exception_err(EXCP0D_GPF, 0); |
raise_exception_err(EXCP0D_GPF, 0); |
827 |
if (load_segment(&e1, &e2, new_cs) != 0) |
if (load_segment(&e1, &e2, new_cs) != 0) |
828 |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
829 |
cpl = env->segs[R_CS].selector & 3; |
cpl = env->cpl; |
830 |
if (e2 & DESC_S_MASK) { |
if (e2 & DESC_S_MASK) { |
831 |
if (!(e2 & DESC_CS_MASK)) |
if (!(e2 & DESC_CS_MASK)) |
832 |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
1079 |
if (!(e2 & DESC_S_MASK) || |
if (!(e2 & DESC_S_MASK) || |
1080 |
!(e2 & DESC_CS_MASK)) |
!(e2 & DESC_CS_MASK)) |
1081 |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
1082 |
cpl = env->segs[R_CS].selector & 3; |
cpl = env->cpl; |
1083 |
rpl = new_cs & 3; |
rpl = new_cs & 3; |
1084 |
if (rpl < cpl) |
if (rpl < cpl) |
1085 |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
1156 |
/* modify processor state */ |
/* modify processor state */ |
1157 |
load_eflags(new_eflags, FL_UPDATE_CPL0_MASK | VM_MASK | VIF_MASK | VIP_MASK); |
load_eflags(new_eflags, FL_UPDATE_CPL0_MASK | VM_MASK | VIF_MASK | VIP_MASK); |
1158 |
load_seg_vm(R_CS, new_cs); |
load_seg_vm(R_CS, new_cs); |
1159 |
|
cpu_x86_set_cpl(env, 3); |
1160 |
load_seg_vm(R_SS, new_ss); |
load_seg_vm(R_SS, new_ss); |
1161 |
load_seg_vm(R_ES, new_es); |
load_seg_vm(R_ES, new_es); |
1162 |
load_seg_vm(R_DS, new_ds); |
load_seg_vm(R_DS, new_ds); |
1163 |
load_seg_vm(R_FS, new_fs); |
load_seg_vm(R_FS, new_fs); |
1164 |
load_seg_vm(R_GS, new_gs); |
load_seg_vm(R_GS, new_gs); |
1165 |
|
|
1166 |
env->eip = new_eip; |
env->eip = new_eip; |
1167 |
env->regs[R_ESP] = new_esp; |
env->regs[R_ESP] = new_esp; |
1168 |
} |
} |