brintos

brintos / linux-shallow public Read only

0
0
Text · 20.1 KiB · f2d6007 Raw
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