When low on memory, kvm_arch_commit_memory_region() might not perform the required action completely, and instead just print a warning and return. This allows the VM to continue running with an inconsistent state. Fix by refilling the struct kvm_s390_mmu_cache and trying again. A true failure only happens if the refill fails, or if the cache cannot be allocated at all; in such case print a warning and kill the VM. Such a failure cannot currently happen. Signed-off-by: Claudio Imbrenda Fixes: e38c884df921 ("KVM: s390: Switch to new gmap") --- arch/s390/kvm/kvm-s390.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 59f784f8c01b..b151d25a4a4c 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -5817,7 +5817,7 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, { const struct dat_walk_ops ops = { .pte_entry = cmma_d_count_pte, }; struct kvm_s390_mmu_cache *mc __free(kvm_s390_mmu_cache) = NULL; - int rc = 0; + int rc = -ENOMEM; guard(mutex)(&kvm->slots_arch_lock); @@ -5825,11 +5825,9 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, return; mc = kvm_s390_new_mmu_cache(); - if (!mc) { - rc = -ENOMEM; + if (!mc) goto out; - } - +retry: scoped_guard(write_lock, &kvm->mmu_lock) { if (kvm->arch.migration_mode && kvm->arch.use_cmma && old) { _dat_walk_gfn_range(old->base_gfn, old->base_gfn + old->npages, @@ -5852,11 +5850,17 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, case KVM_MR_FLAGS_ONLY: break; default: + rc = 0; WARN(1, "Unknown KVM MR CHANGE: %d\n", change); } } + if (rc == -ENOMEM) { + rc = kvm_s390_mmu_cache_topup(mc); + if (!rc) + goto retry; + } out: - if (rc) + if (KVM_BUG_ON(rc, kvm)) pr_warn("failed to commit memory region\n"); return; } -- 2.55.0