Linux: Call dl_hwcap_check earlier, before full auxiliary vector parse

Message ID 8734pb4qr2.fsf@oldenburg.str.redhat.com
State Superseded
Headers
Series Linux: Call dl_hwcap_check earlier, before full auxiliary vector parse |

Checks

Context Check Description
redhat-pt-bot/TryBot-apply_patch success Patch applied to master at the time it was sent
linaro-tcwg-bot/tcwg_glibc_build--master-arm success Build passed
redhat-pt-bot/TryBot-32bit success Build for i686
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_glibc_check--master-arm success Test passed
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 success Test passed

Commit Message

Florian Weimer June 17, 2024, 1:56 p.m. UTC
  The full parsing routine may need the memset function, which could
require non-baseline ISA support.

---
 sysdeps/generic/dl-hwcap-check.h              |  5 ++++-
 sysdeps/powerpc/powerpc64/le/dl-hwcap-check.h | 24 ++++++++++++++++++++----
 sysdeps/s390/s390-64/dl-hwcap-check.h         | 20 +++++++++++++++++---
 sysdeps/unix/sysv/linux/dl-sysdep.c           | 20 +++++++++++++-------
 4 files changed, 54 insertions(+), 15 deletions(-)


base-commit: ca38eff28015f376c020b4dfad5351e45be8d090
  

Comments

Andreas Schwab June 17, 2024, 2:28 p.m. UTC | #1
On Jun 17 2024, Florian Weimer wrote:

> +  {
> +    for (ElfW(auxv_t) *av = GLRO(dl_auxv); av->a_type != AT_NULL; av++)
> +      if (av->a_type == AT_HWCAP2)
> +        {
> +          dl_hwcap2 = av->a_un.a_val;
> +          break;
> +        }
> +  }

I don't think the outer braces are needed here.
  

Patch

diff --git a/sysdeps/generic/dl-hwcap-check.h b/sysdeps/generic/dl-hwcap-check.h
index 55efd129be..65dba6d1a0 100644
--- a/sysdeps/generic/dl-hwcap-check.h
+++ b/sysdeps/generic/dl-hwcap-check.h
@@ -22,7 +22,10 @@ 
 static inline void
 dl_hwcap_check (void)
 {
-  /* The generic implementation does not perform any checks.  */
+  /* The generic implementation does not perform any checks.  Specific
+     implementations may assume that GLRO(dl_auxv) has been
+     initialized (if it exists), but GLRO(dl_hwcap), GLRO(dl_hwcap2)
+     have not been set at this point.  */
 }
 
 #endif /* _DL_HWCAP_CHECK_H */
diff --git a/sysdeps/powerpc/powerpc64/le/dl-hwcap-check.h b/sysdeps/powerpc/powerpc64/le/dl-hwcap-check.h
index 6d463f0511..6f8eeb8c47 100644
--- a/sysdeps/powerpc/powerpc64/le/dl-hwcap-check.h
+++ b/sysdeps/powerpc/powerpc64/le/dl-hwcap-check.h
@@ -25,13 +25,29 @@ 
 static inline void
 dl_hwcap_check (void)
 {
+#if defined GCCMACRO_ARCH_PWR9 || defined GCCMACRO__FLOAT128_HARDWARE__ \
+  || defined GCCMACRO_ARCH_PWR10 || defined GCCMACRO__PCREL__ \
+  || defined GCCMACRO__MMA__
+  /* Early auxiliary vector parsing, to avoid ISA dependencies in
+     later full parsing.  */
+  unsigned long int dl_hwcap2 = 0;
+  {
+    for (ElfW(auxv_t) *av = GLRO(dl_auxv); av->a_type != AT_NULL; av++)
+      if (av->a_type == AT_HWCAP2)
+        {
+          dl_hwcap2 = av->a_un.a_val;
+          break;
+        }
+  }
+#endif
+
 #ifdef GCCMACRO_ARCH_PWR9
-  if ((GLRO (dl_hwcap2) & PPC_FEATURE2_ARCH_3_00) == 0)
+  if ((dl_hwcap2 & PPC_FEATURE2_ARCH_3_00) == 0)
     _dl_fatal_printf ("\
 Fatal glibc error: CPU lacks ISA 3.00 support (POWER9 or later required)\n");
 #endif
 #ifdef GCCMACRO__FLOAT128_HARDWARE__
-  if ((GLRO (dl_hwcap2) & PPC_FEATURE2_HAS_IEEE128) == 0)
+  if ((dl_hwcap2 & PPC_FEATURE2_HAS_IEEE128) == 0)
     _dl_fatal_printf ("\
 Fatal glibc error: CPU lacks float128 support (POWER 9 or later required)\n");
 #endif
@@ -39,12 +55,12 @@  Fatal glibc error: CPU lacks float128 support (POWER 9 or later required)\n");
       running on POWER9 because there are faulting PCREL instructions
       before this point.  */
 #if defined GCCMACRO_ARCH_PWR10 || defined GCCMACRO__PCREL__
-  if ((GLRO (dl_hwcap2) & PPC_FEATURE2_ARCH_3_1) == 0)
+  if ((dl_hwcap2 & PPC_FEATURE2_ARCH_3_1) == 0)
     _dl_fatal_printf ("\
 Fatal glibc error: CPU lacks ISA 3.10 support (POWER10 or later required)\n");
 #endif
 #ifdef GCCMACRO__MMA__
-  if ((GLRO (dl_hwcap2) & PPC_FEATURE2_MMA) == 0)
+  if ((dl_hwcap2 & PPC_FEATURE2_MMA) == 0)
     _dl_fatal_printf ("\
 Fatal glibc error: CPU lacks MMA support (POWER10 or later required)\n");
 #endif
diff --git a/sysdeps/s390/s390-64/dl-hwcap-check.h b/sysdeps/s390/s390-64/dl-hwcap-check.h
index 6ad3242cc9..ee67ebf76e 100644
--- a/sysdeps/s390/s390-64/dl-hwcap-check.h
+++ b/sysdeps/s390/s390-64/dl-hwcap-check.h
@@ -26,16 +26,30 @@  static inline void
 dl_hwcap_check (void)
 {
 #if defined __ARCH__
+# if GCCMACRO__ARCH__ >= 12
+  /* Early auxiliary vector parsing, to avoid ISA dependencies in
+     later full parsing.  */
+  unsigned long int dl_hwcap = 0;
+  {
+    for (ElfW(auxv_t) *av = GLRO(dl_auxv); av->a_type != AT_NULL; av++)
+      if (av->a_type == AT_HWCAP)
+        {
+          dl_hwcap = av->a_un.a_val;
+          break;
+        }
+  }
+# endif
+
 # if GCCMACRO__ARCH__ >= 14
-  if (!(GLRO(dl_hwcap) & HWCAP_S390_VXRS_PDE2))
+  if (!(dl_hwcap & HWCAP_S390_VXRS_PDE2))
     _dl_fatal_printf ("\
 Fatal glibc error: CPU lacks VXRS_PDE2 support (z16 or later required)\n");
 # elif GCCMACRO__ARCH__ >= 13
-  if (!(GLRO(dl_hwcap) & HWCAP_S390_VXRS_EXT2))
+  if (!(dl_hwcap & HWCAP_S390_VXRS_EXT2))
     _dl_fatal_printf ("\
 Fatal glibc error: CPU lacks VXRS_EXT2 support (z15 or later required)\n");
 # elif GCCMACRO__ARCH__ >= 12
-  if (!(GLRO(dl_hwcap) & HWCAP_S390_VXE))
+  if (!(dl_hwcap & HWCAP_S390_VXE))
     _dl_fatal_printf ("\
 Fatal glibc error: CPU lacks VXE support (z14 or later required)\n");
 # endif
diff --git a/sysdeps/unix/sysv/linux/dl-sysdep.c b/sysdeps/unix/sysv/linux/dl-sysdep.c
index e1b14e9eb3..c54100c8a5 100644
--- a/sysdeps/unix/sysv/linux/dl-sysdep.c
+++ b/sysdeps/unix/sysv/linux/dl-sysdep.c
@@ -70,11 +70,10 @@  struct dl_main_arguments
   ElfW(Addr) user_entry;
 };
 
-/* Separate function, so that dl_main can be called without the large
-   array on the stack.  */
+/* First part of argument parsing, up to and including GLRO(dl_auxv)
+   initialization.  */
 static void
-_dl_sysdep_parse_arguments (void **start_argptr,
-			    struct dl_main_arguments *args)
+_dl_sysdep_parse_arguments_1 (void **start_argptr)
 {
   _dl_argc = (intptr_t) *start_argptr;
   _dl_argv = (char **) (start_argptr + 1); /* Necessary aliasing violation.  */
@@ -86,7 +85,13 @@  _dl_sysdep_parse_arguments (void **start_argptr,
 	GLRO(dl_auxv) = (ElfW(auxv_t) *) (tmp + 1);
 	break;
       }
+}
 
+/* Separate function, so that dl_main can be called without the large
+   array on the stack.  */
+static void __attribute__ ((noinline))
+_dl_sysdep_parse_arguments_2 (struct dl_main_arguments *args)
+{
   dl_parse_auxv_t auxv_values = { 0, };
   _dl_parse_auxv (GLRO(dl_auxv), auxv_values);
 
@@ -102,11 +107,12 @@  _dl_sysdep_start (void **start_argptr,
 {
   __libc_stack_end = DL_STACK_END (start_argptr);
 
-  struct dl_main_arguments dl_main_args;
-  _dl_sysdep_parse_arguments (start_argptr, &dl_main_args);
-
+  _dl_sysdep_parse_arguments_1 (start_argptr);
   dl_hwcap_check ();
 
+  struct dl_main_arguments dl_main_args;
+  _dl_sysdep_parse_arguments_2 (&dl_main_args);
+
   __tunables_init (_environ);
 
   /* Initialize DSO sorting algorithm after tunables.  */