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 "../../kselftest.h"
21
22 #define TESTS_PER_HWCAP 3
23
24 /*
25 * Function expected to generate exception when the feature is not
26 * supported and return when it is supported. If the specific exception
27 * is generated then the handler must be able to skip over the
28 * instruction safely.
29 *
30 * Note that it is expected that for many architecture extensions
31 * there are no specific traps due to no architecture state being
32 * added so we may not fault if running on a kernel which doesn't know
33 * to add the hwcap.
34 */
35 typedef void (*sig_fn)(void);
36
aes_sigill(void)37 static void aes_sigill(void)
38 {
39 /* AESE V0.16B, V0.16B */
40 asm volatile(".inst 0x4e284800" : : : );
41 }
42
atomics_sigill(void)43 static void atomics_sigill(void)
44 {
45 /* STADD W0, [SP] */
46 asm volatile(".inst 0xb82003ff" : : : );
47 }
48
crc32_sigill(void)49 static void crc32_sigill(void)
50 {
51 /* CRC32W W0, W0, W1 */
52 asm volatile(".inst 0x1ac14800" : : : );
53 }
54
cssc_sigill(void)55 static void cssc_sigill(void)
56 {
57 /* CNT x0, x0 */
58 asm volatile(".inst 0xdac01c00" : : : "x0");
59 }
60
fp_sigill(void)61 static void fp_sigill(void)
62 {
63 asm volatile("fmov s0, #1");
64 }
65
ilrcpc_sigill(void)66 static void ilrcpc_sigill(void)
67 {
68 /* LDAPUR W0, [SP, #8] */
69 asm volatile(".inst 0x994083e0" : : : );
70 }
71
jscvt_sigill(void)72 static void jscvt_sigill(void)
73 {
74 /* FJCVTZS W0, D0 */
75 asm volatile(".inst 0x1e7e0000" : : : );
76 }
77
lrcpc_sigill(void)78 static void lrcpc_sigill(void)
79 {
80 /* LDAPR W0, [SP, #0] */
81 asm volatile(".inst 0xb8bfc3e0" : : : );
82 }
83
lse128_sigill(void)84 static void lse128_sigill(void)
85 {
86 u64 __attribute__ ((aligned (16))) mem[2] = { 10, 20 };
87 register u64 *memp asm ("x0") = mem;
88 register u64 val0 asm ("x1") = 5;
89 register u64 val1 asm ("x2") = 4;
90
91 /* SWPP X1, X2, [X0] */
92 asm volatile(".inst 0x19228001"
93 : "+r" (memp), "+r" (val0), "+r" (val1)
94 :
95 : "cc", "memory");
96 }
97
mops_sigill(void)98 static void mops_sigill(void)
99 {
100 char dst[1], src[1];
101 register char *dstp asm ("x0") = dst;
102 register char *srcp asm ("x1") = src;
103 register long size asm ("x2") = 1;
104
105 /* CPYP [x0]!, [x1]!, x2! */
106 asm volatile(".inst 0x1d010440"
107 : "+r" (dstp), "+r" (srcp), "+r" (size)
108 :
109 : "cc", "memory");
110 }
111
pmull_sigill(void)112 static void pmull_sigill(void)
113 {
114 /* PMULL V0.1Q, V0.1D, V0.1D */
115 asm volatile(".inst 0x0ee0e000" : : : );
116 }
117
rng_sigill(void)118 static void rng_sigill(void)
119 {
120 asm volatile("mrs x0, S3_3_C2_C4_0" : : : "x0");
121 }
122
sha1_sigill(void)123 static void sha1_sigill(void)
124 {
125 /* SHA1H S0, S0 */
126 asm volatile(".inst 0x5e280800" : : : );
127 }
128
sha2_sigill(void)129 static void sha2_sigill(void)
130 {
131 /* SHA256H Q0, Q0, V0.4S */
132 asm volatile(".inst 0x5e004000" : : : );
133 }
134
sha512_sigill(void)135 static void sha512_sigill(void)
136 {
137 /* SHA512H Q0, Q0, V0.2D */
138 asm volatile(".inst 0xce608000" : : : );
139 }
140
sme_sigill(void)141 static void sme_sigill(void)
142 {
143 /* RDSVL x0, #0 */
144 asm volatile(".inst 0x04bf5800" : : : "x0");
145 }
146
sme2_sigill(void)147 static void sme2_sigill(void)
148 {
149 /* SMSTART ZA */
150 asm volatile("msr S0_3_C4_C5_3, xzr" : : : );
151
152 /* ZERO ZT0 */
153 asm volatile(".inst 0xc0480001" : : : );
154
155 /* SMSTOP */
156 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
157 }
158
sme2p1_sigill(void)159 static void sme2p1_sigill(void)
160 {
161 /* SMSTART SM */
162 asm volatile("msr S0_3_C4_C3_3, xzr" : : : );
163
164 /* BFCLAMP { Z0.H - Z1.H }, Z0.H, Z0.H */
165 asm volatile(".inst 0xc120C000" : : : );
166
167 /* SMSTOP */
168 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
169 }
170
smei16i32_sigill(void)171 static void smei16i32_sigill(void)
172 {
173 /* SMSTART */
174 asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
175
176 /* SMOPA ZA0.S, P0/M, P0/M, Z0.B, Z0.B */
177 asm volatile(".inst 0xa0800000" : : : );
178
179 /* SMSTOP */
180 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
181 }
182
smebi32i32_sigill(void)183 static void smebi32i32_sigill(void)
184 {
185 /* SMSTART */
186 asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
187
188 /* BMOPA ZA0.S, P0/M, P0/M, Z0.B, Z0.B */
189 asm volatile(".inst 0x80800008" : : : );
190
191 /* SMSTOP */
192 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
193 }
194
smeb16b16_sigill(void)195 static void smeb16b16_sigill(void)
196 {
197 /* SMSTART */
198 asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
199
200 /* BFADD ZA.H[W0, 0], {Z0.H-Z1.H} */
201 asm volatile(".inst 0xC1E41C00" : : : );
202
203 /* SMSTOP */
204 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
205 }
206
smef16f16_sigill(void)207 static void smef16f16_sigill(void)
208 {
209 /* SMSTART */
210 asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
211
212 /* FADD ZA.H[W0, 0], { Z0.H-Z1.H } */
213 asm volatile(".inst 0xc1a41C00" : : : );
214
215 /* SMSTOP */
216 asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
217 }
218
sve_sigill(void)219 static void sve_sigill(void)
220 {
221 /* RDVL x0, #0 */
222 asm volatile(".inst 0x04bf5000" : : : "x0");
223 }
224
sve2_sigill(void)225 static void sve2_sigill(void)
226 {
227 /* SQABS Z0.b, P0/M, Z0.B */
228 asm volatile(".inst 0x4408A000" : : : "z0");
229 }
230
sve2p1_sigill(void)231 static void sve2p1_sigill(void)
232 {
233 /* BFADD Z0.H, Z0.H, Z0.H */
234 asm volatile(".inst 0x65000000" : : : "z0");
235 }
236
sveaes_sigill(void)237 static void sveaes_sigill(void)
238 {
239 /* AESD z0.b, z0.b, z0.b */
240 asm volatile(".inst 0x4522e400" : : : "z0");
241 }
242
sveb16b16_sigill(void)243 static void sveb16b16_sigill(void)
244 {
245 /* BFADD ZA.H[W0, 0], {Z0.H-Z1.H} */
246 asm volatile(".inst 0xC1E41C00" : : : );
247 }
248
svepmull_sigill(void)249 static void svepmull_sigill(void)
250 {
251 /* PMULLB Z0.Q, Z0.D, Z0.D */
252 asm volatile(".inst 0x45006800" : : : "z0");
253 }
254
svebitperm_sigill(void)255 static void svebitperm_sigill(void)
256 {
257 /* BDEP Z0.B, Z0.B, Z0.B */
258 asm volatile(".inst 0x4500b400" : : : "z0");
259 }
260
svesha3_sigill(void)261 static void svesha3_sigill(void)
262 {
263 /* EOR3 Z0.D, Z0.D, Z0.D, Z0.D */
264 asm volatile(".inst 0x4203800" : : : "z0");
265 }
266
svesm4_sigill(void)267 static void svesm4_sigill(void)
268 {
269 /* SM4E Z0.S, Z0.S, Z0.S */
270 asm volatile(".inst 0x4523e000" : : : "z0");
271 }
272
svei8mm_sigill(void)273 static void svei8mm_sigill(void)
274 {
275 /* USDOT Z0.S, Z0.B, Z0.B[0] */
276 asm volatile(".inst 0x44a01800" : : : "z0");
277 }
278
svef32mm_sigill(void)279 static void svef32mm_sigill(void)
280 {
281 /* FMMLA Z0.S, Z0.S, Z0.S */
282 asm volatile(".inst 0x64a0e400" : : : "z0");
283 }
284
svef64mm_sigill(void)285 static void svef64mm_sigill(void)
286 {
287 /* FMMLA Z0.D, Z0.D, Z0.D */
288 asm volatile(".inst 0x64e0e400" : : : "z0");
289 }
290
svebf16_sigill(void)291 static void svebf16_sigill(void)
292 {
293 /* BFCVT Z0.H, P0/M, Z0.S */
294 asm volatile(".inst 0x658aa000" : : : "z0");
295 }
296
hbc_sigill(void)297 static void hbc_sigill(void)
298 {
299 /* BC.EQ +4 */
300 asm volatile("cmp xzr, xzr\n"
301 ".inst 0x54000030" : : : "cc");
302 }
303
uscat_sigbus(void)304 static void uscat_sigbus(void)
305 {
306 /* unaligned atomic access */
307 asm volatile("ADD x1, sp, #2" : : : );
308 /* STADD W0, [X1] */
309 asm volatile(".inst 0xb820003f" : : : );
310 }
311
lrcpc3_sigill(void)312 static void lrcpc3_sigill(void)
313 {
314 int data[2] = { 1, 2 };
315
316 register int *src asm ("x0") = data;
317 register int data0 asm ("w2") = 0;
318 register int data1 asm ("w3") = 0;
319
320 /* LDIAPP w2, w3, [x0] */
321 asm volatile(".inst 0x99431802"
322 : "=r" (data0), "=r" (data1) : "r" (src) :);
323 }
324
325 static const struct hwcap_data {
326 const char *name;
327 unsigned long at_hwcap;
328 unsigned long hwcap_bit;
329 const char *cpuinfo;
330 sig_fn sigill_fn;
331 bool sigill_reliable;
332 sig_fn sigbus_fn;
333 bool sigbus_reliable;
334 } hwcaps[] = {
335 {
336 .name = "AES",
337 .at_hwcap = AT_HWCAP,
338 .hwcap_bit = HWCAP_AES,
339 .cpuinfo = "aes",
340 .sigill_fn = aes_sigill,
341 },
342 {
343 .name = "CRC32",
344 .at_hwcap = AT_HWCAP,
345 .hwcap_bit = HWCAP_CRC32,
346 .cpuinfo = "crc32",
347 .sigill_fn = crc32_sigill,
348 },
349 {
350 .name = "CSSC",
351 .at_hwcap = AT_HWCAP2,
352 .hwcap_bit = HWCAP2_CSSC,
353 .cpuinfo = "cssc",
354 .sigill_fn = cssc_sigill,
355 },
356 {
357 .name = "FP",
358 .at_hwcap = AT_HWCAP,
359 .hwcap_bit = HWCAP_FP,
360 .cpuinfo = "fp",
361 .sigill_fn = fp_sigill,
362 },
363 {
364 .name = "JSCVT",
365 .at_hwcap = AT_HWCAP,
366 .hwcap_bit = HWCAP_JSCVT,
367 .cpuinfo = "jscvt",
368 .sigill_fn = jscvt_sigill,
369 },
370 {
371 .name = "LRCPC",
372 .at_hwcap = AT_HWCAP,
373 .hwcap_bit = HWCAP_LRCPC,
374 .cpuinfo = "lrcpc",
375 .sigill_fn = lrcpc_sigill,
376 },
377 {
378 .name = "LRCPC2",
379 .at_hwcap = AT_HWCAP,
380 .hwcap_bit = HWCAP_ILRCPC,
381 .cpuinfo = "ilrcpc",
382 .sigill_fn = ilrcpc_sigill,
383 },
384 {
385 .name = "LRCPC3",
386 .at_hwcap = AT_HWCAP2,
387 .hwcap_bit = HWCAP2_LRCPC3,
388 .cpuinfo = "lrcpc3",
389 .sigill_fn = lrcpc3_sigill,
390 },
391 {
392 .name = "LSE",
393 .at_hwcap = AT_HWCAP,
394 .hwcap_bit = HWCAP_ATOMICS,
395 .cpuinfo = "atomics",
396 .sigill_fn = atomics_sigill,
397 },
398 {
399 .name = "LSE2",
400 .at_hwcap = AT_HWCAP,
401 .hwcap_bit = HWCAP_USCAT,
402 .cpuinfo = "uscat",
403 .sigill_fn = atomics_sigill,
404 .sigbus_fn = uscat_sigbus,
405 .sigbus_reliable = true,
406 },
407 {
408 .name = "LSE128",
409 .at_hwcap = AT_HWCAP2,
410 .hwcap_bit = HWCAP2_LSE128,
411 .cpuinfo = "lse128",
412 .sigill_fn = lse128_sigill,
413 },
414 {
415 .name = "MOPS",
416 .at_hwcap = AT_HWCAP2,
417 .hwcap_bit = HWCAP2_MOPS,
418 .cpuinfo = "mops",
419 .sigill_fn = mops_sigill,
420 .sigill_reliable = true,
421 },
422 {
423 .name = "PMULL",
424 .at_hwcap = AT_HWCAP,
425 .hwcap_bit = HWCAP_PMULL,
426 .cpuinfo = "pmull",
427 .sigill_fn = pmull_sigill,
428 },
429 {
430 .name = "RNG",
431 .at_hwcap = AT_HWCAP2,
432 .hwcap_bit = HWCAP2_RNG,
433 .cpuinfo = "rng",
434 .sigill_fn = rng_sigill,
435 },
436 {
437 .name = "RPRFM",
438 .at_hwcap = AT_HWCAP2,
439 .hwcap_bit = HWCAP2_RPRFM,
440 .cpuinfo = "rprfm",
441 },
442 {
443 .name = "SHA1",
444 .at_hwcap = AT_HWCAP,
445 .hwcap_bit = HWCAP_SHA1,
446 .cpuinfo = "sha1",
447 .sigill_fn = sha1_sigill,
448 },
449 {
450 .name = "SHA2",
451 .at_hwcap = AT_HWCAP,
452 .hwcap_bit = HWCAP_SHA2,
453 .cpuinfo = "sha2",
454 .sigill_fn = sha2_sigill,
455 },
456 {
457 .name = "SHA512",
458 .at_hwcap = AT_HWCAP,
459 .hwcap_bit = HWCAP_SHA512,
460 .cpuinfo = "sha512",
461 .sigill_fn = sha512_sigill,
462 },
463 {
464 .name = "SME",
465 .at_hwcap = AT_HWCAP2,
466 .hwcap_bit = HWCAP2_SME,
467 .cpuinfo = "sme",
468 .sigill_fn = sme_sigill,
469 .sigill_reliable = true,
470 },
471 {
472 .name = "SME2",
473 .at_hwcap = AT_HWCAP2,
474 .hwcap_bit = HWCAP2_SME2,
475 .cpuinfo = "sme2",
476 .sigill_fn = sme2_sigill,
477 .sigill_reliable = true,
478 },
479 {
480 .name = "SME 2.1",
481 .at_hwcap = AT_HWCAP2,
482 .hwcap_bit = HWCAP2_SME2P1,
483 .cpuinfo = "sme2p1",
484 .sigill_fn = sme2p1_sigill,
485 },
486 {
487 .name = "SME I16I32",
488 .at_hwcap = AT_HWCAP2,
489 .hwcap_bit = HWCAP2_SME_I16I32,
490 .cpuinfo = "smei16i32",
491 .sigill_fn = smei16i32_sigill,
492 },
493 {
494 .name = "SME BI32I32",
495 .at_hwcap = AT_HWCAP2,
496 .hwcap_bit = HWCAP2_SME_BI32I32,
497 .cpuinfo = "smebi32i32",
498 .sigill_fn = smebi32i32_sigill,
499 },
500 {
501 .name = "SME B16B16",
502 .at_hwcap = AT_HWCAP2,
503 .hwcap_bit = HWCAP2_SME_B16B16,
504 .cpuinfo = "smeb16b16",
505 .sigill_fn = smeb16b16_sigill,
506 },
507 {
508 .name = "SME F16F16",
509 .at_hwcap = AT_HWCAP2,
510 .hwcap_bit = HWCAP2_SME_F16F16,
511 .cpuinfo = "smef16f16",
512 .sigill_fn = smef16f16_sigill,
513 },
514 {
515 .name = "SVE",
516 .at_hwcap = AT_HWCAP,
517 .hwcap_bit = HWCAP_SVE,
518 .cpuinfo = "sve",
519 .sigill_fn = sve_sigill,
520 .sigill_reliable = true,
521 },
522 {
523 .name = "SVE 2",
524 .at_hwcap = AT_HWCAP2,
525 .hwcap_bit = HWCAP2_SVE2,
526 .cpuinfo = "sve2",
527 .sigill_fn = sve2_sigill,
528 },
529 {
530 .name = "SVE 2.1",
531 .at_hwcap = AT_HWCAP2,
532 .hwcap_bit = HWCAP2_SVE2P1,
533 .cpuinfo = "sve2p1",
534 .sigill_fn = sve2p1_sigill,
535 },
536 {
537 .name = "SVE AES",
538 .at_hwcap = AT_HWCAP2,
539 .hwcap_bit = HWCAP2_SVEAES,
540 .cpuinfo = "sveaes",
541 .sigill_fn = sveaes_sigill,
542 },
543 {
544 .name = "SVE2 B16B16",
545 .at_hwcap = AT_HWCAP2,
546 .hwcap_bit = HWCAP2_SVE_B16B16,
547 .cpuinfo = "sveb16b16",
548 .sigill_fn = sveb16b16_sigill,
549 },
550 {
551 .name = "SVE2 PMULL",
552 .at_hwcap = AT_HWCAP2,
553 .hwcap_bit = HWCAP2_SVEPMULL,
554 .cpuinfo = "svepmull",
555 .sigill_fn = svepmull_sigill,
556 },
557 {
558 .name = "SVE2 BITPERM",
559 .at_hwcap = AT_HWCAP2,
560 .hwcap_bit = HWCAP2_SVEBITPERM,
561 .cpuinfo = "svebitperm",
562 .sigill_fn = svebitperm_sigill,
563 },
564 {
565 .name = "SVE2 SHA3",
566 .at_hwcap = AT_HWCAP2,
567 .hwcap_bit = HWCAP2_SVESHA3,
568 .cpuinfo = "svesha3",
569 .sigill_fn = svesha3_sigill,
570 },
571 {
572 .name = "SVE2 SM4",
573 .at_hwcap = AT_HWCAP2,
574 .hwcap_bit = HWCAP2_SVESM4,
575 .cpuinfo = "svesm4",
576 .sigill_fn = svesm4_sigill,
577 },
578 {
579 .name = "SVE2 I8MM",
580 .at_hwcap = AT_HWCAP2,
581 .hwcap_bit = HWCAP2_SVEI8MM,
582 .cpuinfo = "svei8mm",
583 .sigill_fn = svei8mm_sigill,
584 },
585 {
586 .name = "SVE2 F32MM",
587 .at_hwcap = AT_HWCAP2,
588 .hwcap_bit = HWCAP2_SVEF32MM,
589 .cpuinfo = "svef32mm",
590 .sigill_fn = svef32mm_sigill,
591 },
592 {
593 .name = "SVE2 F64MM",
594 .at_hwcap = AT_HWCAP2,
595 .hwcap_bit = HWCAP2_SVEF64MM,
596 .cpuinfo = "svef64mm",
597 .sigill_fn = svef64mm_sigill,
598 },
599 {
600 .name = "SVE2 BF16",
601 .at_hwcap = AT_HWCAP2,
602 .hwcap_bit = HWCAP2_SVEBF16,
603 .cpuinfo = "svebf16",
604 .sigill_fn = svebf16_sigill,
605 },
606 {
607 .name = "SVE2 EBF16",
608 .at_hwcap = AT_HWCAP2,
609 .hwcap_bit = HWCAP2_SVE_EBF16,
610 .cpuinfo = "sveebf16",
611 },
612 {
613 .name = "HBC",
614 .at_hwcap = AT_HWCAP2,
615 .hwcap_bit = HWCAP2_HBC,
616 .cpuinfo = "hbc",
617 .sigill_fn = hbc_sigill,
618 .sigill_reliable = true,
619 },
620 };
621
622 typedef void (*sighandler_fn)(int, siginfo_t *, void *);
623
624 #define DEF_SIGHANDLER_FUNC(SIG, NUM) \
625 static bool seen_##SIG; \
626 static void handle_##SIG(int sig, siginfo_t *info, void *context) \
627 { \
628 ucontext_t *uc = context; \
629 \
630 seen_##SIG = true; \
631 /* Skip over the offending instruction */ \
632 uc->uc_mcontext.pc += 4; \
633 }
634
635 DEF_SIGHANDLER_FUNC(sigill, SIGILL);
636 DEF_SIGHANDLER_FUNC(sigbus, SIGBUS);
637
cpuinfo_present(const char * name)638 bool cpuinfo_present(const char *name)
639 {
640 FILE *f;
641 char buf[2048], name_space[30], name_newline[30];
642 char *s;
643
644 /*
645 * The feature should appear with a leading space and either a
646 * trailing space or a newline.
647 */
648 snprintf(name_space, sizeof(name_space), " %s ", name);
649 snprintf(name_newline, sizeof(name_newline), " %s\n", name);
650
651 f = fopen("/proc/cpuinfo", "r");
652 if (!f) {
653 ksft_print_msg("Failed to open /proc/cpuinfo\n");
654 return false;
655 }
656
657 while (fgets(buf, sizeof(buf), f)) {
658 /* Features: line? */
659 if (strncmp(buf, "Features\t:", strlen("Features\t:")) != 0)
660 continue;
661
662 /* All CPUs should be symmetric, don't read any more */
663 fclose(f);
664
665 s = strstr(buf, name_space);
666 if (s)
667 return true;
668 s = strstr(buf, name_newline);
669 if (s)
670 return true;
671
672 return false;
673 }
674
675 ksft_print_msg("Failed to find Features in /proc/cpuinfo\n");
676 fclose(f);
677 return false;
678 }
679
install_sigaction(int signum,sighandler_fn handler)680 static int install_sigaction(int signum, sighandler_fn handler)
681 {
682 int ret;
683 struct sigaction sa;
684
685 memset(&sa, 0, sizeof(sa));
686 sa.sa_sigaction = handler;
687 sa.sa_flags = SA_RESTART | SA_SIGINFO;
688 sigemptyset(&sa.sa_mask);
689 ret = sigaction(signum, &sa, NULL);
690 if (ret < 0)
691 ksft_exit_fail_msg("Failed to install SIGNAL handler: %s (%d)\n",
692 strerror(errno), errno);
693
694 return ret;
695 }
696
uninstall_sigaction(int signum)697 static void uninstall_sigaction(int signum)
698 {
699 if (sigaction(signum, NULL, NULL) < 0)
700 ksft_exit_fail_msg("Failed to uninstall SIGNAL handler: %s (%d)\n",
701 strerror(errno), errno);
702 }
703
704 #define DEF_INST_RAISE_SIG(SIG, NUM) \
705 static bool inst_raise_##SIG(const struct hwcap_data *hwcap, \
706 bool have_hwcap) \
707 { \
708 if (!hwcap->SIG##_fn) { \
709 ksft_test_result_skip(#SIG"_%s\n", hwcap->name); \
710 /* assume that it would raise exception in default */ \
711 return true; \
712 } \
713 \
714 install_sigaction(NUM, handle_##SIG); \
715 \
716 seen_##SIG = false; \
717 hwcap->SIG##_fn(); \
718 \
719 if (have_hwcap) { \
720 /* Should be able to use the extension */ \
721 ksft_test_result(!seen_##SIG, \
722 #SIG"_%s\n", hwcap->name); \
723 } else if (hwcap->SIG##_reliable) { \
724 /* Guaranteed a SIGNAL */ \
725 ksft_test_result(seen_##SIG, \
726 #SIG"_%s\n", hwcap->name); \
727 } else { \
728 /* Missing SIGNAL might be fine */ \
729 ksft_print_msg(#SIG"_%sreported for %s\n", \
730 seen_##SIG ? "" : "not ", \
731 hwcap->name); \
732 ksft_test_result_skip(#SIG"_%s\n", \
733 hwcap->name); \
734 } \
735 \
736 uninstall_sigaction(NUM); \
737 return seen_##SIG; \
738 }
739
740 DEF_INST_RAISE_SIG(sigill, SIGILL);
741 DEF_INST_RAISE_SIG(sigbus, SIGBUS);
742
main(void)743 int main(void)
744 {
745 int i;
746 const struct hwcap_data *hwcap;
747 bool have_cpuinfo, have_hwcap, raise_sigill;
748
749 ksft_print_header();
750 ksft_set_plan(ARRAY_SIZE(hwcaps) * TESTS_PER_HWCAP);
751
752 for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
753 hwcap = &hwcaps[i];
754
755 have_hwcap = getauxval(hwcap->at_hwcap) & hwcap->hwcap_bit;
756 have_cpuinfo = cpuinfo_present(hwcap->cpuinfo);
757
758 if (have_hwcap)
759 ksft_print_msg("%s present\n", hwcap->name);
760
761 ksft_test_result(have_hwcap == have_cpuinfo,
762 "cpuinfo_match_%s\n", hwcap->name);
763
764 /*
765 * Testing for SIGBUS only makes sense after make sure
766 * that the instruction does not cause a SIGILL signal.
767 */
768 raise_sigill = inst_raise_sigill(hwcap, have_hwcap);
769 if (!raise_sigill)
770 inst_raise_sigbus(hwcap, have_hwcap);
771 else
772 ksft_test_result_skip("sigbus_%s\n", hwcap->name);
773 }
774
775 ksft_print_cnts();
776
777 return 0;
778 }
779