aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2021-07-23 10:33:44 -1000
committerPeter Maydell <peter.maydell@linaro.org>2021-07-27 10:57:40 +0100
commitb3d52804c591b478ec0620253c2bd71e4ff87bb9 (patch)
tree287bbaa7f2a03b6e837dae465cee9d75b1118dd7 /target
parentce440581c1446e56d911d83c9c3b760ae4f98b3e (diff)
downloadqemu-b3d52804c591b478ec0620253c2bd71e4ff87bb9.zip
qemu-b3d52804c591b478ec0620253c2bd71e4ff87bb9.tar.gz
qemu-b3d52804c591b478ec0620253c2bd71e4ff87bb9.tar.bz2
target/arm: Add sve-default-vector-length cpu property
Mirror the behavour of /proc/sys/abi/sve_default_vector_length under the real linux kernel. We have no way of passing along a real default across exec like the kernel can, but this is a decent way of adjusting the startup vector length of a process. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/482 Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 20210723203344.968563-4-richard.henderson@linaro.org [PMM: tweaked docs formatting, document -1 special-case, added fixup patch from RTH mentioning QEMU's maximum veclen.] Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target')
-rw-r--r--target/arm/cpu.c14
-rw-r--r--target/arm/cpu.h5
-rw-r--r--target/arm/cpu64.c60
3 files changed, 77 insertions, 2 deletions
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 752b15b..2866dd7 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -201,7 +201,8 @@ static void arm_cpu_reset(DeviceState *dev)
env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 16, 2, 3);
/* with reasonable vector length */
if (cpu_isar_feature(aa64_sve, cpu)) {
- env->vfp.zcr_el[1] = MIN(cpu->sve_max_vq - 1, 3);
+ env->vfp.zcr_el[1] =
+ aarch64_sve_zcr_get_valid_len(cpu, cpu->sve_default_vq - 1);
}
/*
* Enable TBI0 but not TBI1.
@@ -1051,7 +1052,16 @@ static void arm_cpu_initfn(Object *obj)
QLIST_INIT(&cpu->pre_el_change_hooks);
QLIST_INIT(&cpu->el_change_hooks);
-#ifndef CONFIG_USER_ONLY
+#ifdef CONFIG_USER_ONLY
+# ifdef TARGET_AARCH64
+ /*
+ * The linux kernel defaults to 512-bit vectors, when sve is supported.
+ * See documentation for /proc/sys/abi/sve_default_vector_length, and
+ * our corresponding sve-default-vector-length cpu property.
+ */
+ cpu->sve_default_vq = 4;
+# endif
+#else
/* Our inbound IRQ and FIQ lines */
if (kvm_enabled()) {
/* VIRQ and VFIQ are unused with KVM but we add them to maintain
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index be9a4dc..9f0a5f8 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1006,6 +1006,11 @@ struct ARMCPU {
/* Used to set the maximum vector length the cpu will support. */
uint32_t sve_max_vq;
+#ifdef CONFIG_USER_ONLY
+ /* Used to set the default vector length at process start. */
+ uint32_t sve_default_vq;
+#endif
+
/*
* In sve_vq_map each set bit is a supported vector length of
* (bit-number + 1) * 16 bytes, i.e. each bit number + 1 is the vector
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index c7a1626..c690318 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -559,6 +559,59 @@ static void cpu_arm_set_sve(Object *obj, bool value, Error **errp)
cpu->isar.id_aa64pfr0 = t;
}
+#ifdef CONFIG_USER_ONLY
+/* Mirror linux /proc/sys/abi/sve_default_vector_length. */
+static void cpu_arm_set_sve_default_vec_len(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ ARMCPU *cpu = ARM_CPU(obj);
+ int32_t default_len, default_vq, remainder;
+
+ if (!visit_type_int32(v, name, &default_len, errp)) {
+ return;
+ }
+
+ /* Undocumented, but the kernel allows -1 to indicate "maximum". */
+ if (default_len == -1) {
+ cpu->sve_default_vq = ARM_MAX_VQ;
+ return;
+ }
+
+ default_vq = default_len / 16;
+ remainder = default_len % 16;
+
+ /*
+ * Note that the 512 max comes from include/uapi/asm/sve_context.h
+ * and is the maximum architectural width of ZCR_ELx.LEN.
+ */
+ if (remainder || default_vq < 1 || default_vq > 512) {
+ error_setg(errp, "cannot set sve-default-vector-length");
+ if (remainder) {
+ error_append_hint(errp, "Vector length not a multiple of 16\n");
+ } else if (default_vq < 1) {
+ error_append_hint(errp, "Vector length smaller than 16\n");
+ } else {
+ error_append_hint(errp, "Vector length larger than %d\n",
+ 512 * 16);
+ }
+ return;
+ }
+
+ cpu->sve_default_vq = default_vq;
+}
+
+static void cpu_arm_get_sve_default_vec_len(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ ARMCPU *cpu = ARM_CPU(obj);
+ int32_t value = cpu->sve_default_vq * 16;
+
+ visit_type_int32(v, name, &value, errp);
+}
+#endif
+
void aarch64_add_sve_properties(Object *obj)
{
uint32_t vq;
@@ -571,6 +624,13 @@ void aarch64_add_sve_properties(Object *obj)
object_property_add(obj, name, "bool", cpu_arm_get_sve_vq,
cpu_arm_set_sve_vq, NULL, NULL);
}
+
+#ifdef CONFIG_USER_ONLY
+ /* Mirror linux /proc/sys/abi/sve_default_vector_length. */
+ object_property_add(obj, "sve-default-vector-length", "int32",
+ cpu_arm_get_sve_default_vec_len,
+ cpu_arm_set_sve_default_vec_len, NULL, NULL);
+#endif
}
void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)