From c59e391194c83833a217f7d91fe038df2f76976b Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 3 Mar 2021 19:10:15 -0500 Subject: [PATCH] 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. Backports c2ba0515f2df58a661fcb5d6485139877d92ab1b --- qemu/target/i386/seg_helper.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/qemu/target/i386/seg_helper.c b/qemu/target/i386/seg_helper.c index ce7d4f82..87a42a9b 100644 --- a/qemu/target/i386/seg_helper.c +++ b/qemu/target/i386/seg_helper.c @@ -2202,7 +2202,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); } } }