@samitouri / QOSamiQemu / commits / 3589cd995b

target/i386: fix long mode segment override prefix decoding

On x86, the ES/CS/SS/DS segment override prefixes are null prefixes in long mode, and should be ignored. (AMD APM Volume 3, Section 1.2.4) This patch fixes the prefix decoding to correctly ignore the prefixes in 64-bit mode. Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3391 Signed-off-by: Jos Craaijo <jos.craaijo@ou.nl> Tested-by: Yudistira Putra <pyudistira519@gmail.com> Link: https://lore.kernel.org/r/20260623-fix-x86-long-mode-segment-override-decoding-v1-1-26d9d4b5804e@ou.nl Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Craaijo, Jos committed Jun 23, 2026 at 13:21 UTC 3589cd995b4facf34071e944fd8ec2294524e25a
4 files changed +44 -4
target/i386/emulate/x86_decode.c
+6
@@ -1851,6 +1851,12 @@ static void decode_prefix(CPUX86State *env, struct x86_decode *decode)
1851 case PREFIX_SS_SEG_OVERRIDE:
1852 case PREFIX_DS_SEG_OVERRIDE:
1853 case PREFIX_ES_SEG_OVERRIDE:
1854 + if (x86_is_long_mode(env_cpu(env))) {
1855 + /* ES/CS/SS/DS segment overrides are ignored in long mode */
1856 + decode->rex.rex = 0;
1857 + break;
1858 + }
1859 + /* fall through when not in long mode */
1860 case PREFIX_FS_SEG_OVERRIDE:
1861 case PREFIX_GS_SEG_OVERRIDE:
1862 decode->segment_override = byte;
target/i386/tcg/decode-new.c.inc
+12 -4
@@ -2816,16 +2816,24 @@ static void disas_insn(DisasContext *s, CPUState *cpu)
2816 s->prefix |= PREFIX_LOCK;
2817 goto next_byte;
2818 case 0x2e:
2819 - s->override = R_CS;
2819 + if (!CODE64(s)) {
2820 + s->override = R_CS;
2821 + }
2822 goto next_byte;
2823 case 0x36:
2822 - s->override = R_SS;
2824 + if (!CODE64(s)) {
2825 + s->override = R_SS;
2826 + }
2827 goto next_byte;
2828 case 0x3e:
2825 - s->override = R_DS;
2829 + if (!CODE64(s)) {
2830 + s->override = R_DS;
2831 + }
2832 goto next_byte;
2833 case 0x26:
2828 - s->override = R_ES;
2834 + if (!CODE64(s)) {
2835 + s->override = R_ES;
2836 + }
2837 goto next_byte;
2838 case 0x64:
2839 s->override = R_FS;
tests/tcg/x86_64/Makefile.target
+1
@@ -15,6 +15,7 @@ X86_64_TESTS += vsyscall
15 X86_64_TESTS += noexec
16 X86_64_TESTS += cmpxchg
17 X86_64_TESTS += adox
18 +X86_64_TESTS += segment-prefixes
19 X86_64_TESTS += test-1648
20 X86_64_TESTS += test-2175
21 X86_64_TESTS += cross-modifying-code
tests/tcg/x86_64/segment-prefixes.c new
+25
@@ -0,0 +1,25 @@
1 +/* SPDX-License-Identifier: GPL-2.0-or-later */
2 +/* See https://gitlab.com/qemu-project/qemu/-/work_items/3391 */
3 +
4 +int main()
5 +{
6 + int data = 0;
7 +
8 + /* Ensure that ignored segment override prefixes are actually ignored */
9 + asm volatile (
10 + "wrgsbase %0\n\t"
11 + ".byte 0x65, 0x26\n\t" /* prefixes: GS + ES */
12 + "movb $0, 0\n\t"
13 + ".byte 0x65, 0x2E\n\t" /* prefixes: GS + CS */
14 + "movb $0, 0\n\t"
15 + ".byte 0x65, 0x36\n\t" /* prefixes: GS + SS */
16 + "movb $0, 0\n\t"
17 + ".byte 0x65, 0x3E\n\t" /* prefixes: GS + DS */
18 + "movb $0, 0\n\t"
19 + :
20 + : "r" (&data)
21 + : "memory"
22 + );
23 +
24 + return 0;
25 +}