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