cpu-exec: Unlock tb_lock if we longjmp out of code generation
If the guest attempts to execute from unreadable memory, this will cause us to longjmp back to the main loop from inside the target frontend decoder. For linux-user mode, this means we will still hold the tb_ctx.tb_lock, and will deadlock when we try to start executing code again. Unlock the lock in the return-from-longjmp code path to avoid this. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Acked-by: Andrei Warkentin <andrey.warkentin@gmail.com> Reviewed-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
parent
cd7ccc8351
commit
bae2c27090
@ -227,6 +227,8 @@ int cpu_exec(CPUArchState *env)
|
||||
TranslationBlock *tb;
|
||||
uint8_t *tc_ptr;
|
||||
uintptr_t next_tb;
|
||||
/* This must be volatile so it is not trashed by longjmp() */
|
||||
volatile bool have_tb_lock = false;
|
||||
|
||||
if (cpu->halted) {
|
||||
if (!cpu_has_work(cpu)) {
|
||||
@ -600,6 +602,7 @@ int cpu_exec(CPUArchState *env)
|
||||
cpu_loop_exit(cpu);
|
||||
}
|
||||
spin_lock(&tcg_ctx.tb_ctx.tb_lock);
|
||||
have_tb_lock = true;
|
||||
tb = tb_find_fast(env);
|
||||
/* Note: we do it here to avoid a gcc bug on Mac OS X when
|
||||
doing it in tb_find_slow */
|
||||
@ -621,6 +624,7 @@ int cpu_exec(CPUArchState *env)
|
||||
tb_add_jump((TranslationBlock *)(next_tb & ~TB_EXIT_MASK),
|
||||
next_tb & TB_EXIT_MASK, tb);
|
||||
}
|
||||
have_tb_lock = false;
|
||||
spin_unlock(&tcg_ctx.tb_ctx.tb_lock);
|
||||
|
||||
/* cpu_interrupt might be called while translating the
|
||||
@ -692,6 +696,10 @@ int cpu_exec(CPUArchState *env)
|
||||
#ifdef TARGET_I386
|
||||
x86_cpu = X86_CPU(cpu);
|
||||
#endif
|
||||
if (have_tb_lock) {
|
||||
spin_unlock(&tcg_ctx.tb_ctx.tb_lock);
|
||||
have_tb_lock = false;
|
||||
}
|
||||
}
|
||||
} /* for(;;) */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user