aboutsummaryrefslogtreecommitdiff
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
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>
-rw-r--r--docs/system/arm/cpu-features.rst15
-rw-r--r--target/arm/cpu.c14
-rw-r--r--target/arm/cpu.h5
-rw-r--r--target/arm/cpu64.c60
4 files changed, 92 insertions, 2 deletions
diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst
index c455442..11dce5c 100644
--- a/docs/system/arm/cpu-features.rst
+++ b/docs/system/arm/cpu-features.rst
@@ -376,3 +376,18 @@ verbose command lines. However, the recommended way to select vector
lengths is to explicitly enable each desired length. Therefore only
example's (1), (4), and (6) exhibit recommended uses of the properties.
+SVE User-mode Default Vector Length Property
+--------------------------------------------
+
+For qemu-aarch64, the cpu property ``sve-default-vector-length=N`` is
+defined to mirror the Linux kernel parameter file
+``/proc/sys/abi/sve_default_vector_length``. The default length, ``N``,
+is in units of bytes and must be between 16 and 8192.
+If not specified, the default vector length is 64.
+
+If the default length is larger than the maximum vector length enabled,
+the actual vector length will be reduced. Note that the maximum vector
+length supported by QEMU is 256.
+
+If this property is set to ``-1`` then the default vector length
+is set to the maximum possible length.
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)