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]

[RFC 2.0] Implementing hwcap2


This is a followup RFC to my original RFC:

http://www.sourceware.org/ml/libc-alpha/2012-10/msg00438.html

I've pushed the following patch to rsa/hwcap2 after following the
procedure we discussed in that conversation.

I would appreciate analysis and comments on my implementation.  I've
tried to make sure I covered all existing architectures.

I'm still waiting on the kernel implementation of AT_HWCAP2, but I know
that this is 'in process' and should close soon.

There are no kernel version guards in this code, nor will there be,
since the getauxval API will simply return NULL if the kernel doesn't
support HWCAP2 at runtime.  A kernel which does support AT_HWCAP2
running under a glibc which doesn't won't cause a problem either.  The
glibc loader will simply not query the AT_HWCAP2 field.

I have a few initial concerns:

I'm presuming that the kernel will assign '26' as AT_HWCAP2.  This may
change when the feature is actually added.

There isn't a usage of hwcap2 in this patch.  There will be a later
patch which adds some feature definitions to powerpc/hwcap.h that
utilize hwcap2.

I'm not sure how useful tst-getauxval is until there is something it can
return from HWCAP2 that's not in HWCAP.  This would only be relevant to
architectures which have features defined in HWCAP2... which would
presumably only be PowerPC to start with.

Ryan S. Arnold
IBM Linux Technology Center
Linux Toolchain Development


commit ffdab8a4315b3bad9fba1f328ed84bb4888bf017
Author: Ryan S. Arnold <rsa@linux.vnet.ibm.com>
Date:   Tue Mar 26 14:00:31 2013 -0500

    Add HWCAP2 support.

diff --git a/ChangeLog b/ChangeLog
index f7f83fb..672475a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2013-03-26  Ryan S. Arnold  <rsa@linux.vnet.ibm.com>
+
+	* elf/dl-cache.c: Include stdint.h for uint64_t.
+	* elf/dl-hwcaps.c: Likewise.
+	* elf/dl-support.c: Likewise.
+	(_dl_aux_init): Add new case for AT_HWCAP2 and 'or' together with
+	AT_HWCAP.
+	* elf/dl-sysdep.c (_dl_sysdep_start): Likewise.
+	(_dl_show_auxv): Add display string for HWCAP2 and display handling
+	code for AT_HWCAP2.
+	* elf/elf.h (AT_HWCAP2): New AT_* definition.
+	* misc/Makefile (tests): Add tst-getauxval.
+	* misc/getauxval.c (__getauxval):  Add return case for AT_HWCAP2.
+	* misc/tst-getauxval.c: New file.
+	* sysdeps/s390/s390-32/multiarch/ifunc-resolve.c: Include stdint.h for
+	uint64_t.
+	(resolve_##FUNC): Change IFUNC resolver to take uint64_t parameter
+	rather than unsigned long int for dl_hwcap.
+	* sysdeps/s390/s390-64/multiarch/ifunc-resolve.c: Likewise.
+	* sysdeps/sparc/sparc64/multiarch/ifunc-impl-list.c: Include stdint.h
+	for uint64_t.
+	(__libc_ifunc_impl_list): Change local int variable hwcap to uint64_t.
+	* sysdeps/unix/sysv/linux/sparc/getshmlba.c: Include stdint.h for
+	uint64_t.
+
 2013-03-26  Siddhesh Poyarekar  <siddhesh@redhat.com>
 
 	* sysdeps/ieee754/dbl-64/mpa.c (__acr): Use integral
diff --git a/elf/dl-cache.c b/elf/dl-cache.c
index 030fdca..0b68d18 100644
--- a/elf/dl-cache.c
+++ b/elf/dl-cache.c
@@ -22,7 +22,7 @@
 #include <sys/mman.h>
 #include <dl-cache.h>
 #include <dl-procinfo.h>
-
+#include <stdint.h>
 #include <_itoa.h>
 
 #ifndef _DL_PLATFORMS_COUNT
diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c
index 8d49383..3fbe30d 100644
--- a/elf/dl-hwcaps.c
+++ b/elf/dl-hwcaps.c
@@ -22,7 +22,7 @@
 #include <libintl.h>
 #include <unistd.h>
 #include <ldsodefs.h>
-
+#include <stdint.h>
 #include <dl-procinfo.h>
 
 #ifdef _DL_FIRST_PLATFORM
diff --git a/elf/dl-support.c b/elf/dl-support.c
index ad9b4c4..96dd7be 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -33,6 +33,7 @@
 #include <unsecvars.h>
 #include <hp-timing.h>
 #include <stackinfo.h>
+#include <stdint.h>
 
 extern char *__progname;
 char **_dl_argv = &__progname;	/* This is checked for some error messages.  */
@@ -211,8 +212,12 @@ _dl_aux_init (ElfW(auxv_t) *av)
 	GL(dl_phnum) = av->a_un.a_val;
 	break;
       case AT_HWCAP:
-	GLRO(dl_hwcap) = (unsigned long int) av->a_un.a_val;
+	GLRO(dl_hwcap) |= (unsigned long int) av->a_un.a_val;
 	break;
+      case AT_HWCAP2:
+	GLRO(dl_hwcap) |= ((uint64_t) av->a_un.a_val) << 32;
+	break;
+
 #ifdef NEED_DL_SYSINFO
       case AT_SYSINFO:
 	GL(dl_sysinfo) = av->a_un.a_val;
diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c
index d8f3dd2..d4edd73 100644
--- a/elf/dl-sysdep.c
+++ b/elf/dl-sysdep.c
@@ -43,6 +43,7 @@
 #include <dl-osinfo.h>
 #include <hp-timing.h>
 #include <tls.h>
+#include <stdint.h>
 
 extern char **_environ attribute_hidden;
 extern char _end[] attribute_hidden;
@@ -154,7 +155,10 @@ _dl_sysdep_start (void **start_argptr,
 	GLRO(dl_platform) = (void *) av->a_un.a_val;
 	break;
       case AT_HWCAP:
-	GLRO(dl_hwcap) = (unsigned long int) av->a_un.a_val;
+	GLRO(dl_hwcap) |= (unsigned long int) av->a_un.a_val;
+	break;
+      case AT_HWCAP2:
+	GLRO(dl_hwcap) |= ((uint64_t) av->a_un.a_val) << 32;
 	break;
       case AT_CLKTCK:
 	GLRO(dl_clktck) = av->a_un.a_val;
@@ -298,6 +302,7 @@ _dl_show_auxv (void)
 	  [AT_SYSINFO - 2] =		{ "SYSINFO:      0x", hex },
 	  [AT_SYSINFO_EHDR - 2] =	{ "SYSINFO_EHDR: 0x", hex },
 	  [AT_RANDOM - 2] =		{ "RANDOM:       0x", hex },
+	  [AT_HWCAP2 - 2] =		{ "HWCAP2:       ", hex },
 	};
       unsigned int idx = (unsigned int) (av->a_type - 2);
 
@@ -309,7 +314,7 @@ _dl_show_auxv (void)
       assert (AT_NULL == 0);
       assert (AT_IGNORE == 1);
 
-      if (av->a_type == AT_HWCAP)
+      if (av->a_type == AT_HWCAP || av->a_type == AT_HWCAP2)
 	{
 	  /* This is handled special.  */
 	  if (_dl_procinfo (av->a_un.a_val) == 0)
diff --git a/elf/elf.h b/elf/elf.h
index d096a97..f69612a 100644
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -1014,6 +1014,9 @@ typedef struct
 
 #define AT_RANDOM	25		/* Address of 16 random bytes.  */
 
+#define AT_HWCAP2	26		/* Extended machine dependent hints
+					   about processor capabilities.  */
+
 #define AT_EXECFN	31		/* Filename of executable.  */
 
 /* Pointer to the global system page used for system calls and other
diff --git a/misc/Makefile b/misc/Makefile
index 5df70e6..c4ff1f1 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -76,7 +76,8 @@ install-lib := libbsd-compat.a libg.a
 gpl2lgpl := error.c error.h
 
 tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \
-	 tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1
+	 tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1 \
+	 tst-getauxval
 ifeq ($(run-built-tests),yes)
 tests: $(objpfx)tst-error1-mem
 endif
diff --git a/misc/getauxval.c b/misc/getauxval.c
index 4321e37..0d69922 100644
--- a/misc/getauxval.c
+++ b/misc/getauxval.c
@@ -26,6 +26,8 @@ __getauxval (unsigned long int type)
 
   if (type == AT_HWCAP)
     return GLRO(dl_hwcap);
+  else if (type == AT_HWCAP2)
+    return GLRO(dl_hwcap) >> 32;
 
   for (p = GLRO(dl_auxv); p->a_type != AT_NULL; p++)
     if (p->a_type == type)
diff --git a/misc/tst-getauxval.c b/misc/tst-getauxval.c
new file mode 100644
index 0000000..34c6c5e
--- /dev/null
+++ b/misc/tst-getauxval.c
@@ -0,0 +1,33 @@
+/* Test AT_HWCAP2 with getauxval.
+   Copyright (C) 2013 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 <sys/auxv.h>
+#include <elf.h>
+
+static int
+do_test (void)
+{
+
+  unsigned long int hwcap2;
+  hwcap2 = getauxval (AT_HWCAP2);
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/s390/s390-32/multiarch/ifunc-resolve.c b/sysdeps/s390/s390-32/multiarch/ifunc-resolve.c
index d57a907..588f785 100644
--- a/sysdeps/s390/s390-32/multiarch/ifunc-resolve.c
+++ b/sysdeps/s390/s390-32/multiarch/ifunc-resolve.c
@@ -19,6 +19,7 @@
 
 #include <unistd.h>
 #include <dl-procinfo.h>
+#include <stdint.h>
 
 #define STFLE_BITS_Z10  34 /* General instructions extension */
 #define STFLE_BITS_Z196 45 /* Distinct operands, pop ... */
@@ -38,7 +39,7 @@
   extern void *FUNC##_z10 attribute_hidden;				\
   extern void *FUNC##_g5 attribute_hidden;				\
 									\
-  void *resolve_##FUNC (unsigned long int dl_hwcap)			\
+  void *resolve_##FUNC (uint64_t dl_hwcap)				\
   {									\
     if ((dl_hwcap & HWCAP_S390_STFLE)					\
 	&& (dl_hwcap & HWCAP_S390_ZARCH)				\
diff --git a/sysdeps/s390/s390-64/multiarch/ifunc-resolve.c b/sysdeps/s390/s390-64/multiarch/ifunc-resolve.c
index 14d9c13..5a9aa3d 100644
--- a/sysdeps/s390/s390-64/multiarch/ifunc-resolve.c
+++ b/sysdeps/s390/s390-64/multiarch/ifunc-resolve.c
@@ -19,6 +19,7 @@
 
 #include <unistd.h>
 #include <dl-procinfo.h>
+#include <stdint.h>
 
 #define STFLE_BITS_Z10  34 /* General instructions extension */
 #define STFLE_BITS_Z196 45 /* Distinct operands, pop ... */
@@ -38,7 +39,7 @@
   extern void *FUNC##_z10 attribute_hidden;				\
   extern void *FUNC##_z900 attribute_hidden;				\
 									\
-  void *resolve_##FUNC (unsigned long int dl_hwcap)			\
+  void *resolve_##FUNC (uint64_t dl_hwcap)				\
   {									\
     if (dl_hwcap & HWCAP_S390_STFLE)					\
       {									\
diff --git a/sysdeps/sparc/sparc64/multiarch/ifunc-impl-list.c b/sysdeps/sparc/sparc64/multiarch/ifunc-impl-list.c
index 2f7a4a9..8004049 100644
--- a/sysdeps/sparc/sparc64/multiarch/ifunc-impl-list.c
+++ b/sysdeps/sparc/sparc64/multiarch/ifunc-impl-list.c
@@ -22,6 +22,7 @@
 #include <ldsodefs.h>
 #include <sysdep.h>
 #include <ifunc-impl-list.h>
+#include <stdint.h>
 
 /* Fill ARRAY of MAX elements with IFUNC implementations for function
    NAME and return the number of valid entries.  */
@@ -31,7 +32,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 			size_t max)
 {
   size_t i = 0;
-  int hwcap;
+  uint64_t hwcap;
 
   hwcap = GLRO(dl_hwcap);
 
diff --git a/sysdeps/unix/sysv/linux/sparc/getshmlba.c b/sysdeps/unix/sysv/linux/sparc/getshmlba.c
index 5affa4b..71b4c7c 100644
--- a/sysdeps/unix/sysv/linux/sparc/getshmlba.c
+++ b/sysdeps/unix/sysv/linux/sparc/getshmlba.c
@@ -18,6 +18,7 @@
 #include <unistd.h>
 #include <sys/shm.h>
 #include <ldsodefs.h>
+#include <stdint.h>
 
 int
 __getshmlba (void)




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