Check that a protected VM enabled only supported features when created. Signed-off-by: Fuad Tabba <tabba@xxxxxxxxxx> --- arch/arm64/kvm/pkvm.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c index cf624350fb27..15a92f3fdd44 100644 --- a/arch/arm64/kvm/pkvm.c +++ b/arch/arm64/kvm/pkvm.c @@ -88,10 +88,53 @@ static void pkvm_teardown_firmware_slot(struct kvm *kvm) kvm->arch.pkvm.firmware_slot = NULL; } +/* + * Check that only supported features are enabled for the protected VM's vcpus. + * + * Return 0 if all features enabled for all vcpus are supported, or -EINVAL if + * one or more vcpus has one or more unsupported features. + */ +static int pkvm_check_features(struct kvm *kvm) +{ + int i; + const struct kvm_vcpu *vcpu; + DECLARE_BITMAP(allowed_features, KVM_VCPU_MAX_FEATURES); + + bitmap_zero(allowed_features, KVM_VCPU_MAX_FEATURES); + + /* + * Support for: + * - CPU starting in poweroff state + * - PSCI v0.2 + * - Pointer authentication: address or generic + * + * No support for remaining features, i.e.,: + * - AArch32 state + * - Performance Monitoring + * - Scalable Vectors + */ + set_bit(KVM_ARM_VCPU_POWER_OFF, allowed_features); + set_bit(KVM_ARM_VCPU_PSCI_0_2, allowed_features); + set_bit(KVM_ARM_VCPU_PTRAUTH_ADDRESS, allowed_features); + set_bit(KVM_ARM_VCPU_PTRAUTH_GENERIC, allowed_features); + + kvm_for_each_vcpu(i, vcpu, kvm) { + if (!bitmap_subset(vcpu->arch.features, allowed_features, + KVM_VCPU_MAX_FEATURES)) + return -EINVAL; + } + + return 0; +} + static int pkvm_enable(struct kvm *kvm, u64 slotid) { int ret; + ret = pkvm_check_features(kvm); + if (ret) + return ret; + ret = pkvm_init_firmware_slot(kvm, slotid); if (ret) return ret; -- 2.32.0.272.g935e593368-goog