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
This commit is contained in:
Bin Meng 2021-03-03 19:10:15 -05:00 committed by Lioncash
parent 1da5d669a7
commit c59e391194

View File

@ -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);
}
}
}