1010#include <sys/sysctl.h>
1111#endif
1212
13- static bool safe_try_feature (bool (* try_feature )(void ));
13+ static bool safe_try_feature (bool (* try_feature )(void ), bool is_exempt );
1414
1515static bool any_fails = false;
1616
1717#if __HAVE_FUNCTION_MULTI_VERSIONING
18- #define CHECK (FN_NAME_SUFFIX , FMV_FEATURE , TARGET_GUARD , BODY ) \
18+ #define CHECK (FN_NAME_SUFFIX , FMV_FEATURE , TARGET_GUARD , IS_EXEMPT , BODY ) \
1919 __attribute__((target(#TARGET_GUARD))) \
2020 static bool try_##FN_NAME_SUFFIX(void) { \
2121 do \
@@ -27,7 +27,8 @@ static bool any_fails = false;
2727 static void check_##FN_NAME_SUFFIX(void) { \
2828 printf("%s\n", #FMV_FEATURE); \
2929 fflush(stdout); \
30- if (!safe_try_feature(try_##FN_NAME_SUFFIX)) { \
30+ /* non-default versions are never exempt from diagnostics */ \
31+ if (!safe_try_feature (try_ ##FN_NAME_SUFFIX , false)) { \
3132 printf("\tFAIL\n"); \
3233 any_fails = true; \
3334 } \
@@ -36,58 +37,59 @@ static bool any_fails = false;
3637 static void check_##FN_NAME_SUFFIX(void) { \
3738 printf("%s\n", #FMV_FEATURE); \
3839 fflush(stdout); \
39- if (safe_try_feature(try_##FN_NAME_SUFFIX)) { \
40+ /* default versions are allowed to UPASS when IS_EXEMPT = true */ \
41+ if (safe_try_feature (try_ ##FN_NAME_SUFFIX , IS_EXEMPT)) { \
4042 printf("\tUPASS\n"); \
4143 any_fails = true; \
4244 } \
4345 }
4446#else
45- #define CHECK (FN_NAME_SUFFIX , FMV_FEATURE , TARGET_GUARD , BODY ) \
47+ #define CHECK (FN_NAME_SUFFIX , FMV_FEATURE , TARGET_GUARD , IS_EXEMPT , BODY ) \
4648 static void check_##FN_NAME_SUFFIX(void) { \
4749 printf("%s\n", #FMV_FEATURE); \
4850 }
4951#endif
5052
51- CHECK (flagm , flagm , flagm , {
53+ CHECK (flagm , flagm , flagm , false, {
5254 asm volatile (
5355 "cfinv" "\n"
5456 "cfinv" "\n"
5557 );
5658})
57- CHECK (flagm2 , flagm2 , arch = armv8 .5 - a , {
59+ CHECK (flagm2 , flagm2 , arch = armv8 .5 - a , false, {
5860 asm volatile (
5961 "axflag" "\n"
6062 "xaflag" "\n"
6163 );
6264})
63- CHECK (dotprod , dotprod , dotprod , {
65+ CHECK (dotprod , dotprod , dotprod , false, {
6466 asm volatile (
6567 "udot v0.4S,v1.16B,v2.16B"
6668 : : : "v0"
6769 );
6870})
69- CHECK (sha3 , sha3 , sha3 , {
71+ CHECK (sha3 , sha3 , sha3 , false, {
7072 asm volatile (
7173 "fmov d0, #0" "\n"
7274 "fmov d1, #0" "\n"
7375 "eor3 v0.16b, v0.16b, v0.16b, v0.16b" "\n"
7476 : : : "v0"
7577 );
7678})
77- CHECK (rdm , rdm , rdm , {
79+ CHECK (rdm , rdm , rdm , false, {
7880 asm volatile (
7981 "sqrdmlah s0, s1, s2"
8082 : : : "s0"
8183 );
8284})
83- CHECK (lse , lse , lse , {
85+ CHECK (lse , lse , lse , false, {
8486 uint64_t pointee = 0 ;
8587 asm volatile (
8688 "swp xzr, xzr, [%[pointee]]"
8789 : : [pointee ]"r" (& pointee )
8890 );
8991})
90- CHECK (sha2 , sha2 , sha2 , {
92+ CHECK (sha2 , sha2 , sha2 , false, {
9193 asm volatile (
9294 "fmov d0, #0" "\n"
9395 "fmov d1, #0" "\n"
@@ -96,96 +98,101 @@ CHECK(sha2, sha2, sha2, {
9698 : : : "v0"
9799 );
98100})
99- CHECK (aes , aes , aes , {
101+ CHECK (aes , aes , aes , false, {
100102 asm volatile (
101103 "fmov d0, #0" "\n"
102104 "fmov d1, #0" "\n"
103105 "aesd v0.16B, v0.16B" "\n"
104106 : : : "v0"
105107 );
106108})
107- CHECK (pmull , pmull , aes , {
109+ CHECK (pmull , pmull , aes , false, {
108110 asm volatile (
109111 "fmov d0, #0" "\n"
110112 "pmull v0.1q, v0.1d, v0.1d" "\n"
111113 : : : "v0"
112114 );
113115})
114- CHECK (rcpc , rcpc , rcpc , {
116+ CHECK (rcpc , rcpc , rcpc , false, {
115117 int x ;
116118 asm volatile (
117119 "ldaprb w0, [%0]"
118120 : : "r" (& x ) : "w0"
119121 );
120122})
121- CHECK (rcpc2 , rcpc2 , arch = armv8 .4 - a , {
123+ CHECK (rcpc2 , rcpc2 , arch = armv8 .4 - a , false, {
122124 int x ;
123125 asm volatile (
124126 "mov x1, %0" "\n"
125127 "ldapurb w0, [x1]" "\n"
126128 : : "r" (& x ) : "w0" , "x1"
127129 );
128130})
129- CHECK (fcma , fcma , fcma , {
131+ CHECK (fcma , fcma , fcma , false, {
130132 asm volatile (
131133 "fmov d0, #0" "\n"
132134 "fcadd v0.2s, v0.2s, v0.2s, #90" "\n"
133135 : : : "v0"
134136 );
135137})
136- CHECK (jscvt , jscvt , jscvt , {
138+ CHECK (jscvt , jscvt , jscvt , false, {
137139 asm volatile (
138140 "fmov d0, #0" "\n"
139141 "fjcvtzs w1, d0" "\n"
140142 : : : "w1" , "d0"
141143 );
142144})
143- CHECK (dpb , dpb , arch = armv8 .2 - a , {
145+ CHECK (dpb , dpb , arch = armv8 .2 - a , false, {
144146 int x ;
145147 asm volatile (
146148 "dc cvap, %0"
147149 : : "r" (& x )
148150 );
149151})
150- CHECK (dpb2 , dpb2 , arch = armv8 .5 - a , {
152+ CHECK (dpb2 , dpb2 , arch = armv8 .5 - a , false, {
151153 int x ;
152154 asm volatile (
153155 "dc cvadp, %0"
154156 : : "r" (& x )
155157 );
156158})
157- CHECK (bf16 , bf16 , bf16 , {
159+ CHECK (bf16 , bf16 , bf16 , false, {
158160 asm volatile (
159161 "bfdot v0.4S,v1.8H,v2.8H"
160162 : : : "v0"
161163 );
162164})
163- CHECK (i8mm , i8mm , i8mm , {
165+ CHECK (i8mm , i8mm , i8mm , false, {
164166 asm volatile (
165167 "sudot v0.4S,v1.16B,v2.4B[0]"
166168 : : : "v0"
167169 );
168170})
169- CHECK (dit , dit , dit , {
171+ CHECK (dit , dit , dit , false, {
170172 asm volatile (
171173 "msr DIT, x0"
172174 : : : "x0"
173175 );
174176})
175- CHECK (fp16 , fp16 , fp16 , {
177+ CHECK (fp16 , fp16 , fp16 , false, {
176178 asm volatile (
177179 "fmov h0, #0"
178180 : : : "v0"
179181 );
180182})
181- CHECK (ssbs2 , ssbs2 , ssbs , {
183+ // When running try_ssbs2() on hardware which is affected by the "SSBS not fully
184+ // self-synchronizing" errata, the linux kernel mutes the detection of ssbs2 via
185+ // hardware caps. As a result the default version ends up running the ssbs2 code
186+ // which was expected to trap originally. Passing IS_EXEMPT = true here allows
187+ // the default version to UPASS.
188+ CHECK (ssbs2 , ssbs2 , ssbs , true, {
182189 asm volatile (
183190 "mrs x0, SSBS" "\n"
184191 "msr SSBS, x0" "\n"
185192 : : : "x0"
186193 );
187194})
188- CHECK (bti , bti , bti , {
195+ CHECK (bti , bti , bti , false, {
189196 // The only test for this requires reading a register that is only
190197 // accessible to EL1.
191198 #ifdef __linux__
@@ -206,35 +213,35 @@ CHECK(bti, bti, bti, {
206213 // TODO: implement me on your platform to fix this test!
207214 #endif
208215})
209- CHECK (simd , simd , simd , {
216+ CHECK (simd , simd , simd , false, {
210217 asm volatile (
211218 "mov v0.B[0], w0"
212219 : : :
213220 );
214221})
215- CHECK (fp , fp , fp , {
222+ CHECK (fp , fp , fp , false, {
216223 asm volatile (
217224 "fmov s0, #0"
218225 : : : "v0"
219226 );
220227})
221- CHECK (crc , crc , crc , {
228+ CHECK (crc , crc , crc , false, {
222229 asm volatile ( "crc32b wzr, wzr, wzr" );
223230})
224- CHECK (sme , sme , sme , {
231+ CHECK (sme , sme , sme , false, {
225232 asm volatile (
226233 "rdsvl x0, #1"
227234 : : : "x0"
228235 );
229236})
230- CHECK (sme2 , sme2 , sme2 , {
237+ CHECK (sme2 , sme2 , sme2 , false, {
231238 asm volatile (
232239 "smstart za" "\n"
233240 "zero { zt0 }" "\n"
234241 "smstop za" "\n"
235242 );
236243})
237- CHECK (ls64 , ls64 , ls64 , {
244+ CHECK (ls64 , ls64 , ls64 , false, {
238245 long data [8 ];
239246 asm volatile (
240247 "ld64b x0, [%0]" "\n"
@@ -246,109 +253,109 @@ CHECK(ls64, ls64, ls64, {
246253 : "x0" , "x1" , "x2" , "x3" , "x4" , "x5" , "x6" , "x7" , "x8" , "memory"
247254 );
248255})
249- CHECK (f32mm , f32mm , f32mm , {
256+ CHECK (f32mm , f32mm , f32mm , false, {
250257 asm volatile (
251258 "fmmla z0.s, z1.s, z2.s"
252259 : : : "v0"
253260 );
254261})
255- CHECK (f64mm , f64mm , f64mm , {
262+ CHECK (f64mm , f64mm , f64mm , false, {
256263 asm volatile (
257264 "fmmla z0.d, z1.d, z2.d"
258265 : : : "v0"
259266 );
260267})
261- CHECK (fp16fml , fp16fml , fp16fml , {
268+ CHECK (fp16fml , fp16fml , fp16fml , false, {
262269 asm volatile (
263270 "fmlal v0.2s, v1.2h, v2.2h"
264271 : : : "v0"
265272 );
266273})
267- CHECK (frintts , frintts , arch = armv8 .5 - a , {
274+ CHECK (frintts , frintts , arch = armv8 .5 - a , false, {
268275 asm volatile (
269276 "frint32z s0, s1"
270277 : : : "v0"
271278 );
272279})
273- CHECK (predres , predres , predres , {
280+ CHECK (predres , predres , predres , false, {
274281 asm volatile (
275282 "cfp rctx, x0" "\n"
276283 "dvp rctx, x1" "\n"
277284 "cpp rctx, x2" "\n"
278285 );
279286})
280- CHECK (rcpc3 , rcpc3 , rcpc3 , {
287+ CHECK (rcpc3 , rcpc3 , rcpc3 , false, {
281288 long x ;
282289 asm volatile (
283290 "stilp wzr, wzr, [%0]"
284291 : : "r" (& x ) : "memory"
285292 );
286293})
287- CHECK (rng , rng , rng , {
294+ CHECK (rng , rng , rng , false, {
288295 asm volatile (
289296 "mrs x0, rndr" "\n"
290297 "mrs x1, rndrrs" "\n"
291298 : : : "x0" , "x1"
292299 );
293300})
294- CHECK (sve , sve , sve , {
301+ CHECK (sve , sve , sve , false, {
295302 asm volatile (
296303 "fadda s0, p7, s0, z31.s"
297304 : : : "v0"
298305 );
299306})
300- CHECK (sve2 , sve2 , sve2 , {
307+ CHECK (sve2 , sve2 , sve2 , false, {
301308 asm volatile (
302309 "match p15.b, p7/z, z0.b, z1.b"
303310 : : : "p15" , "cc"
304311 );
305312})
306- CHECK (sve2_bitperm , sve2 - bitperm , sve2 - bitperm , {
313+ CHECK (sve2_bitperm , sve2 - bitperm , sve2 - bitperm , false, {
307314 asm volatile (
308315 "bext z0.s, z1.s, z2.s"
309316 : : : "z0"
310317 );
311318})
312- CHECK (sve2_sha3 , sve2 - sha3 , sve2 - sha3 , {
319+ CHECK (sve2_sha3 , sve2 - sha3 , sve2 - sha3 , false, {
313320 asm volatile (
314321 "rax1 z0.d, z1.d, z2.d"
315322 : : : "z0"
316323 );
317324})
318- CHECK (sve2_sm4 , sve2 - sm4 , sve2 - sm4 , {
325+ CHECK (sve2_sm4 , sve2 - sm4 , sve2 - sm4 , false, {
319326 asm volatile (
320327 "sm4e z0.s, z0.s, z2.s"
321328 : : : "z0"
322329 );
323330})
324- CHECK (wfxt , wfxt , wfxt , {
331+ CHECK (wfxt , wfxt , wfxt , false, {
325332 asm volatile (
326333 "wfet x0" "\n"
327334 "wfit x1" "\n"
328335 );
329336})
330- CHECK (sb , sb , sb , {
337+ CHECK (sb , sb , sb , false, {
331338 asm volatile ("sb" );
332339})
333- CHECK (sm4 , sm4 , sm4 , {
340+ CHECK (sm4 , sm4 , sm4 , false, {
334341 asm volatile (
335342 "sm4e v0.4s, v1.4s"
336343 : : : "v0"
337344 );
338345})
339- CHECK (sme_f64f64 , sme - f64f64 , sme - f64f64 , {
346+ CHECK (sme_f64f64 , sme - f64f64 , sme - f64f64 , false, {
340347 asm volatile (
341348 "fmops za0.d, p0/m, p0/m, z0.d, z0.d"
342349 : : : "za"
343350 );
344351})
345- CHECK (sme_i16i64 , sme - i16i64 , sme - i16i64 , {
352+ CHECK (sme_i16i64 , sme - i16i64 , sme - i16i64 , false, {
346353 asm volatile (
347354 "smopa za0.d, p0/m, p0/m, z0.h, z0.h"
348355 : : : "za"
349356 );
350357})
351- CHECK (mops , mops , mops , {
358+ CHECK (mops , mops , mops , false, {
352359 long dst [64 ];
353360 long src [64 ];
354361 size_t n = 32 ;
@@ -363,15 +370,15 @@ CHECK(mops, mops, mops, {
363370 );
364371})
365372
366- static bool safe_try_feature (bool (* try_feature )(void )) {
373+ static bool safe_try_feature (bool (* try_feature )(void ), bool is_exempt ) {
367374 int child = fork ();
368375 if (child ) {
369376 int exit_status = -1 ;
370377 if (child != waitpid (child , & exit_status , 0 ))
371378 return false;
372379 return exit_status == 0 ;
373380 } else {
374- exit (try_feature () ? 0 : 1 );
381+ exit (( try_feature () && ! is_exempt ) ? EXIT_SUCCESS : EXIT_FAILURE );
375382 }
376383}
377384
0 commit comments