diff options
Diffstat (limited to 'linux-user')
-rw-r--r-- | linux-user/aarch64/target_syscall.h | 3 | ||||
-rw-r--r-- | linux-user/syscall.c | 27 |
2 files changed, 30 insertions, 0 deletions
diff --git a/linux-user/aarch64/target_syscall.h b/linux-user/aarch64/target_syscall.h index 604ab99b14..205265e619 100644 --- a/linux-user/aarch64/target_syscall.h +++ b/linux-user/aarch64/target_syscall.h @@ -19,4 +19,7 @@ struct target_pt_regs { #define TARGET_MLOCKALL_MCL_CURRENT 1 #define TARGET_MLOCKALL_MCL_FUTURE 2 +#define TARGET_PR_SVE_SET_VL 50 +#define TARGET_PR_SVE_GET_VL 51 + #endif /* AARCH64_TARGET_SYSCALL_H */ diff --git a/linux-user/syscall.c b/linux-user/syscall.c index a8abfd421d..b4f7b14fbe 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -10672,6 +10672,33 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; } #endif +#ifdef TARGET_AARCH64 + case TARGET_PR_SVE_SET_VL: + /* We cannot support either PR_SVE_SET_VL_ONEXEC + or PR_SVE_VL_INHERIT. Therefore, anything above + ARM_MAX_VQ results in EINVAL. */ + ret = -TARGET_EINVAL; + if (arm_feature(cpu_env, ARM_FEATURE_SVE) + && arg2 >= 0 && arg2 <= ARM_MAX_VQ * 16 && !(arg2 & 15)) { + CPUARMState *env = cpu_env; + int old_vq = (env->vfp.zcr_el[1] & 0xf) + 1; + int vq = MAX(arg2 / 16, 1); + + if (vq < old_vq) { + aarch64_sve_narrow_vq(env, vq); + } + env->vfp.zcr_el[1] = vq - 1; + ret = vq * 16; + } + break; + case TARGET_PR_SVE_GET_VL: + ret = -TARGET_EINVAL; + if (arm_feature(cpu_env, ARM_FEATURE_SVE)) { + CPUARMState *env = cpu_env; + ret = ((env->vfp.zcr_el[1] & 0xf) + 1) * 16; + } + break; +#endif /* AARCH64 */ case PR_GET_SECCOMP: case PR_SET_SECCOMP: /* Disable seccomp to prevent the target disabling syscalls we |