diff options
author | Andrew Jones <drjones@redhat.com> | 2019-10-31 15:27:34 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2019-11-01 20:40:59 +0000 |
commit | 87014c6b3660ce54a57cb72171d6f93306b0c44a (patch) | |
tree | b6d4c629d56e000b1245ca7f47db35128367d051 /target | |
parent | 6fa8a37949d912bb463caa0c139ff0ca88c6ec33 (diff) |
target/arm/kvm: host cpu: Add support for sve<N> properties
Allow cpu 'host' to enable SVE when it's available, unless the
user chooses to disable it with the added 'sve=off' cpu property.
Also give the user the ability to select vector lengths with the
sve<N> properties. We don't adopt 'max' cpu's other sve property,
sve-max-vq, because that property is difficult to use with KVM.
That property assumes all vector lengths in the range from 1 up
to and including the specified maximum length are supported, but
there may be optional lengths not supported by the host in that
range. With KVM one must be more specific when enabling vector
lengths.
Signed-off-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Tested-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
Message-id: 20191031142734.8590-10-drjones@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target')
-rw-r--r-- | target/arm/cpu.c | 3 | ||||
-rw-r--r-- | target/arm/cpu.h | 2 | ||||
-rw-r--r-- | target/arm/cpu64.c | 33 | ||||
-rw-r--r-- | target/arm/kvm64.c | 14 |
4 files changed, 35 insertions, 17 deletions
diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 17d1f2b289..7a4ac9339b 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -2670,6 +2670,9 @@ static void arm_host_initfn(Object *obj) ARMCPU *cpu = ARM_CPU(obj); kvm_arm_set_cpu_features_from_host(cpu); + if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { + aarch64_add_sve_properties(obj); + } arm_cpu_post_init(obj); } diff --git a/target/arm/cpu.h b/target/arm/cpu.h index a044d6028b..e1a66a2d1c 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -977,11 +977,13 @@ int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq); void aarch64_sve_change_el(CPUARMState *env, int old_el, int new_el, bool el0_a64); +void aarch64_add_sve_properties(Object *obj); #else static inline void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq) { } static inline void aarch64_sve_change_el(CPUARMState *env, int o, int n, bool a) { } +static inline void aarch64_add_sve_properties(Object *obj) { } #endif #if !defined(CONFIG_TCG) diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index c161a146ff..68baf0482f 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -594,6 +594,21 @@ static void cpu_arm_set_sve(Object *obj, Visitor *v, const char *name, cpu->isar.id_aa64pfr0 = t; } +void aarch64_add_sve_properties(Object *obj) +{ + uint32_t vq; + + object_property_add(obj, "sve", "bool", cpu_arm_get_sve, + cpu_arm_set_sve, NULL, NULL, &error_fatal); + + for (vq = 1; vq <= ARM_MAX_VQ; ++vq) { + char name[8]; + sprintf(name, "sve%d", vq * 128); + object_property_add(obj, name, "bool", cpu_arm_get_sve_vq, + cpu_arm_set_sve_vq, NULL, NULL, &error_fatal); + } +} + /* -cpu max: if KVM is enabled, like -cpu host (best possible with this host); * otherwise, a CPU with as many features enabled as our emulation supports. * The version of '-cpu max' for qemu-system-arm is defined in cpu.c; @@ -602,17 +617,11 @@ static void cpu_arm_set_sve(Object *obj, Visitor *v, const char *name, static void aarch64_max_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); - uint32_t vq; - uint64_t t; if (kvm_enabled()) { kvm_arm_set_cpu_features_from_host(cpu); - if (kvm_arm_sve_supported(CPU(cpu))) { - t = cpu->isar.id_aa64pfr0; - t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1); - cpu->isar.id_aa64pfr0 = t; - } } else { + uint64_t t; uint32_t u; aarch64_a57_initfn(obj); @@ -712,17 +721,9 @@ static void aarch64_max_initfn(Object *obj) #endif } - object_property_add(obj, "sve", "bool", cpu_arm_get_sve, - cpu_arm_set_sve, NULL, NULL, &error_fatal); + aarch64_add_sve_properties(obj); object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_max_vq, cpu_max_set_sve_max_vq, NULL, NULL, &error_fatal); - - for (vq = 1; vq <= ARM_MAX_VQ; ++vq) { - char name[8]; - sprintf(name, "sve%d", vq * 128); - object_property_add(obj, name, "bool", cpu_arm_get_sve_vq, - cpu_arm_set_sve_vq, NULL, NULL, &error_fatal); - } } struct ARMCPUInfo { diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index c93bbee425..876184b8fe 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -488,7 +488,9 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) * and then query that CPU for the relevant ID registers. */ int fdarray[3]; + bool sve_supported; uint64_t features = 0; + uint64_t t; int err; /* Old kernels may not know about the PREFERRED_TARGET ioctl: however @@ -578,13 +580,23 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) ARM64_SYS_REG(3, 0, 0, 3, 2)); } + sve_supported = ioctl(fdarray[0], KVM_CHECK_EXTENSION, KVM_CAP_ARM_SVE) > 0; + kvm_arm_destroy_scratch_host_vcpu(fdarray); if (err < 0) { return false; } - /* We can assume any KVM supporting CPU is at least a v8 + /* Add feature bits that can't appear until after VCPU init. */ + if (sve_supported) { + t = ahcf->isar.id_aa64pfr0; + t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1); + ahcf->isar.id_aa64pfr0 = t; + } + + /* + * We can assume any KVM supporting CPU is at least a v8 * with VFPv4+Neon; this in turn implies most of the other * feature bits. */ |