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>
This commit is contained in:
Richard Henderson 2021-07-23 10:33:44 -10:00 committed by Peter Maydell
parent ce440581c1
commit b3d52804c5
4 changed files with 92 additions and 2 deletions

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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)