diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2013-02-22 18:10:03 +0000 |
---|---|---|
committer | Blue Swirl <blauwirbel@gmail.com> | 2013-03-03 14:28:47 +0000 |
commit | 378df4b23753a11be650af7664ca76bc75cb9f01 (patch) | |
tree | cedcd8fd2c8b23401ca4275ce65388e745cbcb37 /include | |
parent | 77211379d73ea0c89c0b5bb6eee74b17cb06f9a8 (diff) | |
download | hqemu-378df4b23753a11be650af7664ca76bc75cb9f01.zip hqemu-378df4b23753a11be650af7664ca76bc75cb9f01.tar.gz |
Handle CPU interrupts by inline checking of a flag
Fix some of the nasty TCG race conditions and crashes by implementing
cpu_exit() as setting a flag which is checked at the start of each TB.
This avoids crashes if a thread or signal handler calls cpu_exit()
while the execution thread is itself modifying the TB graph (which
may happen in system emulation mode as well as in linux-user mode
with a multithreaded guest binary).
This fixes the crashes seen in LP:668799; however there are another
class of crashes described in LP:1098729 which stem from the fact
that in linux-user with a multithreaded guest all threads will
use and modify the same global TCG date structures (including the
generated code buffer) without any kind of locking. This means that
multithreaded guest binaries are still in the "unsupported"
category.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/exec/gen-icount.h | 12 | ||||
-rw-r--r-- | include/qom/cpu.h | 3 |
2 files changed, 15 insertions, 0 deletions
diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h index c858a73..384153b 100644 --- a/include/exec/gen-icount.h +++ b/include/exec/gen-icount.h @@ -7,10 +7,19 @@ static TCGArg *icount_arg; static int icount_label; +static int exitreq_label; static inline void gen_icount_start(void) { TCGv_i32 count; + TCGv_i32 flag; + + exitreq_label = gen_new_label(); + flag = tcg_temp_local_new_i32(); + tcg_gen_ld_i32(flag, cpu_env, + offsetof(CPUState, tcg_exit_req) - ENV_OFFSET); + tcg_gen_brcondi_i32(TCG_COND_NE, flag, 0, exitreq_label); + tcg_temp_free_i32(flag); if (!use_icount) return; @@ -29,6 +38,9 @@ static inline void gen_icount_start(void) static void gen_icount_end(TranslationBlock *tb, int num_insns) { + gen_set_label(exitreq_label); + tcg_gen_exit_tb((tcg_target_long)tb + TB_EXIT_REQUESTED); + if (use_icount) { *icount_arg = num_insns; gen_set_label(icount_label); diff --git a/include/qom/cpu.h b/include/qom/cpu.h index ee1a7c8..ab2657c 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -71,6 +71,8 @@ struct kvm_run; * @created: Indicates whether the CPU thread has been successfully created. * @stop: Indicates a pending stop request. * @stopped: Indicates the CPU has been artificially stopped. + * @tcg_exit_req: Set to force TCG to stop executing linked TBs for this + * CPU and return to its top level loop. * @env_ptr: Pointer to subclass-specific CPUArchState field. * @current_tb: Currently executing TB. * @kvm_fd: vCPU file descriptor for KVM. @@ -100,6 +102,7 @@ struct CPUState { bool stop; bool stopped; volatile sig_atomic_t exit_request; + volatile sig_atomic_t tcg_exit_req; void *env_ptr; /* CPUArchState */ struct TranslationBlock *current_tb; |