target/i386/seg_helper.c: 16-bit TSS struct format wrong?
This bug has been copied automatically from: https://bugs.launchpad.net/qemu/+bug/1879955
Reported by 'Peter Maydell' on 2020-05-21 :
In target/i386/seg_helper.c:switch_tss_ra() we have the following code to
load registers from a 16-bit TSS struct:
/* 16 bit */
new_cr3 = 0;
new_eip = cpu_lduw_kernel_ra(env, tss_base + 0x0e, retaddr);
new_eflags = cpu_lduw_kernel_ra(env, tss_base + 0x10, retaddr);
for (i = 0; i < 8; i++) {
new_regs[i] = cpu_lduw_kernel_ra(env, tss_base + (0x12 + i *
2),
retaddr) | 0xffff0000;
}
for (i = 0; i < 4; i++) {
new_segs[i] = cpu_lduw_kernel_ra(env, tss_base + (0x22 + i *
4),
retaddr);
}
new_ldt = cpu_lduw_kernel_ra(env, tss_base + 0x2a, retaddr);
This doesn't match up with the structure described here:
https://www.sandpile.org/x86/tss.htm -- which has only 2-byte slots for
the segment registers. It also makes the 3rd segreg use the same offset as
the LDTR, which is very suspicious. I suspect that this should use "(0x22
+ i * 2)".
The code later in the same function that stores the segment registers to
the struct has the same bug.
Found by code inspection; I don't have a test case to check this. As a
non-x86-expert I'm just going to file a bug report in case somebody else
feels like confirming the issue and sending a patch.