[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20160727150517.26983-4-boqun.feng@gmail.com>
Date: Wed, 27 Jul 2016 23:05:17 +0800
From: Boqun Feng <boqun.feng@...il.com>
To: linux-kernel@...r.kernel.org, linux-api@...r.kernel.org
Cc: Mathieu Desnoyers <mathieu.desnoyers@...icios.com>,
Andrew Morton <akpm@...ux-foundation.org>,
Russell King <linux@....linux.org.uk>,
Thomas Gleixner <tglx@...utronix.de>,
Ingo Molnar <mingo@...hat.com>,
"H. Peter Anvin" <hpa@...or.com>, Paul Turner <pjt@...gle.com>,
Andrew Hunter <ahh@...gle.com>,
Peter Zijlstra <peterz@...radead.org>,
Andy Lutomirski <luto@...capital.net>,
Andi Kleen <andi@...stfloor.org>,
Dave Watson <davejwatson@...com>, Chris Lameter <cl@...ux.com>,
Ben Maurer <bmaurer@...com>,
Steven Rostedt <rostedt@...dmis.org>,
"Paul E. McKenney" <paulmck@...ux.vnet.ibm.com>,
Josh Triplett <josh@...htriplett.org>,
Linus Torvalds <torvalds@...ux-foundation.org>,
Michael Ellerman <mpe@...erman.id.au>,
Benjamin Herrenschmidt <benh@...nel.crashing.org>,
Paul Mackerras <paulus@...ba.org>,
Boqun Feng <boqun.feng@...il.com>
Subject: [RFC 4/4] Restartable sequences: Add self-tests for PPC
As rseq syscall is enabled on PPC, implement the self-tests on PPC to
verify the implementation of the syscall.
Please note we only support 32bit userspace on BE kernel.
Signed-off-by: Boqun Feng <boqun.feng@...il.com>
---
tools/testing/selftests/rseq/param_test.c | 14 ++++
tools/testing/selftests/rseq/rseq.h | 120 ++++++++++++++++++++++++++++++
2 files changed, 134 insertions(+)
diff --git a/tools/testing/selftests/rseq/param_test.c b/tools/testing/selftests/rseq/param_test.c
index db25e0a818e5..e2cb1b165f81 100644
--- a/tools/testing/selftests/rseq/param_test.c
+++ b/tools/testing/selftests/rseq/param_test.c
@@ -75,6 +75,20 @@ static __thread unsigned int yield_mod_cnt, nr_retry;
"bne 222b\n\t" \
"333:\n\t"
+#elif __PPC__
+#define INJECT_ASM_REG "r18"
+
+#define RSEQ_INJECT_CLOBBER \
+ , INJECT_ASM_REG
+
+#define RSEQ_INJECT_ASM(n) \
+ "lwz %%" INJECT_ASM_REG ", %[loop_cnt_" #n "]\n\t" \
+ "cmpwi %%" INJECT_ASM_REG ", 0\n\t" \
+ "beq 333f\n\t" \
+ "222:\n\t" \
+ "subic. %%" INJECT_ASM_REG ", %%" INJECT_ASM_REG ", 1\n\t" \
+ "bne 222b\n\t" \
+ "333:\n\t"
#else
#error unsupported target
#endif
diff --git a/tools/testing/selftests/rseq/rseq.h b/tools/testing/selftests/rseq/rseq.h
index 791e14cf42ae..dea0bea52566 100644
--- a/tools/testing/selftests/rseq/rseq.h
+++ b/tools/testing/selftests/rseq/rseq.h
@@ -138,6 +138,35 @@ do { \
#define has_fast_acquire_release() 0
#define has_single_copy_load_64() 1
+#elif __PPC__
+#define smp_mb() __asm__ __volatile__ ("sync" : : : "memory")
+#define smp_lwsync() __asm__ __volatile__ ("lwsync" : : : "memory")
+#define smp_rmb() smp_lwsync()
+#define smp_wmb() smp_lwsync()
+
+#define smp_load_acquire(p) \
+__extension__ ({ \
+ __typeof(*p) ____p1 = READ_ONCE(*p); \
+ smp_lwsync(); \
+ ____p1; \
+})
+
+#define smp_acquire__after_ctrl_dep() smp_lwsync()
+
+#define smp_store_release(p, v) \
+do { \
+ smp_lwsync(); \
+ WRITE_ONCE(*p, v); \
+} while (0)
+
+#define has_fast_acquire_release() 1
+
+# if __PPC64__
+# define has_single_copy_load_64() 1
+# else
+# define has_single_copy_load_64() 0
+# endif
+
#else
#error unsupported target
#endif
@@ -404,6 +433,97 @@ bool rseq_finish(struct rseq_lock *rlock,
: succeed
);
}
+#elif __PPC64__
+ {
+ /*
+ * The __rseq_table section can be used by debuggers to better
+ * handle single-stepping through the restartable critical
+ * sections.
+ */
+ __asm__ __volatile__ goto (
+ ".pushsection __rseq_table, \"aw\"\n\t"
+ ".balign 8\n\t"
+ "4:\n\t"
+ ".quad 1f, 2f, 3f\n\t"
+ ".popsection\n\t"
+ "1:\n\t"
+ RSEQ_INJECT_ASM(1)
+ "lis %%r17, (4b)@highest\n\t"
+ "ori %%r17, %%r17, (4b)@higher\n\t"
+ "rldicr %%r17, %%r17, 32, 31\n\t"
+ "oris %%r17, %%r17, (4b)@h\n\t"
+ "ori %%r17, %%r17, (4b)@l\n\t"
+ "std %%r17, 0(%[rseq_cs])\n\t"
+ RSEQ_INJECT_ASM(2)
+ "lwz %%r17, %[current_event_counter]\n\t"
+ "li %%r16, 0\n\t"
+ "cmpw cr7, %[start_event_counter], %%r17\n\t"
+ "bne cr7, 3f\n\t"
+ RSEQ_INJECT_ASM(3)
+ "std %[to_write], 0(%[target])\n\t"
+ "2:\n\t"
+ RSEQ_INJECT_ASM(4)
+ "std %%r16, 0(%[rseq_cs])\n\t"
+ "b %l[succeed]\n\t"
+ "3:\n\t"
+ "li %%r16, 0\n\t"
+ "std %%r16, 0(%[rseq_cs])\n\t"
+ : /* no outputs */
+ : [start_event_counter]"r"(start_value.event_counter),
+ [current_event_counter]"m"(start_value.rseqp->abi.u.e.event_counter),
+ [to_write]"r"(to_write),
+ [target]"b"(p),
+ [rseq_cs]"b"(&start_value.rseqp->abi.rseq_cs)
+ RSEQ_INJECT_INPUT
+ : "r16", "r17", "memory", "cc"
+ RSEQ_INJECT_CLOBBER
+ : succeed
+ );
+ }
+#elif __PPC__
+ {
+ /*
+ * The __rseq_table section can be used by debuggers to better
+ * handle single-stepping through the restartable critical
+ * sections.
+ */
+ __asm__ __volatile__ goto (
+ ".pushsection __rseq_table, \"aw\"\n\t"
+ ".balign 8\n\t"
+ "4:\n\t"
+ ".long 0x0, 1f, 0x0, 2f, 0x0, 3f\n\t" /* 32 bit only supported on BE */
+ ".popsection\n\t"
+ "1:\n\t"
+ RSEQ_INJECT_ASM(1)
+ "lis %%r17, (4b)@ha\n\t"
+ "addi %%r17, %%r17, (4b)@l\n\t"
+ "stw %%r17, 0(%[rseq_cs])\n\t"
+ RSEQ_INJECT_ASM(2)
+ "lwz %%r17, %[current_event_counter]\n\t"
+ "li %%r16, 0\n\t"
+ "cmpw cr7, %[start_event_counter], %%r17\n\t"
+ "bne cr7, 3f\n\t"
+ RSEQ_INJECT_ASM(3)
+ "stw %[to_write], 0(%[target])\n\t"
+ "2:\n\t"
+ RSEQ_INJECT_ASM(4)
+ "stw %%r16, 0(%[rseq_cs])\n\t"
+ "b %l[succeed]\n\t"
+ "3:\n\t"
+ "li %%r16, 0\n\t"
+ "stw %%r16, 0(%[rseq_cs])\n\t"
+ : /* no outputs */
+ : [start_event_counter]"r"(start_value.event_counter),
+ [current_event_counter]"m"(start_value.rseqp->abi.u.e.event_counter),
+ [to_write]"r"(to_write),
+ [target]"b"(p),
+ [rseq_cs]"b"(&start_value.rseqp->abi.rseq_cs)
+ RSEQ_INJECT_INPUT
+ : "r16", "r17", "memory", "cc"
+ RSEQ_INJECT_CLOBBER
+ : succeed
+ );
+ }
#else
#error unsupported target
#endif
--
2.9.0
Powered by blists - more mailing lists