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