[PATCH v4 11/13] KVM: s390: Fix kvm_arch_commit_memory_region() when low on memory

From: Claudio Imbrenda

Date: Tue Jul 28 2026 - 13:21:46 EST


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 <imbrenda@xxxxxxxxxxxxx>
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