diff options
-rw-r--r-- | Documentation/powerpc/transactional_memory.txt | 32 | ||||
-rw-r--r-- | arch/powerpc/include/asm/cputable.h | 10 | ||||
-rw-r--r-- | arch/powerpc/include/uapi/asm/cputable.h | 1 | ||||
-rw-r--r-- | arch/powerpc/include/uapi/asm/tm.h | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/cputable.c | 4 | ||||
-rw-r--r-- | arch/powerpc/kernel/entry_64.S | 35 | ||||
-rw-r--r-- | tools/testing/selftests/powerpc/tm/Makefile | 4 | ||||
-rw-r--r-- | tools/testing/selftests/powerpc/tm/tm-syscall.c | 3 |
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 | |||
74 | Syscalls | 74 | Syscalls |
75 | ======== | 75 | ======== |
76 | 76 | ||
77 | Performing syscalls from within transaction is not recommended, and can lead | 77 | Syscalls made from within an active transaction will not be performed and the |
78 | to unpredictable results. | 78 | transaction will be doomed by the kernel with the failure code TM_CAUSE_SYSCALL |
79 | | TM_CAUSE_PERSISTENT. | ||
79 | 80 | ||
80 | Syscalls do not by design abort transactions, but beware: The kernel code will | 81 | Syscalls made from within a suspended transaction are performed as normal and |
81 | not be running in transactional state. The effect of syscalls will always | 82 | the transaction is not explicitly doomed by the kernel. However, what the |
82 | remain visible, but depending on the call they may abort your transaction as a | 83 | kernel does to perform the syscall may result in the transaction being doomed |
83 | side-effect, read soon-to-be-aborted transactional data that should not remain | 84 | by the hardware. The syscall is performed in suspended mode so any side |
84 | invisible, etc. If you constantly retry a transaction that constantly aborts | 85 | effects will be persistent, independent of transaction success or failure. No |
85 | itself by calling a syscall, you'll have a livelock & make no progress. | 86 | guarantees are provided by the kernel about which syscalls will affect |
87 | transaction success. | ||
86 | 88 | ||
87 | Simple syscalls (e.g. sigprocmask()) "could" be OK. Even things like write() | 89 | Care must be taken when relying on syscalls to abort during active transactions |
88 | from, say, printf() should be OK as long as the kernel does not access any | 90 | if the calls are made via a library. Libraries may cache values (which may |
89 | memory that was accessed transactionally. | 91 | give the appearance of success) or perform operations that cause transaction |
90 | 92 | failure before entering the kernel (which may produce different failure codes). | |
91 | Consider any syscalls that happen to work as debug-only -- not recommended for | 93 | Examples are glibc's getpid() and lazy symbol resolution. |
92 | production use. Best to queue them up till after the transaction is over. | ||
93 | 94 | ||
94 | 95 | ||
95 | Signals | 96 | Signals |
@@ -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 |
53 | system_call_common: | 54 | system_call_common: |
55 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
56 | BEGIN_FTR_SECTION | ||
57 | extrdi. r10, r12, 1, (63-MSR_TS_T_LG) /* transaction active? */ | ||
58 | bne tabort_syscall | ||
59 | END_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 | ||
322 | tabort_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 @@ | |||
1 | TEST_PROGS := tm-resched-dscr | 1 | TEST_PROGS := tm-resched-dscr tm-syscall |
2 | 2 | ||
3 | all: $(TEST_PROGS) | 3 | all: $(TEST_PROGS) |
4 | 4 | ||
5 | $(TEST_PROGS): ../harness.c | 5 | $(TEST_PROGS): ../harness.c |
6 | 6 | ||
7 | tm-syscall: tm-syscall-asm.S | 7 | tm-syscall: tm-syscall-asm.S |
8 | tm-syscall: CFLAGS += -mhtm | 8 | tm-syscall: CFLAGS += -mhtm -I../../../../../usr/include |
9 | 9 | ||
10 | include ../../lib.mk | 10 | include ../../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); |