From 7f1d59bb8323a67800a93805f4e53e449a64a7c2 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 15 Feb 2018 13:09:37 -0500 Subject: [PATCH] tcg: synchronize cpu->exit_request and cpu->tcg_exit_req accesses Backports commit ab096a75cd626dcd4ad34b2a11652df0269bee0d from qemu --- qemu/cpu-exec.c | 30 +++++++++++++++++------------- qemu/qom/cpu.c | 2 ++ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/qemu/cpu-exec.c b/qemu/cpu-exec.c index 0d7ef172..e6b02e23 100644 --- a/qemu/cpu-exec.c +++ b/qemu/cpu-exec.c @@ -244,19 +244,23 @@ int cpu_exec(struct uc_struct *uc, CPUState *cpu) cpu->current_tb = NULL; switch (next_tb & TB_EXIT_MASK) { - case TB_EXIT_REQUESTED: - /* Something asked us to stop executing - * chained TBs; just continue round the main - * loop. Whatever requested the exit will also - * have set something else (eg exit_request or - * interrupt_request) which we will handle - * next time around the loop. - */ - tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK); - next_tb = 0; - break; - default: - break; + case TB_EXIT_REQUESTED: + /* Something asked us to stop executing + * chained TBs; just continue round the main + * loop. Whatever requested the exit will also + * have set something else (eg exit_request or + * interrupt_request) which we will handle + * next time around the loop. But we need to + * ensure the tcg_exit_req read in generated code + * comes before the next read of cpu->exit_request + * or cpu->interrupt_request. + */ + smp_rmb(); + tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK); + next_tb = 0; + break; + default: + break; } } /* reset soft MMU for next block (it can currently diff --git a/qemu/qom/cpu.c b/qemu/qom/cpu.c index feca15b5..6acd3308 100644 --- a/qemu/qom/cpu.c +++ b/qemu/qom/cpu.c @@ -107,6 +107,8 @@ void cpu_reset_interrupt(CPUState *cpu, int mask) void cpu_exit(CPUState *cpu) { cpu->exit_request = 1; + /* Ensure cpu_exec will see the exit request after TCG has exited. */ + smp_wmb(); cpu->tcg_exit_req = 1; }