From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E958C42AFBB; Fri, 14 Aug 2026 10:33:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786703619; cv=none; b=TikyooOIzzv+yTp5SuPBua6uV/mbwIMwVn3LVvHv8qkcN03xoLMPGjwXcvxtgiavXpxU8Y2x0uth0opq8hJpSIn5EPMY8/SAJXEXERFwcWJH7UjxI5fVTsfDCbp755rP5IojMEYLRw7S66Y4uMbxKLwh0fUDyk2frnKXvt5DH1U= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786703619; c=relaxed/simple; bh=BlTj4P6iQLZ++pr3y+IHUQu9uNU8sG0llyQjpLzSTxo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RrrI61+HNdRBb6jGrpkGQozmJURdirgxSXyVpIyWVNfcejPXCfi/4R58PzVuh2tp2yLnmzB+XV2RfFshMGtdRrUgjuCsg9jH9SxY/sK6lo72qoDezmBWuJV3roZEJcISqDoUNY4k5Y1pRTr7hEL8dqnhOKzUGSXmINymXyar3Gk= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bBzNbLFO; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bBzNbLFO" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1F2601F00A3D; Fri, 14 Aug 2026 10:33:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1786703606; bh=afnZ0jJXOhQY7VGkttvC9Hi+PEuDYghXStcmJck84J4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=bBzNbLFOmSiE6nkWmpu3CnLBhWL9K9NITZ9sqqvp7yohSr/9HEanfI5OpN925RN69 G3r49KTn4S06vIbvAEZD/VtTy4qfkZSXMIkeP8KLciPxxFR/JGYgYt1sEfacpQwp/a gTA2DO6PQRZ978mVimQJRNAyY7u9JVEFOzzrIPwGfI8oLK9mO7fuoZQuvLs0sc8H8I xcKZmtX8TvONB5AhqsBoYQHLn6ZSGNWLHuHaA6NQsV8CI773oldXxLQvFN+ql5dCRE tcRR/rwqaDb7/1d7G8Z6T/48GbEMGLkInNkCFJ3m7bq/5Xa/EOOxQQca3eOIcLVEYq 6Kxl/Dh8jaBTQ== Received: from sofa.misterjones.org ([185.219.108.64] helo=valley-girl.lan) by disco-boy.misterjones.org with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1wupE4-0000000FdQO-15I6; Fri, 14 Aug 2026 10:33:24 +0000 From: Marc Zyngier To: kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: Steffen Eiden , Joey Gouly , Suzuki K Poulose , Oliver Upton , Zenghui Yu , Fuad Tabba , ljs@kernel.org, Shen Yongchao , Karl Mehltretter , Wei-Lin Chang , stable@vger.kernel.org Subject: [PATCH v2 2/2] KVM: arm64: nv: Delay freeing of shadow S2 structures until VM destruction Date: Fri, 14 Aug 2026 11:32:30 +0100 Message-ID: <20260814103230.858578-3-maz@kernel.org> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260814103230.858578-1-maz@kernel.org> References: <20260814103230.858578-1-maz@kernel.org> Precedence: bulk X-Mailing-List: kvmarm@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SA-Exim-Connect-IP: 185.219.108.64 X-SA-Exim-Rcpt-To: kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, seiden@linux.ibm.com, joey.gouly@arm.com, suzuki.poulose@arm.com, oupton@kernel.org, yuzenghui@huawei.com, fuad.tabba@linux.dev, ljs@kernel.org, grayhat@foxmail.com, kmehltretter@gmail.com, weilin.chang@arm.com, stable@vger.kernel.org X-SA-Exim-Mail-From: maz@kernel.org X-SA-Exim-Scanned: No (on disco-boy.misterjones.org); SAEximRunCond expanded to false We free the shadow S2 structures from kvm_arch_flush_shadow_all(), which is a Bad Idea(tm). Freeing the page tables is fair game (this is what this callback is for), but freeing the container that could still be referenced by another part of the system is not great. Instead, grow separate destructors that gets called when we tear the VM down for good. From there, we can nuke both the individual MMUs as well as the global array that points to them, safe in the knowledge that the vcpus themselves have been destroyed already. Note that similarly to what happens for the canonical S2 MMU, we need to manage the freeing of the page tables both in kvm_arch_flush_shadow_all (called on address space teardown) and VM teardown (as a result of closing the VM fd, amongst others), as there is no guaranteed ordering between these two events. Fixes: 4f128f8e1aaac ("KVM: arm64: nv: Support multiple nested Stage-2 mmu structures") Signed-off-by: Marc Zyngier Cc: stable@vger.kernel.org --- arch/arm64/include/asm/kvm_nested.h | 1 + arch/arm64/kvm/arm.c | 4 ++-- arch/arm64/kvm/nested.c | 32 ++++++++++++++++++++--------- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/arch/arm64/include/asm/kvm_nested.h b/arch/arm64/include/asm/kvm_nested.h index 5b8edb2e8a87d..586026e859030 100644 --- a/arch/arm64/include/asm/kvm_nested.h +++ b/arch/arm64/include/asm/kvm_nested.h @@ -67,6 +67,7 @@ static inline u64 translate_ttbr0_el2_to_ttbr0_el1(u64 ttbr0) extern bool forward_smc_trap(struct kvm_vcpu *vcpu); extern bool forward_debug_exception(struct kvm_vcpu *vcpu); extern int kvm_init_nested(struct kvm *kvm); +extern void kvm_destroy_nested(struct kvm *kvm); extern int kvm_vcpu_init_nested(struct kvm_vcpu *vcpu); extern void kvm_init_nested_s2_mmu(struct kvm_s2_mmu *mmu); extern struct kvm_s2_mmu *lookup_s2_mmu(struct kvm_vcpu *vcpu); diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 7607173c1a40c..2b069c6440669 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -269,7 +269,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) err_uninit_mmu: kvm_uninit_stage2_mmu(kvm); - kvfree(kvm->arch.nested_mmus); + kvm_destroy_nested(kvm); err_free_cpumask: free_cpumask_var(kvm->arch.supported_cpus); err_unshare_kvm: @@ -327,7 +327,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm) kvm_unshare_hyp(kvm, kvm + 1); - kvfree(kvm->arch.nested_mmus); + kvm_destroy_nested(kvm); kvm_arm_teardown_hypercalls(kvm); } diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c index 254cbd8703b3d..d0c05db554b1c 100644 --- a/arch/arm64/kvm/nested.c +++ b/arch/arm64/kvm/nested.c @@ -55,6 +55,27 @@ int kvm_init_nested(struct kvm *kvm) return kvm->arch.nested_mmus ? 0 : -ENOMEM; } +static void kvm_uninit_shadow_stage2_mmu(struct kvm *kvm) +{ + for (int i = 0; i < kvm->arch.nested_mmus_size; i++) { + struct kvm_s2_mmu *mmu = kvm->arch.nested_mmus[i]; + + if (!WARN_ON(atomic_read(&mmu->refcnt))) + kvm_free_stage2_pgd(mmu); + } +} + +void kvm_destroy_nested(struct kvm *kvm) +{ + kvm_uninit_shadow_stage2_mmu(kvm); + + for (int i = 0; i < kvm->arch.nested_mmus_size; i+= S2_MMU_PER_VCPU) + kvfree(kvm->arch.nested_mmus[i]); + + kvm->arch.nested_mmus_size = 0; + kvfree(kvm->arch.nested_mmus); +} + static int init_nested_s2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu) { /* @@ -1310,16 +1331,7 @@ void kvm_nested_s2_flush(struct kvm *kvm) void kvm_arch_flush_shadow_all(struct kvm *kvm) { - for (int i = kvm->arch.nested_mmus_size - 1; i >= 0; i--) { - struct kvm_s2_mmu *mmu = kvm->arch.nested_mmus[i]; - - if (!WARN_ON(atomic_read(&mmu->refcnt))) - kvm_free_stage2_pgd(mmu); - - if ((i % S2_MMU_PER_VCPU) == 0) - kvfree(mmu); - } - kvm->arch.nested_mmus_size = 0; + kvm_uninit_shadow_stage2_mmu(kvm); kvm_uninit_stage2_mmu(kvm); } -- 2.47.3