1010 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*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 323 24/*25 * Function expected to generate exception when the feature is not26 * supported and return when it is supported. If the specific exception27 * is generated then the handler must be able to skip over the28 * instruction safely.29 *30 * Note that it is expected that for many architecture extensions31 * there are no specific traps due to no architecture state being32 * added so we may not fault if running on a kernel which doesn't know33 * to add the hwcap.34 */35typedef void (*sig_fn)(void);36 37static void aes_sigill(void)38{39 /* AESE V0.16B, V0.16B */40 asm volatile(".inst 0x4e284800" : : : );41}42 43static void atomics_sigill(void)44{45 /* STADD W0, [SP] */46 asm volatile(".inst 0xb82003ff" : : : );47}48 49static void crc32_sigill(void)50{51 /* CRC32W W0, W0, W1 */52 asm volatile(".inst 0x1ac14800" : : : );53}54 55static void cssc_sigill(void)56{57 /* CNT x0, x0 */58 asm volatile(".inst 0xdac01c00" : : : "x0");59}60 61static void f8cvt_sigill(void)62{63 /* FSCALE V0.4H, V0.4H, V0.4H */64 asm volatile(".inst 0x2ec03c00");65}66 67static void f8dp2_sigill(void)68{69 /* FDOT V0.4H, V0.4H, V0.5H */70 asm volatile(".inst 0xe40fc00");71}72 73static void f8dp4_sigill(void)74{75 /* FDOT V0.2S, V0.2S, V0.2S */76 asm volatile(".inst 0xe00fc00");77}78 79static void f8fma_sigill(void)80{81 /* FMLALB V0.8H, V0.16B, V0.16B */82 asm volatile(".inst 0xec0fc00");83}84 85static void faminmax_sigill(void)86{87 /* FAMIN V0.4H, V0.4H, V0.4H */88 asm volatile(".inst 0x2ec01c00");89}90 91static void fp_sigill(void)92{93 asm volatile("fmov s0, #1");94}95 96static void fpmr_sigill(void)97{98 asm volatile("mrs x0, S3_3_C4_C4_2" : : : "x0");99}100 101static void ilrcpc_sigill(void)102{103 /* LDAPUR W0, [SP, #8] */104 asm volatile(".inst 0x994083e0" : : : );105}106 107static void jscvt_sigill(void)108{109 /* FJCVTZS W0, D0 */110 asm volatile(".inst 0x1e7e0000" : : : );111}112 113static void lrcpc_sigill(void)114{115 /* LDAPR W0, [SP, #0] */116 asm volatile(".inst 0xb8bfc3e0" : : : );117}118 119static 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 133static void lut_sigill(void)134{135 /* LUTI2 V0.16B, { V0.16B }, V[0] */136 asm volatile(".inst 0x4e801000");137}138 139static 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 153static void pmull_sigill(void)154{155 /* PMULL V0.1Q, V0.1D, V0.1D */156 asm volatile(".inst 0x0ee0e000" : : : );157}158 159static void poe_sigill(void)160{161 /* mrs x0, POR_EL0 */162 asm volatile("mrs x0, S3_3_C10_C2_4" : : : "x0");163}164 165static void rng_sigill(void)166{167 asm volatile("mrs x0, S3_3_C2_C4_0" : : : "x0");168}169 170static void sha1_sigill(void)171{172 /* SHA1H S0, S0 */173 asm volatile(".inst 0x5e280800" : : : );174}175 176static void sha2_sigill(void)177{178 /* SHA256H Q0, Q0, V0.4S */179 asm volatile(".inst 0x5e004000" : : : );180}181 182static void sha512_sigill(void)183{184 /* SHA512H Q0, Q0, V0.2D */185 asm volatile(".inst 0xce608000" : : : );186}187 188static void sme_sigill(void)189{190 /* RDSVL x0, #0 */191 asm volatile(".inst 0x04bf5800" : : : "x0");192}193 194static 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 206static 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 218static 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 230static 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 242static 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 254static 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 266static 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 278static 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 290static 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 302static 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 314static 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 326static 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 338static void sve_sigill(void)339{340 /* RDVL x0, #0 */341 asm volatile(".inst 0x04bf5000" : : : "x0");342}343 344static void sve2_sigill(void)345{346 /* SQABS Z0.b, P0/M, Z0.B */347 asm volatile(".inst 0x4408A000" : : : "z0");348}349 350static void sve2p1_sigill(void)351{352 /* BFADD Z0.H, Z0.H, Z0.H */353 asm volatile(".inst 0x65000000" : : : "z0");354}355 356static void sveaes_sigill(void)357{358 /* AESD z0.b, z0.b, z0.b */359 asm volatile(".inst 0x4522e400" : : : "z0");360}361 362static void sveb16b16_sigill(void)363{364 /* BFADD ZA.H[W0, 0], {Z0.H-Z1.H} */365 asm volatile(".inst 0xC1E41C00" : : : );366}367 368static void svepmull_sigill(void)369{370 /* PMULLB Z0.Q, Z0.D, Z0.D */371 asm volatile(".inst 0x45006800" : : : "z0");372}373 374static void svebitperm_sigill(void)375{376 /* BDEP Z0.B, Z0.B, Z0.B */377 asm volatile(".inst 0x4500b400" : : : "z0");378}379 380static void svesha3_sigill(void)381{382 /* EOR3 Z0.D, Z0.D, Z0.D, Z0.D */383 asm volatile(".inst 0x4203800" : : : "z0");384}385 386static void svesm4_sigill(void)387{388 /* SM4E Z0.S, Z0.S, Z0.S */389 asm volatile(".inst 0x4523e000" : : : "z0");390}391 392static void svei8mm_sigill(void)393{394 /* USDOT Z0.S, Z0.B, Z0.B[0] */395 asm volatile(".inst 0x44a01800" : : : "z0");396}397 398static void svef32mm_sigill(void)399{400 /* FMMLA Z0.S, Z0.S, Z0.S */401 asm volatile(".inst 0x64a0e400" : : : "z0");402}403 404static void svef64mm_sigill(void)405{406 /* FMMLA Z0.D, Z0.D, Z0.D */407 asm volatile(".inst 0x64e0e400" : : : "z0");408}409 410static void svebf16_sigill(void)411{412 /* BFCVT Z0.H, P0/M, Z0.S */413 asm volatile(".inst 0x658aa000" : : : "z0");414}415 416static void hbc_sigill(void)417{418 /* BC.EQ +4 */419 asm volatile("cmp xzr, xzr\n"420 ".inst 0x54000030" : : : "cc");421}422 423static 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 431static 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 444static 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 853typedef void (*sighandler_fn)(int, siginfo_t *, void *);854 855#define DEF_SIGHANDLER_FUNC(SIG, NUM) \856static bool seen_##SIG; \857static 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 866DEF_SIGHANDLER_FUNC(sigill, SIGILL);867DEF_SIGHANDLER_FUNC(sigbus, SIGBUS);868 869bool 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 a877 * 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 911static 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 928static 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) \936static 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 971DEF_INST_RAISE_SIG(sigill, SIGILL);972DEF_INST_RAISE_SIG(sigbus, SIGBUS);973 974int 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 sure997 * 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 else1003 ksft_test_result_skip("sigbus_%s\n", hwcap->name);1004 }1005 1006 ksft_print_cnts();1007 1008 return 0;1009}1010