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