[glibc] AArch64: Add ifunc masking tunable

Wilco Dijkstra via Glibc-cvs <[email protected]> Mon, 27 Jul 2026 13:28:36 +0000 (GMT)
Newsgroups gmane.comp.lib.glibc.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=17a90edfe582be0441020987c44ec2925bc9cb10

commit 17a90edfe582be0441020987c44ec2925bc9cb10
Author: Wilco Dijkstra <[email protected]>
Date:   Mon Jul 6 12:25:23 2026 +0000

    AArch64: Add ifunc masking tunable
    
    Remove the glibc.cpu.name tunable since it's unused and out of date.
    Add support for glibc.cpu.hwcaps to adjust ifunc selection for debugging
    and benchmarking.  Only allow disabling of features that are (a) used by
    ifuncs, (b) safe to disable to a more generic ifunc without any security
    impact.
    
    Reviewed-by: Yury Khrustalev <[email protected]>

Diff:
---
 manual/tunables.texi                           | 16 ++----
 sysdeps/aarch64/dl-tunables.list               |  2 +-
 sysdeps/unix/sysv/linux/aarch64/Makefile       |  2 +-
 sysdeps/unix/sysv/linux/aarch64/cpu-features.c | 71 +++++++++++---------------
 4 files changed, 36 insertions(+), 55 deletions(-)

diff --git a/manual/tunables.texi b/manual/tunables.texi
index b53cfbf4be..713f669c4c 100644
--- a/manual/tunables.texi
+++ b/manual/tunables.texi
@@ -572,7 +572,11 @@ On powerpc, the supported HWCAP and HWCAP2 features can be found in
 On loongarch, the supported HWCAP features can be found in
 @code{sysdeps/loongarch/cpu-tunables.c}.
 
-This tunable is specific to i386, x86-64, s390x, powerpc and loongarch.
+On AArch64, the supported HWCAP features can be found in
+@code{sysdeps/unix/sysv/linux/aarch64/cpu-features.c}.
+
+This tunable is specific to i386, x86-64, s390x, powerpc, loongarch and
+aarch64.
 @end deftp
 
 @deftp Tunable glibc.cpu.cached_memopt
@@ -585,16 +589,6 @@ indicates that the process may use device memory.
 This tunable is specific to powerpc, powerpc64 and powerpc64le.
 @end deftp
 
-@deftp Tunable glibc.cpu.name
-The @code{glibc.cpu.name=xxx} tunable allows the user to tell @theglibc{} to
-assume that the CPU is @code{xxx} where xxx may have one of these values:
-@code{generic}, @code{thunderxt88}, @code{thunderx2t99},
-@code{thunderx2t99p1}, @code{ares}, @code{emag}, @code{kunpeng},
-@code{a64fx}.
-
-This tunable is specific to aarch64.
-@end deftp
-
 @deftp Tunable glibc.cpu.x86_data_cache_size
 The @code{glibc.cpu.x86_data_cache_size} tunable allows the user to set
 data cache size in bytes for use in memory and string routines.
diff --git a/sysdeps/aarch64/dl-tunables.list b/sysdeps/aarch64/dl-tunables.list
index a2ccba0b29..c876f3fe0d 100644
--- a/sysdeps/aarch64/dl-tunables.list
+++ b/sysdeps/aarch64/dl-tunables.list
@@ -18,7 +18,7 @@
 
 glibc {
   cpu {
-    name {
+    hwcaps {
       type: STRING
     }
     aarch64_bti {
diff --git a/sysdeps/unix/sysv/linux/aarch64/Makefile b/sysdeps/unix/sysv/linux/aarch64/Makefile
index d1fcb48aa2..baefac15b5 100644
--- a/sysdeps/unix/sysv/linux/aarch64/Makefile
+++ b/sysdeps/unix/sysv/linux/aarch64/Makefile
@@ -17,7 +17,7 @@ tests += \
 tests-static += \
   tst-cpu-tunable-static-pie \
   # tests-static
-tst-cpu-tunable-static-pie-TUNABLES = glibc.cpu.name=generic
+tst-cpu-tunable-static-pie-TUNABLES = glibc.cpu.hwcaps=-midr,-sve,-mops
 endif
 endif
 
diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
index 9a87332ac4..6a13638368 100644
--- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
+++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
@@ -33,56 +33,39 @@
    to see when pointer have been correctly tagged.  */
 #define MTE_ALLOWED_TAGS (0xfffe << PR_MTE_TAG_SHIFT)
 
-static const char cpu_list_name[] = {
-  "kunpeng920\0"
-  "kunpeng950\0"
-  "a64fx\0"
-  "generic\0",
-};
-
-static const uint64_t cpu_list_midr[] = {
-  0x481FD010,
-  0x480FD060,
-  0x460F0010,
-  0x0,
-};
-
-static uint64_t
-get_midr_from_mcpu (const struct tunable_str_t *mcpu)
+static void
+TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *val)
 {
-  const char *name = cpu_list_name;
-  size_t offset = 0;
-  for (int i = 0; i < array_length (cpu_list_midr); i++)
+  struct cpu_features *cpu_features = &GLRO(dl_aarch64_cpu_features);
+  struct tunable_str_comma_state_t cs;
+  tunable_str_comma_init (&cs, val);
+
+  struct tunable_str_comma_t n;
+  while (tunable_str_comma_next (&cs, &n))
     {
-      size_t len = strlen (name);
-      if (tunable_strcmp (mcpu, cpu_list_name + offset, len))
-	return cpu_list_midr[i];
-      offset += len;
+      /* Support disabling of features to select more generic ifuncs.  */
+      if (!n.disable)
+	continue;
+      if (tunable_str_comma_strcmp_cte (&n, "midr"))
+	cpu_features->midr_el1 = 0;
+      else if (tunable_str_comma_strcmp_cte (&n, "zva"))
+	cpu_features->zva_size = 0;
+      else if (tunable_str_comma_strcmp_cte (&n, "sve"))
+	cpu_features->sve = false;
+      else if (tunable_str_comma_strcmp_cte (&n, "sve2"))
+	cpu_features->sve2 = false;
+      else if (tunable_str_comma_strcmp_cte (&n, "mops"))
+	cpu_features->mops = false;
     }
-  return UINT64_MAX;
 }
 
 static inline void
 init_cpu_features (struct cpu_features *cpu_features)
 {
-  register uint64_t midr = UINT64_MAX;
-
-  /* Get the tunable override.  */
-  const struct tunable_str_t *mcpu = TUNABLE_GET (glibc, cpu, name,
-						  struct tunable_str_t *,
-						  NULL);
-  if (mcpu != NULL)
-    midr = get_midr_from_mcpu (mcpu);
-
-  /* If there was no useful tunable override, query the MIDR if the kernel
-     allows it.  */
-  if (midr == UINT64_MAX)
-    {
-      if (GLRO (dl_hwcap) & HWCAP_CPUID)
-	asm volatile ("mrs %0, midr_el1" : "=r"(midr));
-      else
-	midr = 0;
-    }
+  uint64_t midr = 0;
+
+  if (GLRO (dl_hwcap) & HWCAP_CPUID)
+    asm volatile ("mrs %0, midr_el1" : "=r"(midr));
 
   cpu_features->midr_el1 = midr;
 
@@ -108,4 +91,8 @@ init_cpu_features (struct cpu_features *cpu_features)
   if (GLRO (dl_hwcap) & HWCAP_GCS)
     /* GCS status may be updated later by binary compatibility checks.  */
     GL (dl_aarch64_gcs) = TUNABLE_GET (glibc, cpu, aarch64_gcs, uint64_t, 0);
+
+  /* Allow override by glibc.cpu.hwcaps tunable after setting features.  */
+  TUNABLE_GET (glibc, cpu, hwcaps, tunable_val_t *,
+	       TUNABLE_CALLBACK (set_hwcaps));
 }