PSCI can update the power state of a vCPU other than the caller. arm_cpu_has_work() reads env->halt_reason to decide whether that vCPU has work to do, and is called from the vCPU thread without the BQL held. A remote power_state/halt_reason update is therefore not observed until the target vCPU is rescheduled, so the vCPU stays halted and a PSCI CPU_ON of a secondary vCPU can hang.
Kick the vCPU after changing its state so it re-evaluates promptly. Reported-by: Paolo Bonzini <[email protected]> Signed-off-by: Philippe Mathieu-Daudé <[email protected]> --- target/arm/arm-powerctl.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/target/arm/arm-powerctl.c b/target/arm/arm-powerctl.c index ef14a1f8a94..1ba5277b023 100644 --- a/target/arm/arm-powerctl.c +++ b/target/arm/arm-powerctl.c @@ -48,9 +48,14 @@ struct CpuOnInfo { void arm_set_cpu_power_state(ARMCPU *cpu, ARMPSCIState state) { CPUARMState *env = &cpu->env; + CPUState *cs = CPU(cpu); qatomic_set(&cpu->power_state, state); qatomic_set(&env->halt_reason, state == PSCI_OFF ? HALT_PSCI : NOT_HALTED); + + if (!qemu_cpu_is_self(cs)) { + qemu_cpu_kick(cs); + } } static void arm_set_cpu_on_async_work(CPUState *target_cpu_state, -- 2.55.0
