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