This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] PowerPC - cache line size initialization
- From: Adhemerval Zanella <azanella at linux dot vnet dot ibm dot com>
- To: "GNU C. Library" <libc-alpha at sourceware dot org>
- Date: Wed, 21 Dec 2011 10:45:47 -0200
- Subject: [PATCH] PowerPC - cache line size initialization
The PPC A2 memcpy implementation relies on a correct __cache_line_size value
which is currently initialized on '__libc_start_main'
(sysdeps/unix/sysv/linux/powerpc/libc-start.c).
However if a constructor from a DSO (function defined as __attribute__((constructor)))
try to call memcpy, the __cache_line_size is not yet initialized (value 0) and
the implementation fails with a SEGFAULT. A simple fix would be to use a
expect value is its value is 0, however the A2 can have different
__cache_line_size depending of the model.
This patch address the __cache_line_size initialization by moving it to sooner point,
prior any DSO initialization.
---
2011-12-21 Adhemerval Zanella <azanella@linux.vnet.ibm.com>
* sysdeps/unix/sysv/linux/init-first.c: added CACHE_LINE_SETUP macro call,
when defined.
* sysdeps/unix/sysv/linux/powerpc/libc-start.c: Removed the definition and
initialization of __cache_line_size.
* sysdeps/unix/sysv/linux/powerpc/init-first.c: Added the definition and
initialization of __cache_line_size.
---
diff --git a/sysdeps/unix/sysv/linux/init-first.c b/sysdeps/unix/sysv/linux/init-first.c
index a60212f..54701e8 100644
--- a/sysdeps/unix/sysv/linux/init-first.c
+++ b/sysdeps/unix/sysv/linux/init-first.c
@@ -86,6 +86,10 @@ _init (int argc, char **argv, char **envp)
VDSO_SETUP ();
#endif
+#ifdef CACHE_LINE_SETUP
+ CACHE_LINE_SETUP (envp);
+#endif
+
__init_misc (argc, argv, envp);
#ifdef USE_NONOPTION_FLAGS
diff --git a/sysdeps/unix/sysv/linux/powerpc/init-first.c b/sysdeps/unix/sysv/linux/powerpc/init-first.c
index 92dacc7..80f0380 100644
--- a/sysdeps/unix/sysv/linux/powerpc/init-first.c
+++ b/sysdeps/unix/sysv/linux/powerpc/init-first.c
@@ -16,6 +16,7 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
+#include <ldsodefs.h>
#ifdef SHARED
# include <dl-vdso.h>
# undef __gettimeofday
@@ -28,7 +29,6 @@ void *__vdso_clock_gettime;
void *__vdso_clock_getres;
void *__vdso_get_tbfreq;
-
static inline void
_libc_vdso_platform_setup (void)
{
@@ -46,4 +46,52 @@ _libc_vdso_platform_setup (void)
# define VDSO_SETUP _libc_vdso_platform_setup
#endif
+
+int __cache_line_size attribute_hidden;
+
+#define DL_FIND_AUX_FROM_ENVP(__envp, __auxp) \
+ do { \
+ char **_tmp; \
+ size_t _test; \
+ for (_tmp = (__envp); *_tmp; ++_tmp) \
+ continue; \
+ ++_tmp; \
+ \
+ _test = (size_t)_tmp; \
+ _test = (_test + 0xf) & ~0xf; \
+ /* Under some circumstances, MkLinux (up to at least DR3a5) \
+ omits the padding. To work around this, we make a \
+ basic sanity check of the argument vector. Of \
+ course, this means that in future, the argument \
+ vector will have to be laid out to allow for this \
+ test :-(. */ \
+ if (((ElfW(auxv_t) *)_test)->a_type <= 0x10) \
+ _tmp = (char **)_test; \
+ (__auxp) = (ElfW(auxv_t) *) _tmp; \
+ } while (0)
+
+static inline void
+_libc_set_cache_line_size(char **envp)
+{
+ ElfW (auxv_t) * auxp;
+
+ DL_FIND_AUX_FROM_ENVP (envp, auxp);
+
+ /* Initialize the __cache_line_size variable from the aux vector.
+ This is done here and not on __libc_start_main to make function calls
+ from dso constructors be able to address the __cache_line_size and
+ not rely on default values. */
+ for (ElfW (auxv_t) * av = auxp; av->a_type != AT_NULL; ++av)
+ {
+ if (av->a_type == AT_DCACHEBSIZE)
+ {
+ __cache_line_size = av->a_un.a_val;
+ break;
+ }
+ }
+}
+
+#define CACHE_LINE_SETUP(__envp) _libc_set_cache_line_size(__envp)
+
+
#include "../init-first.c"
diff --git a/sysdeps/unix/sysv/linux/powerpc/libc-start.c b/sysdeps/unix/sysv/linux/powerpc/libc-start.c
index 1e6fce4..d281b84 100644
--- a/sysdeps/unix/sysv/linux/powerpc/libc-start.c
+++ b/sysdeps/unix/sysv/linux/powerpc/libc-start.c
@@ -25,7 +25,6 @@
#include <bp-sym.h>
-int __cache_line_size attribute_hidden;
/* The main work is done in the generic function. */
#define LIBC_START_MAIN generic_start_main
#define LIBC_START_DISABLE_INLINE
@@ -80,15 +79,6 @@ int
rtld_fini = NULL;
}
- /* Initialize the __cache_line_size variable from the aux vector. */
- for (ElfW (auxv_t) * av = auxvec; av->a_type != AT_NULL; ++av)
- switch (av->a_type)
- {
- case AT_DCACHEBSIZE:
- __cache_line_size = av->a_un.a_val;
- break;
- }
-
return generic_start_main (stinfo->main, argc, ubp_av, auxvec,
stinfo->init, stinfo->fini, rtld_fini,
stack_on_entry);
--
1.7.1