--- /dev/null
+From 70543358fa08e0f7cebc3447c3b70fe97ad7aaa8 Mon Sep 17 00:00:00 2001
+From: Hyunwoo Kim <imv4bel@gmail.com>
+Date: Fri, 5 Jun 2026 17:27:01 +0900
+Subject: KVM: arm64: Reassign nested_mmus array behind mmu_lock
+
+From: Hyunwoo Kim <imv4bel@gmail.com>
+
+commit 70543358fa08e0f7cebc3447c3b70fe97ad7aaa8 upstream.
+
+kvm->arch.nested_mmus[] is walked under kvm->mmu_lock, including from the
+MMU notifier path (kvm_unmap_gfn_range() -> kvm_nested_s2_unmap()), which
+can run at any time. kvm_vcpu_init_nested() reallocates the array and frees
+the old buffer while holding only kvm->arch.config_lock, so such a walker
+can reference the freed array.
+
+Allocate the new array outside of mmu_lock, as the allocation can sleep.
+Under the lock, copy the existing entries, fix up the back pointers and
+reassign the array. Free the old buffer after dropping the lock, as
+kvfree() can sleep as well.
+
+Fixes: 4f128f8e1aaac ("KVM: arm64: nv: Support multiple nested Stage-2 mmu structures")
+Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
+Reviewed-by: Oliver Upton <oupton@kernel.org>
+Link: https://patch.msgid.link/aiKIVVeIr1aAB1yp@v4bel
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Cc: stable@vger,kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kvm/nested.c | 37 ++++++++++++++++++++++---------------
+ 1 file changed, 22 insertions(+), 15 deletions(-)
+
+--- a/arch/arm64/kvm/nested.c
++++ b/arch/arm64/kvm/nested.c
+@@ -89,21 +89,28 @@ int kvm_vcpu_init_nested(struct kvm_vcpu
+ * again, and there is no reason to affect the whole VM for this.
+ */
+ num_mmus = atomic_read(&kvm->online_vcpus) * S2_MMU_PER_VCPU;
+- tmp = kvrealloc(kvm->arch.nested_mmus,
+- size_mul(sizeof(*kvm->arch.nested_mmus), num_mmus),
+- GFP_KERNEL_ACCOUNT | __GFP_ZERO);
+- if (!tmp)
+- return -ENOMEM;
+-
+- swap(kvm->arch.nested_mmus, tmp);
+-
+- /*
+- * If we went through a realocation, adjust the MMU back-pointers in
+- * the previously initialised kvm_pgtable structures.
+- */
+- if (kvm->arch.nested_mmus != tmp)
+- for (int i = 0; i < kvm->arch.nested_mmus_size; i++)
+- kvm->arch.nested_mmus[i].pgt->mmu = &kvm->arch.nested_mmus[i];
++
++ if (num_mmus > kvm->arch.nested_mmus_size) {
++ tmp = kvcalloc(num_mmus, sizeof(*tmp), GFP_KERNEL_ACCOUNT);
++ if (!tmp)
++ return -ENOMEM;
++
++ write_lock(&kvm->mmu_lock);
++
++ if (kvm->arch.nested_mmus_size) {
++ memcpy(tmp, kvm->arch.nested_mmus,
++ size_mul(sizeof(*tmp), kvm->arch.nested_mmus_size));
++
++ for (int i = 0; i < kvm->arch.nested_mmus_size; i++)
++ tmp[i].pgt->mmu = &tmp[i];
++ }
++
++ swap(kvm->arch.nested_mmus, tmp);
++
++ write_unlock(&kvm->mmu_lock);
++
++ kvfree(tmp);
++ }
+
+ for (int i = kvm->arch.nested_mmus_size; !ret && i < num_mmus; i++)
+ ret = init_nested_s2_mmu(kvm, &kvm->arch.nested_mmus[i]);