linux-user/aarch64: Introduce sve_vq
Add an interface function to extract the digested vector length rather than the raw zcr_el[1] value. This fixes an incorrect return from do_prctl_set_vl where we didn't take into account the set of vector lengths supported by the cpu. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20220607203306.657998-3-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
f45ce4c35f
commit
8b599e5c02
|
@ -315,7 +315,7 @@ static int target_restore_sigframe(CPUARMState *env,
|
||||||
|
|
||||||
case TARGET_SVE_MAGIC:
|
case TARGET_SVE_MAGIC:
|
||||||
if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
|
if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
|
||||||
vq = (env->vfp.zcr_el[1] & 0xf) + 1;
|
vq = sve_vq(env);
|
||||||
sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
|
sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
|
||||||
if (!sve && size == sve_size) {
|
if (!sve && size == sve_size) {
|
||||||
sve = (struct target_sve_context *)ctx;
|
sve = (struct target_sve_context *)ctx;
|
||||||
|
@ -434,7 +434,7 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
|
||||||
|
|
||||||
/* SVE state needs saving only if it exists. */
|
/* SVE state needs saving only if it exists. */
|
||||||
if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
|
if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
|
||||||
vq = (env->vfp.zcr_el[1] & 0xf) + 1;
|
vq = sve_vq(env);
|
||||||
sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
|
sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
|
||||||
sve_ofs = alloc_sigframe_space(sve_size, &layout);
|
sve_ofs = alloc_sigframe_space(sve_size, &layout);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ static abi_long do_prctl_get_vl(CPUArchState *env)
|
||||||
{
|
{
|
||||||
ARMCPU *cpu = env_archcpu(env);
|
ARMCPU *cpu = env_archcpu(env);
|
||||||
if (cpu_isar_feature(aa64_sve, cpu)) {
|
if (cpu_isar_feature(aa64_sve, cpu)) {
|
||||||
return ((cpu->env.vfp.zcr_el[1] & 0xf) + 1) * 16;
|
return sve_vq(env) * 16;
|
||||||
}
|
}
|
||||||
return -TARGET_EINVAL;
|
return -TARGET_EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -25,18 +25,24 @@ static abi_long do_prctl_set_vl(CPUArchState *env, abi_long arg2)
|
||||||
*/
|
*/
|
||||||
if (cpu_isar_feature(aa64_sve, env_archcpu(env))
|
if (cpu_isar_feature(aa64_sve, env_archcpu(env))
|
||||||
&& arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) {
|
&& arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) {
|
||||||
ARMCPU *cpu = env_archcpu(env);
|
|
||||||
uint32_t vq, old_vq;
|
uint32_t vq, old_vq;
|
||||||
|
|
||||||
old_vq = (env->vfp.zcr_el[1] & 0xf) + 1;
|
old_vq = sve_vq(env);
|
||||||
vq = MAX(arg2 / 16, 1);
|
|
||||||
vq = MIN(vq, cpu->sve_max_vq);
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bound the value of arg2, so that we know that it fits into
|
||||||
|
* the 4-bit field in ZCR_EL1. Rely on the hflags rebuild to
|
||||||
|
* sort out the length supported by the cpu.
|
||||||
|
*/
|
||||||
|
vq = MAX(arg2 / 16, 1);
|
||||||
|
vq = MIN(vq, ARM_MAX_VQ);
|
||||||
|
env->vfp.zcr_el[1] = vq - 1;
|
||||||
|
arm_rebuild_hflags(env);
|
||||||
|
|
||||||
|
vq = sve_vq(env);
|
||||||
if (vq < old_vq) {
|
if (vq < old_vq) {
|
||||||
aarch64_sve_narrow_vq(env, vq);
|
aarch64_sve_narrow_vq(env, vq);
|
||||||
}
|
}
|
||||||
env->vfp.zcr_el[1] = vq - 1;
|
|
||||||
arm_rebuild_hflags(env);
|
|
||||||
return vq * 16;
|
return vq * 16;
|
||||||
}
|
}
|
||||||
return -TARGET_EINVAL;
|
return -TARGET_EINVAL;
|
||||||
|
|
|
@ -3286,6 +3286,17 @@ static inline int cpu_mmu_index(CPUARMState *env, bool ifetch)
|
||||||
return EX_TBFLAG_ANY(env->hflags, MMUIDX);
|
return EX_TBFLAG_ANY(env->hflags, MMUIDX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sve_vq
|
||||||
|
* @env: the cpu context
|
||||||
|
*
|
||||||
|
* Return the VL cached within env->hflags, in units of quadwords.
|
||||||
|
*/
|
||||||
|
static inline int sve_vq(CPUARMState *env)
|
||||||
|
{
|
||||||
|
return EX_TBFLAG_A64(env->hflags, VL) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool bswap_code(bool sctlr_b)
|
static inline bool bswap_code(bool sctlr_b)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
|
Loading…
Reference in New Issue