diff options
author | Siddhesh Poyarekar <siddhesh@sourceware.org> | 2017-06-30 22:58:39 +0530 |
---|---|---|
committer | Siddhesh Poyarekar <siddhesh@sourceware.org> | 2017-06-30 22:58:39 +0530 |
commit | 28cfa3a48e59f9c6b9bc25a003a4ede435841382 (patch) | |
tree | ec2c7a24f4fd2a0d8b4e2ead2dabc36b6b3c3cf9 /sysdeps/unix | |
parent | ab85da15301c552e3ea4577a6432aa028bee9295 (diff) | |
download | glibc-28cfa3a48e59f9c6b9bc25a003a4ede435841382.tar.gz glibc-28cfa3a48e59f9c6b9bc25a003a4ede435841382.tar.xz glibc-28cfa3a48e59f9c6b9bc25a003a4ede435841382.zip |
tunables, aarch64: New tunable to override cpu
Add a new tunable (glibc.tune.cpu) to override CPU identification on aarch64. This is useful in two cases: one where it is desirable to pretend to be another CPU for purposes of testing or because routines written for that CPU are beneficial for specific workloads and second where the underlying kernel does not support emulation of MRS to get the MIDR of the CPU. * 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.
Diffstat (limited to 'sysdeps/unix')
-rw-r--r-- | sysdeps/unix/sysv/linux/aarch64/cpu-features.c | 47 |
1 files changed, 41 insertions, 6 deletions
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; } |