@@ -354,13 +354,13 @@ static inline void kvm_vcpu_put_sysregs(struct kvm_vcpu *vcpu) {}
struct kvm *kvm_arch_alloc_vm(void);
void kvm_arch_free_vm(struct kvm *kvm);
-static inline int kvm_arm_setup_stage2(struct kvm *kvm, unsigned long type)
+static inline int kvm_arm_setup_stage2(struct kvm *kvm, unsigned long *type)
{
/*
* On 32bit ARM, VMs get a static 40bit IPA stage2 setup,
- * so any non-zero value used as type is illegal.
+ * so any non-zero value used in the IPA size field is illegal.
*/
- if (type)
+ if (*type & KVM_VM_TYPE_ARM_IPA_SIZE_MASK)
return -EINVAL;
return 0;
}
@@ -534,6 +534,6 @@ void kvm_set_ipa_limit(void);
struct kvm *kvm_arch_alloc_vm(void);
void kvm_arch_free_vm(struct kvm *kvm);
-int kvm_arm_setup_stage2(struct kvm *kvm, unsigned long type);
+int kvm_arm_setup_stage2(struct kvm *kvm, unsigned long *type);
#endif /* __ARM64_KVM_HOST_H__ */
@@ -188,16 +188,14 @@ void kvm_set_ipa_limit(void)
* all CPUs, as it is safe to run with or without the feature and
* the bit is RES0 on CPUs that don't support it.
*/
-int kvm_arm_setup_stage2(struct kvm *kvm, unsigned long type)
+int kvm_arm_setup_stage2(struct kvm *kvm, unsigned long *type)
{
u64 vtcr = VTCR_EL2_FLAGS;
u32 parange, phys_shift;
u8 lvls;
- if (type & ~KVM_VM_TYPE_ARM_IPA_SIZE_MASK)
- return -EINVAL;
-
- phys_shift = KVM_VM_TYPE_ARM_IPA_SIZE(type);
+ phys_shift = KVM_VM_TYPE_ARM_IPA_SIZE(*type);
+ *type &= ~KVM_VM_TYPE_ARM_IPA_SIZE_MASK;
if (phys_shift) {
if (phys_shift > kvm_ipa_limit ||
phys_shift < 32)
@@ -120,10 +120,14 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
{
int ret, cpu;
- ret = kvm_arm_setup_stage2(kvm, type);
+ ret = kvm_arm_setup_stage2(kvm, &type);
if (ret)
return ret;
+ /* Fail if there are type bits that nobody understood: */
+ if (type)
+ return -EINVAL;
+
kvm->arch.last_vcpu_ran = alloc_percpu(typeof(*kvm->arch.last_vcpu_ran));
if (!kvm->arch.last_vcpu_ran)
return -ENOMEM;
Currently, the detection of invalid bits in the KVM_CREATE_VM type argument is done in the kvm_arm_setup_stage2() backend. In order to make it easier to add type flags with independent meanings, this patch moves the logic for rejecting invalid bits to kvm_arch_init_vm(). Backend functions are now responsible for clearing bits they know about from type, so that if any remain after all such functions are called, we know they are invalid. No functional change. Signed-off-by: Dave Martin <Dave.Martin@arm.com> --- Changes since RFC v2: * New patch. **Discussion required** This change facilitates the addition of special-purpose flags in the KVM_CREATE_VM type argument, which may be used to control API features at VM granularity. This is currently one of two main options I can see for controlling the sequencing of the KVM_ARM_VCPU_INIT ioctl, since KVM_CREATE_VCPU has no spare argument bits and there is no obvious place to hook in. (The other, perhaps better option is to alter KVM_ARM_VCPU_INIT's behaviour with a feature flag in struct kvm_vcpu_init.) If API behaviour does not need to diverge before KVM_VCPU_INIT, then we can get away without this patch. The API presented in this series _does_ require divergence however: it requires KVM_ARM_SVE_CONFIG_SET before KVM_VCPU_INIT. It remains up for discussion whether this change is appropriate/ needed. --- arch/arm/include/asm/kvm_host.h | 6 +++--- arch/arm64/include/asm/kvm_host.h | 2 +- arch/arm64/kvm/reset.c | 8 +++----- virt/kvm/arm/arm.c | 6 +++++- 4 files changed, 12 insertions(+), 10 deletions(-)