about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--elf/dl-tunables.c24
-rw-r--r--elf/dl-tunables.h17
-rw-r--r--manual/tunables.texi8
-rw-r--r--sysdeps/aarch64/dl-tunables.list25
-rw-r--r--sysdeps/unix/sysv/linux/aarch64/cpu-features.c47
6 files changed, 106 insertions, 26 deletions
diff --git a/ChangeLog b/ChangeLog
index a95505220d..24832540b8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2017-06-30  Siddhesh Poyarekar  <siddhesh@sourceware.org>
 
+	* elf/dl-tunables.h (tunable_is_name): Move from...
+	* elf/dl-tunables.c (is_name): ... here.
+	(parse_tunables, __tunables_init): Adjust.
+	* manual/tunables.texi: Document glibc.tune.cpu.
+	* sysdeps/aarch64/dl-tunables.list: New file.
+	* sysdeps/unix/sysv/linux/aarch64/cpu-features.c (struct
+	cpu_list): New type.
+	(cpu_list): New list of CPU names and their MIDR.
+	(get_midr_from_mcpu): New function.
+	(init_cpu_features): Override MIDR if necessary.
+
 	* sysdeps/aarch64/multiarch/ifunc-impl-list.c
 	(__libc_ifunc_impl_list): Unconditionally select thunderx
 	routine for testing.
diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
index b3c1392ce4..44c160cac5 100644
--- a/elf/dl-tunables.c
+++ b/elf/dl-tunables.c
@@ -33,22 +33,6 @@
 # define GLIBC_TUNABLES "GLIBC_TUNABLES"
 #endif
 
-/* Compare environment or tunable names, bounded by the name hardcoded in
-   glibc.  */
-static bool
-is_name (const char *orig, const char *envname)
-{
-  for (;*orig != '\0' && *envname != '\0'; envname++, orig++)
-    if (*orig != *envname)
-      break;
-
-  /* The ENVNAME is immediately followed by a value.  */
-  if (*orig == '\0' && *envname == '=')
-    return true;
-  else
-    return false;
-}
-
 #if TUNABLES_FRONTEND == TUNABLES_FRONTEND_valstring
 static char *
 tunables_strdup (const char *in)
@@ -235,7 +219,7 @@ parse_tunables (char *tunestr, char *valstring)
 	{
 	  tunable_t *cur = &tunable_list[i];
 
-	  if (is_name (cur->name, name))
+	  if (tunable_is_name (cur->name, name))
 	    {
 	      /* If we are in a secure context (AT_SECURE) then ignore the tunable
 		 unless it is explicitly marked as secure.  Tunable values take
@@ -318,7 +302,7 @@ __tunables_init (char **envp)
 			       &prev_envp)) != NULL)
     {
 #if TUNABLES_FRONTEND == TUNABLES_FRONTEND_valstring
-      if (is_name (GLIBC_TUNABLES, envname))
+      if (tunable_is_name (GLIBC_TUNABLES, envname))
 	{
 	  char *new_env = tunables_strdup (envname);
 	  if (new_env != NULL)
@@ -341,7 +325,7 @@ __tunables_init (char **envp)
 	  const char *name = cur->env_alias;
 
 	  /* We have a match.  Initialize and move on to the next line.  */
-	  if (is_name (name, envname))
+	  if (tunable_is_name (name, envname))
 	    {
 	      /* For AT_SECURE binaries, we need to check the security settings of
 		 the tunable and decide whether we read the value and also whether
@@ -356,7 +340,7 @@ __tunables_init (char **envp)
 
 		      while (*ep != NULL)
 			{
-			  if (is_name (name, *ep))
+			  if (tunable_is_name (name, *ep))
 			    {
 			      char **dp = ep;
 
diff --git a/elf/dl-tunables.h b/elf/dl-tunables.h
index 6c49dcbf47..c92882acba 100644
--- a/elf/dl-tunables.h
+++ b/elf/dl-tunables.h
@@ -111,5 +111,22 @@ rtld_hidden_proto (__tunable_get_val)
 # define TUNABLES_FRONTEND_valstring 1
 /* The default value for TUNABLES_FRONTEND.  */
 # define TUNABLES_FRONTEND_yes TUNABLES_FRONTEND_valstring
+
+/* Compare two name strings, bounded by the name hardcoded in glibc.  */
+static inline bool
+__always_inline
+tunable_is_name (const char *orig, const char *envname)
+{
+  for (;*orig != '\0' && *envname != '\0'; envname++, orig++)
+    if (*orig != *envname)
+      break;
+
+  /* The ENVNAME is immediately followed by a value.  */
+  if (*orig == '\0' && *envname == '=')
+    return true;
+  else
+    return false;
+}
+
 #endif
 #endif
diff --git a/manual/tunables.texi b/manual/tunables.texi
index 689e8941e7..9331b03702 100644
--- a/manual/tunables.texi
+++ b/manual/tunables.texi
@@ -231,6 +231,14 @@ the ones in @code{sysdeps/x86/cpu-features.h}.
 This tunable is specific to i386 and x86-64.
 @end deftp
 
+@deftp Tunable glibc.tune.cpu
+The @code{glibc.tune.cpu=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}.
+
+This tunable is specific to aarch64.
+@end deftp
+
 @deftp Tunable glibc.tune.x86_data_cache_size
 The @code{glibc.tune.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
new file mode 100644
index 0000000000..b1da2bfdfe
--- /dev/null
+++ b/sysdeps/aarch64/dl-tunables.list
@@ -0,0 +1,25 @@
+# aarch64 specific tunables.
+# Copyright (C) 2017 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/>.
+
+glibc {
+  tune {
+    cpu {
+      type: STRING
+    }
+  }
+}
diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
index ef6eecd17e..47c7d97185 100644
--- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
+++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
@@ -20,18 +20,53 @@
 #include <sys/auxv.h>
 #include <elf/dl-hwcaps.h>
 
+#if HAVE_TUNABLES
+struct cpu_list
+{
+  const char *name;
+  uint64_t midr;
+};
+
+static struct cpu_list cpu_list[] = {
+      {"thunderxt88",	0x430F0A10},
+      {"generic", 	0x0}
+};
+
+static uint64_t
+get_midr_from_mcpu (const char *mcpu)
+{
+  for (int i = 0; i < sizeof (cpu_list) / sizeof (struct cpu_list); i++)
+    if (tunable_is_name (mcpu, cpu_list[i].name) == 0)
+      return cpu_list[i].midr;
+
+  return UINT64_MAX;
+}
+#endif
+
 static inline void
 init_cpu_features (struct cpu_features *cpu_features)
 {
   uint64_t hwcap_mask = GET_HWCAP_MASK();
   uint64_t hwcap = GLRO (dl_hwcap) & hwcap_mask;
 
-  if (hwcap & HWCAP_CPUID)
+  register uint64_t midr = UINT64_MAX;
+
+#if HAVE_TUNABLES
+  /* Get the tunable override.  */
+  const char *mcpu = TUNABLE_GET (glibc, tune, mcpu, const char *, NULL);
+  if (mcpu != NULL)
+    midr = get_midr_from_mcpu (mcpu);
+#endif
+
+  /* If there was no useful tunable override, query the MIDR if the kernel
+     allows it.  */
+  if (midr == UINT64_MAX)
     {
-      register uint64_t id = 0;
-      asm volatile ("mrs %0, midr_el1" : "=r"(id));
-      cpu_features->midr_el1 = id;
+      if (hwcap & HWCAP_CPUID)
+	asm volatile ("mrs %0, midr_el1" : "=r"(midr));
+      else
+	midr = 0;
     }
-  else
-    cpu_features->midr_el1 = 0;
+
+  cpu_features->midr_el1 = midr;
 }