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