10
10
#include <sys/sysctl.h>
11
11
#endif
12
12
13
- static bool safe_try_feature (bool (* try_feature )(void ));
13
+ static bool safe_try_feature (bool (* try_feature )(void ), bool is_exempt );
14
14
15
15
static bool any_fails = false;
16
16
17
17
#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 ) \
19
19
__attribute__((target(#TARGET_GUARD))) \
20
20
static bool try_##FN_NAME_SUFFIX(void) { \
21
21
do \
@@ -27,7 +27,8 @@ static bool any_fails = false;
27
27
static void check_##FN_NAME_SUFFIX(void) { \
28
28
printf("%s\n", #FMV_FEATURE); \
29
29
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)) { \
31
32
printf("\tFAIL\n"); \
32
33
any_fails = true; \
33
34
} \
@@ -36,58 +37,59 @@ static bool any_fails = false;
36
37
static void check_##FN_NAME_SUFFIX(void) { \
37
38
printf("%s\n", #FMV_FEATURE); \
38
39
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)) { \
40
42
printf("\tUPASS\n"); \
41
43
any_fails = true; \
42
44
} \
43
45
}
44
46
#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 ) \
46
48
static void check_##FN_NAME_SUFFIX(void) { \
47
49
printf("%s\n", #FMV_FEATURE); \
48
50
}
49
51
#endif
50
52
51
- CHECK (flagm , flagm , flagm , {
53
+ CHECK (flagm , flagm , flagm , false, {
52
54
asm volatile (
53
55
"cfinv" "\n"
54
56
"cfinv" "\n"
55
57
);
56
58
})
57
- CHECK (flagm2 , flagm2 , arch = armv8 .5 - a , {
59
+ CHECK (flagm2 , flagm2 , arch = armv8 .5 - a , false, {
58
60
asm volatile (
59
61
"axflag" "\n"
60
62
"xaflag" "\n"
61
63
);
62
64
})
63
- CHECK (dotprod , dotprod , dotprod , {
65
+ CHECK (dotprod , dotprod , dotprod , false, {
64
66
asm volatile (
65
67
"udot v0.4S,v1.16B,v2.16B"
66
68
: : : "v0"
67
69
);
68
70
})
69
- CHECK (sha3 , sha3 , sha3 , {
71
+ CHECK (sha3 , sha3 , sha3 , false, {
70
72
asm volatile (
71
73
"fmov d0, #0" "\n"
72
74
"fmov d1, #0" "\n"
73
75
"eor3 v0.16b, v0.16b, v0.16b, v0.16b" "\n"
74
76
: : : "v0"
75
77
);
76
78
})
77
- CHECK (rdm , rdm , rdm , {
79
+ CHECK (rdm , rdm , rdm , false, {
78
80
asm volatile (
79
81
"sqrdmlah s0, s1, s2"
80
82
: : : "s0"
81
83
);
82
84
})
83
- CHECK (lse , lse , lse , {
85
+ CHECK (lse , lse , lse , false, {
84
86
uint64_t pointee = 0 ;
85
87
asm volatile (
86
88
"swp xzr, xzr, [%[pointee]]"
87
89
: : [pointee ]"r" (& pointee )
88
90
);
89
91
})
90
- CHECK (sha2 , sha2 , sha2 , {
92
+ CHECK (sha2 , sha2 , sha2 , false, {
91
93
asm volatile (
92
94
"fmov d0, #0" "\n"
93
95
"fmov d1, #0" "\n"
@@ -96,96 +98,101 @@ CHECK(sha2, sha2, sha2, {
96
98
: : : "v0"
97
99
);
98
100
})
99
- CHECK (aes , aes , aes , {
101
+ CHECK (aes , aes , aes , false, {
100
102
asm volatile (
101
103
"fmov d0, #0" "\n"
102
104
"fmov d1, #0" "\n"
103
105
"aesd v0.16B, v0.16B" "\n"
104
106
: : : "v0"
105
107
);
106
108
})
107
- CHECK (pmull , pmull , aes , {
109
+ CHECK (pmull , pmull , aes , false, {
108
110
asm volatile (
109
111
"fmov d0, #0" "\n"
110
112
"pmull v0.1q, v0.1d, v0.1d" "\n"
111
113
: : : "v0"
112
114
);
113
115
})
114
- CHECK (rcpc , rcpc , rcpc , {
116
+ CHECK (rcpc , rcpc , rcpc , false, {
115
117
int x ;
116
118
asm volatile (
117
119
"ldaprb w0, [%0]"
118
120
: : "r" (& x ) : "w0"
119
121
);
120
122
})
121
- CHECK (rcpc2 , rcpc2 , arch = armv8 .4 - a , {
123
+ CHECK (rcpc2 , rcpc2 , arch = armv8 .4 - a , false, {
122
124
int x ;
123
125
asm volatile (
124
126
"mov x1, %0" "\n"
125
127
"ldapurb w0, [x1]" "\n"
126
128
: : "r" (& x ) : "w0" , "x1"
127
129
);
128
130
})
129
- CHECK (fcma , fcma , fcma , {
131
+ CHECK (fcma , fcma , fcma , false, {
130
132
asm volatile (
131
133
"fmov d0, #0" "\n"
132
134
"fcadd v0.2s, v0.2s, v0.2s, #90" "\n"
133
135
: : : "v0"
134
136
);
135
137
})
136
- CHECK (jscvt , jscvt , jscvt , {
138
+ CHECK (jscvt , jscvt , jscvt , false, {
137
139
asm volatile (
138
140
"fmov d0, #0" "\n"
139
141
"fjcvtzs w1, d0" "\n"
140
142
: : : "w1" , "d0"
141
143
);
142
144
})
143
- CHECK (dpb , dpb , arch = armv8 .2 - a , {
145
+ CHECK (dpb , dpb , arch = armv8 .2 - a , false, {
144
146
int x ;
145
147
asm volatile (
146
148
"dc cvap, %0"
147
149
: : "r" (& x )
148
150
);
149
151
})
150
- CHECK (dpb2 , dpb2 , arch = armv8 .5 - a , {
152
+ CHECK (dpb2 , dpb2 , arch = armv8 .5 - a , false, {
151
153
int x ;
152
154
asm volatile (
153
155
"dc cvadp, %0"
154
156
: : "r" (& x )
155
157
);
156
158
})
157
- CHECK (bf16 , bf16 , bf16 , {
159
+ CHECK (bf16 , bf16 , bf16 , false, {
158
160
asm volatile (
159
161
"bfdot v0.4S,v1.8H,v2.8H"
160
162
: : : "v0"
161
163
);
162
164
})
163
- CHECK (i8mm , i8mm , i8mm , {
165
+ CHECK (i8mm , i8mm , i8mm , false, {
164
166
asm volatile (
165
167
"sudot v0.4S,v1.16B,v2.4B[0]"
166
168
: : : "v0"
167
169
);
168
170
})
169
- CHECK (dit , dit , dit , {
171
+ CHECK (dit , dit , dit , false, {
170
172
asm volatile (
171
173
"msr DIT, x0"
172
174
: : : "x0"
173
175
);
174
176
})
175
- CHECK (fp16 , fp16 , fp16 , {
177
+ CHECK (fp16 , fp16 , fp16 , false, {
176
178
asm volatile (
177
179
"fmov h0, #0"
178
180
: : : "v0"
179
181
);
180
182
})
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, {
182
189
asm volatile (
183
190
"mrs x0, SSBS" "\n"
184
191
"msr SSBS, x0" "\n"
185
192
: : : "x0"
186
193
);
187
194
})
188
- CHECK (bti , bti , bti , {
195
+ CHECK (bti , bti , bti , false, {
189
196
// The only test for this requires reading a register that is only
190
197
// accessible to EL1.
191
198
#ifdef __linux__
@@ -206,35 +213,35 @@ CHECK(bti, bti, bti, {
206
213
// TODO: implement me on your platform to fix this test!
207
214
#endif
208
215
})
209
- CHECK (simd , simd , simd , {
216
+ CHECK (simd , simd , simd , false, {
210
217
asm volatile (
211
218
"mov v0.B[0], w0"
212
219
: : :
213
220
);
214
221
})
215
- CHECK (fp , fp , fp , {
222
+ CHECK (fp , fp , fp , false, {
216
223
asm volatile (
217
224
"fmov s0, #0"
218
225
: : : "v0"
219
226
);
220
227
})
221
- CHECK (crc , crc , crc , {
228
+ CHECK (crc , crc , crc , false, {
222
229
asm volatile ( "crc32b wzr, wzr, wzr" );
223
230
})
224
- CHECK (sme , sme , sme , {
231
+ CHECK (sme , sme , sme , false, {
225
232
asm volatile (
226
233
"rdsvl x0, #1"
227
234
: : : "x0"
228
235
);
229
236
})
230
- CHECK (sme2 , sme2 , sme2 , {
237
+ CHECK (sme2 , sme2 , sme2 , false, {
231
238
asm volatile (
232
239
"smstart za" "\n"
233
240
"zero { zt0 }" "\n"
234
241
"smstop za" "\n"
235
242
);
236
243
})
237
- CHECK (ls64 , ls64 , ls64 , {
244
+ CHECK (ls64 , ls64 , ls64 , false, {
238
245
long data [8 ];
239
246
asm volatile (
240
247
"ld64b x0, [%0]" "\n"
@@ -246,109 +253,109 @@ CHECK(ls64, ls64, ls64, {
246
253
: "x0" , "x1" , "x2" , "x3" , "x4" , "x5" , "x6" , "x7" , "x8" , "memory"
247
254
);
248
255
})
249
- CHECK (f32mm , f32mm , f32mm , {
256
+ CHECK (f32mm , f32mm , f32mm , false, {
250
257
asm volatile (
251
258
"fmmla z0.s, z1.s, z2.s"
252
259
: : : "v0"
253
260
);
254
261
})
255
- CHECK (f64mm , f64mm , f64mm , {
262
+ CHECK (f64mm , f64mm , f64mm , false, {
256
263
asm volatile (
257
264
"fmmla z0.d, z1.d, z2.d"
258
265
: : : "v0"
259
266
);
260
267
})
261
- CHECK (fp16fml , fp16fml , fp16fml , {
268
+ CHECK (fp16fml , fp16fml , fp16fml , false, {
262
269
asm volatile (
263
270
"fmlal v0.2s, v1.2h, v2.2h"
264
271
: : : "v0"
265
272
);
266
273
})
267
- CHECK (frintts , frintts , arch = armv8 .5 - a , {
274
+ CHECK (frintts , frintts , arch = armv8 .5 - a , false, {
268
275
asm volatile (
269
276
"frint32z s0, s1"
270
277
: : : "v0"
271
278
);
272
279
})
273
- CHECK (predres , predres , predres , {
280
+ CHECK (predres , predres , predres , false, {
274
281
asm volatile (
275
282
"cfp rctx, x0" "\n"
276
283
"dvp rctx, x1" "\n"
277
284
"cpp rctx, x2" "\n"
278
285
);
279
286
})
280
- CHECK (rcpc3 , rcpc3 , rcpc3 , {
287
+ CHECK (rcpc3 , rcpc3 , rcpc3 , false, {
281
288
long x ;
282
289
asm volatile (
283
290
"stilp wzr, wzr, [%0]"
284
291
: : "r" (& x ) : "memory"
285
292
);
286
293
})
287
- CHECK (rng , rng , rng , {
294
+ CHECK (rng , rng , rng , false, {
288
295
asm volatile (
289
296
"mrs x0, rndr" "\n"
290
297
"mrs x1, rndrrs" "\n"
291
298
: : : "x0" , "x1"
292
299
);
293
300
})
294
- CHECK (sve , sve , sve , {
301
+ CHECK (sve , sve , sve , false, {
295
302
asm volatile (
296
303
"fadda s0, p7, s0, z31.s"
297
304
: : : "v0"
298
305
);
299
306
})
300
- CHECK (sve2 , sve2 , sve2 , {
307
+ CHECK (sve2 , sve2 , sve2 , false, {
301
308
asm volatile (
302
309
"match p15.b, p7/z, z0.b, z1.b"
303
310
: : : "p15" , "cc"
304
311
);
305
312
})
306
- CHECK (sve2_bitperm , sve2 - bitperm , sve2 - bitperm , {
313
+ CHECK (sve2_bitperm , sve2 - bitperm , sve2 - bitperm , false, {
307
314
asm volatile (
308
315
"bext z0.s, z1.s, z2.s"
309
316
: : : "z0"
310
317
);
311
318
})
312
- CHECK (sve2_sha3 , sve2 - sha3 , sve2 - sha3 , {
319
+ CHECK (sve2_sha3 , sve2 - sha3 , sve2 - sha3 , false, {
313
320
asm volatile (
314
321
"rax1 z0.d, z1.d, z2.d"
315
322
: : : "z0"
316
323
);
317
324
})
318
- CHECK (sve2_sm4 , sve2 - sm4 , sve2 - sm4 , {
325
+ CHECK (sve2_sm4 , sve2 - sm4 , sve2 - sm4 , false, {
319
326
asm volatile (
320
327
"sm4e z0.s, z0.s, z2.s"
321
328
: : : "z0"
322
329
);
323
330
})
324
- CHECK (wfxt , wfxt , wfxt , {
331
+ CHECK (wfxt , wfxt , wfxt , false, {
325
332
asm volatile (
326
333
"wfet x0" "\n"
327
334
"wfit x1" "\n"
328
335
);
329
336
})
330
- CHECK (sb , sb , sb , {
337
+ CHECK (sb , sb , sb , false, {
331
338
asm volatile ("sb" );
332
339
})
333
- CHECK (sm4 , sm4 , sm4 , {
340
+ CHECK (sm4 , sm4 , sm4 , false, {
334
341
asm volatile (
335
342
"sm4e v0.4s, v1.4s"
336
343
: : : "v0"
337
344
);
338
345
})
339
- CHECK (sme_f64f64 , sme - f64f64 , sme - f64f64 , {
346
+ CHECK (sme_f64f64 , sme - f64f64 , sme - f64f64 , false, {
340
347
asm volatile (
341
348
"fmops za0.d, p0/m, p0/m, z0.d, z0.d"
342
349
: : : "za"
343
350
);
344
351
})
345
- CHECK (sme_i16i64 , sme - i16i64 , sme - i16i64 , {
352
+ CHECK (sme_i16i64 , sme - i16i64 , sme - i16i64 , false, {
346
353
asm volatile (
347
354
"smopa za0.d, p0/m, p0/m, z0.h, z0.h"
348
355
: : : "za"
349
356
);
350
357
})
351
- CHECK (mops , mops , mops , {
358
+ CHECK (mops , mops , mops , false, {
352
359
long dst [64 ];
353
360
long src [64 ];
354
361
size_t n = 32 ;
@@ -363,15 +370,15 @@ CHECK(mops, mops, mops, {
363
370
);
364
371
})
365
372
366
- static bool safe_try_feature (bool (* try_feature )(void )) {
373
+ static bool safe_try_feature (bool (* try_feature )(void ), bool is_exempt ) {
367
374
int child = fork ();
368
375
if (child ) {
369
376
int exit_status = -1 ;
370
377
if (child != waitpid (child , & exit_status , 0 ))
371
378
return false;
372
379
return exit_status == 0 ;
373
380
} else {
374
- exit (try_feature () ? 0 : 1 );
381
+ exit (( try_feature () && ! is_exempt ) ? EXIT_SUCCESS : EXIT_FAILURE );
375
382
}
376
383
}
377
384
0 commit comments