From: Tao Cui <[email protected]>

Add a test case that reaches an instruction straddling the end of the 32-bit
address space (0xfffffffe).

The top page (0xfffff000) is SeaBIOS ROM, so the cross-boundary byte is
the ROM's own 0x00 (add r/m8, r8) at 0xffffffff, whose modrm is fetched
from [0x0]. A short exit stub is placed there.  The case runs on
qemu-system-i386 since the bug is 32-bit only.

Signed-off-by: Tao Cui <[email protected]>
Message-ID: <[email protected]>
[rth: Simplify and convert to meson test harness]
Signed-off-by: Richard Henderson <[email protected]>
---
 tests/tcg/i386/system/meson.build  |  4 ++++
 tests/tcg/i386/system/wraparound.S | 35 ++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+)
 create mode 100644 tests/tcg/i386/system/wraparound.S

diff --git a/tests/tcg/i386/system/meson.build 
b/tests/tcg/i386/system/meson.build
index d3f73997c7f..c08563d0ab5 100644
--- a/tests/tcg/i386/system/meson.build
+++ b/tests/tcg/i386/system/meson.build
@@ -34,6 +34,10 @@ foreach t: tcg_tests['multiarch-softmmu']['tests']
   endforeach
 endforeach
 
+tests += {
+  'wraparound.S': { 'cflags': cflags, 'qemu_args': ['-m', '4G'] + 
qemu_def_args }
+}
+
 if 'qemu-system-i386' in emulators
   tcg_tests += {
     'i386-softmmu': {
diff --git a/tests/tcg/i386/system/wraparound.S 
b/tests/tcg/i386/system/wraparound.S
new file mode 100644
index 00000000000..9c77b3a8468
--- /dev/null
+++ b/tests/tcg/i386/system/wraparound.S
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Regression test for the translator_ld crash when an instruction
+ * straddles the end of the 32-bit address space (i386).
+ */
+
+        .code32
+        .section .text
+
+main:
+        /*
+         * The top page (0xfffff000) is SeaBIOS ROM and cannot be written.
+         * Its byte at 0xffffffff (0x00 = "add r/m8, r8") already crosses the
+         * page boundary into page1 at 0x0, which is exactly the case
+         * translator_ld must handle without aborting.  Reaching 0xfffffffe
+         * runs the ROM's cld, then that add; the add's modrm is fetched from
+         * [0x0], which is RAM, so build a short exit stub there:
+         *
+         *   [0x0] c0                 modrm -> "add al, al" (reg; EIP -> 1)
+         *   [0x1] c3                 ret
+         *
+         * Note: this relies on the SeaBIOS byte at 0xffffffff being 0x00
+         * (add r/m8, r8); if that ever changes, the stub below must move.
+         *
+         * Note that eax = 0 before and after the stub, so this becomes
+         * the exit code of the test.
+         */
+        xor     %eax, %eax
+        movw    $0xc3c0, (%eax)
+        movl    $0xfffffffe, %ecx
+        jmp     *%ecx
+
+        .globl  main
+        .type   main, @function
+        .size   main, . - main
-- 
2.53.0


Reply via email to