PowerPC: Influence cpu/arch hwcap features via GLIBC_TUNABLES
[glibc.git] / sysdeps / unix / sysv / linux / powerpc / cpu-features.c
blob7c6e20e7021cd47da9972d143b9e91ed9efeb614
1 /* Initialize cpu feature data. PowerPC version.
2 Copyright (C) 2017-2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 #include <array_length.h>
20 #include <stdint.h>
21 #include <cpu-features.h>
22 #include <elf/dl-tunables.h>
23 #include <unistd.h>
24 #include <string.h>
26 static void
27 TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
29 /* The current IFUNC selection is always using the most recent
30 features which are available via AT_HWCAP or AT_HWCAP2. But in
31 some scenarios it is useful to adjust this selection.
33 The environment variable:
35 GLIBC_TUNABLES=glibc.cpu.hwcaps=-xxx,yyy,....
37 Can be used to enable HWCAP/HWCAP2 feature yyy, disable HWCAP/HWCAP2
38 feature xxx, where the feature name is case-sensitive and has to match
39 the ones mentioned in the file{sysdeps/powerpc/dl-procinfo.c}. */
41 /* Copy the features from dl_powerpc_cpu_features, which contains the
42 features provided by AT_HWCAP and AT_HWCAP2. */
43 struct cpu_features *cpu_features = &GLRO(dl_powerpc_cpu_features);
44 unsigned long int tcbv_hwcap = cpu_features->hwcap;
45 unsigned long int tcbv_hwcap2 = cpu_features->hwcap2;
46 const char *token = valp->strval;
49 const char *token_end, *feature;
50 bool disable;
51 size_t token_len, i, feature_len, offset = 0;
52 /* Find token separator or end of string. */
53 for (token_end = token; *token_end != ','; token_end++)
54 if (*token_end == '\0')
55 break;
57 /* Determine feature. */
58 token_len = token_end - token;
59 if (*token == '-')
61 disable = true;
62 feature = token + 1;
63 feature_len = token_len - 1;
65 else
67 disable = false;
68 feature = token;
69 feature_len = token_len;
71 for (i = 0; i < array_length (hwcap_tunables); ++i)
73 const char *hwcap_name = hwcap_names + offset;
74 size_t hwcap_name_len = strlen (hwcap_name);
75 /* Check the tunable name on the supported list. */
76 if (hwcap_name_len == feature_len
77 && memcmp (feature, hwcap_name, feature_len) == 0)
79 /* Update the hwcap and hwcap2 bits. */
80 if (disable)
82 /* Id is 1 for hwcap2 tunable. */
83 if (hwcap_tunables[i].id)
84 cpu_features->hwcap2 &= ~(hwcap_tunables[i].mask);
85 else
86 cpu_features->hwcap &= ~(hwcap_tunables[i].mask);
88 else
90 /* Enable the features and also check that no unsupported
91 features were enabled by user. */
92 if (hwcap_tunables[i].id)
93 cpu_features->hwcap2 |= (tcbv_hwcap2 & hwcap_tunables[i].mask);
94 else
95 cpu_features->hwcap |= (tcbv_hwcap & hwcap_tunables[i].mask);
97 break;
99 offset += hwcap_name_len + 1;
101 token += token_len;
102 /* ... and skip token separator for next round. */
103 if (*token == ',')
104 token++;
106 while (*token != '\0');
109 static inline void
110 init_cpu_features (struct cpu_features *cpu_features, uint64_t hwcaps[])
112 /* Fill the cpu_features with the supported hwcaps
113 which are set by __tcb_parse_hwcap_and_convert_at_platform. */
114 cpu_features->hwcap = hwcaps[0];
115 cpu_features->hwcap2 = hwcaps[1];
116 /* Default is to use aligned memory access on optimized function unless
117 tunables is enable, since for this case user can explicit disable
118 unaligned optimizations. */
119 int32_t cached_memfunc = TUNABLE_GET (glibc, cpu, cached_memopt, int32_t,
120 NULL);
121 cpu_features->use_cached_memopt = (cached_memfunc > 0);
122 TUNABLE_GET (glibc, cpu, hwcaps, tunable_val_t *,
123 TUNABLE_CALLBACK (set_hwcaps));