[PATCH v4 01/12] KVM: x86/xen: Don't block memslot updates while halted in SCHEDOP_poll
From: David Woodhouse
Date: Mon Oct 19 2026 - 12:52:20 EST
From: David Woodhouse <dwmw@xxxxxxxxxxxx>
kvm_xen_schedop_poll() halts the vCPU from within vcpu_run's exit
handling, without dropping the vCPU's kvm->srcu read section as
vcpu_block() is careful to do around every other halt. The poll wakes
only on delivery of a polled event channel, its poll timer, a signal,
or KVM_REQ_UNBLOCK — and a memslot update raises none of those. With a
zero timeout and a port which nobody is going to signal, the vCPU
sleeps at the guest's pleasure, holding the read section the whole
time.
A memslot update then hangs, unkillably, in kvm_swap_active_memslots()'s
synchronize_srcu() waiting for that reader to quiesce. Any guest with
SCHEDOP_poll available can thus park its VMM's memslot ioctls more or
less indefinitely.
Drop the srcu read section across the halt. A hypercall is only ever
processed from vcpu_run's exit handling, so the vCPU's own read lock
accounting is always the live section here, and nothing between the
unlock and the relock touches memslot-derived state: the pending-event
check which precedes it takes its own read section, and the timer
cleanup which follows does not need one.
Found by Sashiko review while testing the series which lets Xen
attribute ioctls wait out memslot updates — those waits joined the
same queue, with rather more visibility.
Fixes: 1a65105a5aba ("KVM: x86/xen: handle PV spinlocks slowpath")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: LLM
Signed-off-by: David Woodhouse <dwmw@xxxxxxxxxxxx>
---
arch/x86/kvm/xen.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index 6aa00f746cba..2a0477ad0c91 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -1594,7 +1594,15 @@ static bool kvm_xen_schedop_poll(struct kvm_vcpu *vcpu, bool is_64bit,
mod_timer(&vcpu->arch.xen.poll_timer,
jiffies + nsecs_to_jiffies(sched_poll.timeout));
+ /*
+ * Drop the vCPU's kvm->srcu read section across the halt, as
+ * vcpu_block() does: the halt is unbounded (with a zero
+ * timeout, entirely at the guest's pleasure), and a memslot
+ * update cannot complete until this read section quiesces.
+ */
+ kvm_vcpu_srcu_read_unlock(vcpu);
kvm_vcpu_halt(vcpu);
+ kvm_vcpu_srcu_read_lock(vcpu);
if (sched_poll.timeout)
timer_delete(&vcpu->arch.xen.poll_timer);
--
2.43.0