Path: blob/master/tools/testing/selftests/arm64/abi/hwcap.c
26292 views
// SPDX-License-Identifier: GPL-2.0-only1/*2* Copyright (C) 2022 ARM Limited.3*/45#include <errno.h>6#include <signal.h>7#include <stdbool.h>8#include <stddef.h>9#include <stdio.h>10#include <stdlib.h>11#include <string.h>12#include <unistd.h>13#include <sys/auxv.h>14#include <sys/prctl.h>15#include <asm/hwcap.h>16#include <asm/sigcontext.h>17#include <asm/unistd.h>1819#include "../../kselftest.h"2021#define TESTS_PER_HWCAP 32223#ifndef AT_HWCAP324#define AT_HWCAP3 2925#endif2627/*28* Function expected to generate exception when the feature is not29* supported and return when it is supported. If the specific exception30* is generated then the handler must be able to skip over the31* instruction safely.32*33* Note that it is expected that for many architecture extensions34* there are no specific traps due to no architecture state being35* added so we may not fault if running on a kernel which doesn't know36* to add the hwcap.37*/38typedef void (*sig_fn)(void);3940static void aes_sigill(void)41{42/* AESE V0.16B, V0.16B */43asm volatile(".inst 0x4e284800" : : : );44}4546static void atomics_sigill(void)47{48/* STADD W0, [SP] */49asm volatile(".inst 0xb82003ff" : : : );50}5152static void cmpbr_sigill(void)53{54/* Not implemented, too complicated and unreliable anyway */55}565758static void crc32_sigill(void)59{60/* CRC32W W0, W0, W1 */61asm volatile(".inst 0x1ac14800" : : : );62}6364static void cssc_sigill(void)65{66/* CNT x0, x0 */67asm volatile(".inst 0xdac01c00" : : : "x0");68}6970static void f8cvt_sigill(void)71{72/* FSCALE V0.4H, V0.4H, V0.4H */73asm volatile(".inst 0x2ec03c00");74}7576static void f8dp2_sigill(void)77{78/* FDOT V0.4H, V0.4H, V0.5H */79asm volatile(".inst 0xe40fc00");80}8182static void f8dp4_sigill(void)83{84/* FDOT V0.2S, V0.2S, V0.2S */85asm volatile(".inst 0xe00fc00");86}8788static void f8fma_sigill(void)89{90/* FMLALB V0.8H, V0.16B, V0.16B */91asm volatile(".inst 0xec0fc00");92}9394static void f8mm4_sigill(void)95{96/* FMMLA V0.4SH, V0.16B, V0.16B */97asm volatile(".inst 0x6e00ec00");98}99100static void f8mm8_sigill(void)101{102/* FMMLA V0.4S, V0.16B, V0.16B */103asm volatile(".inst 0x6e80ec00");104}105106static void faminmax_sigill(void)107{108/* FAMIN V0.4H, V0.4H, V0.4H */109asm volatile(".inst 0x2ec01c00");110}111112static void fp_sigill(void)113{114asm volatile("fmov s0, #1");115}116117static void fpmr_sigill(void)118{119asm volatile("mrs x0, S3_3_C4_C4_2" : : : "x0");120}121122static void fprcvt_sigill(void)123{124/* FCVTAS S0, H0 */125asm volatile(".inst 0x1efa0000");126}127128static void gcs_sigill(void)129{130unsigned long *gcspr;131132asm volatile(133"mrs %0, S3_3_C2_C5_1"134: "=r" (gcspr)135:136: "cc");137}138139static void ilrcpc_sigill(void)140{141/* LDAPUR W0, [SP, #8] */142asm volatile(".inst 0x994083e0" : : : );143}144145static void jscvt_sigill(void)146{147/* FJCVTZS W0, D0 */148asm volatile(".inst 0x1e7e0000" : : : );149}150151static void lrcpc_sigill(void)152{153/* LDAPR W0, [SP, #0] */154asm volatile(".inst 0xb8bfc3e0" : : : );155}156157static void lse128_sigill(void)158{159u64 __attribute__ ((aligned (16))) mem[2] = { 10, 20 };160register u64 *memp asm ("x0") = mem;161register u64 val0 asm ("x1") = 5;162register u64 val1 asm ("x2") = 4;163164/* SWPP X1, X2, [X0] */165asm volatile(".inst 0x19228001"166: "+r" (memp), "+r" (val0), "+r" (val1)167:168: "cc", "memory");169}170171static void lut_sigill(void)172{173/* LUTI2 V0.16B, { V0.16B }, V[0] */174asm volatile(".inst 0x4e801000");175}176177static void mops_sigill(void)178{179char dst[1], src[1];180register char *dstp asm ("x0") = dst;181register char *srcp asm ("x1") = src;182register long size asm ("x2") = 1;183184/* CPYP [x0]!, [x1]!, x2! */185asm volatile(".inst 0x1d010440"186: "+r" (dstp), "+r" (srcp), "+r" (size)187:188: "cc", "memory");189}190191static void pmull_sigill(void)192{193/* PMULL V0.1Q, V0.1D, V0.1D */194asm volatile(".inst 0x0ee0e000" : : : );195}196197static void poe_sigill(void)198{199/* mrs x0, POR_EL0 */200asm volatile("mrs x0, S3_3_C10_C2_4" : : : "x0");201}202203static void rng_sigill(void)204{205asm volatile("mrs x0, S3_3_C2_C4_0" : : : "x0");206}207208static void sha1_sigill(void)209{210/* SHA1H S0, S0 */211asm volatile(".inst 0x5e280800" : : : );212}213214static void sha2_sigill(void)215{216/* SHA256H Q0, Q0, V0.4S */217asm volatile(".inst 0x5e004000" : : : );218}219220static void sha512_sigill(void)221{222/* SHA512H Q0, Q0, V0.2D */223asm volatile(".inst 0xce608000" : : : );224}225226static void sme_sigill(void)227{228/* RDSVL x0, #0 */229asm volatile(".inst 0x04bf5800" : : : "x0");230}231232static void sme2_sigill(void)233{234/* SMSTART ZA */235asm volatile("msr S0_3_C4_C5_3, xzr" : : : );236237/* ZERO ZT0 */238asm volatile(".inst 0xc0480001" : : : );239240/* SMSTOP */241asm volatile("msr S0_3_C4_C6_3, xzr" : : : );242}243244static void sme2p1_sigill(void)245{246/* SMSTART SM */247asm volatile("msr S0_3_C4_C3_3, xzr" : : : );248249/* BFCLAMP { Z0.H - Z1.H }, Z0.H, Z0.H */250asm volatile(".inst 0xc120C000" : : : );251252/* SMSTOP */253asm volatile("msr S0_3_C4_C6_3, xzr" : : : );254}255256static void sme2p2_sigill(void)257{258/* SMSTART SM */259asm volatile("msr S0_3_C4_C3_3, xzr" : : : );260261/* UXTB Z0.D, P0/Z, Z0.D */262asm volatile(".inst 0x4c1a000" : : : );263264/* SMSTOP */265asm volatile("msr S0_3_C4_C6_3, xzr" : : : );266}267268static void sme_aes_sigill(void)269{270/* SMSTART SM */271asm volatile("msr S0_3_C4_C3_3, xzr" : : : );272273/* AESD z0.b, z0.b, z0.b */274asm volatile(".inst 0x4522e400" : : : "z0");275276/* SMSTOP */277asm volatile("msr S0_3_C4_C6_3, xzr" : : : );278}279280static void sme_sbitperm_sigill(void)281{282/* SMSTART SM */283asm volatile("msr S0_3_C4_C3_3, xzr" : : : );284285/* BDEP Z0.B, Z0.B, Z0.B */286asm volatile(".inst 0x4500b400" : : : "z0");287288/* SMSTOP */289asm volatile("msr S0_3_C4_C6_3, xzr" : : : );290}291292static void smei16i32_sigill(void)293{294/* SMSTART */295asm volatile("msr S0_3_C4_C7_3, xzr" : : : );296297/* SMOPA ZA0.S, P0/M, P0/M, Z0.B, Z0.B */298asm volatile(".inst 0xa0800000" : : : );299300/* SMSTOP */301asm volatile("msr S0_3_C4_C6_3, xzr" : : : );302}303304static void smebi32i32_sigill(void)305{306/* SMSTART */307asm volatile("msr S0_3_C4_C7_3, xzr" : : : );308309/* BMOPA ZA0.S, P0/M, P0/M, Z0.B, Z0.B */310asm volatile(".inst 0x80800008" : : : );311312/* SMSTOP */313asm volatile("msr S0_3_C4_C6_3, xzr" : : : );314}315316static void smeb16b16_sigill(void)317{318/* SMSTART */319asm volatile("msr S0_3_C4_C7_3, xzr" : : : );320321/* BFADD ZA.H[W0, 0], {Z0.H-Z1.H} */322asm volatile(".inst 0xC1E41C00" : : : );323324/* SMSTOP */325asm volatile("msr S0_3_C4_C6_3, xzr" : : : );326}327328static void smef16f16_sigill(void)329{330/* SMSTART */331asm volatile("msr S0_3_C4_C7_3, xzr" : : : );332333/* FADD ZA.H[W0, 0], { Z0.H-Z1.H } */334asm volatile(".inst 0xc1a41C00" : : : );335336/* SMSTOP */337asm volatile("msr S0_3_C4_C6_3, xzr" : : : );338}339340static void smef8f16_sigill(void)341{342/* SMSTART */343asm volatile("msr S0_3_C4_C7_3, xzr" : : : );344345/* FDOT ZA.H[W0, 0], Z0.B-Z1.B, Z0.B-Z1.B */346asm volatile(".inst 0xc1a01020" : : : );347348/* SMSTOP */349asm volatile("msr S0_3_C4_C6_3, xzr" : : : );350}351352static void smef8f32_sigill(void)353{354/* SMSTART */355asm volatile("msr S0_3_C4_C7_3, xzr" : : : );356357/* FDOT ZA.S[W0, 0], { Z0.B-Z1.B }, Z0.B[0] */358asm volatile(".inst 0xc1500038" : : : );359360/* SMSTOP */361asm volatile("msr S0_3_C4_C6_3, xzr" : : : );362}363364static void smelutv2_sigill(void)365{366/* SMSTART */367asm volatile("msr S0_3_C4_C7_3, xzr" : : : );368369/* LUTI4 { Z0.B-Z3.B }, ZT0, { Z0-Z1 } */370asm volatile(".inst 0xc08b0000" : : : );371372/* SMSTOP */373asm volatile("msr S0_3_C4_C6_3, xzr" : : : );374}375376static void smesf8dp2_sigill(void)377{378/* SMSTART */379asm volatile("msr S0_3_C4_C7_3, xzr" : : : );380381/* FDOT Z0.H, Z0.B, Z0.B[0] */382asm volatile(".inst 0x64204400" : : : );383384/* SMSTOP */385asm volatile("msr S0_3_C4_C6_3, xzr" : : : );386}387388static void smesf8dp4_sigill(void)389{390/* SMSTART */391asm volatile("msr S0_3_C4_C7_3, xzr" : : : );392393/* FDOT Z0.S, Z0.B, Z0.B[0] */394asm volatile(".inst 0xc1a41C00" : : : );395396/* SMSTOP */397asm volatile("msr S0_3_C4_C6_3, xzr" : : : );398}399400static void smesf8fma_sigill(void)401{402/* SMSTART */403asm volatile("msr S0_3_C4_C7_3, xzr" : : : );404405/* FMLALB Z0.8H, Z0.B, Z0.B */406asm volatile(".inst 0x64205000");407408/* SMSTOP */409asm volatile("msr S0_3_C4_C6_3, xzr" : : : );410}411412static void smesfexpa_sigill(void)413{414/* SMSTART */415asm volatile("msr S0_3_C4_C7_3, xzr" : : : );416417/* FEXPA Z0.D, Z0.D */418asm volatile(".inst 0x04e0b800");419420/* SMSTOP */421asm volatile("msr S0_3_C4_C6_3, xzr" : : : );422}423424static void smesmop4_sigill(void)425{426/* SMSTART */427asm volatile("msr S0_3_C4_C7_3, xzr" : : : );428429/* SMOP4A ZA0.S, Z0.B, { Z0.B - Z1.B } */430asm volatile(".inst 0x80108000");431432/* SMSTOP */433asm volatile("msr S0_3_C4_C6_3, xzr" : : : );434}435436static void smestmop_sigill(void)437{438/* SMSTART */439asm volatile("msr S0_3_C4_C7_3, xzr" : : : );440441/* STMOPA ZA0.S, { Z0.H - Z1.H }, Z0.H, Z20[0] */442asm volatile(".inst 0x80408008");443444/* SMSTOP */445asm volatile("msr S0_3_C4_C6_3, xzr" : : : );446}447448static void sve_sigill(void)449{450/* RDVL x0, #0 */451asm volatile(".inst 0x04bf5000" : : : "x0");452}453454static void sve2_sigill(void)455{456/* SQABS Z0.b, P0/M, Z0.B */457asm volatile(".inst 0x4408A000" : : : "z0");458}459460static void sve2p1_sigill(void)461{462/* BFADD Z0.H, Z0.H, Z0.H */463asm volatile(".inst 0x65000000" : : : "z0");464}465466static void sve2p2_sigill(void)467{468/* NOT Z0.D, P0/Z, Z0.D */469asm volatile(".inst 0x4cea000" : : : "z0");470}471472static void sveaes_sigill(void)473{474/* AESD z0.b, z0.b, z0.b */475asm volatile(".inst 0x4522e400" : : : "z0");476}477478static void sveaes2_sigill(void)479{480/* AESD {Z0.B - Z1.B }, { Z0.B - Z1.B }, Z0.Q */481asm volatile(".inst 0x4522ec00" : : : "z0");482}483484static void sveb16b16_sigill(void)485{486/* BFADD Z0.H, Z0.H, Z0.H */487asm volatile(".inst 0x65000000" : : : );488}489490static void svebfscale_sigill(void)491{492/* BFSCALE Z0.H, P0/M, Z0.H, Z0.H */493asm volatile(".inst 0x65098000" : : : "z0");494}495496static void svef16mm_sigill(void)497{498/* FMMLA Z0.S, Z0.H, Z0.H */499asm volatile(".inst 0x6420e400");500}501502static void svepmull_sigill(void)503{504/* PMULLB Z0.Q, Z0.D, Z0.D */505asm volatile(".inst 0x45006800" : : : "z0");506}507508static void svebitperm_sigill(void)509{510/* BDEP Z0.B, Z0.B, Z0.B */511asm volatile(".inst 0x4500b400" : : : "z0");512}513514static void svesha3_sigill(void)515{516/* EOR3 Z0.D, Z0.D, Z0.D, Z0.D */517asm volatile(".inst 0x4203800" : : : "z0");518}519520static void sveeltperm_sigill(void)521{522/* COMPACT Z0.B, P0, Z0.B */523asm volatile(".inst 0x5218000" : : : "x0");524}525526static void svesm4_sigill(void)527{528/* SM4E Z0.S, Z0.S, Z0.S */529asm volatile(".inst 0x4523e000" : : : "z0");530}531532static void svei8mm_sigill(void)533{534/* USDOT Z0.S, Z0.B, Z0.B[0] */535asm volatile(".inst 0x44a01800" : : : "z0");536}537538static void svef32mm_sigill(void)539{540/* FMMLA Z0.S, Z0.S, Z0.S */541asm volatile(".inst 0x64a0e400" : : : "z0");542}543544static void svef64mm_sigill(void)545{546/* FMMLA Z0.D, Z0.D, Z0.D */547asm volatile(".inst 0x64e0e400" : : : "z0");548}549550static void svebf16_sigill(void)551{552/* BFCVT Z0.H, P0/M, Z0.S */553asm volatile(".inst 0x658aa000" : : : "z0");554}555556static void hbc_sigill(void)557{558/* BC.EQ +4 */559asm volatile("cmp xzr, xzr\n"560".inst 0x54000030" : : : "cc");561}562563static void uscat_sigbus(void)564{565/* unaligned atomic access */566asm volatile("ADD x1, sp, #2" : : : );567/* STADD W0, [X1] */568asm volatile(".inst 0xb820003f" : : : );569}570571static void lrcpc3_sigill(void)572{573int data[2] = { 1, 2 };574575register int *src asm ("x0") = data;576register int data0 asm ("w2") = 0;577register int data1 asm ("w3") = 0;578579/* LDIAPP w2, w3, [x0] */580asm volatile(".inst 0x99431802"581: "=r" (data0), "=r" (data1) : "r" (src) :);582}583584static const struct hwcap_data {585const char *name;586unsigned long at_hwcap;587unsigned long hwcap_bit;588const char *cpuinfo;589sig_fn sigill_fn;590bool sigill_reliable;591sig_fn sigbus_fn;592bool sigbus_reliable;593} hwcaps[] = {594{595.name = "AES",596.at_hwcap = AT_HWCAP,597.hwcap_bit = HWCAP_AES,598.cpuinfo = "aes",599.sigill_fn = aes_sigill,600},601{602.name = "CMPBR",603.at_hwcap = AT_HWCAP,604.hwcap_bit = HWCAP_CMPBR,605.cpuinfo = "cmpbr",606.sigill_fn = cmpbr_sigill,607},608{609.name = "CRC32",610.at_hwcap = AT_HWCAP,611.hwcap_bit = HWCAP_CRC32,612.cpuinfo = "crc32",613.sigill_fn = crc32_sigill,614},615{616.name = "CSSC",617.at_hwcap = AT_HWCAP2,618.hwcap_bit = HWCAP2_CSSC,619.cpuinfo = "cssc",620.sigill_fn = cssc_sigill,621},622{623.name = "F8CVT",624.at_hwcap = AT_HWCAP2,625.hwcap_bit = HWCAP2_F8CVT,626.cpuinfo = "f8cvt",627.sigill_fn = f8cvt_sigill,628},629{630.name = "F8DP4",631.at_hwcap = AT_HWCAP2,632.hwcap_bit = HWCAP2_F8DP4,633.cpuinfo = "f8dp4",634.sigill_fn = f8dp4_sigill,635},636{637.name = "F8DP2",638.at_hwcap = AT_HWCAP2,639.hwcap_bit = HWCAP2_F8DP2,640.cpuinfo = "f8dp2",641.sigill_fn = f8dp2_sigill,642},643{644.name = "F8E5M2",645.at_hwcap = AT_HWCAP2,646.hwcap_bit = HWCAP2_F8E5M2,647.cpuinfo = "f8e5m2",648},649{650.name = "F8E4M3",651.at_hwcap = AT_HWCAP2,652.hwcap_bit = HWCAP2_F8E4M3,653.cpuinfo = "f8e4m3",654},655{656.name = "F8FMA",657.at_hwcap = AT_HWCAP2,658.hwcap_bit = HWCAP2_F8FMA,659.cpuinfo = "f8fma",660.sigill_fn = f8fma_sigill,661},662{663.name = "F8MM8",664.at_hwcap = AT_HWCAP,665.hwcap_bit = HWCAP_F8MM8,666.cpuinfo = "f8mm8",667.sigill_fn = f8mm8_sigill,668},669{670.name = "F8MM4",671.at_hwcap = AT_HWCAP,672.hwcap_bit = HWCAP_F8MM4,673.cpuinfo = "f8mm4",674.sigill_fn = f8mm4_sigill,675},676{677.name = "FAMINMAX",678.at_hwcap = AT_HWCAP2,679.hwcap_bit = HWCAP2_FAMINMAX,680.cpuinfo = "faminmax",681.sigill_fn = faminmax_sigill,682},683{684.name = "FP",685.at_hwcap = AT_HWCAP,686.hwcap_bit = HWCAP_FP,687.cpuinfo = "fp",688.sigill_fn = fp_sigill,689},690{691.name = "FPMR",692.at_hwcap = AT_HWCAP2,693.hwcap_bit = HWCAP2_FPMR,694.cpuinfo = "fpmr",695.sigill_fn = fpmr_sigill,696.sigill_reliable = true,697},698{699.name = "FPRCVT",700.at_hwcap = AT_HWCAP,701.hwcap_bit = HWCAP_FPRCVT,702.cpuinfo = "fprcvt",703.sigill_fn = fprcvt_sigill,704},705{706.name = "GCS",707.at_hwcap = AT_HWCAP,708.hwcap_bit = HWCAP_GCS,709.cpuinfo = "gcs",710.sigill_fn = gcs_sigill,711.sigill_reliable = true,712},713{714.name = "JSCVT",715.at_hwcap = AT_HWCAP,716.hwcap_bit = HWCAP_JSCVT,717.cpuinfo = "jscvt",718.sigill_fn = jscvt_sigill,719},720{721.name = "LRCPC",722.at_hwcap = AT_HWCAP,723.hwcap_bit = HWCAP_LRCPC,724.cpuinfo = "lrcpc",725.sigill_fn = lrcpc_sigill,726},727{728.name = "LRCPC2",729.at_hwcap = AT_HWCAP,730.hwcap_bit = HWCAP_ILRCPC,731.cpuinfo = "ilrcpc",732.sigill_fn = ilrcpc_sigill,733},734{735.name = "LRCPC3",736.at_hwcap = AT_HWCAP2,737.hwcap_bit = HWCAP2_LRCPC3,738.cpuinfo = "lrcpc3",739.sigill_fn = lrcpc3_sigill,740},741{742.name = "LSE",743.at_hwcap = AT_HWCAP,744.hwcap_bit = HWCAP_ATOMICS,745.cpuinfo = "atomics",746.sigill_fn = atomics_sigill,747},748{749.name = "LSE2",750.at_hwcap = AT_HWCAP,751.hwcap_bit = HWCAP_USCAT,752.cpuinfo = "uscat",753.sigill_fn = atomics_sigill,754.sigbus_fn = uscat_sigbus,755.sigbus_reliable = true,756},757{758.name = "LSE128",759.at_hwcap = AT_HWCAP2,760.hwcap_bit = HWCAP2_LSE128,761.cpuinfo = "lse128",762.sigill_fn = lse128_sigill,763},764{765.name = "LUT",766.at_hwcap = AT_HWCAP2,767.hwcap_bit = HWCAP2_LUT,768.cpuinfo = "lut",769.sigill_fn = lut_sigill,770},771{772.name = "MOPS",773.at_hwcap = AT_HWCAP2,774.hwcap_bit = HWCAP2_MOPS,775.cpuinfo = "mops",776.sigill_fn = mops_sigill,777.sigill_reliable = true,778},779{780.name = "PMULL",781.at_hwcap = AT_HWCAP,782.hwcap_bit = HWCAP_PMULL,783.cpuinfo = "pmull",784.sigill_fn = pmull_sigill,785},786{787.name = "POE",788.at_hwcap = AT_HWCAP2,789.hwcap_bit = HWCAP2_POE,790.cpuinfo = "poe",791.sigill_fn = poe_sigill,792.sigill_reliable = true,793},794{795.name = "RNG",796.at_hwcap = AT_HWCAP2,797.hwcap_bit = HWCAP2_RNG,798.cpuinfo = "rng",799.sigill_fn = rng_sigill,800},801{802.name = "RPRFM",803.at_hwcap = AT_HWCAP2,804.hwcap_bit = HWCAP2_RPRFM,805.cpuinfo = "rprfm",806},807{808.name = "SHA1",809.at_hwcap = AT_HWCAP,810.hwcap_bit = HWCAP_SHA1,811.cpuinfo = "sha1",812.sigill_fn = sha1_sigill,813},814{815.name = "SHA2",816.at_hwcap = AT_HWCAP,817.hwcap_bit = HWCAP_SHA2,818.cpuinfo = "sha2",819.sigill_fn = sha2_sigill,820},821{822.name = "SHA512",823.at_hwcap = AT_HWCAP,824.hwcap_bit = HWCAP_SHA512,825.cpuinfo = "sha512",826.sigill_fn = sha512_sigill,827},828{829.name = "SME",830.at_hwcap = AT_HWCAP2,831.hwcap_bit = HWCAP2_SME,832.cpuinfo = "sme",833.sigill_fn = sme_sigill,834.sigill_reliable = true,835},836{837.name = "SME2",838.at_hwcap = AT_HWCAP2,839.hwcap_bit = HWCAP2_SME2,840.cpuinfo = "sme2",841.sigill_fn = sme2_sigill,842.sigill_reliable = true,843},844{845.name = "SME 2.1",846.at_hwcap = AT_HWCAP2,847.hwcap_bit = HWCAP2_SME2P1,848.cpuinfo = "sme2p1",849.sigill_fn = sme2p1_sigill,850},851{852.name = "SME 2.2",853.at_hwcap = AT_HWCAP,854.hwcap_bit = HWCAP_SME2P2,855.cpuinfo = "sme2p2",856.sigill_fn = sme2p2_sigill,857},858{859.name = "SME AES",860.at_hwcap = AT_HWCAP,861.hwcap_bit = HWCAP_SME_AES,862.cpuinfo = "smeaes",863.sigill_fn = sme_aes_sigill,864},865{866.name = "SME I16I32",867.at_hwcap = AT_HWCAP2,868.hwcap_bit = HWCAP2_SME_I16I32,869.cpuinfo = "smei16i32",870.sigill_fn = smei16i32_sigill,871},872{873.name = "SME BI32I32",874.at_hwcap = AT_HWCAP2,875.hwcap_bit = HWCAP2_SME_BI32I32,876.cpuinfo = "smebi32i32",877.sigill_fn = smebi32i32_sigill,878},879{880.name = "SME B16B16",881.at_hwcap = AT_HWCAP2,882.hwcap_bit = HWCAP2_SME_B16B16,883.cpuinfo = "smeb16b16",884.sigill_fn = smeb16b16_sigill,885},886{887.name = "SME F16F16",888.at_hwcap = AT_HWCAP2,889.hwcap_bit = HWCAP2_SME_F16F16,890.cpuinfo = "smef16f16",891.sigill_fn = smef16f16_sigill,892},893{894.name = "SME F8F16",895.at_hwcap = AT_HWCAP2,896.hwcap_bit = HWCAP2_SME_F8F16,897.cpuinfo = "smef8f16",898.sigill_fn = smef8f16_sigill,899},900{901.name = "SME F8F32",902.at_hwcap = AT_HWCAP2,903.hwcap_bit = HWCAP2_SME_F8F32,904.cpuinfo = "smef8f32",905.sigill_fn = smef8f32_sigill,906},907{908.name = "SME LUTV2",909.at_hwcap = AT_HWCAP2,910.hwcap_bit = HWCAP2_SME_LUTV2,911.cpuinfo = "smelutv2",912.sigill_fn = smelutv2_sigill,913},914{915.name = "SME SBITPERM",916.at_hwcap = AT_HWCAP,917.hwcap_bit = HWCAP_SME_SBITPERM,918.cpuinfo = "smesbitperm",919.sigill_fn = sme_sbitperm_sigill,920},921{922.name = "SME SF8FMA",923.at_hwcap = AT_HWCAP2,924.hwcap_bit = HWCAP2_SME_SF8FMA,925.cpuinfo = "smesf8fma",926.sigill_fn = smesf8fma_sigill,927},928{929.name = "SME SF8DP2",930.at_hwcap = AT_HWCAP2,931.hwcap_bit = HWCAP2_SME_SF8DP2,932.cpuinfo = "smesf8dp2",933.sigill_fn = smesf8dp2_sigill,934},935{936.name = "SME SF8DP4",937.at_hwcap = AT_HWCAP2,938.hwcap_bit = HWCAP2_SME_SF8DP4,939.cpuinfo = "smesf8dp4",940.sigill_fn = smesf8dp4_sigill,941},942{943.name = "SME SFEXPA",944.at_hwcap = AT_HWCAP,945.hwcap_bit = HWCAP_SME_SFEXPA,946.cpuinfo = "smesfexpa",947.sigill_fn = smesfexpa_sigill,948},949{950.name = "SME SMOP4",951.at_hwcap = AT_HWCAP,952.hwcap_bit = HWCAP_SME_SMOP4,953.cpuinfo = "smesmop4",954.sigill_fn = smesmop4_sigill,955},956{957.name = "SME STMOP",958.at_hwcap = AT_HWCAP,959.hwcap_bit = HWCAP_SME_STMOP,960.cpuinfo = "smestmop",961.sigill_fn = smestmop_sigill,962},963{964.name = "SVE",965.at_hwcap = AT_HWCAP,966.hwcap_bit = HWCAP_SVE,967.cpuinfo = "sve",968.sigill_fn = sve_sigill,969.sigill_reliable = true,970},971{972.name = "SVE 2",973.at_hwcap = AT_HWCAP2,974.hwcap_bit = HWCAP2_SVE2,975.cpuinfo = "sve2",976.sigill_fn = sve2_sigill,977},978{979.name = "SVE 2.1",980.at_hwcap = AT_HWCAP2,981.hwcap_bit = HWCAP2_SVE2P1,982.cpuinfo = "sve2p1",983.sigill_fn = sve2p1_sigill,984},985{986.name = "SVE 2.2",987.at_hwcap = AT_HWCAP,988.hwcap_bit = HWCAP_SVE2P2,989.cpuinfo = "sve2p2",990.sigill_fn = sve2p2_sigill,991},992{993.name = "SVE AES",994.at_hwcap = AT_HWCAP2,995.hwcap_bit = HWCAP2_SVEAES,996.cpuinfo = "sveaes",997.sigill_fn = sveaes_sigill,998},999{1000.name = "SVE AES2",1001.at_hwcap = AT_HWCAP,1002.hwcap_bit = HWCAP_SVE_AES2,1003.cpuinfo = "sveaes2",1004.sigill_fn = sveaes2_sigill,1005},1006{1007.name = "SVE BFSCALE",1008.at_hwcap = AT_HWCAP,1009.hwcap_bit = HWCAP_SVE_BFSCALE,1010.cpuinfo = "svebfscale",1011.sigill_fn = svebfscale_sigill,1012},1013{1014.name = "SVE ELTPERM",1015.at_hwcap = AT_HWCAP,1016.hwcap_bit = HWCAP_SVE_ELTPERM,1017.cpuinfo = "sveeltperm",1018.sigill_fn = sveeltperm_sigill,1019},1020{1021.name = "SVE F16MM",1022.at_hwcap = AT_HWCAP,1023.hwcap_bit = HWCAP_SVE_F16MM,1024.cpuinfo = "svef16mm",1025.sigill_fn = svef16mm_sigill,1026},1027{1028.name = "SVE2 B16B16",1029.at_hwcap = AT_HWCAP2,1030.hwcap_bit = HWCAP2_SVE_B16B16,1031.cpuinfo = "sveb16b16",1032.sigill_fn = sveb16b16_sigill,1033},1034{1035.name = "SVE2 PMULL",1036.at_hwcap = AT_HWCAP2,1037.hwcap_bit = HWCAP2_SVEPMULL,1038.cpuinfo = "svepmull",1039.sigill_fn = svepmull_sigill,1040},1041{1042.name = "SVE2 BITPERM",1043.at_hwcap = AT_HWCAP2,1044.hwcap_bit = HWCAP2_SVEBITPERM,1045.cpuinfo = "svebitperm",1046.sigill_fn = svebitperm_sigill,1047},1048{1049.name = "SVE2 SHA3",1050.at_hwcap = AT_HWCAP2,1051.hwcap_bit = HWCAP2_SVESHA3,1052.cpuinfo = "svesha3",1053.sigill_fn = svesha3_sigill,1054},1055{1056.name = "SVE2 SM4",1057.at_hwcap = AT_HWCAP2,1058.hwcap_bit = HWCAP2_SVESM4,1059.cpuinfo = "svesm4",1060.sigill_fn = svesm4_sigill,1061},1062{1063.name = "SVE2 I8MM",1064.at_hwcap = AT_HWCAP2,1065.hwcap_bit = HWCAP2_SVEI8MM,1066.cpuinfo = "svei8mm",1067.sigill_fn = svei8mm_sigill,1068},1069{1070.name = "SVE2 F32MM",1071.at_hwcap = AT_HWCAP2,1072.hwcap_bit = HWCAP2_SVEF32MM,1073.cpuinfo = "svef32mm",1074.sigill_fn = svef32mm_sigill,1075},1076{1077.name = "SVE2 F64MM",1078.at_hwcap = AT_HWCAP2,1079.hwcap_bit = HWCAP2_SVEF64MM,1080.cpuinfo = "svef64mm",1081.sigill_fn = svef64mm_sigill,1082},1083{1084.name = "SVE2 BF16",1085.at_hwcap = AT_HWCAP2,1086.hwcap_bit = HWCAP2_SVEBF16,1087.cpuinfo = "svebf16",1088.sigill_fn = svebf16_sigill,1089},1090{1091.name = "SVE2 EBF16",1092.at_hwcap = AT_HWCAP2,1093.hwcap_bit = HWCAP2_SVE_EBF16,1094.cpuinfo = "sveebf16",1095},1096{1097.name = "HBC",1098.at_hwcap = AT_HWCAP2,1099.hwcap_bit = HWCAP2_HBC,1100.cpuinfo = "hbc",1101.sigill_fn = hbc_sigill,1102.sigill_reliable = true,1103},1104{1105.name = "MTE_FAR",1106.at_hwcap = AT_HWCAP3,1107.hwcap_bit = HWCAP3_MTE_FAR,1108.cpuinfo = "mtefar",1109},1110{1111.name = "MTE_STOREONLY",1112.at_hwcap = AT_HWCAP3,1113.hwcap_bit = HWCAP3_MTE_STORE_ONLY,1114.cpuinfo = "mtestoreonly",1115},1116};11171118typedef void (*sighandler_fn)(int, siginfo_t *, void *);11191120#define DEF_SIGHANDLER_FUNC(SIG, NUM) \1121static bool seen_##SIG; \1122static void handle_##SIG(int sig, siginfo_t *info, void *context) \1123{ \1124ucontext_t *uc = context; \1125\1126seen_##SIG = true; \1127/* Skip over the offending instruction */ \1128uc->uc_mcontext.pc += 4; \1129}11301131DEF_SIGHANDLER_FUNC(sigill, SIGILL);1132DEF_SIGHANDLER_FUNC(sigbus, SIGBUS);11331134bool cpuinfo_present(const char *name)1135{1136FILE *f;1137char buf[2048], name_space[30], name_newline[30];1138char *s;11391140/*1141* The feature should appear with a leading space and either a1142* trailing space or a newline.1143*/1144snprintf(name_space, sizeof(name_space), " %s ", name);1145snprintf(name_newline, sizeof(name_newline), " %s\n", name);11461147f = fopen("/proc/cpuinfo", "r");1148if (!f) {1149ksft_print_msg("Failed to open /proc/cpuinfo\n");1150return false;1151}11521153while (fgets(buf, sizeof(buf), f)) {1154/* Features: line? */1155if (strncmp(buf, "Features\t:", strlen("Features\t:")) != 0)1156continue;11571158/* All CPUs should be symmetric, don't read any more */1159fclose(f);11601161s = strstr(buf, name_space);1162if (s)1163return true;1164s = strstr(buf, name_newline);1165if (s)1166return true;11671168return false;1169}11701171ksft_print_msg("Failed to find Features in /proc/cpuinfo\n");1172fclose(f);1173return false;1174}11751176static int install_sigaction(int signum, sighandler_fn handler)1177{1178int ret;1179struct sigaction sa;11801181memset(&sa, 0, sizeof(sa));1182sa.sa_sigaction = handler;1183sa.sa_flags = SA_RESTART | SA_SIGINFO;1184sigemptyset(&sa.sa_mask);1185ret = sigaction(signum, &sa, NULL);1186if (ret < 0)1187ksft_exit_fail_msg("Failed to install SIGNAL handler: %s (%d)\n",1188strerror(errno), errno);11891190return ret;1191}11921193static void uninstall_sigaction(int signum)1194{1195if (sigaction(signum, NULL, NULL) < 0)1196ksft_exit_fail_msg("Failed to uninstall SIGNAL handler: %s (%d)\n",1197strerror(errno), errno);1198}11991200#define DEF_INST_RAISE_SIG(SIG, NUM) \1201static bool inst_raise_##SIG(const struct hwcap_data *hwcap, \1202bool have_hwcap) \1203{ \1204if (!hwcap->SIG##_fn) { \1205ksft_test_result_skip(#SIG"_%s\n", hwcap->name); \1206/* assume that it would raise exception in default */ \1207return true; \1208} \1209\1210install_sigaction(NUM, handle_##SIG); \1211\1212seen_##SIG = false; \1213hwcap->SIG##_fn(); \1214\1215if (have_hwcap) { \1216/* Should be able to use the extension */ \1217ksft_test_result(!seen_##SIG, \1218#SIG"_%s\n", hwcap->name); \1219} else if (hwcap->SIG##_reliable) { \1220/* Guaranteed a SIGNAL */ \1221ksft_test_result(seen_##SIG, \1222#SIG"_%s\n", hwcap->name); \1223} else { \1224/* Missing SIGNAL might be fine */ \1225ksft_print_msg(#SIG"_%sreported for %s\n", \1226seen_##SIG ? "" : "not ", \1227hwcap->name); \1228ksft_test_result_skip(#SIG"_%s\n", \1229hwcap->name); \1230} \1231\1232uninstall_sigaction(NUM); \1233return seen_##SIG; \1234}12351236DEF_INST_RAISE_SIG(sigill, SIGILL);1237DEF_INST_RAISE_SIG(sigbus, SIGBUS);12381239int main(void)1240{1241int i;1242const struct hwcap_data *hwcap;1243bool have_cpuinfo, have_hwcap, raise_sigill;12441245ksft_print_header();1246ksft_set_plan(ARRAY_SIZE(hwcaps) * TESTS_PER_HWCAP);12471248for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {1249hwcap = &hwcaps[i];12501251have_hwcap = getauxval(hwcap->at_hwcap) & hwcap->hwcap_bit;1252have_cpuinfo = cpuinfo_present(hwcap->cpuinfo);12531254if (have_hwcap)1255ksft_print_msg("%s present\n", hwcap->name);12561257ksft_test_result(have_hwcap == have_cpuinfo,1258"cpuinfo_match_%s\n", hwcap->name);12591260/*1261* Testing for SIGBUS only makes sense after make sure1262* that the instruction does not cause a SIGILL signal.1263*/1264raise_sigill = inst_raise_sigill(hwcap, have_hwcap);1265if (!raise_sigill)1266inst_raise_sigbus(hwcap, have_hwcap);1267else1268ksft_test_result_skip("sigbus_%s\n", hwcap->name);1269}12701271ksft_print_cnts();12721273return 0;1274}127512761277