]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
KVM: arm64: Allow userspace to create protected VMs when pKVM is enabled
authorWill Deacon <will@kernel.org>
Mon, 30 Mar 2026 14:48:32 +0000 (15:48 +0100)
committerMarc Zyngier <maz@kernel.org>
Mon, 30 Mar 2026 15:58:09 +0000 (16:58 +0100)
Introduce a new VM type for KVM/arm64 to allow userspace to request the
creation of a "protected VM" when the host has booted with pKVM enabled.

For now, this feature results in a taint on first use as many aspects of
a protected VM are not yet protected!

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-32-will@kernel.org
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/include/asm/kvm_pkvm.h
arch/arm64/kvm/arm.c
arch/arm64/kvm/mmu.c
arch/arm64/kvm/pkvm.c
include/uapi/linux/kvm.h

index 7041e398fb4c3145d91b11985d99ef3034a640e6..2954b311128c783dc42d58b9a0da49562f484ef9 100644 (file)
@@ -17,7 +17,7 @@
 
 #define HYP_MEMBLOCK_REGIONS 128
 
-int pkvm_init_host_vm(struct kvm *kvm);
+int pkvm_init_host_vm(struct kvm *kvm, unsigned long type);
 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);
index 3589fc08266cfaadfb101fb120a303a1481677dd..c2b666a468937c11766dd5b302963281c6d69d82 100644 (file)
@@ -203,6 +203,9 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 {
        int ret;
 
+       if (type & ~KVM_VM_TYPE_ARM_MASK)
+               return -EINVAL;
+
        mutex_init(&kvm->arch.config_lock);
 
 #ifdef CONFIG_LOCKDEP
@@ -234,9 +237,12 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
                 * If any failures occur after this is successful, make sure to
                 * call __pkvm_unreserve_vm to unreserve the VM in hyp.
                 */
-               ret = pkvm_init_host_vm(kvm);
+               ret = pkvm_init_host_vm(kvm, type);
                if (ret)
                        goto err_uninit_mmu;
+       } else if (type & KVM_VM_TYPE_ARM_PROTECTED) {
+               ret = -EINVAL;
+               goto err_uninit_mmu;
        }
 
        kvm_vgic_early_init(kvm);
index 6a4151e3e4a336d2468e42607a18ea6bd61979e8..45358ae8a300827955f13bc17124bc9c42245ccb 100644 (file)
@@ -881,9 +881,6 @@ static int kvm_init_ipa_range(struct kvm_s2_mmu *mmu, unsigned long type)
        u64 mmfr0, mmfr1;
        u32 phys_shift;
 
-       if (type & ~KVM_VM_TYPE_ARM_IPA_SIZE_MASK)
-               return -EINVAL;
-
        phys_shift = KVM_VM_TYPE_ARM_IPA_SIZE(type);
        if (is_protected_kvm_enabled()) {
                phys_shift = kvm_ipa_limit;
index 7f35df29e98489ad39d9c5e6c421d01b3a5db696..053e4f733e4bed6e37ef21facbd3076612fcada3 100644 (file)
@@ -225,9 +225,10 @@ void pkvm_destroy_hyp_vm(struct kvm *kvm)
        mutex_unlock(&kvm->arch.config_lock);
 }
 
-int pkvm_init_host_vm(struct kvm *kvm)
+int pkvm_init_host_vm(struct kvm *kvm, unsigned long type)
 {
        int ret;
+       bool protected = type & KVM_VM_TYPE_ARM_PROTECTED;
 
        if (pkvm_hyp_vm_is_created(kvm))
                return -EINVAL;
@@ -242,6 +243,11 @@ int pkvm_init_host_vm(struct kvm *kvm)
                return ret;
 
        kvm->arch.pkvm.handle = ret;
+       kvm->arch.pkvm.is_protected = protected;
+       if (protected) {
+               pr_warn_once("kvm: protected VMs are experimental and for development only, tainting kernel\n");
+               add_taint(TAINT_USER, LOCKDEP_STILL_OK);
+       }
 
        return 0;
 }
index 80364d4dbebb0ce9d13f5dea410c36341d157b3d..073b2bcaf560baaea8ef806f1da43902569f075d 100644 (file)
@@ -703,6 +703,11 @@ struct kvm_enable_cap {
 #define KVM_VM_TYPE_ARM_IPA_SIZE_MASK  0xffULL
 #define KVM_VM_TYPE_ARM_IPA_SIZE(x)            \
        ((x) & KVM_VM_TYPE_ARM_IPA_SIZE_MASK)
+
+#define KVM_VM_TYPE_ARM_PROTECTED      (1UL << 31)
+#define KVM_VM_TYPE_ARM_MASK           (KVM_VM_TYPE_ARM_IPA_SIZE_MASK | \
+                                        KVM_VM_TYPE_ARM_PROTECTED)
+
 /*
  * ioctls for /dev/kvm fds:
  */