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:
|
||||
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);
|
||||
if (!sve && size == sve_size) {
|
||||
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. */
|
||||
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_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);
|
||||
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;
|
||||
}
|
||||
@ -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))
|
||||
&& arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) {
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
uint32_t vq, old_vq;
|
||||
|
||||
old_vq = (env->vfp.zcr_el[1] & 0xf) + 1;
|
||||
vq = MAX(arg2 / 16, 1);
|
||||
vq = MIN(vq, cpu->sve_max_vq);
|
||||
old_vq = sve_vq(env);
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
aarch64_sve_narrow_vq(env, vq);
|
||||
}
|
||||
env->vfp.zcr_el[1] = vq - 1;
|
||||
arm_rebuild_hflags(env);
|
||||
return vq * 16;
|
||||
}
|
||||
return -TARGET_EINVAL;
|
||||
|
@ -3286,6 +3286,17 @@ static inline int cpu_mmu_index(CPUARMState *env, bool ifetch)
|
||||
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)
|
||||
{
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
|
Loading…
Reference in New Issue
Block a user