File Index
Files and directories
Sign in
FILE

hwcap.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/arm64/abi/hwcap.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   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 <linux/auxvec.h>
  21
  22#include "kselftest.h"
  23
  24#define TESTS_PER_HWCAP 3
  25
  26#ifndef AT_HWCAP3
  27#define AT_HWCAP3 29
  28#endif
  29
  30/*
  31 * Function expected to generate exception when the feature is not
  32 * supported and return when it is supported. If the specific exception
  33 * is generated then the handler must be able to skip over the
  34 * instruction safely.
  35 *
  36 * Note that it is expected that for many architecture extensions
  37 * there are no specific traps due to no architecture state being
  38 * added so we may not fault if running on a kernel which doesn't know
  39 * to add the hwcap.
  40 */
  41typedef void (*sig_fn)(void);
  42
  43static void aes_sigill(void)
  44{
  45	/* AESE V0.16B, V0.16B */
  46	asm volatile(".inst 0x4e284800" : : : );
  47}
  48
  49static void atomics_sigill(void)
  50{
  51	/* STADD W0, [SP] */
  52	asm volatile(".inst 0xb82003ff" : : : );
  53}
  54
  55static void cmpbr_sigill(void)
  56{
  57	/* Not implemented, too complicated and unreliable anyway */
  58}
  59
  60static void crc32_sigill(void)
  61{
  62	/* CRC32W W0, W0, W1 */
  63	asm volatile(".inst 0x1ac14800" : : : );
  64}
  65
  66static void cssc_sigill(void)
  67{
  68	/* CNT x0, x0 */
  69	asm volatile(".inst 0xdac01c00" : : : "x0");
  70}
  71
  72static void f8cvt_sigill(void)
  73{
  74	/* FSCALE V0.4H, V0.4H, V0.4H */
  75	asm volatile(".inst 0x2ec03c00");
  76}
  77
  78static void f8dp2_sigill(void)
  79{
  80	/* FDOT V0.4H, V0.4H, V0.5H */
  81	asm volatile(".inst 0xe40fc00");
  82}
  83
  84static void f8dp4_sigill(void)
  85{
  86	/* FDOT V0.2S, V0.2S, V0.2S */
  87	asm volatile(".inst 0xe00fc00");
  88}
  89
  90static void f8fma_sigill(void)
  91{
  92	/* FMLALB V0.8H, V0.16B, V0.16B */
  93	asm volatile(".inst 0xec0fc00");
  94}
  95
  96static void f8mm4_sigill(void)
  97{
  98	/* FMMLA V0.4SH, V0.16B, V0.16B */
  99	asm volatile(".inst 0x6e00ec00");
 100}
 101
 102static void f8mm8_sigill(void)
 103{
 104	/* FMMLA V0.4S, V0.16B, V0.16B */
 105	asm volatile(".inst 0x6e80ec00");
 106}
 107
 108static void faminmax_sigill(void)
 109{
 110	/* FAMIN V0.4H, V0.4H, V0.4H */
 111	asm volatile(".inst 0x2ec01c00");
 112}
 113
 114static void fp_sigill(void)
 115{
 116	asm volatile("fmov s0, #1");
 117}
 118
 119static void fpmr_sigill(void)
 120{
 121	asm volatile("mrs x0, S3_3_C4_C4_2" : : : "x0");
 122}
 123
 124static void fprcvt_sigill(void)
 125{
 126	/* FCVTAS S0, H0 */
 127	asm volatile(".inst 0x1efa0000");
 128}
 129
 130static void gcs_sigill(void)
 131{
 132	unsigned long *gcspr;
 133
 134	asm volatile(
 135		"mrs	%0, S3_3_C2_C5_1"
 136	: "=r" (gcspr)
 137	:
 138	: "cc");
 139}
 140
 141static void ilrcpc_sigill(void)
 142{
 143	/* LDAPUR W0, [SP, #8] */
 144	asm volatile(".inst 0x994083e0" : : : );
 145}
 146
 147static void jscvt_sigill(void)
 148{
 149	/* FJCVTZS W0, D0 */
 150	asm volatile(".inst 0x1e7e0000" : : : );
 151}
 152
 153static void lrcpc_sigill(void)
 154{
 155	/* LDAPR W0, [SP, #0] */
 156	asm volatile(".inst 0xb8bfc3e0" : : : );
 157}
 158
 159static void lse128_sigill(void)
 160{
 161	u64 __attribute__ ((aligned (16))) mem[2] = { 10, 20 };
 162	register u64 *memp asm ("x0") = mem;
 163	register u64 val0 asm ("x1") = 5;
 164	register u64 val1 asm ("x2") = 4;
 165
 166	/* SWPP X1, X2, [X0] */
 167	asm volatile(".inst 0x19228001"
 168		     : "+r" (memp), "+r" (val0), "+r" (val1)
 169		     :
 170		     : "cc", "memory");
 171}
 172
 173static void lsfe_sigill(void)
 174{
 175	float __attribute__ ((aligned (16))) mem;
 176	register float *memp asm ("x0") = &mem;
 177
 178	/* STFADD H0, [X0] */
 179	asm volatile(".inst 0x7c20801f"
 180		     : "+r" (memp)
 181		     :
 182		     : "memory");
 183}
 184
 185static void lut_sigill(void)
 186{
 187	/* LUTI2 V0.16B, { V0.16B }, V[0] */
 188	asm volatile(".inst 0x4e801000");
 189}
 190
 191static void mops_sigill(void)
 192{
 193	char dst[1], src[1];
 194	register char *dstp asm ("x0") = dst;
 195	register char *srcp asm ("x1") = src;
 196	register long size asm ("x2") = 1;
 197
 198	/* CPYP [x0]!, [x1]!, x2! */
 199	asm volatile(".inst 0x1d010440"
 200		     : "+r" (dstp), "+r" (srcp), "+r" (size)
 201		     :
 202		     : "cc", "memory");
 203}
 204
 205static void pmull_sigill(void)
 206{
 207	/* PMULL V0.1Q, V0.1D, V0.1D */
 208	asm volatile(".inst 0x0ee0e000" : : : );
 209}
 210
 211static void poe_sigill(void)
 212{
 213	/* mrs x0, POR_EL0 */
 214	asm volatile("mrs x0, S3_3_C10_C2_4" : : : "x0");
 215}
 216
 217static void rng_sigill(void)
 218{
 219	asm volatile("mrs x0, S3_3_C2_C4_0" : : : "x0");
 220}
 221
 222static void sha1_sigill(void)
 223{
 224	/* SHA1H S0, S0 */
 225	asm volatile(".inst 0x5e280800" : : : );
 226}
 227
 228static void sha2_sigill(void)
 229{
 230	/* SHA256H Q0, Q0, V0.4S */
 231	asm volatile(".inst 0x5e004000" : : : );
 232}
 233
 234static void sha512_sigill(void)
 235{
 236	/* SHA512H Q0, Q0, V0.2D */
 237	asm volatile(".inst 0xce608000" : : : );
 238}
 239
 240static void sme_sigill(void)
 241{
 242	/* RDSVL x0, #0 */
 243	asm volatile(".inst 0x04bf5800" : : : "x0");
 244}
 245
 246static void sme2_sigill(void)
 247{
 248	/* SMSTART ZA */
 249	asm volatile("msr S0_3_C4_C5_3, xzr" : : : );
 250
 251	/* ZERO ZT0 */
 252	asm volatile(".inst 0xc0480001" : : : );
 253
 254	/* SMSTOP */
 255	asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
 256}
 257
 258static void sme2p1_sigill(void)
 259{
 260	/* SMSTART SM */
 261	asm volatile("msr S0_3_C4_C3_3, xzr" : : : );
 262
 263	/* BFCLAMP { Z0.H - Z1.H }, Z0.H, Z0.H */
 264	asm volatile(".inst 0xc120C000" : : : );
 265
 266	/* SMSTOP */
 267	asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
 268}
 269
 270static void sme2p2_sigill(void)
 271{
 272	/* SMSTART SM */
 273	asm volatile("msr S0_3_C4_C3_3, xzr" : : : );
 274
 275	/* UXTB Z0.D, P0/Z, Z0.D  */
 276	asm volatile(".inst 0x4c1a000" : : : );
 277
 278	/* SMSTOP */
 279	asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
 280}
 281
 282static void sme_aes_sigill(void)
 283{
 284	/* SMSTART SM */
 285	asm volatile("msr S0_3_C4_C3_3, xzr" : : : );
 286
 287	/* AESD z0.b, z0.b, z0.b */
 288	asm volatile(".inst 0x4522e400" : : : "z0");
 289
 290	/* SMSTOP */
 291	asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
 292}
 293
 294static void sme_sbitperm_sigill(void)
 295{
 296	/* SMSTART SM */
 297	asm volatile("msr S0_3_C4_C3_3, xzr" : : : );
 298
 299	/* BDEP Z0.B, Z0.B, Z0.B */
 300	asm volatile(".inst 0x4500b400" : : : "z0");
 301
 302	/* SMSTOP */
 303	asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
 304}
 305
 306static void smei16i32_sigill(void)
 307{
 308	/* SMSTART */
 309	asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
 310
 311	/* SMOPA ZA0.S, P0/M, P0/M, Z0.B, Z0.B */
 312	asm volatile(".inst 0xa0800000" : : : );
 313
 314	/* SMSTOP */
 315	asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
 316}
 317
 318static void smebi32i32_sigill(void)
 319{
 320	/* SMSTART */
 321	asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
 322
 323	/* BMOPA ZA0.S, P0/M, P0/M, Z0.B, Z0.B */
 324	asm volatile(".inst 0x80800008" : : : );
 325
 326	/* SMSTOP */
 327	asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
 328}
 329
 330static void smeb16b16_sigill(void)
 331{
 332	/* SMSTART */
 333	asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
 334
 335	/* BFADD ZA.H[W0, 0], {Z0.H-Z1.H} */
 336	asm volatile(".inst 0xC1E41C00" : : : );
 337
 338	/* SMSTOP */
 339	asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
 340}
 341
 342static void smef16f16_sigill(void)
 343{
 344	/* SMSTART */
 345	asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
 346
 347	/* FADD ZA.H[W0, 0], { Z0.H-Z1.H } */
 348	asm volatile(".inst 0xc1a41C00" : : : );
 349
 350	/* SMSTOP */
 351	asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
 352}
 353
 354static void smef8f16_sigill(void)
 355{
 356	/* SMSTART */
 357	asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
 358
 359	/* FDOT ZA.H[W0, 0], Z0.B-Z1.B, Z0.B-Z1.B */
 360	asm volatile(".inst 0xc1a01020" : : : );
 361
 362	/* SMSTOP */
 363	asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
 364}
 365
 366static void smef8f32_sigill(void)
 367{
 368	/* SMSTART */
 369	asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
 370
 371	/* FDOT ZA.S[W0, 0], { Z0.B-Z1.B }, Z0.B[0] */
 372	asm volatile(".inst 0xc1500038" : : : );
 373
 374	/* SMSTOP */
 375	asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
 376}
 377
 378static void smelutv2_sigill(void)
 379{
 380	/* SMSTART */
 381	asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
 382
 383	/* LUTI4 { Z0.B-Z3.B }, ZT0, { Z0-Z1 } */
 384	asm volatile(".inst 0xc08b0000" : : : );
 385
 386	/* SMSTOP */
 387	asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
 388}
 389
 390static void smesf8dp2_sigill(void)
 391{
 392	/* SMSTART */
 393	asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
 394
 395	/* FDOT Z0.H, Z0.B, Z0.B[0] */
 396	asm volatile(".inst 0x64204400" : : : );
 397
 398	/* SMSTOP */
 399	asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
 400}
 401
 402static void smesf8dp4_sigill(void)
 403{
 404	/* SMSTART */
 405	asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
 406
 407	/* FDOT Z0.S, Z0.B, Z0.B[0] */
 408	asm volatile(".inst 0xc1a41C00" : : : );
 409
 410	/* SMSTOP */
 411	asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
 412}
 413
 414static void smesf8fma_sigill(void)
 415{
 416	/* SMSTART */
 417	asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
 418
 419	/* FMLALB Z0.8H, Z0.B, Z0.B */
 420	asm volatile(".inst 0x64205000");
 421
 422	/* SMSTOP */
 423	asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
 424}
 425
 426static void smesfexpa_sigill(void)
 427{
 428	/* SMSTART */
 429	asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
 430
 431	/* FEXPA Z0.D, Z0.D */
 432	asm volatile(".inst 0x04e0b800");
 433
 434	/* SMSTOP */
 435	asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
 436}
 437
 438static void smesmop4_sigill(void)
 439{
 440	/* SMSTART */
 441	asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
 442
 443	/* SMOP4A ZA0.S, Z0.B, { Z0.B - Z1.B } */
 444	asm volatile(".inst 0x80108000");
 445
 446	/* SMSTOP */
 447	asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
 448}
 449
 450static void smestmop_sigill(void)
 451{
 452	/* SMSTART */
 453	asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
 454
 455	/* STMOPA ZA0.S, { Z0.H - Z1.H }, Z0.H, Z20[0] */
 456	asm volatile(".inst 0x80408008");
 457
 458	/* SMSTOP */
 459	asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
 460}
 461
 462static void sve_sigill(void)
 463{
 464	/* RDVL x0, #0 */
 465	asm volatile(".inst 0x04bf5000" : : : "x0");
 466}
 467
 468static void sve2_sigill(void)
 469{
 470	/* SQABS Z0.b, P0/M, Z0.B */
 471	asm volatile(".inst 0x4408A000" : : : "z0");
 472}
 473
 474static void sve2p1_sigill(void)
 475{
 476	/* LD1Q {Z0.Q}, P0/Z, [Z0.D, X0] */
 477	asm volatile(".inst 0xC400A000" : : : "z0");
 478}
 479
 480static void sve2p2_sigill(void)
 481{
 482	/* NOT Z0.D, P0/Z, Z0.D */
 483	asm volatile(".inst 0x4cea000" : : : "z0");
 484}
 485
 486static void sveaes_sigill(void)
 487{
 488	/* AESD z0.b, z0.b, z0.b */
 489	asm volatile(".inst 0x4522e400" : : : "z0");
 490}
 491
 492static void sveaes2_sigill(void)
 493{
 494	/* AESD {Z0.B - Z1.B }, { Z0.B - Z1.B }, Z0.Q */
 495	asm volatile(".inst 0x4522ec00" : : : "z0");
 496}
 497
 498static void sveb16b16_sigill(void)
 499{
 500	/* BFADD Z0.H, Z0.H, Z0.H */
 501	asm volatile(".inst 0x65000000" : : : );
 502}
 503
 504static void svebfscale_sigill(void)
 505{
 506	/* BFSCALE Z0.H, P0/M, Z0.H, Z0.H */
 507	asm volatile(".inst 0x65098000" : : : "z0");
 508}
 509
 510static void svef16mm_sigill(void)
 511{
 512	/* FMMLA Z0.S, Z0.H, Z0.H */
 513	asm volatile(".inst 0x6420e400");
 514}
 515
 516static void svepmull_sigill(void)
 517{
 518	/* PMULLB Z0.Q, Z0.D, Z0.D */
 519	asm volatile(".inst 0x45006800" : : : "z0");
 520}
 521
 522static void svebitperm_sigill(void)
 523{
 524	/* BDEP Z0.B, Z0.B, Z0.B */
 525	asm volatile(".inst 0x4500b400" : : : "z0");
 526}
 527
 528static void svesha3_sigill(void)
 529{
 530	/* EOR3 Z0.D, Z0.D, Z0.D, Z0.D */
 531	asm volatile(".inst 0x4203800" : : : "z0");
 532}
 533
 534static void sveeltperm_sigill(void)
 535{
 536	/* COMPACT Z0.B, P0, Z0.B */
 537	asm volatile(".inst 0x5218000" : : : "x0");
 538}
 539
 540static void svesm4_sigill(void)
 541{
 542	/* SM4E Z0.S, Z0.S, Z0.S */
 543	asm volatile(".inst 0x4523e000" : : : "z0");
 544}
 545
 546static void svei8mm_sigill(void)
 547{
 548	/* USDOT Z0.S, Z0.B, Z0.B[0] */
 549	asm volatile(".inst 0x44a01800" : : : "z0");
 550}
 551
 552static void svef32mm_sigill(void)
 553{
 554	/* FMMLA Z0.S, Z0.S, Z0.S */
 555	asm volatile(".inst 0x64a0e400" : : : "z0");
 556}
 557
 558static void svef64mm_sigill(void)
 559{
 560	/* FMMLA Z0.D, Z0.D, Z0.D */
 561	asm volatile(".inst 0x64e0e400" : : : "z0");
 562}
 563
 564static void svebf16_sigill(void)
 565{
 566	/* BFCVT Z0.H, P0/M, Z0.S */
 567	asm volatile(".inst 0x658aa000" : : : "z0");
 568}
 569
 570static void hbc_sigill(void)
 571{
 572	/* BC.EQ +4 */
 573	asm volatile("cmp xzr, xzr\n"
 574		     ".inst 0x54000030" : : : "cc");
 575}
 576
 577static void uscat_sigbus(void)
 578{
 579	/* unaligned atomic access */
 580	asm volatile("ADD x1, sp, #2" : : : );
 581	/* STADD W0, [X1] */
 582	asm volatile(".inst 0xb820003f" : : : );
 583}
 584
 585static void lrcpc3_sigill(void)
 586{
 587	int data[2] = { 1, 2 };
 588
 589	register int *src asm ("x0") = data;
 590	register int data0 asm ("w2") = 0;
 591	register int data1 asm ("w3") = 0;
 592
 593	/* LDIAPP w2, w3, [x0] */
 594	asm volatile(".inst 0x99431802"
 595	              : "=r" (data0), "=r" (data1) : "r" (src) :);
 596}
 597
 598static const struct hwcap_data {
 599	const char *name;
 600	unsigned long at_hwcap;
 601	unsigned long hwcap_bit;
 602	const char *cpuinfo;
 603	sig_fn sigill_fn;
 604	bool sigill_reliable;
 605	sig_fn sigbus_fn;
 606	bool sigbus_reliable;
 607} hwcaps[] = {
 608	{
 609		.name = "AES",
 610		.at_hwcap = AT_HWCAP,
 611		.hwcap_bit = HWCAP_AES,
 612		.cpuinfo = "aes",
 613		.sigill_fn = aes_sigill,
 614	},
 615	{
 616		.name = "CMPBR",
 617		.at_hwcap = AT_HWCAP,
 618		.hwcap_bit = HWCAP_CMPBR,
 619		.cpuinfo = "cmpbr",
 620		.sigill_fn = cmpbr_sigill,
 621	},
 622	{
 623		.name = "CRC32",
 624		.at_hwcap = AT_HWCAP,
 625		.hwcap_bit = HWCAP_CRC32,
 626		.cpuinfo = "crc32",
 627		.sigill_fn = crc32_sigill,
 628	},
 629	{
 630		.name = "CSSC",
 631		.at_hwcap = AT_HWCAP2,
 632		.hwcap_bit = HWCAP2_CSSC,
 633		.cpuinfo = "cssc",
 634		.sigill_fn = cssc_sigill,
 635	},
 636	{
 637		.name = "F8CVT",
 638		.at_hwcap = AT_HWCAP2,
 639		.hwcap_bit = HWCAP2_F8CVT,
 640		.cpuinfo = "f8cvt",
 641		.sigill_fn = f8cvt_sigill,
 642	},
 643	{
 644		.name = "F8DP4",
 645		.at_hwcap = AT_HWCAP2,
 646		.hwcap_bit = HWCAP2_F8DP4,
 647		.cpuinfo = "f8dp4",
 648		.sigill_fn = f8dp4_sigill,
 649	},
 650	{
 651		.name = "F8DP2",
 652		.at_hwcap = AT_HWCAP2,
 653		.hwcap_bit = HWCAP2_F8DP2,
 654		.cpuinfo = "f8dp2",
 655		.sigill_fn = f8dp2_sigill,
 656	},
 657	{
 658		.name = "F8E5M2",
 659		.at_hwcap = AT_HWCAP2,
 660		.hwcap_bit = HWCAP2_F8E5M2,
 661		.cpuinfo = "f8e5m2",
 662	},
 663	{
 664		.name = "F8E4M3",
 665		.at_hwcap = AT_HWCAP2,
 666		.hwcap_bit = HWCAP2_F8E4M3,
 667		.cpuinfo = "f8e4m3",
 668	},
 669	{
 670		.name = "F8FMA",
 671		.at_hwcap = AT_HWCAP2,
 672		.hwcap_bit = HWCAP2_F8FMA,
 673		.cpuinfo = "f8fma",
 674		.sigill_fn = f8fma_sigill,
 675	},
 676	{
 677		.name = "F8MM8",
 678		.at_hwcap = AT_HWCAP,
 679		.hwcap_bit = HWCAP_F8MM8,
 680		.cpuinfo = "f8mm8",
 681		.sigill_fn = f8mm8_sigill,
 682	},
 683	{
 684		.name = "F8MM4",
 685		.at_hwcap = AT_HWCAP,
 686		.hwcap_bit = HWCAP_F8MM4,
 687		.cpuinfo = "f8mm4",
 688		.sigill_fn = f8mm4_sigill,
 689	},
 690	{
 691		.name = "FAMINMAX",
 692		.at_hwcap = AT_HWCAP2,
 693		.hwcap_bit = HWCAP2_FAMINMAX,
 694		.cpuinfo = "faminmax",
 695		.sigill_fn = faminmax_sigill,
 696	},
 697	{
 698		.name = "FP",
 699		.at_hwcap = AT_HWCAP,
 700		.hwcap_bit = HWCAP_FP,
 701		.cpuinfo = "fp",
 702		.sigill_fn = fp_sigill,
 703	},
 704	{
 705		.name = "FPMR",
 706		.at_hwcap = AT_HWCAP2,
 707		.hwcap_bit = HWCAP2_FPMR,
 708		.cpuinfo = "fpmr",
 709		.sigill_fn = fpmr_sigill,
 710		.sigill_reliable = true,
 711	},
 712	{
 713		.name = "FPRCVT",
 714		.at_hwcap = AT_HWCAP,
 715		.hwcap_bit = HWCAP_FPRCVT,
 716		.cpuinfo = "fprcvt",
 717		.sigill_fn = fprcvt_sigill,
 718	},
 719	{
 720		.name = "GCS",
 721		.at_hwcap = AT_HWCAP,
 722		.hwcap_bit = HWCAP_GCS,
 723		.cpuinfo = "gcs",
 724		.sigill_fn = gcs_sigill,
 725		.sigill_reliable = true,
 726	},
 727	{
 728		.name = "JSCVT",
 729		.at_hwcap = AT_HWCAP,
 730		.hwcap_bit = HWCAP_JSCVT,
 731		.cpuinfo = "jscvt",
 732		.sigill_fn = jscvt_sigill,
 733	},
 734	{
 735		.name = "LRCPC",
 736		.at_hwcap = AT_HWCAP,
 737		.hwcap_bit = HWCAP_LRCPC,
 738		.cpuinfo = "lrcpc",
 739		.sigill_fn = lrcpc_sigill,
 740	},
 741	{
 742		.name = "LRCPC2",
 743		.at_hwcap = AT_HWCAP,
 744		.hwcap_bit = HWCAP_ILRCPC,
 745		.cpuinfo = "ilrcpc",
 746		.sigill_fn = ilrcpc_sigill,
 747	},
 748	{
 749		.name = "LRCPC3",
 750		.at_hwcap = AT_HWCAP2,
 751		.hwcap_bit = HWCAP2_LRCPC3,
 752		.cpuinfo = "lrcpc3",
 753		.sigill_fn = lrcpc3_sigill,
 754	},
 755	{
 756		.name = "LSE",
 757		.at_hwcap = AT_HWCAP,
 758		.hwcap_bit = HWCAP_ATOMICS,
 759		.cpuinfo = "atomics",
 760		.sigill_fn = atomics_sigill,
 761	},
 762	{
 763		.name = "LSE2",
 764		.at_hwcap = AT_HWCAP,
 765		.hwcap_bit = HWCAP_USCAT,
 766		.cpuinfo = "uscat",
 767		.sigill_fn = atomics_sigill,
 768		.sigbus_fn = uscat_sigbus,
 769		.sigbus_reliable = true,
 770	},
 771	{
 772		.name = "LSE128",
 773		.at_hwcap = AT_HWCAP2,
 774		.hwcap_bit = HWCAP2_LSE128,
 775		.cpuinfo = "lse128",
 776		.sigill_fn = lse128_sigill,
 777	},
 778	{
 779		.name = "LSFE",
 780		.at_hwcap = AT_HWCAP3,
 781		.hwcap_bit = HWCAP3_LSFE,
 782		.cpuinfo = "lsfe",
 783		.sigill_fn = lsfe_sigill,
 784	},
 785	{
 786		.name = "LUT",
 787		.at_hwcap = AT_HWCAP2,
 788		.hwcap_bit = HWCAP2_LUT,
 789		.cpuinfo = "lut",
 790		.sigill_fn = lut_sigill,
 791	},
 792	{
 793		.name = "MOPS",
 794		.at_hwcap = AT_HWCAP2,
 795		.hwcap_bit = HWCAP2_MOPS,
 796		.cpuinfo = "mops",
 797		.sigill_fn = mops_sigill,
 798		.sigill_reliable = true,
 799	},
 800	{
 801		.name = "PMULL",
 802		.at_hwcap = AT_HWCAP,
 803		.hwcap_bit = HWCAP_PMULL,
 804		.cpuinfo = "pmull",
 805		.sigill_fn = pmull_sigill,
 806	},
 807	{
 808		.name = "POE",
 809		.at_hwcap = AT_HWCAP2,
 810		.hwcap_bit = HWCAP2_POE,
 811		.cpuinfo = "poe",
 812		.sigill_fn = poe_sigill,
 813		.sigill_reliable = true,
 814	},
 815	{
 816		.name = "RNG",
 817		.at_hwcap = AT_HWCAP2,
 818		.hwcap_bit = HWCAP2_RNG,
 819		.cpuinfo = "rng",
 820		.sigill_fn = rng_sigill,
 821	},
 822	{
 823		.name = "RPRFM",
 824		.at_hwcap = AT_HWCAP2,
 825		.hwcap_bit = HWCAP2_RPRFM,
 826		.cpuinfo = "rprfm",
 827	},
 828	{
 829		.name = "SHA1",
 830		.at_hwcap = AT_HWCAP,
 831		.hwcap_bit = HWCAP_SHA1,
 832		.cpuinfo = "sha1",
 833		.sigill_fn = sha1_sigill,
 834	},
 835	{
 836		.name = "SHA2",
 837		.at_hwcap = AT_HWCAP,
 838		.hwcap_bit = HWCAP_SHA2,
 839		.cpuinfo = "sha2",
 840		.sigill_fn = sha2_sigill,
 841	},
 842	{
 843		.name = "SHA512",
 844		.at_hwcap = AT_HWCAP,
 845		.hwcap_bit = HWCAP_SHA512,
 846		.cpuinfo = "sha512",
 847		.sigill_fn = sha512_sigill,
 848	},
 849	{
 850		.name = "SME",
 851		.at_hwcap = AT_HWCAP2,
 852		.hwcap_bit = HWCAP2_SME,
 853		.cpuinfo = "sme",
 854		.sigill_fn = sme_sigill,
 855		.sigill_reliable = true,
 856	},
 857	{
 858		.name = "SME2",
 859		.at_hwcap = AT_HWCAP2,
 860		.hwcap_bit = HWCAP2_SME2,
 861		.cpuinfo = "sme2",
 862		.sigill_fn = sme2_sigill,
 863		.sigill_reliable = true,
 864	},
 865	{
 866		.name = "SME 2.1",
 867		.at_hwcap = AT_HWCAP2,
 868		.hwcap_bit = HWCAP2_SME2P1,
 869		.cpuinfo = "sme2p1",
 870		.sigill_fn = sme2p1_sigill,
 871	},
 872	{
 873		.name = "SME 2.2",
 874		.at_hwcap = AT_HWCAP,
 875		.hwcap_bit = HWCAP_SME2P2,
 876		.cpuinfo = "sme2p2",
 877		.sigill_fn = sme2p2_sigill,
 878	},
 879	{
 880		.name = "SME AES",
 881		.at_hwcap = AT_HWCAP,
 882		.hwcap_bit = HWCAP_SME_AES,
 883		.cpuinfo = "smeaes",
 884		.sigill_fn = sme_aes_sigill,
 885	},
 886	{
 887		.name = "SME I16I32",
 888		.at_hwcap = AT_HWCAP2,
 889		.hwcap_bit = HWCAP2_SME_I16I32,
 890		.cpuinfo = "smei16i32",
 891		.sigill_fn = smei16i32_sigill,
 892	},
 893	{
 894		.name = "SME BI32I32",
 895		.at_hwcap = AT_HWCAP2,
 896		.hwcap_bit = HWCAP2_SME_BI32I32,
 897		.cpuinfo = "smebi32i32",
 898		.sigill_fn = smebi32i32_sigill,
 899	},
 900	{
 901		.name = "SME B16B16",
 902		.at_hwcap = AT_HWCAP2,
 903		.hwcap_bit = HWCAP2_SME_B16B16,
 904		.cpuinfo = "smeb16b16",
 905		.sigill_fn = smeb16b16_sigill,
 906	},
 907	{
 908		.name = "SME F16F16",
 909		.at_hwcap = AT_HWCAP2,
 910		.hwcap_bit = HWCAP2_SME_F16F16,
 911		.cpuinfo = "smef16f16",
 912		.sigill_fn = smef16f16_sigill,
 913	},
 914	{
 915		.name = "SME F8F16",
 916		.at_hwcap = AT_HWCAP2,
 917		.hwcap_bit = HWCAP2_SME_F8F16,
 918		.cpuinfo = "smef8f16",
 919		.sigill_fn = smef8f16_sigill,
 920	},
 921	{
 922		.name = "SME F8F32",
 923		.at_hwcap = AT_HWCAP2,
 924		.hwcap_bit = HWCAP2_SME_F8F32,
 925		.cpuinfo = "smef8f32",
 926		.sigill_fn = smef8f32_sigill,
 927	},
 928	{
 929		.name = "SME LUTV2",
 930		.at_hwcap = AT_HWCAP2,
 931		.hwcap_bit = HWCAP2_SME_LUTV2,
 932		.cpuinfo = "smelutv2",
 933		.sigill_fn = smelutv2_sigill,
 934	},
 935	{
 936		.name = "SME SBITPERM",
 937		.at_hwcap = AT_HWCAP,
 938		.hwcap_bit = HWCAP_SME_SBITPERM,
 939		.cpuinfo = "smesbitperm",
 940		.sigill_fn = sme_sbitperm_sigill,
 941	},
 942	{
 943		.name = "SME SF8FMA",
 944		.at_hwcap = AT_HWCAP2,
 945		.hwcap_bit = HWCAP2_SME_SF8FMA,
 946		.cpuinfo = "smesf8fma",
 947		.sigill_fn = smesf8fma_sigill,
 948	},
 949	{
 950		.name = "SME SF8DP2",
 951		.at_hwcap = AT_HWCAP2,
 952		.hwcap_bit = HWCAP2_SME_SF8DP2,
 953		.cpuinfo = "smesf8dp2",
 954		.sigill_fn = smesf8dp2_sigill,
 955	},
 956	{
 957		.name = "SME SF8DP4",
 958		.at_hwcap = AT_HWCAP2,
 959		.hwcap_bit = HWCAP2_SME_SF8DP4,
 960		.cpuinfo = "smesf8dp4",
 961		.sigill_fn = smesf8dp4_sigill,
 962	},
 963	{
 964		.name = "SME SFEXPA",
 965		.at_hwcap = AT_HWCAP,
 966		.hwcap_bit = HWCAP_SME_SFEXPA,
 967		.cpuinfo = "smesfexpa",
 968		.sigill_fn = smesfexpa_sigill,
 969	},
 970	{
 971		.name = "SME SMOP4",
 972		.at_hwcap = AT_HWCAP,
 973		.hwcap_bit = HWCAP_SME_SMOP4,
 974		.cpuinfo = "smesmop4",
 975		.sigill_fn = smesmop4_sigill,
 976	},
 977	{
 978		.name = "SME STMOP",
 979		.at_hwcap = AT_HWCAP,
 980		.hwcap_bit = HWCAP_SME_STMOP,
 981		.cpuinfo = "smestmop",
 982		.sigill_fn = smestmop_sigill,
 983	},
 984	{
 985		.name = "SVE",
 986		.at_hwcap = AT_HWCAP,
 987		.hwcap_bit = HWCAP_SVE,
 988		.cpuinfo = "sve",
 989		.sigill_fn = sve_sigill,
 990		.sigill_reliable = true,
 991	},
 992	{
 993		.name = "SVE 2",
 994		.at_hwcap = AT_HWCAP2,
 995		.hwcap_bit = HWCAP2_SVE2,
 996		.cpuinfo = "sve2",
 997		.sigill_fn = sve2_sigill,
 998	},
 999	{
1000		.name = "SVE 2.1",
1001		.at_hwcap = AT_HWCAP2,
1002		.hwcap_bit = HWCAP2_SVE2P1,
1003		.cpuinfo = "sve2p1",
1004		.sigill_fn = sve2p1_sigill,
1005	},
1006	{
1007		.name = "SVE 2.2",
1008		.at_hwcap = AT_HWCAP,
1009		.hwcap_bit = HWCAP_SVE2P2,
1010		.cpuinfo = "sve2p2",
1011		.sigill_fn = sve2p2_sigill,
1012	},
1013	{
1014		.name = "SVE AES",
1015		.at_hwcap = AT_HWCAP2,
1016		.hwcap_bit = HWCAP2_SVEAES,
1017		.cpuinfo = "sveaes",
1018		.sigill_fn = sveaes_sigill,
1019	},
1020	{
1021		.name = "SVE AES2",
1022		.at_hwcap = AT_HWCAP,
1023		.hwcap_bit = HWCAP_SVE_AES2,
1024		.cpuinfo = "sveaes2",
1025		.sigill_fn = sveaes2_sigill,
1026	},
1027	{
1028		.name = "SVE BFSCALE",
1029		.at_hwcap = AT_HWCAP,
1030		.hwcap_bit = HWCAP_SVE_BFSCALE,
1031		.cpuinfo = "svebfscale",
1032		.sigill_fn = svebfscale_sigill,
1033	},
1034	{
1035		.name = "SVE ELTPERM",
1036		.at_hwcap = AT_HWCAP,
1037		.hwcap_bit = HWCAP_SVE_ELTPERM,
1038		.cpuinfo = "sveeltperm",
1039		.sigill_fn = sveeltperm_sigill,
1040	},
1041	{
1042		.name = "SVE F16MM",
1043		.at_hwcap = AT_HWCAP,
1044		.hwcap_bit = HWCAP_SVE_F16MM,
1045		.cpuinfo = "svef16mm",
1046		.sigill_fn = svef16mm_sigill,
1047	},
1048	{
1049		.name = "SVE2 B16B16",
1050		.at_hwcap = AT_HWCAP2,
1051		.hwcap_bit = HWCAP2_SVE_B16B16,
1052		.cpuinfo = "sveb16b16",
1053		.sigill_fn = sveb16b16_sigill,
1054	},
1055	{
1056		.name = "SVE2 PMULL",
1057		.at_hwcap = AT_HWCAP2,
1058		.hwcap_bit = HWCAP2_SVEPMULL,
1059		.cpuinfo = "svepmull",
1060		.sigill_fn = svepmull_sigill,
1061	},
1062	{
1063		.name = "SVE2 BITPERM",
1064		.at_hwcap = AT_HWCAP2,
1065		.hwcap_bit = HWCAP2_SVEBITPERM,
1066		.cpuinfo = "svebitperm",
1067		.sigill_fn = svebitperm_sigill,
1068	},
1069	{
1070		.name = "SVE2 SHA3",
1071		.at_hwcap = AT_HWCAP2,
1072		.hwcap_bit = HWCAP2_SVESHA3,
1073		.cpuinfo = "svesha3",
1074		.sigill_fn = svesha3_sigill,
1075	},
1076	{
1077		.name = "SVE2 SM4",
1078		.at_hwcap = AT_HWCAP2,
1079		.hwcap_bit = HWCAP2_SVESM4,
1080		.cpuinfo = "svesm4",
1081		.sigill_fn = svesm4_sigill,
1082	},
1083	{
1084		.name = "SVE2 I8MM",
1085		.at_hwcap = AT_HWCAP2,
1086		.hwcap_bit = HWCAP2_SVEI8MM,
1087		.cpuinfo = "svei8mm",
1088		.sigill_fn = svei8mm_sigill,
1089	},
1090	{
1091		.name = "SVE2 F32MM",
1092		.at_hwcap = AT_HWCAP2,
1093		.hwcap_bit = HWCAP2_SVEF32MM,
1094		.cpuinfo = "svef32mm",
1095		.sigill_fn = svef32mm_sigill,
1096	},
1097	{
1098		.name = "SVE2 F64MM",
1099		.at_hwcap = AT_HWCAP2,
1100		.hwcap_bit = HWCAP2_SVEF64MM,
1101		.cpuinfo = "svef64mm",
1102		.sigill_fn = svef64mm_sigill,
1103	},
1104	{
1105		.name = "SVE2 BF16",
1106		.at_hwcap = AT_HWCAP2,
1107		.hwcap_bit = HWCAP2_SVEBF16,
1108		.cpuinfo = "svebf16",
1109		.sigill_fn = svebf16_sigill,
1110	},
1111	{
1112		.name = "SVE2 EBF16",
1113		.at_hwcap = AT_HWCAP2,
1114		.hwcap_bit = HWCAP2_SVE_EBF16,
1115		.cpuinfo = "sveebf16",
1116	},
1117	{
1118		.name = "HBC",
1119		.at_hwcap = AT_HWCAP2,
1120		.hwcap_bit = HWCAP2_HBC,
1121		.cpuinfo = "hbc",
1122		.sigill_fn = hbc_sigill,
1123		.sigill_reliable = true,
1124	},
1125	{
1126		.name = "MTE_FAR",
1127		.at_hwcap = AT_HWCAP3,
1128		.hwcap_bit = HWCAP3_MTE_FAR,
1129		.cpuinfo = "mtefar",
1130	},
1131	{
1132		.name = "MTE_STOREONLY",
1133		.at_hwcap = AT_HWCAP3,
1134		.hwcap_bit = HWCAP3_MTE_STORE_ONLY,
1135		.cpuinfo = "mtestoreonly",
1136	},
1137};
1138
1139typedef void (*sighandler_fn)(int, siginfo_t *, void *);
1140
1141#define DEF_SIGHANDLER_FUNC(SIG, NUM)					\
1142static bool seen_##SIG;							\
1143static void handle_##SIG(int sig, siginfo_t *info, void *context)	\
1144{									\
1145	ucontext_t *uc = context;					\
1146									\
1147	seen_##SIG = true;						\
1148	/* Skip over the offending instruction */			\
1149	uc->uc_mcontext.pc += 4;					\
1150}
1151
1152DEF_SIGHANDLER_FUNC(sigill, SIGILL);
1153DEF_SIGHANDLER_FUNC(sigbus, SIGBUS);
1154
1155bool cpuinfo_present(const char *name)
1156{
1157	FILE *f;
1158	char buf[2048], name_space[30], name_newline[30];
1159	char *s;
1160
1161	/*
1162	 * The feature should appear with a leading space and either a
1163	 * trailing space or a newline.
1164	 */
1165	snprintf(name_space, sizeof(name_space), " %s ", name);
1166	snprintf(name_newline, sizeof(name_newline), " %s\n", name);
1167
1168	f = fopen("/proc/cpuinfo", "r");
1169	if (!f) {
1170		ksft_print_msg("Failed to open /proc/cpuinfo\n");
1171		return false;
1172	}
1173
1174	while (fgets(buf, sizeof(buf), f)) {
1175		/* Features: line? */
1176		if (strncmp(buf, "Features\t:", strlen("Features\t:")) != 0)
1177			continue;
1178
1179		/* All CPUs should be symmetric, don't read any more */
1180		fclose(f);
1181
1182		s = strstr(buf, name_space);
1183		if (s)
1184			return true;
1185		s = strstr(buf, name_newline);
1186		if (s)
1187			return true;
1188
1189		return false;
1190	}
1191
1192	ksft_print_msg("Failed to find Features in /proc/cpuinfo\n");
1193	fclose(f);
1194	return false;
1195}
1196
1197static int install_sigaction(int signum, sighandler_fn handler)
1198{
1199	int ret;
1200	struct sigaction sa;
1201
1202	memset(&sa, 0, sizeof(sa));
1203	sa.sa_sigaction = handler;
1204	sa.sa_flags = SA_RESTART | SA_SIGINFO;
1205	sigemptyset(&sa.sa_mask);
1206	ret = sigaction(signum, &sa, NULL);
1207	if (ret < 0)
1208		ksft_exit_fail_msg("Failed to install SIGNAL handler: %s (%d)\n",
1209				   strerror(errno), errno);
1210
1211	return ret;
1212}
1213
1214static void uninstall_sigaction(int signum)
1215{
1216	if (sigaction(signum, NULL, NULL) < 0)
1217		ksft_exit_fail_msg("Failed to uninstall SIGNAL handler: %s (%d)\n",
1218				   strerror(errno), errno);
1219}
1220
1221#define DEF_INST_RAISE_SIG(SIG, NUM)					\
1222static bool inst_raise_##SIG(const struct hwcap_data *hwcap,		\
1223				bool have_hwcap)			\
1224{									\
1225	if (!hwcap->SIG##_fn) {						\
1226		ksft_test_result_skip(#SIG"_%s\n", hwcap->name);	\
1227		/* assume that it would raise exception in default */	\
1228		return true;						\
1229	}								\
1230									\
1231	install_sigaction(NUM, handle_##SIG);				\
1232									\
1233	seen_##SIG = false;						\
1234	hwcap->SIG##_fn();						\
1235									\
1236	if (have_hwcap) {						\
1237		/* Should be able to use the extension */		\
1238		ksft_test_result(!seen_##SIG,				\
1239				#SIG"_%s\n", hwcap->name);		\
1240	} else if (hwcap->SIG##_reliable) {				\
1241		/* Guaranteed a SIGNAL */				\
1242		ksft_test_result(seen_##SIG,				\
1243				#SIG"_%s\n", hwcap->name);		\
1244	} else {							\
1245		/* Missing SIGNAL might be fine */			\
1246		ksft_print_msg(#SIG"_%sreported for %s\n",		\
1247				seen_##SIG ? "" : "not ",		\
1248				hwcap->name);				\
1249		ksft_test_result_skip(#SIG"_%s\n",			\
1250					hwcap->name);			\
1251	}								\
1252									\
1253	uninstall_sigaction(NUM);					\
1254	return seen_##SIG;						\
1255}
1256
1257DEF_INST_RAISE_SIG(sigill, SIGILL);
1258DEF_INST_RAISE_SIG(sigbus, SIGBUS);
1259
1260int main(void)
1261{
1262	int i;
1263	const struct hwcap_data *hwcap;
1264	bool have_cpuinfo, have_hwcap, raise_sigill;
1265
1266	ksft_print_header();
1267	ksft_set_plan(ARRAY_SIZE(hwcaps) * TESTS_PER_HWCAP);
1268
1269	for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
1270		hwcap = &hwcaps[i];
1271
1272		have_hwcap = getauxval(hwcap->at_hwcap) & hwcap->hwcap_bit;
1273		have_cpuinfo = cpuinfo_present(hwcap->cpuinfo);
1274
1275		if (have_hwcap)
1276			ksft_print_msg("%s present\n", hwcap->name);
1277
1278		ksft_test_result(have_hwcap == have_cpuinfo,
1279				 "cpuinfo_match_%s\n", hwcap->name);
1280
1281		/*
1282		 * Testing for SIGBUS only makes sense after make sure
1283		 * that the instruction does not cause a SIGILL signal.
1284		 */
1285		raise_sigill = inst_raise_sigill(hwcap, have_hwcap);
1286		if (!raise_sigill)
1287			inst_raise_sigbus(hwcap, have_hwcap);
1288		else
1289			ksft_test_result_skip("sigbus_%s\n", hwcap->name);
1290	}
1291
1292	ksft_print_cnts();
1293
1294	return 0;
1295}
~/ Read-only file preview.