Path: blob/master/tools/testing/selftests/arm64/abi/hwcap.c
29270 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 <linux/auxvec.h>2021#include "../../kselftest.h"2223#define TESTS_PER_HWCAP 32425#ifndef AT_HWCAP326#define AT_HWCAP3 2927#endif2829/*30* Function expected to generate exception when the feature is not31* supported and return when it is supported. If the specific exception32* is generated then the handler must be able to skip over the33* instruction safely.34*35* Note that it is expected that for many architecture extensions36* there are no specific traps due to no architecture state being37* added so we may not fault if running on a kernel which doesn't know38* to add the hwcap.39*/40typedef void (*sig_fn)(void);4142static void aes_sigill(void)43{44/* AESE V0.16B, V0.16B */45asm volatile(".inst 0x4e284800" : : : );46}4748static void atomics_sigill(void)49{50/* STADD W0, [SP] */51asm volatile(".inst 0xb82003ff" : : : );52}5354static void cmpbr_sigill(void)55{56/* Not implemented, too complicated and unreliable anyway */57}5859static void crc32_sigill(void)60{61/* CRC32W W0, W0, W1 */62asm volatile(".inst 0x1ac14800" : : : );63}6465static void cssc_sigill(void)66{67/* CNT x0, x0 */68asm volatile(".inst 0xdac01c00" : : : "x0");69}7071static void f8cvt_sigill(void)72{73/* FSCALE V0.4H, V0.4H, V0.4H */74asm volatile(".inst 0x2ec03c00");75}7677static void f8dp2_sigill(void)78{79/* FDOT V0.4H, V0.4H, V0.5H */80asm volatile(".inst 0xe40fc00");81}8283static void f8dp4_sigill(void)84{85/* FDOT V0.2S, V0.2S, V0.2S */86asm volatile(".inst 0xe00fc00");87}8889static void f8fma_sigill(void)90{91/* FMLALB V0.8H, V0.16B, V0.16B */92asm volatile(".inst 0xec0fc00");93}9495static void f8mm4_sigill(void)96{97/* FMMLA V0.4SH, V0.16B, V0.16B */98asm volatile(".inst 0x6e00ec00");99}100101static void f8mm8_sigill(void)102{103/* FMMLA V0.4S, V0.16B, V0.16B */104asm volatile(".inst 0x6e80ec00");105}106107static void faminmax_sigill(void)108{109/* FAMIN V0.4H, V0.4H, V0.4H */110asm volatile(".inst 0x2ec01c00");111}112113static void fp_sigill(void)114{115asm volatile("fmov s0, #1");116}117118static void fpmr_sigill(void)119{120asm volatile("mrs x0, S3_3_C4_C4_2" : : : "x0");121}122123static void fprcvt_sigill(void)124{125/* FCVTAS S0, H0 */126asm volatile(".inst 0x1efa0000");127}128129static void gcs_sigill(void)130{131unsigned long *gcspr;132133asm volatile(134"mrs %0, S3_3_C2_C5_1"135: "=r" (gcspr)136:137: "cc");138}139140static void ilrcpc_sigill(void)141{142/* LDAPUR W0, [SP, #8] */143asm volatile(".inst 0x994083e0" : : : );144}145146static void jscvt_sigill(void)147{148/* FJCVTZS W0, D0 */149asm volatile(".inst 0x1e7e0000" : : : );150}151152static void lrcpc_sigill(void)153{154/* LDAPR W0, [SP, #0] */155asm volatile(".inst 0xb8bfc3e0" : : : );156}157158static void lse128_sigill(void)159{160u64 __attribute__ ((aligned (16))) mem[2] = { 10, 20 };161register u64 *memp asm ("x0") = mem;162register u64 val0 asm ("x1") = 5;163register u64 val1 asm ("x2") = 4;164165/* SWPP X1, X2, [X0] */166asm volatile(".inst 0x19228001"167: "+r" (memp), "+r" (val0), "+r" (val1)168:169: "cc", "memory");170}171172static void lsfe_sigill(void)173{174float __attribute__ ((aligned (16))) mem;175register float *memp asm ("x0") = &mem;176177/* STFADD H0, [X0] */178asm volatile(".inst 0x7c20801f"179: "+r" (memp)180:181: "memory");182}183184static void lut_sigill(void)185{186/* LUTI2 V0.16B, { V0.16B }, V[0] */187asm volatile(".inst 0x4e801000");188}189190static void mops_sigill(void)191{192char dst[1], src[1];193register char *dstp asm ("x0") = dst;194register char *srcp asm ("x1") = src;195register long size asm ("x2") = 1;196197/* CPYP [x0]!, [x1]!, x2! */198asm volatile(".inst 0x1d010440"199: "+r" (dstp), "+r" (srcp), "+r" (size)200:201: "cc", "memory");202}203204static void pmull_sigill(void)205{206/* PMULL V0.1Q, V0.1D, V0.1D */207asm volatile(".inst 0x0ee0e000" : : : );208}209210static void poe_sigill(void)211{212/* mrs x0, POR_EL0 */213asm volatile("mrs x0, S3_3_C10_C2_4" : : : "x0");214}215216static void rng_sigill(void)217{218asm volatile("mrs x0, S3_3_C2_C4_0" : : : "x0");219}220221static void sha1_sigill(void)222{223/* SHA1H S0, S0 */224asm volatile(".inst 0x5e280800" : : : );225}226227static void sha2_sigill(void)228{229/* SHA256H Q0, Q0, V0.4S */230asm volatile(".inst 0x5e004000" : : : );231}232233static void sha512_sigill(void)234{235/* SHA512H Q0, Q0, V0.2D */236asm volatile(".inst 0xce608000" : : : );237}238239static void sme_sigill(void)240{241/* RDSVL x0, #0 */242asm volatile(".inst 0x04bf5800" : : : "x0");243}244245static void sme2_sigill(void)246{247/* SMSTART ZA */248asm volatile("msr S0_3_C4_C5_3, xzr" : : : );249250/* ZERO ZT0 */251asm volatile(".inst 0xc0480001" : : : );252253/* SMSTOP */254asm volatile("msr S0_3_C4_C6_3, xzr" : : : );255}256257static void sme2p1_sigill(void)258{259/* SMSTART SM */260asm volatile("msr S0_3_C4_C3_3, xzr" : : : );261262/* BFCLAMP { Z0.H - Z1.H }, Z0.H, Z0.H */263asm volatile(".inst 0xc120C000" : : : );264265/* SMSTOP */266asm volatile("msr S0_3_C4_C6_3, xzr" : : : );267}268269static void sme2p2_sigill(void)270{271/* SMSTART SM */272asm volatile("msr S0_3_C4_C3_3, xzr" : : : );273274/* UXTB Z0.D, P0/Z, Z0.D */275asm volatile(".inst 0x4c1a000" : : : );276277/* SMSTOP */278asm volatile("msr S0_3_C4_C6_3, xzr" : : : );279}280281static void sme_aes_sigill(void)282{283/* SMSTART SM */284asm volatile("msr S0_3_C4_C3_3, xzr" : : : );285286/* AESD z0.b, z0.b, z0.b */287asm volatile(".inst 0x4522e400" : : : "z0");288289/* SMSTOP */290asm volatile("msr S0_3_C4_C6_3, xzr" : : : );291}292293static void sme_sbitperm_sigill(void)294{295/* SMSTART SM */296asm volatile("msr S0_3_C4_C3_3, xzr" : : : );297298/* BDEP Z0.B, Z0.B, Z0.B */299asm volatile(".inst 0x4500b400" : : : "z0");300301/* SMSTOP */302asm volatile("msr S0_3_C4_C6_3, xzr" : : : );303}304305static void smei16i32_sigill(void)306{307/* SMSTART */308asm volatile("msr S0_3_C4_C7_3, xzr" : : : );309310/* SMOPA ZA0.S, P0/M, P0/M, Z0.B, Z0.B */311asm volatile(".inst 0xa0800000" : : : );312313/* SMSTOP */314asm volatile("msr S0_3_C4_C6_3, xzr" : : : );315}316317static void smebi32i32_sigill(void)318{319/* SMSTART */320asm volatile("msr S0_3_C4_C7_3, xzr" : : : );321322/* BMOPA ZA0.S, P0/M, P0/M, Z0.B, Z0.B */323asm volatile(".inst 0x80800008" : : : );324325/* SMSTOP */326asm volatile("msr S0_3_C4_C6_3, xzr" : : : );327}328329static void smeb16b16_sigill(void)330{331/* SMSTART */332asm volatile("msr S0_3_C4_C7_3, xzr" : : : );333334/* BFADD ZA.H[W0, 0], {Z0.H-Z1.H} */335asm volatile(".inst 0xC1E41C00" : : : );336337/* SMSTOP */338asm volatile("msr S0_3_C4_C6_3, xzr" : : : );339}340341static void smef16f16_sigill(void)342{343/* SMSTART */344asm volatile("msr S0_3_C4_C7_3, xzr" : : : );345346/* FADD ZA.H[W0, 0], { Z0.H-Z1.H } */347asm volatile(".inst 0xc1a41C00" : : : );348349/* SMSTOP */350asm volatile("msr S0_3_C4_C6_3, xzr" : : : );351}352353static void smef8f16_sigill(void)354{355/* SMSTART */356asm volatile("msr S0_3_C4_C7_3, xzr" : : : );357358/* FDOT ZA.H[W0, 0], Z0.B-Z1.B, Z0.B-Z1.B */359asm volatile(".inst 0xc1a01020" : : : );360361/* SMSTOP */362asm volatile("msr S0_3_C4_C6_3, xzr" : : : );363}364365static void smef8f32_sigill(void)366{367/* SMSTART */368asm volatile("msr S0_3_C4_C7_3, xzr" : : : );369370/* FDOT ZA.S[W0, 0], { Z0.B-Z1.B }, Z0.B[0] */371asm volatile(".inst 0xc1500038" : : : );372373/* SMSTOP */374asm volatile("msr S0_3_C4_C6_3, xzr" : : : );375}376377static void smelutv2_sigill(void)378{379/* SMSTART */380asm volatile("msr S0_3_C4_C7_3, xzr" : : : );381382/* LUTI4 { Z0.B-Z3.B }, ZT0, { Z0-Z1 } */383asm volatile(".inst 0xc08b0000" : : : );384385/* SMSTOP */386asm volatile("msr S0_3_C4_C6_3, xzr" : : : );387}388389static void smesf8dp2_sigill(void)390{391/* SMSTART */392asm volatile("msr S0_3_C4_C7_3, xzr" : : : );393394/* FDOT Z0.H, Z0.B, Z0.B[0] */395asm volatile(".inst 0x64204400" : : : );396397/* SMSTOP */398asm volatile("msr S0_3_C4_C6_3, xzr" : : : );399}400401static void smesf8dp4_sigill(void)402{403/* SMSTART */404asm volatile("msr S0_3_C4_C7_3, xzr" : : : );405406/* FDOT Z0.S, Z0.B, Z0.B[0] */407asm volatile(".inst 0xc1a41C00" : : : );408409/* SMSTOP */410asm volatile("msr S0_3_C4_C6_3, xzr" : : : );411}412413static void smesf8fma_sigill(void)414{415/* SMSTART */416asm volatile("msr S0_3_C4_C7_3, xzr" : : : );417418/* FMLALB Z0.8H, Z0.B, Z0.B */419asm volatile(".inst 0x64205000");420421/* SMSTOP */422asm volatile("msr S0_3_C4_C6_3, xzr" : : : );423}424425static void smesfexpa_sigill(void)426{427/* SMSTART */428asm volatile("msr S0_3_C4_C7_3, xzr" : : : );429430/* FEXPA Z0.D, Z0.D */431asm volatile(".inst 0x04e0b800");432433/* SMSTOP */434asm volatile("msr S0_3_C4_C6_3, xzr" : : : );435}436437static void smesmop4_sigill(void)438{439/* SMSTART */440asm volatile("msr S0_3_C4_C7_3, xzr" : : : );441442/* SMOP4A ZA0.S, Z0.B, { Z0.B - Z1.B } */443asm volatile(".inst 0x80108000");444445/* SMSTOP */446asm volatile("msr S0_3_C4_C6_3, xzr" : : : );447}448449static void smestmop_sigill(void)450{451/* SMSTART */452asm volatile("msr S0_3_C4_C7_3, xzr" : : : );453454/* STMOPA ZA0.S, { Z0.H - Z1.H }, Z0.H, Z20[0] */455asm volatile(".inst 0x80408008");456457/* SMSTOP */458asm volatile("msr S0_3_C4_C6_3, xzr" : : : );459}460461static void sve_sigill(void)462{463/* RDVL x0, #0 */464asm volatile(".inst 0x04bf5000" : : : "x0");465}466467static void sve2_sigill(void)468{469/* SQABS Z0.b, P0/M, Z0.B */470asm volatile(".inst 0x4408A000" : : : "z0");471}472473static void sve2p1_sigill(void)474{475/* BFADD Z0.H, Z0.H, Z0.H */476asm volatile(".inst 0x65000000" : : : "z0");477}478479static void sve2p2_sigill(void)480{481/* NOT Z0.D, P0/Z, Z0.D */482asm volatile(".inst 0x4cea000" : : : "z0");483}484485static void sveaes_sigill(void)486{487/* AESD z0.b, z0.b, z0.b */488asm volatile(".inst 0x4522e400" : : : "z0");489}490491static void sveaes2_sigill(void)492{493/* AESD {Z0.B - Z1.B }, { Z0.B - Z1.B }, Z0.Q */494asm volatile(".inst 0x4522ec00" : : : "z0");495}496497static void sveb16b16_sigill(void)498{499/* BFADD Z0.H, Z0.H, Z0.H */500asm volatile(".inst 0x65000000" : : : );501}502503static void svebfscale_sigill(void)504{505/* BFSCALE Z0.H, P0/M, Z0.H, Z0.H */506asm volatile(".inst 0x65098000" : : : "z0");507}508509static void svef16mm_sigill(void)510{511/* FMMLA Z0.S, Z0.H, Z0.H */512asm volatile(".inst 0x6420e400");513}514515static void svepmull_sigill(void)516{517/* PMULLB Z0.Q, Z0.D, Z0.D */518asm volatile(".inst 0x45006800" : : : "z0");519}520521static void svebitperm_sigill(void)522{523/* BDEP Z0.B, Z0.B, Z0.B */524asm volatile(".inst 0x4500b400" : : : "z0");525}526527static void svesha3_sigill(void)528{529/* EOR3 Z0.D, Z0.D, Z0.D, Z0.D */530asm volatile(".inst 0x4203800" : : : "z0");531}532533static void sveeltperm_sigill(void)534{535/* COMPACT Z0.B, P0, Z0.B */536asm volatile(".inst 0x5218000" : : : "x0");537}538539static void svesm4_sigill(void)540{541/* SM4E Z0.S, Z0.S, Z0.S */542asm volatile(".inst 0x4523e000" : : : "z0");543}544545static void svei8mm_sigill(void)546{547/* USDOT Z0.S, Z0.B, Z0.B[0] */548asm volatile(".inst 0x44a01800" : : : "z0");549}550551static void svef32mm_sigill(void)552{553/* FMMLA Z0.S, Z0.S, Z0.S */554asm volatile(".inst 0x64a0e400" : : : "z0");555}556557static void svef64mm_sigill(void)558{559/* FMMLA Z0.D, Z0.D, Z0.D */560asm volatile(".inst 0x64e0e400" : : : "z0");561}562563static void svebf16_sigill(void)564{565/* BFCVT Z0.H, P0/M, Z0.S */566asm volatile(".inst 0x658aa000" : : : "z0");567}568569static void hbc_sigill(void)570{571/* BC.EQ +4 */572asm volatile("cmp xzr, xzr\n"573".inst 0x54000030" : : : "cc");574}575576static void uscat_sigbus(void)577{578/* unaligned atomic access */579asm volatile("ADD x1, sp, #2" : : : );580/* STADD W0, [X1] */581asm volatile(".inst 0xb820003f" : : : );582}583584static void lrcpc3_sigill(void)585{586int data[2] = { 1, 2 };587588register int *src asm ("x0") = data;589register int data0 asm ("w2") = 0;590register int data1 asm ("w3") = 0;591592/* LDIAPP w2, w3, [x0] */593asm volatile(".inst 0x99431802"594: "=r" (data0), "=r" (data1) : "r" (src) :);595}596597static const struct hwcap_data {598const char *name;599unsigned long at_hwcap;600unsigned long hwcap_bit;601const char *cpuinfo;602sig_fn sigill_fn;603bool sigill_reliable;604sig_fn sigbus_fn;605bool sigbus_reliable;606} hwcaps[] = {607{608.name = "AES",609.at_hwcap = AT_HWCAP,610.hwcap_bit = HWCAP_AES,611.cpuinfo = "aes",612.sigill_fn = aes_sigill,613},614{615.name = "CMPBR",616.at_hwcap = AT_HWCAP,617.hwcap_bit = HWCAP_CMPBR,618.cpuinfo = "cmpbr",619.sigill_fn = cmpbr_sigill,620},621{622.name = "CRC32",623.at_hwcap = AT_HWCAP,624.hwcap_bit = HWCAP_CRC32,625.cpuinfo = "crc32",626.sigill_fn = crc32_sigill,627},628{629.name = "CSSC",630.at_hwcap = AT_HWCAP2,631.hwcap_bit = HWCAP2_CSSC,632.cpuinfo = "cssc",633.sigill_fn = cssc_sigill,634},635{636.name = "F8CVT",637.at_hwcap = AT_HWCAP2,638.hwcap_bit = HWCAP2_F8CVT,639.cpuinfo = "f8cvt",640.sigill_fn = f8cvt_sigill,641},642{643.name = "F8DP4",644.at_hwcap = AT_HWCAP2,645.hwcap_bit = HWCAP2_F8DP4,646.cpuinfo = "f8dp4",647.sigill_fn = f8dp4_sigill,648},649{650.name = "F8DP2",651.at_hwcap = AT_HWCAP2,652.hwcap_bit = HWCAP2_F8DP2,653.cpuinfo = "f8dp2",654.sigill_fn = f8dp2_sigill,655},656{657.name = "F8E5M2",658.at_hwcap = AT_HWCAP2,659.hwcap_bit = HWCAP2_F8E5M2,660.cpuinfo = "f8e5m2",661},662{663.name = "F8E4M3",664.at_hwcap = AT_HWCAP2,665.hwcap_bit = HWCAP2_F8E4M3,666.cpuinfo = "f8e4m3",667},668{669.name = "F8FMA",670.at_hwcap = AT_HWCAP2,671.hwcap_bit = HWCAP2_F8FMA,672.cpuinfo = "f8fma",673.sigill_fn = f8fma_sigill,674},675{676.name = "F8MM8",677.at_hwcap = AT_HWCAP,678.hwcap_bit = HWCAP_F8MM8,679.cpuinfo = "f8mm8",680.sigill_fn = f8mm8_sigill,681},682{683.name = "F8MM4",684.at_hwcap = AT_HWCAP,685.hwcap_bit = HWCAP_F8MM4,686.cpuinfo = "f8mm4",687.sigill_fn = f8mm4_sigill,688},689{690.name = "FAMINMAX",691.at_hwcap = AT_HWCAP2,692.hwcap_bit = HWCAP2_FAMINMAX,693.cpuinfo = "faminmax",694.sigill_fn = faminmax_sigill,695},696{697.name = "FP",698.at_hwcap = AT_HWCAP,699.hwcap_bit = HWCAP_FP,700.cpuinfo = "fp",701.sigill_fn = fp_sigill,702},703{704.name = "FPMR",705.at_hwcap = AT_HWCAP2,706.hwcap_bit = HWCAP2_FPMR,707.cpuinfo = "fpmr",708.sigill_fn = fpmr_sigill,709.sigill_reliable = true,710},711{712.name = "FPRCVT",713.at_hwcap = AT_HWCAP,714.hwcap_bit = HWCAP_FPRCVT,715.cpuinfo = "fprcvt",716.sigill_fn = fprcvt_sigill,717},718{719.name = "GCS",720.at_hwcap = AT_HWCAP,721.hwcap_bit = HWCAP_GCS,722.cpuinfo = "gcs",723.sigill_fn = gcs_sigill,724.sigill_reliable = true,725},726{727.name = "JSCVT",728.at_hwcap = AT_HWCAP,729.hwcap_bit = HWCAP_JSCVT,730.cpuinfo = "jscvt",731.sigill_fn = jscvt_sigill,732},733{734.name = "LRCPC",735.at_hwcap = AT_HWCAP,736.hwcap_bit = HWCAP_LRCPC,737.cpuinfo = "lrcpc",738.sigill_fn = lrcpc_sigill,739},740{741.name = "LRCPC2",742.at_hwcap = AT_HWCAP,743.hwcap_bit = HWCAP_ILRCPC,744.cpuinfo = "ilrcpc",745.sigill_fn = ilrcpc_sigill,746},747{748.name = "LRCPC3",749.at_hwcap = AT_HWCAP2,750.hwcap_bit = HWCAP2_LRCPC3,751.cpuinfo = "lrcpc3",752.sigill_fn = lrcpc3_sigill,753},754{755.name = "LSE",756.at_hwcap = AT_HWCAP,757.hwcap_bit = HWCAP_ATOMICS,758.cpuinfo = "atomics",759.sigill_fn = atomics_sigill,760},761{762.name = "LSE2",763.at_hwcap = AT_HWCAP,764.hwcap_bit = HWCAP_USCAT,765.cpuinfo = "uscat",766.sigill_fn = atomics_sigill,767.sigbus_fn = uscat_sigbus,768.sigbus_reliable = true,769},770{771.name = "LSE128",772.at_hwcap = AT_HWCAP2,773.hwcap_bit = HWCAP2_LSE128,774.cpuinfo = "lse128",775.sigill_fn = lse128_sigill,776},777{778.name = "LSFE",779.at_hwcap = AT_HWCAP3,780.hwcap_bit = HWCAP3_LSFE,781.cpuinfo = "lsfe",782.sigill_fn = lsfe_sigill,783},784{785.name = "LUT",786.at_hwcap = AT_HWCAP2,787.hwcap_bit = HWCAP2_LUT,788.cpuinfo = "lut",789.sigill_fn = lut_sigill,790},791{792.name = "MOPS",793.at_hwcap = AT_HWCAP2,794.hwcap_bit = HWCAP2_MOPS,795.cpuinfo = "mops",796.sigill_fn = mops_sigill,797.sigill_reliable = true,798},799{800.name = "PMULL",801.at_hwcap = AT_HWCAP,802.hwcap_bit = HWCAP_PMULL,803.cpuinfo = "pmull",804.sigill_fn = pmull_sigill,805},806{807.name = "POE",808.at_hwcap = AT_HWCAP2,809.hwcap_bit = HWCAP2_POE,810.cpuinfo = "poe",811.sigill_fn = poe_sigill,812.sigill_reliable = true,813},814{815.name = "RNG",816.at_hwcap = AT_HWCAP2,817.hwcap_bit = HWCAP2_RNG,818.cpuinfo = "rng",819.sigill_fn = rng_sigill,820},821{822.name = "RPRFM",823.at_hwcap = AT_HWCAP2,824.hwcap_bit = HWCAP2_RPRFM,825.cpuinfo = "rprfm",826},827{828.name = "SHA1",829.at_hwcap = AT_HWCAP,830.hwcap_bit = HWCAP_SHA1,831.cpuinfo = "sha1",832.sigill_fn = sha1_sigill,833},834{835.name = "SHA2",836.at_hwcap = AT_HWCAP,837.hwcap_bit = HWCAP_SHA2,838.cpuinfo = "sha2",839.sigill_fn = sha2_sigill,840},841{842.name = "SHA512",843.at_hwcap = AT_HWCAP,844.hwcap_bit = HWCAP_SHA512,845.cpuinfo = "sha512",846.sigill_fn = sha512_sigill,847},848{849.name = "SME",850.at_hwcap = AT_HWCAP2,851.hwcap_bit = HWCAP2_SME,852.cpuinfo = "sme",853.sigill_fn = sme_sigill,854.sigill_reliable = true,855},856{857.name = "SME2",858.at_hwcap = AT_HWCAP2,859.hwcap_bit = HWCAP2_SME2,860.cpuinfo = "sme2",861.sigill_fn = sme2_sigill,862.sigill_reliable = true,863},864{865.name = "SME 2.1",866.at_hwcap = AT_HWCAP2,867.hwcap_bit = HWCAP2_SME2P1,868.cpuinfo = "sme2p1",869.sigill_fn = sme2p1_sigill,870},871{872.name = "SME 2.2",873.at_hwcap = AT_HWCAP,874.hwcap_bit = HWCAP_SME2P2,875.cpuinfo = "sme2p2",876.sigill_fn = sme2p2_sigill,877},878{879.name = "SME AES",880.at_hwcap = AT_HWCAP,881.hwcap_bit = HWCAP_SME_AES,882.cpuinfo = "smeaes",883.sigill_fn = sme_aes_sigill,884},885{886.name = "SME I16I32",887.at_hwcap = AT_HWCAP2,888.hwcap_bit = HWCAP2_SME_I16I32,889.cpuinfo = "smei16i32",890.sigill_fn = smei16i32_sigill,891},892{893.name = "SME BI32I32",894.at_hwcap = AT_HWCAP2,895.hwcap_bit = HWCAP2_SME_BI32I32,896.cpuinfo = "smebi32i32",897.sigill_fn = smebi32i32_sigill,898},899{900.name = "SME B16B16",901.at_hwcap = AT_HWCAP2,902.hwcap_bit = HWCAP2_SME_B16B16,903.cpuinfo = "smeb16b16",904.sigill_fn = smeb16b16_sigill,905},906{907.name = "SME F16F16",908.at_hwcap = AT_HWCAP2,909.hwcap_bit = HWCAP2_SME_F16F16,910.cpuinfo = "smef16f16",911.sigill_fn = smef16f16_sigill,912},913{914.name = "SME F8F16",915.at_hwcap = AT_HWCAP2,916.hwcap_bit = HWCAP2_SME_F8F16,917.cpuinfo = "smef8f16",918.sigill_fn = smef8f16_sigill,919},920{921.name = "SME F8F32",922.at_hwcap = AT_HWCAP2,923.hwcap_bit = HWCAP2_SME_F8F32,924.cpuinfo = "smef8f32",925.sigill_fn = smef8f32_sigill,926},927{928.name = "SME LUTV2",929.at_hwcap = AT_HWCAP2,930.hwcap_bit = HWCAP2_SME_LUTV2,931.cpuinfo = "smelutv2",932.sigill_fn = smelutv2_sigill,933},934{935.name = "SME SBITPERM",936.at_hwcap = AT_HWCAP,937.hwcap_bit = HWCAP_SME_SBITPERM,938.cpuinfo = "smesbitperm",939.sigill_fn = sme_sbitperm_sigill,940},941{942.name = "SME SF8FMA",943.at_hwcap = AT_HWCAP2,944.hwcap_bit = HWCAP2_SME_SF8FMA,945.cpuinfo = "smesf8fma",946.sigill_fn = smesf8fma_sigill,947},948{949.name = "SME SF8DP2",950.at_hwcap = AT_HWCAP2,951.hwcap_bit = HWCAP2_SME_SF8DP2,952.cpuinfo = "smesf8dp2",953.sigill_fn = smesf8dp2_sigill,954},955{956.name = "SME SF8DP4",957.at_hwcap = AT_HWCAP2,958.hwcap_bit = HWCAP2_SME_SF8DP4,959.cpuinfo = "smesf8dp4",960.sigill_fn = smesf8dp4_sigill,961},962{963.name = "SME SFEXPA",964.at_hwcap = AT_HWCAP,965.hwcap_bit = HWCAP_SME_SFEXPA,966.cpuinfo = "smesfexpa",967.sigill_fn = smesfexpa_sigill,968},969{970.name = "SME SMOP4",971.at_hwcap = AT_HWCAP,972.hwcap_bit = HWCAP_SME_SMOP4,973.cpuinfo = "smesmop4",974.sigill_fn = smesmop4_sigill,975},976{977.name = "SME STMOP",978.at_hwcap = AT_HWCAP,979.hwcap_bit = HWCAP_SME_STMOP,980.cpuinfo = "smestmop",981.sigill_fn = smestmop_sigill,982},983{984.name = "SVE",985.at_hwcap = AT_HWCAP,986.hwcap_bit = HWCAP_SVE,987.cpuinfo = "sve",988.sigill_fn = sve_sigill,989.sigill_reliable = true,990},991{992.name = "SVE 2",993.at_hwcap = AT_HWCAP2,994.hwcap_bit = HWCAP2_SVE2,995.cpuinfo = "sve2",996.sigill_fn = sve2_sigill,997},998{999.name = "SVE 2.1",1000.at_hwcap = AT_HWCAP2,1001.hwcap_bit = HWCAP2_SVE2P1,1002.cpuinfo = "sve2p1",1003.sigill_fn = sve2p1_sigill,1004},1005{1006.name = "SVE 2.2",1007.at_hwcap = AT_HWCAP,1008.hwcap_bit = HWCAP_SVE2P2,1009.cpuinfo = "sve2p2",1010.sigill_fn = sve2p2_sigill,1011},1012{1013.name = "SVE AES",1014.at_hwcap = AT_HWCAP2,1015.hwcap_bit = HWCAP2_SVEAES,1016.cpuinfo = "sveaes",1017.sigill_fn = sveaes_sigill,1018},1019{1020.name = "SVE AES2",1021.at_hwcap = AT_HWCAP,1022.hwcap_bit = HWCAP_SVE_AES2,1023.cpuinfo = "sveaes2",1024.sigill_fn = sveaes2_sigill,1025},1026{1027.name = "SVE BFSCALE",1028.at_hwcap = AT_HWCAP,1029.hwcap_bit = HWCAP_SVE_BFSCALE,1030.cpuinfo = "svebfscale",1031.sigill_fn = svebfscale_sigill,1032},1033{1034.name = "SVE ELTPERM",1035.at_hwcap = AT_HWCAP,1036.hwcap_bit = HWCAP_SVE_ELTPERM,1037.cpuinfo = "sveeltperm",1038.sigill_fn = sveeltperm_sigill,1039},1040{1041.name = "SVE F16MM",1042.at_hwcap = AT_HWCAP,1043.hwcap_bit = HWCAP_SVE_F16MM,1044.cpuinfo = "svef16mm",1045.sigill_fn = svef16mm_sigill,1046},1047{1048.name = "SVE2 B16B16",1049.at_hwcap = AT_HWCAP2,1050.hwcap_bit = HWCAP2_SVE_B16B16,1051.cpuinfo = "sveb16b16",1052.sigill_fn = sveb16b16_sigill,1053},1054{1055.name = "SVE2 PMULL",1056.at_hwcap = AT_HWCAP2,1057.hwcap_bit = HWCAP2_SVEPMULL,1058.cpuinfo = "svepmull",1059.sigill_fn = svepmull_sigill,1060},1061{1062.name = "SVE2 BITPERM",1063.at_hwcap = AT_HWCAP2,1064.hwcap_bit = HWCAP2_SVEBITPERM,1065.cpuinfo = "svebitperm",1066.sigill_fn = svebitperm_sigill,1067},1068{1069.name = "SVE2 SHA3",1070.at_hwcap = AT_HWCAP2,1071.hwcap_bit = HWCAP2_SVESHA3,1072.cpuinfo = "svesha3",1073.sigill_fn = svesha3_sigill,1074},1075{1076.name = "SVE2 SM4",1077.at_hwcap = AT_HWCAP2,1078.hwcap_bit = HWCAP2_SVESM4,1079.cpuinfo = "svesm4",1080.sigill_fn = svesm4_sigill,1081},1082{1083.name = "SVE2 I8MM",1084.at_hwcap = AT_HWCAP2,1085.hwcap_bit = HWCAP2_SVEI8MM,1086.cpuinfo = "svei8mm",1087.sigill_fn = svei8mm_sigill,1088},1089{1090.name = "SVE2 F32MM",1091.at_hwcap = AT_HWCAP2,1092.hwcap_bit = HWCAP2_SVEF32MM,1093.cpuinfo = "svef32mm",1094.sigill_fn = svef32mm_sigill,1095},1096{1097.name = "SVE2 F64MM",1098.at_hwcap = AT_HWCAP2,1099.hwcap_bit = HWCAP2_SVEF64MM,1100.cpuinfo = "svef64mm",1101.sigill_fn = svef64mm_sigill,1102},1103{1104.name = "SVE2 BF16",1105.at_hwcap = AT_HWCAP2,1106.hwcap_bit = HWCAP2_SVEBF16,1107.cpuinfo = "svebf16",1108.sigill_fn = svebf16_sigill,1109},1110{1111.name = "SVE2 EBF16",1112.at_hwcap = AT_HWCAP2,1113.hwcap_bit = HWCAP2_SVE_EBF16,1114.cpuinfo = "sveebf16",1115},1116{1117.name = "HBC",1118.at_hwcap = AT_HWCAP2,1119.hwcap_bit = HWCAP2_HBC,1120.cpuinfo = "hbc",1121.sigill_fn = hbc_sigill,1122.sigill_reliable = true,1123},1124{1125.name = "MTE_FAR",1126.at_hwcap = AT_HWCAP3,1127.hwcap_bit = HWCAP3_MTE_FAR,1128.cpuinfo = "mtefar",1129},1130{1131.name = "MTE_STOREONLY",1132.at_hwcap = AT_HWCAP3,1133.hwcap_bit = HWCAP3_MTE_STORE_ONLY,1134.cpuinfo = "mtestoreonly",1135},1136};11371138typedef void (*sighandler_fn)(int, siginfo_t *, void *);11391140#define DEF_SIGHANDLER_FUNC(SIG, NUM) \1141static bool seen_##SIG; \1142static void handle_##SIG(int sig, siginfo_t *info, void *context) \1143{ \1144ucontext_t *uc = context; \1145\1146seen_##SIG = true; \1147/* Skip over the offending instruction */ \1148uc->uc_mcontext.pc += 4; \1149}11501151DEF_SIGHANDLER_FUNC(sigill, SIGILL);1152DEF_SIGHANDLER_FUNC(sigbus, SIGBUS);11531154bool cpuinfo_present(const char *name)1155{1156FILE *f;1157char buf[2048], name_space[30], name_newline[30];1158char *s;11591160/*1161* The feature should appear with a leading space and either a1162* trailing space or a newline.1163*/1164snprintf(name_space, sizeof(name_space), " %s ", name);1165snprintf(name_newline, sizeof(name_newline), " %s\n", name);11661167f = fopen("/proc/cpuinfo", "r");1168if (!f) {1169ksft_print_msg("Failed to open /proc/cpuinfo\n");1170return false;1171}11721173while (fgets(buf, sizeof(buf), f)) {1174/* Features: line? */1175if (strncmp(buf, "Features\t:", strlen("Features\t:")) != 0)1176continue;11771178/* All CPUs should be symmetric, don't read any more */1179fclose(f);11801181s = strstr(buf, name_space);1182if (s)1183return true;1184s = strstr(buf, name_newline);1185if (s)1186return true;11871188return false;1189}11901191ksft_print_msg("Failed to find Features in /proc/cpuinfo\n");1192fclose(f);1193return false;1194}11951196static int install_sigaction(int signum, sighandler_fn handler)1197{1198int ret;1199struct sigaction sa;12001201memset(&sa, 0, sizeof(sa));1202sa.sa_sigaction = handler;1203sa.sa_flags = SA_RESTART | SA_SIGINFO;1204sigemptyset(&sa.sa_mask);1205ret = sigaction(signum, &sa, NULL);1206if (ret < 0)1207ksft_exit_fail_msg("Failed to install SIGNAL handler: %s (%d)\n",1208strerror(errno), errno);12091210return ret;1211}12121213static void uninstall_sigaction(int signum)1214{1215if (sigaction(signum, NULL, NULL) < 0)1216ksft_exit_fail_msg("Failed to uninstall SIGNAL handler: %s (%d)\n",1217strerror(errno), errno);1218}12191220#define DEF_INST_RAISE_SIG(SIG, NUM) \1221static bool inst_raise_##SIG(const struct hwcap_data *hwcap, \1222bool have_hwcap) \1223{ \1224if (!hwcap->SIG##_fn) { \1225ksft_test_result_skip(#SIG"_%s\n", hwcap->name); \1226/* assume that it would raise exception in default */ \1227return true; \1228} \1229\1230install_sigaction(NUM, handle_##SIG); \1231\1232seen_##SIG = false; \1233hwcap->SIG##_fn(); \1234\1235if (have_hwcap) { \1236/* Should be able to use the extension */ \1237ksft_test_result(!seen_##SIG, \1238#SIG"_%s\n", hwcap->name); \1239} else if (hwcap->SIG##_reliable) { \1240/* Guaranteed a SIGNAL */ \1241ksft_test_result(seen_##SIG, \1242#SIG"_%s\n", hwcap->name); \1243} else { \1244/* Missing SIGNAL might be fine */ \1245ksft_print_msg(#SIG"_%sreported for %s\n", \1246seen_##SIG ? "" : "not ", \1247hwcap->name); \1248ksft_test_result_skip(#SIG"_%s\n", \1249hwcap->name); \1250} \1251\1252uninstall_sigaction(NUM); \1253return seen_##SIG; \1254}12551256DEF_INST_RAISE_SIG(sigill, SIGILL);1257DEF_INST_RAISE_SIG(sigbus, SIGBUS);12581259int main(void)1260{1261int i;1262const struct hwcap_data *hwcap;1263bool have_cpuinfo, have_hwcap, raise_sigill;12641265ksft_print_header();1266ksft_set_plan(ARRAY_SIZE(hwcaps) * TESTS_PER_HWCAP);12671268for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {1269hwcap = &hwcaps[i];12701271have_hwcap = getauxval(hwcap->at_hwcap) & hwcap->hwcap_bit;1272have_cpuinfo = cpuinfo_present(hwcap->cpuinfo);12731274if (have_hwcap)1275ksft_print_msg("%s present\n", hwcap->name);12761277ksft_test_result(have_hwcap == have_cpuinfo,1278"cpuinfo_match_%s\n", hwcap->name);12791280/*1281* Testing for SIGBUS only makes sense after make sure1282* that the instruction does not cause a SIGILL signal.1283*/1284raise_sigill = inst_raise_sigill(hwcap, have_hwcap);1285if (!raise_sigill)1286inst_raise_sigbus(hwcap, have_hwcap);1287else1288ksft_test_result_skip("sigbus_%s\n", hwcap->name);1289}12901291ksft_print_cnts();12921293return 0;1294}129512961297