@@ -360,7 +360,7 @@ static int set_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
if (!vcpu_has_sve(vcpu))
return -ENOENT;
- if (kvm_arm_vcpu_sve_finalized(vcpu))
+ if (kvm_arm_vcpu_sve_finalized(vcpu) || kvm_realm_is_created(vcpu->kvm))
return -EPERM; /* too late! */
if (WARN_ON(vcpu->arch.sve_state))
@@ -822,6 +822,7 @@ static bool validate_realm_set_reg(struct kvm_vcpu *vcpu,
switch (reg->id) {
case KVM_REG_ARM_PMCR_EL0:
case KVM_REG_ARM_ID_AA64DFR0_EL1:
+ case KVM_REG_ARM64_SVE_VLS:
return true;
}
}
@@ -345,6 +345,44 @@ static void realm_unmap_shared_range(struct kvm *kvm,
}
}
+static int realm_init_sve_param(struct kvm *kvm, struct realm_params *params)
+{
+ int ret = 0;
+ unsigned long i;
+ struct kvm_vcpu *vcpu;
+ int vl, last_vl = -1;
+
+ /*
+ * Get the preferred SVE configuration, set by userspace with the
+ * KVM_ARM_VCPU_SVE feature and KVM_REG_ARM64_SVE_VLS pseudo-register.
+ */
+ kvm_for_each_vcpu(i, vcpu, kvm) {
+ mutex_lock(&vcpu->mutex);
+ if (vcpu_has_sve(vcpu)) {
+ if (!kvm_arm_vcpu_sve_finalized(vcpu))
+ ret = -EINVAL;
+ vl = vcpu->arch.sve_max_vl;
+ } else {
+ vl = 0;
+ }
+ mutex_unlock(&vcpu->mutex);
+ if (ret)
+ return ret;
+
+ /* We need all vCPUs to have the same SVE config */
+ if (last_vl >= 0 && last_vl != vl)
+ return -EINVAL;
+
+ last_vl = vl;
+ }
+
+ if (last_vl > 0) {
+ params->sve_vl = sve_vq_from_vl(last_vl) - 1;
+ params->flags |= RMI_REALM_PARAM_FLAG_SVE;
+ }
+ return 0;
+}
+
/* Calculate the number of s2 root rtts needed */
static int realm_num_root_rtts(struct realm *realm)
{
@@ -411,6 +449,10 @@ static int realm_create_rd(struct kvm *kvm)
params->flags |= RMI_REALM_PARAM_FLAG_PMU;
}
+ r = realm_init_sve_param(kvm, params);
+ if (r)
+ goto out_undelegate_tables;
+
params_phys = virt_to_phys(params);
if (rmi_realm_create(rd_phys, params_phys)) {