Commit fd460606 authored by Kevin O'Connor's avatar Kevin O'Connor Committed by Paolo Bonzini
Browse files

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: default avatarKevin O'Connor <kevin@koconnor.net>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 010e639a
Loading
Loading
Loading
Loading
+19 −19
Original line number Diff line number Diff line
@@ -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 (env->eflags & VM_MASK) {
            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);
    cpu_x86_set_cpl(env, dpl);
    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
@@ -911,6 +911,12 @@ static void do_interrupt64(CPUX86State *env, int intno, int is_int,
        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) {
        ss = 0 | dpl;
        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);
    cpu_x86_set_cpl(env, dpl);
    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

@@ -960,6 +960,8 @@ void helper_syscall(CPUX86State *env, int next_eip_addend)

        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_load_seg_cache(env, R_CS, selector & 0xfffc,
                           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_S_MASK |
                               DESC_W_MASK | DESC_A_MASK);
        env->eflags &= ~env->fmask;
        cpu_load_eflags(env, env->eflags, 0);
        if (code64) {
            env->eip = env->lstar;
        } else {
@@ -982,6 +982,7 @@ void helper_syscall(CPUX86State *env, int next_eip_addend)
    } else {
        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_load_seg_cache(env, R_CS, selector & 0xfffc,
                           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_S_MASK |
                               DESC_W_MASK | DESC_A_MASK);
        env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
        env->eip = (uint32_t)env->star;
    }
}
@@ -1014,6 +1014,9 @@ void helper_sysret(CPUX86State *env, int dflag)
    }
    selector = (env->star >> 48) & 0xffff;
    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) {
            cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3,
                                   0, 0xffffffff,
@@ -1035,11 +1038,9 @@ void helper_sysret(CPUX86State *env, int dflag)
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
                               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);
    } else {
        env->eflags |= IF_MASK;
        cpu_x86_load_seg_cache(env, R_CS, selector | 3,
                               0, 0xffffffff,
                               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_S_MASK | (3 << DESC_DPL_SHIFT) |
                               DESC_W_MASK | DESC_A_MASK);
        env->eflags |= IF_MASK;
        cpu_x86_set_cpl(env, 3);
    }
}