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