]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: arm64: Consolidate pKVM hypervisor VM initialization logic
authorFuad Tabba <tabba@google.com>
Tue, 9 Sep 2025 07:24:34 +0000 (08:24 +0100)
committerMarc Zyngier <maz@kernel.org>
Mon, 15 Sep 2025 09:46:55 +0000 (10:46 +0100)
The insert_vm_table_entry() function was performing tasks beyond its
primary responsibility. In addition to inserting a VM pointer into the
vm_table, it was also initializing several fields within 'struct
pkvm_hyp_vm', such as the VMID and stage-2 MMU pointers. This mixing of
concerns made the code harder to follow.

As another preparatory step towards allowing a VM table entry to be
reserved before the VM is fully created, this logic must be cleaned up.
By separating table insertion from state initialization, we can control
the timing of the initialization step more precisely in subsequent
patches.

Refactor the code to consolidate all initialization logic into
init_pkvm_hyp_vm():

- Move the initialization of the handle, VMID, and MMU fields from
  insert_vm_table_entry() to init_pkvm_hyp_vm().

- Simplify insert_vm_table_entry() to perform only one action: placing
  the provided pkvm_hyp_vm pointer into the vm_table.

- Update the calling sequence in __pkvm_init_vm() to first allocate an
  entry in the VM table, initialize the VM, and then insert the VM into
  the VM table. This is all protected by the vm_table_lock for now.
  Subsequent patches will adjust the sequence and not hold the
  vm_table_lock while initializing the VM at the hypervisor
  (init_pkvm_hyp_vm()).

Signed-off-by: Fuad Tabba <tabba@google.com>
Tested-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/kvm/hyp/nvhe/pkvm.c

index 64b760d30d0583a591e23bc7a6ae608be5c74812..a9abbeb530f04ee6f4a41bda6ac348fa1e4e5ad2 100644 (file)
@@ -410,15 +410,26 @@ static void unpin_host_vcpus(struct pkvm_hyp_vcpu *hyp_vcpus[],
 }
 
 static void init_pkvm_hyp_vm(struct kvm *host_kvm, struct pkvm_hyp_vm *hyp_vm,
-                            unsigned int nr_vcpus)
+                            unsigned int nr_vcpus, pkvm_handle_t handle)
 {
+       struct kvm_s2_mmu *mmu = &hyp_vm->kvm.arch.mmu;
+       int idx = vm_handle_to_idx(handle);
+
+       hyp_vm->kvm.arch.pkvm.handle = handle;
+
        hyp_vm->host_kvm = host_kvm;
        hyp_vm->kvm.created_vcpus = nr_vcpus;
-       hyp_vm->kvm.arch.mmu.vtcr = host_mmu.arch.mmu.vtcr;
        hyp_vm->kvm.arch.pkvm.is_protected = READ_ONCE(host_kvm->arch.pkvm.is_protected);
        hyp_vm->kvm.arch.pkvm.is_created = true;
        hyp_vm->kvm.arch.flags = 0;
        pkvm_init_features_from_host(hyp_vm, host_kvm);
+
+       /* VMID 0 is reserved for the host */
+       atomic64_set(&mmu->vmid.id, idx + 1);
+
+       mmu->vtcr = host_mmu.arch.mmu.vtcr;
+       mmu->arch = &hyp_vm->kvm.arch;
+       mmu->pgt = &hyp_vm->pgt;
 }
 
 static int pkvm_vcpu_init_sve(struct pkvm_hyp_vcpu *hyp_vcpu, struct kvm_vcpu *host_vcpu)
@@ -532,29 +543,19 @@ static int allocate_vm_table_entry(void)
 }
 
 /*
- * Insert a pointer to the new VM into the VM table.
+ * Insert a pointer to the initialized VM into the VM table.
  *
  * Return 0 on success, or negative error code on failure.
  */
-static int insert_vm_table_entry(struct kvm *host_kvm,
-                                struct pkvm_hyp_vm *hyp_vm,
-                                pkvm_handle_t handle)
+static int insert_vm_table_entry(pkvm_handle_t handle,
+                                struct pkvm_hyp_vm *hyp_vm)
 {
-       struct kvm_s2_mmu *mmu = &hyp_vm->kvm.arch.mmu;
        unsigned int idx;
 
        hyp_assert_lock_held(&vm_table_lock);
-
        idx = vm_handle_to_idx(handle);
-       hyp_vm->kvm.arch.pkvm.handle = idx_to_vm_handle(idx);
-
-       /* VMID 0 is reserved for the host */
-       atomic64_set(&mmu->vmid.id, idx + 1);
-
-       mmu->arch = &hyp_vm->kvm.arch;
-       mmu->pgt = &hyp_vm->pgt;
-
        vm_table[idx] = hyp_vm;
+
        return 0;
 }
 
@@ -668,8 +669,6 @@ int __pkvm_init_vm(struct kvm *host_kvm, unsigned long vm_hva,
        if (!pgd)
                goto err_remove_mappings;
 
-       init_pkvm_hyp_vm(host_kvm, hyp_vm, nr_vcpus);
-
        hyp_spin_lock(&vm_table_lock);
        ret = allocate_vm_table_entry();
        if (ret < 0)
@@ -677,19 +676,21 @@ int __pkvm_init_vm(struct kvm *host_kvm, unsigned long vm_hva,
 
        handle = idx_to_vm_handle(ret);
 
-       ret = insert_vm_table_entry(host_kvm, hyp_vm, handle);
-       if (ret)
-               goto err_unlock;
+       init_pkvm_hyp_vm(host_kvm, hyp_vm, nr_vcpus, handle);
 
        ret = kvm_guest_prepare_stage2(hyp_vm, pgd);
+       if (ret)
+               goto err_remove_vm_table_entry;
+
+       ret = insert_vm_table_entry(handle, hyp_vm);
        if (ret)
                goto err_remove_vm_table_entry;
        hyp_spin_unlock(&vm_table_lock);
 
-       return hyp_vm->kvm.arch.pkvm.handle;
+       return handle;
 
 err_remove_vm_table_entry:
-       remove_vm_table_entry(hyp_vm->kvm.arch.pkvm.handle);
+       remove_vm_table_entry(handle);
 err_unlock:
        hyp_spin_unlock(&vm_table_lock);
 err_remove_mappings: