|
|
|
commit 56cf2763819d2f721c98f2b8bcc04a3c673837d3
|
|
|
|
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
|
|
|
|
Date: Fri Nov 7 12:34:52 2014 -0500
|
|
|
|
|
|
|
|
powerpc: abort transaction in syscalls
|
|
|
|
|
|
|
|
Linux kernel powerpc documentation states issuing a syscall inside a
|
|
|
|
transaction is not recommended and may lead to undefined behavior. It
|
|
|
|
also states syscalls does not abort transactoin neither they run in
|
|
|
|
transactional state.
|
|
|
|
|
|
|
|
To avoid side-effects being visible outside transactions, GLIBC with
|
|
|
|
lock elision enabled will issue a transaction abort instruction just
|
|
|
|
before all syscalls if hardware supports hardware transactions.
|
|
|
|
|
|
|
|
Index: glibc-2.17-c758a686/nptl/sysdeps/powerpc/tcb-offsets.sym
|
|
|
|
===================================================================
|
|
|
|
--- glibc-2.17-c758a686.orig/nptl/sysdeps/powerpc/tcb-offsets.sym
|
|
|
|
+++ glibc-2.17-c758a686/nptl/sysdeps/powerpc/tcb-offsets.sym
|
|
|
|
@@ -15,6 +15,7 @@ MULTIPLE_THREADS_OFFSET thread_offsetof
|
|
|
|
PID thread_offsetof (pid)
|
|
|
|
TID thread_offsetof (tid)
|
|
|
|
POINTER_GUARD (offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
|
|
|
|
+TM_CAPABLE (offsetof (tcbhead_t, tm_capable) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
|
|
|
|
#ifndef __ASSUME_PRIVATE_FUTEX
|
|
|
|
PRIVATE_FUTEX_OFFSET thread_offsetof (header.private_futex)
|
|
|
|
#endif
|
|
|
|
Index: glibc-2.17-c758a686/nptl/sysdeps/powerpc/tls.h
|
|
|
|
===================================================================
|
|
|
|
--- glibc-2.17-c758a686.orig/nptl/sysdeps/powerpc/tls.h
|
|
|
|
+++ glibc-2.17-c758a686/nptl/sysdeps/powerpc/tls.h
|
|
|
|
@@ -61,6 +61,15 @@ typedef union dtv
|
|
|
|
are private. */
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
+ /* Indicate if HTM capable (ISA 2.07). */
|
|
|
|
+ uint32_t tm_capable;
|
|
|
|
+ /* Reservation for AT_PLATFORM data - powerpc64. */
|
|
|
|
+#ifdef __powerpc64__
|
|
|
|
+ uint32_t at_platform;
|
|
|
|
+#endif
|
|
|
|
+ /* Reservation for Dynamic System Optimizer ABI. */
|
|
|
|
+ uintptr_t dso_slot2;
|
|
|
|
+ uintptr_t dso_slot1;
|
|
|
|
/* GCC split stack support. */
|
|
|
|
void *__private_ss;
|
|
|
|
/* Reservation for the Event-Based Branching ABI. */
|
|
|
|
@@ -123,7 +132,11 @@ register void *__thread_register __asm__
|
|
|
|
special attention since 'errno' is not yet available and if the
|
|
|
|
operation can cause a failure 'errno' must not be touched. */
|
|
|
|
# define TLS_INIT_TP(tcbp, secondcall) \
|
|
|
|
- (__thread_register = (void *) (tcbp) + TLS_TCB_OFFSET, NULL)
|
|
|
|
+ ({ \
|
|
|
|
+ __thread_register = (void *) (tcbp) + TLS_TCB_OFFSET; \
|
|
|
|
+ THREAD_SET_TM_CAPABLE (GLRO (dl_hwcap2) & PPC_FEATURE2_HAS_HTM ? 1 : 0); \
|
|
|
|
+ NULL; \
|
|
|
|
+ })
|
|
|
|
|
|
|
|
/* Return the address of the dtv for the current thread. */
|
|
|
|
# define THREAD_DTV() \
|
|
|
|
@@ -177,6 +190,13 @@ register void *__thread_register __asm__
|
|
|
|
+ TLS_PRE_TCB_SIZE))[-1].pointer_guard \
|
|
|
|
= THREAD_GET_POINTER_GUARD())
|
|
|
|
|
|
|
|
+/* tm_capable field in TCB head. */
|
|
|
|
+# define THREAD_GET_TM_CAPABLE() \
|
|
|
|
+ (((tcbhead_t *) ((char *) __thread_register \
|
|
|
|
+ - TLS_TCB_OFFSET))[-1].tm_capable)
|
|
|
|
+# define THREAD_SET_TM_CAPABLE(value) \
|
|
|
|
+ (THREAD_GET_TM_CAPABLE () = (value))
|
|
|
|
+
|
|
|
|
/* l_tls_offset == 0 is perfectly valid on PPC, so we have to use some
|
|
|
|
different value to mean unset l_tls_offset. */
|
|
|
|
# define NO_TLS_OFFSET -1
|
|
|
|
Index: glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/sysdep.h
|
|
|
|
===================================================================
|
|
|
|
--- glibc-2.17-c758a686.orig/sysdeps/powerpc/powerpc32/sysdep.h
|
|
|
|
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/sysdep.h
|
|
|
|
@@ -89,7 +89,23 @@ GOT_LABEL: ; \
|
|
|
|
cfi_endproc; \
|
|
|
|
ASM_SIZE_DIRECTIVE(name)
|
|
|
|
|
|
|
|
+#if ! IS_IN(rtld) && defined (ENABLE_LOCK_ELISION)
|
|
|
|
+# define ABORT_TRANSACTION \
|
|
|
|
+ cmpwi 2,0; \
|
|
|
|
+ beq 1f; \
|
|
|
|
+ lwz 0,TM_CAPABLE(2); \
|
|
|
|
+ cmpwi 0,0; \
|
|
|
|
+ beq 1f; \
|
|
|
|
+ li 0,_ABORT_SYSCALL; \
|
|
|
|
+ tabort. 0; \
|
|
|
|
+ .align 4; \
|
|
|
|
+1:
|
|
|
|
+#else
|
|
|
|
+# define ABORT_TRANSACTION
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
#define DO_CALL(syscall) \
|
|
|
|
+ ABORT_TRANSACTION \
|
|
|
|
li 0,syscall; \
|
|
|
|
sc
|
|
|
|
|
|
|
|
Index: glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/sysdep.h
|
|
|
|
===================================================================
|
|
|
|
--- glibc-2.17-c758a686.orig/sysdeps/powerpc/powerpc64/sysdep.h
|
|
|
|
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/sysdep.h
|
|
|
|
@@ -283,7 +283,23 @@ LT_LABELSUFFIX(name,_name_end): ; \
|
|
|
|
TRACEBACK_MASK(name,mask) \
|
|
|
|
END_2(name)
|
|
|
|
|
|
|
|
+#if !IS_IN(rtld) && defined (ENABLE_LOCK_ELISION)
|
|
|
|
+# define ABORT_TRANSACTION \
|
|
|
|
+ cmpdi 13,0; \
|
|
|
|
+ beq 1f; \
|
|
|
|
+ lwz 0,TM_CAPABLE(13); \
|
|
|
|
+ cmpwi 0,0; \
|
|
|
|
+ beq 1f; \
|
|
|
|
+ li 0,_ABORT_SYSCALL; \
|
|
|
|
+ tabort. 0; \
|
|
|
|
+ .align 4; \
|
|
|
|
+1:
|
|
|
|
+#else
|
|
|
|
+# define ABORT_TRANSACTION
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
#define DO_CALL(syscall) \
|
|
|
|
+ ABORT_TRANSACTION \
|
|
|
|
li 0,syscall; \
|
|
|
|
sc
|
|
|
|
|
|
|
|
Index: glibc-2.17-c758a686/sysdeps/powerpc/sysdep.h
|
|
|
|
===================================================================
|
|
|
|
--- glibc-2.17-c758a686.orig/sysdeps/powerpc/sysdep.h
|
|
|
|
+++ glibc-2.17-c758a686/sysdeps/powerpc/sysdep.h
|
|
|
|
@@ -21,6 +21,10 @@
|
|
|
|
*/
|
|
|
|
#define _SYS_AUXV_H 1
|
|
|
|
#include <bits/hwcap.h>
|
|
|
|
+#ifdef ENABLE_LOCK_ELISION
|
|
|
|
+#include <tls.h>
|
|
|
|
+#include <htm.h>
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
#define PPC_FEATURE_970 (PPC_FEATURE_POWER4 + PPC_FEATURE_HAS_ALTIVEC)
|
|
|
|
|
|
|
|
@@ -164,4 +168,22 @@
|
|
|
|
#define ALIGNARG(log2) log2
|
|
|
|
#define ASM_SIZE_DIRECTIVE(name) .size name,.-name
|
|
|
|
|
|
|
|
+#else
|
|
|
|
+
|
|
|
|
+/* Linux kernel powerpc documentation [1] states issuing a syscall inside a
|
|
|
|
+ transaction is not recommended and may lead to undefined behavior. It
|
|
|
|
+ also states syscalls do not abort transactions. To avoid such traps,
|
|
|
|
+ we abort transaction just before syscalls.
|
|
|
|
+
|
|
|
|
+ [1] Documentation/powerpc/transactional_memory.txt [Syscalls] */
|
|
|
|
+#if !IS_IN(rtld) && defined (ENABLE_LOCK_ELISION)
|
|
|
|
+# define ABORT_TRANSACTION \
|
|
|
|
+ ({ \
|
|
|
|
+ if (THREAD_GET_TM_CAPABLE ()) \
|
|
|
|
+ __builtin_tabort (_ABORT_SYSCALL); \
|
|
|
|
+ })
|
|
|
|
+#else
|
|
|
|
+# define ABORT_TRANSACTION
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
#endif /* __ASSEMBLER__ */
|
|
|
|
Index: glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
|
|
|
|
===================================================================
|
|
|
|
--- glibc-2.17-c758a686.orig/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
|
|
|
|
+++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
|
|
|
|
@@ -194,6 +194,7 @@
|
|
|
|
register long int r11 __asm__ ("r11"); \
|
|
|
|
register long int r12 __asm__ ("r12"); \
|
|
|
|
LOADARGS_##nr(name, args); \
|
|
|
|
+ ABORT_TRANSACTION; \
|
|
|
|
__asm__ __volatile__ \
|
|
|
|
("sc \n\t" \
|
|
|
|
"mfcr %0" \
|
|
|
|
Index: glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
|
|
|
|
===================================================================
|
|
|
|
--- glibc-2.17-c758a686.orig/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
|
|
|
|
+++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
|
|
|
|
@@ -201,6 +201,7 @@
|
|
|
|
register long int r7 __asm__ ("r7"); \
|
|
|
|
register long int r8 __asm__ ("r8"); \
|
|
|
|
LOADARGS_##nr (name, ##args); \
|
|
|
|
+ ABORT_TRANSACTION; \
|
|
|
|
__asm__ __volatile__ \
|
|
|
|
("sc\n\t" \
|
|
|
|
"mfcr %0\n\t" \
|
|
|
|
Index: glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/createthread.c
|
|
|
|
===================================================================
|
|
|
|
--- glibc-2.17-c758a686.orig/nptl/sysdeps/unix/sysv/linux/powerpc/createthread.c
|
|
|
|
+++ glibc-2.17-c758a686/nptl/sysdeps/unix/sysv/linux/powerpc/createthread.c
|
|
|
|
@@ -16,9 +16,16 @@
|
|
|
|
License along with the GNU C Library; if not, see
|
|
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
|
|
|
|
+/* RHEL 7-specific changes: The functions PREPARE_CREATE and TLS_VALUE
|
|
|
|
+ are used by createthread.c to override thread setup. In upstream
|
|
|
|
+ they appear in TLS_DEFINE_INIT_TP. */
|
|
|
|
+# define PREPARE_CREATE \
|
|
|
|
+ void *tp = (void *) (pd) + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE; \
|
|
|
|
+ (((tcbhead_t *) ((char *) tp - TLS_TCB_OFFSET))[-1].tm_capable) = \
|
|
|
|
+ THREAD_GET_TM_CAPABLE ();
|
|
|
|
+
|
|
|
|
/* Value passed to 'clone' for initialization of the thread register. */
|
|
|
|
-#define TLS_VALUE ((void *) (pd) \
|
|
|
|
- + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE)
|
|
|
|
+# define TLS_VALUE tp
|
|
|
|
|
|
|
|
/* Get the real implementation. */
|
|
|
|
#include <nptl/sysdeps/pthread/createthread.c>
|