Commit b0052d15 authored by Jan Kiszka's avatar Jan Kiszka Committed by Aurelien Jarno
Browse files

Fix cpu_unlink_tb race



If a signal hit after the env->exit_request check but before cpu_exec
updated env->current_tb, cpu_unlink_tb called from the signal hander
will not unlink the current TB. This may leave us stuck in a guest loop
if no further unlink is invoked.

Fix this by reordering current_tb update and exit_request check,
additionally enforcing the correct order via a compiler barrier.

Signed-off-by: default avatarJan Kiszka <jan.kiszka@siemens.com>
Acked-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Reviewed-by: default avatarMarcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: default avatarAurelien Jarno <aurelien@aurel32.net>
parent 1d93f0f0
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -600,8 +600,9 @@ int cpu_exec(CPUState *env1)
                   TB, but before it is linked into a potentially
                   infinite loop and becomes env->current_tb. Avoid
                   starting execution if there is a pending interrupt. */
                if (!unlikely (env->exit_request)) {
                env->current_tb = tb;
                barrier();
                if (likely(!env->exit_request)) {
                    tc_ptr = tb->tc_ptr;
                /* execute the generated code */
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
@@ -610,7 +611,6 @@ int cpu_exec(CPUState *env1)
#define env cpu_single_env
#endif
                    next_tb = tcg_qemu_tb_exec(tc_ptr);
                    env->current_tb = NULL;
                    if ((next_tb & 3) == 2) {
                        /* Instruction counter expired.  */
                        int insns_left;
@@ -639,6 +639,7 @@ int cpu_exec(CPUState *env1)
                        }
                    }
                }
                env->current_tb = NULL;
                /* reset soft MMU for next block (it can currently
                   only be set by a memory fault) */
            } /* for(;;) */