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. */