All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] accel/tcg: fix crash on instruction straddling address-space end
@ 2026-09-16 23:51 Richard Henderson
  2026-09-16 23:51 ` [PATCH v2 1/2] accel/tcg: Allow some address space wraparound during translation Richard Henderson
  2026-09-16 23:51 ` [PATCH v2 2/2] tests/tcg/i386/system: Add regression test for translator_ld wraparound Richard Henderson
  0 siblings, 2 replies; 5+ messages in thread
From: Richard Henderson @ 2026-09-16 23:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: cui.tao

Handle address space wraparound during translation, with help from
the target translator.

Without cooperation of the target translator, unless this is a 64-bit
guest, this will no longer assert but is unlikely to function
correctly as generic code doesn't know the address space width.

Thanks to Tao Cui for a brilliant test case.


r~


Richard Henderson (1):
  accel/tcg: Allow some address space wraparound during translation

Tao Cui (1):
  tests/tcg/i386/system: Add regression test for translator_ld
    wraparound

 include/exec/translator.h          |  3 ++
 accel/tcg/translator.c             | 45 +++++++++++++++++++-----------
 tests/tcg/i386/system/meson.build  |  4 +++
 tests/tcg/i386/system/wraparound.S | 35 +++++++++++++++++++++++
 4 files changed, 70 insertions(+), 17 deletions(-)
 create mode 100644 tests/tcg/i386/system/wraparound.S

-- 
2.53.0



^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 1/2] accel/tcg: Allow some address space wraparound during translation
  2026-09-16 23:51 [PATCH v2 0/2] accel/tcg: fix crash on instruction straddling address-space end Richard Henderson
@ 2026-09-16 23:51 ` Richard Henderson
  2026-09-23 13:13   ` Jim MacArthur
  2026-09-16 23:51 ` [PATCH v2 2/2] tests/tcg/i386/system: Add regression test for translator_ld wraparound Richard Henderson
  1 sibling, 1 reply; 5+ messages in thread
From: Richard Henderson @ 2026-09-16 23:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: cui.tao

Allow the two pages of translation to be non-contiguous.
As long as the target translator wraps pc properly, this
allows address space wraparound to function correctly.

This avoids an assert on a valid i386 system-mode test case.

Reported-by: Tao Cui <cui.tao@linux.dev>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/exec/translator.h |  3 +++
 accel/tcg/translator.c    | 45 ++++++++++++++++++++++++---------------
 2 files changed, 31 insertions(+), 17 deletions(-)

diff --git a/include/exec/translator.h b/include/exec/translator.h
index 978dee25add..104e6d4f361 100644
--- a/include/exec/translator.h
+++ b/include/exec/translator.h
@@ -55,6 +55,8 @@ typedef enum DisasJumpType {
  * @pc_first: Address of first guest instruction in this TB.
  * @pc_next: Address of next guest instruction in this TB (current during
  *           disassembly).
+ * @pc_second_page: Address of the beginning of the second page of this TB,
+ *                  or -1 if the TB does not yet extend to a second page.
  * @is_jmp: What instruction to disassemble next.
  * @num_insns: Number of translated instructions (including current).
  * @max_insns: Maximum number of instructions to be translated in this TB.
@@ -69,6 +71,7 @@ struct DisasContextBase {
     TranslationBlock *tb;
     vaddr pc_first;
     vaddr pc_next;
+    vaddr pc_second_page;
     DisasJumpType is_jmp;
     int num_insns;
     int max_insns;
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
index 57daded60ff..52e605708f3 100644
--- a/accel/tcg/translator.c
+++ b/accel/tcg/translator.c
@@ -134,6 +134,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
     db->tb = tb;
     db->pc_first = pc;
     db->pc_next = pc;
+    db->pc_second_page = -1;
     db->is_jmp = DISAS_NEXT;
     db->num_insns = 0;
     db->max_insns = *max_insns;
@@ -285,16 +286,18 @@ static bool translator_ld(CPUArchState *env, DisasContextBase *db,
     /*
      * The read must conclude on the second page and not extend to a third.
      *
-     * TODO: We could allow the two pages to be virtually discontiguous,
-     * since we already allow the two pages to be physically discontiguous.
-     * The only reasonable use case would be executing an insn at the end
-     * of the address space wrapping around to the beginning.  For that,
-     * we would need to know the current width of the address space.
-     * In the meantime, assert.
+     * TODO: This doesn't handle address space wraparound properly for
+     * multi-byte reads, as we don't know the size of the address space here.
+     * But if the target translator wraps pc to 0 itself, and issues aligned
+     * reads, then this can work.
      */
-    base = (base & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
-    assert(((base ^ pc) & TARGET_PAGE_MASK) == 0);
-    assert(((base ^ last) & TARGET_PAGE_MASK) == 0);
+    if (db->pc_second_page == -1) {
+        db->pc_second_page = pc & TARGET_PAGE_MASK;
+    } else {
+        assert((pc & TARGET_PAGE_MASK) == db->pc_second_page);
+    }
+    assert((last & TARGET_PAGE_MASK) == db->pc_second_page);
+    base = db->pc_second_page;
     host = db->host_addr[1];
 
     if (host == NULL) {
@@ -372,16 +375,24 @@ static void record_save(DisasContextBase *db, vaddr pc,
 {
     int offset;
 
-    /* Do not record probes before the start of TB. */
-    if (pc < db->pc_first) {
-        return;
-    }
-
     /*
-     * In translator_access, we verified that pc is within 2 pages
-     * of pc_first, thus this will never overflow.
+     * In translator_ld, we verified that we touched no more than 2 pages,
+     * but we did not verify that they were virtually contiguous.
+     * Here, reimagine the two pages as virtually contiguous.
      */
-    offset = pc - db->pc_first;
+    if (likely(((db->pc_first ^ pc) & TARGET_PAGE_MASK) == 0)) {
+        /* first page */
+        /* Do not record probes before the start of TB. */
+        if (pc < db->pc_first) {
+            return;
+        }
+        offset = pc - db->pc_first;
+    } else {
+        int first_page_end_offset = -(db->pc_first | TARGET_PAGE_MASK);
+        assert(db->pc_second_page != -1);
+        assert((pc & TARGET_PAGE_MASK) == db->pc_second_page);
+        offset = pc - db->pc_second_page + first_page_end_offset;
+    }
 
     /*
      * Either the first or second page may be I/O.  If it is the second,
-- 
2.53.0



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2 2/2] tests/tcg/i386/system: Add regression test for translator_ld wraparound
  2026-09-16 23:51 [PATCH v2 0/2] accel/tcg: fix crash on instruction straddling address-space end Richard Henderson
  2026-09-16 23:51 ` [PATCH v2 1/2] accel/tcg: Allow some address space wraparound during translation Richard Henderson
@ 2026-09-16 23:51 ` Richard Henderson
  2026-09-23 11:08   ` Jim MacArthur
  1 sibling, 1 reply; 5+ messages in thread
From: Richard Henderson @ 2026-09-16 23:51 UTC (permalink / raw)
  To: qemu-devel; +Cc: cui.tao, Tao Cui

From: Tao Cui <cuitao@kylinos.cn>

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 <cuitao@kylinos.cn>
Message-ID: <20260709020529.126652-3-cui.tao@linux.dev>
[rth: Simplify and convert to meson test harness]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 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



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 2/2] tests/tcg/i386/system: Add regression test for translator_ld wraparound
  2026-09-16 23:51 ` [PATCH v2 2/2] tests/tcg/i386/system: Add regression test for translator_ld wraparound Richard Henderson
@ 2026-09-23 11:08   ` Jim MacArthur
  0 siblings, 0 replies; 5+ messages in thread
From: Jim MacArthur @ 2026-09-23 11:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: richard.henderson

On Wed, Sep 16, 2026 at 01:51:58PM -1000, Richard Henderson wrote:
> From: Tao Cui <cuitao@kylinos.cn>
> 
> 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 <cuitao@kylinos.cn>
> Message-ID: <20260709020529.126652-3-cui.tao@linux.dev>
> [rth: Simplify and convert to meson test harness]
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  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

Nice test case!

Reviewed-by: Jim MacArthur <jim.macarthur@linaro.org>



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 1/2] accel/tcg: Allow some address space wraparound during translation
  2026-09-16 23:51 ` [PATCH v2 1/2] accel/tcg: Allow some address space wraparound during translation Richard Henderson
@ 2026-09-23 13:13   ` Jim MacArthur
  0 siblings, 0 replies; 5+ messages in thread
From: Jim MacArthur @ 2026-09-23 13:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: richard.henderson

On Wed, Sep 16, 2026 at 01:51:57PM -1000, Richard Henderson wrote:
> Allow the two pages of translation to be non-contiguous.
> As long as the target translator wraps pc properly, this
> allows address space wraparound to function correctly.
> 
> This avoids an assert on a valid i386 system-mode test case.
> 
> Reported-by: Tao Cui <cui.tao@linux.dev>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  include/exec/translator.h |  3 +++
>  accel/tcg/translator.c    | 45 ++++++++++++++++++++++++---------------
>  2 files changed, 31 insertions(+), 17 deletions(-)
> 
> diff --git a/include/exec/translator.h b/include/exec/translator.h
> index 978dee25add..104e6d4f361 100644

Reviewed-by: Jim MacArthur <jim.macarthur@linaro.org>



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-09-23 13:14 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-16 23:51 [PATCH v2 0/2] accel/tcg: fix crash on instruction straddling address-space end Richard Henderson
2026-09-16 23:51 ` [PATCH v2 1/2] accel/tcg: Allow some address space wraparound during translation Richard Henderson
2026-09-23 13:13   ` Jim MacArthur
2026-09-16 23:51 ` [PATCH v2 2/2] tests/tcg/i386/system: Add regression test for translator_ld wraparound Richard Henderson
2026-09-23 11:08   ` Jim MacArthur

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.