target/i386: seg_helper: Correct segment selector nullification in the RET/IRET helper
authorBin Meng <bin.meng@windriver.com>
Fri, 13 Nov 2020 09:56:18 +0000 (17:56 +0800)
committerPaolo Bonzini <pbonzini@redhat.com>
Thu, 10 Dec 2020 17:15:00 +0000 (12:15 -0500)
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>
target/i386/seg_helper.c

index 09b65546609acb53823a17588008244b9869ef6f..e6ffa1f018701f15cd9238d064de4fa7c79e605d 100644 (file)
@@ -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);
         }
     }
 }