Message ID | 20241212155610.76522-39-steven.price@arm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | arm64: Support for Arm CCA in KVM | expand |
On 12/13/24 1:56 AM, Steven Price wrote: > From: Jean-Philippe Brucker <jean-philippe@linaro.org> > > Obtain the max vector length configured by userspace on the vCPUs, and > write it into the Realm parameters. By default the vCPU is configured > with the max vector length reported by RMM, and userspace can reduce it > with a write to KVM_REG_ARM64_SVE_VLS. > > Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> > Signed-off-by: Steven Price <steven.price@arm.com> > --- > arch/arm64/kvm/guest.c | 3 ++- > arch/arm64/kvm/rme.c | 42 ++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 44 insertions(+), 1 deletion(-) > > diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c > index 429c8f10b76a..5562029368c5 100644 > --- a/arch/arm64/kvm/guest.c > +++ b/arch/arm64/kvm/guest.c > @@ -363,7 +363,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)) > @@ -825,6 +825,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; > } > } > diff --git a/arch/arm64/kvm/rme.c b/arch/arm64/kvm/rme.c > index 39dbc19e4a42..3116ecee37a8 100644 > --- a/arch/arm64/kvm/rme.c > +++ b/arch/arm64/kvm/rme.c > @@ -297,6 +297,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 max_vl, realm_max_vl = -1; > + I would suggest to rename 'max_vl' and 'realm_max_vl' to 'vl' and 'last_vl' since we're not looking for the maximal VLs. Instead, we're making sure the VLs on all vCPUs are equal. > + /* > + * 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; > + max_vl = vcpu->arch.sve_max_vl; > + } else { > + max_vl = 0; > + } > + mutex_unlock(&vcpu->mutex); > + if (ret) > + return ret; > + > + /* We need all vCPUs to have the same SVE config */ > + if (realm_max_vl >= 0 && realm_max_vl != max_vl) > + return -EINVAL; > + > + realm_max_vl = max_vl; > + } > + > + if (realm_max_vl > 0) { > + params->sve_vl = sve_vq_from_vl(realm_max_vl) - 1; > + params->flags |= RMI_REALM_PARAM_FLAG_SVE; > + } > + return 0; > +} > + > static int realm_create_rd(struct kvm *kvm) > { > struct realm *realm = &kvm->arch.realm; > @@ -344,6 +382,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)) { Thanks, Gavin
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 429c8f10b76a..5562029368c5 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -363,7 +363,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)) @@ -825,6 +825,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; } } diff --git a/arch/arm64/kvm/rme.c b/arch/arm64/kvm/rme.c index 39dbc19e4a42..3116ecee37a8 100644 --- a/arch/arm64/kvm/rme.c +++ b/arch/arm64/kvm/rme.c @@ -297,6 +297,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 max_vl, realm_max_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; + max_vl = vcpu->arch.sve_max_vl; + } else { + max_vl = 0; + } + mutex_unlock(&vcpu->mutex); + if (ret) + return ret; + + /* We need all vCPUs to have the same SVE config */ + if (realm_max_vl >= 0 && realm_max_vl != max_vl) + return -EINVAL; + + realm_max_vl = max_vl; + } + + if (realm_max_vl > 0) { + params->sve_vl = sve_vq_from_vl(realm_max_vl) - 1; + params->flags |= RMI_REALM_PARAM_FLAG_SVE; + } + return 0; +} + static int realm_create_rd(struct kvm *kvm) { struct realm *realm = &kvm->arch.realm; @@ -344,6 +382,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)) {