summaryrefslogtreecommitdiff
path: root/accel
diff options
context:
space:
mode:
authorDavid Hildenbrand <david@redhat.com>2017-11-29 20:13:19 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2017-12-21 09:22:44 +0100
commitd84be02d69a23dea249f351324d497f613994129 (patch)
tree690877750db2178744532e9ec29692da7e4a4178 /accel
parentebd05fea9be1dfd043aaa763fb6d2cd971346a58 (diff)
downloadqemu-d84be02d69a23dea249f351324d497f613994129.tar.gz
cpu-exec: fix missed CPU kick during interrupt injection
The conditional memory barrier not only looks strange but actually is wrong. On s390x, I can reproduce interrupts via cpu_interrupt() not leading to a proper kick out of emulation every now and then. cpu_interrupt() is especially used for inter CPU communication via SIGP (esp. external calls and emergency interrupts). With this patch, I was not able to reproduce. (esp. no stalls or hangs in the guest). My setup is s390x MTTCG with 16 VCPUs on 8 CPU host, running make -j16. Signed-off-by: David Hildenbrand <david@redhat.com> Message-Id: <20171129191319.11483-1-david@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'accel')
-rw-r--r--accel/tcg/cpu-exec.c12
1 files changed, 3 insertions, 9 deletions
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index 9b544d88c8..4452cd9856 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -525,19 +525,13 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
TranslationBlock **last_tb)
{
CPUClass *cc = CPU_GET_CLASS(cpu);
- int32_t insns_left;
/* 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())
*/
- insns_left = atomic_read(&cpu->icount_decr.u32);
- atomic_set(&cpu->icount_decr.u16.high, 0);
- if (unlikely(insns_left < 0)) {
- /* Ensure the zeroing of icount_decr comes before the next read
- * of cpu->exit_request or cpu->interrupt_request.
- */
- smp_mb();
- }
+ atomic_mb_set(&cpu->icount_decr.u16.high, 0);
if (unlikely(atomic_read(&cpu->interrupt_request))) {
int interrupt_request;