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