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