xref: /linux/tools/testing/selftests/arm64/abi/hwcap.c (revision 57a96356bb6942e16283138d0a42baad29169ed8)
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 
45 static void aes_sigill(void)
46 {
47 	/* AESE V0.16B, V0.16B */
48 	asm volatile(".inst 0x4e284800" : : : );
49 }
50 
51 static void atomics_sigill(void)
52 {
53 	/* STADD W0, [SP] */
54 	asm volatile(".inst 0xb82003ff" : : : );
55 }
56 
57 static void cmpbr_sigill(void)
58 {
59 	/* Not implemented, too complicated and unreliable anyway */
60 }
61 
62 static void crc32_sigill(void)
63 {
64 	/* CRC32W W0, W0, W1 */
65 	asm volatile(".inst 0x1ac14800" : : : );
66 }
67 
68 static void cssc_sigill(void)
69 {
70 	/* CNT x0, x0 */
71 	asm volatile(".inst 0xdac01c00" : : : "x0");
72 }
73 
74 static void f8cvt_sigill(void)
75 {
76 	/* FSCALE V0.4H, V0.4H, V0.4H */
77 	asm volatile(".inst 0x2ec03c00");
78 }
79 
80 static void f8dp2_sigill(void)
81 {
82 	/* FDOT V0.4H, V0.4H, V0.5H */
83 	asm volatile(".inst 0xe40fc00");
84 }
85 
86 static void f8dp4_sigill(void)
87 {
88 	/* FDOT V0.2S, V0.2S, V0.2S */
89 	asm volatile(".inst 0xe00fc00");
90 }
91 
92 static void f8fma_sigill(void)
93 {
94 	/* FMLALB V0.8H, V0.16B, V0.16B */
95 	asm volatile(".inst 0xec0fc00");
96 }
97 
98 static void f8mm4_sigill(void)
99 {
100 	/* FMMLA V0.4SH, V0.16B, V0.16B */
101 	asm volatile(".inst 0x6e00ec00");
102 }
103 
104 static void f8mm8_sigill(void)
105 {
106 	/* FMMLA V0.4S, V0.16B, V0.16B */
107 	asm volatile(".inst 0x6e80ec00");
108 }
109 
110 static void faminmax_sigill(void)
111 {
112 	/* FAMIN V0.4H, V0.4H, V0.4H */
113 	asm volatile(".inst 0x2ec01c00");
114 }
115 
116 static void fp_sigill(void)
117 {
118 	asm volatile("fmov s0, #1");
119 }
120 
121 static void fpmr_sigill(void)
122 {
123 	asm volatile("mrs x0, S3_3_C4_C4_2" : : : "x0");
124 }
125 
126 static void fprcvt_sigill(void)
127 {
128 	/* FCVTAS S0, H0 */
129 	asm volatile(".inst 0x1efa0000");
130 }
131 
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 
143 static void ilrcpc_sigill(void)
144 {
145 	/* LDAPUR W0, [SP, #8] */
146 	asm volatile(".inst 0x994083e0" : : : );
147 }
148 
149 static void jscvt_sigill(void)
150 {
151 	/* FJCVTZS W0, D0 */
152 	asm volatile(".inst 0x1e7e0000" : : : );
153 }
154 
155 static void lrcpc_sigill(void)
156 {
157 	/* LDAPR W0, [SP, #0] */
158 	asm volatile(".inst 0xb8bfc3e0" : : : );
159 }
160 
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 
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 
187 static void lut_sigill(void)
188 {
189 	/* LUTI2 V0.16B, { V0.16B }, V[0] */
190 	asm volatile(".inst 0x4e801000");
191 }
192 
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 
207 static void pmull_sigill(void)
208 {
209 	/* PMULL V0.1Q, V0.1D, V0.1D */
210 	asm volatile(".inst 0x0ee0e000" : : : );
211 }
212 
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 
219 static void rng_sigill(void)
220 {
221 	asm volatile("mrs x0, S3_3_C2_C4_0" : : : "x0");
222 }
223 
224 static void sha1_sigill(void)
225 {
226 	/* SHA1H S0, S0 */
227 	asm volatile(".inst 0x5e280800" : : : );
228 }
229 
230 static void sha2_sigill(void)
231 {
232 	/* SHA256H Q0, Q0, V0.4S */
233 	asm volatile(".inst 0x5e004000" : : : );
234 }
235 
236 static void sha512_sigill(void)
237 {
238 	/* SHA512H Q0, Q0, V0.2D */
239 	asm volatile(".inst 0xce608000" : : : );
240 }
241 
242 static void sme_sigill(void)
243 {
244 	/* RDSVL x0, #0 */
245 	asm volatile(".inst 0x04bf5800" : : : "x0");
246 }
247 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
464 static void sve_sigill(void)
465 {
466 	/* RDVL x0, #0 */
467 	asm volatile(".inst 0x04bf5000" : : : "x0");
468 }
469 
470 static void sve2_sigill(void)
471 {
472 	/* SQABS Z0.b, P0/M, Z0.B */
473 	asm volatile(".inst 0x4408A000" : : : "z0");
474 }
475 
476 static void sve2p1_sigill(void)
477 {
478 	/* BFADD Z0.H, Z0.H, Z0.H */
479 	asm volatile(".inst 0x65000000" : : : "z0");
480 }
481 
482 static void sve2p2_sigill(void)
483 {
484 	/* NOT Z0.D, P0/Z, Z0.D */
485 	asm volatile(".inst 0x4cea000" : : : "z0");
486 }
487 
488 static void sveaes_sigill(void)
489 {
490 	/* AESD z0.b, z0.b, z0.b */
491 	asm volatile(".inst 0x4522e400" : : : "z0");
492 }
493 
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 
500 static void sveb16b16_sigill(void)
501 {
502 	/* BFADD Z0.H, Z0.H, Z0.H */
503 	asm volatile(".inst 0x65000000" : : : );
504 }
505 
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 
512 static void svef16mm_sigill(void)
513 {
514 	/* FMMLA Z0.S, Z0.H, Z0.H */
515 	asm volatile(".inst 0x6420e400");
516 }
517 
518 static void svepmull_sigill(void)
519 {
520 	/* PMULLB Z0.Q, Z0.D, Z0.D */
521 	asm volatile(".inst 0x45006800" : : : "z0");
522 }
523 
524 static void svebitperm_sigill(void)
525 {
526 	/* BDEP Z0.B, Z0.B, Z0.B */
527 	asm volatile(".inst 0x4500b400" : : : "z0");
528 }
529 
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 
536 static void sveeltperm_sigill(void)
537 {
538 	/* COMPACT Z0.B, P0, Z0.B */
539 	asm volatile(".inst 0x5218000" : : : "x0");
540 }
541 
542 static void svesm4_sigill(void)
543 {
544 	/* SM4E Z0.S, Z0.S, Z0.S */
545 	asm volatile(".inst 0x4523e000" : : : "z0");
546 }
547 
548 static void svei8mm_sigill(void)
549 {
550 	/* USDOT Z0.S, Z0.B, Z0.B[0] */
551 	asm volatile(".inst 0x44a01800" : : : "z0");
552 }
553 
554 static void svef32mm_sigill(void)
555 {
556 	/* FMMLA Z0.S, Z0.S, Z0.S */
557 	asm volatile(".inst 0x64a0e400" : : : "z0");
558 }
559 
560 static void svef64mm_sigill(void)
561 {
562 	/* FMMLA Z0.D, Z0.D, Z0.D */
563 	asm volatile(".inst 0x64e0e400" : : : "z0");
564 }
565 
566 static void svebf16_sigill(void)
567 {
568 	/* BFCVT Z0.H, P0/M, Z0.S */
569 	asm volatile(".inst 0x658aa000" : : : "z0");
570 }
571 
572 static void hbc_sigill(void)
573 {
574 	/* BC.EQ +4 */
575 	asm volatile("cmp xzr, xzr\n"
576 		     ".inst 0x54000030" : : : "cc");
577 }
578 
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 
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 
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 
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 
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 
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 
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 
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