[PATCH 09/16] KVM: planes: Kick the running twin's pCPU, not the request target's
From: David Woodhouse
Date: Wed Nov 11 2026 - 17:34:07 EST
From: David Woodhouse <dwmw@xxxxxxxxxxxx>
The remote kick paths (kvm_make_vcpus_request_mask(),
kvm_make_all_cpus_request(), __kvm_vcpu_kick()) read
READ_ONCE(vcpu->cpu) of the plane-0 vCPU. But vcpu->cpu is per plane
vCPU (kvm_arch_vcpu_load() refreshes only the loaded twin's copy),
while vcpu->mode is shared in kvm_vcpu_common. When the vCPU thread
has migrated pCPUs while a non-zero plane was loaded, the shared mode
reads IN_GUEST_MODE but the IPI goes to plane 0's stale pCPU: a
waiting request such as a remote TLB flush completes while the twin
keeps running on stale translations.
Read the pCPU from common->current_vcpu in both kick paths. It names
the loaded twin, so its cpu field tracks where the vCPU thread runs
(on x86, kvm_arch_vcpu_load() refreshes it).
Found by a local Sashiko review.
Signed-off-by: David Woodhouse <dwmw@xxxxxxxxxxxx>
---
virt/kvm/kvm_main.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index d256bbf301f4..24d2291b60a2 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -244,7 +244,14 @@ static void kvm_make_vcpu_request(struct kvm_vcpu *vcpu, unsigned int req,
* finalized. See kvm_vcpu_kick() for more details on handling requests.
*/
if (kvm_request_needs_ipi(vcpu, req)) {
- cpu = READ_ONCE(vcpu->cpu);
+ /*
+ * vcpu->cpu is per plane vCPU and kvm_arch_vcpu_load()
+ * refreshes only the loaded twin's, so this plane's copy
+ * can point at a pCPU the thread has long left while a
+ * twin runs elsewhere. The mode just checked is shared;
+ * the IPI must go where the running twin actually is.
+ */
+ cpu = READ_ONCE(READ_ONCE(vcpu->common->current_vcpu)->cpu);
if (cpu != -1 && cpu != current_cpu)
__cpumask_set_cpu(cpu, tmp);
}
@@ -4129,7 +4136,13 @@ void __kvm_vcpu_kick(struct kvm_vcpu *vcpu, bool wait)
* vCPU also requires it to leave IN_GUEST_MODE.
*/
if (kvm_arch_vcpu_should_kick(vcpu)) {
- cpu = READ_ONCE(vcpu->cpu);
+ /*
+ * Target the running twin's pCPU: this plane's vcpu->cpu
+ * goes stale whenever the thread migrates while another
+ * plane is loaded, and the IN_GUEST_MODE just observed is
+ * the (shared) mode of whichever twin runs.
+ */
+ cpu = READ_ONCE(READ_ONCE(vcpu->common->current_vcpu)->cpu);
if (cpu != me && (unsigned int)cpu < nr_cpu_ids && cpu_online(cpu)) {
/*
* Use a reschedule IPI to kick the vCPU if the caller
--
2.50.1