aboutsummaryrefslogtreecommitdiff
path: root/linux-user/aarch64
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2022-07-08 20:45:37 +0530
committerPeter Maydell <peter.maydell@linaro.org>2022-07-11 13:43:52 +0100
commit24d87c187c46a935f2b6bd7194d9958fb28be786 (patch)
treeb7318aa25892738b19d3cb05229bfda19368e534 /linux-user/aarch64
parentfd72f5d0bae2bcdb695cb8da57b41c49c001f91f (diff)
linux-user/aarch64: Implement PR_SME_GET_VL, PR_SME_SET_VL
These prctl set the Streaming SVE vector length, which may be completely different from the Normal SVE vector length. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20220708151540.18136-43-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'linux-user/aarch64')
-rw-r--r--linux-user/aarch64/target_prctl.h54
1 files changed, 54 insertions, 0 deletions
diff --git a/linux-user/aarch64/target_prctl.h b/linux-user/aarch64/target_prctl.h
index 40481e6663..907c314146 100644
--- a/linux-user/aarch64/target_prctl.h
+++ b/linux-user/aarch64/target_prctl.h
@@ -10,6 +10,7 @@ static abi_long do_prctl_sve_get_vl(CPUArchState *env)
{
ARMCPU *cpu = env_archcpu(env);
if (cpu_isar_feature(aa64_sve, cpu)) {
+ /* PSTATE.SM is always unset on syscall entry. */
return sve_vq(env) * 16;
}
return -TARGET_EINVAL;
@@ -27,6 +28,7 @@ static abi_long do_prctl_sve_set_vl(CPUArchState *env, abi_long arg2)
&& arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) {
uint32_t vq, old_vq;
+ /* PSTATE.SM is always unset on syscall entry. */
old_vq = sve_vq(env);
/*
@@ -49,6 +51,58 @@ static abi_long do_prctl_sve_set_vl(CPUArchState *env, abi_long arg2)
}
#define do_prctl_sve_set_vl do_prctl_sve_set_vl
+static abi_long do_prctl_sme_get_vl(CPUArchState *env)
+{
+ ARMCPU *cpu = env_archcpu(env);
+ if (cpu_isar_feature(aa64_sme, cpu)) {
+ return sme_vq(env) * 16;
+ }
+ return -TARGET_EINVAL;
+}
+#define do_prctl_sme_get_vl do_prctl_sme_get_vl
+
+static abi_long do_prctl_sme_set_vl(CPUArchState *env, abi_long arg2)
+{
+ /*
+ * We cannot support either PR_SME_SET_VL_ONEXEC or PR_SME_VL_INHERIT.
+ * Note the kernel definition of sve_vl_valid allows for VQ=512,
+ * i.e. VL=8192, even though the architectural maximum is VQ=16.
+ */
+ if (cpu_isar_feature(aa64_sme, env_archcpu(env))
+ && arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) {
+ int vq, old_vq;
+
+ old_vq = sme_vq(env);
+
+ /*
+ * Bound the value of vq, so that we know that it fits into
+ * the 4-bit field in SMCR_EL1. Because PSTATE.SM is cleared
+ * on syscall entry, we are not modifying the current SVE
+ * vector length.
+ */
+ vq = MAX(arg2 / 16, 1);
+ vq = MIN(vq, 16);
+ env->vfp.smcr_el[1] =
+ FIELD_DP64(env->vfp.smcr_el[1], SMCR, LEN, vq - 1);
+
+ /* Delay rebuilding hflags until we know if ZA must change. */
+ vq = sve_vqm1_for_el_sm(env, 0, true) + 1;
+
+ if (vq != old_vq) {
+ /*
+ * PSTATE.ZA state is cleared on any change to SVL.
+ * We need not call arm_rebuild_hflags because PSTATE.SM was
+ * cleared on syscall entry, so this hasn't changed VL.
+ */
+ env->svcr = FIELD_DP64(env->svcr, SVCR, ZA, 0);
+ arm_rebuild_hflags(env);
+ }
+ return vq * 16;
+ }
+ return -TARGET_EINVAL;
+}
+#define do_prctl_sme_set_vl do_prctl_sme_set_vl
+
static abi_long do_prctl_reset_keys(CPUArchState *env, abi_long arg2)
{
ARMCPU *cpu = env_archcpu(env);