From: David Woodhouse <[email protected]>

The next commit lets the Xen attribute ioctls wait out a memslot
update while holding xen_lock. A memslot update in turn waits for
all kvm->srcu readers, so a vCPU which blocks on xen_lock inside its
own read section would close a three-way cycle. The hypercall page
MSR write is the only such acquisition; step out of the read section
around it.

Signed-off-by: David Woodhouse <[email protected]>
Assisted-by: LLM
---
 arch/x86/include/asm/kvm_host.h | 4 ++++
 arch/x86/kvm/xen.c              | 8 ++++++++
 2 files changed, 12 insertions(+)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 3af7395c2430..6bebc4a79a33 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1108,6 +1108,10 @@ struct kvm_hv {
 #ifdef CONFIG_KVM_XEN
 /* Xen emulation context */
 struct kvm_xen {
+       /*
+        * Never taken inside a kvm->srcu read section: holders may wait
+        * out memslot updates (synchronize_srcu).
+        */
        struct mutex xen_lock;
        u32 xen_version;
        bool long_mode;
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index d64630a417a7..74dad6789e42 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -1320,7 +1320,15 @@ int kvm_xen_write_hypercall_page(struct kvm_vcpu *vcpu, 
u64 data)
        bool lm = is_long_mode(vcpu);
        int r = 0;
 
+       /*
+        * The attribute ioctls wait out memslot updates while holding
+        * xen_lock; a memslot update waits for this vCPU's kvm->srcu
+        * read section to quiesce. Blocking on xen_lock inside that
+        * read section would close the cycle, so step out of it first.
+        */
+       kvm_vcpu_srcu_read_unlock(vcpu);
        mutex_lock(&kvm->arch.xen.xen_lock);
+       kvm_vcpu_srcu_read_lock(vcpu);
        if (kvm->arch.xen.long_mode != lm) {
                kvm->arch.xen.long_mode = lm;
 
-- 
2.43.0


Reply via email to