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 37 static void aes_sigill(void) 38 { 39 /* AESE V0.16B, V0.16B */ 40 asm volatile(".inst 0x4e284800" : : : ); 41 } 42 43 static void atomics_sigill(void) 44 { 45 /* STADD W0, [SP] */ 46 asm volatile(".inst 0xb82003ff" : : : ); 47 } 48 49 static void crc32_sigill(void) 50 { 51 /* CRC32W W0, W0, W1 */ 52 asm volatile(".inst 0x1ac14800" : : : ); 53 } 54 55 static void cssc_sigill(void) 56 { 57 /* CNT x0, x0 */ 58 asm volatile(".inst 0xdac01c00" : : : "x0"); 59 } 60 61 static void fp_sigill(void) 62 { 63 asm volatile("fmov s0, #1"); 64 } 65 66 static void ilrcpc_sigill(void) 67 { 68 /* LDAPUR W0, [SP, #8] */ 69 asm volatile(".inst 0x994083e0" : : : ); 70 } 71 72 static void jscvt_sigill(void) 73 { 74 /* FJCVTZS W0, D0 */ 75 asm volatile(".inst 0x1e7e0000" : : : ); 76 } 77 78 static void lrcpc_sigill(void) 79 { 80 /* LDAPR W0, [SP, #0] */ 81 asm volatile(".inst 0xb8bfc3e0" : : : ); 82 } 83 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 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 112 static void pmull_sigill(void) 113 { 114 /* PMULL V0.1Q, V0.1D, V0.1D */ 115 asm volatile(".inst 0x0ee0e000" : : : ); 116 } 117 118 static void rng_sigill(void) 119 { 120 asm volatile("mrs x0, S3_3_C2_C4_0" : : : "x0"); 121 } 122 123 static void sha1_sigill(void) 124 { 125 /* SHA1H S0, S0 */ 126 asm volatile(".inst 0x5e280800" : : : ); 127 } 128 129 static void sha2_sigill(void) 130 { 131 /* SHA256H Q0, Q0, V0.4S */ 132 asm volatile(".inst 0x5e004000" : : : ); 133 } 134 135 static void sha512_sigill(void) 136 { 137 /* SHA512H Q0, Q0, V0.2D */ 138 asm volatile(".inst 0xce608000" : : : ); 139 } 140 141 static void sme_sigill(void) 142 { 143 /* RDSVL x0, #0 */ 144 asm volatile(".inst 0x04bf5800" : : : "x0"); 145 } 146 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 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 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 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 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 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 219 static void sve_sigill(void) 220 { 221 /* RDVL x0, #0 */ 222 asm volatile(".inst 0x04bf5000" : : : "x0"); 223 } 224 225 static void sve2_sigill(void) 226 { 227 /* SQABS Z0.b, P0/M, Z0.B */ 228 asm volatile(".inst 0x4408A000" : : : "z0"); 229 } 230 231 static void sve2p1_sigill(void) 232 { 233 /* BFADD Z0.H, Z0.H, Z0.H */ 234 asm volatile(".inst 0x65000000" : : : "z0"); 235 } 236 237 static void sveaes_sigill(void) 238 { 239 /* AESD z0.b, z0.b, z0.b */ 240 asm volatile(".inst 0x4522e400" : : : "z0"); 241 } 242 243 static void sveb16b16_sigill(void) 244 { 245 /* BFADD ZA.H[W0, 0], {Z0.H-Z1.H} */ 246 asm volatile(".inst 0xC1E41C00" : : : ); 247 } 248 249 static void svepmull_sigill(void) 250 { 251 /* PMULLB Z0.Q, Z0.D, Z0.D */ 252 asm volatile(".inst 0x45006800" : : : "z0"); 253 } 254 255 static void svebitperm_sigill(void) 256 { 257 /* BDEP Z0.B, Z0.B, Z0.B */ 258 asm volatile(".inst 0x4500b400" : : : "z0"); 259 } 260 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 267 static void svesm4_sigill(void) 268 { 269 /* SM4E Z0.S, Z0.S, Z0.S */ 270 asm volatile(".inst 0x4523e000" : : : "z0"); 271 } 272 273 static void svei8mm_sigill(void) 274 { 275 /* USDOT Z0.S, Z0.B, Z0.B[0] */ 276 asm volatile(".inst 0x44a01800" : : : "z0"); 277 } 278 279 static void svef32mm_sigill(void) 280 { 281 /* FMMLA Z0.S, Z0.S, Z0.S */ 282 asm volatile(".inst 0x64a0e400" : : : "z0"); 283 } 284 285 static void svef64mm_sigill(void) 286 { 287 /* FMMLA Z0.D, Z0.D, Z0.D */ 288 asm volatile(".inst 0x64e0e400" : : : "z0"); 289 } 290 291 static void svebf16_sigill(void) 292 { 293 /* BFCVT Z0.H, P0/M, Z0.S */ 294 asm volatile(".inst 0x658aa000" : : : "z0"); 295 } 296 297 static void hbc_sigill(void) 298 { 299 /* BC.EQ +4 */ 300 asm volatile("cmp xzr, xzr\n" 301 ".inst 0x54000030" : : : "cc"); 302 } 303 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 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 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 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 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 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