Probe for SVE vector sizes with the same scratch vm that we use for probing other features. Remove a separate initialization path in arm_cpu_sve_finalize. Unexport kvm_arm_sve_get_vls.
Signed-off-by: Richard Henderson <[email protected]> --- target/arm/kvm_arm.h | 10 ------ target/arm/cpu64.c | 20 +----------- target/arm/kvm-stub.c | 5 --- target/arm/kvm.c | 73 ++++++++++++++++--------------------------- 4 files changed, 28 insertions(+), 80 deletions(-) diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h index cc0b374254..97549766ea 100644 --- a/target/arm/kvm_arm.h +++ b/target/arm/kvm_arm.h @@ -124,16 +124,6 @@ bool kvm_arm_create_scratch_host_vcpu(int *fdarray, */ void kvm_arm_destroy_scratch_host_vcpu(int *fdarray); -/** - * kvm_arm_sve_get_vls: - * @cpu: ARMCPU - * - * Get all the SVE vector lengths supported by the KVM host, setting - * the bits corresponding to their length in quadwords minus one - * (vq - 1) up to ARM_MAX_VQ. Return the resulting map. - */ -uint32_t kvm_arm_sve_get_vls(ARMCPU *cpu); - /** * kvm_arm_set_cpu_features_from_host: * @cpu: ARMCPU to set the features for diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index 10c6796548..0116b6cc88 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -79,28 +79,10 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) */ uint32_t vq_map = cpu->sve_vq.map; uint32_t vq_init = cpu->sve_vq.init; - uint32_t vq_supported; + uint32_t vq_supported = cpu->sve_vq.supported; uint32_t vq_mask = 0; uint32_t tmp, vq, max_vq = 0; - /* - * CPU models specify a set of supported vector lengths which are - * enabled by default. Attempting to enable any vector length not set - * in the supported bitmap results in an error. When KVM is enabled we - * fetch the supported bitmap from the host. - */ - if (kvm_enabled()) { - if (kvm_arm_sve_supported()) { - cpu->sve_vq.supported = kvm_arm_sve_get_vls(cpu); - vq_supported = cpu->sve_vq.supported; - } else { - assert(!cpu_isar_feature(aa64_sve, cpu)); - vq_supported = 0; - } - } else { - vq_supported = cpu->sve_vq.supported; - } - /* * Process explicit sve<N> properties. * From the properties, sve_vq_map<N> implies sve_vq_init<N>. diff --git a/target/arm/kvm-stub.c b/target/arm/kvm-stub.c index ea67deea52..f2de36aef3 100644 --- a/target/arm/kvm-stub.c +++ b/target/arm/kvm-stub.c @@ -95,11 +95,6 @@ void kvm_arm_steal_time_finalize(ARMCPU *cpu, Error **errp) g_assert_not_reached(); } -uint32_t kvm_arm_sve_get_vls(ARMCPU *cpu) -{ - g_assert_not_reached(); -} - void kvm_arm_enable_mte(Object *cpuobj, Error **errp) { g_assert_not_reached(); diff --git a/target/arm/kvm.c b/target/arm/kvm.c index e0fd79b78c..464356989b 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -60,6 +60,7 @@ typedef struct ARMHostCPUFeatures { ARMISARegisters isar; uint64_t features; uint32_t target; + uint32_t sve_vq_supported; const char *dtb_compatible; } ARMHostCPUFeatures; @@ -243,58 +244,34 @@ static int get_host_cpu_reg(int fd, ARMHostCPUFeatures *ahcf, return ret; } -uint32_t kvm_arm_sve_get_vls(ARMCPU *cpu) +static uint32_t kvm_arm_sve_get_vls(int fd) { /* Only call this function if kvm_arm_sve_supported() returns true. */ - static uint64_t vls[KVM_ARM64_SVE_VLS_WORDS]; - static bool probed; + uint64_t vls[KVM_ARM64_SVE_VLS_WORDS]; + struct kvm_one_reg reg = { + .id = KVM_REG_ARM64_SVE_VLS, + .addr = (uint64_t)&vls[0], + }; uint32_t vq = 0; - int i; + int ret; - /* - * KVM ensures all host CPUs support the same set of vector lengths. - * So we only need to create the scratch VCPUs once and then cache - * the results. - */ - if (!probed) { - struct kvm_vcpu_init init = { - .target = -1, - .features[0] = (1 << KVM_ARM_VCPU_SVE), - }; - struct kvm_one_reg reg = { - .id = KVM_REG_ARM64_SVE_VLS, - .addr = (uint64_t)&vls[0], - }; - int fdarray[3], ret; - - probed = true; - - if (!kvm_arm_create_scratch_host_vcpu(fdarray, &init)) { - error_report("failed to create scratch VCPU with SVE enabled"); - abort(); - } - ret = ioctl(fdarray[2], KVM_GET_ONE_REG, ®); - kvm_arm_destroy_scratch_host_vcpu(fdarray); - if (ret) { - error_report("failed to get KVM_REG_ARM64_SVE_VLS: %s", - strerror(errno)); - abort(); - } - - for (i = KVM_ARM64_SVE_VLS_WORDS - 1; i >= 0; --i) { - if (vls[i]) { - vq = 64 - clz64(vls[i]) + i * 64; - break; - } - } - if (vq > ARM_MAX_VQ) { - warn_report("KVM supports vector lengths larger than " - "QEMU can enable"); - vls[0] &= MAKE_64BIT_MASK(0, ARM_MAX_VQ); - } + ret = ioctl(fd, KVM_GET_ONE_REG, ®); + if (ret) { + error_report("failed to get KVM_REG_ARM64_SVE_VLS: %s", + strerror(errno)); + abort(); } - return vls[0]; + for (int i = KVM_ARM64_SVE_VLS_WORDS - 1; i >= 0; --i) { + if (vls[i]) { + vq = 64 - clz64(vls[i]) + i * 64; + break; + } + } + if (vq > ARM_MAX_VQ) { + warn_report("KVM supports vector lengths larger than QEMU can enable"); + } + return vls[0] & MAKE_64BIT_MASK(0, ARM_MAX_VQ); } static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) @@ -469,6 +446,9 @@ static bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) * So only read the register if we set KVM_ARM_VCPU_SVE above. */ err |= get_host_cpu_reg(fd, ahcf, ID_AA64ZFR0_EL1_IDX); + + /* Read the set of supported vector lengths. */ + arm_host_cpu_features.sve_vq_supported = kvm_arm_sve_get_vls(fd); } } @@ -516,6 +496,7 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) cpu->kvm_target = arm_host_cpu_features.target; cpu->dtb_compatible = arm_host_cpu_features.dtb_compatible; cpu->isar = arm_host_cpu_features.isar; + cpu->sve_vq.supported = arm_host_cpu_features.sve_vq_supported; env->features = arm_host_cpu_features.features; } -- 2.43.0
