or1k: Add prctl wrapper to unwrap variadic args
[glibc.git] / sysdeps / x86 / cpu-tunables.c
blob89da7a03daa665f64054a821e7bc3a517ef036a3
1 /* x86 CPU feature tuning.
2 This file is part of the GNU C Library.
3 Copyright (C) 2017-2024 Free Software Foundation, Inc.
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 #define TUNABLE_NAMESPACE cpu
20 #include <stdbool.h>
21 #include <stdint.h>
22 #include <unistd.h> /* Get STDOUT_FILENO for _dl_printf. */
23 #include <elf/dl-tunables.h>
24 #include <string.h>
25 #include <cpu-features.h>
26 #include <ldsodefs.h>
27 #include <dl-tunables-parse.h>
28 #include <dl-symbol-redir-ifunc.h>
30 #define CHECK_GLIBC_IFUNC_CPU_OFF(f, cpu_features, name, len) \
31 _Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \
32 if (tunable_str_comma_strcmp_cte (&f, #name)) \
33 { \
34 CPU_FEATURE_UNSET (cpu_features, name) \
35 break; \
38 #define CHECK_GLIBC_IFUNC_CPU_BOTH(f, cpu_features, name, len) \
39 _Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \
40 if (tunable_str_comma_strcmp_cte (&f, #name)) \
41 { \
42 if (f.disable) \
43 CPU_FEATURE_UNSET (cpu_features, name) \
44 else \
45 CPU_FEATURE_SET_ACTIVE (cpu_features, name) \
46 break; \
49 /* Disable a preferred feature NAME. We don't enable a preferred feature
50 which isn't available. */
51 #define CHECK_GLIBC_IFUNC_PREFERRED_OFF(f, cpu_features, name, len) \
52 _Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \
53 if (tunable_str_comma_strcmp_cte (&f, #name)) \
54 { \
55 cpu_features->preferred[index_arch_##name] \
56 &= ~bit_arch_##name; \
57 break; \
60 /* Enable/disable a preferred feature NAME. */
61 #define CHECK_GLIBC_IFUNC_PREFERRED_BOTH(f, cpu_features, name, len) \
62 _Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \
63 if (tunable_str_comma_strcmp_cte (&f, #name)) \
64 { \
65 if (f.disable) \
66 cpu_features->preferred[index_arch_##name] &= ~bit_arch_##name; \
67 else \
68 cpu_features->preferred[index_arch_##name] |= bit_arch_##name; \
69 break; \
72 /* Enable/disable a preferred feature NAME. Enable a preferred feature
73 only if the feature NEED is usable. */
74 #define CHECK_GLIBC_IFUNC_PREFERRED_NEED_BOTH(f, cpu_features, name, \
75 need, len) \
76 _Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \
77 if (tunable_str_comma_strcmp_cte (&f, #name)) \
78 { \
79 if (f.disable) \
80 cpu_features->preferred[index_arch_##name] &= ~bit_arch_##name; \
81 else if (CPU_FEATURE_USABLE_P (cpu_features, need)) \
82 cpu_features->preferred[index_arch_##name] |= bit_arch_##name; \
83 break; \
86 attribute_hidden
87 void
88 TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
90 /* The current IFUNC selection is based on microbenchmarks in glibc.
91 It should give the best performance for most workloads. But other
92 choices may have better performance for a particular workload or on
93 the hardware which wasn't available when the selection was made.
94 The environment variable:
96 GLIBC_TUNABLES=glibc.cpu.hwcaps=-xxx,yyy,-zzz,....
98 can be used to enable CPU/ARCH feature yyy, disable CPU/ARCH feature
99 yyy and zzz, where the feature name is case-sensitive and has to
100 match the ones in cpu-features.h. It can be used by glibc developers
101 to tune for a new processor or override the IFUNC selection to
102 improve performance for a particular workload.
104 NOTE: the IFUNC selection may change over time. Please check all
105 multiarch implementations when experimenting. */
107 struct cpu_features *cpu_features = &GLRO(dl_x86_cpu_features);
109 struct tunable_str_comma_state_t ts;
110 tunable_str_comma_init (&ts, valp);
112 struct tunable_str_comma_t n;
113 while (tunable_str_comma_next (&ts, &n))
115 switch (n.len)
117 default:
118 break;
119 case 3:
120 if (n.disable)
122 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, AVX, 3);
123 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, CX8, 3);
124 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, FMA, 3);
125 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, HTT, 3);
126 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, IBT, 3);
127 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, RTM, 3);
129 break;
130 case 4:
131 if (n.disable)
133 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, AVX2, 4);
134 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, BMI1, 4);
135 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, BMI2, 4);
136 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, CMOV, 4);
137 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, ERMS, 4);
138 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, FMA4, 4);
139 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, SSE2, 4);
140 CHECK_GLIBC_IFUNC_PREFERRED_OFF (n, cpu_features, I586, 4);
141 CHECK_GLIBC_IFUNC_PREFERRED_OFF (n, cpu_features, I686, 4);
143 break;
144 case 5:
146 CHECK_GLIBC_IFUNC_CPU_BOTH (n, cpu_features, SHSTK, 5);
148 if (n.disable)
150 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, LZCNT, 5);
151 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, MOVBE, 5);
152 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, SSSE3, 5);
153 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, XSAVE, 5);
155 break;
156 case 6:
157 if (n.disable)
159 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, POPCNT, 6);
160 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, SSE4_1, 6);
161 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, SSE4_2, 6);
162 if (memcmp (n.str, "XSAVEC", 6) == 0)
164 /* Update xsave_state_size to XSAVE state size. */
165 cpu_features->xsave_state_size
166 = cpu_features->xsave_state_full_size;
167 CPU_FEATURE_UNSET (cpu_features, XSAVEC);
170 break;
171 case 7:
172 if (n.disable)
174 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, AVX512F, 7);
175 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, OSXSAVE, 7);
177 break;
178 case 8:
179 if (n.disable)
181 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, AVX512CD, 8);
182 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, AVX512BW, 8);
183 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, AVX512DQ, 8);
184 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, AVX512ER, 8);
185 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, AVX512PF, 8);
186 CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, AVX512VL, 8);
188 CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features, Slow_BSF, 8);
189 break;
190 case 11:
192 CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features, Prefer_ERMS,
193 11);
194 CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features, Prefer_FSRM,
195 11);
196 CHECK_GLIBC_IFUNC_PREFERRED_NEED_BOTH (n, cpu_features,
197 Slow_SSE4_2,
198 SSE4_2,
199 11);
201 break;
202 case 15:
204 CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features,
205 Fast_Rep_String, 15);
207 break;
208 case 16:
210 CHECK_GLIBC_IFUNC_PREFERRED_NEED_BOTH
211 (n, cpu_features, Prefer_No_AVX512, AVX512F, 16);
213 break;
214 case 18:
216 CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features,
217 Fast_Copy_Backward, 18);
219 break;
220 case 19:
222 CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features,
223 Fast_Unaligned_Load, 19);
224 CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features,
225 Fast_Unaligned_Copy, 19);
227 break;
228 case 20:
230 CHECK_GLIBC_IFUNC_PREFERRED_NEED_BOTH
231 (n, cpu_features, Prefer_No_VZEROUPPER, AVX, 20);
233 break;
234 case 23:
236 CHECK_GLIBC_IFUNC_PREFERRED_NEED_BOTH
237 (n, cpu_features, AVX_Fast_Unaligned_Load, AVX, 23);
239 break;
240 case 24:
242 CHECK_GLIBC_IFUNC_PREFERRED_NEED_BOTH
243 (n, cpu_features, MathVec_Prefer_No_AVX512, AVX512F, 24);
245 break;
246 case 26:
248 CHECK_GLIBC_IFUNC_PREFERRED_NEED_BOTH
249 (n, cpu_features, Prefer_PMINUB_for_stringop, SSE2, 26);
251 break;
256 #if CET_ENABLED
257 attribute_hidden
258 void
259 TUNABLE_CALLBACK (set_x86_ibt) (tunable_val_t *valp)
261 if (tunable_strcmp_cte (valp, "on"))
262 GL(dl_x86_feature_control).ibt = cet_always_on;
263 else if (tunable_strcmp_cte (valp, "off"))
264 GL(dl_x86_feature_control).ibt = cet_always_off;
265 else if (tunable_strcmp_cte (valp, "permissive"))
266 GL(dl_x86_feature_control).ibt = cet_permissive;
269 attribute_hidden
270 void
271 TUNABLE_CALLBACK (set_x86_shstk) (tunable_val_t *valp)
273 if (tunable_strcmp_cte (valp, "on"))
274 GL(dl_x86_feature_control).shstk = cet_always_on;
275 else if (tunable_strcmp_cte (valp, "off"))
276 GL(dl_x86_feature_control).shstk = cet_always_off;
277 else if (tunable_strcmp_cte (valp, "permissive"))
278 GL(dl_x86_feature_control).shstk = cet_permissive;
280 #endif