linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [V5 0/7] Add new powerpc specific ELF core notes
@ 2014-11-25  8:05 Anshuman Khandual
  2014-11-25  8:05 ` [V5 1/7] elf: Add new powerpc specifc core note sections Anshuman Khandual
                   ` (6 more replies)
  0 siblings, 7 replies; 10+ messages in thread
From: Anshuman Khandual @ 2014-11-25  8:05 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev
  Cc: peterz, akpm, tglx, james.hogan, avagin, Paul.Clothier, palves,
	oleg, dhowells, davej, davem, mikey, benh, sukadev, mpe,
	sam.bobroff, kirjanov, shuahkh

	This patch series adds five new ELF core note sections which can be
used with existing ptrace request PTRACE_GETREGSET-SETREGSET for accessing
various transactional memory and miscellaneous debug register sets on powerpc
platform.

Previous versions:
==================
RFC: https://lkml.org/lkml/2014/4/1/292
V1:  https://lkml.org/lkml/2014/4/2/43
V2:  https://lkml.org/lkml/2014/5/5/88
V3:  https://lkml.org/lkml/2014/5/23/486
V4:  https://lkml.org/lkml/2014/11/11/6

Changes in V5:
--------------
- Changed flush_tmregs_to_thread, so not to take into account self tracing
- Dropped the 3rd patch in the series which had merged two functions
- Fixed one build problem for the misc debug register patch
- Accommodated almost all the review comments from Suka on the 6th patch
- Minor changes to the self test program
- Changed commit messages for some of the patches

Changes in V4:
--------------
- Added one test program into the powerpc selftest bucket in this regard
- Split the 2nd patch in the previous series into four different patches
- Accommodated most of the review comments on the previous patch series
- Added a patch to merge functions __switch_to_tm and tm_reclaim_task

Changes in V3:
--------------
- Added two new error paths in every TM related get/set functions when regset
  support is not present on the system (ENODEV) or when the process does not
  have any transaction active (ENODATA) in the context
- Installed the active hooks for all the newly added regset core note types

Changes in V2:
--------------
- Removed all the power specific ptrace requests corresponding to new NT_PPC_*
  elf core note types. Now all the register sets can be accessed from ptrace
  through PTRACE_GETREGSET/PTRACE_SETREGSET using the individual NT_PPC* core
  note type instead
- Fixed couple of attribute values for REGSET_TM_CGPR register set
- Renamed flush_tmreg_to_thread as flush_tmregs_to_thread
- Fixed 32 bit checkpointed GPR support
- Changed commit messages accordingly

Test Result
-----------
The patch series has been verified both in 32 bit and 64 bit compiled test
program. Test result for the selftest test (64 bit compiled) can be found here.

test: tm_ptrace
tags: git_version:v3.18-rc6-8-ge2aa4ce
===Testing TM based PTRACE Interface===
Testing TM specific SPR:
TFHAR: 10001098
TEXASR: de0000018c000001
TFIAR: c000000000041858
TM ORIG_MSR: 800000050000f032
TM CH DSCR: a (PASSED)
TM CH TAR: 14 (PASSED)
TM CH PPR: 8000000000000 (PASSED)
Testing TM checkpointed GPR:
TM CH NIP: 10001098
TM CH LINK: 10000ea0
TM CH CCR: 24000422
TM CH GPR[0]: 0 (PASSED)
TM CH GPR[1]: 1 (PASSED)
TM CH GPR[2]: 2 (PASSED)
TM CH GPR[3]: 3 (PASSED)
TM CH GPR[4]: 4 (PASSED)
TM CH GPR[5]: 5 (PASSED)
TM CH GPR[6]: 6 (PASSED)
TM CH GPR[7]: 7 (PASSED)
TM CH GPR[8]: 8 (PASSED)
TM CH GPR[9]: 9 (PASSED)
TM CH GPR[10]: a (PASSED)
TM CH GPR[11]: b (PASSED)
TM CH GPR[12]: c (PASSED)
TM CH GPR[13]: d (PASSED)
TM CH GPR[14]: e (PASSED)
TM CH GPR[15]: f (PASSED)
TM CH GPR[16]: 0 (PASSED)
TM CH GPR[17]: 1 (PASSED)
TM CH GPR[18]: 2 (PASSED)
TM CH GPR[19]: 3 (PASSED)
TM CH GPR[20]: 4 (PASSED)
TM CH GPR[21]: 5 (PASSED)
TM CH GPR[22]: 6 (PASSED)
TM CH GPR[23]: 7 (PASSED)
TM CH GPR[24]: 8 (PASSED)
TM CH GPR[25]: 9 (PASSED)
TM CH GPR[26]: a (PASSED)
TM CH GPR[27]: b (PASSED)
TM CH GPR[28]: c (PASSED)
TM CH GPR[29]: d (PASSED)
TM CH GPR[30]: e (PASSED)
TM CH GPR[31]: f (PASSED)
Testing TM checkpointed FPR:
TM CH FPSCR: 0
TM CH FPR[0]: 0 (PASSED)
TM CH FPR[1]: 1 (PASSED)
TM CH FPR[2]: 2 (PASSED)
TM CH FPR[3]: 3 (PASSED)
TM CH FPR[4]: 4 (PASSED)
TM CH FPR[5]: 5 (PASSED)
TM CH FPR[6]: 6 (PASSED)
TM CH FPR[7]: 7 (PASSED)
TM CH FPR[8]: 8 (PASSED)
TM CH FPR[9]: 9 (PASSED)
TM CH FPR[10]: a (PASSED)
TM CH FPR[11]: b (PASSED)
TM CH FPR[12]: c (PASSED)
TM CH FPR[13]: d (PASSED)
TM CH FPR[14]: e (PASSED)
TM CH FPR[15]: f (PASSED)
TM CH FPR[16]: 0 (PASSED)
TM CH FPR[17]: 1 (PASSED)
TM CH FPR[18]: 2 (PASSED)
TM CH FPR[19]: 3 (PASSED)
TM CH FPR[20]: 4 (PASSED)
TM CH FPR[21]: 5 (PASSED)
TM CH FPR[22]: 6 (PASSED)
TM CH FPR[23]: 7 (PASSED)
TM CH FPR[24]: 8 (PASSED)
TM CH FPR[25]: 9 (PASSED)
TM CH FPR[26]: a (PASSED)
TM CH FPR[27]: b (PASSED)
TM CH FPR[28]: c (PASSED)
TM CH FPR[29]: d (PASSED)
TM CH FPR[30]: e (PASSED)
TM CH FPR[31]: f (PASSED)
Testing TM running GPR:
TM RN NIP: 100011b0
TM RN LINK: 10000ea0
TM RN CCR: 4000422
TM RN GPR[0]: f (PASSED)
TM RN GPR[1]: e (PASSED)
TM RN GPR[2]: d (PASSED)
TM RN GPR[3]: c (PASSED)
TM RN GPR[4]: b (PASSED)
TM RN GPR[5]: a (PASSED)
TM RN GPR[6]: 9 (PASSED)
TM RN GPR[7]: 8 (PASSED)
TM RN GPR[8]: 7 (PASSED)
TM RN GPR[9]: 6 (PASSED)
TM RN GPR[10]: 5 (PASSED)
TM RN GPR[11]: 4 (PASSED)
TM RN GPR[12]: 3 (PASSED)
TM RN GPR[13]: 2 (PASSED)
TM RN GPR[14]: 1 (PASSED)
TM RN GPR[15]: 0 (PASSED)
TM RN GPR[16]: f (PASSED)
TM RN GPR[17]: e (PASSED)
TM RN GPR[18]: d (PASSED)
TM RN GPR[19]: c (PASSED)
TM RN GPR[20]: b (PASSED)
TM RN GPR[21]: a (PASSED)
TM RN GPR[22]: 9 (PASSED)
TM RN GPR[23]: 8 (PASSED)
TM RN GPR[24]: 7 (PASSED)
TM RN GPR[25]: 6 (PASSED)
TM RN GPR[26]: 5 (PASSED)
TM RN GPR[27]: 4 (PASSED)
TM RN GPR[28]: 3 (PASSED)
TM RN GPR[29]: 2 (PASSED)
TM RN GPR[30]: 1 (PASSED)
TM RN GPR[31]: 0 (PASSED)
Testing TM running FPR:
TM RN FPSCR: 0
TM RN FPR[0]: f (PASSED)
TM RN FPR[1]: e (PASSED)
TM RN FPR[2]: d (PASSED)
TM RN FPR[3]: c (PASSED)
TM RN FPR[4]: b (PASSED)
TM RN FPR[5]: a (PASSED)
TM RN FPR[6]: 9 (PASSED)
TM RN FPR[7]: 8 (PASSED)
TM RN FPR[8]: 7 (PASSED)
TM RN FPR[9]: 6 (PASSED)
TM RN FPR[10]: 5 (PASSED)
TM RN FPR[11]: 4 (PASSED)
TM RN FPR[12]: 3 (PASSED)
TM RN FPR[13]: 2 (PASSED)
TM RN FPR[14]: 1 (PASSED)
TM RN FPR[15]: 0 (PASSED)
TM RN FPR[16]: f (PASSED)
TM RN FPR[17]: e (PASSED)
TM RN FPR[18]: d (PASSED)
TM RN FPR[19]: c (PASSED)
TM RN FPR[20]: b (PASSED)
TM RN FPR[21]: a (PASSED)
TM RN FPR[22]: 9 (PASSED)
TM RN FPR[23]: 8 (PASSED)
TM RN FPR[24]: 7 (PASSED)
TM RN FPR[25]: 6 (PASSED)
TM RN FPR[26]: 5 (PASSED)
TM RN FPR[27]: 4 (PASSED)
TM RN FPR[28]: 3 (PASSED)
TM RN FPR[29]: 2 (PASSED)
TM RN FPR[30]: 1 (PASSED)
TM RN FPR[31]: 0 (PASSED)
Testing TM running MISC debug registers:
TM RN DSCR: 32 (PASSED)
TM RN TAR: 3c (PASSED)
TM RN PPR: 4000000000000 (PASSED)
success: tm_ptrace

Anshuman Khandual (7):
  elf: Add new powerpc specifc core note sections
  powerpc, process: Add the function flush_tmregs_to_thread
  powerpc, ptrace: Enable fpr_(get/set) for transactional memory
  powerpc, ptrace: Enable vr_(get/set) for transactional memory
  powerpc, ptrace: Enable support for transactional memory register sets
  powerpc, ptrace: Enable support for miscellaneous debug registers
  selftests, powerpc: Add test case for TM related ptrace interface

 arch/powerpc/include/asm/switch_to.h           |   8 +
 arch/powerpc/include/uapi/asm/elf.h            |   3 +
 arch/powerpc/kernel/process.c                  |  20 +
 arch/powerpc/kernel/ptrace.c                   | 987 ++++++++++++++++++++++++-
 include/uapi/linux/elf.h                       |   5 +
 tools/testing/selftests/powerpc/tm/Makefile    |   2 +-
 tools/testing/selftests/powerpc/tm/tm-ptrace.c | 542 ++++++++++++++
 7 files changed, 1542 insertions(+), 25 deletions(-)
 create mode 100644 tools/testing/selftests/powerpc/tm/tm-ptrace.c

-- 
1.9.3


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [V5 1/7] elf: Add new powerpc specifc core note sections
  2014-11-25  8:05 [V5 0/7] Add new powerpc specific ELF core notes Anshuman Khandual
@ 2014-11-25  8:05 ` Anshuman Khandual
  2014-11-25  8:05 ` [V5 2/7] powerpc, process: Add the function flush_tmregs_to_thread Anshuman Khandual
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Anshuman Khandual @ 2014-11-25  8:05 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev
  Cc: peterz, akpm, tglx, james.hogan, avagin, Paul.Clothier, palves,
	oleg, dhowells, davej, davem, mikey, benh, sukadev, mpe,
	sam.bobroff, kirjanov, shuahkh

This patch adds four new ELF core note sections for powerpc
transactional memory and one new ELF core note section for
powerpc general miscellaneous debug registers. These addition
of new ELF core note sections extends the existing ELF ABI
without affecting it in any manner.

Acked-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 include/uapi/linux/elf.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h
index ea9bf25..2260fc0 100644
--- a/include/uapi/linux/elf.h
+++ b/include/uapi/linux/elf.h
@@ -379,6 +379,11 @@ typedef struct elf64_shdr {
 #define NT_PPC_VMX	0x100		/* PowerPC Altivec/VMX registers */
 #define NT_PPC_SPE	0x101		/* PowerPC SPE/EVR registers */
 #define NT_PPC_VSX	0x102		/* PowerPC VSX registers */
+#define NT_PPC_TM_SPR	0x103		/* PowerPC TM special registers */
+#define NT_PPC_TM_CGPR	0x104		/* PowerpC TM checkpointed GPR */
+#define NT_PPC_TM_CFPR	0x105		/* PowerPC TM checkpointed FPR */
+#define NT_PPC_TM_CVMX	0x106		/* PowerPC TM checkpointed VMX */
+#define NT_PPC_MISC	0x107		/* PowerPC miscellaneous registers */
 #define NT_386_TLS	0x200		/* i386 TLS slots (struct user_desc) */
 #define NT_386_IOPERM	0x201		/* x86 io permission bitmap (1=deny) */
 #define NT_X86_XSTATE	0x202		/* x86 extended state using xsave */
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [V5 2/7] powerpc, process: Add the function flush_tmregs_to_thread
  2014-11-25  8:05 [V5 0/7] Add new powerpc specific ELF core notes Anshuman Khandual
  2014-11-25  8:05 ` [V5 1/7] elf: Add new powerpc specifc core note sections Anshuman Khandual
@ 2014-11-25  8:05 ` Anshuman Khandual
  2014-11-25  8:05 ` [V5 3/7] powerpc, ptrace: Enable fpr_(get/set) for transactional memory Anshuman Khandual
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Anshuman Khandual @ 2014-11-25  8:05 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev
  Cc: peterz, akpm, tglx, james.hogan, avagin, Paul.Clothier, palves,
	oleg, dhowells, davej, davem, mikey, benh, sukadev, mpe,
	sam.bobroff, kirjanov, shuahkh

This patch creates a function flush_tmregs_to_thread which
will then be used by subsequent patches in this series. The
function checks for self tracing ptrace interface attempts
while in the TM context and logs appropriate warning message.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/switch_to.h |  8 ++++++++
 arch/powerpc/kernel/process.c        | 20 ++++++++++++++++++++
 2 files changed, 28 insertions(+)

diff --git a/arch/powerpc/include/asm/switch_to.h b/arch/powerpc/include/asm/switch_to.h
index 58abeda..23752a9 100644
--- a/arch/powerpc/include/asm/switch_to.h
+++ b/arch/powerpc/include/asm/switch_to.h
@@ -82,6 +82,14 @@ static inline void flush_spe_to_thread(struct task_struct *t)
 }
 #endif
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+extern void flush_tmregs_to_thread(struct task_struct *);
+#else
+static inline void flush_tmregs_to_thread(struct task_struct *t)
+{
+}
+#endif
+
 static inline void clear_task_ebb(struct task_struct *t)
 {
 #ifdef CONFIG_PPC_BOOK3S_64
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 923cd2d..0013f24 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -745,6 +745,26 @@ void restore_tm_state(struct pt_regs *regs)
 #define __switch_to_tm(prev)
 #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+void flush_tmregs_to_thread(struct task_struct *tsk)
+{
+	/*
+	 * Process self tracing is not yet supported through
+	 * ptrace interface. Ptrace generic code should have
+	 * prevented this from happening in the first place.
+	 * Warn once here with the message, if some how it
+	 * is attempted.
+	 */
+	WARN_ONCE(tsk == current,
+		"Not expecting ptrace on self: TM regs may be incorrect\n");
+
+	/*
+	 * If task is not current, it should have been flushed
+	 * already to it's thread_struct during __switch_to().
+	 */
+}
+#endif
+
 struct task_struct *__switch_to(struct task_struct *prev,
 	struct task_struct *new)
 {
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [V5 3/7] powerpc, ptrace: Enable fpr_(get/set) for transactional memory
  2014-11-25  8:05 [V5 0/7] Add new powerpc specific ELF core notes Anshuman Khandual
  2014-11-25  8:05 ` [V5 1/7] elf: Add new powerpc specifc core note sections Anshuman Khandual
  2014-11-25  8:05 ` [V5 2/7] powerpc, process: Add the function flush_tmregs_to_thread Anshuman Khandual
@ 2014-11-25  8:05 ` Anshuman Khandual
  2014-11-25  8:05 ` [V5 4/7] powerpc, ptrace: Enable vr_(get/set) " Anshuman Khandual
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Anshuman Khandual @ 2014-11-25  8:05 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev
  Cc: peterz, akpm, tglx, james.hogan, avagin, Paul.Clothier, palves,
	oleg, dhowells, davej, davem, mikey, benh, sukadev, mpe,
	sam.bobroff, kirjanov, shuahkh

This patch enables the fpr_get which gets the running value of all
the FPR registers and the fpr_set which sets the running value of
of all the FPR registers to accommodate in transaction ptrace
interface based requests.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 arch/powerpc/kernel/ptrace.c | 103 ++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 97 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index f21897b..fd36b32 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -357,6 +357,33 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset,
 	return ret;
 }
 
+
+/*
+ * fpr_get
+ *
+ * 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	fpr[32];
+ *	u64	fpscr;
+ * };
+ *
+ * There are two config options CONFIG_VSX and CONFIG_PPC_TRANSACTIONAL_MEM
+ * which determines the final code in this function. All the combinations of
+ * these two config options are possible except the one below as transactional
+ * memory config pulls in CONFIG_VSX automatically.
+ *
+ *	!defined(CONFIG_VSX) && defined(CONFIG_PPC_TRANSACTIONAL_MEM)
+ *
+ */
 static int fpr_get(struct task_struct *target, const struct user_regset *regset,
 		   unsigned int pos, unsigned int count,
 		   void *kbuf, void __user *ubuf)
@@ -367,22 +394,64 @@ static int fpr_get(struct task_struct *target, const struct user_regset *regset,
 #endif
 	flush_fp_to_thread(target);
 
-#ifdef CONFIG_VSX
+#if defined(CONFIG_VSX) && defined(CONFIG_PPC_TRANSACTIONAL_MEM)
+	/* copy to local buffer then write that out */
+	if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+		flush_altivec_to_thread(target);
+		flush_tmregs_to_thread(target);
+		for (i = 0; i < 32 ; i++)
+			buf[i] = target->thread.TS_TRANS_FPR(i);
+		buf[32] = target->thread.transact_fp.fpscr;
+	} else {
+		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);
+#endif
+
+#if defined(CONFIG_VSX) && !defined(CONFIG_PPC_TRANSACTIONAL_MEM)
 	/* 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);
+#endif
 
-#else
+
+#if !defined(CONFIG_VSX) && !defined(CONFIG_PPC_TRANSACTIONAL_MEM)
 	BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
 		     offsetof(struct thread_fp_state, fpr[32][0]));
-
 	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 				   &target->thread.fp_state, 0, -1);
 #endif
 }
 
+/*
+ * fpr_set
+ *
+ * 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 setss 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	fpr[32];
+ *	u64	fpscr;
+ * };
+ *
+ * There are two config options CONFIG_VSX and CONFIG_PPC_TRANSACTIONAL_MEM
+ * which determines the final code in this function. All the combinations of
+ * these two config options are possible except the one below as transactional
+ * memory config pulls in CONFIG_VSX automatically.
+ *
+ *	!defined(CONFIG_VSX) && defined(CONFIG_PPC_TRANSACTIONAL_MEM)
+ */
 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)
@@ -393,7 +462,27 @@ static int fpr_set(struct task_struct *target, const struct user_regset *regset,
 #endif
 	flush_fp_to_thread(target);
 
-#ifdef CONFIG_VSX
+#if defined(CONFIG_VSX) && defined(CONFIG_PPC_TRANSACTIONAL_MEM)
+	/* copy to local buffer then write that out */
+	i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
+	if (i)
+		return i;
+
+	if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+		flush_altivec_to_thread(target);
+		flush_tmregs_to_thread(target);
+		for (i = 0; i < 32 ; i++)
+			target->thread.TS_TRANS_FPR(i) = buf[i];
+		target->thread.transact_fp.fpscr = buf[32];
+	} else {
+		for (i = 0; i < 32 ; i++)
+			target->thread.TS_FPR(i) = buf[i];
+		target->thread.fp_state.fpscr = buf[32];
+	}
+	return 0;
+#endif
+
+#if defined(CONFIG_VSX) && !defined(CONFIG_PPC_TRANSACTIONAL_MEM)
 	/* copy to local buffer then write that out */
 	i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
 	if (i)
@@ -402,12 +491,14 @@ static int fpr_set(struct task_struct *target, const struct user_regset *regset,
 		target->thread.TS_FPR(i) = buf[i];
 	target->thread.fp_state.fpscr = buf[32];
 	return 0;
-#else
+#endif
+
+#if !defined(CONFIG_VSX) && !defined(CONFIG_PPC_TRANSACTIONAL_MEM)
 	BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
 		     offsetof(struct thread_fp_state, fpr[32][0]));
-
 	return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 				  &target->thread.fp_state, 0, -1);
+
 #endif
 }
 
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [V5 4/7] powerpc, ptrace: Enable vr_(get/set) for transactional memory
  2014-11-25  8:05 [V5 0/7] Add new powerpc specific ELF core notes Anshuman Khandual
                   ` (2 preceding siblings ...)
  2014-11-25  8:05 ` [V5 3/7] powerpc, ptrace: Enable fpr_(get/set) for transactional memory Anshuman Khandual
@ 2014-11-25  8:05 ` Anshuman Khandual
  2014-11-25  8:05 ` [V5 5/7] powerpc, ptrace: Enable support for transactional memory register sets Anshuman Khandual
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Anshuman Khandual @ 2014-11-25  8:05 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev
  Cc: peterz, akpm, tglx, james.hogan, avagin, Paul.Clothier, palves,
	oleg, dhowells, davej, davem, mikey, benh, sukadev, mpe,
	sam.bobroff, kirjanov, shuahkh

This patch enables the vr_get which gets the running value of all
the VMX registers and the vr_set which sets the running value of
of all the VMX registers to accommodate in transaction ptrace
interface based requests.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 arch/powerpc/kernel/ptrace.c | 94 ++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 91 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index fd36b32..2bbbd10 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -523,10 +523,30 @@ static int vr_active(struct task_struct *target,
 	return target->thread.used_vr ? regset->n : 0;
 }
 
+/*
+ * vr_get
+ *
+ * When the transaction is active, 'transact_vr' holds the current running
+ * value of all the VMX registers and 'vr_state' holds the last checkpointed
+ * value of all the VMX registers for the current transaction to fall back
+ * on in case it aborts. When transaction is not active 'vr_state' holds
+ * the current running state of all the VMX registers. So this function which
+ * gets the current running values of all the VMX registers, needs to know
+ * whether any transaction is active or not.
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct data {
+ *	vector128	vr[32];
+ *	vector128	vscr;
+ *	vector128	vrsave;
+ * };
+ */
 static int vr_get(struct task_struct *target, const struct user_regset *regset,
 		  unsigned int pos, unsigned int count,
 		  void *kbuf, void __user *ubuf)
 {
+	struct thread_vr_state *addr;
 	int ret;
 
 	flush_altivec_to_thread(target);
@@ -534,8 +554,19 @@ static int vr_get(struct task_struct *target, const struct user_regset *regset,
 	BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
 		     offsetof(struct thread_vr_state, vr[32]));
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+		flush_fp_to_thread(target);
+		flush_tmregs_to_thread(target);
+		addr = &target->thread.transact_vr;
+	} else {
+		addr = &target->thread.vr_state;
+	}
+#else
+	addr = &target->thread.vr_state;
+#endif
 	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-				  &target->thread.vr_state, 0,
+				  addr, 0,
 				  33 * sizeof(vector128));
 	if (!ret) {
 		/*
@@ -546,7 +577,16 @@ static int vr_get(struct task_struct *target, const struct user_regset *regset,
 			u32 word;
 		} vrsave;
 		memset(&vrsave, 0, sizeof(vrsave));
+
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+		if (MSR_TM_ACTIVE(target->thread.regs->msr))
+			vrsave.word = target->thread.transact_vrsave;
+		else
+			vrsave.word = target->thread.vrsave;
+#else
 		vrsave.word = target->thread.vrsave;
+#endif
+
 		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave,
 					  33 * sizeof(vector128), -1);
 	}
@@ -554,10 +594,30 @@ static int vr_get(struct task_struct *target, const struct user_regset *regset,
 	return ret;
 }
 
+/*
+ * vr_set
+ *
+ * When the transaction is active, 'transact_vr' holds the current running
+ * value of all the VMX registers and 'vr_state' holds the last checkpointed
+ * value of all the VMX registers for the current transaction to fall back
+ * on in case it aborts. When transaction is not active 'vr_state' holds
+ * the current running state of all the VMX registers. So this function which
+ * sets the current running values of all the VMX registers, needs to know
+ * whether any transaction is active or not.
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct data {
+ *	vector128	vr[32];
+ *	vector128	vscr;
+ *	vector128	vrsave;
+ * };
+ */
 static int vr_set(struct task_struct *target, const struct user_regset *regset,
 		  unsigned int pos, unsigned int count,
 		  const void *kbuf, const void __user *ubuf)
 {
+	struct thread_vr_state *addr;
 	int ret;
 
 	flush_altivec_to_thread(target);
@@ -565,8 +625,19 @@ static int vr_set(struct task_struct *target, const struct user_regset *regset,
 	BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
 		     offsetof(struct thread_vr_state, vr[32]));
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+		flush_fp_to_thread(target);
+		flush_tmregs_to_thread(target);
+		addr = &target->thread.transact_vr;
+	} else {
+		addr = &target->thread.vr_state;
+	}
+#else
+	addr = &target->thread.vr_state;
+#endif
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-				 &target->thread.vr_state, 0,
+				 addr, 0,
 				 33 * sizeof(vector128));
 	if (!ret && count > 0) {
 		/*
@@ -577,11 +648,28 @@ static int vr_set(struct task_struct *target, const struct user_regset *regset,
 			u32 word;
 		} vrsave;
 		memset(&vrsave, 0, sizeof(vrsave));
+
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+		if (MSR_TM_ACTIVE(target->thread.regs->msr))
+			vrsave.word = target->thread.transact_vrsave;
+		else
+			vrsave.word = target->thread.vrsave;
+#else
 		vrsave.word = target->thread.vrsave;
+#endif
 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave,
 					 33 * sizeof(vector128), -1);
-		if (!ret)
+		if (!ret) {
+
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+			if (MSR_TM_ACTIVE(target->thread.regs->msr))
+				target->thread.transact_vrsave = vrsave.word;
+			else
+				target->thread.vrsave = vrsave.word;
+#else
 			target->thread.vrsave = vrsave.word;
+#endif
+		}
 	}
 
 	return ret;
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [V5 5/7] powerpc, ptrace: Enable support for transactional memory register sets
  2014-11-25  8:05 [V5 0/7] Add new powerpc specific ELF core notes Anshuman Khandual
                   ` (3 preceding siblings ...)
  2014-11-25  8:05 ` [V5 4/7] powerpc, ptrace: Enable vr_(get/set) " Anshuman Khandual
@ 2014-11-25  8:05 ` Anshuman Khandual
  2014-11-25  8:05 ` [V5 6/7] powerpc, ptrace: Enable support for miscellaneous debug registers Anshuman Khandual
  2014-11-25  8:05 ` [V5 7/7] selftests, powerpc: Add test case for TM related ptrace interface Anshuman Khandual
  6 siblings, 0 replies; 10+ messages in thread
From: Anshuman Khandual @ 2014-11-25  8:05 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev
  Cc: peterz, akpm, tglx, james.hogan, avagin, Paul.Clothier, palves,
	oleg, dhowells, davej, davem, mikey, benh, sukadev, mpe,
	sam.bobroff, kirjanov, shuahkh

This patch enables get and set of transactional memory related register
sets through PTRACE_GETREGSET-PTRACE_SETREGSET interface by implementing
four new powerpc specific register sets i.e REGSET_TM_SPR, REGSET_TM_CGPR,
REGSET_TM_CFPR, REGSET_CVMX support corresponding to these following new
ELF core note types added previously in this regard.

	(1) NT_PPC_TM_SPR
	(2) NT_PPC_TM_CGPR
	(3) NT_PPC_TM_CFPR
	(4) NT_PPC_TM_CVMX

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 arch/powerpc/include/uapi/asm/elf.h |   2 +
 arch/powerpc/kernel/ptrace.c        | 667 +++++++++++++++++++++++++++++++++++-
 2 files changed, 654 insertions(+), 15 deletions(-)

diff --git a/arch/powerpc/include/uapi/asm/elf.h b/arch/powerpc/include/uapi/asm/elf.h
index 59dad11..fdc8e2f 100644
--- a/arch/powerpc/include/uapi/asm/elf.h
+++ b/arch/powerpc/include/uapi/asm/elf.h
@@ -91,6 +91,8 @@
 
 #define ELF_NGREG	48	/* includes nip, msr, lr, etc. */
 #define ELF_NFPREG	33	/* includes fpscr */
+#define ELF_NVMX	34	/* includes all vector registers */
+#define ELF_NTMSPRREG	7	/* includes TM sprs, org_msr, dscr, tar, ppr */
 
 typedef unsigned long elf_greg_t64;
 typedef elf_greg_t64 elf_gregset_t64[ELF_NGREG];
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 2bbbd10..faa9058 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -63,6 +63,11 @@ struct pt_regs_offset {
 	{.name = STR(gpr##num), .offset = offsetof(struct pt_regs, gpr[num])}
 #define REG_OFFSET_END {.name = NULL, .offset = 0}
 
+/* Some common structure offsets */
+#define TSO(f)	(offsetof(struct thread_struct, f))
+#define TVSO(f)	(offsetof(struct thread_vr_state, f))
+#define TFSO(f)	(offsetof(struct thread_fp_state, f))
+
 static const struct pt_regs_offset regoffset_table[] = {
 	GPR_OFFSET_NAME(0),
 	GPR_OFFSET_NAME(1),
@@ -792,6 +797,532 @@ static int evr_set(struct task_struct *target, const struct user_regset *regset,
 }
 #endif /* CONFIG_SPE */
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+/*
+ * tm_spr_active
+ *
+ * This function checks number of available regisers in
+ * the transactional memory SPR category.
+ */
+static int tm_spr_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_spr_get
+ *
+ * This function gets transactional memory related SPR registers
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct {
+ *	u64		tm_tfhar;
+ *	u64		tm_texasr;
+ *	u64		tm_tfiar;
+ *	unsigned long	tm_orig_msr;
+ *	unsigned long	tm_tar;
+ *	unsigned long	tm_ppr;
+ *	unsigned long	tm_dscr;
+ * };
+ */
+static int tm_spr_get(struct task_struct *target,
+		      const struct user_regset *regset,
+		      unsigned int pos, unsigned int count,
+		      void *kbuf, void __user *ubuf)
+{
+	int ret;
+
+	/* Build tests */
+	BUILD_BUG_ON(TSO(tm_tfhar) + sizeof(u64) != TSO(tm_texasr));
+	BUILD_BUG_ON(TSO(tm_texasr) + sizeof(u64) != TSO(tm_tfiar));
+	BUILD_BUG_ON(TSO(tm_tfiar) + sizeof(u64) != TSO(tm_orig_msr));
+	BUILD_BUG_ON(TSO(ckpt_regs) + sizeof(struct pt_regs) != TSO(tm_tar));
+	BUILD_BUG_ON(TSO(tm_tar) + sizeof(unsigned long) != TSO(tm_ppr));
+	BUILD_BUG_ON(TSO(tm_ppr) + sizeof(unsigned long) != TSO(tm_dscr));
+
+	if (!cpu_has_feature(CPU_FTR_TM))
+		return -ENODEV;
+
+	if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+		return -ENODATA;
+
+	/* Flush the states */
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmregs_to_thread(target);
+
+	/* TFHAR register */
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_tfhar, 0, sizeof(u64));
+
+	/* TEXASR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_texasr, sizeof(u64),
+				2 * sizeof(u64));
+
+	/* TFIAR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_tfiar,
+				2 * sizeof(u64), 3 * sizeof(u64));
+
+	/* TM checkpointed original MSR */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_orig_msr, 3 * sizeof(u64),
+				3 * sizeof(u64) + sizeof(unsigned long));
+
+	/* TM checkpointed TAR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_tar, 3 * sizeof(u64) +
+				sizeof(unsigned long) ,
+				3 * sizeof(u64) + 2 * sizeof(unsigned long));
+
+	/* TM checkpointed PPR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_ppr, 3 * sizeof(u64) +
+				2 * sizeof(unsigned long),
+				3 * sizeof(u64) + 3 * sizeof(unsigned long));
+
+	/* TM checkpointed DSCR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_dscr, 3 * sizeof(u64) +
+				3 * sizeof(unsigned long),
+				3 * sizeof(u64) + 4 * sizeof(unsigned long));
+	return ret;
+}
+
+/*
+ * tm_spr_set
+ *
+ * This function sets transactional memory related SPR registers
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct {
+ *	u64		tm_tfhar;
+ *	u64		tm_texasr;
+ *	u64		tm_tfiar;
+ *	unsigned long	tm_orig_msr;
+ *	unsigned long	tm_tar;
+ *	unsigned long	tm_ppr;
+ *	unsigned long	tm_dscr;
+ * };
+ */
+static int tm_spr_set(struct task_struct *target,
+		      const struct user_regset *regset,
+		      unsigned int pos, unsigned int count,
+		      const void *kbuf, const void __user *ubuf)
+{
+	int ret;
+
+	/* Build tests */
+	BUILD_BUG_ON(TSO(tm_tfhar) + sizeof(u64) != TSO(tm_texasr));
+	BUILD_BUG_ON(TSO(tm_texasr) + sizeof(u64) != TSO(tm_tfiar));
+	BUILD_BUG_ON(TSO(tm_tfiar) + sizeof(u64) != TSO(tm_orig_msr));
+	BUILD_BUG_ON(TSO(ckpt_regs) + sizeof(struct pt_regs) != TSO(tm_tar));
+	BUILD_BUG_ON(TSO(tm_tar) + sizeof(unsigned long) != TSO(tm_ppr));
+	BUILD_BUG_ON(TSO(tm_ppr) + sizeof(unsigned long) != TSO(tm_dscr));
+
+	if (!cpu_has_feature(CPU_FTR_TM))
+		return -ENODEV;
+
+	if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+		return -ENODATA;
+
+	/* Flush the states */
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmregs_to_thread(target);
+
+	/* TFHAR register */
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_tfhar, 0, sizeof(u64));
+
+	/* TEXASR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_texasr, sizeof(u64),
+				2 * sizeof(u64));
+
+	/* TFIAR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_tfiar,
+				 2 * sizeof(u64), 3 * sizeof(u64));
+
+
+	/* TM checkpointed orig MSR */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_orig_msr, 3 * sizeof(u64),
+				3 * sizeof(u64) + sizeof(unsigned long));
+
+
+	/* TM checkpointed TAR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_tar, 3 * sizeof(u64) +
+				sizeof(unsigned long), 3 * sizeof(u64) +
+				2 * sizeof(unsigned long));
+
+	/* TM checkpointed PPR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_ppr, 3 * sizeof(u64) +
+				2 * sizeof(unsigned long), 3 * sizeof(u64) +
+				3 * sizeof(unsigned long));
+
+	/* TM checkpointed DSCR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_dscr, 3 * sizeof(u64) +
+				3 * sizeof(unsigned long), 3 * sizeof(u64) +
+				4 * sizeof(unsigned long));
+	return ret;
+}
+
+/*
+ * tm_cgpr_active
+ *
+ * This function checks the number of available regisers in
+ * transaction checkpointed GPR category.
+ */
+static int tm_cgpr_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_cgpr_get
+ *
+ * This function gets transaction checkpointed GPR registers
+ *
+ * When the transaction is active, 'ckpt_regs' holds all the checkpointed
+ * GPR register values for the current transaction to fall back on if it
+ * aborts in between. This function gets those checkpointed GPR registers.
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct data {
+ *	struct pt_regs ckpt_regs;
+ * };
+ */
+static int tm_cgpr_get(struct task_struct *target,
+			const struct user_regset *regset,
+			unsigned int pos, unsigned int count,
+			void *kbuf, void __user *ubuf)
+{
+	int ret;
+
+	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);
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+					&target->thread.ckpt_regs, 0,
+					sizeof(struct pt_regs));
+	return ret;
+}
+
+/*
+ * tm_cgpr_set
+ *
+ * This function sets in transaction checkpointed GPR registers
+ *
+ * When the transaction is active, 'ckpt_regs' holds the checkpointed
+ * GPR register values for the current transaction to fall back on if it
+ * aborts in between. This function sets those checkpointed GPR registers.
+ *
+ * Userspace intaerface buffer:
+ *
+ * struct data {
+ *	struct pt_regs ckpt_regs;
+ * };
+ */
+static int tm_cgpr_set(struct task_struct *target,
+			const struct user_regset *regset,
+			unsigned int pos, unsigned int count,
+			const void *kbuf, const void __user *ubuf)
+{
+	int ret;
+
+	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);
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+					&target->thread.ckpt_regs, 0,
+					sizeof(struct pt_regs));
+	return ret;
+}
+
+/*
+ * tm_cfpr_active
+ *
+ * This function checks 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
+ *
+ * This function gets in transaction checkpointed FPR registers
+ *
+ * When the transaction is active 'fp_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.
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct data {
+ *	u64	fpr[32];
+ *	u64	fpscr;
+ *};
+ */
+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;
+
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmregs_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);
+}
+
+/*
+ * tm_cfpr_set
+ *
+ * This function sets in transaction checkpointed FPR registers
+ *
+ * When the transaction is active 'fp_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.
+ *
+ * Userspace interface buffer layout:
+ *
+ * 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_FPR(i) = buf[i];
+	target->thread.fp_state.fpscr = buf[32];
+	return 0;
+}
+
+/*
+ * tm_cvmx_active
+ *
+ * This function checks the number of available regisers in
+ * checkpointed VMX category.
+ */
+static int tm_cvmx_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_cvmx_get
+ *
+ * This function gets in transaction checkpointed VMX registers
+ *
+ * When the transaction is active 'vr_state' and 'vr_save' hold
+ * the checkpointed values for the current transaction to fall
+ * back on if it aborts in between.
+ *
+ * User interface buffer:
+ *
+ * struct data {
+ *	vector128	vr[32];
+ *	vector128	vscr;
+ *	vector128	vrsave;
+ *};
+ */
+static int tm_cvmx_get(struct task_struct *target,
+			const struct user_regset *regset,
+			unsigned int pos, unsigned int count,
+			void *kbuf, void __user *ubuf)
+{
+	int ret;
+
+	BUILD_BUG_ON(TVSO(vscr) != TVSO(vr[32]));
+
+	if (!cpu_has_feature(CPU_FTR_TM))
+		return -ENODEV;
+
+	if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+		return -ENODATA;
+
+	/* Flush the state */
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmregs_to_thread(target);
+
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+					&target->thread.vr_state, 0,
+					33 * sizeof(vector128));
+	if (!ret) {
+		/*
+		 * Copy out only the low-order word of vrsave.
+		 */
+		union {
+			elf_vrreg_t reg;
+			u32 word;
+		} vrsave;
+		memset(&vrsave, 0, sizeof(vrsave));
+		vrsave.word = target->thread.vrsave;
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave,
+						33 * sizeof(vector128), -1);
+	}
+
+	return ret;
+}
+
+/*
+ * tm_cvmx_set
+ *
+ * This function sets in transaction checkpointed VMX registers
+ *
+ * When the transaction is active 'vr_state' and 'vr_save' hold
+ * the checkpointed values for the current transaction to fall
+ * back on if it aborts in between.
+ *
+ * Userspace interface buffer:
+ *
+ * struct data {
+ *	vector128	vr[32];
+ *	vector128	vscr;
+ *	vector128	vrsave;
+ *};
+ */
+static int tm_cvmx_set(struct task_struct *target,
+			const struct user_regset *regset,
+			unsigned int pos, unsigned int count,
+			const void *kbuf, const void __user *ubuf)
+{
+	int ret;
+
+	BUILD_BUG_ON(TVSO(vscr) != TVSO(vr[32]));
+
+	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);
+
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+					&target->thread.vr_state, 0,
+					33 * sizeof(vector128));
+	if (!ret && count > 0) {
+		/*
+		 * We use only the low-order word of vrsave.
+		 */
+		union {
+			elf_vrreg_t reg;
+			u32 word;
+		} vrsave;
+		memset(&vrsave, 0, sizeof(vrsave));
+		vrsave.word = target->thread.vrsave;
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave,
+						33 * sizeof(vector128), -1);
+		if (!ret)
+			target->thread.vrsave = vrsave.word;
+	}
+
+	return ret;
+}
+#endif	/* CONFIG_PPC_TRANSACTIONAL_MEM */
 
 /*
  * These are our native regset flavors.
@@ -808,6 +1339,12 @@ enum powerpc_regset {
 #ifdef CONFIG_SPE
 	REGSET_SPE,
 #endif
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	REGSET_TM_SPR,		/* TM specific SPR registers */
+	REGSET_TM_CGPR,		/* TM checkpointed GPR registers */
+	REGSET_TM_CFPR,		/* TM checkpointed FPR registers */
+	REGSET_TM_CVMX,		/* TM checkpointed VMX registers */
+#endif
 };
 
 static const struct user_regset native_regsets[] = {
@@ -842,6 +1379,28 @@ static const struct user_regset native_regsets[] = {
 		.active = evr_active, .get = evr_get, .set = evr_set
 	},
 #endif
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	[REGSET_TM_SPR] = {
+		.core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG,
+		.size = sizeof(u64), .align = sizeof(u64),
+		.active = tm_spr_active, .get = tm_spr_get, .set = tm_spr_set
+	},
+	[REGSET_TM_CGPR] = {
+		.core_note_type = NT_PPC_TM_CGPR, .n = ELF_NGREG,
+		.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
+	},
+	[REGSET_TM_CVMX] = {
+		.core_note_type = NT_PPC_TM_CVMX, .n = ELF_NVMX,
+		.size = sizeof(vector128), .align = sizeof(vector128),
+		.active = tm_cvmx_active, .get = tm_cvmx_get, .set = tm_cvmx_set
+	},
+#endif
 };
 
 static const struct user_regset_view user_ppc_native_view = {
@@ -852,26 +1411,38 @@ static const struct user_regset_view user_ppc_native_view = {
 #ifdef CONFIG_PPC64
 #include <linux/compat.h>
 
-static int gpr32_get(struct task_struct *target,
+static int common_gpr32_get(struct task_struct *target,
 		     const struct user_regset *regset,
 		     unsigned int pos, unsigned int count,
-		     void *kbuf, void __user *ubuf)
+			    void *kbuf, void __user *ubuf, bool in_tm)
 {
-	const unsigned long *regs = &target->thread.regs->gpr[0];
+	const unsigned long *regs = NULL;
 	compat_ulong_t *k = kbuf;
 	compat_ulong_t __user *u = ubuf;
 	compat_ulong_t reg;
 	int i;
 
-	if (target->thread.regs == NULL)
-		return -EIO;
+	if (in_tm) {
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+		regs = &target->thread.ckpt_regs.gpr[0];
+#endif
+	} else {
+		regs = &target->thread.regs->gpr[0];
 
-	if (!FULL_REGS(target->thread.regs)) {
-		/* We have a partial register set.  Fill 14-31 with bogus values */
-		for (i = 14; i < 32; i++)
-			target->thread.regs->gpr[i] = NV_REG_POISON; 
+		if (target->thread.regs == NULL)
+			return -EIO;
+
+		if (!FULL_REGS(target->thread.regs)) {
+			/*
+			 * We have a partial register set.
+			 * Fill 14-31 with bogus values.
+			 */
+			for (i = 14; i < 32; i++)
+				target->thread.regs->gpr[i] = NV_REG_POISON;
+		}
 	}
 
+	BUG_ON(!regs);
 	pos /= sizeof(reg);
 	count /= sizeof(reg);
 
@@ -909,21 +1480,30 @@ static int gpr32_get(struct task_struct *target,
 					PT_REGS_COUNT * sizeof(reg), -1);
 }
 
-static int gpr32_set(struct task_struct *target,
+static int common_gpr32_set(struct task_struct *target,
 		     const struct user_regset *regset,
 		     unsigned int pos, unsigned int count,
-		     const void *kbuf, const void __user *ubuf)
+		     const void *kbuf, const void __user *ubuf, bool in_tm)
 {
-	unsigned long *regs = &target->thread.regs->gpr[0];
+	unsigned long *regs = NULL;
 	const compat_ulong_t *k = kbuf;
 	const compat_ulong_t __user *u = ubuf;
 	compat_ulong_t reg;
 
-	if (target->thread.regs == NULL)
-		return -EIO;
+	if (in_tm) {
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+		regs = &target->thread.ckpt_regs.gpr[0];
+#endif
+	} else {
+		regs = &target->thread.regs->gpr[0];
 
-	CHECK_FULL_REGS(target->thread.regs);
+		if (target->thread.regs == NULL)
+			return -EIO;
 
+		CHECK_FULL_REGS(target->thread.regs);
+	}
+
+	BUG_ON(!regs);
 	pos /= sizeof(reg);
 	count /= sizeof(reg);
 
@@ -982,6 +1562,40 @@ static int gpr32_set(struct task_struct *target,
 					 (PT_TRAP + 1) * sizeof(reg), -1);
 }
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+static int tm_cgpr32_get(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     void *kbuf, void __user *ubuf)
+{
+	return common_gpr32_get(target, regset, pos, count, kbuf, ubuf, 1);
+}
+
+static int tm_cgpr32_set(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     const void *kbuf, const void __user *ubuf)
+{
+	return common_gpr32_set(target, regset, pos, count, kbuf, ubuf, 1);
+}
+#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
+
+static int gpr32_get(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     void *kbuf, void __user *ubuf)
+{
+	return common_gpr32_get(target, regset, pos, count, kbuf, ubuf, 0);
+}
+
+static int gpr32_set(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     const void *kbuf, const void __user *ubuf)
+{
+	return common_gpr32_set(target, regset, pos, count, kbuf, ubuf, 0);
+}
+
 /*
  * These are the regset flavors matching the CONFIG_PPC32 native set.
  */
@@ -1010,6 +1624,29 @@ static const struct user_regset compat_regsets[] = {
 		.active = evr_active, .get = evr_get, .set = evr_set
 	},
 #endif
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	[REGSET_TM_SPR] = {
+		.core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG,
+		.size = sizeof(u64), .align = sizeof(u64),
+		.active = tm_spr_active, .get = tm_spr_get, .set = tm_spr_set
+	},
+	[REGSET_TM_CGPR] = {
+		.core_note_type = NT_PPC_TM_CGPR, .n = ELF_NGREG,
+		.size = sizeof(long), .align = sizeof(long),
+		.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
+	},
+	[REGSET_TM_CVMX] = {
+		.core_note_type = NT_PPC_TM_CVMX, .n = ELF_NVMX,
+		.size = sizeof(vector128), .align = sizeof(vector128),
+		.active = tm_cvmx_active, .get = tm_cvmx_get, .set = tm_cvmx_set
+	},
+#endif
 };
 
 static const struct user_regset_view user_ppc_compat_view = {
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [V5 6/7] powerpc, ptrace: Enable support for miscellaneous debug registers
  2014-11-25  8:05 [V5 0/7] Add new powerpc specific ELF core notes Anshuman Khandual
                   ` (4 preceding siblings ...)
  2014-11-25  8:05 ` [V5 5/7] powerpc, ptrace: Enable support for transactional memory register sets Anshuman Khandual
@ 2014-11-25  8:05 ` Anshuman Khandual
  2014-11-25  8:05 ` [V5 7/7] selftests, powerpc: Add test case for TM related ptrace interface Anshuman Khandual
  6 siblings, 0 replies; 10+ messages in thread
From: Anshuman Khandual @ 2014-11-25  8:05 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev
  Cc: peterz, akpm, tglx, james.hogan, avagin, Paul.Clothier, palves,
	oleg, dhowells, davej, davem, mikey, benh, sukadev, mpe,
	sam.bobroff, kirjanov, shuahkh

This patch enables get and set of miscellaneous debug registers through
ptrace PTRACE_GETREGSET-PTRACE_SETREGSET interface by implementing new
powerpc specific register set REGSET_MISC support corresponding to the
new ELF core note NT_PPC_MISC added previously in this regard.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 arch/powerpc/include/uapi/asm/elf.h |   1 +
 arch/powerpc/kernel/ptrace.c        | 123 ++++++++++++++++++++++++++++++++++++
 2 files changed, 124 insertions(+)

diff --git a/arch/powerpc/include/uapi/asm/elf.h b/arch/powerpc/include/uapi/asm/elf.h
index fdc8e2f..a41bd98 100644
--- a/arch/powerpc/include/uapi/asm/elf.h
+++ b/arch/powerpc/include/uapi/asm/elf.h
@@ -93,6 +93,7 @@
 #define ELF_NFPREG	33	/* includes fpscr */
 #define ELF_NVMX	34	/* includes all vector registers */
 #define ELF_NTMSPRREG	7	/* includes TM sprs, org_msr, dscr, tar, ppr */
+#define ELF_NMISCREG	3	/* includes dscr, tar, ppr */
 
 typedef unsigned long elf_greg_t64;
 typedef elf_greg_t64 elf_gregset_t64[ELF_NGREG];
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index faa9058..61cc7ae 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -1324,6 +1324,114 @@ static int tm_cvmx_set(struct task_struct *target,
 }
 #endif	/* CONFIG_PPC_TRANSACTIONAL_MEM */
 
+#ifdef CONFIG_PPC64
+/*
+ * get_misc_dbg
+ *
+ * This function gets miscellaneous debug registers
+ * which includes DSCR, PPR and TAR.
+ *
+ * Userspace intarface buffer layout:
+ *
+ * struct {
+ *	unsigned long dscr;
+ *	unsigned long ppr;
+ *	unsigned long tar;
+ * };
+ *
+ * The data element 'tar' will be valid only if the
+ * kernel has CONFIG_PPC_BOOK3S_64 config option enabled.
+ */
+static int get_misc_dbg(struct task_struct *target,
+			const struct user_regset *regset, unsigned int pos,
+			unsigned int count, void *kbuf, void __user *ubuf)
+{
+	int ret;
+
+	/* Build test */
+	BUILD_BUG_ON(TSO(dscr) + 2 * sizeof(unsigned long) != TSO(ppr));
+
+#ifdef CONFIG_PPC_BOOK3S_64
+	BUILD_BUG_ON(TSO(ppr) + sizeof(unsigned long) != TSO(tar));
+#endif
+
+	/* DSCR register */
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+					&target->thread.dscr, 0,
+					sizeof(unsigned long));
+
+	/* PPR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+						&target->thread.ppr,
+						sizeof(unsigned long),
+						2 * sizeof(unsigned long));
+
+#ifdef CONFIG_PPC_BOOK3S_64
+	/* TAR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+						&target->thread.tar,
+						2 * sizeof(unsigned long),
+						3 * sizeof(unsigned long));
+#endif
+	return ret;
+}
+
+/*
+ * set_misc_dbg
+ *
+ * This function sets miscellaneous debug registers
+ * which includes DSCR, PPR and TAR.
+ *
+ * Userspace intarface buffer layout:
+ *
+ * struct {
+ *	unsigned long dscr;
+ *	unsigned long ppr;
+ *	unsigned long tar;
+ * };
+ *
+ * The data element 'tar' will be valid only if the
+ * kernel has CONFIG_PPC_BOOK3S_64 config option enabled.
+ */
+static int set_misc_dbg(struct task_struct *target,
+			const struct user_regset *regset, unsigned int pos,
+			unsigned int count, const void *kbuf,
+			const void __user *ubuf)
+{
+	int ret;
+
+	/* Build test */
+	BUILD_BUG_ON(TSO(dscr) + 2 * sizeof(unsigned long) != TSO(ppr));
+
+#ifdef CONFIG_PPC_BOOK3S_64
+	BUILD_BUG_ON(TSO(ppr) + sizeof(unsigned long) != TSO(tar));
+#endif
+
+	/* DSCR register */
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+					&target->thread.dscr, 0,
+					sizeof(unsigned long));
+
+	/* PPR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+						&target->thread.ppr,
+						sizeof(unsigned long),
+						2 * sizeof(unsigned long));
+#ifdef CONFIG_PPC_BOOK3S_64
+	/* TAR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+						&target->thread.tar,
+						2 * sizeof(unsigned long),
+						3 * sizeof(unsigned long));
+#endif
+	return ret;
+}
+#endif /* CONFIG_PPC64 */
+
 /*
  * These are our native regset flavors.
  */
@@ -1345,6 +1453,9 @@ enum powerpc_regset {
 	REGSET_TM_CFPR,		/* TM checkpointed FPR registers */
 	REGSET_TM_CVMX,		/* TM checkpointed VMX registers */
 #endif
+#ifdef CONFIG_PPC64
+	REGSET_MISC		/* Miscellaneous debug registers */
+#endif
 };
 
 static const struct user_regset native_regsets[] = {
@@ -1401,6 +1512,13 @@ static const struct user_regset native_regsets[] = {
 		.active = tm_cvmx_active, .get = tm_cvmx_get, .set = tm_cvmx_set
 	},
 #endif
+#ifdef CONFIG_PPC64
+	[REGSET_MISC] = {
+		.core_note_type = NT_PPC_MISC, .n = ELF_NMISCREG,
+		.size = sizeof(u64), .align = sizeof(u64),
+		.get = get_misc_dbg, .set = set_misc_dbg
+	},
+#endif
 };
 
 static const struct user_regset_view user_ppc_native_view = {
@@ -1647,6 +1765,11 @@ static const struct user_regset compat_regsets[] = {
 		.active = tm_cvmx_active, .get = tm_cvmx_get, .set = tm_cvmx_set
 	},
 #endif
+	[REGSET_MISC] = {
+		.core_note_type = NT_PPC_MISC, .n = ELF_NMISCREG,
+		.size = sizeof(u64), .align = sizeof(u64),
+		.get = get_misc_dbg, .set = set_misc_dbg
+	},
 };
 
 static const struct user_regset_view user_ppc_compat_view = {
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [V5 7/7] selftests, powerpc: Add test case for TM related ptrace interface
  2014-11-25  8:05 [V5 0/7] Add new powerpc specific ELF core notes Anshuman Khandual
                   ` (5 preceding siblings ...)
  2014-11-25  8:05 ` [V5 6/7] powerpc, ptrace: Enable support for miscellaneous debug registers Anshuman Khandual
@ 2014-11-25  8:05 ` Anshuman Khandual
  2014-11-25 17:06   ` Shuah Khan
  6 siblings, 1 reply; 10+ messages in thread
From: Anshuman Khandual @ 2014-11-25  8:05 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev
  Cc: peterz, akpm, tglx, james.hogan, avagin, Paul.Clothier, palves,
	oleg, dhowells, davej, davem, mikey, benh, sukadev, mpe,
	sam.bobroff, kirjanov, shuahkh

This patch adds one more test case called 'tm-ptrace' targeting TM
related ptrace interface. This test creates one child process to
run some basic TM transactions and the parent process attaches the
child to do some ptrace probing using the recently added regset
interfaces. The parent process then compares the received values
against the expected values to verify whether it has passed the
given test or not.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 tools/testing/selftests/powerpc/tm/Makefile    |   2 +-
 tools/testing/selftests/powerpc/tm/tm-ptrace.c | 542 +++++++++++++++++++++++++
 2 files changed, 543 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/powerpc/tm/tm-ptrace.c

diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
index 2cede23..71d400a 100644
--- a/tools/testing/selftests/powerpc/tm/Makefile
+++ b/tools/testing/selftests/powerpc/tm/Makefile
@@ -1,4 +1,4 @@
-PROGS := tm-resched-dscr
+PROGS := tm-resched-dscr tm-ptrace
 
 all: $(PROGS)
 
diff --git a/tools/testing/selftests/powerpc/tm/tm-ptrace.c b/tools/testing/selftests/powerpc/tm/tm-ptrace.c
new file mode 100644
index 0000000..7a6c7d3
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-ptrace.c
@@ -0,0 +1,542 @@
+/*
+ * Test program for TM ptrace interface
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Copyright 2014 IBM Corporation
+ *
+ * Author: Anshuman Khandual <khandual@linux.vnet.ibm.com>
+ */
+#include <inttypes.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+#include <errno.h>
+#include <sys/ptrace.h>
+#include <sys/uio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/signal.h>
+#include <sys/user.h>
+#include <linux/elf.h>
+#include <linux/types.h>
+
+#include "utils.h"
+
+#define TEST_PASS 0
+#define TEST_FAIL 1
+
+#define MAX_STR_LENGTH 100
+
+/* ELF core notes */
+#define NT_PPC_TM_SPR  0x103	/* PowerPC TM special registers */
+#define NT_PPC_TM_CGPR 0x104	/* PowerpC TM checkpointed GPR */
+#define NT_PPC_TM_CFPR 0x105	/* PowerPC TM checkpointed FPR */
+#define NT_PPC_TM_CVMX 0x106	/* PowerPC TM checkpointed VMX */
+#define NT_PPC_MISC    0x107	/* PowerPC miscellaneous registers */
+
+/* TM instructions */
+#define TBEGIN		".long 0x7C00051D ;"
+#define TEND		".long 0x7C00055D ;"
+
+/* SPR number */
+#define SPRN_DSCR	3
+#define SPRN_TAR	815
+#define SPRN_PPR	896
+
+#define C_DSCR	10		/* TM checkpointed DSCR */
+#define C_TAR	20		/* TM checkpointed TAR */
+#define C_PPR	0x8000000000000	/* TM checkpointed PPR */
+
+#define DSCR	50		/* TM running DSCR */
+#define TAR	60		/* TM running TAR */
+#define PPR	0x4000000000000	/* TM running PPR */
+
+/* Values for GPR-FPR[0..31] */
+#define VAL0	0
+#define VAL1	1
+#define VAL2	2
+#define VAL3	3
+#define VAL4	4
+#define VAL5	5
+#define VAL6	6
+#define VAL7	7
+#define VAL8	8
+#define VAL9	9
+#define VAL10	10
+#define VAL11	11
+#define VAL12	12
+#define VAL13	13
+#define VAL14	14
+#define VAL15	15
+#define VAL_MAX	16
+
+/* Standard data types */
+typedef unsigned int u32;
+typedef __vector128 vector128;
+
+/* NT_PPC_TM_SPR buffer layout */
+struct tm_spr_regs {
+	u64	tm_tfhar;
+	u64	tm_texasr;
+	u64	tm_tfiar;
+	u64	tm_orig_msr;
+	u64	tm_tar;
+	u64	tm_ppr;
+	u64	tm_dscr;
+};
+
+/*
+ * NT_PPC_TM_CGPR buffer layout
+ *
+ * Same as that of struct pt_regs
+ */
+
+/* NT_PPC_TM_CFPR buffer layout */
+struct tm_cfpr {
+	u64	fpr[32];
+	u64	fpscr;
+};
+
+/* NT_PPC_TM_CVMX buffer layout */
+struct tm_cvmx {
+	vector128	vr[32] __attribute__((aligned(16)));
+	vector128	vscr __attribute__((aligned(16)));
+	u32		vrsave;
+};
+
+/* NT_PPC_MISC buffer layout */
+struct misc_regs {
+	u64	dscr;
+	u64	ppr;
+	u64	tar;
+};
+
+/*
+ * do_tm_transaction
+ *
+ * This functions sets the values for TAR, DSCR, PPR, GPR[0..31],
+ * FPR[0..31] registers before starting the trasanction which will
+ * enable the kernel to save them as checkpointed values. Then it
+ * starts the transaction where it loads a different set of values
+ * into the same registers again thus enabling the kernel to save
+ * them off as running values for this transaction. Then the function
+ * gets stuck forcing the process to loop at one single instruction.
+ * The transaction never finishes, thus giving the parent process
+ * the opportunity to trace the running and checkpointed values of
+ * various registers.
+ */
+void do_tm_transaction(void)
+{
+	asm __volatile__(
+		/* TM checkpointed values */
+
+		/* SPR */
+		"li 0, %[c_tar];"	/* TAR */
+		"mtspr %[sprn_tar], 0;"
+		"li 0, %[c_dscr];"	/* DSCR */
+		"mtspr %[sprn_dscr], 0;"
+		"or	1,1,1;"		/* PPR (0x8000000000000) */
+
+		/* GPR[0..31] */
+		"li 0, %[val0];"	/* GPR[0] */
+		"li 1, %[val1];"	/* GPR[1] */
+		"li 2, %[val2];"	/* GPR[2] */
+		"li 3, %[val3];"	/* GPR[3] */
+		"li 4, %[val4];"	/* GPR[4] */
+		"li 5, %[val5];"	/* GPR[5] */
+		"li 6, %[val6];"	/* GPR[6] */
+		"li 7, %[val7];"	/* GPR[7] */
+		"li 8, %[val8];"	/* GPR[8] */
+		"li 9, %[val9];"	/* GPR[9] */
+		"li 10, %[val10];"	/* GPR[10] */
+		"li 11, %[val11];"	/* GPR[11] */
+		"li 12, %[val12];"	/* GPR[12] */
+		"li 13, %[val13];"	/* GPR[13] */
+		"li 14, %[val14];"	/* GPR[14] */
+		"li 15, %[val15];"	/* GPR[15] */
+		"li 16, %[val0];"	/* GPR[16] */
+		"li 17, %[val1];"	/* GPR[17] */
+		"li 18, %[val2];"	/* GPR[18] */
+		"li 19, %[val3];"	/* GPR[19] */
+		"li 20, %[val4];"	/* GPR[20] */
+		"li 21, %[val5];"	/* GPR[21] */
+		"li 22, %[val6];"	/* GPR[22] */
+		"li 23, %[val7];"	/* GPR[23] */
+		"li 24, %[val8];"	/* GPR[24] */
+		"li 25, %[val9];"	/* GPR[25] */
+		"li 26, %[val10];"	/* GPR[26] */
+		"li 27, %[val11];"	/* GPR[27] */
+		"li 28, %[val12];"	/* GPR[28] */
+		"li 29, %[val13];"	/* GPR[29] */
+		"li 30, %[val14];"	/* GPR[30] */
+		"li 31, %[val15];"	/* GPR[31] */
+
+		/* FPR[0..31] */
+		".long 0x7C000166;"	/* GPR[0] --> FPR[0] */
+		".long 0x7C210166;"	/* GPR[1] --> FPR[1] */
+		".long 0x7C420166;"	/* GPR[0] --> FPR[2] */
+		".long 0x7C630166;"	/* GPR[3] --> FPR[3] */
+		".long 0x7C840166;"	/* GPR[4] --> FPR[4] */
+		".long 0x7CA50166;"	/* GPR[5] --> FPR[5] */
+		".long 0x7CC60166;"	/* GPR[6] --> FPR[6] */
+		".long 0x7CE70166;"	/* GPR[7] --> FPR[7] */
+		".long 0x7D080166;"	/* GPR[8] --> FPR[8] */
+		".long 0x7D290166;"	/* GPR[9] --> FPR[9] */
+		".long 0x7d4a0166;"	/* GPR[10] --> FPR[10] */
+		".long 0x7d6b0166;"	/* GPR[11] --> FPR[11] */
+		".long 0x7d8c0166;"	/* GPR[12] --> FPR[12] */
+		".long 0x7dad0166;"	/* GPR[13] --> FPR[13] */
+		".long 0x7dce0166;"	/* GPR[14] --> FPR[14] */
+		".long 0x7def0166;"	/* GPR[15] --> FPR[15] */
+		".long 0x7e100166;"	/* GPR[16] --> FPR[16] */
+		".long 0x7e310166;"	/* GPR[17] --> FPR[17] */
+		".long 0x7e520166;"	/* GPR[18] --> FPR[18] */
+		".long 0x7e730166;"	/* GPR[19] --> FPR[19] */
+		".long 0x7e940166;"	/* GPR[20] --> FPR[20] */
+		".long 0x7eb50166;"	/* GPR[21] --> FPR[21] */
+		".long 0x7ed60166;"	/* GPR[22] --> FPR[22] */
+		".long 0x7ef70166;"	/* GPR[23] --> FPR[23] */
+		".long 0x7f180166;"	/* GPR[24] --> FPR[24] */
+		".long 0x7f390166;"	/* GPR[25] --> FPR[25] */
+		".long 0x7f5a0166;"	/* GPR[26] --> FPR[26] */
+		".long 0x7f7b0166;"	/* GPR[27] --> FPR[27] */
+		".long 0x7f9c0166;"	/* GPR[28] --> FPR[28] */
+		".long 0x7fbd0166;"	/* GPR[29] --> FPR[29] */
+		".long 0x7fde0166;"	/* GPR[30] --> FPR[30] */
+		".long 0x7fff0166;"	/* GPR[31] --> FPR[31] */
+
+		/* TM running values */
+
+		"1: ;"
+		TBEGIN
+		"beq 2f;"
+
+		/* SPR */
+		"li 0, %[tar];"		/* TAR */
+		"mtspr %[sprn_tar], 0;"
+		"li 0, %[dscr];"	/* DSCR */
+		"mtspr %[sprn_dscr], 0;"
+		"or	31,31,31;"	/* PPR (0x4000000000000) */
+
+		/* GPR[0..31] */
+		"li 0, %[val15];"	/* GPR[0] */
+		"li 1, %[val14];"	/* GPR[1] */
+		"li 2, %[val13];"	/* GPR[2] */
+		"li 3, %[val12];"	/* GPR[3] */
+		"li 4, %[val11];"	/* GPR[4] */
+		"li 5, %[val10];"	/* GPR[5] */
+		"li 6, %[val9];"	/* GPR[6] */
+		"li 7, %[val8];"	/* GPR[7] */
+		"li 8, %[val7];"	/* GPR[8] */
+		"li 9, %[val6];"	/* GPR[9] */
+		"li 10, %[val5];"	/* GPR[10] */
+		"li 11, %[val4];"	/* GPR[11] */
+		"li 12, %[val3];"	/* GPR[12] */
+		"li 13, %[val2];"	/* GPR[13] */
+		"li 14, %[val1];"	/* GPR[14] */
+		"li 15, %[val0];"	/* GPR[15] */
+		"li 16, %[val15];"	/* GPR[16] */
+		"li 17, %[val14];"	/* GPR[17] */
+		"li 18, %[val13];"	/* GPR[18] */
+		"li 19, %[val12];"	/* GPR[19] */
+		"li 20, %[val11];"	/* GPR[20] */
+		"li 21, %[val10];"	/* GPR[21] */
+		"li 22, %[val9];"	/* GPR[22] */
+		"li 23, %[val8];"	/* GPR[23] */
+		"li 24, %[val7];"	/* GPR[24] */
+		"li 25, %[val6];"	/* GPR[25] */
+		"li 26, %[val5];"	/* GPR[26] */
+		"li 27, %[val4];"	/* GPR[27] */
+		"li 28, %[val3];"	/* GPR[28] */
+		"li 29, %[val2];"	/* GPR[29] */
+		"li 30, %[val1];"	/* GPR[30] */
+		"li 31, %[val0];"	/* GPR[31] */
+
+		/* FPR[0..31] */
+		".long 0x7C000166;"	/* GPR[0] --> FPR[0] */
+		".long 0x7C210166;"	/* GPR[1] --> FPR[1] */
+		".long 0x7C420166;"	/* GPR[2] --> FPR[2] */
+		".long 0x7C630166;"	/* GPR[3] --> FPR[3] */
+		".long 0x7C840166;"	/* GPR[4] --> FPR[4] */
+		".long 0x7CA50166;"	/* GPR[5] --> FPR[5] */
+		".long 0x7CC60166;"	/* GPR[6] --> FPR[6] */
+		".long 0x7CE70166;"	/* GPR[7] --> FPR[7] */
+		".long 0x7D080166;"	/* GPR[8] --> FPR[8] */
+		".long 0x7D290166;"	/* GPR[9] --> FPR[9] */
+		".long 0x7d4a0166;"	/* GPR[10] --> FPR[10] */
+		".long 0x7d6b0166;"	/* GPR[11] --> FPR[11] */
+		".long 0x7d8c0166;"	/* GPR[12] --> FPR[12] */
+		".long 0x7dad0166;"	/* GPR[13] --> FPR[13] */
+		".long 0x7dce0166;"	/* GPR[14] --> FPR[14] */
+		".long 0x7def0166;"	/* GPR[15] --> FPR[15] */
+		".long 0x7e100166;"	/* GPR[16] --> FPR[16] */
+		".long 0x7e310166;"	/* GPR[17] --> FPR[17] */
+		".long 0x7e520166;"	/* GPR[18] --> FPR[18] */
+		".long 0x7e730166;"	/* GPR[19] --> FPR[19] */
+		".long 0x7e940166;"	/* GPR[20] --> FPR[20] */
+		".long 0x7eb50166;"	/* GPR[21] --> FPR[21] */
+		".long 0x7ed60166;"	/* GPR[22] --> FPR[22] */
+		".long 0x7ef70166;"	/* GPR[23] --> FPR[23] */
+		".long 0x7f180166;"	/* GPR[24] --> FPR[24] */
+		".long 0x7f390166;"	/* GPR[25] --> FPR[25] */
+		".long 0x7f5a0166;"	/* GPR[26] --> FPR[26] */
+		".long 0x7f7b0166;"	/* GPR[27] --> FPR[27] */
+		".long 0x7f9c0166;"	/* GPR[28] --> FPR[28] */
+		".long 0x7fbd0166;"	/* GPR[29] --> FPR[29] */
+		".long 0x7fde0166;"	/* GPR[30] --> FPR[30] */
+		".long 0x7fff0166;"	/* GPR[31] --> FPR[31] */
+
+		"b .;"			/* Get stuck here */
+		TEND
+
+		/* Transaction abort handler */
+		"2: ;"
+		"b 1b;"			/* Start from TBEGIN */
+
+		:: [sprn_dscr]"i"(SPRN_DSCR), [sprn_tar]"i"(SPRN_TAR),
+		[sprn_ppr]"i"(SPRN_PPR), [val0]"i"(VAL0),
+		[val1]"i"(VAL1), [val2]"i"(VAL2), [val3]"i"(VAL3),
+		[val4]"i"(VAL4), [val5]"i"(VAL5), [val6]"i"(VAL6),
+		[val7]"i"(VAL7), [val8]"i"(VAL8), [val9]"i"(VAL9),
+		[val10]"i"(VAL10), [val11]"i"(VAL11), [val12]"i"(VAL12),
+		[val13]"i"(VAL13), [val14]"i"(VAL14), [val15]"i"(VAL15),
+		[c_tar]"i"(C_TAR), [c_dscr]"i"(C_DSCR), [tar]"i"(TAR),
+		[dscr]"i"(DSCR), [ppr]"i"(PPR), [c_ppr]"i"(C_PPR)
+		: "memory", "r7");
+}
+
+void test_result(const u64 variable, const u64 value, const char *str)
+{
+	if (variable == value)
+		printf("%s: %llx (PASSED)\n", str, variable);
+	else
+		printf("%s: %llx (FAILED)\n", str, variable);
+}
+
+int trace_tm_transaction(pid_t child)
+{
+	struct tm_spr_regs *tmspr;
+	struct pt_regs *cregs, *regs;
+	struct tm_cfpr *cfpr, *fpr;
+	struct misc_regs *mregs;
+	struct iovec iov;
+	char str[MAX_STR_LENGTH];
+	int ret, i, j;
+
+	regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
+	fpr = (struct tm_cfpr *) malloc(sizeof(struct tm_cfpr));
+
+	/* Wait till the tracee hits "b ." instruction */
+	sleep(3);
+
+	ret = ptrace(PTRACE_ATTACH, child, NULL, NULL);
+	if (ret) {
+		printf("ptrace(PTRACE_ATTACH) Failed: %s\n", strerror(errno));
+		return TEST_FAIL;
+	}
+
+	ret = waitpid(child, NULL, 0);
+	if (ret != child) {
+		printf("PID mismatch: %s\n", strerror(errno));
+		return TEST_FAIL;
+	}
+
+	/* TM specific SPR */
+	printf("Testing TM specific SPR:\n");
+	iov.iov_base = (struct tm_spr_regs *)
+				malloc(sizeof(struct tm_spr_regs));
+	iov.iov_len = sizeof(struct tm_spr_regs);
+	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_SPR, &iov);
+	if (ret) {
+		printf("ptrace(NT_PPC_TM_SPR) Failed: %s\n", strerror(errno));
+		return TEST_FAIL;
+	}
+
+	if (iov.iov_len != sizeof(struct tm_spr_regs)) {
+		printf("ptrace(NT_PPC_TM_SPR): Returned wrong length\n");
+		return TEST_FAIL;
+	}
+
+	tmspr = iov.iov_base;
+
+	printf("TFHAR: %llx\n", tmspr->tm_tfhar);
+	printf("TEXASR: %llx\n", tmspr->tm_texasr);
+	printf("TFIAR: %llx\n", tmspr->tm_tfiar);
+	printf("TM ORIG_MSR: %llx\n", tmspr->tm_orig_msr);
+
+	test_result(tmspr->tm_dscr, C_DSCR, "TM CH DSCR");
+	test_result(tmspr->tm_tar, C_TAR, "TM CH TAR");
+	test_result(tmspr->tm_ppr, C_PPR, "TM CH PPR");
+
+	/* TM checkpointed GPR */
+	printf("Testing TM checkpointed GPR:\n");
+	iov.iov_base = (struct pt_regs *) malloc(sizeof(struct pt_regs));
+	iov.iov_len = sizeof(struct pt_regs);
+	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CGPR, &iov);
+	if (ret) {
+		printf("ptrace(NT_PPC_TM_CGPR) Failed: %s\n", strerror(errno));
+		return TEST_FAIL;
+	}
+
+	if (iov.iov_len != sizeof(struct pt_regs)) {
+		printf("ptrace(NT_PPC_TM_CGPR): Returned wrong length\n");
+		return TEST_FAIL;
+	}
+
+	cregs = iov.iov_base;
+
+	printf("TM CH NIP: %lx\n", cregs->nip);
+	printf("TM CH LINK: %lx\n", cregs->link);
+	printf("TM CH CCR: %lx\n", cregs->ccr);
+
+	for (i = 0; i < VAL_MAX; i++) {
+		sprintf(str, "TM CH GPR[%d]", i);
+		test_result(cregs->gpr[i], i, str);
+	}
+
+	for (j = 0; i < VAL_MAX * 2; j++, i++) {
+		sprintf(str, "TM CH GPR[%d]", i);
+		test_result(cregs->gpr[i], j, str);
+	}
+
+	/* TM checkpointed FPR */
+	printf("Testing TM checkpointed FPR:\n");
+	iov.iov_base = (struct tm_cfpr *) malloc(sizeof(struct tm_cfpr));
+	iov.iov_len = sizeof(struct tm_cfpr);
+	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CFPR, &iov);
+	if (ret) {
+		printf("ptrace(NT_PPC_TM_CFPR) Failed: %s\n", strerror(errno));
+		return TEST_FAIL;
+	}
+
+	if (iov.iov_len != sizeof(struct tm_cfpr)) {
+		printf("ptrace(NT_PPC_TM_CFPR): Returned wrong length\n");
+		return TEST_FAIL;
+	}
+
+	cfpr = iov.iov_base;
+	printf("TM CH FPSCR: %llx\n", cfpr->fpscr);
+
+	for (i = 0; i < VAL_MAX; i++) {
+		sprintf(str, "TM CH FPR[%d]", i);
+		test_result(cfpr->fpr[i], i, str);
+	}
+
+	for (j = 0; i < VAL_MAX * 2; j++, i++) {
+		sprintf(str, "TM CH FPR[%d]", i);
+		test_result(cfpr->fpr[i], j, str);
+	}
+
+	/* TM running GPR */
+	printf("Testing TM running GPR:\n");
+	ret = ptrace(PTRACE_GETREGS, child, NULL, regs);
+	if (ret) {
+		printf("ptrace(PTRACE_GETREGS) Failed: %s\n", strerror(errno));
+		return TEST_FAIL;
+	}
+
+	printf("TM RN NIP: %lx\n", regs->nip);
+	printf("TM RN LINK: %lx\n", regs->link);
+	printf("TM RN CCR: %lx\n", regs->ccr);
+
+	for (i = 0, j = VAL_MAX - 1; i < VAL_MAX; i++, j--) {
+		sprintf(str, "TM RN GPR[%d]", i);
+		test_result(regs->gpr[i], j, str);
+	}
+
+	for (j = VAL_MAX - 1 ; i < VAL_MAX * 2; i++, j--) {
+		sprintf(str, "TM RN GPR[%d]", i);
+		test_result(regs->gpr[i], j, str);
+	}
+
+	/* TM running FPR */
+	printf("Testing TM running FPR:\n");
+	ret = ptrace(PTRACE_GETFPREGS, child, NULL, fpr);
+	if (ret) {
+		printf("ptrace(PTRACE_GETFPREGS) Failed: %s\n",
+							strerror(errno));
+		return TEST_FAIL;
+	}
+
+	printf("TM RN FPSCR: %llx\n", fpr->fpscr);
+
+	for (i = 0, j = VAL_MAX - 1; i < VAL_MAX; i++, j--) {
+		sprintf(str, "TM RN FPR[%d]", i);
+		test_result(fpr->fpr[i], j, str);
+	}
+
+	for (j = VAL_MAX - 1; i < VAL_MAX * 2; i++, j--) {
+		sprintf(str, "TM RN FPR[%d]", i);
+		test_result(fpr->fpr[i], j, str);
+	}
+
+	/* TM running MISC debug registers */
+	printf("Testing TM running MISC debug registers:\n");
+	iov.iov_base = (struct misc_regs *) malloc(sizeof(struct misc_regs));
+	iov.iov_len = sizeof(struct misc_regs);
+	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_MISC, &iov);
+	if (ret) {
+		printf("ptrace(NT_PPC_MISC): Failed: %s\n", strerror(errno));
+		return TEST_FAIL;
+	}
+
+	if (iov.iov_len != sizeof(struct misc_regs)) {
+		printf("ptrace(NT_PPC_TM_MISC): Returned wrong length\n");
+		return TEST_FAIL;
+	}
+
+	mregs = iov.iov_base;
+	test_result(mregs->dscr, DSCR, "TM RN DSCR");
+	test_result(mregs->tar, TAR, "TM RN TAR");
+	test_result(mregs->ppr, PPR, "TM RN PPR");
+
+	ret = ptrace(PTRACE_DETACH, child, NULL, NULL);
+	if (ret) {
+		printf("ptrace(PTRACE_DETACH) Failed: %s\n", strerror(errno));
+		return 1;
+	}
+
+	if (kill(child, SIGTERM)) {
+		printf("kill() Failed\n");
+		return TEST_FAIL;
+	}
+
+	ret = waitpid(child, NULL, 0);
+	if (ret != child) {
+		printf("PID mismatch: %s\n", strerror(errno));
+		return TEST_FAIL;
+	}
+	return TEST_PASS;
+}
+
+int tm_ptrace_test(void)
+{
+	pid_t child;
+
+	printf("===Testing TM based PTRACE Interface===\n");
+	fflush(stdout);
+	child = fork();
+	if (child < 0) {
+		printf("fork() Failed: %s\n", strerror(errno));
+		return TEST_FAIL;
+	}
+
+	/* Child to run the transaction */
+	if (child == 0)
+		do_tm_transaction();
+
+	/* Parent to trace the child */
+	if (child)
+		trace_tm_transaction(child);
+	return TEST_PASS;
+}
+
+int main(void)
+{
+	return test_harness(tm_ptrace_test, "tm_ptrace");
+}
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [V5 7/7] selftests, powerpc: Add test case for TM related ptrace interface
  2014-11-25  8:05 ` [V5 7/7] selftests, powerpc: Add test case for TM related ptrace interface Anshuman Khandual
@ 2014-11-25 17:06   ` Shuah Khan
  2014-11-26  5:10     ` Anshuman Khandual
  0 siblings, 1 reply; 10+ messages in thread
From: Shuah Khan @ 2014-11-25 17:06 UTC (permalink / raw)
  To: Anshuman Khandual, linux-kernel, linuxppc-dev
  Cc: peterz, akpm, tglx, james.hogan, avagin, Paul.Clothier, palves,
	oleg, dhowells, davej, davem, mikey, benh, sukadev, mpe,
	sam.bobroff, kirjanov

On 11/25/2014 01:05 AM, Anshuman Khandual wrote:
> This patch adds one more test case called 'tm-ptrace' targeting TM
> related ptrace interface. This test creates one child process to
> run some basic TM transactions and the parent process attaches the
> child to do some ptrace probing using the recently added regset
> interfaces. The parent process then compares the received values
> against the expected values to verify whether it has passed the
> given test or not.
> 
> Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
> ---
>  tools/testing/selftests/powerpc/tm/Makefile    |   2 +-
>  tools/testing/selftests/powerpc/tm/tm-ptrace.c | 542 +++++++++++++++++++++++++
>  2 files changed, 543 insertions(+), 1 deletion(-)
>  create mode 100644 tools/testing/selftests/powerpc/tm/tm-ptrace.c
> 
> diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
> index 2cede23..71d400a 100644
> --- a/tools/testing/selftests/powerpc/tm/Makefile
> +++ b/tools/testing/selftests/powerpc/tm/Makefile
> @@ -1,4 +1,4 @@
> -PROGS := tm-resched-dscr
> +PROGS := tm-resched-dscr tm-ptrace
>  

Could you please add .gitignore for the binaries in this directory
to avoid git status including the binaries it in its output.

thanks,
-- Shuah

-- 
Shuah Khan
Sr. Linux Kernel Developer
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [V5 7/7] selftests, powerpc: Add test case for TM related ptrace interface
  2014-11-25 17:06   ` Shuah Khan
@ 2014-11-26  5:10     ` Anshuman Khandual
  0 siblings, 0 replies; 10+ messages in thread
From: Anshuman Khandual @ 2014-11-26  5:10 UTC (permalink / raw)
  To: Shuah Khan, linux-kernel, linuxppc-dev
  Cc: peterz, akpm, tglx, james.hogan, avagin, Paul.Clothier, palves,
	oleg, dhowells, davej, davem, mikey, benh, sukadev, mpe,
	sam.bobroff, kirjanov

On 11/25/2014 10:36 PM, Shuah Khan wrote:
> On 11/25/2014 01:05 AM, Anshuman Khandual wrote:
>> > This patch adds one more test case called 'tm-ptrace' targeting TM
>> > related ptrace interface. This test creates one child process to
>> > run some basic TM transactions and the parent process attaches the
>> > child to do some ptrace probing using the recently added regset
>> > interfaces. The parent process then compares the received values
>> > against the expected values to verify whether it has passed the
>> > given test or not.
>> > 
>> > Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
>> > ---
>> >  tools/testing/selftests/powerpc/tm/Makefile    |   2 +-
>> >  tools/testing/selftests/powerpc/tm/tm-ptrace.c | 542 +++++++++++++++++++++++++
>> >  2 files changed, 543 insertions(+), 1 deletion(-)
>> >  create mode 100644 tools/testing/selftests/powerpc/tm/tm-ptrace.c
>> > 
>> > diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
>> > index 2cede23..71d400a 100644
>> > --- a/tools/testing/selftests/powerpc/tm/Makefile
>> > +++ b/tools/testing/selftests/powerpc/tm/Makefile
>> > @@ -1,4 +1,4 @@
>> > -PROGS := tm-resched-dscr
>> > +PROGS := tm-resched-dscr tm-ptrace
>> >  
> Could you please add .gitignore for the binaries in this directory
> to avoid git status including the binaries it in its output.

Sure, will add one.


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2014-11-26  5:10 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-25  8:05 [V5 0/7] Add new powerpc specific ELF core notes Anshuman Khandual
2014-11-25  8:05 ` [V5 1/7] elf: Add new powerpc specifc core note sections Anshuman Khandual
2014-11-25  8:05 ` [V5 2/7] powerpc, process: Add the function flush_tmregs_to_thread Anshuman Khandual
2014-11-25  8:05 ` [V5 3/7] powerpc, ptrace: Enable fpr_(get/set) for transactional memory Anshuman Khandual
2014-11-25  8:05 ` [V5 4/7] powerpc, ptrace: Enable vr_(get/set) " Anshuman Khandual
2014-11-25  8:05 ` [V5 5/7] powerpc, ptrace: Enable support for transactional memory register sets Anshuman Khandual
2014-11-25  8:05 ` [V5 6/7] powerpc, ptrace: Enable support for miscellaneous debug registers Anshuman Khandual
2014-11-25  8:05 ` [V5 7/7] selftests, powerpc: Add test case for TM related ptrace interface Anshuman Khandual
2014-11-25 17:06   ` Shuah Khan
2014-11-26  5:10     ` Anshuman Khandual

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).