diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 98ac302ac9a6..eba8c310b784 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -901,10 +901,7 @@ int kvm_set_ipa_limit(void); struct kvm *kvm_arch_alloc_vm(void); void kvm_arch_free_vm(struct kvm *kvm); -static inline bool kvm_vm_is_protected(struct kvm *kvm) -{ - return false; -} +#define kvm_vm_is_protected(kvm) ((kvm)->arch.pkvm.enabled) void kvm_init_protected_traps(struct kvm_vcpu *vcpu); diff --git a/arch/arm64/include/asm/kvm_pkvm.h b/arch/arm64/include/asm/kvm_pkvm.h index 2043518e2bde..b46ea822225b 100644 --- a/arch/arm64/include/asm/kvm_pkvm.h +++ b/arch/arm64/include/asm/kvm_pkvm.h @@ -17,6 +17,7 @@ #define HYP_MEMBLOCK_REGIONS 128 #define PVMFW_INVALID_LOAD_ADDR (-1) +int kvm_init_pvm(struct kvm *kvm, unsigned long type); int create_el2_shadow(struct kvm *kvm); /* diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 1af8c4a0e063..76af06182e45 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -156,10 +156,17 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) { int ret; + if (type & ~KVM_VM_TYPE_MASK) + return -EINVAL; + ret = kvm_share_hyp(kvm, kvm + 1); if (ret) return ret; + ret = kvm_init_pvm(kvm, type); + if (ret) + return ret; + ret = kvm_init_stage2_mmu(kvm, &kvm->arch.mmu, type); if (ret) return ret; diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index 24f18fcea4ba..e8d3c67c97b8 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -632,9 +632,6 @@ int kvm_init_stage2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu, unsigned long t 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; diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c index 67230b10fca7..dc60c8d60565 100644 --- a/arch/arm64/kvm/pkvm.c +++ b/arch/arm64/kvm/pkvm.c @@ -244,3 +244,18 @@ static int __init pkvm_firmware_rmem_clear(void) return 0; } device_initcall_sync(pkvm_firmware_rmem_clear); + +int kvm_init_pvm(struct kvm *kvm, unsigned long type) +{ + mutex_init(&kvm->arch.pkvm.shadow_lock); + kvm->arch.pkvm.pvmfw_load_addr = PVMFW_INVALID_LOAD_ADDR; + + if (!(type & KVM_VM_TYPE_ARM_PROTECTED)) + return 0; + + if (!is_protected_kvm_enabled()) + return -EINVAL; + + kvm->arch.pkvm.enabled = true; + return 0; +} diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index a067410ebea5..f7828c94c48c 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -863,6 +863,12 @@ struct kvm_ppc_resize_hpt { #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_MASK (KVM_VM_TYPE_ARM_IPA_SIZE_MASK | \ + KVM_VM_TYPE_ARM_PROTECTED) + /* * ioctls for /dev/kvm fds: */ @@ -1112,6 +1118,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_BINARY_STATS_FD 203 #define KVM_CAP_EXIT_ON_EMULATION_FAILURE 204 #define KVM_CAP_ARM_MTE 205 +#define KVM_CAP_ARM_PROTECTED_VM 0xffbadab1 #ifdef KVM_CAP_IRQ_ROUTING