GNU C Library master sources branch master updated. glibc-2.22-573-g67385a0

tuliom@sourceware.org tuliom@sourceware.org
Thu Dec 3 16:11:00 GMT 2015


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  67385a01d229751569b6aac067ffdcd813a15d7a (commit)
      from  db340c904dd519142025a09190bf48ad28152ab9 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=67385a01d229751569b6aac067ffdcd813a15d7a

commit 67385a01d229751569b6aac067ffdcd813a15d7a
Author: Carlos Eduardo Seo <cseo@linux.vnet.ibm.com>
Date:   Thu Oct 22 19:26:58 2015 -0500

    powerpc: Add hwcap/hwcap2/platform data to TCB.
    
    This patch adds a new feature for powerpc.  In order to get faster access to
    the HWCAP/HWCAP2 bits and platform number (i.e. for implementing
    __builtin_cpu_is () / __builtin_cpu_supports () in GCC) without the overhead of
    reading from the auxiliary vector, we now reserve space for them in the TCB.
    This is an ABI change for GLIBC 2.23.
    
    A new versioned symbol '__parse_hwcap_and_convert_at_platform' is available to
    get the data from the auxiliary vector and parse it, and store it for later use
    in the TLS initialization code.  This function is called very early
    (in _dl_sysdep_start () via DL_PLATFORM_INFO for the dynamic linking case, and
    in __libc_start_main () for the static linking case) to make sure the data is
    available at the time of TLS initialization.
    
    	* sysdeps/powerpc/Makefile (sysdep-dl-routines): Add hwcapinfo.
    	(sysdep_routines): Likewise.
    	(sysdep-rtld-routines): Likewise.
    	[$(subdir) = nptl](tests): Add test-get_hwcap and test-get_hwcap-static
    	[$(subdir) = nptl](tests-static): test-get_hwcap-static
    	* sysdeps/powerpc/Versions: Added new
    	__parse_hwcap_and_convert_at_platform symbol to GLIBC-2.23.
    	* sysdeps/powerpc/hwcapinfo.c: New file.
    	(__tcb_parse_hwcap_and_convert_at_platform): New function to initialize
    	and parse hwcap, hwcap2 and platform number information.
    	* sysdeps/powerpc/hwcapinfo.h: New file.  Creates global variables
    	to store HWCAP+HWCAP2 and platform number.
    	* sysdeps/powerpc/nptl/tcb-offsets.sym: Added new offsets
    	for HWCAP+HWCAP2 and platform number in the TCB.
    	* sysdeps/powerpc/nptl/tls.h: New functionality.  Stores
    	the HWCAP, HWCAP2 and platform number in the TCB.
    	(dtv): Added new fields for HWCAP+HWCAP2 and platform number.
    	(TLS_INIT_TP): Included calls to add the hwcap and
    	at_platform values in the TCB in TP initialization.
    	(TLS_DEFINE_INIT_TP): Likewise.
    	(THREAD_GET_HWCAP): New macro.
    	(THREAD_SET_HWCAP): Likewise.
    	(THREAD_GET_AT_PLATFORM): Likewise.
    	(THREAD_SET_AT_PLATFORM): Likewise.
    	* sysdeps/powerpc/powerpc32/dl-machine.h:
    	(dl_platform_init): New function that calls
    	__parse_hwcap_and_convert_at_platform for the dymanic linking case for
    	powerpc32.
    	* sysdeps/powerpc/powerpc64/dl-machine.h: Likewise, for powerpc64.
    	* sysdeps/powerpc/test-get_hwcap-static.c: New file.  Testcase for
    	this functionality, static linking case.
    	* sysdeps/powerpc/test-get_hwcap.c: New file.  Likewise, dynamic
    	linking case.
    	* sysdeps/unix/sysv/linux/powerpc/libc-start.c: Added call to
    	__parse_hwcap_and_convert_at_platform for the static linking case.
    	* sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist:
    	Included the new __parse_hwcap_and_convert_at_platform symbol in the
    	ABI list for GLIBC 2.23.
    	* sysdeps/unix/sysv/linux/powerpc/powerpc64/ld-le.abilist:
    	Likewise.
    	* sysdeps/unix/sysv/linux/powerpc/powerpc64/ld.abilist:
    	Likewise.

diff --git a/ChangeLog b/ChangeLog
index a6f661f..4b41f95 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,48 @@
+2015-12-03  Carlos Eduardo Seo  <cseo@linux.vnet.ibm.com>
+
+	* sysdeps/powerpc/Makefile (sysdep-dl-routines): Add hwcapinfo.
+	(sysdep_routines): Likewise.
+	(sysdep-rtld-routines): Likewise.
+	[$(subdir) = nptl](tests): Add test-get_hwcap and test-get_hwcap-static
+	[$(subdir) = nptl](tests-static): test-get_hwcap-static
+	* sysdeps/powerpc/Versions: Added new
+	__parse_hwcap_and_convert_at_platform symbol to GLIBC-2.23.
+	* sysdeps/powerpc/hwcapinfo.c: New file.
+	(__tcb_parse_hwcap_and_convert_at_platform): New function to initialize
+	and parse hwcap, hwcap2 and platform number information.
+	* sysdeps/powerpc/hwcapinfo.h: New file.  Creates global variables
+	to store HWCAP+HWCAP2 and platform number.
+	* sysdeps/powerpc/nptl/tcb-offsets.sym: Added new offsets
+	for HWCAP+HWCAP2 and platform number in the TCB.
+	* sysdeps/powerpc/nptl/tls.h: New functionality.  Stores
+	the HWCAP, HWCAP2 and platform number in the TCB.
+	(dtv): Added new fields for HWCAP+HWCAP2 and platform number.
+	(TLS_INIT_TP): Included calls to add the hwcap and
+	at_platform values in the TCB in TP initialization.
+	(TLS_DEFINE_INIT_TP): Likewise.
+	(THREAD_GET_HWCAP): New macro.
+	(THREAD_SET_HWCAP): Likewise.
+	(THREAD_GET_AT_PLATFORM): Likewise.
+	(THREAD_SET_AT_PLATFORM): Likewise.
+	* sysdeps/powerpc/powerpc32/dl-machine.h:
+	(dl_platform_init): New function that calls
+	__parse_hwcap_and_convert_at_platform for the dymanic linking case for
+	powerpc32.
+	* sysdeps/powerpc/powerpc64/dl-machine.h: Likewise, for powerpc64.
+	* sysdeps/powerpc/test-get_hwcap-static.c: New file.  Testcase for
+	this functionality, static linking case.
+	* sysdeps/powerpc/test-get_hwcap.c: New file.  Likewise, dynamic
+	linking case.
+	* sysdeps/unix/sysv/linux/powerpc/libc-start.c: Added call to
+	__parse_hwcap_and_convert_at_platform for the static linking case.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist:
+	Included the new __parse_hwcap_and_convert_at_platform symbol in the
+	ABI list for GLIBC 2.23.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/ld-le.abilist:
+	Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/ld.abilist:
+	Likewise.
+
 2015-12-02  Ludovic Courtès  <ludo@gnu.org>
 
 	* configure.ac: Use 'pwd -P' instead of '/bin/pwd'.
diff --git a/sysdeps/powerpc/Makefile b/sysdeps/powerpc/Makefile
index 533d763..099fbf6 100644
--- a/sysdeps/powerpc/Makefile
+++ b/sysdeps/powerpc/Makefile
@@ -4,10 +4,10 @@ endif
 
 ifeq ($(subdir),elf)
 # extra shared linker files to link into dl-allobjs.so and libc
-sysdep-dl-routines += dl-machine
-sysdep_routines += dl-machine
+sysdep-dl-routines += dl-machine hwcapinfo
+sysdep_routines += dl-machine hwcapinfo
 # extra shared linker files to link only into dl-allobjs.so
-sysdep-rtld-routines += dl-machine
+sysdep-rtld-routines += dl-machine hwcapinfo
 # Don't optimize GD tls sequence to LE.
 LDFLAGS-tst-tlsopt-powerpc += -Wl,--no-tls-optimize
 tests += tst-tlsopt-powerpc
@@ -26,6 +26,11 @@ gen-as-const-headers += rtld-global-offsets.sym
 gen-as-const-headers += locale-defines.sym
 endif
 
+ifeq ($(subdir),nptl)
+tests += test-get_hwcap test-get_hwcap-static
+tests-static += test-get_hwcap-static
+endif
+
 ifeq ($(subdir),misc)
 sysdep_headers += sys/platform/ppc.h
 tests += test-gettimebase
diff --git a/sysdeps/powerpc/Versions b/sysdeps/powerpc/Versions
index 2aebf7c..b959ea4 100644
--- a/sysdeps/powerpc/Versions
+++ b/sysdeps/powerpc/Versions
@@ -20,4 +20,9 @@ ld {
   GLIBC_2.22 {
     __tls_get_addr_opt;
   }
+  GLIBC_2.23 {
+    # Symbol used to version control when the ABI started to specify that HWCAP
+    # and AT_PLATFORM data should be stored into the TCB.
+    __parse_hwcap_and_convert_at_platform;
+  }
 }
diff --git a/sysdeps/powerpc/hwcapinfo.c b/sysdeps/powerpc/hwcapinfo.c
new file mode 100644
index 0000000..a115ffc
--- /dev/null
+++ b/sysdeps/powerpc/hwcapinfo.c
@@ -0,0 +1,76 @@
+/* powerpc HWCAP/HWCAP2 and AT_PLATFORM data pre-processing.
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <unistd.h>
+#include <shlib-compat.h>
+#include <dl-procinfo.h>
+
+uint64_t __tcb_hwcap __attribute__ ((visibility ("hidden")));
+uint32_t __tcb_platform __attribute__ ((visibility ("hidden")));
+
+/* This function parses the HWCAP/HWCAP2 fields, adding the previous supported
+   ISA bits, as well as converting the AT_PLATFORM string to a number.  This
+   data is stored in two global variables that can be used later by the
+   powerpc-specific code to store it into the TCB.  */
+void
+__tcb_parse_hwcap_and_convert_at_platform (void)
+{
+
+  uint64_t h1, h2;
+
+  /* Read AT_PLATFORM string from auxv and convert it to a number.  */
+  __tcb_platform = _dl_string_platform (GLRO (dl_platform));
+
+  /* Read HWCAP and HWCAP2 from auxv.  */
+  h1 = GLRO (dl_hwcap);
+  h2 = GLRO (dl_hwcap2);
+
+  /* hwcap contains only the latest supported ISA, the code checks which is
+     and fills the previous supported ones.  */
+
+  if (h2 & PPC_FEATURE2_ARCH_2_07)
+    h1 |= PPC_FEATURE_ARCH_2_06
+       | PPC_FEATURE_ARCH_2_05
+       | PPC_FEATURE_POWER5_PLUS
+       | PPC_FEATURE_POWER5
+       | PPC_FEATURE_POWER4;
+  else if (h1 & PPC_FEATURE_ARCH_2_06)
+    h1 |= PPC_FEATURE_ARCH_2_05
+       | PPC_FEATURE_POWER5_PLUS
+       | PPC_FEATURE_POWER5
+       | PPC_FEATURE_POWER4;
+  else if (h1 & PPC_FEATURE_ARCH_2_05)
+    h1 |= PPC_FEATURE_POWER5_PLUS
+       | PPC_FEATURE_POWER5
+       | PPC_FEATURE_POWER4;
+  else if (h1 & PPC_FEATURE_POWER5_PLUS)
+    h1 |= PPC_FEATURE_POWER5
+       | PPC_FEATURE_POWER4;
+  else if (h1 & PPC_FEATURE_POWER5)
+    h1 |= PPC_FEATURE_POWER4;
+
+  /* Consolidate both HWCAP and HWCAP2 into a single doubleword so that
+     we can read both in a single load later.  */
+  __tcb_hwcap = h2;
+  __tcb_hwcap = (h1 << 32) | __tcb_hwcap;
+
+}
+#if IS_IN (rtld)
+versioned_symbol (ld, __tcb_parse_hwcap_and_convert_at_platform, \
+		  __parse_hwcap_and_convert_at_platform, GLIBC_2_23);
+#endif
diff --git a/sysdeps/powerpc/hwcapinfo.h b/sysdeps/powerpc/hwcapinfo.h
new file mode 100644
index 0000000..f9f6bc7
--- /dev/null
+++ b/sysdeps/powerpc/hwcapinfo.h
@@ -0,0 +1,29 @@
+/* powerpc HWCAP/HWCAP2 and AT_PLATFORM data pre-processing.
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdint.h>
+
+#ifndef HWCAPINFO_H
+# define HWCAPINFO_H
+
+extern uint64_t __tcb_hwcap  attribute_hidden;
+extern uint32_t __tcb_platform attribute_hidden;
+
+extern void __tcb_parse_hwcap_and_convert_at_platform (void);
+
+#endif
diff --git a/sysdeps/powerpc/nptl/tcb-offsets.sym b/sysdeps/powerpc/nptl/tcb-offsets.sym
index d955142..f580e69 100644
--- a/sysdeps/powerpc/nptl/tcb-offsets.sym
+++ b/sysdeps/powerpc/nptl/tcb-offsets.sym
@@ -19,7 +19,15 @@ POINTER_GUARD			(offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (
 TAR_SAVE			(offsetof (tcbhead_t, tar_save) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
 DSO_SLOT1			(offsetof (tcbhead_t, dso_slot1) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
 DSO_SLOT2			(offsetof (tcbhead_t, dso_slot2) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
+#ifdef __powerpc64__
+TCB_AT_PLATFORM			(offsetof (tcbhead_t, at_platform) - TLS_TCB_OFFSET - sizeof(tcbhead_t))
+#endif
 TM_CAPABLE			(offsetof (tcbhead_t, tm_capable) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
+#ifndef __powerpc64__
+TCB_AT_PLATFORM			(offsetof (tcbhead_t, at_platform) - TLS_TCB_OFFSET - sizeof(tcbhead_t))
+PADDING				(offsetof (tcbhead_t, padding) - TLS_TCB_OFFSET - sizeof(tcbhead_t))
+#endif
+TCB_HWCAP			(offsetof (tcbhead_t, hwcap) - TLS_TCB_OFFSET - sizeof (tcbhead_t))
 #ifndef __ASSUME_PRIVATE_FUTEX
 PRIVATE_FUTEX_OFFSET		thread_offsetof (header.private_futex)
 #endif
diff --git a/sysdeps/powerpc/nptl/tls.h b/sysdeps/powerpc/nptl/tls.h
index 1f3d97a..7b6682c 100644
--- a/sysdeps/powerpc/nptl/tls.h
+++ b/sysdeps/powerpc/nptl/tls.h
@@ -44,6 +44,8 @@ typedef union dtv
 
 #ifndef __ASSEMBLER__
 
+# include <hwcapinfo.h>
+
 /* Get system call information.  */
 # include <sysdep.h>
 
@@ -63,8 +65,24 @@ typedef union dtv
    are private.  */
 typedef struct
 {
+  /* Reservation for HWCAP data.  To be accessed by GCC in
+     __builtin_cpu_supports(), so it is a part of public ABI.  */
+  uint64_t hwcap;
+  /* Reservation for AT_PLATFORM data.  To be accessed by GCC in
+     __builtin_cpu_is(), so it is a part of public ABI.  Since there
+     are different ABIs for 32 and 64 bit, we put this field in a
+     previously empty padding space for powerpc64.  */
+#ifndef __powerpc64__
+  /* Padding to maintain alignment.  */
+  uint32_t padding;
+  uint32_t at_platform;
+#endif
   /* Indicate if HTM capable (ISA 2.07).  */
-  int tm_capable;
+  uint32_t tm_capable;
+  /* Reservation for AT_PLATFORM data - powerpc64.  */
+#ifdef __powerpc64__
+  uint32_t at_platform;
+#endif
   /* Reservation for Dynamic System Optimizer ABI.  */
   uintptr_t dso_slot2;
   uintptr_t dso_slot1;
@@ -134,7 +152,9 @@ register void *__thread_register __asm__ ("r13");
 # define TLS_INIT_TP(tcbp) \
   ({ 									      \
     __thread_register = (void *) (tcbp) + TLS_TCB_OFFSET;		      \
-    THREAD_SET_TM_CAPABLE (GLRO (dl_hwcap2) & PPC_FEATURE2_HAS_HTM ? 1 : 0);  \
+    THREAD_SET_TM_CAPABLE (__tcb_hwcap & PPC_FEATURE2_HAS_HTM ? 1 : 0);	      \
+    THREAD_SET_HWCAP (__tcb_hwcap);					      \
+    THREAD_SET_AT_PLATFORM (__tcb_platform);				      \
     NULL;								      \
   })
 
@@ -142,7 +162,11 @@ register void *__thread_register __asm__ ("r13");
 # define TLS_DEFINE_INIT_TP(tp, pd) \
     void *tp = (void *) (pd) + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE;	      \
     (((tcbhead_t *) ((char *) tp - TLS_TCB_OFFSET))[-1].tm_capable) =	      \
-      THREAD_GET_TM_CAPABLE ();
+      THREAD_GET_TM_CAPABLE ();						      \
+    (((tcbhead_t *) ((char *) tp - TLS_TCB_OFFSET))[-1].hwcap) =	      \
+      THREAD_GET_HWCAP ();						      \
+    (((tcbhead_t *) ((char *) tp - TLS_TCB_OFFSET))[-1].at_platform) =	      \
+      THREAD_GET_AT_PLATFORM ();
 
 /* Return the address of the dtv for the current thread.  */
 # define THREAD_DTV() \
@@ -203,6 +227,20 @@ register void *__thread_register __asm__ ("r13");
 # define THREAD_SET_TM_CAPABLE(value) \
     (THREAD_GET_TM_CAPABLE () = (value))
 
+/* hwcap field in TCB head.  */
+# define THREAD_GET_HWCAP() \
+    (((tcbhead_t *) ((char *) __thread_register				      \
+		     - TLS_TCB_OFFSET))[-1].hwcap)
+# define THREAD_SET_HWCAP(value) \
+    (THREAD_GET_HWCAP () = (value))
+
+/* at_platform field in TCB head.  */
+# define THREAD_GET_AT_PLATFORM() \
+    (((tcbhead_t *) ((char *) __thread_register				      \
+		     - TLS_TCB_OFFSET))[-1].at_platform)
+# define THREAD_SET_AT_PLATFORM(value) \
+    (THREAD_GET_AT_PLATFORM () = (value))
+
 /* l_tls_offset == 0 is perfectly valid on PPC, so we have to use some
    different value to mean unset l_tls_offset.  */
 # define NO_TLS_OFFSET		-1
diff --git a/sysdeps/powerpc/powerpc32/dl-machine.h b/sysdeps/powerpc/powerpc32/dl-machine.h
index 8b0c067..8d2f311 100644
--- a/sysdeps/powerpc/powerpc32/dl-machine.h
+++ b/sysdeps/powerpc/powerpc32/dl-machine.h
@@ -24,6 +24,7 @@
 #include <assert.h>
 #include <dl-tls.h>
 #include <dl-irel.h>
+#include <hwcapinfo.h>
 
 /* Translate a processor specific dynamic tag to the index
    in l_info array.  */
@@ -150,6 +151,19 @@ __elf_preferred_address(struct link_map *loader, size_t maplength,
 #define ELF_MACHINE_NO_REL 1
 #define ELF_MACHINE_NO_RELA 0
 
+/* We define an initialization function to initialize HWCAP/HWCAP2 and
+   platform data so it can be copied into the TCB later.  This is called
+   very early in _dl_sysdep_start for dynamically linked binaries.  */
+#ifdef SHARED
+# define DL_PLATFORM_INIT dl_platform_init ()
+
+static inline void __attribute__ ((unused))
+dl_platform_init (void)
+{
+  __tcb_parse_hwcap_and_convert_at_platform ();
+}
+#endif
+
 /* Set up the loaded object described by MAP so its unrelocated PLT
    entries will jump to the on-demand fixup code in dl-runtime.c.
    Also install a small trampoline to be used by entries that have
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h
index 0576781..dc0f522 100644
--- a/sysdeps/powerpc/powerpc64/dl-machine.h
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h
@@ -26,6 +26,7 @@
 #include <sys/param.h>
 #include <dl-tls.h>
 #include <sysdep.h>
+#include <hwcapinfo.h>
 
 /* Translate a processor specific dynamic tag to the index
    in l_info array.  */
@@ -296,6 +297,19 @@ BODY_PREFIX "_dl_start_user:\n"						\
 #define ELF_MACHINE_NO_REL 1
 #define ELF_MACHINE_NO_RELA 0
 
+/* We define an initialization function to initialize HWCAP/HWCAP2 and
+   platform data so it can be copied into the TCB later.  This is called
+   very early in _dl_sysdep_start for dynamically linked binaries.  */
+#ifdef SHARED
+# define DL_PLATFORM_INIT dl_platform_init ()
+
+static inline void __attribute__ ((unused))
+dl_platform_init (void)
+{
+  __tcb_parse_hwcap_and_convert_at_platform ();
+}
+#endif
+
 /* Stuff for the PLT.  */
 #if _CALL_ELF != 2
 #define PLT_INITIAL_ENTRY_WORDS 3
diff --git a/sysdeps/powerpc/test-get_hwcap-static.c b/sysdeps/powerpc/test-get_hwcap-static.c
new file mode 100644
index 0000000..0acee43
--- /dev/null
+++ b/sysdeps/powerpc/test-get_hwcap-static.c
@@ -0,0 +1,23 @@
+/* Check __ppc_get_hwcap() and __ppc_get_at_plaftorm() functionality.
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Tests if the hwcap, hwcap2 and platform data are stored in the TCB.  */
+
+#define STATIC_TST_HWCAP 1
+
+#include "test-get_hwcap.c"
diff --git a/sysdeps/powerpc/test-get_hwcap.c b/sysdeps/powerpc/test-get_hwcap.c
new file mode 100644
index 0000000..11aa840
--- /dev/null
+++ b/sysdeps/powerpc/test-get_hwcap.c
@@ -0,0 +1,188 @@
+/* Check __ppc_get_hwcap() and __ppc_get_at_plaftorm() functionality.
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Tests if the hwcap, hwcap2 and platform data are stored in the TCB.  */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <pthread.h>
+
+#include <sys/auxv.h>
+
+#include <dl-procinfo.h>
+
+#ifndef STATIC_TST_HWCAP
+#undef PROCINFO_DECL
+#include <dl-procinfo.c>
+#endif
+
+/* Offsets copied from tcb-offsets.h.  */
+
+#ifdef __powerpc64__
+# define __TPREG     "r13"
+# define __HWCAPOFF -28776
+# define __ATPLATOFF -28764
+#else
+# define __TPREG     "r2"
+# define __HWCAPOFF -28736
+# define __HWCAP2OFF -28732
+# define __ATPLATOFF -28724
+#endif
+
+uint64_t check_tcbhwcap (long tid)
+{
+
+  uint32_t tcb_at_platform, at_platform;
+  uint64_t hwcap, hwcap2, tcb_hwcap;
+  const char *at_platform_string;
+
+  /* Testing if the hwcap/hwcap2 data is correctly initialized by
+     TLS_TP_INIT.  */
+
+  register unsigned long __tp __asm__ (__TPREG);
+
+#ifdef __powerpc64__
+  __asm__  ("ld %0,%1(%2)\n"
+	    : "=r" (tcb_hwcap)
+	    : "i" (__HWCAPOFF), "b" (__tp));
+#else
+  uint64_t h1, h2;
+
+  __asm__ ("lwz %0,%1(%2)\n"
+      : "=r" (h1)
+      : "i" (__HWCAPOFF), "b" (__tp));
+  __asm__ ("lwz %0,%1(%2)\n"
+      : "=r" (h2)
+      : "i" (__HWCAP2OFF), "b" (__tp));
+  tcb_hwcap = (h1 >> 32) << 32 | (h2 >> 32);
+#endif
+
+  hwcap = getauxval (AT_HWCAP);
+  hwcap2 = getauxval (AT_HWCAP2);
+
+  /* hwcap contains only the latest supported ISA, the code checks which is
+     and fills the previous supported ones.  This is necessary because the
+     same is done in hwcapinfo.c when setting the values that are copied to
+     the TCB.  */
+
+  if (hwcap2 & PPC_FEATURE2_ARCH_2_07)
+    hwcap |= PPC_FEATURE_ARCH_2_06
+	  | PPC_FEATURE_ARCH_2_05
+	  | PPC_FEATURE_POWER5_PLUS
+	  | PPC_FEATURE_POWER5
+	  | PPC_FEATURE_POWER4;
+  else if (hwcap & PPC_FEATURE_ARCH_2_06)
+    hwcap |= PPC_FEATURE_ARCH_2_05
+	  | PPC_FEATURE_POWER5_PLUS
+	  | PPC_FEATURE_POWER5
+	  | PPC_FEATURE_POWER4;
+  else if (hwcap & PPC_FEATURE_ARCH_2_05)
+    hwcap |= PPC_FEATURE_POWER5_PLUS
+	  | PPC_FEATURE_POWER5
+	  | PPC_FEATURE_POWER4;
+  else if (hwcap & PPC_FEATURE_POWER5_PLUS)
+    hwcap |= PPC_FEATURE_POWER5
+	  | PPC_FEATURE_POWER4;
+  else if (hwcap & PPC_FEATURE_POWER5)
+    hwcap |= PPC_FEATURE_POWER4;
+
+  hwcap = (hwcap << 32) + hwcap2;
+
+  if ( tcb_hwcap != hwcap )
+    {
+      printf ("FAIL: __ppc_get_hwcap() - HWCAP is %" PRIx64 ". Should be %"
+	      PRIx64 " for thread %ld.\n", tcb_hwcap, hwcap, tid);
+      return 1;
+    }
+
+  /* Same test for the platform number.  */
+  __asm__  ("lwz %0,%1(%2)\n"
+	    : "=r" (tcb_at_platform)
+	    : "i" (__ATPLATOFF), "b" (__tp));
+
+  at_platform_string = (const char *) getauxval (AT_PLATFORM);
+  at_platform = _dl_string_platform (at_platform_string);
+
+  if ( tcb_at_platform != at_platform )
+    {
+      printf ("FAIL: __ppc_get_at_platform() - AT_PLATFORM is %x. Should be %x"
+	     " for thread %ld\n", tcb_at_platform, at_platform, tid);
+      return 1;
+    }
+
+  return 0;
+}
+
+void *t1 (void *tid)
+{
+  if (check_tcbhwcap ((long) tid))
+    {
+      pthread_exit (tid);
+    }
+
+  pthread_exit (NULL);
+
+}
+
+static int
+do_test (void)
+{
+
+  pthread_t threads[2];
+  pthread_attr_t attr;
+  pthread_attr_init (&attr);
+  pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE);
+  void *status;
+
+  long i = 0;
+
+  /* Check for main.  */
+  if (check_tcbhwcap (i))
+    {
+      return 1;
+    }
+
+  /* Check for other thread.  */
+  i++;
+  if (pthread_create (&threads[i], &attr, t1, (void *)i))
+    {
+      printf ("FAIL: error creating thread %ld.\n", i);
+      return 1;
+    }
+
+  pthread_attr_destroy (&attr);
+  if (pthread_join (threads[i], &status))
+    {
+      printf ("FAIL: error joining thread %ld.\n", i);
+      return 1;
+    }
+  if (status)
+    {
+      return 1;
+    }
+
+  printf("PASS: HWCAP, HWCAP2 and AT_PLATFORM are correctly set in the TCB for"
+	 " all threads.\n");
+
+  pthread_exit (NULL);
+
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/unix/sysv/linux/powerpc/libc-start.c b/sysdeps/unix/sysv/linux/powerpc/libc-start.c
index a9364c7..209a16d 100644
--- a/sysdeps/unix/sysv/linux/powerpc/libc-start.c
+++ b/sysdeps/unix/sysv/linux/powerpc/libc-start.c
@@ -20,6 +20,9 @@
 #include <ldsodefs.h>
 #include <sysdep.h>
 
+#ifndef SHARED
+#include <hwcapinfo.h>
+#endif
 
 int __cache_line_size attribute_hidden;
 /* The main work is done in the generic function.  */
@@ -68,15 +71,34 @@ __libc_start_main (int argc, char **argv,
       rtld_fini = NULL;
     }
 
-  /* Initialize the __cache_line_size variable from the aux vector.  */
+  /* Initialize the __cache_line_size variable from the aux vector.  For the
+     static case, we also need _dl_hwcap, _dl_hwcap2 and _dl_platform, so we
+     can call __tcb_parse_hwcap_and_convert_at_platform ().  */
   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;
+#ifndef SHARED
+      case AT_HWCAP:
+	_dl_hwcap = (unsigned long int) av->a_un.a_val;
+	break;
+      case AT_HWCAP2:
+	_dl_hwcap2 = (unsigned long int) av->a_un.a_val;
+	break;
+      case AT_PLATFORM:
+	_dl_platform = (void *) av->a_un.a_val;
+	break;
+#endif
       }
 
+  /* Initialize hwcap/hwcap2 and platform data so it can be copied to
+     the TCB later in __libc_setup_tls (). (static case only).  */
+#ifndef SHARED
+  __tcb_parse_hwcap_and_convert_at_platform ();
+#endif
+
   return generic_start_main (stinfo->main, argc, argv, auxvec,
 			     stinfo->init, stinfo->fini, rtld_fini,
 			     stack_on_entry);
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist
index 6f554dc..2eb4d5f 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist
@@ -10,6 +10,8 @@ GLIBC_2.1 __libc_stack_end D 0x4
 GLIBC_2.1 _dl_mcount F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 __tls_get_addr_opt F
+GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __parse_hwcap_and_convert_at_platform F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __tls_get_addr F
 GLIBC_2.4 GLIBC_2.4 A
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/ld-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/ld-le.abilist
index 15553c1..27d451b 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/ld-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/ld-le.abilist
@@ -10,3 +10,5 @@ GLIBC_2.17 malloc F
 GLIBC_2.17 realloc F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 __tls_get_addr_opt F
+GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __parse_hwcap_and_convert_at_platform F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/ld.abilist
index ca573ea..8914eb0 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/ld.abilist
@@ -1,5 +1,7 @@
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 __tls_get_addr_opt F
+GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __parse_hwcap_and_convert_at_platform F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __libc_memalign F
 GLIBC_2.3 __libc_stack_end D 0x8

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                                          |   45 +++++
 sysdeps/powerpc/Makefile                           |   11 +-
 sysdeps/powerpc/Versions                           |    5 +
 sysdeps/powerpc/hwcapinfo.c                        |   76 ++++++++
 sysdeps/powerpc/hwcapinfo.h                        |   29 +++
 sysdeps/powerpc/nptl/tcb-offsets.sym               |    8 +
 sysdeps/powerpc/nptl/tls.h                         |   44 +++++-
 sysdeps/powerpc/powerpc32/dl-machine.h             |   14 ++
 sysdeps/powerpc/powerpc64/dl-machine.h             |   14 ++
 sysdeps/powerpc/test-get_hwcap-static.c            |   23 +++
 sysdeps/powerpc/test-get_hwcap.c                   |  188 ++++++++++++++++++++
 sysdeps/unix/sysv/linux/powerpc/libc-start.c       |   24 +++-
 .../unix/sysv/linux/powerpc/powerpc32/ld.abilist   |    2 +
 .../sysv/linux/powerpc/powerpc64/ld-le.abilist     |    2 +
 .../unix/sysv/linux/powerpc/powerpc64/ld.abilist   |    2 +
 15 files changed, 480 insertions(+), 7 deletions(-)
 create mode 100644 sysdeps/powerpc/hwcapinfo.c
 create mode 100644 sysdeps/powerpc/hwcapinfo.h
 create mode 100644 sysdeps/powerpc/test-get_hwcap-static.c
 create mode 100644 sysdeps/powerpc/test-get_hwcap.c


hooks/post-receive
-- 
GNU C Library master sources



More information about the Glibc-cvs mailing list