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