Revision b6d78bfa
b/cpu-exec.c | ||
---|---|---|
244 | 244 |
(unsigned long)env->segs[R_ES].base | |
245 | 245 |
(unsigned long)env->segs[R_SS].base) != 0) << |
246 | 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 | 249 |
flags |= (env->eflags & (IOPL_MASK | TF_MASK)); |
255 | 250 |
cs_base = env->segs[R_CS].base; |
256 | 251 |
pc = cs_base + env->eip; |
b/cpu-i386.h | ||
---|---|---|
256 | 256 |
SegmentCache tr; |
257 | 257 |
SegmentCache gdt; /* only base and limit are used */ |
258 | 258 |
SegmentCache idt; /* only base and limit are used */ |
259 |
int cpl; /* current cpl */ |
|
259 | 260 |
|
260 | 261 |
/* sysenter registers */ |
261 | 262 |
uint32_t sysenter_cs; |
... | ... | |
276 | 277 |
|
277 | 278 |
uint32_t breakpoints[MAX_BREAKPOINTS]; |
278 | 279 |
int nb_breakpoints; |
280 |
int singlestep_enabled; |
|
279 | 281 |
|
280 | 282 |
/* user data */ |
281 | 283 |
void *opaque; |
... | ... | |
298 | 300 |
/* needed to load some predefinied segment registers */ |
299 | 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 | 309 |
/* simulate fsave/frstor */ |
302 | 310 |
void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32); |
303 | 311 |
void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32); |
b/helper-i386.c | ||
---|---|---|
189 | 189 |
{ |
190 | 190 |
SegmentCache *dt; |
191 | 191 |
uint8_t *ptr, *ssp; |
192 |
int type, dpl, cpl, selector, ss_dpl;
|
|
192 |
int type, dpl, selector, ss_dpl; |
|
193 | 193 |
int has_error_code, new_stack, shift; |
194 | 194 |
uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2, push_size; |
195 | 195 |
uint32_t old_cs, old_ss, old_esp, old_eip; |
... | ... | |
216 | 216 |
break; |
217 | 217 |
} |
218 | 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 | 219 |
/* check privledge if software int */ |
224 |
if (is_int && dpl < cpl) |
|
220 |
if (is_int && dpl < env->cpl)
|
|
225 | 221 |
raise_exception_err(EXCP0D_GPF, intno * 8 + 2); |
226 | 222 |
/* check valid bit */ |
227 | 223 |
if (!(e2 & DESC_P_MASK)) |
... | ... | |
236 | 232 |
if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) |
237 | 233 |
raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
238 | 234 |
dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
239 |
if (dpl > cpl) |
|
235 |
if (dpl > env->cpl)
|
|
240 | 236 |
raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
241 | 237 |
if (!(e2 & DESC_P_MASK)) |
242 | 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 | 240 |
/* to inner priviledge */ |
245 | 241 |
get_ss_esp_from_tss(&ss, &esp, dpl); |
246 | 242 |
if ((ss & 0xfffc) == 0) |
... | ... | |
259 | 255 |
if (!(ss_e2 & DESC_P_MASK)) |
260 | 256 |
raise_exception_err(EXCP0A_TSS, ss & 0xfffc); |
261 | 257 |
new_stack = 1; |
262 |
} else if ((e2 & DESC_C_MASK) || dpl == cpl) { |
|
258 |
} else if ((e2 & DESC_C_MASK) || dpl == env->cpl) {
|
|
263 | 259 |
/* to same priviledge */ |
264 | 260 |
new_stack = 0; |
265 | 261 |
} else { |
... | ... | |
406 | 402 |
{ |
407 | 403 |
SegmentCache *dt; |
408 | 404 |
uint8_t *ptr; |
409 |
int dpl, cpl;
|
|
405 |
int dpl; |
|
410 | 406 |
uint32_t e2; |
411 | 407 |
|
412 | 408 |
dt = &env->idt; |
... | ... | |
414 | 410 |
e2 = ldl(ptr + 4); |
415 | 411 |
|
416 | 412 |
dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
417 |
cpl = 3; |
|
418 | 413 |
/* check privledge if software int */ |
419 |
if (is_int && dpl < cpl) |
|
414 |
if (is_int && dpl < env->cpl)
|
|
420 | 415 |
raise_exception_err(EXCP0D_GPF, intno * 8 + 2); |
421 | 416 |
|
422 | 417 |
/* Since we emulate only user space, we cannot do more than |
... | ... | |
728 | 723 |
selector, (unsigned long)sc->base, sc->limit, sc->flags); |
729 | 724 |
#endif |
730 | 725 |
} |
726 |
if (seg_reg == R_CS) { |
|
727 |
cpu_x86_set_cpl(env, selector & 3); |
|
728 |
} |
|
731 | 729 |
sc->selector = selector; |
732 | 730 |
} |
733 | 731 |
|
... | ... | |
744 | 742 |
raise_exception_err(EXCP0D_GPF, 0); |
745 | 743 |
if (load_segment(&e1, &e2, new_cs) != 0) |
746 | 744 |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
747 |
cpl = env->segs[R_CS].selector & 3;
|
|
745 |
cpl = env->cpl;
|
|
748 | 746 |
if (e2 & DESC_S_MASK) { |
749 | 747 |
if (!(e2 & DESC_CS_MASK)) |
750 | 748 |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
... | ... | |
828 | 826 |
raise_exception_err(EXCP0D_GPF, 0); |
829 | 827 |
if (load_segment(&e1, &e2, new_cs) != 0) |
830 | 828 |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
831 |
cpl = env->segs[R_CS].selector & 3;
|
|
829 |
cpl = env->cpl;
|
|
832 | 830 |
if (e2 & DESC_S_MASK) { |
833 | 831 |
if (!(e2 & DESC_CS_MASK)) |
834 | 832 |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
... | ... | |
1081 | 1079 |
if (!(e2 & DESC_S_MASK) || |
1082 | 1080 |
!(e2 & DESC_CS_MASK)) |
1083 | 1081 |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
1084 |
cpl = env->segs[R_CS].selector & 3;
|
|
1082 |
cpl = env->cpl;
|
|
1085 | 1083 |
rpl = new_cs & 3; |
1086 | 1084 |
if (rpl < cpl) |
1087 | 1085 |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
... | ... | |
1158 | 1156 |
/* modify processor state */ |
1159 | 1157 |
load_eflags(new_eflags, FL_UPDATE_CPL0_MASK | VM_MASK | VIF_MASK | VIP_MASK); |
1160 | 1158 |
load_seg_vm(R_CS, new_cs); |
1159 |
cpu_x86_set_cpl(env, 3); |
|
1161 | 1160 |
load_seg_vm(R_SS, new_ss); |
1162 | 1161 |
load_seg_vm(R_ES, new_es); |
1163 | 1162 |
load_seg_vm(R_DS, new_ds); |
1164 | 1163 |
load_seg_vm(R_FS, new_fs); |
1165 | 1164 |
load_seg_vm(R_GS, new_gs); |
1166 |
|
|
1165 |
|
|
1167 | 1166 |
env->eip = new_eip; |
1168 | 1167 |
env->regs[R_ESP] = new_esp; |
1169 | 1168 |
} |
b/translate-i386.c | ||
---|---|---|
4113 | 4113 |
dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1; |
4114 | 4114 |
dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7; |
4115 | 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 | 4117 |
dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3; |
4124 | 4118 |
dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1; |
4125 | 4119 |
dc->cc_op = CC_OP_DYNAMIC; |
... | ... | |
4362 | 4356 |
int cpl, error_code, is_dirty, is_user, prot, page_size; |
4363 | 4357 |
void *map_addr; |
4364 | 4358 |
|
4365 |
cpl = env->segs[R_CS].selector & 3;
|
|
4359 |
cpl = env->cpl;
|
|
4366 | 4360 |
is_user = (cpl == 3); |
4367 | 4361 |
|
4368 | 4362 |
#ifdef DEBUG_MMU |
Also available in: Unified diff