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
+}