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 crc32_sigill(void) 50 { 51 /* CRC32W W0, W0, W1 */ 52 asm volatile(".inst 0x1ac14800" : : : ); 53 } 54 55 static void cssc_sigill(void) 56 { 57 /* CNT x0, x0 */ 58 asm volatile(".inst 0xdac01c00" : : : "x0"); 59 } 60 61 static void f8cvt_sigill(void) 62 { 63 /* FSCALE V0.4H, V0.4H, V0.4H */ 64 asm volatile(".inst 0x2ec03c00"); 65 } 66 67 static void f8dp2_sigill(void) 68 { 69 /* FDOT V0.4H, V0.4H, V0.5H */ 70 asm volatile(".inst 0xe40fc00"); 71 } 72 73 static void f8dp4_sigill(void) 74 { 75 /* FDOT V0.2S, V0.2S, V0.2S */ 76 asm volatile(".inst 0xe00fc00"); 77 } 78 79 static void f8fma_sigill(void) 80 { 81 /* FMLALB V0.8H, V0.16B, V0.16B */ 82 asm volatile(".inst 0xec0fc00"); 83 } 84 85 static void faminmax_sigill(void) 86 { 87 /* FAMIN V0.4H, V0.4H, V0.4H */ 88 asm volatile(".inst 0x2ec01c00"); 89 } 90 91 static void fp_sigill(void) 92 { 93 asm volatile("fmov s0, #1"); 94 } 95 96 static void fpmr_sigill(void) 97 { 98 asm volatile("mrs x0, S3_3_C4_C4_2" : : : "x0"); 99 } 100 101 static void gcs_sigill(void) 102 { 103 unsigned long *gcspr; 104 105 asm volatile( 106 "mrs %0, S3_3_C2_C5_1" 107 : "=r" (gcspr) 108 : 109 : "cc"); 110 } 111 112 static void ilrcpc_sigill(void) 113 { 114 /* LDAPUR W0, [SP, #8] */ 115 asm volatile(".inst 0x994083e0" : : : ); 116 } 117 118 static void jscvt_sigill(void) 119 { 120 /* FJCVTZS W0, D0 */ 121 asm volatile(".inst 0x1e7e0000" : : : ); 122 } 123 124 static void lrcpc_sigill(void) 125 { 126 /* LDAPR W0, [SP, #0] */ 127 asm volatile(".inst 0xb8bfc3e0" : : : ); 128 } 129 130 static void lse128_sigill(void) 131 { 132 u64 __attribute__ ((aligned (16))) mem[2] = { 10, 20 }; 133 register u64 *memp asm ("x0") = mem; 134 register u64 val0 asm ("x1") = 5; 135 register u64 val1 asm ("x2") = 4; 136 137 /* SWPP X1, X2, [X0] */ 138 asm volatile(".inst 0x19228001" 139 : "+r" (memp), "+r" (val0), "+r" (val1) 140 : 141 : "cc", "memory"); 142 } 143 144 static void lut_sigill(void) 145 { 146 /* LUTI2 V0.16B, { V0.16B }, V[0] */ 147 asm volatile(".inst 0x4e801000"); 148 } 149 150 static void mops_sigill(void) 151 { 152 char dst[1], src[1]; 153 register char *dstp asm ("x0") = dst; 154 register char *srcp asm ("x1") = src; 155 register long size asm ("x2") = 1; 156 157 /* CPYP [x0]!, [x1]!, x2! */ 158 asm volatile(".inst 0x1d010440" 159 : "+r" (dstp), "+r" (srcp), "+r" (size) 160 : 161 : "cc", "memory"); 162 } 163 164 static void pmull_sigill(void) 165 { 166 /* PMULL V0.1Q, V0.1D, V0.1D */ 167 asm volatile(".inst 0x0ee0e000" : : : ); 168 } 169 170 static void poe_sigill(void) 171 { 172 /* mrs x0, POR_EL0 */ 173 asm volatile("mrs x0, S3_3_C10_C2_4" : : : "x0"); 174 } 175 176 static void rng_sigill(void) 177 { 178 asm volatile("mrs x0, S3_3_C2_C4_0" : : : "x0"); 179 } 180 181 static void sha1_sigill(void) 182 { 183 /* SHA1H S0, S0 */ 184 asm volatile(".inst 0x5e280800" : : : ); 185 } 186 187 static void sha2_sigill(void) 188 { 189 /* SHA256H Q0, Q0, V0.4S */ 190 asm volatile(".inst 0x5e004000" : : : ); 191 } 192 193 static void sha512_sigill(void) 194 { 195 /* SHA512H Q0, Q0, V0.2D */ 196 asm volatile(".inst 0xce608000" : : : ); 197 } 198 199 static void sme_sigill(void) 200 { 201 /* RDSVL x0, #0 */ 202 asm volatile(".inst 0x04bf5800" : : : "x0"); 203 } 204 205 static void sme2_sigill(void) 206 { 207 /* SMSTART ZA */ 208 asm volatile("msr S0_3_C4_C5_3, xzr" : : : ); 209 210 /* ZERO ZT0 */ 211 asm volatile(".inst 0xc0480001" : : : ); 212 213 /* SMSTOP */ 214 asm volatile("msr S0_3_C4_C6_3, xzr" : : : ); 215 } 216 217 static void sme2p1_sigill(void) 218 { 219 /* SMSTART SM */ 220 asm volatile("msr S0_3_C4_C3_3, xzr" : : : ); 221 222 /* BFCLAMP { Z0.H - Z1.H }, Z0.H, Z0.H */ 223 asm volatile(".inst 0xc120C000" : : : ); 224 225 /* SMSTOP */ 226 asm volatile("msr S0_3_C4_C6_3, xzr" : : : ); 227 } 228 229 static void smei16i32_sigill(void) 230 { 231 /* SMSTART */ 232 asm volatile("msr S0_3_C4_C7_3, xzr" : : : ); 233 234 /* SMOPA ZA0.S, P0/M, P0/M, Z0.B, Z0.B */ 235 asm volatile(".inst 0xa0800000" : : : ); 236 237 /* SMSTOP */ 238 asm volatile("msr S0_3_C4_C6_3, xzr" : : : ); 239 } 240 241 static void smebi32i32_sigill(void) 242 { 243 /* SMSTART */ 244 asm volatile("msr S0_3_C4_C7_3, xzr" : : : ); 245 246 /* BMOPA ZA0.S, P0/M, P0/M, Z0.B, Z0.B */ 247 asm volatile(".inst 0x80800008" : : : ); 248 249 /* SMSTOP */ 250 asm volatile("msr S0_3_C4_C6_3, xzr" : : : ); 251 } 252 253 static void smeb16b16_sigill(void) 254 { 255 /* SMSTART */ 256 asm volatile("msr S0_3_C4_C7_3, xzr" : : : ); 257 258 /* BFADD ZA.H[W0, 0], {Z0.H-Z1.H} */ 259 asm volatile(".inst 0xC1E41C00" : : : ); 260 261 /* SMSTOP */ 262 asm volatile("msr S0_3_C4_C6_3, xzr" : : : ); 263 } 264 265 static void smef16f16_sigill(void) 266 { 267 /* SMSTART */ 268 asm volatile("msr S0_3_C4_C7_3, xzr" : : : ); 269 270 /* FADD ZA.H[W0, 0], { Z0.H-Z1.H } */ 271 asm volatile(".inst 0xc1a41C00" : : : ); 272 273 /* SMSTOP */ 274 asm volatile("msr S0_3_C4_C6_3, xzr" : : : ); 275 } 276 277 static void smef8f16_sigill(void) 278 { 279 /* SMSTART */ 280 asm volatile("msr S0_3_C4_C7_3, xzr" : : : ); 281 282 /* FDOT ZA.H[W0, 0], Z0.B-Z1.B, Z0.B-Z1.B */ 283 asm volatile(".inst 0xc1a01020" : : : ); 284 285 /* SMSTOP */ 286 asm volatile("msr S0_3_C4_C6_3, xzr" : : : ); 287 } 288 289 static void smef8f32_sigill(void) 290 { 291 /* SMSTART */ 292 asm volatile("msr S0_3_C4_C7_3, xzr" : : : ); 293 294 /* FDOT ZA.S[W0, 0], { Z0.B-Z1.B }, Z0.B[0] */ 295 asm volatile(".inst 0xc1500038" : : : ); 296 297 /* SMSTOP */ 298 asm volatile("msr S0_3_C4_C6_3, xzr" : : : ); 299 } 300 301 static void smelutv2_sigill(void) 302 { 303 /* SMSTART */ 304 asm volatile("msr S0_3_C4_C7_3, xzr" : : : ); 305 306 /* LUTI4 { Z0.B-Z3.B }, ZT0, { Z0-Z1 } */ 307 asm volatile(".inst 0xc08b0000" : : : ); 308 309 /* SMSTOP */ 310 asm volatile("msr S0_3_C4_C6_3, xzr" : : : ); 311 } 312 313 static void smesf8dp2_sigill(void) 314 { 315 /* SMSTART */ 316 asm volatile("msr S0_3_C4_C7_3, xzr" : : : ); 317 318 /* FDOT Z0.H, Z0.B, Z0.B[0] */ 319 asm volatile(".inst 0x64204400" : : : ); 320 321 /* SMSTOP */ 322 asm volatile("msr S0_3_C4_C6_3, xzr" : : : ); 323 } 324 325 static void smesf8dp4_sigill(void) 326 { 327 /* SMSTART */ 328 asm volatile("msr S0_3_C4_C7_3, xzr" : : : ); 329 330 /* FDOT Z0.S, Z0.B, Z0.B[0] */ 331 asm volatile(".inst 0xc1a41C00" : : : ); 332 333 /* SMSTOP */ 334 asm volatile("msr S0_3_C4_C6_3, xzr" : : : ); 335 } 336 337 static void smesf8fma_sigill(void) 338 { 339 /* SMSTART */ 340 asm volatile("msr S0_3_C4_C7_3, xzr" : : : ); 341 342 /* FMLALB V0.8H, V0.16B, V0.16B */ 343 asm volatile(".inst 0xec0fc00"); 344 345 /* SMSTOP */ 346 asm volatile("msr S0_3_C4_C6_3, xzr" : : : ); 347 } 348 349 static void sve_sigill(void) 350 { 351 /* RDVL x0, #0 */ 352 asm volatile(".inst 0x04bf5000" : : : "x0"); 353 } 354 355 static void sve2_sigill(void) 356 { 357 /* SQABS Z0.b, P0/M, Z0.B */ 358 asm volatile(".inst 0x4408A000" : : : "z0"); 359 } 360 361 static void sve2p1_sigill(void) 362 { 363 /* BFADD Z0.H, Z0.H, Z0.H */ 364 asm volatile(".inst 0x65000000" : : : "z0"); 365 } 366 367 static void sveaes_sigill(void) 368 { 369 /* AESD z0.b, z0.b, z0.b */ 370 asm volatile(".inst 0x4522e400" : : : "z0"); 371 } 372 373 static void sveb16b16_sigill(void) 374 { 375 /* BFADD Z0.H, Z0.H, Z0.H */ 376 asm volatile(".inst 0x65000000" : : : ); 377 } 378 379 static void svepmull_sigill(void) 380 { 381 /* PMULLB Z0.Q, Z0.D, Z0.D */ 382 asm volatile(".inst 0x45006800" : : : "z0"); 383 } 384 385 static void svebitperm_sigill(void) 386 { 387 /* BDEP Z0.B, Z0.B, Z0.B */ 388 asm volatile(".inst 0x4500b400" : : : "z0"); 389 } 390 391 static void svesha3_sigill(void) 392 { 393 /* EOR3 Z0.D, Z0.D, Z0.D, Z0.D */ 394 asm volatile(".inst 0x4203800" : : : "z0"); 395 } 396 397 static void svesm4_sigill(void) 398 { 399 /* SM4E Z0.S, Z0.S, Z0.S */ 400 asm volatile(".inst 0x4523e000" : : : "z0"); 401 } 402 403 static void svei8mm_sigill(void) 404 { 405 /* USDOT Z0.S, Z0.B, Z0.B[0] */ 406 asm volatile(".inst 0x44a01800" : : : "z0"); 407 } 408 409 static void svef32mm_sigill(void) 410 { 411 /* FMMLA Z0.S, Z0.S, Z0.S */ 412 asm volatile(".inst 0x64a0e400" : : : "z0"); 413 } 414 415 static void svef64mm_sigill(void) 416 { 417 /* FMMLA Z0.D, Z0.D, Z0.D */ 418 asm volatile(".inst 0x64e0e400" : : : "z0"); 419 } 420 421 static void svebf16_sigill(void) 422 { 423 /* BFCVT Z0.H, P0/M, Z0.S */ 424 asm volatile(".inst 0x658aa000" : : : "z0"); 425 } 426 427 static void hbc_sigill(void) 428 { 429 /* BC.EQ +4 */ 430 asm volatile("cmp xzr, xzr\n" 431 ".inst 0x54000030" : : : "cc"); 432 } 433 434 static void uscat_sigbus(void) 435 { 436 /* unaligned atomic access */ 437 asm volatile("ADD x1, sp, #2" : : : ); 438 /* STADD W0, [X1] */ 439 asm volatile(".inst 0xb820003f" : : : ); 440 } 441 442 static void lrcpc3_sigill(void) 443 { 444 int data[2] = { 1, 2 }; 445 446 register int *src asm ("x0") = data; 447 register int data0 asm ("w2") = 0; 448 register int data1 asm ("w3") = 0; 449 450 /* LDIAPP w2, w3, [x0] */ 451 asm volatile(".inst 0x99431802" 452 : "=r" (data0), "=r" (data1) : "r" (src) :); 453 } 454 455 static const struct hwcap_data { 456 const char *name; 457 unsigned long at_hwcap; 458 unsigned long hwcap_bit; 459 const char *cpuinfo; 460 sig_fn sigill_fn; 461 bool sigill_reliable; 462 sig_fn sigbus_fn; 463 bool sigbus_reliable; 464 } hwcaps[] = { 465 { 466 .name = "AES", 467 .at_hwcap = AT_HWCAP, 468 .hwcap_bit = HWCAP_AES, 469 .cpuinfo = "aes", 470 .sigill_fn = aes_sigill, 471 }, 472 { 473 .name = "CRC32", 474 .at_hwcap = AT_HWCAP, 475 .hwcap_bit = HWCAP_CRC32, 476 .cpuinfo = "crc32", 477 .sigill_fn = crc32_sigill, 478 }, 479 { 480 .name = "CSSC", 481 .at_hwcap = AT_HWCAP2, 482 .hwcap_bit = HWCAP2_CSSC, 483 .cpuinfo = "cssc", 484 .sigill_fn = cssc_sigill, 485 }, 486 { 487 .name = "F8CVT", 488 .at_hwcap = AT_HWCAP2, 489 .hwcap_bit = HWCAP2_F8CVT, 490 .cpuinfo = "f8cvt", 491 .sigill_fn = f8cvt_sigill, 492 }, 493 { 494 .name = "F8DP4", 495 .at_hwcap = AT_HWCAP2, 496 .hwcap_bit = HWCAP2_F8DP4, 497 .cpuinfo = "f8dp4", 498 .sigill_fn = f8dp4_sigill, 499 }, 500 { 501 .name = "F8DP2", 502 .at_hwcap = AT_HWCAP2, 503 .hwcap_bit = HWCAP2_F8DP2, 504 .cpuinfo = "f8dp2", 505 .sigill_fn = f8dp2_sigill, 506 }, 507 { 508 .name = "F8E5M2", 509 .at_hwcap = AT_HWCAP2, 510 .hwcap_bit = HWCAP2_F8E5M2, 511 .cpuinfo = "f8e5m2", 512 }, 513 { 514 .name = "F8E4M3", 515 .at_hwcap = AT_HWCAP2, 516 .hwcap_bit = HWCAP2_F8E4M3, 517 .cpuinfo = "f8e4m3", 518 }, 519 { 520 .name = "F8FMA", 521 .at_hwcap = AT_HWCAP2, 522 .hwcap_bit = HWCAP2_F8FMA, 523 .cpuinfo = "f8fma", 524 .sigill_fn = f8fma_sigill, 525 }, 526 { 527 .name = "FAMINMAX", 528 .at_hwcap = AT_HWCAP2, 529 .hwcap_bit = HWCAP2_FAMINMAX, 530 .cpuinfo = "faminmax", 531 .sigill_fn = faminmax_sigill, 532 }, 533 { 534 .name = "FP", 535 .at_hwcap = AT_HWCAP, 536 .hwcap_bit = HWCAP_FP, 537 .cpuinfo = "fp", 538 .sigill_fn = fp_sigill, 539 }, 540 { 541 .name = "FPMR", 542 .at_hwcap = AT_HWCAP2, 543 .hwcap_bit = HWCAP2_FPMR, 544 .cpuinfo = "fpmr", 545 .sigill_fn = fpmr_sigill, 546 .sigill_reliable = true, 547 }, 548 { 549 .name = "GCS", 550 .at_hwcap = AT_HWCAP, 551 .hwcap_bit = HWCAP_GCS, 552 .cpuinfo = "gcs", 553 .sigill_fn = gcs_sigill, 554 .sigill_reliable = true, 555 }, 556 { 557 .name = "JSCVT", 558 .at_hwcap = AT_HWCAP, 559 .hwcap_bit = HWCAP_JSCVT, 560 .cpuinfo = "jscvt", 561 .sigill_fn = jscvt_sigill, 562 }, 563 { 564 .name = "LRCPC", 565 .at_hwcap = AT_HWCAP, 566 .hwcap_bit = HWCAP_LRCPC, 567 .cpuinfo = "lrcpc", 568 .sigill_fn = lrcpc_sigill, 569 }, 570 { 571 .name = "LRCPC2", 572 .at_hwcap = AT_HWCAP, 573 .hwcap_bit = HWCAP_ILRCPC, 574 .cpuinfo = "ilrcpc", 575 .sigill_fn = ilrcpc_sigill, 576 }, 577 { 578 .name = "LRCPC3", 579 .at_hwcap = AT_HWCAP2, 580 .hwcap_bit = HWCAP2_LRCPC3, 581 .cpuinfo = "lrcpc3", 582 .sigill_fn = lrcpc3_sigill, 583 }, 584 { 585 .name = "LSE", 586 .at_hwcap = AT_HWCAP, 587 .hwcap_bit = HWCAP_ATOMICS, 588 .cpuinfo = "atomics", 589 .sigill_fn = atomics_sigill, 590 }, 591 { 592 .name = "LSE2", 593 .at_hwcap = AT_HWCAP, 594 .hwcap_bit = HWCAP_USCAT, 595 .cpuinfo = "uscat", 596 .sigill_fn = atomics_sigill, 597 .sigbus_fn = uscat_sigbus, 598 .sigbus_reliable = true, 599 }, 600 { 601 .name = "LSE128", 602 .at_hwcap = AT_HWCAP2, 603 .hwcap_bit = HWCAP2_LSE128, 604 .cpuinfo = "lse128", 605 .sigill_fn = lse128_sigill, 606 }, 607 { 608 .name = "LUT", 609 .at_hwcap = AT_HWCAP2, 610 .hwcap_bit = HWCAP2_LUT, 611 .cpuinfo = "lut", 612 .sigill_fn = lut_sigill, 613 }, 614 { 615 .name = "MOPS", 616 .at_hwcap = AT_HWCAP2, 617 .hwcap_bit = HWCAP2_MOPS, 618 .cpuinfo = "mops", 619 .sigill_fn = mops_sigill, 620 .sigill_reliable = true, 621 }, 622 { 623 .name = "PMULL", 624 .at_hwcap = AT_HWCAP, 625 .hwcap_bit = HWCAP_PMULL, 626 .cpuinfo = "pmull", 627 .sigill_fn = pmull_sigill, 628 }, 629 { 630 .name = "POE", 631 .at_hwcap = AT_HWCAP2, 632 .hwcap_bit = HWCAP2_POE, 633 .cpuinfo = "poe", 634 .sigill_fn = poe_sigill, 635 .sigill_reliable = true, 636 }, 637 { 638 .name = "RNG", 639 .at_hwcap = AT_HWCAP2, 640 .hwcap_bit = HWCAP2_RNG, 641 .cpuinfo = "rng", 642 .sigill_fn = rng_sigill, 643 }, 644 { 645 .name = "RPRFM", 646 .at_hwcap = AT_HWCAP2, 647 .hwcap_bit = HWCAP2_RPRFM, 648 .cpuinfo = "rprfm", 649 }, 650 { 651 .name = "SHA1", 652 .at_hwcap = AT_HWCAP, 653 .hwcap_bit = HWCAP_SHA1, 654 .cpuinfo = "sha1", 655 .sigill_fn = sha1_sigill, 656 }, 657 { 658 .name = "SHA2", 659 .at_hwcap = AT_HWCAP, 660 .hwcap_bit = HWCAP_SHA2, 661 .cpuinfo = "sha2", 662 .sigill_fn = sha2_sigill, 663 }, 664 { 665 .name = "SHA512", 666 .at_hwcap = AT_HWCAP, 667 .hwcap_bit = HWCAP_SHA512, 668 .cpuinfo = "sha512", 669 .sigill_fn = sha512_sigill, 670 }, 671 { 672 .name = "SME", 673 .at_hwcap = AT_HWCAP2, 674 .hwcap_bit = HWCAP2_SME, 675 .cpuinfo = "sme", 676 .sigill_fn = sme_sigill, 677 .sigill_reliable = true, 678 }, 679 { 680 .name = "SME2", 681 .at_hwcap = AT_HWCAP2, 682 .hwcap_bit = HWCAP2_SME2, 683 .cpuinfo = "sme2", 684 .sigill_fn = sme2_sigill, 685 .sigill_reliable = true, 686 }, 687 { 688 .name = "SME 2.1", 689 .at_hwcap = AT_HWCAP2, 690 .hwcap_bit = HWCAP2_SME2P1, 691 .cpuinfo = "sme2p1", 692 .sigill_fn = sme2p1_sigill, 693 }, 694 { 695 .name = "SME I16I32", 696 .at_hwcap = AT_HWCAP2, 697 .hwcap_bit = HWCAP2_SME_I16I32, 698 .cpuinfo = "smei16i32", 699 .sigill_fn = smei16i32_sigill, 700 }, 701 { 702 .name = "SME BI32I32", 703 .at_hwcap = AT_HWCAP2, 704 .hwcap_bit = HWCAP2_SME_BI32I32, 705 .cpuinfo = "smebi32i32", 706 .sigill_fn = smebi32i32_sigill, 707 }, 708 { 709 .name = "SME B16B16", 710 .at_hwcap = AT_HWCAP2, 711 .hwcap_bit = HWCAP2_SME_B16B16, 712 .cpuinfo = "smeb16b16", 713 .sigill_fn = smeb16b16_sigill, 714 }, 715 { 716 .name = "SME F16F16", 717 .at_hwcap = AT_HWCAP2, 718 .hwcap_bit = HWCAP2_SME_F16F16, 719 .cpuinfo = "smef16f16", 720 .sigill_fn = smef16f16_sigill, 721 }, 722 { 723 .name = "SME F8F16", 724 .at_hwcap = AT_HWCAP2, 725 .hwcap_bit = HWCAP2_SME_F8F16, 726 .cpuinfo = "smef8f16", 727 .sigill_fn = smef8f16_sigill, 728 }, 729 { 730 .name = "SME F8F32", 731 .at_hwcap = AT_HWCAP2, 732 .hwcap_bit = HWCAP2_SME_F8F32, 733 .cpuinfo = "smef8f32", 734 .sigill_fn = smef8f32_sigill, 735 }, 736 { 737 .name = "SME LUTV2", 738 .at_hwcap = AT_HWCAP2, 739 .hwcap_bit = HWCAP2_SME_LUTV2, 740 .cpuinfo = "smelutv2", 741 .sigill_fn = smelutv2_sigill, 742 }, 743 { 744 .name = "SME SF8FMA", 745 .at_hwcap = AT_HWCAP2, 746 .hwcap_bit = HWCAP2_SME_SF8FMA, 747 .cpuinfo = "smesf8fma", 748 .sigill_fn = smesf8fma_sigill, 749 }, 750 { 751 .name = "SME SF8DP2", 752 .at_hwcap = AT_HWCAP2, 753 .hwcap_bit = HWCAP2_SME_SF8DP2, 754 .cpuinfo = "smesf8dp2", 755 .sigill_fn = smesf8dp2_sigill, 756 }, 757 { 758 .name = "SME SF8DP4", 759 .at_hwcap = AT_HWCAP2, 760 .hwcap_bit = HWCAP2_SME_SF8DP4, 761 .cpuinfo = "smesf8dp4", 762 .sigill_fn = smesf8dp4_sigill, 763 }, 764 { 765 .name = "SVE", 766 .at_hwcap = AT_HWCAP, 767 .hwcap_bit = HWCAP_SVE, 768 .cpuinfo = "sve", 769 .sigill_fn = sve_sigill, 770 .sigill_reliable = true, 771 }, 772 { 773 .name = "SVE 2", 774 .at_hwcap = AT_HWCAP2, 775 .hwcap_bit = HWCAP2_SVE2, 776 .cpuinfo = "sve2", 777 .sigill_fn = sve2_sigill, 778 }, 779 { 780 .name = "SVE 2.1", 781 .at_hwcap = AT_HWCAP2, 782 .hwcap_bit = HWCAP2_SVE2P1, 783 .cpuinfo = "sve2p1", 784 .sigill_fn = sve2p1_sigill, 785 }, 786 { 787 .name = "SVE AES", 788 .at_hwcap = AT_HWCAP2, 789 .hwcap_bit = HWCAP2_SVEAES, 790 .cpuinfo = "sveaes", 791 .sigill_fn = sveaes_sigill, 792 }, 793 { 794 .name = "SVE2 B16B16", 795 .at_hwcap = AT_HWCAP2, 796 .hwcap_bit = HWCAP2_SVE_B16B16, 797 .cpuinfo = "sveb16b16", 798 .sigill_fn = sveb16b16_sigill, 799 }, 800 { 801 .name = "SVE2 PMULL", 802 .at_hwcap = AT_HWCAP2, 803 .hwcap_bit = HWCAP2_SVEPMULL, 804 .cpuinfo = "svepmull", 805 .sigill_fn = svepmull_sigill, 806 }, 807 { 808 .name = "SVE2 BITPERM", 809 .at_hwcap = AT_HWCAP2, 810 .hwcap_bit = HWCAP2_SVEBITPERM, 811 .cpuinfo = "svebitperm", 812 .sigill_fn = svebitperm_sigill, 813 }, 814 { 815 .name = "SVE2 SHA3", 816 .at_hwcap = AT_HWCAP2, 817 .hwcap_bit = HWCAP2_SVESHA3, 818 .cpuinfo = "svesha3", 819 .sigill_fn = svesha3_sigill, 820 }, 821 { 822 .name = "SVE2 SM4", 823 .at_hwcap = AT_HWCAP2, 824 .hwcap_bit = HWCAP2_SVESM4, 825 .cpuinfo = "svesm4", 826 .sigill_fn = svesm4_sigill, 827 }, 828 { 829 .name = "SVE2 I8MM", 830 .at_hwcap = AT_HWCAP2, 831 .hwcap_bit = HWCAP2_SVEI8MM, 832 .cpuinfo = "svei8mm", 833 .sigill_fn = svei8mm_sigill, 834 }, 835 { 836 .name = "SVE2 F32MM", 837 .at_hwcap = AT_HWCAP2, 838 .hwcap_bit = HWCAP2_SVEF32MM, 839 .cpuinfo = "svef32mm", 840 .sigill_fn = svef32mm_sigill, 841 }, 842 { 843 .name = "SVE2 F64MM", 844 .at_hwcap = AT_HWCAP2, 845 .hwcap_bit = HWCAP2_SVEF64MM, 846 .cpuinfo = "svef64mm", 847 .sigill_fn = svef64mm_sigill, 848 }, 849 { 850 .name = "SVE2 BF16", 851 .at_hwcap = AT_HWCAP2, 852 .hwcap_bit = HWCAP2_SVEBF16, 853 .cpuinfo = "svebf16", 854 .sigill_fn = svebf16_sigill, 855 }, 856 { 857 .name = "SVE2 EBF16", 858 .at_hwcap = AT_HWCAP2, 859 .hwcap_bit = HWCAP2_SVE_EBF16, 860 .cpuinfo = "sveebf16", 861 }, 862 { 863 .name = "HBC", 864 .at_hwcap = AT_HWCAP2, 865 .hwcap_bit = HWCAP2_HBC, 866 .cpuinfo = "hbc", 867 .sigill_fn = hbc_sigill, 868 .sigill_reliable = true, 869 }, 870 }; 871 872 typedef void (*sighandler_fn)(int, siginfo_t *, void *); 873 874 #define DEF_SIGHANDLER_FUNC(SIG, NUM) \ 875 static bool seen_##SIG; \ 876 static void handle_##SIG(int sig, siginfo_t *info, void *context) \ 877 { \ 878 ucontext_t *uc = context; \ 879 \ 880 seen_##SIG = true; \ 881 /* Skip over the offending instruction */ \ 882 uc->uc_mcontext.pc += 4; \ 883 } 884 885 DEF_SIGHANDLER_FUNC(sigill, SIGILL); 886 DEF_SIGHANDLER_FUNC(sigbus, SIGBUS); 887 888 bool cpuinfo_present(const char *name) 889 { 890 FILE *f; 891 char buf[2048], name_space[30], name_newline[30]; 892 char *s; 893 894 /* 895 * The feature should appear with a leading space and either a 896 * trailing space or a newline. 897 */ 898 snprintf(name_space, sizeof(name_space), " %s ", name); 899 snprintf(name_newline, sizeof(name_newline), " %s\n", name); 900 901 f = fopen("/proc/cpuinfo", "r"); 902 if (!f) { 903 ksft_print_msg("Failed to open /proc/cpuinfo\n"); 904 return false; 905 } 906 907 while (fgets(buf, sizeof(buf), f)) { 908 /* Features: line? */ 909 if (strncmp(buf, "Features\t:", strlen("Features\t:")) != 0) 910 continue; 911 912 /* All CPUs should be symmetric, don't read any more */ 913 fclose(f); 914 915 s = strstr(buf, name_space); 916 if (s) 917 return true; 918 s = strstr(buf, name_newline); 919 if (s) 920 return true; 921 922 return false; 923 } 924 925 ksft_print_msg("Failed to find Features in /proc/cpuinfo\n"); 926 fclose(f); 927 return false; 928 } 929 930 static int install_sigaction(int signum, sighandler_fn handler) 931 { 932 int ret; 933 struct sigaction sa; 934 935 memset(&sa, 0, sizeof(sa)); 936 sa.sa_sigaction = handler; 937 sa.sa_flags = SA_RESTART | SA_SIGINFO; 938 sigemptyset(&sa.sa_mask); 939 ret = sigaction(signum, &sa, NULL); 940 if (ret < 0) 941 ksft_exit_fail_msg("Failed to install SIGNAL handler: %s (%d)\n", 942 strerror(errno), errno); 943 944 return ret; 945 } 946 947 static void uninstall_sigaction(int signum) 948 { 949 if (sigaction(signum, NULL, NULL) < 0) 950 ksft_exit_fail_msg("Failed to uninstall SIGNAL handler: %s (%d)\n", 951 strerror(errno), errno); 952 } 953 954 #define DEF_INST_RAISE_SIG(SIG, NUM) \ 955 static bool inst_raise_##SIG(const struct hwcap_data *hwcap, \ 956 bool have_hwcap) \ 957 { \ 958 if (!hwcap->SIG##_fn) { \ 959 ksft_test_result_skip(#SIG"_%s\n", hwcap->name); \ 960 /* assume that it would raise exception in default */ \ 961 return true; \ 962 } \ 963 \ 964 install_sigaction(NUM, handle_##SIG); \ 965 \ 966 seen_##SIG = false; \ 967 hwcap->SIG##_fn(); \ 968 \ 969 if (have_hwcap) { \ 970 /* Should be able to use the extension */ \ 971 ksft_test_result(!seen_##SIG, \ 972 #SIG"_%s\n", hwcap->name); \ 973 } else if (hwcap->SIG##_reliable) { \ 974 /* Guaranteed a SIGNAL */ \ 975 ksft_test_result(seen_##SIG, \ 976 #SIG"_%s\n", hwcap->name); \ 977 } else { \ 978 /* Missing SIGNAL might be fine */ \ 979 ksft_print_msg(#SIG"_%sreported for %s\n", \ 980 seen_##SIG ? "" : "not ", \ 981 hwcap->name); \ 982 ksft_test_result_skip(#SIG"_%s\n", \ 983 hwcap->name); \ 984 } \ 985 \ 986 uninstall_sigaction(NUM); \ 987 return seen_##SIG; \ 988 } 989 990 DEF_INST_RAISE_SIG(sigill, SIGILL); 991 DEF_INST_RAISE_SIG(sigbus, SIGBUS); 992 993 int main(void) 994 { 995 int i; 996 const struct hwcap_data *hwcap; 997 bool have_cpuinfo, have_hwcap, raise_sigill; 998 999 ksft_print_header(); 1000 ksft_set_plan(ARRAY_SIZE(hwcaps) * TESTS_PER_HWCAP); 1001 1002 for (i = 0; i < ARRAY_SIZE(hwcaps); i++) { 1003 hwcap = &hwcaps[i]; 1004 1005 have_hwcap = getauxval(hwcap->at_hwcap) & hwcap->hwcap_bit; 1006 have_cpuinfo = cpuinfo_present(hwcap->cpuinfo); 1007 1008 if (have_hwcap) 1009 ksft_print_msg("%s present\n", hwcap->name); 1010 1011 ksft_test_result(have_hwcap == have_cpuinfo, 1012 "cpuinfo_match_%s\n", hwcap->name); 1013 1014 /* 1015 * Testing for SIGBUS only makes sense after make sure 1016 * that the instruction does not cause a SIGILL signal. 1017 */ 1018 raise_sigill = inst_raise_sigill(hwcap, have_hwcap); 1019 if (!raise_sigill) 1020 inst_raise_sigbus(hwcap, have_hwcap); 1021 else 1022 ksft_test_result_skip("sigbus_%s\n", hwcap->name); 1023 } 1024 1025 ksft_print_cnts(); 1026 1027 return 0; 1028 } 1029