summaryrefslogtreecommitdiff
path: root/target/i386
diff options
context:
space:
mode:
authorBin Meng <bin.meng@windriver.com>2020-11-13 17:56:18 +0800
committerPaolo Bonzini <pbonzini@redhat.com>2020-12-10 12:15:00 -0500
commitc2ba0515f2df58a661fcb5d6485139877d92ab1b (patch)
tree9f9ddc8815192d2682a8950263d64ff856448c1c /target/i386
parentc1bb5418e32ec70c72af332354b5963eab7a5579 (diff)
downloadqemu-c2ba0515f2df58a661fcb5d6485139877d92ab1b.zip
target/i386: seg_helper: Correct segment selector nullification in the RET/IRET helper
Per the SDM, when returning to outer privilege level, for segment registers (ES, FS, GS, and DS) if the check fails, the segment selector becomes null, but QEMU clears the base/limit/flags as well as nullifying the segment selector, which should be a spec violation. Real hardware seems to be compliant with the spec, at least on one Coffee Lake board I tested. Signed-off-by: Bin Meng <bin.meng@windriver.com> Message-Id: <1605261378-77971-1-git-send-email-bmeng.cn@gmail.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'target/i386')
-rw-r--r--target/i386/seg_helper.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/target/i386/seg_helper.c b/target/i386/seg_helper.c
index 09b6554660..e6ffa1f018 100644
--- a/target/i386/seg_helper.c
+++ b/target/i386/seg_helper.c
@@ -2108,7 +2108,10 @@ static inline void validate_seg(CPUX86State *env, int seg_reg, int cpl)
if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
/* data or non conforming code segment */
if (dpl < cpl) {
- cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0);
+ cpu_x86_load_seg_cache(env, seg_reg, 0,
+ env->segs[seg_reg].base,
+ env->segs[seg_reg].limit,
+ env->segs[seg_reg].flags & ~DESC_P_MASK);
}
}
}