From a4f83debce2efc170c59cafdf685afe511c3be61 Mon Sep 17 00:00:00 2001 From: Doug Cook Date: Mon, 14 Sep 2026 09:41:04 +0100 Subject: [PATCH] target/arm/whpx: fix whpx-arm post-reset CPU state Reset should leave CPU 0 running, and should leave all other CPUs suspended. Instead, no CPUs are suspended and CPUs may be left in low-power states. Fix by updating state in whpx_set_registers WHPX_LEVEL_RESET_STATE. Signed-off-by: Doug Cook Reviewed-by: Mohamed Mediouni Signed-off-by: Peter Maydell (cherry picked from commit 57197bf183f3afa906f9007de918244adff9ab7e) Signed-off-by: Michael Tokarev --- target/arm/whpx/whpx-all.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/target/arm/whpx/whpx-all.c b/target/arm/whpx/whpx-all.c index 6aa5e2cfd2..cca0f8e30d 100644 --- a/target/arm/whpx/whpx-all.c +++ b/target/arm/whpx/whpx-all.c @@ -617,6 +617,37 @@ void whpx_set_registers(CPUState *cpu, WHPXStateLevel level) whpx_set_reg(cpu, whpx_sreg_match[i].reg, val); } } + + if (level == WHPX_LEVEL_RESET_STATE) { + /* + * WHPX keeps the "vCPU is in a low-power wait" state (entered when the + * guest executes WFI/WFE) in WHvRegisterInternalActivityState, and that + * state is not affected by writing the architectural registers above. + * If the guest happened to be idle when the reset was requested, the + * vCPU would stay suspended forever. + * + * StartupSuspend is the bit WHP uses to hold a vCPU that has not been + * started yet, and it is how secondary vCPUs are parked until PSCI + * CPU_ON releases them. + */ + WHV_REGISTER_NAME name = WHvRegisterInternalActivityState; + bool powered_off = arm_cpu->power_state == PSCI_OFF; + WHV_REGISTER_VALUE ia; + HRESULT hr; + + clean_whv_register_value(&ia); + hr = whp_dispatch.WHvGetVirtualProcessorRegisters( + whpx_global.partition, cpu->cpu_index, &name, 1, &ia); + if (SUCCEEDED(hr) && + (ia.InternalActivity.IdleSuspend || + ia.InternalActivity.HaltSuspend || + ia.InternalActivity.StartupSuspend != powered_off)) { + ia.InternalActivity.IdleSuspend = 0; + ia.InternalActivity.HaltSuspend = 0; + ia.InternalActivity.StartupSuspend = powered_off; + whpx_set_reg(cpu, WHvRegisterInternalActivityState, ia); + } + } } static uint32_t max_vcpu_index;