[v3] AArch64: Add ifunc masking tunable

Message ID PAWPR08MB8982A195119525A0F275D12983F12@PAWPR08MB8982.eurprd08.prod.outlook.com (mailing list archive)
State New
Headers
Series [v3] AArch64: Add ifunc masking tunable |

Checks

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

Commit Message

Wilco Dijkstra July 6, 2026, 12:49 p.m. UTC
  v3: keep the tst-cpu-tunable-static-pie test

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 (undocumented since this is for developers only).
Only allow disabling of features that are (a) used by ifuncs, (b) safe
to disable to a more generic ifunc without any security impact.

---
  

Patch

diff --git a/manual/tunables.texi b/manual/tunables.texi
index e1d9fbae9cebe961fe45203251a761c3323a9917..17ff92501d0e0fcbb47512589289f933f1e82119 100644
--- a/manual/tunables.texi
+++ b/manual/tunables.texi
@@ -469,16 +469,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 a2ccba0b293a2d728ec6986f7ddd5b9793c1de17..c876f3fe0d4891be425f0c022e4adcaa11f86af4 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 d1fcb48aa250dffd8b7e5b41f5b290512dc797e2..baefac15b5985414a5044766048cab5e84e4636f 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 9a87332ac49c0272930200ece5276eb5a4a2fae4..6a13638368673870b9a9e35bbb43108612561ae9 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));
 }