Create a helper method release_gmap_shadow_safe() to simplify releasing the gmap shadow of a vsie_page and a method kvm_s390_vsie_destroy_page() reduce nesting. Both methods will be called from multiple places in upcoming patches. Signed-off-by: Christoph Schlameuss --- arch/s390/kvm/s390/vsie.c | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/arch/s390/kvm/s390/vsie.c b/arch/s390/kvm/s390/vsie.c index 75676f493ab2..78d59fc535f7 100644 --- a/arch/s390/kvm/s390/vsie.c +++ b/arch/s390/kvm/s390/vsie.c @@ -164,6 +164,17 @@ static void release_gmap_shadow(struct vsie_page *vsie_page) } } +static void release_gmap_shadow_safe(struct kvm *kvm, struct vsie_page *vsie_page) +{ + if (!vsie_page->gmap_cache.gmap) + return; + + guard(spinlock)(&kvm->arch.gmap->children_lock); + + if (vsie_page->gmap_cache.gmap) + release_gmap_shadow(vsie_page); +} + static struct gmap *acquire_gmap_shadow(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) { union ctlreg0 cr0; @@ -751,13 +762,13 @@ static int shadow_scb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) } /* unpin the scb provided by guest 2, marking it as dirty */ -static void unpin_scb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page, +static void unpin_scb(struct kvm *kvm, struct vsie_page *vsie_page, gpa_t gpa) { hpa_t hpa = virt_to_phys(vsie_page->scb_o); if (hpa) - unpin_guest_page(vcpu->kvm, gpa, hpa); + unpin_guest_page(kvm, gpa, hpa); vsie_page->scb_o = NULL; } @@ -1585,11 +1596,7 @@ static struct vsie_page *get_vsie_page(struct kvm *kvm, unsigned long addr) mutex_unlock(&kvm->arch.vsie.mutex); memset(&vsie_page->scb_s, 0, sizeof(struct kvm_s390_sie_block)); - if (vsie_page->gmap_cache.gmap) { - scoped_guard(spinlock, &kvm->arch.gmap->children_lock) - if (vsie_page->gmap_cache.gmap) - release_gmap_shadow(vsie_page); - } + release_gmap_shadow_safe(kvm, vsie_page); prefix_unmapped(vsie_page); vsie_page->fault_addr = 0; vsie_page->scb_s.ihcpu = 0xffffU; @@ -1644,7 +1651,7 @@ int kvm_s390_handle_vsie(struct kvm_vcpu *vcpu) out_unshadow: unshadow_scb(vcpu, vsie_page); out_unpin_scb: - unpin_scb(vcpu, vsie_page, scb_addr); + unpin_scb(vcpu->kvm, vsie_page, scb_addr); out_put: put_vsie_page(vsie_page); @@ -1658,24 +1665,29 @@ void kvm_s390_vsie_init(struct kvm *kvm) xa_init_flags(&kvm->arch.vsie.addr_to_page, XA_FLAGS_ACCOUNT); } +static void kvm_s390_vsie_destroy_page(struct kvm *kvm, struct vsie_page *vsie_page) +{ + unpin_scb(kvm, vsie_page, vsie_page->scb_gpa); + release_gmap_shadow_safe(kvm, vsie_page); + free_vsie_page(vsie_page); +} + /* Destroy the vsie data structures. To be called when a vm is destroyed. */ void kvm_s390_vsie_destroy(struct kvm *kvm) { struct vsie_page *vsie_page; int i; - mutex_lock(&kvm->arch.vsie.mutex); + guard(mutex)(&kvm->arch.vsie.mutex); + for (i = 0; i < kvm->arch.vsie.page_count; i++) { vsie_page = kvm->arch.vsie.pages[i]; - scoped_guard(spinlock, &kvm->arch.gmap->children_lock) - if (vsie_page->gmap_cache.gmap) - release_gmap_shadow(vsie_page); kvm->arch.vsie.pages[i] = NULL; - free_vsie_page(vsie_page); + kvm_s390_vsie_destroy_page(kvm, vsie_page); } - xa_destroy(&kvm->arch.vsie.addr_to_page); + kvm->arch.vsie.page_count = 0; - mutex_unlock(&kvm->arch.vsie.mutex); + xa_destroy(&kvm->arch.vsie.addr_to_page); } void kvm_s390_vsie_kick(struct kvm_vcpu *vcpu) -- 2.55.0