Port-powerpc archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

ppc vs. gcc48 - switching from PPC EABI to PPC SVR4/TLS ABI



hi ppc folks,

I've figured out another of the remaining problems with switching to gcc48.
mallacan@ reported that atf-run crashes in a gcc48 world, and the problem
has to do with how we manage the TLS private pointer.  supporting TLS on
powerpc actually involved switching from the PPC EABI (embedded ABI)
(which uses the R2 register for small data items) to the PPC SVR4 ABI
(which uses the R2 register for the TLS private pointer).
there are some gyrations in the kernel, ld.elf_so and libc.so
to try to make dynamically-linked EABI programs continue to work,
but this is really a lost cause.  EABI programs which use R2 already can't
use pthreads (since our pthreads code uses R2 for TLS support),
and with gcc48 we started configuring libstdc++ to use TLS to implement
C++ exceptions (which is why atf-run has a problem with gcc48).
usage of TLS internally within NetBSD shared libraries will only grow
over time, so any such R2-using EABI programs will only become more broken
in the future.

I haven't yet found any PPC EABI binaries which actually use the R2 register,
so I suspect that such binaries are vanishingly rare, if any exist at all.
accordingly, I'd like to fix the problems caused by the EABI-compat gyrations
by removing support for dynamically-linked EABI binaries (ie. any that actually
use the R2 register for the EABI purpose).  statically-linked EABI binaries
will continue to work, since the kernel will no longer treat R2 specially
when TLS is not actually being used.

I'll commit the attached patch in a few days if there are no objections.

-Chuck
Index: src/lib/libc/tls/tls.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/lib/libc/tls/tls.c,v
retrieving revision 1.7
diff -u -p -r1.7 tls.c
--- src/lib/libc/tls/tls.c	19 Aug 2013 22:14:37 -0000	1.7
+++ src/lib/libc/tls/tls.c	20 Nov 2014 21:29:30 -0000
@@ -155,15 +155,6 @@ __libc_static_tls_setup(void)
 	struct tls_tcb *tcb;
 
 	if (&rtld_DYNAMIC != NULL) {
-#ifdef __powerpc__
-		/*
-		 * Old powerpc crt0's are going to overwrite r2 so we need to
-		 * restore it but only do so if the saved value isn't NULL (if
-		 * it is NULL, ld.elf_so doesn't have the matching change).
-		 */
-		if ((tcb = _lwp_getprivate()) != NULL)
-			__lwp_settcb(tcb);
-#endif
 		return;
 	}
 
Index: src/libexec/ld.elf_so/tls.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/libexec/ld.elf_so/tls.c,v
retrieving revision 1.9
diff -u -p -r1.9 tls.c
--- src/libexec/ld.elf_so/tls.c	21 Oct 2013 19:14:15 -0000	1.9
+++ src/libexec/ld.elf_so/tls.c	20 Nov 2014 21:29:18 -0000
@@ -106,13 +106,6 @@ _rtld_tls_initial_allocation(void)
 	tcb = _rtld_tls_allocate_locked();
 #ifdef __HAVE___LWP_SETTCB
 	__lwp_settcb(tcb);
-#ifdef __powerpc__
-	/*
-	 * Save the tcb pointer so that libc can retrieve it.  Older
-	 * crt0 will obliterate r2 so there is code in libc to restore it.
-	 */
-	_lwp_setprivate(tcb);
-#endif
 #else
 	_lwp_setprivate(tcb);
 #endif
Index: src/sys/arch/powerpc/include/types.h
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/powerpc/include/types.h,v
retrieving revision 1.49
diff -u -p -r1.49 types.h
--- src/sys/arch/powerpc/include/types.h	18 Mar 2014 18:20:41 -0000	1.49
+++ src/sys/arch/powerpc/include/types.h	21 Nov 2014 05:30:10 -0000
@@ -81,6 +81,7 @@ typedef volatile int __cpu_simple_lock_t
 #ifdef _LP64
 #define	__HAVE_ATOMIC64_OPS
 #endif
+#define	__HAVE_CPU_LWP_SETPRIVATE
 #define	__HAVE_COMMON___TLS_GET_ADDR
 #define	__HAVE___LWP_GETTCB_FAST
 #define	__HAVE___LWP_SETTCB
Index: src/sys/arch/powerpc/powerpc/sig_machdep.c
===================================================================
RCS file: /home/chs/netbsd/cvs/src/sys/arch/powerpc/powerpc/sig_machdep.c,v
retrieving revision 1.43
diff -u -p -r1.43 sig_machdep.c
--- src/sys/arch/powerpc/powerpc/sig_machdep.c	11 Sep 2012 00:15:19 -0000	1.43
+++ src/sys/arch/powerpc/powerpc/sig_machdep.c	20 Nov 2014 21:36:37 -0000
@@ -43,6 +43,7 @@ __KERNEL_RCSID(0, "$NetBSD: sig_machdep.
 #include <sys/syscallargs.h>
 #include <sys/systm.h>
 #include <sys/ucontext.h>
+#include <sys/cpu.h>
 
 #include <uvm/uvm_extern.h>
 
@@ -172,8 +173,7 @@ cpu_getmcontext(struct lwp *l, mcontext_
 #endif
 
 	*flagp |= _UC_CPU;
-	if (gr[_REG_R2] == (uintptr_t)l->l_private)
-		*flagp |= _UC_TLSBASE;
+	*flagp |= _UC_TLSBASE;
 
 #ifdef PPC_HAVE_FPU
 	/* Save FPU context, if any. */
@@ -231,17 +231,6 @@ cpu_setmcontext(struct lwp *l, const mco
 #ifdef PPC_OEA
 		tf->tf_mq = gr[_REG_MQ];
 #endif
-		/*
-		 * If R2 contains the TLS base, make sure to update l->l_private.
-		 * If not, restore R2 from l->l_private if not null.  Since setcontext
-		 * existed before the TCB code, a static program could expect R2 to
-		 * the small data pointer.
-		 */
-		if (flags & _UC_TLSBASE) {
-			l->l_private = (void *) tf->tf_fixreg[_REG_R2];
-		} else if (l->l_private) {
-			tf->tf_fixreg[_REG_R2] = (uintptr_t)l->l_private;
-		}
 	}
 
 #ifdef PPC_HAVE_FPU
@@ -264,3 +253,12 @@ cpu_setmcontext(struct lwp *l, const mco
 
 	return (0);
 }
+
+int
+cpu_lwp_setprivate(lwp_t *l, void *addr)
+{
+	struct trapframe * const tf = l->l_md.md_utf;
+
+	tf->tf_fixreg[_REG_R2] = (register_t)addr;
+	return 0;
+}


Home | Main Index | Thread Index | Old Index