Re: [PATCH] KVM: VMX: Clear GUEST_ACTIVITY_STATE when userspace makes a vCPU RUNNABLE

Chao Gao <[email protected]>
Newsgroups org.kernel.vger.kvm,org.kernel.vger.linux-kernel,org.kernel.vger.stable
Message-ID <[email protected]>
On Wed, Aug 19, 2026 at 11:46:52AM +0800, Keqiang Duan wrote:
>Force a vCPU out of its hardware-tracked halted state when userspace
>explicitly declares the vCPU RUNNABLE via KVM_SET_MP_STATE, i.e. clear
>VMCS.GUEST_ACTIVITY_STATE if it says the vCPU is halted.  Add an optional
>kvm_x86_ops hook to do the clearing, as SVM has no equivalent VMCB field.
>
>When HLT-exiting is disabled for a VM (KVM_CAP_X86_DISABLE_EXITS with
>KVM_X86_DISABLE_EXITS_HLT, e.g. QEMU's "-overcommit cpu-pm=on"), a guest
>HLT halts the physical CPU instead of exiting to KVM, and hardware saves
>GUEST_ACTIVITY_STATE=HLT into the VMCS on the next VM-Exit.  That field is
>sticky: it survives VM-Exit/VM-Enter and is only cleared by vmx_clear_hlt()
>on event injection, or by vmx_vcpu_reset() on INIT / vCPU creation.
>
>Nothing clears it on a userspace-driven state change.  KVM_SET_REGS only
>writes the software register cache and KVM_SET_MP_STATE only writes
>vcpu->arch.mp_state; kvm_vcpu_running() likewise consults software state
>only.  A VMM that emulates a machine reset therefore ends up with a vCPU
>that KVM happily VM-Enters while hardware refuses to fetch instructions.
>
>Reproduce with a Linux guest by triggering a panic/kdump on a non-boot
>vCPU: nmi_shootdown_cpus() parks the other vCPUs -- including vCPU0 -- in
>crash_nmi_callback(), which does local_irq_disable() followed by a bare
>HLT.  The capture kernel then resets the machine via port 0xCF9.  QEMU
>rewrites RIP to 0xfff0 and sets mp_state to RUNNABLE, but vCPU0's
>GUEST_ACTIVITY_STATE is still HLT, so the BSP never executes the reset
>vector, never sends SIPIs, and the entire VM hangs at "reboot: machine
>restart" forever.  Only destroying and recreating the VM recovers it.
>
>Clearing the state is always safe: waking from HLT is architecturally
>permitted to be spurious, and every HLT in the kernel is inside a loop.
>Hook KVM_SET_MP_STATE rather than the VM-Enter path so that the clearing
>is driven by an explicit userspace declaration, and so that no work is
>added to vmx_vcpu_run().
>
>Note, vmx_clear_hlt() loses its "static" qualifier as the kvm_x86_ops table
>now lives in vmx/main.c.  TDX cannot disable HLT-exiting and KVM cannot
>access a TD's VMCS, so vt_clear_hlt() short-circuits for TD vCPUs,
>following the existing vt_*() wrapper pattern.
>
>Fixes: caa057a2cad6 ("KVM: X86: Provide a capability to disable HLT intercepts")
>Cc: [email protected]
>Signed-off-by: Keqiang Duan <[email protected]>

There was an earlier attempt to fix this issue:

https://lore.kernel.org/kvm/[email protected]

Sean suggested doing exactly this there, i.e. clearing the activity state in
kvm_arch_vcpu_ioctl_set_mpstate() via a new kvm_x86_ops hook:

https://lore.kernel.org/kvm/[email protected]/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.