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