arm64/sve: Generalise vector length configuration prctl() for SME
authorMark Brown <broonie@kernel.org>
Fri, 10 Dec 2021 18:40:58 +0000 (18:40 +0000)
committerCatalin Marinas <catalin.marinas@arm.com>
Tue, 14 Dec 2021 18:33:44 +0000 (18:33 +0000)
In preparation for adding SME support update the bulk of the implementation
for the vector length configuration prctl() calls to be independent of
vector type.

Signed-off-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20211210184133.320748-3-broonie@kernel.org
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
arch/arm64/include/asm/fpsimd.h
arch/arm64/kernel/fpsimd.c
arch/arm64/kernel/ptrace.c
arch/arm64/kvm/reset.c

index dbb4b30..cb24385 100644 (file)
@@ -51,8 +51,8 @@ extern void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *state,
 extern void fpsimd_flush_task_state(struct task_struct *target);
 extern void fpsimd_save_and_flush_cpu_state(void);
 
-/* Maximum VL that SVE VL-agnostic software can transparently support */
-#define SVE_VL_ARCH_MAX 0x100
+/* Maximum VL that SVE/SME VL-agnostic software can transparently support */
+#define VL_ARCH_MAX 0x100
 
 /* Offset of FFR in the SVE register dump */
 static inline size_t sve_ffr_offset(int vl)
@@ -122,7 +122,7 @@ extern void fpsimd_sync_to_sve(struct task_struct *task);
 extern void sve_sync_to_fpsimd(struct task_struct *task);
 extern void sve_sync_from_fpsimd_zeropad(struct task_struct *task);
 
-extern int sve_set_vector_length(struct task_struct *task,
+extern int vec_set_vector_length(struct task_struct *task, enum vec_type type,
                                 unsigned long vl, unsigned long flags);
 
 extern int sve_set_current_vl(unsigned long arg);
index 23e575c..4a98cc3 100644 (file)
@@ -632,7 +632,7 @@ void sve_sync_from_fpsimd_zeropad(struct task_struct *task)
        __fpsimd_to_sve(sst, fst, vq);
 }
 
-int sve_set_vector_length(struct task_struct *task,
+int vec_set_vector_length(struct task_struct *task, enum vec_type type,
                          unsigned long vl, unsigned long flags)
 {
        if (flags & ~(unsigned long)(PR_SVE_VL_INHERIT |
@@ -643,33 +643,35 @@ int sve_set_vector_length(struct task_struct *task,
                return -EINVAL;
 
        /*
-        * Clamp to the maximum vector length that VL-agnostic SVE code can
-        * work with.  A flag may be assigned in the future to allow setting
-        * of larger vector lengths without confusing older software.
+        * Clamp to the maximum vector length that VL-agnostic code
+        * can work with.  A flag may be assigned in the future to
+        * allow setting of larger vector lengths without confusing
+        * older software.
         */
-       if (vl > SVE_VL_ARCH_MAX)
-               vl = SVE_VL_ARCH_MAX;
+       if (vl > VL_ARCH_MAX)
+               vl = VL_ARCH_MAX;
 
-       vl = find_supported_vector_length(ARM64_VEC_SVE, vl);
+       vl = find_supported_vector_length(type, vl);
 
        if (flags & (PR_SVE_VL_INHERIT |
                     PR_SVE_SET_VL_ONEXEC))
-               task_set_sve_vl_onexec(task, vl);
+               task_set_vl_onexec(task, type, vl);
        else
                /* Reset VL to system default on next exec: */
-               task_set_sve_vl_onexec(task, 0);
+               task_set_vl_onexec(task, type, 0);
 
        /* Only actually set the VL if not deferred: */
        if (flags & PR_SVE_SET_VL_ONEXEC)
                goto out;
 
-       if (vl == task_get_sve_vl(task))
+       if (vl == task_get_vl(task, type))
                goto out;
 
        /*
         * To ensure the FPSIMD bits of the SVE vector registers are preserved,
         * write any live register state back to task_struct, and convert to a
-        * non-SVE thread.
+        * regular FPSIMD thread.  Since the vector length can only be changed
+        * with a syscall we can't be in streaming mode while reconfiguring.
         */
        if (task == current) {
                get_cpu_fpsimd_context();
@@ -690,10 +692,10 @@ int sve_set_vector_length(struct task_struct *task,
         */
        sve_free(task);
 
-       task_set_sve_vl(task, vl);
+       task_set_vl(task, type, vl);
 
 out:
-       update_tsk_thread_flag(task, TIF_SVE_VL_INHERIT,
+       update_tsk_thread_flag(task, vec_vl_inherit_flag(type),
                               flags & PR_SVE_VL_INHERIT);
 
        return 0;
@@ -701,20 +703,21 @@ out:
 
 /*
  * Encode the current vector length and flags for return.
- * This is only required for prctl(): ptrace has separate fields
+ * This is only required for prctl(): ptrace has separate fields.
+ * SVE and SME use the same bits for _ONEXEC and _INHERIT.
  *
- * flags are as for sve_set_vector_length().
+ * flags are as for vec_set_vector_length().
  */
-static int sve_prctl_status(unsigned long flags)
+static int vec_prctl_status(enum vec_type type, unsigned long flags)
 {
        int ret;
 
        if (flags & PR_SVE_SET_VL_ONEXEC)
-               ret = task_get_sve_vl_onexec(current);
+               ret = task_get_vl_onexec(current, type);
        else
-               ret = task_get_sve_vl(current);
+               ret = task_get_vl(current, type);
 
-       if (test_thread_flag(TIF_SVE_VL_INHERIT))
+       if (test_thread_flag(vec_vl_inherit_flag(type)))
                ret |= PR_SVE_VL_INHERIT;
 
        return ret;
@@ -732,11 +735,11 @@ int sve_set_current_vl(unsigned long arg)
        if (!system_supports_sve() || is_compat_task())
                return -EINVAL;
 
-       ret = sve_set_vector_length(current, vl, flags);
+       ret = vec_set_vector_length(current, ARM64_VEC_SVE, vl, flags);
        if (ret)
                return ret;
 
-       return sve_prctl_status(flags);
+       return vec_prctl_status(ARM64_VEC_SVE, flags);
 }
 
 /* PR_SVE_GET_VL */
@@ -745,7 +748,7 @@ int sve_get_current_vl(void)
        if (!system_supports_sve() || is_compat_task())
                return -EINVAL;
 
-       return sve_prctl_status(0);
+       return vec_prctl_status(ARM64_VEC_SVE, 0);
 }
 
 static void vec_probe_vqs(struct vl_info *info,
index 88a9034..716dde2 100644 (file)
@@ -812,9 +812,9 @@ static int sve_set(struct task_struct *target,
 
        /*
         * Apart from SVE_PT_REGS_MASK, all SVE_PT_* flags are consumed by
-        * sve_set_vector_length(), which will also validate them for us:
+        * vec_set_vector_length(), which will also validate them for us:
         */
-       ret = sve_set_vector_length(target, header.vl,
+       ret = vec_set_vector_length(target, ARM64_VEC_SVE, header.vl,
                ((unsigned long)header.flags & ~SVE_PT_REGS_MASK) << 16);
        if (ret)
                goto out;
index 426bd7f..27386f0 100644 (file)
@@ -52,10 +52,10 @@ int kvm_arm_init_sve(void)
                 * The get_sve_reg()/set_sve_reg() ioctl interface will need
                 * to be extended with multiple register slice support in
                 * order to support vector lengths greater than
-                * SVE_VL_ARCH_MAX:
+                * VL_ARCH_MAX:
                 */
-               if (WARN_ON(kvm_sve_max_vl > SVE_VL_ARCH_MAX))
-                       kvm_sve_max_vl = SVE_VL_ARCH_MAX;
+               if (WARN_ON(kvm_sve_max_vl > VL_ARCH_MAX))
+                       kvm_sve_max_vl = VL_ARCH_MAX;
 
                /*
                 * Don't even try to make use of vector lengths that
@@ -103,7 +103,7 @@ static int kvm_vcpu_finalize_sve(struct kvm_vcpu *vcpu)
         * set_sve_vls().  Double-check here just to be sure:
         */
        if (WARN_ON(!sve_vl_valid(vl) || vl > sve_max_virtualisable_vl() ||
-                   vl > SVE_VL_ARCH_MAX))
+                   vl > VL_ARCH_MAX))
                return -EIO;
 
        buf = kzalloc(SVE_SIG_REGS_SIZE(sve_vq_from_vl(vl)), GFP_KERNEL_ACCOUNT);