FAILED: patch "[PATCH] KVM: arm64: nv: Fix life cycle of the nested_mmus array" failed to apply to 7.2-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 7.2-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-7.2.y
git checkout FETCH_HEAD
git cherry-pick -x 33346f8960c7bb6a3b4e273b5cfe25c5a8be349f
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026092948-velocity-mandatory-1d5d@gregkh' --subject-prefix 'PATCH 7.2.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 33346f8960c7bb6a3b4e273b5cfe25c5a8be349f Mon Sep 17 00:00:00 2001
From: Marc Zyngier <[email protected]>
Date: Fri, 11 Sep 2026 17:22:02 +0100
Subject: [PATCH] KVM: arm64: nv: Fix life cycle of the nested_mmus array
The nested_mmus array holds the shadow page tables that are used when a guest is running a nested context. These structures are allocated on VCPU_INIT for whole guest, which implies that they may have to be relocated as the array grows.
Should a VCPU_INIT occur whilst a vcpu is actively running an L2 and that the allocation requires relocation, that vcpu will still be running with a pointer to the previous structure, which will have been freed.
Fix this by turning the array of structures to an array of pointers, which is now allocated at VM creation, sized to the absolute maximum that KVM can handle.
In turn, each VCPU_INIT contributes S2_MMU_PER_VCPU to the pool. No reallocation is ever performed, and the life cycle of each object is much clearer:
- the nested_mmus array is allocated in kvm_init_nested(), and freed in kvm_arch_destroy_vm()
- s2_mmu structures are allocated in kvm_vcpu_init_nested(), and freed on kvm_arch_flush_shadow_all()
Finally, the freeing of vcpu->arch.vncr_array is made consistent rather than being done on some failure paths, but not others.
arch/arm64/include/asm/kvm_host.h +1 -1
@@ -322,7 +322,7 @@ struct kvm_arch {* Stage 2 paging state for VMs with nested S2 using a virtual * VMID. */ -struct kvm_s2_mmu *nested_mmus; +struct kvm_s2_mmu **nested_mmus;size_t nested_mmus_size;int nested_mmus_next;
arch/arm64/include/asm/kvm_nested.h +1 -1
@@ -66,7 +66,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 void kvm_init_nested (struct kvm *kvm); +extern int kvm_init_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);
arch/arm64/kvm/arm.c +6 -2
@@ -236,8 +236,6 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)mutex_unlock (&kvm->lock);#endif -kvm_init_nested (kvm); - ret =kvm_share_hyp (kvm, kvm +1 );if (ret)return ret;
@@ -252,6 +250,10 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)if (ret) goto err_free_cpumask; + ret =kvm_init_nested (kvm); +if (ret) + goto err_uninit_mmu; +if (is_protected_kvm_enabled ()) {/* * If any failures occur after this is successful, make sure to
@@ -280,6 +282,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); err_free_cpumask:free_cpumask_var (kvm->arch.supported_cpus); err_unshare_kvm:
@@ -337,6 +340,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm)kvm_unshare_hyp (kvm, kvm +1 ); +kvfree (kvm->arch.nested_mmus);kvm_arm_teardown_hypercalls (kvm); }
arch/arm64/kvm/nested.c +43 -50
171 lines not on this page · raw message
Sasha Levin
maintainerPATCH 1/1 KVM: arm64: nv: Fix life cycle of the nested_mmus array
From: Marc Zyngier <[email protected]>
[ Upstream commit 33346f8960c7bb6a3b4e273b5cfe25c5a8be349f ]
The nested_mmus array holds the shadow page tables that are used when a guest is running a nested context. These structures are allocated on VCPU_INIT for whole guest, which implies that they may have to be relocated as the array grows.
Should a VCPU_INIT occur whilst a vcpu is actively running an L2 and that the allocation requires relocation, that vcpu will still be running with a pointer to the previous structure, which will have been freed.
Fix this by turning the array of structures to an array of pointers, which is now allocated at VM creation, sized to the absolute maximum that KVM can handle.
In turn, each VCPU_INIT contributes S2_MMU_PER_VCPU to the pool. No reallocation is ever performed, and the life cycle of each object is much clearer:
- the nested_mmus array is allocated in kvm_init_nested(), and freed in kvm_arch_destroy_vm()
- s2_mmu structures are allocated in kvm_vcpu_init_nested(), and freed on kvm_arch_flush_shadow_all()
Finally, the freeing of vcpu->arch.vncr_array is made consistent rather than being done on some failure paths, but not others.
--- arch/arm64/include/asm/kvm_host.h | 2 +- arch/arm64/include/asm/kvm_nested.h | 2 +- arch/arm64/kvm/arm.c | 8 ++- arch/arm64/kvm/nested.c | 89 +++++++++++++---------------- 4 files changed, 49 insertions(+), 52 deletions(-)
arch/arm64/include/asm/kvm_host.h +1 -1
@@ -322,7 +322,7 @@ struct kvm_arch {* Stage 2 paging state for VMs with nested S2 using a virtual * VMID. */ -struct kvm_s2_mmu *nested_mmus; +struct kvm_s2_mmu **nested_mmus;size_t nested_mmus_size;int nested_mmus_next;
arch/arm64/include/asm/kvm_nested.h +1 -1
@@ -66,7 +66,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 void kvm_init_nested (struct kvm *kvm); +extern int kvm_init_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);
arch/arm64/kvm/arm.c +6 -2
@@ -236,8 +236,6 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)mutex_unlock (&kvm->lock);#endif -kvm_init_nested (kvm); - ret =kvm_share_hyp (kvm, kvm +1 );if (ret)return ret;
@@ -252,6 +250,10 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)if (ret) goto err_free_cpumask; + ret =kvm_init_nested (kvm); +if (ret) + goto err_uninit_mmu; +if (is_protected_kvm_enabled ()) {/* * If any failures occur after this is successful, make sure to
@@ -280,6 +282,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); err_free_cpumask:free_cpumask_var (kvm->arch.supported_cpus); err_unshare_kvm:
@@ -337,6 +340,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm)kvm_unshare_hyp (kvm, kvm +1 ); +kvfree (kvm->arch.nested_mmus);kvm_arm_teardown_hypercalls (kvm); }
arch/arm64/kvm/nested.c +41 -48
168 lines not on this page · raw message
Signature · 1 line
2.53.0