MIPS: Factor out NT_PRFPREG regset access helpers
authorMaciej W. Rozycki <macro@mips.com>
Mon, 11 Dec 2017 22:51:35 +0000 (22:51 +0000)
committerRalf Baechle <ralf@linux-mips.org>
Tue, 12 Dec 2017 18:11:26 +0000 (19:11 +0100)
In preparation to fix a commit 72b22bbad1e7 ("MIPS: Don't assume 64-bit
FP registers for FP regset") FCSR access regression factor out
NT_PRFPREG regset access helpers for the non-MSA and the MSA variants
respectively, to avoid having to deal with excessive indentation in the
actual fix.

No functional change, however use `target->thread.fpu.fpr[0]' rather
than `target->thread.fpu.fpr[i]' for FGR holding type size determination
as there's no `i' variable to refer to anymore, and for the factored out
`i' variable declaration use `unsigned int' rather than `unsigned' as
its type, following the common style.

Signed-off-by: Maciej W. Rozycki <macro@mips.com>
Fixes: 72b22bbad1e7 ("MIPS: Don't assume 64-bit FP registers for FP regset")
Cc: James Hogan <james.hogan@mips.com>
Cc: Paul Burton <Paul.Burton@mips.com>
Cc: Alex Smith <alex@alex-smith.me.uk>
Cc: Dave Martin <Dave.Martin@arm.com>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Cc: stable@vger.kernel.org # v3.15+
Patchwork: https://patchwork.linux-mips.org/patch/17925/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/kernel/ptrace.c

index efbd8df..62e8ffd 100644 (file)
@@ -419,25 +419,36 @@ static int gpr64_set(struct task_struct *target,
 
 #endif /* CONFIG_64BIT */
 
-static int fpr_get(struct task_struct *target,
-                  const struct user_regset *regset,
-                  unsigned int pos, unsigned int count,
-                  void *kbuf, void __user *ubuf)
+/*
+ * Copy the floating-point context to the supplied NT_PRFPREG buffer,
+ * !CONFIG_CPU_HAS_MSA variant.  FP context's general register slots
+ * correspond 1:1 to buffer slots.
+ */
+static int fpr_get_fpa(struct task_struct *target,
+                      unsigned int *pos, unsigned int *count,
+                      void **kbuf, void __user **ubuf)
 {
-       unsigned i;
-       int err;
-       u64 fpr_val;
-
-       /* XXX fcr31  */
+       return user_regset_copyout(pos, count, kbuf, ubuf,
+                                  &target->thread.fpu,
+                                  0, sizeof(elf_fpregset_t));
+}
 
-       if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
-               return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-                                          &target->thread.fpu,
-                                          0, sizeof(elf_fpregset_t));
+/*
+ * Copy the floating-point context to the supplied NT_PRFPREG buffer,
+ * CONFIG_CPU_HAS_MSA variant.  Only lower 64 bits of FP context's
+ * general register slots are copied to buffer slots.
+ */
+static int fpr_get_msa(struct task_struct *target,
+                      unsigned int *pos, unsigned int *count,
+                      void **kbuf, void __user **ubuf)
+{
+       unsigned int i;
+       u64 fpr_val;
+       int err;
 
        for (i = 0; i < NUM_FPU_REGS; i++) {
                fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
-               err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+               err = user_regset_copyout(pos, count, kbuf, ubuf,
                                          &fpr_val, i * sizeof(elf_fpreg_t),
                                          (i + 1) * sizeof(elf_fpreg_t));
                if (err)
@@ -447,27 +458,54 @@ static int fpr_get(struct task_struct *target,
        return 0;
 }
 
-static int fpr_set(struct task_struct *target,
+/* Copy the floating-point context to the supplied NT_PRFPREG buffer.  */
+static int fpr_get(struct task_struct *target,
                   const struct user_regset *regset,
                   unsigned int pos, unsigned int count,
-                  const void *kbuf, const void __user *ubuf)
+                  void *kbuf, void __user *ubuf)
 {
-       unsigned i;
        int err;
-       u64 fpr_val;
 
        /* XXX fcr31  */
 
-       init_fp_ctx(target);
+       if (sizeof(target->thread.fpu.fpr[0]) == sizeof(elf_fpreg_t))
+               err = fpr_get_fpa(target, &pos, &count, &kbuf, &ubuf);
+       else
+               err = fpr_get_msa(target, &pos, &count, &kbuf, &ubuf);
+
+       return err;
+}
 
-       if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
-               return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-                                         &target->thread.fpu,
-                                         0, sizeof(elf_fpregset_t));
+/*
+ * Copy the supplied NT_PRFPREG buffer to the floating-point context,
+ * !CONFIG_CPU_HAS_MSA variant.   Buffer slots correspond 1:1 to FP
+ * context's general register slots.
+ */
+static int fpr_set_fpa(struct task_struct *target,
+                      unsigned int *pos, unsigned int *count,
+                      const void **kbuf, const void __user **ubuf)
+{
+       return user_regset_copyin(pos, count, kbuf, ubuf,
+                                 &target->thread.fpu,
+                                 0, sizeof(elf_fpregset_t));
+}
+
+/*
+ * Copy the supplied NT_PRFPREG buffer to the floating-point context,
+ * CONFIG_CPU_HAS_MSA variant.  Buffer slots are copied to lower 64
+ * bits only of FP context's general register slots.
+ */
+static int fpr_set_msa(struct task_struct *target,
+                      unsigned int *pos, unsigned int *count,
+                      const void **kbuf, const void __user **ubuf)
+{
+       unsigned int i;
+       u64 fpr_val;
+       int err;
 
        BUILD_BUG_ON(sizeof(fpr_val) != sizeof(elf_fpreg_t));
-       for (i = 0; i < NUM_FPU_REGS && count >= sizeof(elf_fpreg_t); i++) {
-               err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+       for (i = 0; i < NUM_FPU_REGS && *count >= sizeof(elf_fpreg_t); i++) {
+               err = user_regset_copyin(pos, count, kbuf, ubuf,
                                         &fpr_val, i * sizeof(elf_fpreg_t),
                                         (i + 1) * sizeof(elf_fpreg_t));
                if (err)
@@ -478,6 +516,26 @@ static int fpr_set(struct task_struct *target,
        return 0;
 }
 
+/* Copy the supplied NT_PRFPREG buffer to the floating-point context.  */
+static int fpr_set(struct task_struct *target,
+                  const struct user_regset *regset,
+                  unsigned int pos, unsigned int count,
+                  const void *kbuf, const void __user *ubuf)
+{
+       int err;
+
+       /* XXX fcr31  */
+
+       init_fp_ctx(target);
+
+       if (sizeof(target->thread.fpu.fpr[0]) == sizeof(elf_fpreg_t))
+               err = fpr_set_fpa(target, &pos, &count, &kbuf, &ubuf);
+       else
+               err = fpr_set_msa(target, &pos, &count, &kbuf, &ubuf);
+
+       return err;
+}
+
 enum mips_regset {
        REGSET_GPR,
        REGSET_FPR,