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