diff options
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | elf/dl-tunables.c | 24 | ||||
-rw-r--r-- | elf/dl-tunables.h | 17 | ||||
-rw-r--r-- | manual/tunables.texi | 8 | ||||
-rw-r--r-- | sysdeps/aarch64/dl-tunables.list | 25 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/aarch64/cpu-features.c | 47 |
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; } |