@@ -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 (EX_TBFLAG_A64(env->hflags, SVE_LEN) + 1) * 16;
}
return -TARGET_EINVAL;
}
@@ -25,18 +25,25 @@ 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;
+ old_vq = EX_TBFLAG_A64(env->hflags, SVE_LEN) + 1;
+
+ /*
+ * Bound the value of vq, 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, cpu->sve_max_vq);
+ vq = MIN(vq, 16);
+ env->vfp.zcr_el[1] = vq - 1;
+ arm_rebuild_hflags(env);
+
+ vq = EX_TBFLAG_A64(env->hflags, SVE_LEN) + 1;
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;
@@ -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 = EX_TBFLAG_A64(env->hflags, SVE_LEN) + 1;
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 = EX_TBFLAG_A64(env->hflags, SVE_LEN) + 1;
sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
sve_ofs = alloc_sigframe_space(sve_size, &layout);
}
Use 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. It also prepares us for Streaming SVE mode, where the vector length comes from a different cpreg. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- linux-user/aarch64/target_prctl.h | 19 +++++++++++++------ linux-user/aarch64/signal.c | 4 ++-- 2 files changed, 15 insertions(+), 8 deletions(-)