From: Quentin Perret <qper...@google.com>

We currently fixup the hypervisor stage-1 refcount only for specific
portions of the hyp stage-1 VA space. In order to allow unmapping pages
outside of these ranges, let's fixup the refcount for the entire hyp VA
space.

Signed-off-by: Quentin Perret <qper...@google.com>
---
 arch/arm64/kvm/hyp/nvhe/setup.c | 62 +++++++++++++++++++++++----------
 1 file changed, 43 insertions(+), 19 deletions(-)

diff --git a/arch/arm64/kvm/hyp/nvhe/setup.c b/arch/arm64/kvm/hyp/nvhe/setup.c
index e9e146e50254..b306da2b5dae 100644
--- a/arch/arm64/kvm/hyp/nvhe/setup.c
+++ b/arch/arm64/kvm/hyp/nvhe/setup.c
@@ -167,12 +167,11 @@ static void hpool_put_page(void *addr)
        hyp_put_page(&hpool, addr);
 }
 
-static int finalize_host_mappings_walker(u64 addr, u64 end, u32 level,
-                                        kvm_pte_t *ptep,
-                                        enum kvm_pgtable_walk_flags flag,
-                                        void * const arg)
+static int fix_host_ownership_walker(u64 addr, u64 end, u32 level,
+                                    kvm_pte_t *ptep,
+                                    enum kvm_pgtable_walk_flags flag,
+                                    void * const arg)
 {
-       struct kvm_pgtable_mm_ops *mm_ops = arg;
        enum kvm_pgtable_prot prot;
        enum pkvm_page_state state;
        kvm_pte_t pte = *ptep;
@@ -181,15 +180,6 @@ static int finalize_host_mappings_walker(u64 addr, u64 
end, u32 level,
        if (!kvm_pte_valid(pte))
                return 0;
 
-       /*
-        * Fix-up the refcount for the page-table pages as the early allocator
-        * was unable to access the hyp_vmemmap and so the buddy allocator has
-        * initialised the refcount to '1'.
-        */
-       mm_ops->get_page(ptep);
-       if (flag != KVM_PGTABLE_WALK_LEAF)
-               return 0;
-
        if (level != (KVM_PGTABLE_MAX_LEVELS - 1))
                return -EINVAL;
 
@@ -218,12 +208,30 @@ static int finalize_host_mappings_walker(u64 addr, u64 
end, u32 level,
        return host_stage2_idmap_locked(phys, PAGE_SIZE, prot);
 }
 
-static int finalize_host_mappings(void)
+static int fix_hyp_pgtable_refcnt_walker(u64 addr, u64 end, u32 level,
+                                        kvm_pte_t *ptep,
+                                        enum kvm_pgtable_walk_flags flag,
+                                        void * const arg)
+{
+       struct kvm_pgtable_mm_ops *mm_ops = arg;
+       kvm_pte_t pte = *ptep;
+
+       /*
+        * Fix-up the refcount for the page-table pages as the early allocator
+        * was unable to access the hyp_vmemmap and so the buddy allocator has
+        * initialised the refcount to '1'.
+        */
+       if (kvm_pte_valid(pte))
+               mm_ops->get_page(ptep);
+
+       return 0;
+}
+
+static int fix_host_ownership(void)
 {
        struct kvm_pgtable_walker walker = {
-               .cb     = finalize_host_mappings_walker,
-               .flags  = KVM_PGTABLE_WALK_LEAF | KVM_PGTABLE_WALK_TABLE_POST,
-               .arg    = pkvm_pgtable.mm_ops,
+               .cb     = fix_host_ownership_walker,
+               .flags  = KVM_PGTABLE_WALK_LEAF,
        };
        int i, ret;
 
@@ -239,6 +247,18 @@ static int finalize_host_mappings(void)
        return 0;
 }
 
+static int fix_hyp_pgtable_refcnt(void)
+{
+       struct kvm_pgtable_walker walker = {
+               .cb     = fix_hyp_pgtable_refcnt_walker,
+               .flags  = KVM_PGTABLE_WALK_LEAF | KVM_PGTABLE_WALK_TABLE_POST,
+               .arg    = pkvm_pgtable.mm_ops,
+       };
+
+       return kvm_pgtable_walk(&pkvm_pgtable, 0, BIT(pkvm_pgtable.ia_bits),
+                               &walker);
+}
+
 void __noreturn __pkvm_init_finalise(void)
 {
        struct kvm_host_data *host_data = this_cpu_ptr(&kvm_host_data);
@@ -268,7 +288,11 @@ void __noreturn __pkvm_init_finalise(void)
        };
        pkvm_pgtable.mm_ops = &pkvm_pgtable_mm_ops;
 
-       ret = finalize_host_mappings();
+       ret = fix_host_ownership();
+       if (ret)
+               goto out;
+
+       ret = fix_hyp_pgtable_refcnt();
        if (ret)
                goto out;
 
-- 
2.36.1.124.g0e6072fb45-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

Reply via email to