diff options
Diffstat (limited to 'accel/tcg/cpu-exec.c')
| -rw-r--r-- | accel/tcg/cpu-exec.c | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 8491e5badd..7c20d9db12 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -40,6 +40,7 @@ #include "exec/replay-core.h" #include "system/tcg.h" #include "exec/helper-proto-common.h" +#include "tcg-accel-ops.h" #include "tb-jmp-cache.h" #include "tb-hash.h" #include "tb-context.h" @@ -748,6 +749,22 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret) return false; } +void tcg_kick_vcpu_thread(CPUState *cpu) +{ +#ifndef CONFIG_USER_ONLY + /* + * Ensure cpu_exec will see the reason why the exit request was set. + * FIXME: this is not always needed. Other accelerators instead + * read interrupt_request and set exit_request on demand from the + * CPU thread; see kvm_arch_pre_run() for example. + */ + qatomic_store_release(&cpu->exit_request, true); +#endif + + /* Ensure cpu_exec will see the exit request after TCG has exited. */ + qatomic_store_release(&cpu->neg.icount_decr.u16.high, -1); +} + static inline bool icount_exit_request(CPUState *cpu) { if (!icount_enabled()) { @@ -774,7 +791,8 @@ static inline bool cpu_handle_interrupt(CPUState *cpu, /* Clear the interrupt flag now since we're processing * cpu->interrupt_request and cpu->exit_request. * Ensure zeroing happens before reading cpu->exit_request or - * cpu->interrupt_request (see also smp_wmb in cpu_exit()) + * cpu->interrupt_request (see also store-release in + * tcg_kick_vcpu_thread()) */ qatomic_set_mb(&cpu->neg.icount_decr.u16.high, 0); @@ -784,7 +802,7 @@ static inline bool cpu_handle_interrupt(CPUState *cpu, if (unlikely(cpu_test_interrupt(cpu, ~0))) { bql_lock(); if (cpu_test_interrupt(cpu, CPU_INTERRUPT_DEBUG)) { - cpu->interrupt_request &= ~CPU_INTERRUPT_DEBUG; + cpu_reset_interrupt(cpu, CPU_INTERRUPT_DEBUG); cpu->exception_index = EXCP_DEBUG; bql_unlock(); return true; @@ -793,7 +811,7 @@ static inline bool cpu_handle_interrupt(CPUState *cpu, /* Do nothing */ } else if (cpu_test_interrupt(cpu, CPU_INTERRUPT_HALT)) { replay_interrupt(); - cpu->interrupt_request &= ~CPU_INTERRUPT_HALT; + cpu_reset_interrupt(cpu, CPU_INTERRUPT_HALT); cpu->halted = 1; cpu->exception_index = EXCP_HLT; bql_unlock(); @@ -840,7 +858,7 @@ static inline bool cpu_handle_interrupt(CPUState *cpu, } } if (cpu_test_interrupt(cpu, CPU_INTERRUPT_EXITTB)) { - cpu->interrupt_request &= ~CPU_INTERRUPT_EXITTB; + cpu_reset_interrupt(cpu, CPU_INTERRUPT_EXITTB); /* ensure that no TB jump will be modified as the program flow was changed */ *last_tb = NULL; @@ -851,9 +869,11 @@ static inline bool cpu_handle_interrupt(CPUState *cpu, } #endif /* !CONFIG_USER_ONLY */ - /* Finally, check if we need to exit to the main loop. */ - if (unlikely(qatomic_read(&cpu->exit_request)) || icount_exit_request(cpu)) { - qatomic_set(&cpu->exit_request, 0); + /* + * Finally, check if we need to exit to the main loop. + * The corresponding store-release is in cpu_exit. + */ + if (unlikely(qatomic_load_acquire(&cpu->exit_request)) || icount_exit_request(cpu)) { if (cpu->exception_index == -1) { cpu->exception_index = EXCP_INTERRUPT; } |