arm_cpu_has_work() runs without the BQL held and can inspect halt_reason and event_register while other CPU contexts update them. The WFxT timer may also consume HALT_WFE asynchronously.
Use atomic accesses for the halt state, including the WFI/WFE and halt-exit stores. This keeps the halt/wakeup protocol race-free and matches the atomic state transitions used by the asynchronous wake-up paths. Signed-off-by: Philippe Mathieu-Daudé <[email protected]> Reviewed-by: Richard Henderson <[email protected]> Message-Id: <[email protected]> --- target/arm/cpu.c | 7 ++++--- target/arm/tcg/op_helper.c | 8 ++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 5cfd3bcfc8e..090470da40a 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -144,20 +144,21 @@ int arm_cpu_mmu_index(CPUState *cs, bool ifetch) static bool arm_cpu_has_work(CPUState *cs) { ARMCPU *cpu = ARM_CPU(cs); + ARMHaltReason halt_reason = qatomic_read(&cpu->env.halt_reason); /* * Only another PSCI call can wake the CPU up in which case the * power_state would be set by arm_set_cpu_on_and_reset_async_work() */ if (qatomic_read(&cpu->power_state) == PSCI_OFF) { - g_assert(cpu->env.halt_reason == HALT_PSCI); + g_assert(halt_reason == HALT_PSCI); return false; } /* * A wake-up event should only wake us if we are halted on a WFE */ - if (cpu->env.halt_reason == HALT_WFE && cpu->env.event_register) { + if (halt_reason == HALT_WFE && qatomic_read(&cpu->env.event_register)) { return true; } @@ -882,7 +883,7 @@ bool arm_cpu_exec_halt(CPUState *cs) timer_del(cpu->wfxt_timer); } /* clear the halt reason */ - cpu->env.halt_reason = NOT_HALTED; + qatomic_set(&cpu->env.halt_reason, NOT_HALTED); } return leave_halt; } diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c index c2b09176cb1..643b1482523 100644 --- a/target/arm/tcg/op_helper.c +++ b/target/arm/tcg/op_helper.c @@ -398,7 +398,7 @@ void HELPER(wfi)(CPUARMState *env, uint32_t insn_len) target_el); } - env->halt_reason = HALT_WFI; + qatomic_set(&env->halt_reason, HALT_WFI); cs->exception_index = EXCP_HLT; cs->halted = 1; cpu_loop_exit(cs); @@ -460,7 +460,7 @@ void HELPER(wfit)(CPUARMState *env, uint32_t rd) } else { timer_mod(cpu->wfxt_timer, nexttick); } - env->halt_reason = HALT_WFI; + qatomic_set(&env->halt_reason, HALT_WFI); cs->exception_index = EXCP_HLT; cs->halted = 1; cpu_loop_exit(cs); @@ -629,7 +629,7 @@ void HELPER(wfe)(CPUARMState *env, uint32_t insn_len) } } - env->halt_reason = HALT_WFE; + qatomic_set(&env->halt_reason, HALT_WFE); cs->exception_index = EXCP_HLT; cs->halted = 1; cpu_loop_exit(cs); @@ -723,7 +723,7 @@ void HELPER(wfet)(CPUARMState *env, uint32_t rd) } } - env->halt_reason = HALT_WFE; + qatomic_set(&env->halt_reason, HALT_WFE); cs->exception_index = EXCP_HLT; cs->halted = 1; cpu_loop_exit(cs); -- 2.53.0
