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

