On 6/4/21 8:52 AM, Alex Bennée wrote:
+void kvm_sve_get_supported_lens(ARMCPU *cpu, unsigned long *kvm_supported) +{ + /* Collect the set of vector lengths supported by KVM. */ + bitmap_zero(kvm_supported, ARM_MAX_VQ); + + if (kvm_arm_sve_supported()) { + kvm_arm_sve_get_vls(CPU(cpu), kvm_supported); + } else { + assert(!cpu_isar_feature(aa64_sve, cpu)); + } +} + +void kvm_sve_enable_lens(unsigned long *sve_vq_map, + unsigned long *sve_vq_init, uint32_t max_vq, + unsigned long *kvm_supported) +{ + /* + * For KVM we have to automatically enable all supported unitialized + * lengths, even when the smaller lengths are not all powers-of-two. + */ + DECLARE_BITMAP(tmp, ARM_MAX_VQ); + + bitmap_andnot(tmp, kvm_supported, sve_vq_init, max_vq); + bitmap_or(sve_vq_map, sve_vq_map, tmp, max_vq); +} + +uint32_t kvm_sve_disable_lens(unsigned long *sve_vq_map, + unsigned long *sve_vq_init, + unsigned long *kvm_supported, Error **errp) +{ + uint32_t max_vq, vq; + + /* Disabling a supported length disables all larger lengths. */ + for (vq = 1; vq <= ARM_MAX_VQ; ++vq) { + if (test_bit(vq - 1, sve_vq_init) && + test_bit(vq - 1, kvm_supported)) { + break; + } + } + + max_vq = vq <= ARM_MAX_VQ ? vq - 1 : ARM_MAX_VQ; + bitmap_andnot(sve_vq_map, kvm_supported, sve_vq_init, max_vq); + + if (max_vq == 0 || bitmap_empty(sve_vq_map, max_vq)) { + error_setg(errp, "cannot disable sve%d", vq * 128); + error_append_hint(errp, "Disabling sve%d results in all " + "vector lengths being disabled.\n", + vq * 128); + error_append_hint(errp, "With SVE enabled, at least one " + "vector length must be enabled.\n"); + return 0; + } + + return max_vq; +} + +bool kvm_sve_validate_lens(unsigned long *sve_vq_map, uint32_t max_vq, + unsigned long *kvm_supported, Error **errp, + uint32_t sve_max_vq) +{ + /* Ensure the set of lengths matches what KVM supports. */ + DECLARE_BITMAP(tmp, ARM_MAX_VQ); + uint32_t vq; + + bitmap_xor(tmp, sve_vq_map, kvm_supported, max_vq); + if (bitmap_empty(tmp, max_vq)) { + return true; + } + + vq = find_last_bit(tmp, max_vq) + 1; + if (test_bit(vq - 1, sve_vq_map)) { + if (sve_max_vq) { + error_setg(errp, "cannot set sve-max-vq=%d", sve_max_vq); + error_append_hint(errp, "This KVM host does not support " + "the vector length %d-bits.\n", vq * 128); + error_append_hint(errp, "It may not be possible to use " + "sve-max-vq with this KVM host. Try " + "using only sve<N> properties.\n"); + } else { + error_setg(errp, "cannot enable sve%d", vq * 128); + error_append_hint(errp, "This KVM host does not support " + "the vector length %d-bits.\n", vq * 128); + } + } else { + error_setg(errp, "cannot disable sve%d", vq * 128); + error_append_hint(errp, "The KVM host requires all " + "supported vector lengths smaller " + "than %d bits to also be enabled.\n", max_vq * 128); + } + return false; +}
Also, I think I mentioned this before in review of a previous version, I strongly suspect that aside from kvm_sve_get_supported_lens, the other functions will be used without change by all other hw virt systems.
So I think we'll do best, short term, to keep all of this in cpu-sve.c for now. The tcg_enabled() test should elide all of the code that's not needed when !CONFIG_TCG.
r~