--- v11
+++ v12
@@ -1,12 +1,11 @@
From: Anshuman Khandual <khandual@linux.vnet.ibm.com>
-This patch enables support for TM checkpointed FPR register
-set ELF core note NT_PPC_CFPR based ptrace requests through
-PTRACE_GETREGSET, PTRACE_SETREGSET calls. This is achieved
-through adding a register set REGSET_CFPR in powerpc
-corresponding to the ELF core note section added. It
-implements the get, set and active functions for this new
-register set added.
+This patch enables in transaction NT_PPC_VSX ptrace requests. The
+function vsr_get which gets the running value of all VSX registers
+and the function vsr_set which sets the running value of of all VSX
+registers work on the running set of VMX registers whose location
+will be different if transaction is active. This patch makes these
+functions adapt to situations when the transaction is active.
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
@@ -31,168 +30,114 @@
Cc: linux-kernel@vger.kernel.org
Cc: linux-kselftest@vger.kernel.org
Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
-Signed-off-by: Simon Guo <wei.guo.simon@gmail.com>
---
- arch/powerpc/kernel/ptrace.c | 126 +++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 126 insertions(+)
+ arch/powerpc/kernel/ptrace.c | 64 ++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 64 insertions(+)
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
-index 0334c23..a3d4bad 100644
+index 3baa57e..ebf3b0e 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
-@@ -799,6 +799,121 @@ static int tm_cgpr_set(struct task_struct *target,
+@@ -681,6 +681,21 @@ static int vsr_active(struct task_struct *target,
+ return target->thread.used_vsr ? regset->n : 0;
+ }
+
++/*
++ * When the transaction is active, 'transact_fp' holds the current running
++ * value of all FPR registers and 'fp_state' holds the last checkpointed
++ * value of all FPR registers for the current transaction. When transaction
++ * is not active 'fp_state' holds the current running state of all the FPR
++ * registers. So this function which returns the current running values of
++ * all the FPR registers, needs to know whether any transaction is active
++ * or not.
++ *
++ * 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)
+@@ -688,16 +703,47 @@ static int vsr_get(struct task_struct *target, const struct user_regset *regset,
+ u64 buf[32];
+ int ret, i;
+
++#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
++ flush_fp_to_thread(target);
++ flush_altivec_to_thread(target);
++ flush_tmregs_to_thread(target);
++#endif
+ flush_vsx_to_thread(target);
+
++#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
++ if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
++ for (i = 0; i < 32 ; i++)
++ buf[i] = target->thread.
++ transact_fp.fpr[i][TS_VSRLOWOFFSET];
++ } else {
++ for (i = 0; i < 32 ; i++)
++ buf[i] = target->thread.
++ fp_state.fpr[i][TS_VSRLOWOFFSET];
++ }
++#else
+ for (i = 0; i < 32 ; i++)
+ buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
++#endif
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ buf, 0, 32 * sizeof(double));
return ret;
}
-+
-+/**
-+ * tm_cfpr_active - get active number of registers in CFPR
-+ * @target: The target task.
-+ * @regset: The user regset structure.
+
++/*
++ * When the transaction is active, 'transact_fp' holds the current running
++ * value of all FPR registers and 'fp_state' holds the last checkpointed
++ * value of all FPR registers for the current transaction. When transaction
++ * is not active 'fp_state' holds the current running state of all the FPR
++ * registers. So this function which sets the current running values of all
++ * the FPR registers, needs to know whether any transaction is active or not.
+ *
-+ * This function checks for the active number of available
-+ * regisers in transaction checkpointed FPR category.
-+ */
-+static int tm_cfpr_active(struct task_struct *target,
-+ const struct user_regset *regset)
-+{
-+ if (!cpu_has_feature(CPU_FTR_TM))
-+ return -ENODEV;
-+
-+ if (!MSR_TM_ACTIVE(target->thread.regs->msr))
-+ return 0;
-+
-+ return regset->n;
-+}
-+
-+/**
-+ * tm_cfpr_get - get CFPR registers
-+ * @target: The target task.
-+ * @regset: The user regset structure.
-+ * @pos: The buffer position.
-+ * @count: Number of bytes to copy.
-+ * @kbuf: Kernel buffer to copy from.
-+ * @ubuf: User buffer to copy into.
-+ *
-+ * This function gets in transaction checkpointed FPR registers.
-+ *
-+ * When the transaction is active 'ckfp_state' holds the checkpointed
-+ * values for the current transaction to fall back on if it aborts
-+ * in between. This function gets those checkpointed FPR registers.
-+ * The userspace interface buffer layout is as follows.
++ * Userspace interface buffer layout:
+ *
+ * struct data {
-+ * u64 fpr[32];
-+ * u64 fpscr;
-+ *};
++ * u64 vsx[32];
++ * };
+ */
-+static int tm_cfpr_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;
-+
-+ if (!cpu_has_feature(CPU_FTR_TM))
-+ return -ENODEV;
-+
-+ if (!MSR_TM_ACTIVE(target->thread.regs->msr))
-+ return -ENODATA;
-+
+ 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)
+@@ -705,12 +751,30 @@ static int vsr_set(struct task_struct *target, const struct user_regset *regset,
+ u64 buf[32];
+ int ret,i;
+
++#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ flush_fp_to_thread(target);
+ flush_altivec_to_thread(target);
+ flush_tmregs_to_thread(target);
++#endif
+ flush_vsx_to_thread(target);
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ buf, 0, 32 * sizeof(double));
+
-+ /* copy to local buffer then write that out */
-+ for (i = 0; i < 32 ; i++)
-+ buf[i] = target->thread.TS_CKFPR(i);
-+ buf[32] = target->thread.ckfp_state.fpscr;
-+ return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
-+}
-+
-+/**
-+ * tm_cfpr_set - set CFPR registers
-+ * @target: The target task.
-+ * @regset: The user regset structure.
-+ * @pos: The buffer position.
-+ * @count: Number of bytes to copy.
-+ * @kbuf: Kernel buffer to copy into.
-+ * @ubuf: User buffer to copy from.
-+ *
-+ * This function sets in transaction checkpointed FPR registers.
-+ *
-+ * When the transaction is active 'ckfp_state' holds the checkpointed
-+ * FPR register values for the current transaction to fall back on
-+ * if it aborts in between. This function sets these checkpointed
-+ * FPR registers. The userspace interface buffer layout is as follows.
-+ *
-+ * struct data {
-+ * u64 fpr[32];
-+ * u64 fpscr;
-+ *};
-+ */
-+static int tm_cfpr_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;
-+
-+ if (!cpu_has_feature(CPU_FTR_TM))
-+ return -ENODEV;
-+
-+ if (!MSR_TM_ACTIVE(target->thread.regs->msr))
-+ return -ENODATA;
-+
-+ flush_fp_to_thread(target);
-+ flush_altivec_to_thread(target);
-+ flush_tmregs_to_thread(target);
-+
-+ /* 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_CKFPR(i) = buf[i];
-+ target->thread.ckfp_state.fpscr = buf[32];
-+ return 0;
-+}
- #endif
++#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
++ if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
++ for (i = 0; i < 32 ; i++)
++ target->thread.transact_fp.
++ fpr[i][TS_VSRLOWOFFSET] = buf[i];
++ } else {
++ for (i = 0; i < 32 ; i++)
++ target->thread.fp_state.
++ fpr[i][TS_VSRLOWOFFSET] = buf[i];
++ }
++#else
+ for (i = 0; i < 32 ; i++)
+ target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i];
++#endif
- /*
-@@ -818,6 +933,7 @@ enum powerpc_regset {
- #endif
- #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
- REGSET_TM_CGPR, /* TM checkpointed GPR registers */
-+ REGSET_TM_CFPR, /* TM checkpointed FPR registers */
- #endif
- };
-@@ -859,6 +975,11 @@ static const struct user_regset native_regsets[] = {
- .size = sizeof(long), .align = sizeof(long),
- .active = tm_cgpr_active, .get = tm_cgpr_get, .set = tm_cgpr_set
- },
-+ [REGSET_TM_CFPR] = {
-+ .core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG,
-+ .size = sizeof(double), .align = sizeof(double),
-+ .active = tm_cfpr_active, .get = tm_cfpr_get, .set = tm_cfpr_set
-+ },
- #endif
- };
-
-@@ -1091,6 +1212,11 @@ static const struct user_regset compat_regsets[] = {
- .active = tm_cgpr_active,
- .get = tm_cgpr32_get, .set = tm_cgpr32_set
- },
-+ [REGSET_TM_CFPR] = {
-+ .core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG,
-+ .size = sizeof(double), .align = sizeof(double),
-+ .active = tm_cfpr_active, .get = tm_cfpr_get, .set = tm_cfpr_set
-+ },
- #endif
- };
-
+ return ret;
--
1.8.3.1