1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (C) 2022 ARM Limited.
4 */
5
6 #include <errno.h>
7 #include <signal.h>
8 #include <stdbool.h>
9 #include <stddef.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
14 #include <linux/auxvec.h>
15 #include <linux/compiler.h>
16 #include <sys/auxv.h>
17 #include <sys/prctl.h>
18 #include <asm/hwcap.h>
19 #include <asm/sigcontext.h>
20 #include <asm/unistd.h>
21
22 #include <linux/auxvec.h>
23
24 #include "kselftest.h"
25
26 #define TESTS_PER_HWCAP 3
27
28 #ifndef AT_HWCAP3
29 #define AT_HWCAP3 29
30 #endif
31
32 /*
33 * Function expected to generate exception when the feature is not
34 * supported and return when it is supported. If the specific exception
35 * is generated then the handler must be able to skip over the
36 * instruction safely.
37 *
38 * Note that it is expected that for many architecture extensions
39 * there are no specific traps due to no architecture state being
40 * added so we may not fault if running on a kernel which doesn't know
41 * to add the hwcap.
42 */
43 typedef void (*sig_fn)(void);
44
aes_sigill(void)45 static void aes_sigill(void)
46 {
47 /* AESE V0.16B, V0.16B */
48 asm volatile(".inst 0x4e284800" : : : );
49 }
50
atomics_sigill(void)51 static void atomics_sigill(void)
52 {
53 /* STADD W0, [SP] */
54 asm volatile(".inst 0xb82003ff" : : : );
55 }
56
cmpbr_sigill(void)57 static void cmpbr_sigill(void)
58 {
59 asm volatile(".inst 0x74C00040\n" /* CBEQ w0, w0, +8 */
60 "udf #0" : : : "cc"); /* UDF #0 */
61 }
62
crc32_sigill(void)63 static void crc32_sigill(void)
64 {
65 /* CRC32W W0, W0, W1 */
66 asm volatile(".inst 0x1ac14800" : : : );
67 }
68
cssc_sigill(void)69 static void cssc_sigill(void)
70 {
71 /* CNT x0, x0 */
72 asm volatile(".inst 0xdac01c00" : : : "x0");
73 }
74
f8cvt_sigill(void)75 static void f8cvt_sigill(void)
76 {
77 /* FSCALE V0.4H, V0.4H, V0.4H */
78 asm volatile(".inst 0x2ec03c00");
79 }
80
f8dp2_sigill(void)81 static void f8dp2_sigill(void)
82 {
83 /* FDOT V0.4H, V0.4H, V0.5H */
84 asm volatile(".inst 0xe40fc00");
85 }
86
f8dp4_sigill(void)87 static void f8dp4_sigill(void)
88 {
89 /* FDOT V0.2S, V0.2S, V0.2S */
90 asm volatile(".inst 0xe00fc00");
91 }
92
f8fma_sigill(void)93 static void f8fma_sigill(void)
94 {
95 /* FMLALB V0.8H, V0.16B, V0.16B */
96 asm volatile(".inst 0xec0fc00");
97 }
98
f8mm4_sigill(void)99 static void f8mm4_sigill(void)
100 {
101 /* FMMLA V0.4SH, V0.16B, V0.16B */
102 asm volatile(".inst 0x6e00ec00");
103 }
104
f8mm8_sigill(void)105 static void f8mm8_sigill(void)
106 {
107 /* FMMLA V0.4S, V0.16B, V0.16B */
108 asm volatile(".inst 0x6e80ec00");
109 }
110
faminmax_sigill(void)111 static void faminmax_sigill(void)
112 {
113 /* FAMIN V0.4H, V0.4H, V0.4H */
114 asm volatile(".inst 0x2ec01c00");
115 }
116
fp_sigill(void)117 static void fp_sigill(void)
118 {
119 asm volatile("fmov s0, #1");
120 }
121
fpmr_sigill(void)122 static void fpmr_sigill(void)
123 {
124 asm volatile("mrs x0, S3_3_C4_C4_2" : : : "x0");
125 }
126
fprcvt_sigill(void)127 static void fprcvt_sigill(void)
128 {
129 /* FCVTAS S0, H0 */
130 asm volatile(".inst 0x1efa0000");
131 }
132
gcs_sigill(void)133 static void gcs_sigill(void)
134 {
135 unsigned long *gcspr;
136
137 asm volatile(
138 "mrs %0, S3_3_C2_C5_1"
139 : "=r" (gcspr)
140 :
141 : "cc");
142 }
143
ilrcpc_sigill(void)144 static void ilrcpc_sigill(void)
145 {
146 /* LDAPUR W0, [SP, #8] */
147 asm volatile(".inst 0x994083e0" : : : );
148 }
149
jscvt_sigill(void)150 static void jscvt_sigill(void)
151 {
152 /* FJCVTZS W0, D0 */
153 asm volatile(".inst 0x1e7e0000" : : : );
154 }
155
lrcpc_sigill(void)156 static void lrcpc_sigill(void)
157 {
158 /* LDAPR W0, [SP, #0] */
159 asm volatile(".inst 0xb8bfc3e0" : : : );
160 }
161
lse128_sigill(void)162 static void lse128_sigill(void)
163 {
164 u64 __attribute__ ((aligned (16))) mem[2] = { 10, 20 };
165 register u64 *memp asm ("x0") = mem;
166 register u64 val0 asm ("x1") = 5;
167 register u64 val1 asm ("x2") = 4;
168
169 /* SWPP X1, X2, [X0] */
170 asm volatile(".inst 0x19228001"
171 : "+r" (memp), "+r" (val0), "+r" (val1)
172 :
173 : "cc", "memory");
174 }
175
lsfe_sigill(void)176 static void lsfe_sigill(void)
177 {
178 float __attribute__ ((aligned (16))) mem;
179 register float *memp asm ("x0") = &mem;
180
181 /* STFADD H0, [X0] */
182 asm volatile(".inst 0x7c20801f"
183 : "+r" (memp)
184 :
185 : "memory");
186 }
187
lut_sigill(void)188 static void lut_sigill(void)
189 {
190 /* LUTI2 V0.16B, { V0.16B }, V[0] */
191 asm volatile(".inst 0x4e801000");
192 }
193
mops_sigill(void)194 static void mops_sigill(void)
195 {
196 char dst[1], src[1];
197 register char *dstp asm ("x0") = dst;
198 register char *srcp asm ("x1") = src;
199 register long size asm ("x2") = 1;
200
201 /* CPYP [x0]!, [x1]!, x2! */
202 asm volatile(".inst 0x1d010440"
203 : "+r" (dstp), "+r" (srcp), "+r" (size)
204 :
205 : "cc", "memory");
206 }
207
pmull_sigill(void)208 static void pmull_sigill(void)
209 {
210 /* PMULL V0.1Q, V0.1D, V0.1D */
211 asm volatile(".inst 0x0ee0e000" : : : );
212 }
213
poe_sigill(void)214 static void poe_sigill(void)
215 {
216 /* mrs x0, POR_EL0 */
217 asm volatile("mrs x0, S3_3_C10_C2_4" : : : "x0");
218 }
219
rng_sigill(void)220 static void rng_sigill(void)
221 {
222 asm volatile("mrs x0, S3_3_C2_C4_0" : : : "x0");
223 }
224
sha1_sigill(void)225 static void sha1_sigill(void)
226 {
227 /* SHA1H S0, S0 */
228 asm volatile(".inst 0x5e280800" : : : );
229 }
230
sha2_sigill(void)231 static void sha2_sigill(void)
232 {
233 /* SHA256H Q0, Q0, V0.4S */
234 asm volatile(".inst 0x5e004000" : : : );
235 }
236
sha512_sigill(void)237 static void sha512_sigill(void)
238 {
239 /* SHA512H Q0, Q0, V0.2D */
240 asm volatile(".inst 0xce608000" : : : );
241 }
242
sme_sigill(void)243 static void sme_sigill(void)
244 {
245 /* RDSVL x0, #0 */
246 asm volatile(".inst 0x04bf5800" : : : "x0");
247 }
248
sme2_sigill(void)249 static void sme2_sigill(void)
250 {
251 /* SMSTART ZA */
252 asm volatile("msr S0_3_C4_C5_3, xzr" : : : );
253
254 /* ZERO ZT0 */
255 asm volatile(".inst 0xc0480001" : : : );
256
257 /* SMSTOP */
258 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
259 }
260
sme2p1_sigill(void)261 static void sme2p1_sigill(void)
262 {
263 /* SMSTART SM */
264 asm volatile("msr S0_3_C4_C3_3, xzr" : : : );
265
266 /* BFCLAMP { Z0.H - Z1.H }, Z0.H, Z0.H */
267 asm volatile(".inst 0xc120C000" : : : );
268
269 /* SMSTOP */
270 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
271 }
272
sme2p2_sigill(void)273 static void sme2p2_sigill(void)
274 {
275 /* SMSTART SM */
276 asm volatile("msr S0_3_C4_C3_3, xzr" : : : );
277
278 /* UXTB Z0.D, P0/Z, Z0.D */
279 asm volatile(".inst 0x4c1a000" : : : );
280
281 /* SMSTOP */
282 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
283 }
284
sme_aes_sigill(void)285 static void sme_aes_sigill(void)
286 {
287 /* SMSTART SM */
288 asm volatile("msr S0_3_C4_C3_3, xzr" : : : );
289
290 /* AESD z0.b, z0.b, z0.b */
291 asm volatile(".inst 0x4522e400" : : : "z0");
292
293 /* SMSTOP */
294 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
295 }
296
sme_sbitperm_sigill(void)297 static void sme_sbitperm_sigill(void)
298 {
299 /* SMSTART SM */
300 asm volatile("msr S0_3_C4_C3_3, xzr" : : : );
301
302 /* BDEP Z0.B, Z0.B, Z0.B */
303 asm volatile(".inst 0x4500b400" : : : "z0");
304
305 /* SMSTOP */
306 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
307 }
308
smei16i32_sigill(void)309 static void smei16i32_sigill(void)
310 {
311 /* SMSTART */
312 asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
313
314 /* SMOPA ZA0.S, P0/M, P0/M, Z0.B, Z0.B */
315 asm volatile(".inst 0xa0800000" : : : );
316
317 /* SMSTOP */
318 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
319 }
320
smebi32i32_sigill(void)321 static void smebi32i32_sigill(void)
322 {
323 /* SMSTART */
324 asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
325
326 /* BMOPA ZA0.S, P0/M, P0/M, Z0.B, Z0.B */
327 asm volatile(".inst 0x80800008" : : : );
328
329 /* SMSTOP */
330 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
331 }
332
smeb16b16_sigill(void)333 static void smeb16b16_sigill(void)
334 {
335 /* SMSTART */
336 asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
337
338 /* BFADD ZA.H[W0, 0], {Z0.H-Z1.H} */
339 asm volatile(".inst 0xC1E41C00" : : : );
340
341 /* SMSTOP */
342 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
343 }
344
smef16f16_sigill(void)345 static void smef16f16_sigill(void)
346 {
347 /* SMSTART */
348 asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
349
350 /* FADD ZA.H[W0, 0], { Z0.H-Z1.H } */
351 asm volatile(".inst 0xc1a41C00" : : : );
352
353 /* SMSTOP */
354 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
355 }
356
smef8f16_sigill(void)357 static void smef8f16_sigill(void)
358 {
359 /* SMSTART */
360 asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
361
362 /* FDOT ZA.H[W0, 0], Z0.B-Z1.B, Z0.B-Z1.B */
363 asm volatile(".inst 0xc1a01020" : : : );
364
365 /* SMSTOP */
366 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
367 }
368
smef8f32_sigill(void)369 static void smef8f32_sigill(void)
370 {
371 /* SMSTART */
372 asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
373
374 /* FDOT ZA.S[W0, 0], { Z0.B-Z1.B }, Z0.B[0] */
375 asm volatile(".inst 0xc1500038" : : : );
376
377 /* SMSTOP */
378 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
379 }
380
smelutv2_sigill(void)381 static void smelutv2_sigill(void)
382 {
383 /* SMSTART */
384 asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
385
386 /* LUTI4 { Z0.B-Z3.B }, ZT0, { Z0-Z1 } */
387 asm volatile(".inst 0xc08b0000" : : : );
388
389 /* SMSTOP */
390 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
391 }
392
smesf8dp2_sigill(void)393 static void smesf8dp2_sigill(void)
394 {
395 /* SMSTART */
396 asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
397
398 /* FDOT Z0.H, Z0.B, Z0.B[0] */
399 asm volatile(".inst 0x64204400" : : : );
400
401 /* SMSTOP */
402 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
403 }
404
smesf8dp4_sigill(void)405 static void smesf8dp4_sigill(void)
406 {
407 /* SMSTART */
408 asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
409
410 /* FDOT Z0.S, Z0.B, Z0.B[0] */
411 asm volatile(".inst 0xc1a41C00" : : : );
412
413 /* SMSTOP */
414 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
415 }
416
smesf8fma_sigill(void)417 static void smesf8fma_sigill(void)
418 {
419 /* SMSTART */
420 asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
421
422 /* FMLALB Z0.8H, Z0.B, Z0.B */
423 asm volatile(".inst 0x64205000");
424
425 /* SMSTOP */
426 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
427 }
428
smesfexpa_sigill(void)429 static void smesfexpa_sigill(void)
430 {
431 /* SMSTART */
432 asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
433
434 /* FEXPA Z0.D, Z0.D */
435 asm volatile(".inst 0x04e0b800");
436
437 /* SMSTOP */
438 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
439 }
440
smesmop4_sigill(void)441 static void smesmop4_sigill(void)
442 {
443 /* SMSTART */
444 asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
445
446 /* SMOP4A ZA0.S, Z0.B, { Z0.B - Z1.B } */
447 asm volatile(".inst 0x80108000");
448
449 /* SMSTOP */
450 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
451 }
452
smestmop_sigill(void)453 static void smestmop_sigill(void)
454 {
455 /* SMSTART */
456 asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
457
458 /* STMOPA ZA0.S, { Z0.H - Z1.H }, Z0.H, Z20[0] */
459 asm volatile(".inst 0x80408008");
460
461 /* SMSTOP */
462 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
463 }
464
sve_sigill(void)465 static void sve_sigill(void)
466 {
467 /* RDVL x0, #0 */
468 asm volatile(".inst 0x04bf5000" : : : "x0");
469 }
470
sve2_sigill(void)471 static void sve2_sigill(void)
472 {
473 /* SQABS Z0.b, P0/M, Z0.B */
474 asm volatile(".inst 0x4408A000" : : : "z0");
475 }
476
sve2p1_sigill(void)477 static void sve2p1_sigill(void)
478 {
479 /* LD1Q {Z0.Q}, P0/Z, [Z0.D, X0] */
480 asm volatile(".inst 0xC400A000" : : : "z0");
481 }
482
sve2p2_sigill(void)483 static void sve2p2_sigill(void)
484 {
485 /* NOT Z0.D, P0/Z, Z0.D */
486 asm volatile(".inst 0x4cea000" : : : "z0");
487 }
488
sveaes_sigill(void)489 static void sveaes_sigill(void)
490 {
491 /* AESD z0.b, z0.b, z0.b */
492 asm volatile(".inst 0x4522e400" : : : "z0");
493 }
494
sveaes2_sigill(void)495 static void sveaes2_sigill(void)
496 {
497 /* AESD {Z0.B - Z1.B }, { Z0.B - Z1.B }, Z0.Q */
498 asm volatile(".inst 0x4522ec00" : : : "z0");
499 }
500
sveb16b16_sigill(void)501 static void sveb16b16_sigill(void)
502 {
503 /* BFADD Z0.H, Z0.H, Z0.H */
504 asm volatile(".inst 0x65000000" : : : );
505 }
506
svebfscale_sigill(void)507 static void svebfscale_sigill(void)
508 {
509 /* BFSCALE Z0.H, P0/M, Z0.H, Z0.H */
510 asm volatile(".inst 0x65098000" : : : "z0");
511 }
512
svef16mm_sigill(void)513 static void svef16mm_sigill(void)
514 {
515 /* FMMLA Z0.S, Z0.H, Z0.H */
516 asm volatile(".inst 0x6420e400");
517 }
518
svepmull_sigill(void)519 static void svepmull_sigill(void)
520 {
521 /* PMULLB Z0.Q, Z0.D, Z0.D */
522 asm volatile(".inst 0x45006800" : : : "z0");
523 }
524
svebitperm_sigill(void)525 static void svebitperm_sigill(void)
526 {
527 /* BDEP Z0.B, Z0.B, Z0.B */
528 asm volatile(".inst 0x4500b400" : : : "z0");
529 }
530
svesha3_sigill(void)531 static void svesha3_sigill(void)
532 {
533 /* EOR3 Z0.D, Z0.D, Z0.D, Z0.D */
534 asm volatile(".inst 0x4203800" : : : "z0");
535 }
536
sveeltperm_sigill(void)537 static void sveeltperm_sigill(void)
538 {
539 /* COMPACT Z0.B, P0, Z0.B */
540 asm volatile(".inst 0x5218000" : : : "x0");
541 }
542
svesm4_sigill(void)543 static void svesm4_sigill(void)
544 {
545 /* SM4E Z0.S, Z0.S, Z0.S */
546 asm volatile(".inst 0x4523e000" : : : "z0");
547 }
548
svei8mm_sigill(void)549 static void svei8mm_sigill(void)
550 {
551 /* USDOT Z0.S, Z0.B, Z0.B[0] */
552 asm volatile(".inst 0x44a01800" : : : "z0");
553 }
554
svef32mm_sigill(void)555 static void svef32mm_sigill(void)
556 {
557 /* FMMLA Z0.S, Z0.S, Z0.S */
558 asm volatile(".inst 0x64a0e400" : : : "z0");
559 }
560
svef64mm_sigill(void)561 static void svef64mm_sigill(void)
562 {
563 /* FMMLA Z0.D, Z0.D, Z0.D */
564 asm volatile(".inst 0x64e0e400" : : : "z0");
565 }
566
svebf16_sigill(void)567 static void svebf16_sigill(void)
568 {
569 /* BFCVT Z0.H, P0/M, Z0.S */
570 asm volatile(".inst 0x658aa000" : : : "z0");
571 }
572
hbc_sigill(void)573 static void hbc_sigill(void)
574 {
575 /* BC.EQ +4 */
576 asm volatile("cmp xzr, xzr\n"
577 ".inst 0x54000030" : : : "cc");
578 }
579
uscat_sigbus(void)580 static void uscat_sigbus(void)
581 {
582 /* unaligned atomic access */
583 asm volatile("ADD x1, sp, #2" : : : );
584 /* STADD W0, [X1] */
585 asm volatile(".inst 0xb820003f" : : : );
586 }
587
lrcpc3_sigill(void)588 static void lrcpc3_sigill(void)
589 {
590 int data[2] = { 1, 2 };
591
592 register int *src asm ("x0") = data;
593 register int data0 asm ("w2") = 0;
594 register int data1 asm ("w3") = 0;
595
596 /* LDIAPP w2, w3, [x0] */
597 asm volatile(".inst 0x99431802"
598 : "=r" (data0), "=r" (data1) : "r" (src) :);
599 }
600
ignore_signal(int sig,siginfo_t * info,void * context)601 static void ignore_signal(int sig, siginfo_t *info, void *context)
602 {
603 ucontext_t *uc = context;
604
605 uc->uc_mcontext.pc += 4;
606 }
607
ls64_sigill(void)608 static void ls64_sigill(void)
609 {
610 struct sigaction ign, old;
611 char src[64] __aligned(64) = { 1 };
612
613 /*
614 * LS64 requires target memory to be Device/Non-cacheable (if
615 * FEAT_LS64WB not supported) and the completer supports these
616 * instructions, otherwise we'll receive a SIGBUS. Since we are only
617 * testing the ABI here, so just ignore the SIGBUS and see if we can
618 * execute the instructions without receiving a SIGILL. Restore the
619 * handler of SIGBUS after this test.
620 */
621 ign.sa_sigaction = ignore_signal;
622 ign.sa_flags = SA_SIGINFO | SA_RESTART;
623 sigemptyset(&ign.sa_mask);
624 sigaction(SIGBUS, &ign, &old);
625
626 register void *xn asm ("x8") = src;
627 register u64 xt_1 asm ("x0");
628
629 /* LD64B x0, [x8] */
630 asm volatile(".inst 0xf83fd100" : "=r" (xt_1) : "r" (xn)
631 : "x1", "x2", "x3", "x4", "x5", "x6", "x7");
632
633 /* ST64B x0, [x8] */
634 asm volatile(".inst 0xf83f9100" : : "r" (xt_1), "r" (xn)
635 : "x1", "x2", "x3", "x4", "x5", "x6", "x7");
636
637 sigaction(SIGBUS, &old, NULL);
638 }
639
640 static const struct hwcap_data {
641 const char *name;
642 unsigned long at_hwcap;
643 unsigned long hwcap_bit;
644 const char *cpuinfo;
645 sig_fn sigill_fn;
646 bool sigill_reliable;
647 sig_fn sigbus_fn;
648 bool sigbus_reliable;
649 } hwcaps[] = {
650 {
651 .name = "AES",
652 .at_hwcap = AT_HWCAP,
653 .hwcap_bit = HWCAP_AES,
654 .cpuinfo = "aes",
655 .sigill_fn = aes_sigill,
656 },
657 {
658 .name = "CMPBR",
659 .at_hwcap = AT_HWCAP,
660 .hwcap_bit = HWCAP_CMPBR,
661 .cpuinfo = "cmpbr",
662 .sigill_fn = cmpbr_sigill,
663 },
664 {
665 .name = "CRC32",
666 .at_hwcap = AT_HWCAP,
667 .hwcap_bit = HWCAP_CRC32,
668 .cpuinfo = "crc32",
669 .sigill_fn = crc32_sigill,
670 },
671 {
672 .name = "CSSC",
673 .at_hwcap = AT_HWCAP2,
674 .hwcap_bit = HWCAP2_CSSC,
675 .cpuinfo = "cssc",
676 .sigill_fn = cssc_sigill,
677 },
678 {
679 .name = "F8CVT",
680 .at_hwcap = AT_HWCAP2,
681 .hwcap_bit = HWCAP2_F8CVT,
682 .cpuinfo = "f8cvt",
683 .sigill_fn = f8cvt_sigill,
684 },
685 {
686 .name = "F8DP4",
687 .at_hwcap = AT_HWCAP2,
688 .hwcap_bit = HWCAP2_F8DP4,
689 .cpuinfo = "f8dp4",
690 .sigill_fn = f8dp4_sigill,
691 },
692 {
693 .name = "F8DP2",
694 .at_hwcap = AT_HWCAP2,
695 .hwcap_bit = HWCAP2_F8DP2,
696 .cpuinfo = "f8dp2",
697 .sigill_fn = f8dp2_sigill,
698 },
699 {
700 .name = "F8E5M2",
701 .at_hwcap = AT_HWCAP2,
702 .hwcap_bit = HWCAP2_F8E5M2,
703 .cpuinfo = "f8e5m2",
704 },
705 {
706 .name = "F8E4M3",
707 .at_hwcap = AT_HWCAP2,
708 .hwcap_bit = HWCAP2_F8E4M3,
709 .cpuinfo = "f8e4m3",
710 },
711 {
712 .name = "F8FMA",
713 .at_hwcap = AT_HWCAP2,
714 .hwcap_bit = HWCAP2_F8FMA,
715 .cpuinfo = "f8fma",
716 .sigill_fn = f8fma_sigill,
717 },
718 {
719 .name = "F8MM8",
720 .at_hwcap = AT_HWCAP,
721 .hwcap_bit = HWCAP_F8MM8,
722 .cpuinfo = "f8mm8",
723 .sigill_fn = f8mm8_sigill,
724 },
725 {
726 .name = "F8MM4",
727 .at_hwcap = AT_HWCAP,
728 .hwcap_bit = HWCAP_F8MM4,
729 .cpuinfo = "f8mm4",
730 .sigill_fn = f8mm4_sigill,
731 },
732 {
733 .name = "FAMINMAX",
734 .at_hwcap = AT_HWCAP2,
735 .hwcap_bit = HWCAP2_FAMINMAX,
736 .cpuinfo = "faminmax",
737 .sigill_fn = faminmax_sigill,
738 },
739 {
740 .name = "FP",
741 .at_hwcap = AT_HWCAP,
742 .hwcap_bit = HWCAP_FP,
743 .cpuinfo = "fp",
744 .sigill_fn = fp_sigill,
745 },
746 {
747 .name = "FPMR",
748 .at_hwcap = AT_HWCAP2,
749 .hwcap_bit = HWCAP2_FPMR,
750 .cpuinfo = "fpmr",
751 .sigill_fn = fpmr_sigill,
752 .sigill_reliable = true,
753 },
754 {
755 .name = "FPRCVT",
756 .at_hwcap = AT_HWCAP,
757 .hwcap_bit = HWCAP_FPRCVT,
758 .cpuinfo = "fprcvt",
759 .sigill_fn = fprcvt_sigill,
760 },
761 {
762 .name = "GCS",
763 .at_hwcap = AT_HWCAP,
764 .hwcap_bit = HWCAP_GCS,
765 .cpuinfo = "gcs",
766 .sigill_fn = gcs_sigill,
767 .sigill_reliable = true,
768 },
769 {
770 .name = "JSCVT",
771 .at_hwcap = AT_HWCAP,
772 .hwcap_bit = HWCAP_JSCVT,
773 .cpuinfo = "jscvt",
774 .sigill_fn = jscvt_sigill,
775 },
776 {
777 .name = "LRCPC",
778 .at_hwcap = AT_HWCAP,
779 .hwcap_bit = HWCAP_LRCPC,
780 .cpuinfo = "lrcpc",
781 .sigill_fn = lrcpc_sigill,
782 },
783 {
784 .name = "LRCPC2",
785 .at_hwcap = AT_HWCAP,
786 .hwcap_bit = HWCAP_ILRCPC,
787 .cpuinfo = "ilrcpc",
788 .sigill_fn = ilrcpc_sigill,
789 },
790 {
791 .name = "LRCPC3",
792 .at_hwcap = AT_HWCAP2,
793 .hwcap_bit = HWCAP2_LRCPC3,
794 .cpuinfo = "lrcpc3",
795 .sigill_fn = lrcpc3_sigill,
796 },
797 {
798 .name = "LSE",
799 .at_hwcap = AT_HWCAP,
800 .hwcap_bit = HWCAP_ATOMICS,
801 .cpuinfo = "atomics",
802 .sigill_fn = atomics_sigill,
803 },
804 {
805 .name = "LSE2",
806 .at_hwcap = AT_HWCAP,
807 .hwcap_bit = HWCAP_USCAT,
808 .cpuinfo = "uscat",
809 .sigill_fn = atomics_sigill,
810 .sigbus_fn = uscat_sigbus,
811 .sigbus_reliable = true,
812 },
813 {
814 .name = "LSE128",
815 .at_hwcap = AT_HWCAP2,
816 .hwcap_bit = HWCAP2_LSE128,
817 .cpuinfo = "lse128",
818 .sigill_fn = lse128_sigill,
819 },
820 {
821 .name = "LSFE",
822 .at_hwcap = AT_HWCAP3,
823 .hwcap_bit = HWCAP3_LSFE,
824 .cpuinfo = "lsfe",
825 .sigill_fn = lsfe_sigill,
826 },
827 {
828 .name = "LUT",
829 .at_hwcap = AT_HWCAP2,
830 .hwcap_bit = HWCAP2_LUT,
831 .cpuinfo = "lut",
832 .sigill_fn = lut_sigill,
833 },
834 {
835 .name = "MOPS",
836 .at_hwcap = AT_HWCAP2,
837 .hwcap_bit = HWCAP2_MOPS,
838 .cpuinfo = "mops",
839 .sigill_fn = mops_sigill,
840 .sigill_reliable = true,
841 },
842 {
843 .name = "PMULL",
844 .at_hwcap = AT_HWCAP,
845 .hwcap_bit = HWCAP_PMULL,
846 .cpuinfo = "pmull",
847 .sigill_fn = pmull_sigill,
848 },
849 {
850 .name = "POE",
851 .at_hwcap = AT_HWCAP2,
852 .hwcap_bit = HWCAP2_POE,
853 .cpuinfo = "poe",
854 .sigill_fn = poe_sigill,
855 .sigill_reliable = true,
856 },
857 {
858 .name = "RNG",
859 .at_hwcap = AT_HWCAP2,
860 .hwcap_bit = HWCAP2_RNG,
861 .cpuinfo = "rng",
862 .sigill_fn = rng_sigill,
863 },
864 {
865 .name = "RPRFM",
866 .at_hwcap = AT_HWCAP2,
867 .hwcap_bit = HWCAP2_RPRFM,
868 .cpuinfo = "rprfm",
869 },
870 {
871 .name = "SHA1",
872 .at_hwcap = AT_HWCAP,
873 .hwcap_bit = HWCAP_SHA1,
874 .cpuinfo = "sha1",
875 .sigill_fn = sha1_sigill,
876 },
877 {
878 .name = "SHA2",
879 .at_hwcap = AT_HWCAP,
880 .hwcap_bit = HWCAP_SHA2,
881 .cpuinfo = "sha2",
882 .sigill_fn = sha2_sigill,
883 },
884 {
885 .name = "SHA512",
886 .at_hwcap = AT_HWCAP,
887 .hwcap_bit = HWCAP_SHA512,
888 .cpuinfo = "sha512",
889 .sigill_fn = sha512_sigill,
890 },
891 {
892 .name = "SME",
893 .at_hwcap = AT_HWCAP2,
894 .hwcap_bit = HWCAP2_SME,
895 .cpuinfo = "sme",
896 .sigill_fn = sme_sigill,
897 .sigill_reliable = true,
898 },
899 {
900 .name = "SME2",
901 .at_hwcap = AT_HWCAP2,
902 .hwcap_bit = HWCAP2_SME2,
903 .cpuinfo = "sme2",
904 .sigill_fn = sme2_sigill,
905 .sigill_reliable = true,
906 },
907 {
908 .name = "SME 2.1",
909 .at_hwcap = AT_HWCAP2,
910 .hwcap_bit = HWCAP2_SME2P1,
911 .cpuinfo = "sme2p1",
912 .sigill_fn = sme2p1_sigill,
913 },
914 {
915 .name = "SME 2.2",
916 .at_hwcap = AT_HWCAP,
917 .hwcap_bit = HWCAP_SME2P2,
918 .cpuinfo = "sme2p2",
919 .sigill_fn = sme2p2_sigill,
920 },
921 {
922 .name = "SME AES",
923 .at_hwcap = AT_HWCAP,
924 .hwcap_bit = HWCAP_SME_AES,
925 .cpuinfo = "smeaes",
926 .sigill_fn = sme_aes_sigill,
927 },
928 {
929 .name = "SME I16I32",
930 .at_hwcap = AT_HWCAP2,
931 .hwcap_bit = HWCAP2_SME_I16I32,
932 .cpuinfo = "smei16i32",
933 .sigill_fn = smei16i32_sigill,
934 },
935 {
936 .name = "SME BI32I32",
937 .at_hwcap = AT_HWCAP2,
938 .hwcap_bit = HWCAP2_SME_BI32I32,
939 .cpuinfo = "smebi32i32",
940 .sigill_fn = smebi32i32_sigill,
941 },
942 {
943 .name = "SME B16B16",
944 .at_hwcap = AT_HWCAP2,
945 .hwcap_bit = HWCAP2_SME_B16B16,
946 .cpuinfo = "smeb16b16",
947 .sigill_fn = smeb16b16_sigill,
948 },
949 {
950 .name = "SME F16F16",
951 .at_hwcap = AT_HWCAP2,
952 .hwcap_bit = HWCAP2_SME_F16F16,
953 .cpuinfo = "smef16f16",
954 .sigill_fn = smef16f16_sigill,
955 },
956 {
957 .name = "SME F8F16",
958 .at_hwcap = AT_HWCAP2,
959 .hwcap_bit = HWCAP2_SME_F8F16,
960 .cpuinfo = "smef8f16",
961 .sigill_fn = smef8f16_sigill,
962 },
963 {
964 .name = "SME F8F32",
965 .at_hwcap = AT_HWCAP2,
966 .hwcap_bit = HWCAP2_SME_F8F32,
967 .cpuinfo = "smef8f32",
968 .sigill_fn = smef8f32_sigill,
969 },
970 {
971 .name = "SME LUTV2",
972 .at_hwcap = AT_HWCAP2,
973 .hwcap_bit = HWCAP2_SME_LUTV2,
974 .cpuinfo = "smelutv2",
975 .sigill_fn = smelutv2_sigill,
976 },
977 {
978 .name = "SME SBITPERM",
979 .at_hwcap = AT_HWCAP,
980 .hwcap_bit = HWCAP_SME_SBITPERM,
981 .cpuinfo = "smesbitperm",
982 .sigill_fn = sme_sbitperm_sigill,
983 },
984 {
985 .name = "SME SF8FMA",
986 .at_hwcap = AT_HWCAP2,
987 .hwcap_bit = HWCAP2_SME_SF8FMA,
988 .cpuinfo = "smesf8fma",
989 .sigill_fn = smesf8fma_sigill,
990 },
991 {
992 .name = "SME SF8DP2",
993 .at_hwcap = AT_HWCAP2,
994 .hwcap_bit = HWCAP2_SME_SF8DP2,
995 .cpuinfo = "smesf8dp2",
996 .sigill_fn = smesf8dp2_sigill,
997 },
998 {
999 .name = "SME SF8DP4",
1000 .at_hwcap = AT_HWCAP2,
1001 .hwcap_bit = HWCAP2_SME_SF8DP4,
1002 .cpuinfo = "smesf8dp4",
1003 .sigill_fn = smesf8dp4_sigill,
1004 },
1005 {
1006 .name = "SME SFEXPA",
1007 .at_hwcap = AT_HWCAP,
1008 .hwcap_bit = HWCAP_SME_SFEXPA,
1009 .cpuinfo = "smesfexpa",
1010 .sigill_fn = smesfexpa_sigill,
1011 },
1012 {
1013 .name = "SME SMOP4",
1014 .at_hwcap = AT_HWCAP,
1015 .hwcap_bit = HWCAP_SME_SMOP4,
1016 .cpuinfo = "smesmop4",
1017 .sigill_fn = smesmop4_sigill,
1018 },
1019 {
1020 .name = "SME STMOP",
1021 .at_hwcap = AT_HWCAP,
1022 .hwcap_bit = HWCAP_SME_STMOP,
1023 .cpuinfo = "smestmop",
1024 .sigill_fn = smestmop_sigill,
1025 },
1026 {
1027 .name = "SVE",
1028 .at_hwcap = AT_HWCAP,
1029 .hwcap_bit = HWCAP_SVE,
1030 .cpuinfo = "sve",
1031 .sigill_fn = sve_sigill,
1032 .sigill_reliable = true,
1033 },
1034 {
1035 .name = "SVE 2",
1036 .at_hwcap = AT_HWCAP2,
1037 .hwcap_bit = HWCAP2_SVE2,
1038 .cpuinfo = "sve2",
1039 .sigill_fn = sve2_sigill,
1040 },
1041 {
1042 .name = "SVE 2.1",
1043 .at_hwcap = AT_HWCAP2,
1044 .hwcap_bit = HWCAP2_SVE2P1,
1045 .cpuinfo = "sve2p1",
1046 .sigill_fn = sve2p1_sigill,
1047 },
1048 {
1049 .name = "SVE 2.2",
1050 .at_hwcap = AT_HWCAP,
1051 .hwcap_bit = HWCAP_SVE2P2,
1052 .cpuinfo = "sve2p2",
1053 .sigill_fn = sve2p2_sigill,
1054 },
1055 {
1056 .name = "SVE AES",
1057 .at_hwcap = AT_HWCAP2,
1058 .hwcap_bit = HWCAP2_SVEAES,
1059 .cpuinfo = "sveaes",
1060 .sigill_fn = sveaes_sigill,
1061 },
1062 {
1063 .name = "SVE AES2",
1064 .at_hwcap = AT_HWCAP,
1065 .hwcap_bit = HWCAP_SVE_AES2,
1066 .cpuinfo = "sveaes2",
1067 .sigill_fn = sveaes2_sigill,
1068 },
1069 {
1070 .name = "SVE BFSCALE",
1071 .at_hwcap = AT_HWCAP,
1072 .hwcap_bit = HWCAP_SVE_BFSCALE,
1073 .cpuinfo = "svebfscale",
1074 .sigill_fn = svebfscale_sigill,
1075 },
1076 {
1077 .name = "SVE ELTPERM",
1078 .at_hwcap = AT_HWCAP,
1079 .hwcap_bit = HWCAP_SVE_ELTPERM,
1080 .cpuinfo = "sveeltperm",
1081 .sigill_fn = sveeltperm_sigill,
1082 },
1083 {
1084 .name = "SVE F16MM",
1085 .at_hwcap = AT_HWCAP,
1086 .hwcap_bit = HWCAP_SVE_F16MM,
1087 .cpuinfo = "svef16mm",
1088 .sigill_fn = svef16mm_sigill,
1089 },
1090 {
1091 .name = "SVE2 B16B16",
1092 .at_hwcap = AT_HWCAP2,
1093 .hwcap_bit = HWCAP2_SVE_B16B16,
1094 .cpuinfo = "sveb16b16",
1095 .sigill_fn = sveb16b16_sigill,
1096 },
1097 {
1098 .name = "SVE2 PMULL",
1099 .at_hwcap = AT_HWCAP2,
1100 .hwcap_bit = HWCAP2_SVEPMULL,
1101 .cpuinfo = "svepmull",
1102 .sigill_fn = svepmull_sigill,
1103 },
1104 {
1105 .name = "SVE2 BITPERM",
1106 .at_hwcap = AT_HWCAP2,
1107 .hwcap_bit = HWCAP2_SVEBITPERM,
1108 .cpuinfo = "svebitperm",
1109 .sigill_fn = svebitperm_sigill,
1110 },
1111 {
1112 .name = "SVE2 SHA3",
1113 .at_hwcap = AT_HWCAP2,
1114 .hwcap_bit = HWCAP2_SVESHA3,
1115 .cpuinfo = "svesha3",
1116 .sigill_fn = svesha3_sigill,
1117 },
1118 {
1119 .name = "SVE2 SM4",
1120 .at_hwcap = AT_HWCAP2,
1121 .hwcap_bit = HWCAP2_SVESM4,
1122 .cpuinfo = "svesm4",
1123 .sigill_fn = svesm4_sigill,
1124 },
1125 {
1126 .name = "SVE2 I8MM",
1127 .at_hwcap = AT_HWCAP2,
1128 .hwcap_bit = HWCAP2_SVEI8MM,
1129 .cpuinfo = "svei8mm",
1130 .sigill_fn = svei8mm_sigill,
1131 },
1132 {
1133 .name = "SVE2 F32MM",
1134 .at_hwcap = AT_HWCAP2,
1135 .hwcap_bit = HWCAP2_SVEF32MM,
1136 .cpuinfo = "svef32mm",
1137 .sigill_fn = svef32mm_sigill,
1138 },
1139 {
1140 .name = "SVE2 F64MM",
1141 .at_hwcap = AT_HWCAP2,
1142 .hwcap_bit = HWCAP2_SVEF64MM,
1143 .cpuinfo = "svef64mm",
1144 .sigill_fn = svef64mm_sigill,
1145 },
1146 {
1147 .name = "SVE2 BF16",
1148 .at_hwcap = AT_HWCAP2,
1149 .hwcap_bit = HWCAP2_SVEBF16,
1150 .cpuinfo = "svebf16",
1151 .sigill_fn = svebf16_sigill,
1152 },
1153 {
1154 .name = "SVE2 EBF16",
1155 .at_hwcap = AT_HWCAP2,
1156 .hwcap_bit = HWCAP2_SVE_EBF16,
1157 .cpuinfo = "sveebf16",
1158 },
1159 {
1160 .name = "HBC",
1161 .at_hwcap = AT_HWCAP2,
1162 .hwcap_bit = HWCAP2_HBC,
1163 .cpuinfo = "hbc",
1164 .sigill_fn = hbc_sigill,
1165 .sigill_reliable = true,
1166 },
1167 {
1168 .name = "MTE_FAR",
1169 .at_hwcap = AT_HWCAP3,
1170 .hwcap_bit = HWCAP3_MTE_FAR,
1171 .cpuinfo = "mtefar",
1172 },
1173 {
1174 .name = "MTE_STOREONLY",
1175 .at_hwcap = AT_HWCAP3,
1176 .hwcap_bit = HWCAP3_MTE_STORE_ONLY,
1177 .cpuinfo = "mtestoreonly",
1178 },
1179 {
1180 .name = "LS64",
1181 .at_hwcap = AT_HWCAP3,
1182 .hwcap_bit = HWCAP3_LS64,
1183 .cpuinfo = "ls64",
1184 .sigill_fn = ls64_sigill,
1185 .sigill_reliable = true,
1186 },
1187 };
1188
1189 typedef void (*sighandler_fn)(int, siginfo_t *, void *);
1190
1191 #define DEF_SIGHANDLER_FUNC(SIG, NUM) \
1192 static bool seen_##SIG; \
1193 static void handle_##SIG(int sig, siginfo_t *info, void *context) \
1194 { \
1195 ucontext_t *uc = context; \
1196 \
1197 seen_##SIG = true; \
1198 /* Skip over the offending instruction */ \
1199 uc->uc_mcontext.pc += 4; \
1200 }
1201
1202 DEF_SIGHANDLER_FUNC(sigill, SIGILL);
1203 DEF_SIGHANDLER_FUNC(sigbus, SIGBUS);
1204
cpuinfo_present(const char * name)1205 bool cpuinfo_present(const char *name)
1206 {
1207 FILE *f;
1208 char buf[2048], name_space[30], name_newline[30];
1209 char *s;
1210
1211 /*
1212 * The feature should appear with a leading space and either a
1213 * trailing space or a newline.
1214 */
1215 snprintf(name_space, sizeof(name_space), " %s ", name);
1216 snprintf(name_newline, sizeof(name_newline), " %s\n", name);
1217
1218 f = fopen("/proc/cpuinfo", "r");
1219 if (!f) {
1220 ksft_print_msg("Failed to open /proc/cpuinfo\n");
1221 return false;
1222 }
1223
1224 while (fgets(buf, sizeof(buf), f)) {
1225 /* Features: line? */
1226 if (strncmp(buf, "Features\t:", strlen("Features\t:")) != 0)
1227 continue;
1228
1229 /* All CPUs should be symmetric, don't read any more */
1230 fclose(f);
1231
1232 s = strstr(buf, name_space);
1233 if (s)
1234 return true;
1235 s = strstr(buf, name_newline);
1236 if (s)
1237 return true;
1238
1239 return false;
1240 }
1241
1242 ksft_print_msg("Failed to find Features in /proc/cpuinfo\n");
1243 fclose(f);
1244 return false;
1245 }
1246
install_sigaction(int signum,sighandler_fn handler)1247 static int install_sigaction(int signum, sighandler_fn handler)
1248 {
1249 int ret;
1250 struct sigaction sa;
1251
1252 memset(&sa, 0, sizeof(sa));
1253 sa.sa_sigaction = handler;
1254 sa.sa_flags = SA_RESTART | SA_SIGINFO;
1255 sigemptyset(&sa.sa_mask);
1256 ret = sigaction(signum, &sa, NULL);
1257 if (ret < 0)
1258 ksft_exit_fail_msg("Failed to install SIGNAL handler: %s (%d)\n",
1259 strerror(errno), errno);
1260
1261 return ret;
1262 }
1263
uninstall_sigaction(int signum)1264 static void uninstall_sigaction(int signum)
1265 {
1266 if (sigaction(signum, NULL, NULL) < 0)
1267 ksft_exit_fail_msg("Failed to uninstall SIGNAL handler: %s (%d)\n",
1268 strerror(errno), errno);
1269 }
1270
1271 #define DEF_INST_RAISE_SIG(SIG, NUM) \
1272 static bool inst_raise_##SIG(const struct hwcap_data *hwcap, \
1273 bool have_hwcap) \
1274 { \
1275 if (!hwcap->SIG##_fn) { \
1276 ksft_test_result_skip(#SIG"_%s\n", hwcap->name); \
1277 /* assume that it would raise exception in default */ \
1278 return true; \
1279 } \
1280 \
1281 install_sigaction(NUM, handle_##SIG); \
1282 \
1283 seen_##SIG = false; \
1284 hwcap->SIG##_fn(); \
1285 \
1286 if (have_hwcap) { \
1287 /* Should be able to use the extension */ \
1288 ksft_test_result(!seen_##SIG, \
1289 #SIG"_%s\n", hwcap->name); \
1290 } else if (hwcap->SIG##_reliable) { \
1291 /* Guaranteed a SIGNAL */ \
1292 ksft_test_result(seen_##SIG, \
1293 #SIG"_%s\n", hwcap->name); \
1294 } else { \
1295 /* Missing SIGNAL might be fine */ \
1296 ksft_print_msg(#SIG"_%sreported for %s\n", \
1297 seen_##SIG ? "" : "not ", \
1298 hwcap->name); \
1299 ksft_test_result_skip(#SIG"_%s\n", \
1300 hwcap->name); \
1301 } \
1302 \
1303 uninstall_sigaction(NUM); \
1304 return seen_##SIG; \
1305 }
1306
1307 DEF_INST_RAISE_SIG(sigill, SIGILL);
1308 DEF_INST_RAISE_SIG(sigbus, SIGBUS);
1309
main(void)1310 int main(void)
1311 {
1312 int i;
1313 const struct hwcap_data *hwcap;
1314 bool have_cpuinfo, have_hwcap, raise_sigill;
1315
1316 ksft_print_header();
1317 ksft_set_plan(ARRAY_SIZE(hwcaps) * TESTS_PER_HWCAP);
1318
1319 for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
1320 hwcap = &hwcaps[i];
1321
1322 have_hwcap = getauxval(hwcap->at_hwcap) & hwcap->hwcap_bit;
1323 have_cpuinfo = cpuinfo_present(hwcap->cpuinfo);
1324
1325 if (have_hwcap)
1326 ksft_print_msg("%s present\n", hwcap->name);
1327
1328 ksft_test_result(have_hwcap == have_cpuinfo,
1329 "cpuinfo_match_%s\n", hwcap->name);
1330
1331 /*
1332 * Testing for SIGBUS only makes sense after make sure
1333 * that the instruction does not cause a SIGILL signal.
1334 */
1335 raise_sigill = inst_raise_sigill(hwcap, have_hwcap);
1336 if (!raise_sigill)
1337 inst_raise_sigbus(hwcap, have_hwcap);
1338 else
1339 ksft_test_result_skip("sigbus_%s\n", hwcap->name);
1340 }
1341
1342 ksft_print_cnts();
1343
1344 return 0;
1345 }
1346