]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: arm64: Decouple hyp VM creation state from its handle
authorFuad Tabba <tabba@google.com>
Tue, 9 Sep 2025 07:24:32 +0000 (08:24 +0100)
committerMarc Zyngier <maz@kernel.org>
Mon, 15 Sep 2025 09:46:55 +0000 (10:46 +0100)
Currently, the presence of a pKVM handle (pkvm.handle != 0) is used to
determine if the corresponding hypervisor (EL2) VM has been created and
initialized. This couples the handle's lifecycle with the VM's creation
state.

This coupling will become problematic with upcoming changes that will
allocate the pKVM handle earlier in the VM's life, before the VM is
instantiated at the hypervisor.

To prepare for this and make the state tracking explicit, decouple the
two concepts. Introduce a new boolean flag, 'pkvm.is_created', to track
whether the hypervisor-side VM has been created and initialized.

A new helper, pkvm_hyp_vm_is_created(), is added to check this flag. All
call sites that previously checked for the handle's existence are
converted to use the new, explicit check. The 'is_created' flag is set
to true upon successful creation in the hypervisor (EL2) and cleared
upon destruction.

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/include/asm/kvm_host.h
arch/arm64/include/asm/kvm_pkvm.h
arch/arm64/kvm/hyp/nvhe/pkvm.c
arch/arm64/kvm/pkvm.c

index a4289c2f13f53dbd7400de10234b4fc2981c1e93..bc57749e3fb90fb5d81f530c0485e9916bda01e6 100644 (file)
@@ -253,6 +253,7 @@ struct kvm_protected_vm {
        struct kvm_hyp_memcache teardown_mc;
        struct kvm_hyp_memcache stage2_teardown_mc;
        bool is_protected;
+       bool is_created;
 };
 
 struct kvm_mpidr_data {
index ea58282f59bb4fe8841064bfafffe9af3c17b667..08be89c95466eb98349a0bef06d2b17678f297df 100644 (file)
@@ -18,6 +18,7 @@
 
 int pkvm_init_host_vm(struct kvm *kvm);
 int pkvm_create_hyp_vm(struct kvm *kvm);
+bool pkvm_hyp_vm_is_created(struct kvm *kvm);
 void pkvm_destroy_hyp_vm(struct kvm *kvm);
 int pkvm_create_hyp_vcpu(struct kvm_vcpu *vcpu);
 
index abe173406c88c13075e18b186c37e8dfc216fe20..969f6b293234df9a2e81e459a1124c7edd36ab53 100644 (file)
@@ -407,6 +407,7 @@ static void init_pkvm_hyp_vm(struct kvm *host_kvm, struct pkvm_hyp_vm *hyp_vm,
        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);
 }
index 7aaeb66e3f394f96ddf779e053ad4456f2ad07ae..45d699bba96a1d07e4e4cb7131ddf9c521f580c7 100644 (file)
@@ -87,12 +87,13 @@ void __init kvm_hyp_reserve(void)
 
 static void __pkvm_destroy_hyp_vm(struct kvm *kvm)
 {
-       if (kvm->arch.pkvm.handle) {
+       if (pkvm_hyp_vm_is_created(kvm)) {
                WARN_ON(kvm_call_hyp_nvhe(__pkvm_teardown_vm,
                                          kvm->arch.pkvm.handle));
        }
 
        kvm->arch.pkvm.handle = 0;
+       kvm->arch.pkvm.is_created = false;
        free_hyp_memcache(&kvm->arch.pkvm.teardown_mc);
        free_hyp_memcache(&kvm->arch.pkvm.stage2_teardown_mc);
 }
@@ -165,6 +166,7 @@ static int __pkvm_create_hyp_vm(struct kvm *kvm)
                goto free_vm;
 
        kvm->arch.pkvm.handle = ret;
+       kvm->arch.pkvm.is_created = true;
        kvm->arch.pkvm.stage2_teardown_mc.flags |= HYP_MEMCACHE_ACCOUNT_STAGE2;
        kvm_account_pgtable_pages(pgd, pgd_sz / PAGE_SIZE);
 
@@ -176,12 +178,17 @@ free_pgd:
        return ret;
 }
 
+bool pkvm_hyp_vm_is_created(struct kvm *kvm)
+{
+       return READ_ONCE(kvm->arch.pkvm.is_created);
+}
+
 int pkvm_create_hyp_vm(struct kvm *kvm)
 {
        int ret = 0;
 
        mutex_lock(&kvm->arch.config_lock);
-       if (!kvm->arch.pkvm.handle)
+       if (!pkvm_hyp_vm_is_created(kvm))
                ret = __pkvm_create_hyp_vm(kvm);
        mutex_unlock(&kvm->arch.config_lock);