This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]