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