powerpc/ptrace: split out VSX related functions.
authorChristophe Leroy <christophe.leroy@c-s.fr>
Fri, 28 Feb 2020 00:14:41 +0000 (00:14 +0000)
committerMichael Ellerman <mpe@ellerman.id.au>
Wed, 1 Apr 2020 03:30:48 +0000 (14:30 +1100)
Move CONFIG_VSX functions out of ptrace.c, into
ptrace-vsx.c and ptrace-novsx.c

Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/dc8e20c8c95b7e83add0c6dd48f9470628896c5c.1582848567.git.christophe.leroy@c-s.fr
arch/powerpc/kernel/ptrace/Makefile
arch/powerpc/kernel/ptrace/ptrace-decl.h [new file with mode: 0644]
arch/powerpc/kernel/ptrace/ptrace-novsx.c [new file with mode: 0644]
arch/powerpc/kernel/ptrace/ptrace-vsx.c [new file with mode: 0644]
arch/powerpc/kernel/ptrace/ptrace.c

index 02fb28e..238c271 100644 (file)
@@ -7,3 +7,7 @@ CFLAGS_ptrace.o         += -DUTS_MACHINE='"$(UTS_MACHINE)"'
 
 obj-y                          += ptrace.o
 obj-$(CONFIG_PPC64)            += ptrace32.o
+obj-$(CONFIG_VSX)              += ptrace-vsx.o
+ifneq ($(CONFIG_VSX),y)
+obj-y                          += ptrace-novsx.o
+endif
diff --git a/arch/powerpc/kernel/ptrace/ptrace-decl.h b/arch/powerpc/kernel/ptrace/ptrace-decl.h
new file mode 100644 (file)
index 0000000..764df4e
--- /dev/null
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/* ptrace-(no)vsx */
+
+int fpr_get(struct task_struct *target, const struct user_regset *regset,
+           unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
+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);
+
+/* ptrace-vsx */
+
+int vsr_active(struct task_struct *target, const struct user_regset *regset);
+int vsr_get(struct task_struct *target, const struct user_regset *regset,
+           unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf);
+int vsr_set(struct task_struct *target, const struct user_regset *regset,
+           unsigned int pos, unsigned int count,
+           const void *kbuf, const void __user *ubuf);
+
+/* ptrace */
+
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+void flush_tmregs_to_thread(struct task_struct *tsk);
+#else
+static inline void flush_tmregs_to_thread(struct task_struct *tsk) { }
+#endif
diff --git a/arch/powerpc/kernel/ptrace/ptrace-novsx.c b/arch/powerpc/kernel/ptrace/ptrace-novsx.c
new file mode 100644 (file)
index 0000000..b2dc4e9
--- /dev/null
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/regset.h>
+
+#include <asm/switch_to.h>
+
+#include "ptrace-decl.h"
+
+/*
+ * Regardless of transactions, 'fp_state' holds the current running
+ * value of all FPR registers and 'ckfp_state' holds the last checkpointed
+ * value of all FPR registers for the current transaction.
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct data {
+ *     u64     fpr[32];
+ *     u64     fpscr;
+ * };
+ */
+int fpr_get(struct task_struct *target, const struct user_regset *regset,
+           unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
+{
+       BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
+                    offsetof(struct thread_fp_state, fpr[32]));
+
+       flush_fp_to_thread(target);
+
+       return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+                                  &target->thread.fp_state, 0, -1);
+}
+
+/*
+ * Regardless of transactions, 'fp_state' holds the current running
+ * value of all FPR registers and 'ckfp_state' holds the last checkpointed
+ * value of all FPR registers for the current transaction.
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct data {
+ *     u64     fpr[32];
+ *     u64     fpscr;
+ * };
+ *
+ */
+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)
+{
+       BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
+                    offsetof(struct thread_fp_state, fpr[32]));
+
+       flush_fp_to_thread(target);
+
+       return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+                                 &target->thread.fp_state, 0, -1);
+}
diff --git a/arch/powerpc/kernel/ptrace/ptrace-vsx.c b/arch/powerpc/kernel/ptrace/ptrace-vsx.c
new file mode 100644 (file)
index 0000000..d53466d
--- /dev/null
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/regset.h>
+
+#include <asm/switch_to.h>
+
+#include "ptrace-decl.h"
+
+/*
+ * Regardless of transactions, 'fp_state' holds the current running
+ * value of all FPR registers and 'ckfp_state' holds the last checkpointed
+ * value of all FPR registers for the current transaction.
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct data {
+ *     u64     fpr[32];
+ *     u64     fpscr;
+ * };
+ */
+int fpr_get(struct task_struct *target, const struct user_regset *regset,
+           unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
+{
+       u64 buf[33];
+       int i;
+
+       flush_fp_to_thread(target);
+
+       /* copy to local buffer then write that out */
+       for (i = 0; i < 32 ; i++)
+               buf[i] = target->thread.TS_FPR(i);
+       buf[32] = target->thread.fp_state.fpscr;
+       return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
+}
+
+/*
+ * Regardless of transactions, 'fp_state' holds the current running
+ * value of all FPR registers and 'ckfp_state' holds the last checkpointed
+ * value of all FPR registers for the current transaction.
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct data {
+ *     u64     fpr[32];
+ *     u64     fpscr;
+ * };
+ *
+ */
+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)
+{
+       u64 buf[33];
+       int i;
+
+       flush_fp_to_thread(target);
+
+       for (i = 0; i < 32 ; i++)
+               buf[i] = target->thread.TS_FPR(i);
+       buf[32] = target->thread.fp_state.fpscr;
+
+       /* copy to local buffer then write that out */
+       i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
+       if (i)
+               return i;
+
+       for (i = 0; i < 32 ; i++)
+               target->thread.TS_FPR(i) = buf[i];
+       target->thread.fp_state.fpscr = buf[32];
+       return 0;
+}
+
+/*
+ * Currently to set and and get all the vsx state, you need to call
+ * the fp and VMX calls as well.  This only get/sets the lower 32
+ * 128bit VSX registers.
+ */
+
+int vsr_active(struct task_struct *target, const struct user_regset *regset)
+{
+       flush_vsx_to_thread(target);
+       return target->thread.used_vsr ? regset->n : 0;
+}
+
+/*
+ * Regardless of transactions, 'fp_state' holds the current running
+ * value of all FPR registers and 'ckfp_state' holds the last
+ * checkpointed value of all FPR registers for the current
+ * transaction.
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct data {
+ *     u64     vsx[32];
+ * };
+ */
+int vsr_get(struct task_struct *target, const struct user_regset *regset,
+           unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
+{
+       u64 buf[32];
+       int ret, i;
+
+       flush_tmregs_to_thread(target);
+       flush_fp_to_thread(target);
+       flush_altivec_to_thread(target);
+       flush_vsx_to_thread(target);
+
+       for (i = 0; i < 32 ; i++)
+               buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
+
+       ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+                                 buf, 0, 32 * sizeof(double));
+
+       return ret;
+}
+
+/*
+ * Regardless of transactions, 'fp_state' holds the current running
+ * value of all FPR registers and 'ckfp_state' holds the last
+ * checkpointed value of all FPR registers for the current
+ * transaction.
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct data {
+ *     u64     vsx[32];
+ * };
+ */
+int vsr_set(struct task_struct *target, const struct user_regset *regset,
+           unsigned int pos, unsigned int count,
+           const void *kbuf, const void __user *ubuf)
+{
+       u64 buf[32];
+       int ret, i;
+
+       flush_tmregs_to_thread(target);
+       flush_fp_to_thread(target);
+       flush_altivec_to_thread(target);
+       flush_vsx_to_thread(target);
+
+       for (i = 0; i < 32 ; i++)
+               buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
+
+       ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+                                buf, 0, 32 * sizeof(double));
+       if (!ret)
+               for (i = 0; i < 32 ; i++)
+                       target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i];
+
+       return ret;
+}
index 22826c9..ead33b7 100644 (file)
@@ -33,6 +33,8 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/syscalls.h>
 
+#include "ptrace-decl.h"
+
 struct pt_regs_offset {
        const char *name;
        int offset;
@@ -100,7 +102,7 @@ static const struct pt_regs_offset regoffset_table[] = {
 };
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
-static void flush_tmregs_to_thread(struct task_struct *tsk)
+void flush_tmregs_to_thread(struct task_struct *tsk)
 {
        /*
         * If task is not current, it will have been flushed already to
@@ -120,8 +122,6 @@ static void flush_tmregs_to_thread(struct task_struct *tsk)
                tm_save_sprs(&(tsk->thread));
        }
 }
-#else
-static inline void flush_tmregs_to_thread(struct task_struct *tsk) { }
 #endif
 
 /**
@@ -403,91 +403,6 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset,
        return ret;
 }
 
-/*
- * Regardless of transactions, 'fp_state' holds the current running
- * value of all FPR registers and 'ckfp_state' holds the last checkpointed
- * value of all FPR registers for the current transaction.
- *
- * Userspace interface buffer layout:
- *
- * struct data {
- *     u64     fpr[32];
- *     u64     fpscr;
- * };
- */
-static int fpr_get(struct task_struct *target, const struct user_regset *regset,
-                  unsigned int pos, unsigned int count,
-                  void *kbuf, void __user *ubuf)
-{
-#ifdef CONFIG_VSX
-       u64 buf[33];
-       int i;
-
-       flush_fp_to_thread(target);
-
-       /* copy to local buffer then write that out */
-       for (i = 0; i < 32 ; i++)
-               buf[i] = target->thread.TS_FPR(i);
-       buf[32] = target->thread.fp_state.fpscr;
-       return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
-#else
-       BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
-                    offsetof(struct thread_fp_state, fpr[32]));
-
-       flush_fp_to_thread(target);
-
-       return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-                                  &target->thread.fp_state, 0, -1);
-#endif
-}
-
-/*
- * Regardless of transactions, 'fp_state' holds the current running
- * value of all FPR registers and 'ckfp_state' holds the last checkpointed
- * value of all FPR registers for the current transaction.
- *
- * Userspace interface buffer layout:
- *
- * struct data {
- *     u64     fpr[32];
- *     u64     fpscr;
- * };
- *
- */
-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)
-{
-#ifdef CONFIG_VSX
-       u64 buf[33];
-       int i;
-
-       flush_fp_to_thread(target);
-
-       for (i = 0; i < 32 ; i++)
-               buf[i] = target->thread.TS_FPR(i);
-       buf[32] = target->thread.fp_state.fpscr;
-
-       /* copy to local buffer then write that out */
-       i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
-       if (i)
-               return i;
-
-       for (i = 0; i < 32 ; i++)
-               target->thread.TS_FPR(i) = buf[i];
-       target->thread.fp_state.fpscr = buf[32];
-       return 0;
-#else
-       BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
-                    offsetof(struct thread_fp_state, fpr[32]));
-
-       flush_fp_to_thread(target);
-
-       return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-                                 &target->thread.fp_state, 0, -1);
-#endif
-}
-
 #ifdef CONFIG_ALTIVEC
 /*
  * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
@@ -612,90 +527,6 @@ static int vr_set(struct task_struct *target, const struct user_regset *regset,
 }
 #endif /* CONFIG_ALTIVEC */
 
-#ifdef CONFIG_VSX
-/*
- * Currently to set and and get all the vsx state, you need to call
- * the fp and VMX calls as well.  This only get/sets the lower 32
- * 128bit VSX registers.
- */
-
-static int vsr_active(struct task_struct *target,
-                     const struct user_regset *regset)
-{
-       flush_vsx_to_thread(target);
-       return target->thread.used_vsr ? regset->n : 0;
-}
-
-/*
- * Regardless of transactions, 'fp_state' holds the current running
- * value of all FPR registers and 'ckfp_state' holds the last
- * checkpointed value of all FPR registers for the current
- * transaction.
- *
- * Userspace interface buffer layout:
- *
- * struct data {
- *     u64     vsx[32];
- * };
- */
-static int vsr_get(struct task_struct *target, const struct user_regset *regset,
-                  unsigned int pos, unsigned int count,
-                  void *kbuf, void __user *ubuf)
-{
-       u64 buf[32];
-       int ret, i;
-
-       flush_tmregs_to_thread(target);
-       flush_fp_to_thread(target);
-       flush_altivec_to_thread(target);
-       flush_vsx_to_thread(target);
-
-       for (i = 0; i < 32 ; i++)
-               buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
-
-       ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-                                 buf, 0, 32 * sizeof(double));
-
-       return ret;
-}
-
-/*
- * Regardless of transactions, 'fp_state' holds the current running
- * value of all FPR registers and 'ckfp_state' holds the last
- * checkpointed value of all FPR registers for the current
- * transaction.
- *
- * Userspace interface buffer layout:
- *
- * struct data {
- *     u64     vsx[32];
- * };
- */
-static int vsr_set(struct task_struct *target, const struct user_regset *regset,
-                  unsigned int pos, unsigned int count,
-                  const void *kbuf, const void __user *ubuf)
-{
-       u64 buf[32];
-       int ret,i;
-
-       flush_tmregs_to_thread(target);
-       flush_fp_to_thread(target);
-       flush_altivec_to_thread(target);
-       flush_vsx_to_thread(target);
-
-       for (i = 0; i < 32 ; i++)
-               buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
-
-       ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-                                buf, 0, 32 * sizeof(double));
-       if (!ret)
-               for (i = 0; i < 32 ; i++)
-                       target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i];
-
-       return ret;
-}
-#endif /* CONFIG_VSX */
-
 #ifdef CONFIG_SPE
 
 /*