Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[platform/kernel/linux-rpi.git] / arch / arm64 / kernel / fpsimd.c
index 6fb361e..5280e09 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/compiler.h>
 #include <linux/cpu.h>
 #include <linux/cpu_pm.h>
+#include <linux/ctype.h>
 #include <linux/kernel.h>
 #include <linux/linkage.h>
 #include <linux/irqflags.h>
@@ -410,12 +411,13 @@ static unsigned int find_supported_vector_length(enum vec_type type,
 
 #if defined(CONFIG_ARM64_SVE) && defined(CONFIG_SYSCTL)
 
-static int sve_proc_do_default_vl(struct ctl_table *table, int write,
+static int vec_proc_do_default_vl(struct ctl_table *table, int write,
                                  void *buffer, size_t *lenp, loff_t *ppos)
 {
-       struct vl_info *info = &vl_info[ARM64_VEC_SVE];
+       struct vl_info *info = table->extra1;
+       enum vec_type type = info->type;
        int ret;
-       int vl = get_sve_default_vl();
+       int vl = get_default_vl(type);
        struct ctl_table tmp_table = {
                .data = &vl,
                .maxlen = sizeof(vl),
@@ -432,7 +434,7 @@ static int sve_proc_do_default_vl(struct ctl_table *table, int write,
        if (!sve_vl_valid(vl))
                return -EINVAL;
 
-       set_sve_default_vl(find_supported_vector_length(ARM64_VEC_SVE, vl));
+       set_default_vl(type, find_supported_vector_length(type, vl));
        return 0;
 }
 
@@ -440,7 +442,8 @@ static struct ctl_table sve_default_vl_table[] = {
        {
                .procname       = "sve_default_vector_length",
                .mode           = 0644,
-               .proc_handler   = sve_proc_do_default_vl,
+               .proc_handler   = vec_proc_do_default_vl,
+               .extra1         = &vl_info[ARM64_VEC_SVE],
        },
        { }
 };
@@ -633,7 +636,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 |
@@ -644,33 +647,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();
@@ -691,10 +696,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;
@@ -702,20 +707,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;
@@ -733,11 +739,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 */
@@ -746,7 +752,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,
@@ -1111,7 +1117,7 @@ static void fpsimd_flush_thread_vl(enum vec_type type)
                vl = get_default_vl(type);
 
        if (WARN_ON(!sve_vl_valid(vl)))
-               vl = SVE_VL_MIN;
+               vl = vl_info[type].min_vl;
 
        supported_vl = find_supported_vector_length(type, vl);
        if (WARN_ON(supported_vl != vl))
@@ -1217,7 +1223,8 @@ void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *st, void *sve_state,
 /*
  * Load the userland FPSIMD state of 'current' from memory, but only if the
  * FPSIMD state already held in the registers is /not/ the most recent FPSIMD
- * state of 'current'
+ * state of 'current'.  This is called when we are preparing to return to
+ * userspace to ensure that userspace sees a good register state.
  */
 void fpsimd_restore_current_state(void)
 {
@@ -1248,7 +1255,9 @@ void fpsimd_restore_current_state(void)
 /*
  * Load an updated userland FPSIMD state for 'current' from memory and set the
  * flag that indicates that the FPSIMD register contents are the most recent
- * FPSIMD state of 'current'
+ * FPSIMD state of 'current'. This is used by the signal code to restore the
+ * register state when returning from a signal handler in FPSIMD only cases,
+ * any SVE context will be discarded.
  */
 void fpsimd_update_current_state(struct user_fpsimd_state const *state)
 {