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