Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/arm64/abi/hwcap.c
26292 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 <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
41
static void aes_sigill(void)
42
{
43
/* AESE V0.16B, V0.16B */
44
asm volatile(".inst 0x4e284800" : : : );
45
}
46
47
static void atomics_sigill(void)
48
{
49
/* STADD W0, [SP] */
50
asm volatile(".inst 0xb82003ff" : : : );
51
}
52
53
static void cmpbr_sigill(void)
54
{
55
/* Not implemented, too complicated and unreliable anyway */
56
}
57
58
59
static void crc32_sigill(void)
60
{
61
/* CRC32W W0, W0, W1 */
62
asm volatile(".inst 0x1ac14800" : : : );
63
}
64
65
static void cssc_sigill(void)
66
{
67
/* CNT x0, x0 */
68
asm volatile(".inst 0xdac01c00" : : : "x0");
69
}
70
71
static void f8cvt_sigill(void)
72
{
73
/* FSCALE V0.4H, V0.4H, V0.4H */
74
asm volatile(".inst 0x2ec03c00");
75
}
76
77
static void f8dp2_sigill(void)
78
{
79
/* FDOT V0.4H, V0.4H, V0.5H */
80
asm volatile(".inst 0xe40fc00");
81
}
82
83
static void f8dp4_sigill(void)
84
{
85
/* FDOT V0.2S, V0.2S, V0.2S */
86
asm volatile(".inst 0xe00fc00");
87
}
88
89
static void f8fma_sigill(void)
90
{
91
/* FMLALB V0.8H, V0.16B, V0.16B */
92
asm volatile(".inst 0xec0fc00");
93
}
94
95
static void f8mm4_sigill(void)
96
{
97
/* FMMLA V0.4SH, V0.16B, V0.16B */
98
asm volatile(".inst 0x6e00ec00");
99
}
100
101
static void f8mm8_sigill(void)
102
{
103
/* FMMLA V0.4S, V0.16B, V0.16B */
104
asm volatile(".inst 0x6e80ec00");
105
}
106
107
static void faminmax_sigill(void)
108
{
109
/* FAMIN V0.4H, V0.4H, V0.4H */
110
asm volatile(".inst 0x2ec01c00");
111
}
112
113
static void fp_sigill(void)
114
{
115
asm volatile("fmov s0, #1");
116
}
117
118
static void fpmr_sigill(void)
119
{
120
asm volatile("mrs x0, S3_3_C4_C4_2" : : : "x0");
121
}
122
123
static void fprcvt_sigill(void)
124
{
125
/* FCVTAS S0, H0 */
126
asm volatile(".inst 0x1efa0000");
127
}
128
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
140
static void ilrcpc_sigill(void)
141
{
142
/* LDAPUR W0, [SP, #8] */
143
asm volatile(".inst 0x994083e0" : : : );
144
}
145
146
static void jscvt_sigill(void)
147
{
148
/* FJCVTZS W0, D0 */
149
asm volatile(".inst 0x1e7e0000" : : : );
150
}
151
152
static void lrcpc_sigill(void)
153
{
154
/* LDAPR W0, [SP, #0] */
155
asm volatile(".inst 0xb8bfc3e0" : : : );
156
}
157
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
172
static void lut_sigill(void)
173
{
174
/* LUTI2 V0.16B, { V0.16B }, V[0] */
175
asm volatile(".inst 0x4e801000");
176
}
177
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
192
static void pmull_sigill(void)
193
{
194
/* PMULL V0.1Q, V0.1D, V0.1D */
195
asm volatile(".inst 0x0ee0e000" : : : );
196
}
197
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
204
static void rng_sigill(void)
205
{
206
asm volatile("mrs x0, S3_3_C2_C4_0" : : : "x0");
207
}
208
209
static void sha1_sigill(void)
210
{
211
/* SHA1H S0, S0 */
212
asm volatile(".inst 0x5e280800" : : : );
213
}
214
215
static void sha2_sigill(void)
216
{
217
/* SHA256H Q0, Q0, V0.4S */
218
asm volatile(".inst 0x5e004000" : : : );
219
}
220
221
static void sha512_sigill(void)
222
{
223
/* SHA512H Q0, Q0, V0.2D */
224
asm volatile(".inst 0xce608000" : : : );
225
}
226
227
static void sme_sigill(void)
228
{
229
/* RDSVL x0, #0 */
230
asm volatile(".inst 0x04bf5800" : : : "x0");
231
}
232
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
449
static void sve_sigill(void)
450
{
451
/* RDVL x0, #0 */
452
asm volatile(".inst 0x04bf5000" : : : "x0");
453
}
454
455
static void sve2_sigill(void)
456
{
457
/* SQABS Z0.b, P0/M, Z0.B */
458
asm volatile(".inst 0x4408A000" : : : "z0");
459
}
460
461
static void sve2p1_sigill(void)
462
{
463
/* BFADD Z0.H, Z0.H, Z0.H */
464
asm volatile(".inst 0x65000000" : : : "z0");
465
}
466
467
static void sve2p2_sigill(void)
468
{
469
/* NOT Z0.D, P0/Z, Z0.D */
470
asm volatile(".inst 0x4cea000" : : : "z0");
471
}
472
473
static void sveaes_sigill(void)
474
{
475
/* AESD z0.b, z0.b, z0.b */
476
asm volatile(".inst 0x4522e400" : : : "z0");
477
}
478
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
485
static void sveb16b16_sigill(void)
486
{
487
/* BFADD Z0.H, Z0.H, Z0.H */
488
asm volatile(".inst 0x65000000" : : : );
489
}
490
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
497
static void svef16mm_sigill(void)
498
{
499
/* FMMLA Z0.S, Z0.H, Z0.H */
500
asm volatile(".inst 0x6420e400");
501
}
502
503
static void svepmull_sigill(void)
504
{
505
/* PMULLB Z0.Q, Z0.D, Z0.D */
506
asm volatile(".inst 0x45006800" : : : "z0");
507
}
508
509
static void svebitperm_sigill(void)
510
{
511
/* BDEP Z0.B, Z0.B, Z0.B */
512
asm volatile(".inst 0x4500b400" : : : "z0");
513
}
514
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
521
static void sveeltperm_sigill(void)
522
{
523
/* COMPACT Z0.B, P0, Z0.B */
524
asm volatile(".inst 0x5218000" : : : "x0");
525
}
526
527
static void svesm4_sigill(void)
528
{
529
/* SM4E Z0.S, Z0.S, Z0.S */
530
asm volatile(".inst 0x4523e000" : : : "z0");
531
}
532
533
static void svei8mm_sigill(void)
534
{
535
/* USDOT Z0.S, Z0.B, Z0.B[0] */
536
asm volatile(".inst 0x44a01800" : : : "z0");
537
}
538
539
static void svef32mm_sigill(void)
540
{
541
/* FMMLA Z0.S, Z0.S, Z0.S */
542
asm volatile(".inst 0x64a0e400" : : : "z0");
543
}
544
545
static void svef64mm_sigill(void)
546
{
547
/* FMMLA Z0.D, Z0.D, Z0.D */
548
asm volatile(".inst 0x64e0e400" : : : "z0");
549
}
550
551
static void svebf16_sigill(void)
552
{
553
/* BFCVT Z0.H, P0/M, Z0.S */
554
asm volatile(".inst 0x658aa000" : : : "z0");
555
}
556
557
static void hbc_sigill(void)
558
{
559
/* BC.EQ +4 */
560
asm volatile("cmp xzr, xzr\n"
561
".inst 0x54000030" : : : "cc");
562
}
563
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
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
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
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
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
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
1277