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