Commit 3992091713 for qemu.org

commit 3992091713eb51a4a1cf0a592a30ae9e856c6b55
Author: Stian Halseth <stian@itx.no>
Date:   Wed Oct 28 10:53:09 2026 -0500

    accel/tcg: Do not flush and retry in place in tb_gen_code

    When the code buffer is full in a serial context, tb_gen_code() flushes
    it and retries in place. cpu_exec_loop() then chains its last_tb, now
    freed, into the new TB. When that TB is invalidated, tb_jmp_unlink()
    follows the stale entry and qemu crashes inside its SIGSEGV handler.

    Always queue the flush and leave through cpu_loop_exit(), as before
    commit ebf7a5d294a3. This also brings back the cleanup in
    cpu_loop_exit() and cpu_exec_longjmp_cleanup() that the retry skipped.

    Since commit 25e5c6a320db ("accel/tcg: Allow cross-page goto_tb
    chaining in user-only builds"), user-only builds hit this easily,
    e.g. qemu-sparc64 -tb-size 1 on a program writing next to its PLT.

    Cc: qemu-stable@nongnu.org
    Fixes: ebf7a5d294a3 ("accel/tcg: Improve buffer overflow in tb_gen_code")
    Suggested-by: Alex Bennée <alex.bennee@linaro.org>
    Signed-off-by: Stian Halseth <stian@itx.no>
    Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
    Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 328d96aba3..ea8257935e 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -288,12 +288,11 @@ TranslationBlock *tb_gen_code(CPUState *cpu, TCGTBCPUState s)
     assert_no_pages_locked();
     tb = tcg_tb_alloc(tcg_ctx);
     if (unlikely(!tb)) {
-        /* flush must be done */
-        if (cpu_in_serial_context(cpu)) {
-            trace_tb_gen_code_buffer_overflow("tcg_tb_alloc");
-            tb_flush__exclusive_or_serial();
-            goto buffer_overflow;
-        }
+        /*
+         * Flush must be done.  Always exit the cpu loop so that the
+         * last_tb linkage within the inner cpu loop does not apply.
+         */
+        trace_tb_gen_code_buffer_overflow("tcg_tb_alloc");
         queue_tb_flush(cpu);
         mmap_unlock();
         /* Make the execution loop process the flush as soon as possible.  */