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:
parent
ce440581c1
commit
b3d52804c5
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user