[PATCH] PowerPC - cache line size initialization

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] PowerPC - cache line size initialization

Adhemerval Zanella
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  <[hidden email]>

        * 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

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] PowerPC - cache line size initialization

Ulrich Drepper-2
On Wed, Dec 21, 2011 at 07:45, Adhemerval Zanella
<[hidden email]> wrote:
> This patch address the __cache_line_size initialization by moving it to sooner point,
> prior any DSO initialization.

No.  Just look what other architectures do.  Also, if the value is not
optimized all you should get is less performance.  Otherwise the code
isn't written as it should.
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] PowerPC - cache line size initialization

Steve Munroe
[hidden email] wrote on 12/21/2011 08:30:17 PM:

> From: Ulrich Drepper <[hidden email]>
> To: Adhemerval Zanella <[hidden email]>
> Cc: "GNU C. Library" <[hidden email]>
> Date: 12/21/2011 09:37 PM
> Subject: Re: [PATCH] PowerPC - cache line size initialization
> Sent by: [hidden email]
>
> On Wed, Dec 21, 2011 at 07:45, Adhemerval Zanella
> <[hidden email]> wrote:
> > This patch address the __cache_line_size initialization by moving
> it to sooner point,
> > prior any DSO initialization.
>
> No.  Just look what other architectures do.  Also, if the value is not
> optimized all you should get is less performance.  Otherwise the code
> isn't written as it should.
>

Adhermerval, just change to code to check for '0' __cache_line_size and if
equal execute as if the fill char is none zero (the path that does not use
DCBZ).

Assuming this is memset code is unique to A2/A2O only they will take the
hit (for allowing multiple cache line sizes).

This has been going on too long ...


Steven J. Munroe
Linux on Power Toolchain Architect