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