aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam bobroff <sam.bobroff@au1.ibm.com>2015-06-11 21:06:32 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2015-06-19 03:10:28 -0400
commitb4b56f9ecab40f3b4ef53e130c9f6663be491894 (patch)
treefb469b542c15a246790eca454d405bef3dc2c227
parentb5926430dfa07d17e5d768c16b0d81c13a793f7c (diff)
powerpc/tm: Abort syscalls in active transactions
This patch changes the syscall handler to doom (tabort) active transactions when a syscall is made and return very early without performing the syscall and keeping side effects to a minimum (no CPU accounting or system call tracing is performed). Also included is a new HWCAP2 bit, PPC_FEATURE2_HTM_NOSC, to indicate this behaviour to userspace. Currently, the system call instruction automatically suspends an active transaction which causes side effects to persist when an active transaction fails. This does change the kernel's behaviour, but in a way that was documented as unsupported. It doesn't reduce functionality as syscalls will still be performed after tsuspend; it just requires that the transaction be explicitly suspended. It also provides a consistent interface and makes the behaviour of user code substantially the same across powerpc and platforms that do not support suspended transactions (e.g. x86 and s390). Performance measurements using http://ozlabs.org/~anton/junkcode/null_syscall.c indicate the cost of a normal (non-aborted) system call increases by about 0.25%. Signed-off-by: Sam Bobroff <sam.bobroff@au1.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--Documentation/powerpc/transactional_memory.txt32
-rw-r--r--arch/powerpc/include/asm/cputable.h10
-rw-r--r--arch/powerpc/include/uapi/asm/cputable.h1
-rw-r--r--arch/powerpc/include/uapi/asm/tm.h2
-rw-r--r--arch/powerpc/kernel/cputable.c4
-rw-r--r--arch/powerpc/kernel/entry_64.S35
-rw-r--r--tools/testing/selftests/powerpc/tm/Makefile4
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-syscall.c3
8 files changed, 66 insertions, 25 deletions
diff --git a/Documentation/powerpc/transactional_memory.txt b/Documentation/powerpc/transactional_memory.txt
index ded69794a5c0..ba0a2a4a54ba 100644
--- a/Documentation/powerpc/transactional_memory.txt
+++ b/Documentation/powerpc/transactional_memory.txt
@@ -74,22 +74,23 @@ Causes of transaction aborts
74Syscalls 74Syscalls
75======== 75========
76 76
77Performing syscalls from within transaction is not recommended, and can lead 77Syscalls made from within an active transaction will not be performed and the
78to unpredictable results. 78transaction will be doomed by the kernel with the failure code TM_CAUSE_SYSCALL
79| TM_CAUSE_PERSISTENT.
79 80
80Syscalls do not by design abort transactions, but beware: The kernel code will 81Syscalls made from within a suspended transaction are performed as normal and
81not be running in transactional state. The effect of syscalls will always 82the transaction is not explicitly doomed by the kernel. However, what the
82remain visible, but depending on the call they may abort your transaction as a 83kernel does to perform the syscall may result in the transaction being doomed
83side-effect, read soon-to-be-aborted transactional data that should not remain 84by the hardware. The syscall is performed in suspended mode so any side
84invisible, etc. If you constantly retry a transaction that constantly aborts 85effects will be persistent, independent of transaction success or failure. No
85itself by calling a syscall, you'll have a livelock & make no progress. 86guarantees are provided by the kernel about which syscalls will affect
87transaction success.
86 88
87Simple syscalls (e.g. sigprocmask()) "could" be OK. Even things like write() 89Care must be taken when relying on syscalls to abort during active transactions
88from, say, printf() should be OK as long as the kernel does not access any 90if the calls are made via a library. Libraries may cache values (which may
89memory that was accessed transactionally. 91give the appearance of success) or perform operations that cause transaction
90 92failure before entering the kernel (which may produce different failure codes).
91Consider any syscalls that happen to work as debug-only -- not recommended for 93Examples are glibc's getpid() and lazy symbol resolution.
92production use. Best to queue them up till after the transaction is over.
93 94
94 95
95Signals 96Signals
@@ -176,8 +177,7 @@ kernel aborted a transaction:
176 TM_CAUSE_RESCHED Thread was rescheduled. 177 TM_CAUSE_RESCHED Thread was rescheduled.
177 TM_CAUSE_TLBI Software TLB invalid. 178 TM_CAUSE_TLBI Software TLB invalid.
178 TM_CAUSE_FAC_UNAV FP/VEC/VSX unavailable trap. 179 TM_CAUSE_FAC_UNAV FP/VEC/VSX unavailable trap.
179 TM_CAUSE_SYSCALL Currently unused; future syscalls that must abort 180 TM_CAUSE_SYSCALL Syscall from active transaction.
180 transactions for consistency will use this.
181 TM_CAUSE_SIGNAL Signal delivered. 181 TM_CAUSE_SIGNAL Signal delivered.
182 TM_CAUSE_MISC Currently unused. 182 TM_CAUSE_MISC Currently unused.
183 TM_CAUSE_ALIGNMENT Alignment fault. 183 TM_CAUSE_ALIGNMENT Alignment fault.
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index 6367b8347dad..4994648b9265 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -242,11 +242,13 @@ enum {
242 242
243/* We only set the TM feature if the kernel was compiled with TM supprt */ 243/* We only set the TM feature if the kernel was compiled with TM supprt */
244#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 244#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
245#define CPU_FTR_TM_COMP CPU_FTR_TM 245#define CPU_FTR_TM_COMP CPU_FTR_TM
246#define PPC_FEATURE2_HTM_COMP PPC_FEATURE2_HTM 246#define PPC_FEATURE2_HTM_COMP PPC_FEATURE2_HTM
247#define PPC_FEATURE2_HTM_NOSC_COMP PPC_FEATURE2_HTM_NOSC
247#else 248#else
248#define CPU_FTR_TM_COMP 0 249#define CPU_FTR_TM_COMP 0
249#define PPC_FEATURE2_HTM_COMP 0 250#define PPC_FEATURE2_HTM_COMP 0
251#define PPC_FEATURE2_HTM_NOSC_COMP 0
250#endif 252#endif
251 253
252/* We need to mark all pages as being coherent if we're SMP or we have a 254/* We need to mark all pages as being coherent if we're SMP or we have a
diff --git a/arch/powerpc/include/uapi/asm/cputable.h b/arch/powerpc/include/uapi/asm/cputable.h
index de2c0e4ee1aa..43686043e297 100644
--- a/arch/powerpc/include/uapi/asm/cputable.h
+++ b/arch/powerpc/include/uapi/asm/cputable.h
@@ -42,5 +42,6 @@
42#define PPC_FEATURE2_ISEL 0x08000000 42#define PPC_FEATURE2_ISEL 0x08000000
43#define PPC_FEATURE2_TAR 0x04000000 43#define PPC_FEATURE2_TAR 0x04000000
44#define PPC_FEATURE2_VEC_CRYPTO 0x02000000 44#define PPC_FEATURE2_VEC_CRYPTO 0x02000000
45#define PPC_FEATURE2_HTM_NOSC 0x01000000
45 46
46#endif /* _UAPI__ASM_POWERPC_CPUTABLE_H */ 47#endif /* _UAPI__ASM_POWERPC_CPUTABLE_H */
diff --git a/arch/powerpc/include/uapi/asm/tm.h b/arch/powerpc/include/uapi/asm/tm.h
index 5d836b7c1176..5047659815a5 100644
--- a/arch/powerpc/include/uapi/asm/tm.h
+++ b/arch/powerpc/include/uapi/asm/tm.h
@@ -11,7 +11,7 @@
11#define TM_CAUSE_RESCHED 0xde 11#define TM_CAUSE_RESCHED 0xde
12#define TM_CAUSE_TLBI 0xdc 12#define TM_CAUSE_TLBI 0xdc
13#define TM_CAUSE_FAC_UNAV 0xda 13#define TM_CAUSE_FAC_UNAV 0xda
14#define TM_CAUSE_SYSCALL 0xd8 /* future use */ 14#define TM_CAUSE_SYSCALL 0xd8
15#define TM_CAUSE_MISC 0xd6 /* future use */ 15#define TM_CAUSE_MISC 0xd6 /* future use */
16#define TM_CAUSE_SIGNAL 0xd4 16#define TM_CAUSE_SIGNAL 0xd4
17#define TM_CAUSE_ALIGNMENT 0xd2 17#define TM_CAUSE_ALIGNMENT 0xd2
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 60262fdf35ba..7d80bfdfb15e 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -108,7 +108,9 @@ extern void __restore_cpu_e6500(void);
108 PPC_FEATURE_TRUE_LE | \ 108 PPC_FEATURE_TRUE_LE | \
109 PPC_FEATURE_PSERIES_PERFMON_COMPAT) 109 PPC_FEATURE_PSERIES_PERFMON_COMPAT)
110#define COMMON_USER2_POWER8 (PPC_FEATURE2_ARCH_2_07 | \ 110#define COMMON_USER2_POWER8 (PPC_FEATURE2_ARCH_2_07 | \
111 PPC_FEATURE2_HTM_COMP | PPC_FEATURE2_DSCR | \ 111 PPC_FEATURE2_HTM_COMP | \
112 PPC_FEATURE2_HTM_NOSC_COMP | \
113 PPC_FEATURE2_DSCR | \
112 PPC_FEATURE2_ISEL | PPC_FEATURE2_TAR | \ 114 PPC_FEATURE2_ISEL | PPC_FEATURE2_TAR | \
113 PPC_FEATURE2_VEC_CRYPTO) 115 PPC_FEATURE2_VEC_CRYPTO)
114#define COMMON_USER_PA6T (COMMON_USER_PPC64 | PPC_FEATURE_PA6T |\ 116#define COMMON_USER_PA6T (COMMON_USER_PPC64 | PPC_FEATURE_PA6T |\
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 278888e89acc..579e0f9a2d57 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -34,6 +34,7 @@
34#include <asm/ftrace.h> 34#include <asm/ftrace.h>
35#include <asm/hw_irq.h> 35#include <asm/hw_irq.h>
36#include <asm/context_tracking.h> 36#include <asm/context_tracking.h>
37#include <asm/tm.h>
37 38
38/* 39/*
39 * System calls. 40 * System calls.
@@ -51,6 +52,12 @@ exception_marker:
51 52
52 .globl system_call_common 53 .globl system_call_common
53system_call_common: 54system_call_common:
55#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
56BEGIN_FTR_SECTION
57 extrdi. r10, r12, 1, (63-MSR_TS_T_LG) /* transaction active? */
58 bne tabort_syscall
59END_FTR_SECTION_IFSET(CPU_FTR_TM)
60#endif
54 andi. r10,r12,MSR_PR 61 andi. r10,r12,MSR_PR
55 mr r10,r1 62 mr r10,r1
56 addi r1,r1,-INT_FRAME_SIZE 63 addi r1,r1,-INT_FRAME_SIZE
@@ -311,6 +318,34 @@ syscall_exit_work:
311 bl do_syscall_trace_leave 318 bl do_syscall_trace_leave
312 b ret_from_except 319 b ret_from_except
313 320
321#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
322tabort_syscall:
323 /* Firstly we need to enable TM in the kernel */
324 mfmsr r10
325 li r13, 1
326 rldimi r10, r13, MSR_TM_LG, 63-MSR_TM_LG
327 mtmsrd r10, 0
328
329 /* tabort, this dooms the transaction, nothing else */
330 li r13, (TM_CAUSE_SYSCALL|TM_CAUSE_PERSISTENT)
331 TABORT(R13)
332
333 /*
334 * Return directly to userspace. We have corrupted user register state,
335 * but userspace will never see that register state. Execution will
336 * resume after the tbegin of the aborted transaction with the
337 * checkpointed register state.
338 */
339 li r13, MSR_RI
340 andc r10, r10, r13
341 mtmsrd r10, 1
342 mtspr SPRN_SRR0, r11
343 mtspr SPRN_SRR1, r12
344
345 rfid
346 b . /* prevent speculative execution */
347#endif
348
314/* Save non-volatile GPRs, if not already saved. */ 349/* Save non-volatile GPRs, if not already saved. */
315_GLOBAL(save_nvgprs) 350_GLOBAL(save_nvgprs)
316 ld r11,_TRAP(r1) 351 ld r11,_TRAP(r1)
diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
index 6bff955e1d55..4bea62a319dc 100644
--- a/tools/testing/selftests/powerpc/tm/Makefile
+++ b/tools/testing/selftests/powerpc/tm/Makefile
@@ -1,11 +1,11 @@
1TEST_PROGS := tm-resched-dscr 1TEST_PROGS := tm-resched-dscr tm-syscall
2 2
3all: $(TEST_PROGS) 3all: $(TEST_PROGS)
4 4
5$(TEST_PROGS): ../harness.c 5$(TEST_PROGS): ../harness.c
6 6
7tm-syscall: tm-syscall-asm.S 7tm-syscall: tm-syscall-asm.S
8tm-syscall: CFLAGS += -mhtm 8tm-syscall: CFLAGS += -mhtm -I../../../../../usr/include
9 9
10include ../../lib.mk 10include ../../lib.mk
11 11
diff --git a/tools/testing/selftests/powerpc/tm/tm-syscall.c b/tools/testing/selftests/powerpc/tm/tm-syscall.c
index 3ed8d4b252fa..1276e23da63b 100644
--- a/tools/testing/selftests/powerpc/tm/tm-syscall.c
+++ b/tools/testing/selftests/powerpc/tm/tm-syscall.c
@@ -82,7 +82,8 @@ int tm_syscall(void)
82 unsigned count = 0; 82 unsigned count = 0;
83 struct timeval end, now; 83 struct timeval end, now;
84 84
85 SKIP_IF(!((long)get_auxv_entry(AT_HWCAP2) & PPC_FEATURE2_HTM)); 85 SKIP_IF(!((long)get_auxv_entry(AT_HWCAP2)
86 & PPC_FEATURE2_HTM_NOSC));
86 setbuf(stdout, NULL); 87 setbuf(stdout, NULL);
87 88
88 printf("Testing transactional syscalls for %d seconds...\n", TEST_DURATION); 89 printf("Testing transactional syscalls for %d seconds...\n", TEST_DURATION);