Path: blob/master/tools/testing/selftests/arm64/abi/hwcap.c
50693 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 <linux/auxvec.h>14#include <linux/compiler.h>15#include <sys/auxv.h>16#include <sys/prctl.h>17#include <asm/hwcap.h>18#include <asm/sigcontext.h>19#include <asm/unistd.h>2021#include <linux/auxvec.h>2223#include "kselftest.h"2425#define TESTS_PER_HWCAP 32627#ifndef AT_HWCAP328#define AT_HWCAP3 2929#endif3031/*32* Function expected to generate exception when the feature is not33* supported and return when it is supported. If the specific exception34* is generated then the handler must be able to skip over the35* instruction safely.36*37* Note that it is expected that for many architecture extensions38* there are no specific traps due to no architecture state being39* added so we may not fault if running on a kernel which doesn't know40* to add the hwcap.41*/42typedef void (*sig_fn)(void);4344static void aes_sigill(void)45{46/* AESE V0.16B, V0.16B */47asm volatile(".inst 0x4e284800" : : : );48}4950static void atomics_sigill(void)51{52/* STADD W0, [SP] */53asm volatile(".inst 0xb82003ff" : : : );54}5556static void cmpbr_sigill(void)57{58/* Not implemented, too complicated and unreliable anyway */59}6061static void crc32_sigill(void)62{63/* CRC32W W0, W0, W1 */64asm volatile(".inst 0x1ac14800" : : : );65}6667static void cssc_sigill(void)68{69/* CNT x0, x0 */70asm volatile(".inst 0xdac01c00" : : : "x0");71}7273static void f8cvt_sigill(void)74{75/* FSCALE V0.4H, V0.4H, V0.4H */76asm volatile(".inst 0x2ec03c00");77}7879static void f8dp2_sigill(void)80{81/* FDOT V0.4H, V0.4H, V0.5H */82asm volatile(".inst 0xe40fc00");83}8485static void f8dp4_sigill(void)86{87/* FDOT V0.2S, V0.2S, V0.2S */88asm volatile(".inst 0xe00fc00");89}9091static void f8fma_sigill(void)92{93/* FMLALB V0.8H, V0.16B, V0.16B */94asm volatile(".inst 0xec0fc00");95}9697static void f8mm4_sigill(void)98{99/* FMMLA V0.4SH, V0.16B, V0.16B */100asm volatile(".inst 0x6e00ec00");101}102103static void f8mm8_sigill(void)104{105/* FMMLA V0.4S, V0.16B, V0.16B */106asm volatile(".inst 0x6e80ec00");107}108109static void faminmax_sigill(void)110{111/* FAMIN V0.4H, V0.4H, V0.4H */112asm volatile(".inst 0x2ec01c00");113}114115static void fp_sigill(void)116{117asm volatile("fmov s0, #1");118}119120static void fpmr_sigill(void)121{122asm volatile("mrs x0, S3_3_C4_C4_2" : : : "x0");123}124125static void fprcvt_sigill(void)126{127/* FCVTAS S0, H0 */128asm volatile(".inst 0x1efa0000");129}130131static void gcs_sigill(void)132{133unsigned long *gcspr;134135asm volatile(136"mrs %0, S3_3_C2_C5_1"137: "=r" (gcspr)138:139: "cc");140}141142static void ilrcpc_sigill(void)143{144/* LDAPUR W0, [SP, #8] */145asm volatile(".inst 0x994083e0" : : : );146}147148static void jscvt_sigill(void)149{150/* FJCVTZS W0, D0 */151asm volatile(".inst 0x1e7e0000" : : : );152}153154static void lrcpc_sigill(void)155{156/* LDAPR W0, [SP, #0] */157asm volatile(".inst 0xb8bfc3e0" : : : );158}159160static void lse128_sigill(void)161{162u64 __attribute__ ((aligned (16))) mem[2] = { 10, 20 };163register u64 *memp asm ("x0") = mem;164register u64 val0 asm ("x1") = 5;165register u64 val1 asm ("x2") = 4;166167/* SWPP X1, X2, [X0] */168asm volatile(".inst 0x19228001"169: "+r" (memp), "+r" (val0), "+r" (val1)170:171: "cc", "memory");172}173174static void lsfe_sigill(void)175{176float __attribute__ ((aligned (16))) mem;177register float *memp asm ("x0") = &mem;178179/* STFADD H0, [X0] */180asm volatile(".inst 0x7c20801f"181: "+r" (memp)182:183: "memory");184}185186static void lut_sigill(void)187{188/* LUTI2 V0.16B, { V0.16B }, V[0] */189asm volatile(".inst 0x4e801000");190}191192static void mops_sigill(void)193{194char dst[1], src[1];195register char *dstp asm ("x0") = dst;196register char *srcp asm ("x1") = src;197register long size asm ("x2") = 1;198199/* CPYP [x0]!, [x1]!, x2! */200asm volatile(".inst 0x1d010440"201: "+r" (dstp), "+r" (srcp), "+r" (size)202:203: "cc", "memory");204}205206static void pmull_sigill(void)207{208/* PMULL V0.1Q, V0.1D, V0.1D */209asm volatile(".inst 0x0ee0e000" : : : );210}211212static void poe_sigill(void)213{214/* mrs x0, POR_EL0 */215asm volatile("mrs x0, S3_3_C10_C2_4" : : : "x0");216}217218static void rng_sigill(void)219{220asm volatile("mrs x0, S3_3_C2_C4_0" : : : "x0");221}222223static void sha1_sigill(void)224{225/* SHA1H S0, S0 */226asm volatile(".inst 0x5e280800" : : : );227}228229static void sha2_sigill(void)230{231/* SHA256H Q0, Q0, V0.4S */232asm volatile(".inst 0x5e004000" : : : );233}234235static void sha512_sigill(void)236{237/* SHA512H Q0, Q0, V0.2D */238asm volatile(".inst 0xce608000" : : : );239}240241static void sme_sigill(void)242{243/* RDSVL x0, #0 */244asm volatile(".inst 0x04bf5800" : : : "x0");245}246247static void sme2_sigill(void)248{249/* SMSTART ZA */250asm volatile("msr S0_3_C4_C5_3, xzr" : : : );251252/* ZERO ZT0 */253asm volatile(".inst 0xc0480001" : : : );254255/* SMSTOP */256asm volatile("msr S0_3_C4_C6_3, xzr" : : : );257}258259static void sme2p1_sigill(void)260{261/* SMSTART SM */262asm volatile("msr S0_3_C4_C3_3, xzr" : : : );263264/* BFCLAMP { Z0.H - Z1.H }, Z0.H, Z0.H */265asm volatile(".inst 0xc120C000" : : : );266267/* SMSTOP */268asm volatile("msr S0_3_C4_C6_3, xzr" : : : );269}270271static void sme2p2_sigill(void)272{273/* SMSTART SM */274asm volatile("msr S0_3_C4_C3_3, xzr" : : : );275276/* UXTB Z0.D, P0/Z, Z0.D */277asm volatile(".inst 0x4c1a000" : : : );278279/* SMSTOP */280asm volatile("msr S0_3_C4_C6_3, xzr" : : : );281}282283static void sme_aes_sigill(void)284{285/* SMSTART SM */286asm volatile("msr S0_3_C4_C3_3, xzr" : : : );287288/* AESD z0.b, z0.b, z0.b */289asm volatile(".inst 0x4522e400" : : : "z0");290291/* SMSTOP */292asm volatile("msr S0_3_C4_C6_3, xzr" : : : );293}294295static void sme_sbitperm_sigill(void)296{297/* SMSTART SM */298asm volatile("msr S0_3_C4_C3_3, xzr" : : : );299300/* BDEP Z0.B, Z0.B, Z0.B */301asm volatile(".inst 0x4500b400" : : : "z0");302303/* SMSTOP */304asm volatile("msr S0_3_C4_C6_3, xzr" : : : );305}306307static void smei16i32_sigill(void)308{309/* SMSTART */310asm volatile("msr S0_3_C4_C7_3, xzr" : : : );311312/* SMOPA ZA0.S, P0/M, P0/M, Z0.B, Z0.B */313asm volatile(".inst 0xa0800000" : : : );314315/* SMSTOP */316asm volatile("msr S0_3_C4_C6_3, xzr" : : : );317}318319static void smebi32i32_sigill(void)320{321/* SMSTART */322asm volatile("msr S0_3_C4_C7_3, xzr" : : : );323324/* BMOPA ZA0.S, P0/M, P0/M, Z0.B, Z0.B */325asm volatile(".inst 0x80800008" : : : );326327/* SMSTOP */328asm volatile("msr S0_3_C4_C6_3, xzr" : : : );329}330331static void smeb16b16_sigill(void)332{333/* SMSTART */334asm volatile("msr S0_3_C4_C7_3, xzr" : : : );335336/* BFADD ZA.H[W0, 0], {Z0.H-Z1.H} */337asm volatile(".inst 0xC1E41C00" : : : );338339/* SMSTOP */340asm volatile("msr S0_3_C4_C6_3, xzr" : : : );341}342343static void smef16f16_sigill(void)344{345/* SMSTART */346asm volatile("msr S0_3_C4_C7_3, xzr" : : : );347348/* FADD ZA.H[W0, 0], { Z0.H-Z1.H } */349asm volatile(".inst 0xc1a41C00" : : : );350351/* SMSTOP */352asm volatile("msr S0_3_C4_C6_3, xzr" : : : );353}354355static void smef8f16_sigill(void)356{357/* SMSTART */358asm volatile("msr S0_3_C4_C7_3, xzr" : : : );359360/* FDOT ZA.H[W0, 0], Z0.B-Z1.B, Z0.B-Z1.B */361asm volatile(".inst 0xc1a01020" : : : );362363/* SMSTOP */364asm volatile("msr S0_3_C4_C6_3, xzr" : : : );365}366367static void smef8f32_sigill(void)368{369/* SMSTART */370asm volatile("msr S0_3_C4_C7_3, xzr" : : : );371372/* FDOT ZA.S[W0, 0], { Z0.B-Z1.B }, Z0.B[0] */373asm volatile(".inst 0xc1500038" : : : );374375/* SMSTOP */376asm volatile("msr S0_3_C4_C6_3, xzr" : : : );377}378379static void smelutv2_sigill(void)380{381/* SMSTART */382asm volatile("msr S0_3_C4_C7_3, xzr" : : : );383384/* LUTI4 { Z0.B-Z3.B }, ZT0, { Z0-Z1 } */385asm volatile(".inst 0xc08b0000" : : : );386387/* SMSTOP */388asm volatile("msr S0_3_C4_C6_3, xzr" : : : );389}390391static void smesf8dp2_sigill(void)392{393/* SMSTART */394asm volatile("msr S0_3_C4_C7_3, xzr" : : : );395396/* FDOT Z0.H, Z0.B, Z0.B[0] */397asm volatile(".inst 0x64204400" : : : );398399/* SMSTOP */400asm volatile("msr S0_3_C4_C6_3, xzr" : : : );401}402403static void smesf8dp4_sigill(void)404{405/* SMSTART */406asm volatile("msr S0_3_C4_C7_3, xzr" : : : );407408/* FDOT Z0.S, Z0.B, Z0.B[0] */409asm volatile(".inst 0xc1a41C00" : : : );410411/* SMSTOP */412asm volatile("msr S0_3_C4_C6_3, xzr" : : : );413}414415static void smesf8fma_sigill(void)416{417/* SMSTART */418asm volatile("msr S0_3_C4_C7_3, xzr" : : : );419420/* FMLALB Z0.8H, Z0.B, Z0.B */421asm volatile(".inst 0x64205000");422423/* SMSTOP */424asm volatile("msr S0_3_C4_C6_3, xzr" : : : );425}426427static void smesfexpa_sigill(void)428{429/* SMSTART */430asm volatile("msr S0_3_C4_C7_3, xzr" : : : );431432/* FEXPA Z0.D, Z0.D */433asm volatile(".inst 0x04e0b800");434435/* SMSTOP */436asm volatile("msr S0_3_C4_C6_3, xzr" : : : );437}438439static void smesmop4_sigill(void)440{441/* SMSTART */442asm volatile("msr S0_3_C4_C7_3, xzr" : : : );443444/* SMOP4A ZA0.S, Z0.B, { Z0.B - Z1.B } */445asm volatile(".inst 0x80108000");446447/* SMSTOP */448asm volatile("msr S0_3_C4_C6_3, xzr" : : : );449}450451static void smestmop_sigill(void)452{453/* SMSTART */454asm volatile("msr S0_3_C4_C7_3, xzr" : : : );455456/* STMOPA ZA0.S, { Z0.H - Z1.H }, Z0.H, Z20[0] */457asm volatile(".inst 0x80408008");458459/* SMSTOP */460asm volatile("msr S0_3_C4_C6_3, xzr" : : : );461}462463static void sve_sigill(void)464{465/* RDVL x0, #0 */466asm volatile(".inst 0x04bf5000" : : : "x0");467}468469static void sve2_sigill(void)470{471/* SQABS Z0.b, P0/M, Z0.B */472asm volatile(".inst 0x4408A000" : : : "z0");473}474475static void sve2p1_sigill(void)476{477/* BFADD Z0.H, Z0.H, Z0.H */478asm volatile(".inst 0x65000000" : : : "z0");479}480481static void sve2p2_sigill(void)482{483/* NOT Z0.D, P0/Z, Z0.D */484asm volatile(".inst 0x4cea000" : : : "z0");485}486487static void sveaes_sigill(void)488{489/* AESD z0.b, z0.b, z0.b */490asm volatile(".inst 0x4522e400" : : : "z0");491}492493static void sveaes2_sigill(void)494{495/* AESD {Z0.B - Z1.B }, { Z0.B - Z1.B }, Z0.Q */496asm volatile(".inst 0x4522ec00" : : : "z0");497}498499static void sveb16b16_sigill(void)500{501/* BFADD Z0.H, Z0.H, Z0.H */502asm volatile(".inst 0x65000000" : : : );503}504505static void svebfscale_sigill(void)506{507/* BFSCALE Z0.H, P0/M, Z0.H, Z0.H */508asm volatile(".inst 0x65098000" : : : "z0");509}510511static void svef16mm_sigill(void)512{513/* FMMLA Z0.S, Z0.H, Z0.H */514asm volatile(".inst 0x6420e400");515}516517static void svepmull_sigill(void)518{519/* PMULLB Z0.Q, Z0.D, Z0.D */520asm volatile(".inst 0x45006800" : : : "z0");521}522523static void svebitperm_sigill(void)524{525/* BDEP Z0.B, Z0.B, Z0.B */526asm volatile(".inst 0x4500b400" : : : "z0");527}528529static void svesha3_sigill(void)530{531/* EOR3 Z0.D, Z0.D, Z0.D, Z0.D */532asm volatile(".inst 0x4203800" : : : "z0");533}534535static void sveeltperm_sigill(void)536{537/* COMPACT Z0.B, P0, Z0.B */538asm volatile(".inst 0x5218000" : : : "x0");539}540541static void svesm4_sigill(void)542{543/* SM4E Z0.S, Z0.S, Z0.S */544asm volatile(".inst 0x4523e000" : : : "z0");545}546547static void svei8mm_sigill(void)548{549/* USDOT Z0.S, Z0.B, Z0.B[0] */550asm volatile(".inst 0x44a01800" : : : "z0");551}552553static void svef32mm_sigill(void)554{555/* FMMLA Z0.S, Z0.S, Z0.S */556asm volatile(".inst 0x64a0e400" : : : "z0");557}558559static void svef64mm_sigill(void)560{561/* FMMLA Z0.D, Z0.D, Z0.D */562asm volatile(".inst 0x64e0e400" : : : "z0");563}564565static void svebf16_sigill(void)566{567/* BFCVT Z0.H, P0/M, Z0.S */568asm volatile(".inst 0x658aa000" : : : "z0");569}570571static void hbc_sigill(void)572{573/* BC.EQ +4 */574asm volatile("cmp xzr, xzr\n"575".inst 0x54000030" : : : "cc");576}577578static void uscat_sigbus(void)579{580/* unaligned atomic access */581asm volatile("ADD x1, sp, #2" : : : );582/* STADD W0, [X1] */583asm volatile(".inst 0xb820003f" : : : );584}585586static void lrcpc3_sigill(void)587{588int data[2] = { 1, 2 };589590register int *src asm ("x0") = data;591register int data0 asm ("w2") = 0;592register int data1 asm ("w3") = 0;593594/* LDIAPP w2, w3, [x0] */595asm volatile(".inst 0x99431802"596: "=r" (data0), "=r" (data1) : "r" (src) :);597}598599static void ignore_signal(int sig, siginfo_t *info, void *context)600{601ucontext_t *uc = context;602603uc->uc_mcontext.pc += 4;604}605606static void ls64_sigill(void)607{608struct sigaction ign, old;609char src[64] __aligned(64) = { 1 };610611/*612* LS64 requires target memory to be Device/Non-cacheable (if613* FEAT_LS64WB not supported) and the completer supports these614* instructions, otherwise we'll receive a SIGBUS. Since we are only615* testing the ABI here, so just ignore the SIGBUS and see if we can616* execute the instructions without receiving a SIGILL. Restore the617* handler of SIGBUS after this test.618*/619ign.sa_sigaction = ignore_signal;620ign.sa_flags = SA_SIGINFO | SA_RESTART;621sigemptyset(&ign.sa_mask);622sigaction(SIGBUS, &ign, &old);623624register void *xn asm ("x8") = src;625register u64 xt_1 asm ("x0");626627/* LD64B x0, [x8] */628asm volatile(".inst 0xf83fd100" : "=r" (xt_1) : "r" (xn)629: "x1", "x2", "x3", "x4", "x5", "x6", "x7");630631/* ST64B x0, [x8] */632asm volatile(".inst 0xf83f9100" : : "r" (xt_1), "r" (xn)633: "x1", "x2", "x3", "x4", "x5", "x6", "x7");634635sigaction(SIGBUS, &old, NULL);636}637638static const struct hwcap_data {639const char *name;640unsigned long at_hwcap;641unsigned long hwcap_bit;642const char *cpuinfo;643sig_fn sigill_fn;644bool sigill_reliable;645sig_fn sigbus_fn;646bool sigbus_reliable;647} hwcaps[] = {648{649.name = "AES",650.at_hwcap = AT_HWCAP,651.hwcap_bit = HWCAP_AES,652.cpuinfo = "aes",653.sigill_fn = aes_sigill,654},655{656.name = "CMPBR",657.at_hwcap = AT_HWCAP,658.hwcap_bit = HWCAP_CMPBR,659.cpuinfo = "cmpbr",660.sigill_fn = cmpbr_sigill,661},662{663.name = "CRC32",664.at_hwcap = AT_HWCAP,665.hwcap_bit = HWCAP_CRC32,666.cpuinfo = "crc32",667.sigill_fn = crc32_sigill,668},669{670.name = "CSSC",671.at_hwcap = AT_HWCAP2,672.hwcap_bit = HWCAP2_CSSC,673.cpuinfo = "cssc",674.sigill_fn = cssc_sigill,675},676{677.name = "F8CVT",678.at_hwcap = AT_HWCAP2,679.hwcap_bit = HWCAP2_F8CVT,680.cpuinfo = "f8cvt",681.sigill_fn = f8cvt_sigill,682},683{684.name = "F8DP4",685.at_hwcap = AT_HWCAP2,686.hwcap_bit = HWCAP2_F8DP4,687.cpuinfo = "f8dp4",688.sigill_fn = f8dp4_sigill,689},690{691.name = "F8DP2",692.at_hwcap = AT_HWCAP2,693.hwcap_bit = HWCAP2_F8DP2,694.cpuinfo = "f8dp2",695.sigill_fn = f8dp2_sigill,696},697{698.name = "F8E5M2",699.at_hwcap = AT_HWCAP2,700.hwcap_bit = HWCAP2_F8E5M2,701.cpuinfo = "f8e5m2",702},703{704.name = "F8E4M3",705.at_hwcap = AT_HWCAP2,706.hwcap_bit = HWCAP2_F8E4M3,707.cpuinfo = "f8e4m3",708},709{710.name = "F8FMA",711.at_hwcap = AT_HWCAP2,712.hwcap_bit = HWCAP2_F8FMA,713.cpuinfo = "f8fma",714.sigill_fn = f8fma_sigill,715},716{717.name = "F8MM8",718.at_hwcap = AT_HWCAP,719.hwcap_bit = HWCAP_F8MM8,720.cpuinfo = "f8mm8",721.sigill_fn = f8mm8_sigill,722},723{724.name = "F8MM4",725.at_hwcap = AT_HWCAP,726.hwcap_bit = HWCAP_F8MM4,727.cpuinfo = "f8mm4",728.sigill_fn = f8mm4_sigill,729},730{731.name = "FAMINMAX",732.at_hwcap = AT_HWCAP2,733.hwcap_bit = HWCAP2_FAMINMAX,734.cpuinfo = "faminmax",735.sigill_fn = faminmax_sigill,736},737{738.name = "FP",739.at_hwcap = AT_HWCAP,740.hwcap_bit = HWCAP_FP,741.cpuinfo = "fp",742.sigill_fn = fp_sigill,743},744{745.name = "FPMR",746.at_hwcap = AT_HWCAP2,747.hwcap_bit = HWCAP2_FPMR,748.cpuinfo = "fpmr",749.sigill_fn = fpmr_sigill,750.sigill_reliable = true,751},752{753.name = "FPRCVT",754.at_hwcap = AT_HWCAP,755.hwcap_bit = HWCAP_FPRCVT,756.cpuinfo = "fprcvt",757.sigill_fn = fprcvt_sigill,758},759{760.name = "GCS",761.at_hwcap = AT_HWCAP,762.hwcap_bit = HWCAP_GCS,763.cpuinfo = "gcs",764.sigill_fn = gcs_sigill,765.sigill_reliable = true,766},767{768.name = "JSCVT",769.at_hwcap = AT_HWCAP,770.hwcap_bit = HWCAP_JSCVT,771.cpuinfo = "jscvt",772.sigill_fn = jscvt_sigill,773},774{775.name = "LRCPC",776.at_hwcap = AT_HWCAP,777.hwcap_bit = HWCAP_LRCPC,778.cpuinfo = "lrcpc",779.sigill_fn = lrcpc_sigill,780},781{782.name = "LRCPC2",783.at_hwcap = AT_HWCAP,784.hwcap_bit = HWCAP_ILRCPC,785.cpuinfo = "ilrcpc",786.sigill_fn = ilrcpc_sigill,787},788{789.name = "LRCPC3",790.at_hwcap = AT_HWCAP2,791.hwcap_bit = HWCAP2_LRCPC3,792.cpuinfo = "lrcpc3",793.sigill_fn = lrcpc3_sigill,794},795{796.name = "LSE",797.at_hwcap = AT_HWCAP,798.hwcap_bit = HWCAP_ATOMICS,799.cpuinfo = "atomics",800.sigill_fn = atomics_sigill,801},802{803.name = "LSE2",804.at_hwcap = AT_HWCAP,805.hwcap_bit = HWCAP_USCAT,806.cpuinfo = "uscat",807.sigill_fn = atomics_sigill,808.sigbus_fn = uscat_sigbus,809.sigbus_reliable = true,810},811{812.name = "LSE128",813.at_hwcap = AT_HWCAP2,814.hwcap_bit = HWCAP2_LSE128,815.cpuinfo = "lse128",816.sigill_fn = lse128_sigill,817},818{819.name = "LSFE",820.at_hwcap = AT_HWCAP3,821.hwcap_bit = HWCAP3_LSFE,822.cpuinfo = "lsfe",823.sigill_fn = lsfe_sigill,824},825{826.name = "LUT",827.at_hwcap = AT_HWCAP2,828.hwcap_bit = HWCAP2_LUT,829.cpuinfo = "lut",830.sigill_fn = lut_sigill,831},832{833.name = "MOPS",834.at_hwcap = AT_HWCAP2,835.hwcap_bit = HWCAP2_MOPS,836.cpuinfo = "mops",837.sigill_fn = mops_sigill,838.sigill_reliable = true,839},840{841.name = "PMULL",842.at_hwcap = AT_HWCAP,843.hwcap_bit = HWCAP_PMULL,844.cpuinfo = "pmull",845.sigill_fn = pmull_sigill,846},847{848.name = "POE",849.at_hwcap = AT_HWCAP2,850.hwcap_bit = HWCAP2_POE,851.cpuinfo = "poe",852.sigill_fn = poe_sigill,853.sigill_reliable = true,854},855{856.name = "RNG",857.at_hwcap = AT_HWCAP2,858.hwcap_bit = HWCAP2_RNG,859.cpuinfo = "rng",860.sigill_fn = rng_sigill,861},862{863.name = "RPRFM",864.at_hwcap = AT_HWCAP2,865.hwcap_bit = HWCAP2_RPRFM,866.cpuinfo = "rprfm",867},868{869.name = "SHA1",870.at_hwcap = AT_HWCAP,871.hwcap_bit = HWCAP_SHA1,872.cpuinfo = "sha1",873.sigill_fn = sha1_sigill,874},875{876.name = "SHA2",877.at_hwcap = AT_HWCAP,878.hwcap_bit = HWCAP_SHA2,879.cpuinfo = "sha2",880.sigill_fn = sha2_sigill,881},882{883.name = "SHA512",884.at_hwcap = AT_HWCAP,885.hwcap_bit = HWCAP_SHA512,886.cpuinfo = "sha512",887.sigill_fn = sha512_sigill,888},889{890.name = "SME",891.at_hwcap = AT_HWCAP2,892.hwcap_bit = HWCAP2_SME,893.cpuinfo = "sme",894.sigill_fn = sme_sigill,895.sigill_reliable = true,896},897{898.name = "SME2",899.at_hwcap = AT_HWCAP2,900.hwcap_bit = HWCAP2_SME2,901.cpuinfo = "sme2",902.sigill_fn = sme2_sigill,903.sigill_reliable = true,904},905{906.name = "SME 2.1",907.at_hwcap = AT_HWCAP2,908.hwcap_bit = HWCAP2_SME2P1,909.cpuinfo = "sme2p1",910.sigill_fn = sme2p1_sigill,911},912{913.name = "SME 2.2",914.at_hwcap = AT_HWCAP,915.hwcap_bit = HWCAP_SME2P2,916.cpuinfo = "sme2p2",917.sigill_fn = sme2p2_sigill,918},919{920.name = "SME AES",921.at_hwcap = AT_HWCAP,922.hwcap_bit = HWCAP_SME_AES,923.cpuinfo = "smeaes",924.sigill_fn = sme_aes_sigill,925},926{927.name = "SME I16I32",928.at_hwcap = AT_HWCAP2,929.hwcap_bit = HWCAP2_SME_I16I32,930.cpuinfo = "smei16i32",931.sigill_fn = smei16i32_sigill,932},933{934.name = "SME BI32I32",935.at_hwcap = AT_HWCAP2,936.hwcap_bit = HWCAP2_SME_BI32I32,937.cpuinfo = "smebi32i32",938.sigill_fn = smebi32i32_sigill,939},940{941.name = "SME B16B16",942.at_hwcap = AT_HWCAP2,943.hwcap_bit = HWCAP2_SME_B16B16,944.cpuinfo = "smeb16b16",945.sigill_fn = smeb16b16_sigill,946},947{948.name = "SME F16F16",949.at_hwcap = AT_HWCAP2,950.hwcap_bit = HWCAP2_SME_F16F16,951.cpuinfo = "smef16f16",952.sigill_fn = smef16f16_sigill,953},954{955.name = "SME F8F16",956.at_hwcap = AT_HWCAP2,957.hwcap_bit = HWCAP2_SME_F8F16,958.cpuinfo = "smef8f16",959.sigill_fn = smef8f16_sigill,960},961{962.name = "SME F8F32",963.at_hwcap = AT_HWCAP2,964.hwcap_bit = HWCAP2_SME_F8F32,965.cpuinfo = "smef8f32",966.sigill_fn = smef8f32_sigill,967},968{969.name = "SME LUTV2",970.at_hwcap = AT_HWCAP2,971.hwcap_bit = HWCAP2_SME_LUTV2,972.cpuinfo = "smelutv2",973.sigill_fn = smelutv2_sigill,974},975{976.name = "SME SBITPERM",977.at_hwcap = AT_HWCAP,978.hwcap_bit = HWCAP_SME_SBITPERM,979.cpuinfo = "smesbitperm",980.sigill_fn = sme_sbitperm_sigill,981},982{983.name = "SME SF8FMA",984.at_hwcap = AT_HWCAP2,985.hwcap_bit = HWCAP2_SME_SF8FMA,986.cpuinfo = "smesf8fma",987.sigill_fn = smesf8fma_sigill,988},989{990.name = "SME SF8DP2",991.at_hwcap = AT_HWCAP2,992.hwcap_bit = HWCAP2_SME_SF8DP2,993.cpuinfo = "smesf8dp2",994.sigill_fn = smesf8dp2_sigill,995},996{997.name = "SME SF8DP4",998.at_hwcap = AT_HWCAP2,999.hwcap_bit = HWCAP2_SME_SF8DP4,1000.cpuinfo = "smesf8dp4",1001.sigill_fn = smesf8dp4_sigill,1002},1003{1004.name = "SME SFEXPA",1005.at_hwcap = AT_HWCAP,1006.hwcap_bit = HWCAP_SME_SFEXPA,1007.cpuinfo = "smesfexpa",1008.sigill_fn = smesfexpa_sigill,1009},1010{1011.name = "SME SMOP4",1012.at_hwcap = AT_HWCAP,1013.hwcap_bit = HWCAP_SME_SMOP4,1014.cpuinfo = "smesmop4",1015.sigill_fn = smesmop4_sigill,1016},1017{1018.name = "SME STMOP",1019.at_hwcap = AT_HWCAP,1020.hwcap_bit = HWCAP_SME_STMOP,1021.cpuinfo = "smestmop",1022.sigill_fn = smestmop_sigill,1023},1024{1025.name = "SVE",1026.at_hwcap = AT_HWCAP,1027.hwcap_bit = HWCAP_SVE,1028.cpuinfo = "sve",1029.sigill_fn = sve_sigill,1030.sigill_reliable = true,1031},1032{1033.name = "SVE 2",1034.at_hwcap = AT_HWCAP2,1035.hwcap_bit = HWCAP2_SVE2,1036.cpuinfo = "sve2",1037.sigill_fn = sve2_sigill,1038},1039{1040.name = "SVE 2.1",1041.at_hwcap = AT_HWCAP2,1042.hwcap_bit = HWCAP2_SVE2P1,1043.cpuinfo = "sve2p1",1044.sigill_fn = sve2p1_sigill,1045},1046{1047.name = "SVE 2.2",1048.at_hwcap = AT_HWCAP,1049.hwcap_bit = HWCAP_SVE2P2,1050.cpuinfo = "sve2p2",1051.sigill_fn = sve2p2_sigill,1052},1053{1054.name = "SVE AES",1055.at_hwcap = AT_HWCAP2,1056.hwcap_bit = HWCAP2_SVEAES,1057.cpuinfo = "sveaes",1058.sigill_fn = sveaes_sigill,1059},1060{1061.name = "SVE AES2",1062.at_hwcap = AT_HWCAP,1063.hwcap_bit = HWCAP_SVE_AES2,1064.cpuinfo = "sveaes2",1065.sigill_fn = sveaes2_sigill,1066},1067{1068.name = "SVE BFSCALE",1069.at_hwcap = AT_HWCAP,1070.hwcap_bit = HWCAP_SVE_BFSCALE,1071.cpuinfo = "svebfscale",1072.sigill_fn = svebfscale_sigill,1073},1074{1075.name = "SVE ELTPERM",1076.at_hwcap = AT_HWCAP,1077.hwcap_bit = HWCAP_SVE_ELTPERM,1078.cpuinfo = "sveeltperm",1079.sigill_fn = sveeltperm_sigill,1080},1081{1082.name = "SVE F16MM",1083.at_hwcap = AT_HWCAP,1084.hwcap_bit = HWCAP_SVE_F16MM,1085.cpuinfo = "svef16mm",1086.sigill_fn = svef16mm_sigill,1087},1088{1089.name = "SVE2 B16B16",1090.at_hwcap = AT_HWCAP2,1091.hwcap_bit = HWCAP2_SVE_B16B16,1092.cpuinfo = "sveb16b16",1093.sigill_fn = sveb16b16_sigill,1094},1095{1096.name = "SVE2 PMULL",1097.at_hwcap = AT_HWCAP2,1098.hwcap_bit = HWCAP2_SVEPMULL,1099.cpuinfo = "svepmull",1100.sigill_fn = svepmull_sigill,1101},1102{1103.name = "SVE2 BITPERM",1104.at_hwcap = AT_HWCAP2,1105.hwcap_bit = HWCAP2_SVEBITPERM,1106.cpuinfo = "svebitperm",1107.sigill_fn = svebitperm_sigill,1108},1109{1110.name = "SVE2 SHA3",1111.at_hwcap = AT_HWCAP2,1112.hwcap_bit = HWCAP2_SVESHA3,1113.cpuinfo = "svesha3",1114.sigill_fn = svesha3_sigill,1115},1116{1117.name = "SVE2 SM4",1118.at_hwcap = AT_HWCAP2,1119.hwcap_bit = HWCAP2_SVESM4,1120.cpuinfo = "svesm4",1121.sigill_fn = svesm4_sigill,1122},1123{1124.name = "SVE2 I8MM",1125.at_hwcap = AT_HWCAP2,1126.hwcap_bit = HWCAP2_SVEI8MM,1127.cpuinfo = "svei8mm",1128.sigill_fn = svei8mm_sigill,1129},1130{1131.name = "SVE2 F32MM",1132.at_hwcap = AT_HWCAP2,1133.hwcap_bit = HWCAP2_SVEF32MM,1134.cpuinfo = "svef32mm",1135.sigill_fn = svef32mm_sigill,1136},1137{1138.name = "SVE2 F64MM",1139.at_hwcap = AT_HWCAP2,1140.hwcap_bit = HWCAP2_SVEF64MM,1141.cpuinfo = "svef64mm",1142.sigill_fn = svef64mm_sigill,1143},1144{1145.name = "SVE2 BF16",1146.at_hwcap = AT_HWCAP2,1147.hwcap_bit = HWCAP2_SVEBF16,1148.cpuinfo = "svebf16",1149.sigill_fn = svebf16_sigill,1150},1151{1152.name = "SVE2 EBF16",1153.at_hwcap = AT_HWCAP2,1154.hwcap_bit = HWCAP2_SVE_EBF16,1155.cpuinfo = "sveebf16",1156},1157{1158.name = "HBC",1159.at_hwcap = AT_HWCAP2,1160.hwcap_bit = HWCAP2_HBC,1161.cpuinfo = "hbc",1162.sigill_fn = hbc_sigill,1163.sigill_reliable = true,1164},1165{1166.name = "MTE_FAR",1167.at_hwcap = AT_HWCAP3,1168.hwcap_bit = HWCAP3_MTE_FAR,1169.cpuinfo = "mtefar",1170},1171{1172.name = "MTE_STOREONLY",1173.at_hwcap = AT_HWCAP3,1174.hwcap_bit = HWCAP3_MTE_STORE_ONLY,1175.cpuinfo = "mtestoreonly",1176},1177{1178.name = "LS64",1179.at_hwcap = AT_HWCAP3,1180.hwcap_bit = HWCAP3_LS64,1181.cpuinfo = "ls64",1182.sigill_fn = ls64_sigill,1183.sigill_reliable = true,1184},1185};11861187typedef void (*sighandler_fn)(int, siginfo_t *, void *);11881189#define DEF_SIGHANDLER_FUNC(SIG, NUM) \1190static bool seen_##SIG; \1191static void handle_##SIG(int sig, siginfo_t *info, void *context) \1192{ \1193ucontext_t *uc = context; \1194\1195seen_##SIG = true; \1196/* Skip over the offending instruction */ \1197uc->uc_mcontext.pc += 4; \1198}11991200DEF_SIGHANDLER_FUNC(sigill, SIGILL);1201DEF_SIGHANDLER_FUNC(sigbus, SIGBUS);12021203bool cpuinfo_present(const char *name)1204{1205FILE *f;1206char buf[2048], name_space[30], name_newline[30];1207char *s;12081209/*1210* The feature should appear with a leading space and either a1211* trailing space or a newline.1212*/1213snprintf(name_space, sizeof(name_space), " %s ", name);1214snprintf(name_newline, sizeof(name_newline), " %s\n", name);12151216f = fopen("/proc/cpuinfo", "r");1217if (!f) {1218ksft_print_msg("Failed to open /proc/cpuinfo\n");1219return false;1220}12211222while (fgets(buf, sizeof(buf), f)) {1223/* Features: line? */1224if (strncmp(buf, "Features\t:", strlen("Features\t:")) != 0)1225continue;12261227/* All CPUs should be symmetric, don't read any more */1228fclose(f);12291230s = strstr(buf, name_space);1231if (s)1232return true;1233s = strstr(buf, name_newline);1234if (s)1235return true;12361237return false;1238}12391240ksft_print_msg("Failed to find Features in /proc/cpuinfo\n");1241fclose(f);1242return false;1243}12441245static int install_sigaction(int signum, sighandler_fn handler)1246{1247int ret;1248struct sigaction sa;12491250memset(&sa, 0, sizeof(sa));1251sa.sa_sigaction = handler;1252sa.sa_flags = SA_RESTART | SA_SIGINFO;1253sigemptyset(&sa.sa_mask);1254ret = sigaction(signum, &sa, NULL);1255if (ret < 0)1256ksft_exit_fail_msg("Failed to install SIGNAL handler: %s (%d)\n",1257strerror(errno), errno);12581259return ret;1260}12611262static void uninstall_sigaction(int signum)1263{1264if (sigaction(signum, NULL, NULL) < 0)1265ksft_exit_fail_msg("Failed to uninstall SIGNAL handler: %s (%d)\n",1266strerror(errno), errno);1267}12681269#define DEF_INST_RAISE_SIG(SIG, NUM) \1270static bool inst_raise_##SIG(const struct hwcap_data *hwcap, \1271bool have_hwcap) \1272{ \1273if (!hwcap->SIG##_fn) { \1274ksft_test_result_skip(#SIG"_%s\n", hwcap->name); \1275/* assume that it would raise exception in default */ \1276return true; \1277} \1278\1279install_sigaction(NUM, handle_##SIG); \1280\1281seen_##SIG = false; \1282hwcap->SIG##_fn(); \1283\1284if (have_hwcap) { \1285/* Should be able to use the extension */ \1286ksft_test_result(!seen_##SIG, \1287#SIG"_%s\n", hwcap->name); \1288} else if (hwcap->SIG##_reliable) { \1289/* Guaranteed a SIGNAL */ \1290ksft_test_result(seen_##SIG, \1291#SIG"_%s\n", hwcap->name); \1292} else { \1293/* Missing SIGNAL might be fine */ \1294ksft_print_msg(#SIG"_%sreported for %s\n", \1295seen_##SIG ? "" : "not ", \1296hwcap->name); \1297ksft_test_result_skip(#SIG"_%s\n", \1298hwcap->name); \1299} \1300\1301uninstall_sigaction(NUM); \1302return seen_##SIG; \1303}13041305DEF_INST_RAISE_SIG(sigill, SIGILL);1306DEF_INST_RAISE_SIG(sigbus, SIGBUS);13071308int main(void)1309{1310int i;1311const struct hwcap_data *hwcap;1312bool have_cpuinfo, have_hwcap, raise_sigill;13131314ksft_print_header();1315ksft_set_plan(ARRAY_SIZE(hwcaps) * TESTS_PER_HWCAP);13161317for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {1318hwcap = &hwcaps[i];13191320have_hwcap = getauxval(hwcap->at_hwcap) & hwcap->hwcap_bit;1321have_cpuinfo = cpuinfo_present(hwcap->cpuinfo);13221323if (have_hwcap)1324ksft_print_msg("%s present\n", hwcap->name);13251326ksft_test_result(have_hwcap == have_cpuinfo,1327"cpuinfo_match_%s\n", hwcap->name);13281329/*1330* Testing for SIGBUS only makes sense after make sure1331* that the instruction does not cause a SIGILL signal.1332*/1333raise_sigill = inst_raise_sigill(hwcap, have_hwcap);1334if (!raise_sigill)1335inst_raise_sigbus(hwcap, have_hwcap);1336else1337ksft_test_result_skip("sigbus_%s\n", hwcap->name);1338}13391340ksft_print_cnts();13411342return 0;1343}134413451346