]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: arm64: Ignore MMU notifier callbacks for protected VMs
authorWill Deacon <will@kernel.org>
Mon, 30 Mar 2026 14:48:09 +0000 (15:48 +0100)
committerMarc Zyngier <maz@kernel.org>
Mon, 30 Mar 2026 15:58:07 +0000 (16:58 +0100)
In preparation for supporting the donation of pinned pages to protected
VMs, return early from the MMU notifiers when called for a protected VM,
as the necessary hypercalls are exposed only for non-protected guests.

Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
Tested-by: Mostafa Saleh <smostafa@google.com>
Signed-off-by: Will Deacon <will@kernel.org>
Link: https://patch.msgid.link/20260330144841.26181-9-will@kernel.org
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/kvm/mmu.c
arch/arm64/kvm/pkvm.c

index 17d64a1e11e5c00906fcc93c3948cbab69009040..5e7821fe0fc45837707198c59f428c8ec8e92d5d 100644 (file)
@@ -340,6 +340,9 @@ static void __unmap_stage2_range(struct kvm_s2_mmu *mmu, phys_addr_t start, u64
 void kvm_stage2_unmap_range(struct kvm_s2_mmu *mmu, phys_addr_t start,
                            u64 size, bool may_block)
 {
+       if (kvm_vm_is_protected(kvm_s2_mmu_to_kvm(mmu)))
+               return;
+
        __unmap_stage2_range(mmu, start, size, may_block);
 }
 
@@ -2223,7 +2226,7 @@ out_unlock:
 
 bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
 {
-       if (!kvm->arch.mmu.pgt)
+       if (!kvm->arch.mmu.pgt || kvm_vm_is_protected(kvm))
                return false;
 
        __unmap_stage2_range(&kvm->arch.mmu, range->start << PAGE_SHIFT,
@@ -2238,7 +2241,7 @@ bool kvm_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
 {
        u64 size = (range->end - range->start) << PAGE_SHIFT;
 
-       if (!kvm->arch.mmu.pgt)
+       if (!kvm->arch.mmu.pgt || kvm_vm_is_protected(kvm))
                return false;
 
        return KVM_PGT_FN(kvm_pgtable_stage2_test_clear_young)(kvm->arch.mmu.pgt,
@@ -2254,7 +2257,7 @@ bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
 {
        u64 size = (range->end - range->start) << PAGE_SHIFT;
 
-       if (!kvm->arch.mmu.pgt)
+       if (!kvm->arch.mmu.pgt || kvm_vm_is_protected(kvm))
                return false;
 
        return KVM_PGT_FN(kvm_pgtable_stage2_test_clear_young)(kvm->arch.mmu.pgt,
index 42f6e50825ac1856de7bee4f3eb976daddc7b678..dd93dfdfe52d416a03387748f2dad7ec9595780e 100644 (file)
@@ -407,7 +407,12 @@ int pkvm_pgtable_stage2_map(struct kvm_pgtable *pgt, u64 addr, u64 size,
 
 int pkvm_pgtable_stage2_unmap(struct kvm_pgtable *pgt, u64 addr, u64 size)
 {
-       lockdep_assert_held_write(&kvm_s2_mmu_to_kvm(pgt->mmu)->mmu_lock);
+       struct kvm *kvm = kvm_s2_mmu_to_kvm(pgt->mmu);
+
+       if (WARN_ON(kvm_vm_is_protected(kvm)))
+               return -EPERM;
+
+       lockdep_assert_held_write(&kvm->mmu_lock);
 
        return __pkvm_pgtable_stage2_unshare(pgt, addr, addr + size);
 }
@@ -419,6 +424,9 @@ int pkvm_pgtable_stage2_wrprotect(struct kvm_pgtable *pgt, u64 addr, u64 size)
        struct pkvm_mapping *mapping;
        int ret = 0;
 
+       if (WARN_ON(kvm_vm_is_protected(kvm)))
+               return -EPERM;
+
        lockdep_assert_held(&kvm->mmu_lock);
        for_each_mapping_in_range_safe(pgt, addr, addr + size, mapping) {
                ret = kvm_call_hyp_nvhe(__pkvm_host_wrprotect_guest, handle, mapping->gfn,
@@ -450,6 +458,9 @@ bool pkvm_pgtable_stage2_test_clear_young(struct kvm_pgtable *pgt, u64 addr, u64
        struct pkvm_mapping *mapping;
        bool young = false;
 
+       if (WARN_ON(kvm_vm_is_protected(kvm)))
+               return false;
+
        lockdep_assert_held(&kvm->mmu_lock);
        for_each_mapping_in_range_safe(pgt, addr, addr + size, mapping)
                young |= kvm_call_hyp_nvhe(__pkvm_host_test_clear_young_guest, handle, mapping->gfn,
@@ -461,12 +472,18 @@ bool pkvm_pgtable_stage2_test_clear_young(struct kvm_pgtable *pgt, u64 addr, u64
 int pkvm_pgtable_stage2_relax_perms(struct kvm_pgtable *pgt, u64 addr, enum kvm_pgtable_prot prot,
                                    enum kvm_pgtable_walk_flags flags)
 {
+       if (WARN_ON(kvm_vm_is_protected(kvm_s2_mmu_to_kvm(pgt->mmu))))
+               return -EPERM;
+
        return kvm_call_hyp_nvhe(__pkvm_host_relax_perms_guest, addr >> PAGE_SHIFT, prot);
 }
 
 void pkvm_pgtable_stage2_mkyoung(struct kvm_pgtable *pgt, u64 addr,
                                 enum kvm_pgtable_walk_flags flags)
 {
+       if (WARN_ON(kvm_vm_is_protected(kvm_s2_mmu_to_kvm(pgt->mmu))))
+               return;
+
        WARN_ON(kvm_call_hyp_nvhe(__pkvm_host_mkyoung_guest, addr >> PAGE_SHIFT));
 }