powerpc/tm: Abort syscalls in active transactions
Subsystems (3)
v3 cover powerpc/tm: Abort syscalls in active transactions
See the first patch for a description of the reasoning behind this change.
This set includes the change, a kernel selftest for it and some slight refactoring of the selftest code.
v3:
Patch 1/4: powerpc/tm: Abort syscalls in active transactions
Use "TABORT()" macro to allow building on versions of gcc that don't support the "tabort." instruction.
v2:
Patch 1/4: powerpc/tm: Abort syscalls in active transactions
Also update the failure code table.
Patch 3/4: selftests/powerpc: Add transactional syscall test
Further testing has shown that the success or failure of the transactions was affected by minor changes to the code, compiler optimisation and linker settings.
To address this, I've moved the transactional part of the test to a separate function, written in assembly. I've also extended the test to as many transactions as it can fit into ten seconds, to better test for failures that occur more rarely. This has stabilised the results, and it's no longer necessary to use special compiler or linker flags.
Patch 4/4: powerpc/tm: Correct minor documentation typos
Discovered some typos while updating the documentation.
Sam Bobroff (4):
powerpc/tm: Abort syscalls in active transactions selftests/powerpc: Move get_auxv_entry() to harness.c selftests/powerpc: Add transactional syscall test powerpc/tm: Correct minor documentation typos
Documentation/powerpc/transactional_memory.txt | 36 +++---- arch/powerpc/include/uapi/asm/tm.h | 2 +- arch/powerpc/kernel/entry_64.S | 19 ++++ tools/testing/selftests/powerpc/harness.c | 47 +++++++++ tools/testing/selftests/powerpc/pmu/lib.c | 47 --------- tools/testing/selftests/powerpc/pmu/lib.h | 1 - tools/testing/selftests/powerpc/tm/.gitignore | 1 + tools/testing/selftests/powerpc/tm/Makefile | 4 +- .../testing/selftests/powerpc/tm/tm-syscall-asm.S | 27 +++++ .../testing/selftests/powerpc/tm/tm-syscall-asm.h | 2 + tools/testing/selftests/powerpc/tm/tm-syscall.c | 109 ++++++++++++++++++++ tools/testing/selftests/powerpc/utils.h | 2 +- 12 files changed, 228 insertions(+), 69 deletions(-) create mode 100644 tools/testing/selftests/powerpc/tm/tm-syscall-asm.S create mode 100644 tools/testing/selftests/powerpc/tm/tm-syscall-asm.h create mode 100644 tools/testing/selftests/powerpc/tm/tm-syscall.c
Signature · 1 line
1.7.10.4
PATCH v3 1/4 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 immediately without performing the syscall.
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 because syscalls will still be performed after tsuspend. 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 system call increases by about 0.5%.
---
v3:
Use "TABORT()" macro to allow building on versions of gcc that don't support the "tabort." instruction.
v2:
Also update the failure code table.
Documentation/powerpc/transactional_memory.txt | 32 ++++++++++++------------ arch/powerpc/include/uapi/asm/tm.h | 2 +- arch/powerpc/kernel/entry_64.S | 19 ++++++++++++++ 3 files changed, 36 insertions(+), 17 deletions(-)
Documentation/powerpc/transactional_memory.txt +16 -16
@@ -74,22 +74,23 @@ Causes of transaction aborts Syscalls ======== -Performing syscalls from within transaction is not recommended, and can lead -to unpredictable results. +Syscalls made from within an active transaction will not be performed and the +transaction will be doomed by the kernel with the failure code TM_CAUSE_SYSCALL +| TM_CAUSE_PERSISTENT. -Syscalls do not by design abort transactions, but beware: The kernel code will -not be running in transactional state. The effect of syscalls will always -remain visible, but depending on the call they may abort your transaction as a -side-effect, read soon-to-be-aborted transactional data that should not remain -invisible, etc. If you constantly retry a transaction that constantly aborts -itself by calling a syscall, you'll have a livelock & make no progress. +Syscalls made from within a suspended transaction are performed as normal and +the transaction is not explicitly doomed by the kernel. However, what the +kernel does to perform the syscall may result in the transaction being doomed +by the hardware. The syscall is performed in suspended mode so any side +effects will be persistent, independent of transaction success or failure. No +guarantees are provided by the kernel about which syscalls will affect +transaction success. -Simple syscalls (e.g. sigprocmask()) "could" be OK. Even things like write() -from, say, printf() should be OK as long as the kernel does not access any -memory that was accessed transactionally. - -Consider any syscalls that happen to work as debug-only -- not recommended for -production use. Best to queue them up till after the transaction is over. +Care must be taken when relying on syscalls to abort during active transactions +if the calls are made via a library. Libraries may cache values (which may +give the appearance of success) or perform operations that cause transaction +failure before entering the kernel (which may produce different failure codes). +Examples are glibc's getpid() and lazy symbol resolution. Signals
@@ -176,8 +177,7 @@ kernel aborted a transaction: TM_CAUSE_RESCHED Thread was rescheduled. TM_CAUSE_TLBI Software TLB invalide. TM_CAUSE_FAC_UNAV FP/VEC/VSX unavailable trap. - TM_CAUSE_SYSCALL Currently unused; future syscalls that must abort - transactions for consistency will use this. + TM_CAUSE_SYSCALL Syscall from active transaction. TM_CAUSE_SIGNAL Signal delivered. TM_CAUSE_MISC Currently unused. TM_CAUSE_ALIGNMENT Alignment fault.
arch/powerpc/include/uapi/asm/tm.h +1 -1
@@ -11,7 +11,7 @@#define TM_CAUSE_RESCHED 0xde#define TM_CAUSE_TLBI 0xdc#define TM_CAUSE_FAC_UNAV 0xda -#define TM_CAUSE_SYSCALL 0xd8/* future use */ +#define TM_CAUSE_SYSCALL 0xd8#define TM_CAUSE_MISC 0xd6/* future use */ #define TM_CAUSE_SIGNAL 0xd4#define TM_CAUSE_ALIGNMENT 0xd2
arch/powerpc/kernel/entry_64.S +19 -0
@@ -34,6 +34,7 @@ #include <asm/ftrace.h> #include <asm/hw_irq.h> #include <asm/context_tracking.h> +#include <asm/tm.h> /* * System calls.
@@ -145,6 +146,24 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR) andi. r11,r10,_TIF_SYSCALL_DOTRACE bne syscall_dotrace .Lsyscall_dotrace_cont: +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM +BEGIN_FTR_SECTION + b 1f +END_FTR_SECTION_IFCLR(CPU_FTR_TM) + extrdi. r11, r12, 1, (63-MSR_TS_T_LG) /* transaction active? */ + beq+ 1f + + /* Doom the transaction and don't perform the syscall: */ + mfmsr r11 + li r12, 1 + rldimi r11, r12, MSR_TM_LG, 63-MSR_TM_LG + mtmsrd r11, 0 + li r11, (TM_CAUSE_SYSCALL|TM_CAUSE_PERSISTENT) + TABORT(R11) + + b .Lsyscall_exit +1: +#endif cmpldi 0,r0,NR_syscalls bge- syscall_enosys
Signature · 1 line
1.7.10.4
PATCH v3 2/4 selftests/powerpc: Move get_auxv_entry() to harness.c
In reply to Sam BobroffMove get_auxv_entry() from pmu/lib.c up to harness.c in order to make it available to other tests.
--- tools/testing/selftests/powerpc/harness.c | 47 +++++++++++++++++++++++++++++ tools/testing/selftests/powerpc/pmu/lib.c | 47 ----------------------------- tools/testing/selftests/powerpc/pmu/lib.h | 1 - tools/testing/selftests/powerpc/utils.h | 2 +- 4 files changed, 48 insertions(+), 49 deletions(-)
tools/testing/selftests/powerpc/harness.c +47 -0
@@ -11,6 +11,10 @@#include <sys/types.h> #include <sys/wait.h> #include <unistd.h> +#include <elf.h> +#include <fcntl.h> +#include <link.h> +#include <sys/stat.h> #include "subunit.h" #include "utils.h"
@@ -112,3 +116,46 @@ int test_harness(int (test_function)(void), char *name)return rc; } + +static char auxv[4096 ]; + +void *get_auxv_entry (int type) +{ +ElfW (auxv_t) *p; +void *result; +ssize_t num; +int fd; + + fd =open ("/proc/self/auxv" ,O_RDONLY ); +if (fd ==-1 ) { +perror ("open" ); +return NULL ; + } + + result =NULL ; + + num =read (fd, auxv,sizeof (auxv)); +if (num <0 ) { +perror ("read" ); + goto out; + } + +if (num >sizeof (auxv)) { +printf ("Overflowed auxv buffer\n" ); + goto out; + } + + p = (ElfW (auxv_t) *)auxv; + +while (p->a_type !=AT_NULL ) { +if (p->a_type == type) { + result = (void *)p->a_un.a_val; +break ; + } + + p++; + } +out: +close (fd); +return result; +}
tools/testing/selftests/powerpc/pmu/lib.c +0 -47
60 lines not on this page · raw message
tools/testing/selftests/powerpc/pmu/lib.h +0 -1
@@ -29,7 +29,6 @@ extern int notify_parent(union pipe write_pipe);extern int notify_parent_of_error (union pipe write_pipe);extern pid_t eat_cpu (int (test_function )(void ));extern bool require_paranoia_below (int level); -extern void *get_auxv_entry (int type);struct addr_range {uint64_t first, last;
tools/testing/selftests/powerpc/utils.h +1 -1
@@ -19,7 +19,7 @@ typedef uint8_t u8;int test_harness (int (test_function )(void ),char *name); - +extern void *get_auxv_entry (int type);/* Yes, this is evil */ #define FAIL_IF (x) \
Signature · 1 line
1.7.10.4
PATCH v3 3/4 selftests/powerpc: Add transactional syscall test
In reply to Sam BobroffCheck that a syscall made during an active transaction will fail with the correct failure code and that one made during a suspended transaction will succeed.
---
v2:
Further testing has shown that the success or failure of the transactions was affected by minor changes to the code, compiler optimisation and linker settings.
To address this, I've moved the transactional part of the test to a separate function, written in assembly. I've also extended the test to as many transactions as it can fit into ten seconds, to better test for failures that occur more rarely. This has stabilised the results, and it's no longer necessary to use special compiler or linker flags.
tools/testing/selftests/powerpc/tm/.gitignore | 1 + tools/testing/selftests/powerpc/tm/Makefile | 4 +- .../testing/selftests/powerpc/tm/tm-syscall-asm.S | 27 +++++ .../testing/selftests/powerpc/tm/tm-syscall-asm.h | 2 + tools/testing/selftests/powerpc/tm/tm-syscall.c | 109 ++++++++++++++++++++ 5 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/powerpc/tm/tm-syscall-asm.S create mode 100644 tools/testing/selftests/powerpc/tm/tm-syscall-asm.h create mode 100644 tools/testing/selftests/powerpc/tm/tm-syscall.c
tools/testing/selftests/powerpc/tm/.gitignore +1 -0
@@ -1 +1,2 @@ tm-resched-dscr +tm-syscall
tools/testing/selftests/powerpc/tm/Makefile +3 -1
@@ -1,8 +1,10 @@ -PROGS := tm-resched-dscr +PROGS := tm-resched-dscr tm-syscall +CFLAGS:=$(CFLAGS) -mhtm all: $(PROGS) $(PROGS): ../harness.c +tm-syscall: tm-syscall-asm.S run_tests: all @-for PROG in $(PROGS); do \
tools/testing/selftests/powerpc/tm/tm-syscall-asm.S new file +27 -0
@@ -0,0 +1,27 @@ +#include <ppc-asm.h> +#include <asm/unistd.h> + + .text +FUNC_START(getppid_tm_active_impl) + tbegin. + beq 1f + li r0, __NR_getppid + sc + tend. + blr +1: + li r3, -1 + blr + +FUNC_START(getppid_tm_suspended_impl) + tbegin. + beq 1f + li r0, __NR_getppid + tsuspend. + sc + tresume. + tend. + blr +1: + li r3, -1 + blr
tools/testing/selftests/powerpc/tm/tm-syscall-asm.h new file +2 -0
@@ -0,0 +1,2 @@ +extern int getppid_tm_active_impl (void ); +extern int getppid_tm_suspended_impl (void );
tools/testing/selftests/powerpc/tm/tm-syscall.c new file +109 -0
109 lines not on this page · raw message
Signature · 1 line
1.7.10.4
PATCH v3 4/4 powerpc/tm: Correct minor documentation typos
In reply to Sam Bobroff---
v2:
Discovered some typos while updating the documentation.
Documentation/powerpc/transactional_memory.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
Documentation/powerpc/transactional_memory.txt +2 -2
@@ -175,7 +175,7 @@ These are defined in <asm/reg.h>, and distinguish different reasons why the kernel aborted a transaction: TM_CAUSE_RESCHED Thread was rescheduled. - TM_CAUSE_TLBI Software TLB invalide. + TM_CAUSE_TLBI Software TLB invalid. TM_CAUSE_FAC_UNAV FP/VEC/VSX unavailable trap. TM_CAUSE_SYSCALL Syscall from active transaction. TM_CAUSE_SIGNAL Signal delivered.
@@ -185,7 +185,7 @@ kernel aborted a transaction: These can be checked by the user program's abort handler as TEXASR[0:7]. If bit 7 is set, it indicates that the error is consider persistent. For example -a TM_CAUSE_ALIGNMENT will be persistent while a TM_CAUSE_RESCHED will not.q +a TM_CAUSE_ALIGNMENT will be persistent while a TM_CAUSE_RESCHED will not. GDB ===
Signature · 1 line
1.7.10.4