summaryrefslogtreecommitdiffstats
path: root/accel/tcg
diff options
context:
space:
mode:
authorRichard Henderson2021-01-23 23:11:17 +0100
committerRichard Henderson2021-01-24 19:03:27 +0100
commitae30e86661b0f48562cd95918d37cbeec5d02262 (patch)
treebd84c59f604bae6c128f02b06b4607433a13d2df /accel/tcg
parenttcg: Toggle page execution for Apple Silicon (diff)
downloadqemu-ae30e86661b0f48562cd95918d37cbeec5d02262.tar.gz
qemu-ae30e86661b0f48562cd95918d37cbeec5d02262.tar.xz
qemu-ae30e86661b0f48562cd95918d37cbeec5d02262.zip
tcg: Restart code generation when we run out of temps
Some large translation blocks can generate so many unique constants that we run out of temps to hold them. In this case, longjmp back to the start of code generation and restart with a smaller translation block. Buglink: https://bugs.launchpad.net/bugs/1912065 Tested-by: BALATON Zoltan <balaton@eik.bme.hu> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'accel/tcg')
-rw-r--r--accel/tcg/translate-all.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index d09c187e0f..81d4c83f22 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -1926,11 +1926,17 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
ti = profile_getclock();
#endif
+ gen_code_size = sigsetjmp(tcg_ctx->jmp_trans, 0);
+ if (unlikely(gen_code_size != 0)) {
+ goto error_return;
+ }
+
tcg_func_start(tcg_ctx);
tcg_ctx->cpu = env_cpu(env);
gen_intermediate_code(cpu, tb, max_insns);
tcg_ctx->cpu = NULL;
+ max_insns = tb->icount;
trace_translate_block(tb, tb->pc, tb->tc.ptr);
@@ -1955,6 +1961,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
gen_code_size = tcg_gen_code(tcg_ctx, tb);
if (unlikely(gen_code_size < 0)) {
+ error_return:
switch (gen_code_size) {
case -1:
/*
@@ -1966,6 +1973,9 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
* flush the TBs, allocate a new TB, re-initialize it per
* above, and re-do the actual code generation.
*/
+ qemu_log_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT,
+ "Restarting code generation for "
+ "code_gen_buffer overflow\n");
goto buffer_overflow;
case -2:
@@ -1978,9 +1988,12 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
* Try again with half as many insns as we attempted this time.
* If a single insn overflows, there's a bug somewhere...
*/
- max_insns = tb->icount;
assert(max_insns > 1);
max_insns /= 2;
+ qemu_log_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT,
+ "Restarting code generation with "
+ "smaller translation block (max %d insns)\n",
+ max_insns);
goto tb_overflow;
default: