target-i386: set eflags prior to calling cpu_x86_load_seg_cache() in seg_helper.c

The cpu_x86_load_seg_cache() function inspects eflags, so make sure
all changes to eflags are done prior to loading the segment caches.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Kevin O'Connor 2014-04-29 16:38:31 -04:00 committed by Paolo Bonzini
parent 010e639a8d
commit fd460606fd

View file

@ -739,6 +739,12 @@ static void do_interrupt_protected(CPUX86State *env, int intno, int is_int,
} }
} }
/* interrupt gate clear IF mask */
if ((type & 1) == 0) {
env->eflags &= ~IF_MASK;
}
env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
if (new_stack) { if (new_stack) {
if (env->eflags & VM_MASK) { if (env->eflags & VM_MASK) {
cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0, 0); cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0, 0);
@ -759,12 +765,6 @@ static void do_interrupt_protected(CPUX86State *env, int intno, int is_int,
e2); e2);
cpu_x86_set_cpl(env, dpl); cpu_x86_set_cpl(env, dpl);
env->eip = offset; env->eip = offset;
/* interrupt gate clear IF mask */
if ((type & 1) == 0) {
env->eflags &= ~IF_MASK;
}
env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
} }
#ifdef TARGET_X86_64 #ifdef TARGET_X86_64
@ -911,6 +911,12 @@ static void do_interrupt64(CPUX86State *env, int intno, int is_int,
PUSHQ(esp, error_code); PUSHQ(esp, error_code);
} }
/* interrupt gate clear IF mask */
if ((type & 1) == 0) {
env->eflags &= ~IF_MASK;
}
env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
if (new_stack) { if (new_stack) {
ss = 0 | dpl; ss = 0 | dpl;
cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0); cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0);
@ -924,12 +930,6 @@ static void do_interrupt64(CPUX86State *env, int intno, int is_int,
e2); e2);
cpu_x86_set_cpl(env, dpl); cpu_x86_set_cpl(env, dpl);
env->eip = offset; env->eip = offset;
/* interrupt gate clear IF mask */
if ((type & 1) == 0) {
env->eflags &= ~IF_MASK;
}
env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
} }
#endif #endif
@ -960,6 +960,8 @@ void helper_syscall(CPUX86State *env, int next_eip_addend)
code64 = env->hflags & HF_CS64_MASK; code64 = env->hflags & HF_CS64_MASK;
env->eflags &= ~env->fmask;
cpu_load_eflags(env, env->eflags, 0);
cpu_x86_set_cpl(env, 0); cpu_x86_set_cpl(env, 0);
cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
0, 0xffffffff, 0, 0xffffffff,
@ -972,8 +974,6 @@ void helper_syscall(CPUX86State *env, int next_eip_addend)
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
DESC_S_MASK | DESC_S_MASK |
DESC_W_MASK | DESC_A_MASK); DESC_W_MASK | DESC_A_MASK);
env->eflags &= ~env->fmask;
cpu_load_eflags(env, env->eflags, 0);
if (code64) { if (code64) {
env->eip = env->lstar; env->eip = env->lstar;
} else { } else {
@ -982,6 +982,7 @@ void helper_syscall(CPUX86State *env, int next_eip_addend)
} else { } else {
env->regs[R_ECX] = (uint32_t)(env->eip + next_eip_addend); env->regs[R_ECX] = (uint32_t)(env->eip + next_eip_addend);
env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
cpu_x86_set_cpl(env, 0); cpu_x86_set_cpl(env, 0);
cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc,
0, 0xffffffff, 0, 0xffffffff,
@ -993,7 +994,6 @@ void helper_syscall(CPUX86State *env, int next_eip_addend)
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
DESC_S_MASK | DESC_S_MASK |
DESC_W_MASK | DESC_A_MASK); DESC_W_MASK | DESC_A_MASK);
env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
env->eip = (uint32_t)env->star; env->eip = (uint32_t)env->star;
} }
} }
@ -1014,6 +1014,9 @@ void helper_sysret(CPUX86State *env, int dflag)
} }
selector = (env->star >> 48) & 0xffff; selector = (env->star >> 48) & 0xffff;
if (env->hflags & HF_LMA_MASK) { if (env->hflags & HF_LMA_MASK) {
cpu_load_eflags(env, (uint32_t)(env->regs[11]), TF_MASK | AC_MASK
| ID_MASK | IF_MASK | IOPL_MASK | VM_MASK | RF_MASK |
NT_MASK);
if (dflag == 2) { if (dflag == 2) {
cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3, cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3,
0, 0xffffffff, 0, 0xffffffff,
@ -1035,11 +1038,9 @@ void helper_sysret(CPUX86State *env, int dflag)
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
DESC_S_MASK | (3 << DESC_DPL_SHIFT) | DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
DESC_W_MASK | DESC_A_MASK); DESC_W_MASK | DESC_A_MASK);
cpu_load_eflags(env, (uint32_t)(env->regs[11]), TF_MASK | AC_MASK
| ID_MASK | IF_MASK | IOPL_MASK | VM_MASK | RF_MASK |
NT_MASK);
cpu_x86_set_cpl(env, 3); cpu_x86_set_cpl(env, 3);
} else { } else {
env->eflags |= IF_MASK;
cpu_x86_load_seg_cache(env, R_CS, selector | 3, cpu_x86_load_seg_cache(env, R_CS, selector | 3,
0, 0xffffffff, 0, 0xffffffff,
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
@ -1051,7 +1052,6 @@ void helper_sysret(CPUX86State *env, int dflag)
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
DESC_S_MASK | (3 << DESC_DPL_SHIFT) | DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
DESC_W_MASK | DESC_A_MASK); DESC_W_MASK | DESC_A_MASK);
env->eflags |= IF_MASK;
cpu_x86_set_cpl(env, 3); cpu_x86_set_cpl(env, 3);
} }
} }