All of lore.kernel.org
 help / color / mirror / Atom feed
From: Claudio Imbrenda <imbrenda@linux.ibm.com>
To: linux-kernel@vger.kernel.org
Cc: kvm@vger.kernel.org, linux-s390@vger.kernel.org,
	borntraeger@de.ibm.com, frankja@linux.ibm.com, david@kernel.org,
	seiden@linux.ibm.com, nrb@linux.ibm.com,
	schlameuss@linux.ibm.com, gra@linux.ibm.com
Subject: [PATCH v1 07/11] KVM: s390: Move all code into kvm_arch_prepare_memory_region()
Date: Tue, 11 Aug 2026 17:56:37 +0200	[thread overview]
Message-ID: <20260811155641.219777-8-imbrenda@linux.ibm.com> (raw)
In-Reply-To: <20260811155641.219777-1-imbrenda@linux.ibm.com>

Move all code from kvm_arch_commit_memory_region() into
kvm_arch_prepare_memory_region(). This allows the function to fail
gracefully if needed. The previous behaviour was to print a warning and
continue execution with page tables incosistent with the memslots.

The new kvm_s390_mmu_cache_extended_topup() function is used to
guarantee that the necessary DAT table updates can be performed
successfully.

Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Fixes: e38c884df921 ("KVM: s390: Switch to new gmap")
---
 arch/s390/kvm/kvm-s390.c | 124 +++++++++++++++++++--------------------
 1 file changed, 59 insertions(+), 65 deletions(-)

diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 02c5428ba239..c4196f9af05d 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -5766,11 +5766,28 @@ bool kvm_arch_irqchip_in_kernel(struct kvm *kvm)
 }
 
 /* Section: memory related */
+static long cmma_d_count_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)
+{
+	union pgste pgste;
+
+	pgste = pgste_get_lock(ptep);
+	if (pgste.cmma_d) {
+		pgste.cmma_d = 0;
+		atomic64_dec(walk->priv);
+	}
+	pgste_set_unlock(ptep, pgste);
+	return 0;
+}
+
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
 				   const struct kvm_memory_slot *old,
 				   struct kvm_memory_slot *new,
 				   enum kvm_mr_change change)
 {
+	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;
+
 	if (kvm_is_ucontrol(kvm) && new && new->id < KVM_USER_MEM_SLOTS)
 		return -EINVAL;
 
@@ -5785,6 +5802,10 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
 		 * and munmap() stuff in this slot after doing this call at any
 		 * time.
 		 */
+		if (change != KVM_MR_MOVE && change != KVM_MR_CREATE) {
+			WARN(1, "Unknown KVM MR CHANGE: %d\n", change);
+			return -EINVAL;
+		}
 		if (new->userspace_addr & ~PAGE_MASK)
 			return -EINVAL;
 		if ((new->base_gfn + new->npages) * PAGE_SIZE > kvm->arch.mem_limit)
@@ -5793,57 +5814,27 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
 			return -EINVAL;
 	}
 
-	if (!kvm->arch.migration_mode)
-		return 0;
-
-	/*
-	 * Turn off migration mode when:
-	 * - userspace creates a new memslot with dirty logging off,
-	 * - userspace modifies an existing memslot (MOVE or FLAGS_ONLY) and
-	 *   dirty logging is turned off.
-	 * Migration mode expects dirty page logging being enabled to store
-	 * its dirty bitmap.
-	 */
-	if (change != KVM_MR_DELETE &&
-	    !(new->flags & KVM_MEM_LOG_DIRTY_PAGES))
-		WARN(kvm_s390_vm_stop_migration(kvm),
-		     "Failed to stop migration mode");
-
-	return 0;
-}
-
-static long cmma_d_count_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)
-{
-	union pgste pgste;
-
-	pgste = pgste_get_lock(ptep);
-	if (pgste.cmma_d) {
-		pgste.cmma_d = 0;
-		atomic64_dec(walk->priv);
+	if (kvm->arch.migration_mode) {
+		/*
+		 * Turn off migration mode when:
+		 * - userspace creates a new memslot with dirty logging off,
+		 * - userspace modifies an existing memslot (MOVE or FLAGS_ONLY)
+		 *   and dirty logging is turned off.
+		 * Migration mode expects dirty page logging being enabled to
+		 * store its dirty bitmap.
+		 */
+		if (change != KVM_MR_DELETE &&
+		    !(new->flags & KVM_MEM_LOG_DIRTY_PAGES))
+			WARN(kvm_s390_vm_stop_migration(kvm),
+			     "Failed to stop migration mode");
 	}
-	pgste_set_unlock(ptep, pgste);
-	return 0;
-}
-
-void kvm_arch_commit_memory_region(struct kvm *kvm,
-				struct kvm_memory_slot *old,
-				const struct kvm_memory_slot *new,
-				enum kvm_mr_change change)
-{
-	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;
-
-	guard(mutex)(&kvm->slots_arch_lock);
 
 	if (change == KVM_MR_FLAGS_ONLY)
-		return;
+		return 0;
 
 	mc = kvm_s390_new_mmu_cache();
-	if (!mc) {
-		rc = -ENOMEM;
-		goto out;
-	}
+	if (!mc || kvm_s390_mmu_cache_extended_topup(mc))
+		return -ENOMEM;
 
 	scoped_guard(write_lock, &kvm->mmu_lock) {
 		if (kvm->arch.migration_mode && kvm->arch.use_cmma && old) {
@@ -5852,28 +5843,31 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
 					    &kvm->arch.cmma_dirty_pages);
 		}
 
-		switch (change) {
-		case KVM_MR_DELETE:
+		if (change == KVM_MR_DELETE || change == KVM_MR_MOVE)
 			rc = dat_delete_slot(mc, kvm->arch.gmap->asce, old->base_gfn, old->npages);
-			break;
-		case KVM_MR_MOVE:
-			rc = dat_delete_slot(mc, kvm->arch.gmap->asce, old->base_gfn, old->npages);
-			if (rc)
-				break;
-			fallthrough;
-		case KVM_MR_CREATE:
+		if (!rc && (change == KVM_MR_MOVE || change == KVM_MR_CREATE))
 			rc = dat_create_slot(mc, kvm->arch.gmap->asce, new->base_gfn, new->npages);
-			break;
-		case KVM_MR_FLAGS_ONLY:
-			break;
-		default:
-			WARN(1, "Unknown KVM MR CHANGE: %d\n", change);
-		}
 	}
-out:
-	if (rc)
-		pr_warn("failed to commit memory region\n");
-	return;
+
+	/*
+	 * dat_{create,delete}_slot() can only fail in two cases:
+	 * - Internal consistency error in the gmap DAT tables
+	 * - Out of memory while allocating DAT tables
+	 * The first case should not be possible in general, and is a symptom of
+	 * a serious KVM bug; the second should also be impossible because the
+	 * mmu cache has been filled to the brim, and has more than enough
+	 * capacity to handle the worst cases. Hence it is safe to put this
+	 * KVM_BUG_ON() here, as it should not be triggerable unless some
+	 * serious bug has occurred somewhere else.
+	 */
+	return KVM_BUG_ON(rc, kvm);
+}
+
+void kvm_arch_commit_memory_region(struct kvm *kvm,
+				   struct kvm_memory_slot *old,
+				   const struct kvm_memory_slot *new,
+				   enum kvm_mr_change change)
+{
 }
 
 /**
-- 
2.55.0


  parent reply	other threads:[~2026-08-11 15:56 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-11 15:56 [PATCH v1 00/11] KVM: s390: And then... even more fixes again Claudio Imbrenda
2026-08-11 15:56 ` [PATCH v1 01/11] KVM: s390: Properly handle NULL pointer in dat_cond_set_storage_key() Claudio Imbrenda
2026-08-12  7:02   ` Christian Borntraeger
2026-08-12  8:06   ` Christoph Schlameuss
2026-08-11 15:56 ` [PATCH v1 02/11] KVM: s390: Use srcu in kvm_arch_vcpu_unlocked_ioctl() Claudio Imbrenda
2026-08-11 17:26   ` Christian Borntraeger
2026-08-11 18:01     ` Claudio Imbrenda
2026-08-11 15:56 ` [PATCH v1 03/11] KVM: s390: Fix get_all_floating_irqs() Claudio Imbrenda
2026-08-12  7:11   ` Christian Borntraeger
2026-08-12  9:12     ` Claudio Imbrenda
2026-08-11 15:56 ` [PATCH v1 04/11] KVM: s390: Fix dirty marking in adapter_indicators_set*() Claudio Imbrenda
2026-08-11 15:56 ` [PATCH v1 05/11] KVM: s390: Fix pgste_get_trylock_multiple() Claudio Imbrenda
2026-08-11 17:07   ` Christian Borntraeger
2026-08-11 15:56 ` [PATCH v1 06/11] KVM: s390: Introduce extended topup for struct kvm_s390_mmu_cache Claudio Imbrenda
2026-08-11 15:56 ` Claudio Imbrenda [this message]
2026-08-12  8:39   ` [PATCH v1 07/11] KVM: s390: Move all code into kvm_arch_prepare_memory_region() Christian Borntraeger
2026-08-11 15:56 ` [PATCH v1 08/11] KVM: s390: Fix IRQ injection with SIGP Stop and Store Status Claudio Imbrenda
2026-08-11 15:56 ` [PATCH v1 09/11] KVM: s390: Fix kvm_s390_clear_pv_state() Claudio Imbrenda
2026-08-12  7:22   ` Christian Borntraeger
2026-08-12  8:07   ` Christian Borntraeger
2026-08-11 15:56 ` [PATCH v1 10/11] KVM: s390: Fix potential tiny kernel stack leak Claudio Imbrenda
2026-08-11 17:03   ` Christian Borntraeger
2026-08-11 15:56 ` [PATCH v1 11/11] KVM: s390: Fix _gaccess_shadow_fault() Claudio Imbrenda

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260811155641.219777-8-imbrenda@linux.ibm.com \
    --to=imbrenda@linux.ibm.com \
    --cc=borntraeger@de.ibm.com \
    --cc=david@kernel.org \
    --cc=frankja@linux.ibm.com \
    --cc=gra@linux.ibm.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=nrb@linux.ibm.com \
    --cc=schlameuss@linux.ibm.com \
    --cc=seiden@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.