Use kvm_s390_mmu_cache_alloc_rmap() to allocate the rmap in gmap_insert_rmap(), instead of a normal kzalloc_obj() with GFP_ATOMIC. This guarantees forward progress. Fixes: a2c17f9270cc ("KVM: s390: New gmap code") Signed-off-by: Claudio Imbrenda CC: stable@vger.kernel.org # 7.1 --- arch/s390/kvm/gaccess.c | 16 ++++++++-------- arch/s390/kvm/gmap.c | 7 ++++--- arch/s390/kvm/gmap.h | 3 ++- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c index 20e28b183c1a..022ea7736521 100644 --- a/arch/s390/kvm/gaccess.c +++ b/arch/s390/kvm/gaccess.c @@ -1419,8 +1419,8 @@ static int walk_guest_tables(struct gmap *sg, unsigned long saddr, struct pgtwal return kvm_s390_get_guest_page(kvm, entries + LEVEL_MEM, table.pte.pfra, wr); } -static int _do_shadow_pte(struct gmap *sg, gpa_t raddr, union pte *ptep_h, union pte *ptep, - struct guest_fault *f, bool p) +static int _do_shadow_pte(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gpa_t raddr, + union pte *ptep_h, union pte *ptep, struct guest_fault *f, bool p) { union pgste pgste; union pte newpte; @@ -1430,7 +1430,7 @@ static int _do_shadow_pte(struct gmap *sg, gpa_t raddr, union pte *ptep_h, union lockdep_assert_held(&sg->parent->children_lock); scoped_guard(spinlock, &sg->host_to_rmap_lock) - rc = gmap_insert_rmap(sg, f->gfn, gpa_to_gfn(raddr), TABLE_TYPE_PAGE_TABLE); + rc = gmap_insert_rmap(mc, sg, f->gfn, gpa_to_gfn(raddr), TABLE_TYPE_PAGE_TABLE); if (rc) return rc; @@ -1462,8 +1462,8 @@ static int _do_shadow_pte(struct gmap *sg, gpa_t raddr, union pte *ptep_h, union return 0; } -static int _do_shadow_crste(struct gmap *sg, gpa_t raddr, union crste *host, union crste *table, - struct guest_fault *f, bool p) +static int _do_shadow_crste(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gpa_t raddr, + union crste *host, union crste *table, struct guest_fault *f, bool p) { union crste newcrste, oldcrste; unsigned long mask; @@ -1476,7 +1476,7 @@ static int _do_shadow_crste(struct gmap *sg, gpa_t raddr, union crste *host, uni mask = is_pmd(*table) ? _SEGMENT_FR_MASK : _REGION3_FR_MASK; r_gfn = gpa_to_gfn(raddr) & mask; scoped_guard(spinlock, &sg->host_to_rmap_lock) - rc = gmap_insert_rmap(sg, f->gfn & mask, r_gfn, host->h.tt); + rc = gmap_insert_rmap(mc, sg, f->gfn & mask, r_gfn, host->h.tt); if (rc) return rc; @@ -1578,8 +1578,8 @@ static int _gaccess_do_shadow(struct kvm_s390_mmu_cache *mc, struct gmap *sg, if (KVM_BUG_ON(l > TABLE_TYPE_REGION3, sg->kvm)) return -EFAULT; if (l == TABLE_TYPE_PAGE_TABLE) - return _do_shadow_pte(sg, saddr, ptep_h, ptep, entries + LEVEL_MEM, w->p); - return _do_shadow_crste(sg, saddr, host, table, entries + LEVEL_MEM, w->p); + return _do_shadow_pte(mc, sg, saddr, ptep_h, ptep, entries + LEVEL_MEM, w->p); + return _do_shadow_crste(mc, sg, saddr, host, table, entries + LEVEL_MEM, w->p); } static inline int _gaccess_shadow_fault(struct kvm_vcpu *vcpu, struct gmap *sg, gpa_t saddr, diff --git a/arch/s390/kvm/gmap.c b/arch/s390/kvm/gmap.c index 52d55ddea8d4..1d289f8fa3b2 100644 --- a/arch/s390/kvm/gmap.c +++ b/arch/s390/kvm/gmap.c @@ -1000,7 +1000,8 @@ int gmap_pv_destroy_range(struct gmap *gmap, gfn_t start, gfn_t end, bool interr return 0; } -int gmap_insert_rmap(struct gmap *sg, gfn_t p_gfn, gfn_t r_gfn, int level) +int gmap_insert_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gfn, + gfn_t r_gfn, int level) { struct vsie_rmap *rmap __free(kvfree) = NULL; struct vsie_rmap *temp; @@ -1010,7 +1011,7 @@ int gmap_insert_rmap(struct gmap *sg, gfn_t p_gfn, gfn_t r_gfn, int level) KVM_BUG_ON(!is_shadow(sg), sg->kvm); lockdep_assert_held(&sg->host_to_rmap_lock); - rmap = kzalloc_obj(*rmap, GFP_ATOMIC); + rmap = kvm_s390_mmu_cache_alloc_rmap(mc); if (!rmap) return -ENOMEM; @@ -1057,7 +1058,7 @@ int gmap_protect_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gf if (level <= TABLE_TYPE_REGION1) { bitmask = -1UL << (8 + 11 * level); scoped_guard(spinlock, &sg->host_to_rmap_lock) - rc = gmap_insert_rmap(sg, p_gfn, r_gfn & bitmask, level); + rc = gmap_insert_rmap(mc, sg, p_gfn, r_gfn & bitmask, level); } if (rc) return rc; diff --git a/arch/s390/kvm/gmap.h b/arch/s390/kvm/gmap.h index 4e6979783e16..75df5d39bd78 100644 --- a/arch/s390/kvm/gmap.h +++ b/arch/s390/kvm/gmap.h @@ -100,7 +100,8 @@ int gmap_ucas_map(struct gmap *gmap, gfn_t p_gfn, gfn_t c_gfn, unsigned long cou void gmap_ucas_unmap(struct gmap *gmap, gfn_t c_gfn, unsigned long count); int gmap_enable_skeys(struct gmap *gmap); int gmap_pv_destroy_range(struct gmap *gmap, gfn_t start, gfn_t end, bool interruptible); -int gmap_insert_rmap(struct gmap *sg, gfn_t p_gfn, gfn_t r_gfn, int level); +int gmap_insert_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gfn, + gfn_t r_gfn, int level); int gmap_protect_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gfn, gfn_t r_gfn, kvm_pfn_t pfn, int level, bool wr); void gmap_set_cmma_all_dirty(struct gmap *gmap); -- 2.54.0