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