]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
KVM: arm64: Register 'selftest_vm' in the VM table
authorWill Deacon <will@kernel.org>
Mon, 30 Mar 2026 14:48:35 +0000 (15:48 +0100)
committerMarc Zyngier <maz@kernel.org>
Mon, 30 Mar 2026 15:58:09 +0000 (16:58 +0100)
In preparation for extending the pKVM page ownership selftests to cover
forceful reclaim of donated pages, rework the creation of the
'selftest_vm' so that it is registered in the VM table while the tests
are running.

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-35-will@kernel.org
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
arch/arm64/kvm/hyp/nvhe/mem_protect.c
arch/arm64/kvm/hyp/nvhe/pkvm.c

index 99d8398afe20b8d290bbc619e07b375baf24d472..5031879ccb87badd306ea5fe9ef5f1e597c2ece4 100644 (file)
@@ -76,6 +76,8 @@ static __always_inline void __load_host_stage2(void)
 
 #ifdef CONFIG_NVHE_EL2_DEBUG
 void pkvm_ownership_selftest(void *base);
+struct pkvm_hyp_vcpu *init_selftest_vm(void *virt);
+void teardown_selftest_vm(void);
 #else
 static inline void pkvm_ownership_selftest(void *base) { }
 #endif
index 13d2cb2f5fab0367ae71bee97dbf52a1b3a76bc8..d8f8ebe59129c95dc7f0ff4cd0b7b6659e005eee 100644 (file)
@@ -1648,53 +1648,18 @@ struct pkvm_expected_state {
 
 static struct pkvm_expected_state selftest_state;
 static struct hyp_page *selftest_page;
-
-static struct pkvm_hyp_vm selftest_vm = {
-       .kvm = {
-               .arch = {
-                       .mmu = {
-                               .arch = &selftest_vm.kvm.arch,
-                               .pgt = &selftest_vm.pgt,
-                       },
-               },
-       },
-};
-
-static struct pkvm_hyp_vcpu selftest_vcpu = {
-       .vcpu = {
-               .arch = {
-                       .hw_mmu = &selftest_vm.kvm.arch.mmu,
-               },
-               .kvm = &selftest_vm.kvm,
-       },
-};
-
-static void init_selftest_vm(void *virt)
-{
-       struct hyp_page *p = hyp_virt_to_page(virt);
-       int i;
-
-       selftest_vm.kvm.arch.mmu.vtcr = host_mmu.arch.mmu.vtcr;
-       WARN_ON(kvm_guest_prepare_stage2(&selftest_vm, virt));
-
-       for (i = 0; i < pkvm_selftest_pages(); i++) {
-               if (p[i].refcount)
-                       continue;
-               p[i].refcount = 1;
-               hyp_put_page(&selftest_vm.pool, hyp_page_to_virt(&p[i]));
-       }
-}
+static struct pkvm_hyp_vcpu *selftest_vcpu;
 
 static u64 selftest_ipa(void)
 {
-       return BIT(selftest_vm.pgt.ia_bits - 1);
+       return BIT(selftest_vcpu->vcpu.arch.hw_mmu->pgt->ia_bits - 1);
 }
 
 static void assert_page_state(void)
 {
        void *virt = hyp_page_to_virt(selftest_page);
        u64 size = PAGE_SIZE << selftest_page->order;
-       struct pkvm_hyp_vcpu *vcpu = &selftest_vcpu;
+       struct pkvm_hyp_vcpu *vcpu = selftest_vcpu;
        u64 phys = hyp_virt_to_phys(virt);
        u64 ipa[2] = { selftest_ipa(), selftest_ipa() + PAGE_SIZE };
        struct pkvm_hyp_vm *vm;
@@ -1709,10 +1674,10 @@ static void assert_page_state(void)
        WARN_ON(__hyp_check_page_state_range(phys, size, selftest_state.hyp));
        hyp_unlock_component();
 
-       guest_lock_component(&selftest_vm);
+       guest_lock_component(vm);
        WARN_ON(__guest_check_page_state_range(vm, ipa[0], size, selftest_state.guest[0]));
        WARN_ON(__guest_check_page_state_range(vm, ipa[1], size, selftest_state.guest[1]));
-       guest_unlock_component(&selftest_vm);
+       guest_unlock_component(vm);
 }
 
 #define assert_transition_res(res, fn, ...)            \
@@ -1725,14 +1690,15 @@ void pkvm_ownership_selftest(void *base)
 {
        enum kvm_pgtable_prot prot = KVM_PGTABLE_PROT_RWX;
        void *virt = hyp_alloc_pages(&host_s2_pool, 0);
-       struct pkvm_hyp_vcpu *vcpu = &selftest_vcpu;
-       struct pkvm_hyp_vm *vm = &selftest_vm;
+       struct pkvm_hyp_vcpu *vcpu;
        u64 phys, size, pfn, gfn;
+       struct pkvm_hyp_vm *vm;
 
        WARN_ON(!virt);
        selftest_page = hyp_virt_to_page(virt);
        selftest_page->refcount = 0;
-       init_selftest_vm(base);
+       selftest_vcpu = vcpu = init_selftest_vm(base);
+       vm = pkvm_hyp_vcpu_to_hyp_vm(vcpu);
 
        size = PAGE_SIZE << selftest_page->order;
        phys = hyp_virt_to_phys(virt);
@@ -1856,6 +1822,7 @@ void pkvm_ownership_selftest(void *base)
        selftest_state.hyp = PKVM_PAGE_OWNED;
        assert_transition_res(0,        __pkvm_host_donate_hyp, pfn, 1);
 
+       teardown_selftest_vm();
        selftest_page->refcount = 1;
        hyp_put_page(&host_s2_pool, virt);
 }
index 6f3b94a37fe39d5097fd7c8c12540a8ff68df40c..8b906217c4c3532cdeec53a2d13e428339ebb505 100644 (file)
@@ -733,6 +733,55 @@ void __pkvm_unreserve_vm(pkvm_handle_t handle)
        hyp_spin_unlock(&vm_table_lock);
 }
 
+#ifdef CONFIG_NVHE_EL2_DEBUG
+static struct pkvm_hyp_vm selftest_vm = {
+       .kvm = {
+               .arch = {
+                       .mmu = {
+                               .arch = &selftest_vm.kvm.arch,
+                               .pgt = &selftest_vm.pgt,
+                       },
+               },
+       },
+};
+
+static struct pkvm_hyp_vcpu selftest_vcpu = {
+       .vcpu = {
+               .arch = {
+                       .hw_mmu = &selftest_vm.kvm.arch.mmu,
+               },
+               .kvm = &selftest_vm.kvm,
+       },
+};
+
+struct pkvm_hyp_vcpu *init_selftest_vm(void *virt)
+{
+       struct hyp_page *p = hyp_virt_to_page(virt);
+       int i;
+
+       selftest_vm.kvm.arch.mmu.vtcr = host_mmu.arch.mmu.vtcr;
+       WARN_ON(kvm_guest_prepare_stage2(&selftest_vm, virt));
+
+       for (i = 0; i < pkvm_selftest_pages(); i++) {
+               if (p[i].refcount)
+                       continue;
+               p[i].refcount = 1;
+               hyp_put_page(&selftest_vm.pool, hyp_page_to_virt(&p[i]));
+       }
+
+       selftest_vm.kvm.arch.pkvm.handle = __pkvm_reserve_vm();
+       insert_vm_table_entry(selftest_vm.kvm.arch.pkvm.handle, &selftest_vm);
+       return &selftest_vcpu;
+}
+
+void teardown_selftest_vm(void)
+{
+       hyp_spin_lock(&vm_table_lock);
+       remove_vm_table_entry(selftest_vm.kvm.arch.pkvm.handle);
+       hyp_spin_unlock(&vm_table_lock);
+}
+#endif /* CONFIG_NVHE_EL2_DEBUG */
+
 /*
  * Initialize the hypervisor copy of the VM state using host-donated memory.
  *