~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/arm64/abi/hwcap.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 /*
 25  * Function expected to generate exception when the feature is not
 26  * supported and return when it is supported. If the specific exception
 27  * is generated then the handler must be able to skip over the
 28  * instruction safely.
 29  *
 30  * Note that it is expected that for many architecture extensions
 31  * there are no specific traps due to no architecture state being
 32  * added so we may not fault if running on a kernel which doesn't know
 33  * to add the hwcap.
 34  */
 35 typedef void (*sig_fn)(void);
 36 
 37 static void aes_sigill(void)
 38 {
 39         /* AESE V0.16B, V0.16B */
 40         asm volatile(".inst 0x4e284800" : : : );
 41 }
 42 
 43 static void atomics_sigill(void)
 44 {
 45         /* STADD W0, [SP] */
 46         asm volatile(".inst 0xb82003ff" : : : );
 47 }
 48 
 49 static void crc32_sigill(void)
 50 {
 51         /* CRC32W W0, W0, W1 */
 52         asm volatile(".inst 0x1ac14800" : : : );
 53 }
 54 
 55 static void cssc_sigill(void)
 56 {
 57         /* CNT x0, x0 */
 58         asm volatile(".inst 0xdac01c00" : : : "x0");
 59 }
 60 
 61 static void f8cvt_sigill(void)
 62 {
 63         /* FSCALE V0.4H, V0.4H, V0.4H */
 64         asm volatile(".inst 0x2ec03c00");
 65 }
 66 
 67 static void f8dp2_sigill(void)
 68 {
 69         /* FDOT V0.4H, V0.4H, V0.5H */
 70         asm volatile(".inst 0xe40fc00");
 71 }
 72 
 73 static void f8dp4_sigill(void)
 74 {
 75         /* FDOT V0.2S, V0.2S, V0.2S */
 76         asm volatile(".inst 0xe00fc00");
 77 }
 78 
 79 static void f8fma_sigill(void)
 80 {
 81         /* FMLALB V0.8H, V0.16B, V0.16B */
 82         asm volatile(".inst 0xec0fc00");
 83 }
 84 
 85 static void faminmax_sigill(void)
 86 {
 87         /* FAMIN V0.4H, V0.4H, V0.4H */
 88         asm volatile(".inst 0x2ec01c00");
 89 }
 90 
 91 static void fp_sigill(void)
 92 {
 93         asm volatile("fmov s0, #1");
 94 }
 95 
 96 static void fpmr_sigill(void)
 97 {
 98         asm volatile("mrs x0, S3_3_C4_C4_2" : : : "x0");
 99 }
100 
101 static void ilrcpc_sigill(void)
102 {
103         /* LDAPUR W0, [SP, #8] */
104         asm volatile(".inst 0x994083e0" : : : );
105 }
106 
107 static void jscvt_sigill(void)
108 {
109         /* FJCVTZS W0, D0 */
110         asm volatile(".inst 0x1e7e0000" : : : );
111 }
112 
113 static void lrcpc_sigill(void)
114 {
115         /* LDAPR W0, [SP, #0] */
116         asm volatile(".inst 0xb8bfc3e0" : : : );
117 }
118 
119 static void lse128_sigill(void)
120 {
121         u64 __attribute__ ((aligned (16))) mem[2] = { 10, 20 };
122         register u64 *memp asm ("x0") = mem;
123         register u64 val0 asm ("x1") = 5;
124         register u64 val1 asm ("x2") = 4;
125 
126         /* SWPP X1, X2, [X0] */
127         asm volatile(".inst 0x19228001"
128                      : "+r" (memp), "+r" (val0), "+r" (val1)
129                      :
130                      : "cc", "memory");
131 }
132 
133 static void lut_sigill(void)
134 {
135         /* LUTI2 V0.16B, { V0.16B }, V[0] */
136         asm volatile(".inst 0x4e801000");
137 }
138 
139 static void mops_sigill(void)
140 {
141         char dst[1], src[1];
142         register char *dstp asm ("x0") = dst;
143         register char *srcp asm ("x1") = src;
144         register long size asm ("x2") = 1;
145 
146         /* CPYP [x0]!, [x1]!, x2! */
147         asm volatile(".inst 0x1d010440"
148                      : "+r" (dstp), "+r" (srcp), "+r" (size)
149                      :
150                      : "cc", "memory");
151 }
152 
153 static void pmull_sigill(void)
154 {
155         /* PMULL V0.1Q, V0.1D, V0.1D */
156         asm volatile(".inst 0x0ee0e000" : : : );
157 }
158 
159 static void rng_sigill(void)
160 {
161         asm volatile("mrs x0, S3_3_C2_C4_0" : : : "x0");
162 }
163 
164 static void sha1_sigill(void)
165 {
166         /* SHA1H S0, S0 */
167         asm volatile(".inst 0x5e280800" : : : );
168 }
169 
170 static void sha2_sigill(void)
171 {
172         /* SHA256H Q0, Q0, V0.4S */
173         asm volatile(".inst 0x5e004000" : : : );
174 }
175 
176 static void sha512_sigill(void)
177 {
178         /* SHA512H Q0, Q0, V0.2D */
179         asm volatile(".inst 0xce608000" : : : );
180 }
181 
182 static void sme_sigill(void)
183 {
184         /* RDSVL x0, #0 */
185         asm volatile(".inst 0x04bf5800" : : : "x0");
186 }
187 
188 static void sme2_sigill(void)
189 {
190         /* SMSTART ZA */
191         asm volatile("msr S0_3_C4_C5_3, xzr" : : : );
192 
193         /* ZERO ZT0 */
194         asm volatile(".inst 0xc0480001" : : : );
195 
196         /* SMSTOP */
197         asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
198 }
199 
200 static void sme2p1_sigill(void)
201 {
202         /* SMSTART SM */
203         asm volatile("msr S0_3_C4_C3_3, xzr" : : : );
204 
205         /* BFCLAMP { Z0.H - Z1.H }, Z0.H, Z0.H */
206         asm volatile(".inst 0xc120C000" : : : );
207 
208         /* SMSTOP */
209         asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
210 }
211 
212 static void smei16i32_sigill(void)
213 {
214         /* SMSTART */
215         asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
216 
217         /* SMOPA ZA0.S, P0/M, P0/M, Z0.B, Z0.B */
218         asm volatile(".inst 0xa0800000" : : : );
219 
220         /* SMSTOP */
221         asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
222 }
223 
224 static void smebi32i32_sigill(void)
225 {
226         /* SMSTART */
227         asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
228 
229         /* BMOPA ZA0.S, P0/M, P0/M, Z0.B, Z0.B */
230         asm volatile(".inst 0x80800008" : : : );
231 
232         /* SMSTOP */
233         asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
234 }
235 
236 static void smeb16b16_sigill(void)
237 {
238         /* SMSTART */
239         asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
240 
241         /* BFADD ZA.H[W0, 0], {Z0.H-Z1.H} */
242         asm volatile(".inst 0xC1E41C00" : : : );
243 
244         /* SMSTOP */
245         asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
246 }
247 
248 static void smef16f16_sigill(void)
249 {
250         /* SMSTART */
251         asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
252 
253         /* FADD ZA.H[W0, 0], { Z0.H-Z1.H } */
254         asm volatile(".inst 0xc1a41C00" : : : );
255 
256         /* SMSTOP */
257         asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
258 }
259 
260 static void smef8f16_sigill(void)
261 {
262         /* SMSTART */
263         asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
264 
265         /* FDOT ZA.H[W0, 0], Z0.B-Z1.B, Z0.B-Z1.B */
266         asm volatile(".inst 0xc1a01020" : : : );
267 
268         /* SMSTOP */
269         asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
270 }
271 
272 static void smef8f32_sigill(void)
273 {
274         /* SMSTART */
275         asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
276 
277         /* FDOT ZA.S[W0, 0], { Z0.B-Z1.B }, Z0.B[0] */
278         asm volatile(".inst 0xc1500038" : : : );
279 
280         /* SMSTOP */
281         asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
282 }
283 
284 static void smelutv2_sigill(void)
285 {
286         /* SMSTART */
287         asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
288 
289         /* LUTI4 { Z0.B-Z3.B }, ZT0, { Z0-Z1 } */
290         asm volatile(".inst 0xc08b0000" : : : );
291 
292         /* SMSTOP */
293         asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
294 }
295 
296 static void smesf8dp2_sigill(void)
297 {
298         /* SMSTART */
299         asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
300 
301         /* FDOT Z0.H, Z0.B, Z0.B[0] */
302         asm volatile(".inst 0x64204400" : : : );
303 
304         /* SMSTOP */
305         asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
306 }
307 
308 static void smesf8dp4_sigill(void)
309 {
310         /* SMSTART */
311         asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
312 
313         /* FDOT Z0.S, Z0.B, Z0.B[0] */
314         asm volatile(".inst 0xc1a41C00" : : : );
315 
316         /* SMSTOP */
317         asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
318 }
319 
320 static void smesf8fma_sigill(void)
321 {
322         /* SMSTART */
323         asm volatile("msr S0_3_C4_C7_3, xzr" : : : );
324 
325         /* FMLALB V0.8H, V0.16B, V0.16B */
326         asm volatile(".inst 0xec0fc00");
327 
328         /* SMSTOP */
329         asm volatile("msr S0_3_C4_C6_3, xzr" : : : );
330 }
331 
332 static void sve_sigill(void)
333 {
334         /* RDVL x0, #0 */
335         asm volatile(".inst 0x04bf5000" : : : "x0");
336 }
337 
338 static void sve2_sigill(void)
339 {
340         /* SQABS Z0.b, P0/M, Z0.B */
341         asm volatile(".inst 0x4408A000" : : : "z0");
342 }
343 
344 static void sve2p1_sigill(void)
345 {
346         /* BFADD Z0.H, Z0.H, Z0.H */
347         asm volatile(".inst 0x65000000" : : : "z0");
348 }
349 
350 static void sveaes_sigill(void)
351 {
352         /* AESD z0.b, z0.b, z0.b */
353         asm volatile(".inst 0x4522e400" : : : "z0");
354 }
355 
356 static void sveb16b16_sigill(void)
357 {
358         /* BFADD ZA.H[W0, 0], {Z0.H-Z1.H} */
359         asm volatile(".inst 0xC1E41C00" : : : );
360 }
361 
362 static void svepmull_sigill(void)
363 {
364         /* PMULLB Z0.Q, Z0.D, Z0.D */
365         asm volatile(".inst 0x45006800" : : : "z0");
366 }
367 
368 static void svebitperm_sigill(void)
369 {
370         /* BDEP Z0.B, Z0.B, Z0.B */
371         asm volatile(".inst 0x4500b400" : : : "z0");
372 }
373 
374 static void svesha3_sigill(void)
375 {
376         /* EOR3 Z0.D, Z0.D, Z0.D, Z0.D */
377         asm volatile(".inst 0x4203800" : : : "z0");
378 }
379 
380 static void svesm4_sigill(void)
381 {
382         /* SM4E Z0.S, Z0.S, Z0.S */
383         asm volatile(".inst 0x4523e000" : : : "z0");
384 }
385 
386 static void svei8mm_sigill(void)
387 {
388         /* USDOT Z0.S, Z0.B, Z0.B[0] */
389         asm volatile(".inst 0x44a01800" : : : "z0");
390 }
391 
392 static void svef32mm_sigill(void)
393 {
394         /* FMMLA Z0.S, Z0.S, Z0.S */
395         asm volatile(".inst 0x64a0e400" : : : "z0");
396 }
397 
398 static void svef64mm_sigill(void)
399 {
400         /* FMMLA Z0.D, Z0.D, Z0.D */
401         asm volatile(".inst 0x64e0e400" : : : "z0");
402 }
403 
404 static void svebf16_sigill(void)
405 {
406         /* BFCVT Z0.H, P0/M, Z0.S */
407         asm volatile(".inst 0x658aa000" : : : "z0");
408 }
409 
410 static void hbc_sigill(void)
411 {
412         /* BC.EQ +4 */
413         asm volatile("cmp xzr, xzr\n"
414                      ".inst 0x54000030" : : : "cc");
415 }
416 
417 static void uscat_sigbus(void)
418 {
419         /* unaligned atomic access */
420         asm volatile("ADD x1, sp, #2" : : : );
421         /* STADD W0, [X1] */
422         asm volatile(".inst 0xb820003f" : : : );
423 }
424 
425 static void lrcpc3_sigill(void)
426 {
427         int data[2] = { 1, 2 };
428 
429         register int *src asm ("x0") = data;
430         register int data0 asm ("w2") = 0;
431         register int data1 asm ("w3") = 0;
432 
433         /* LDIAPP w2, w3, [x0] */
434         asm volatile(".inst 0x99431802"
435                       : "=r" (data0), "=r" (data1) : "r" (src) :);
436 }
437 
438 static const struct hwcap_data {
439         const char *name;
440         unsigned long at_hwcap;
441         unsigned long hwcap_bit;
442         const char *cpuinfo;
443         sig_fn sigill_fn;
444         bool sigill_reliable;
445         sig_fn sigbus_fn;
446         bool sigbus_reliable;
447 } hwcaps[] = {
448         {
449                 .name = "AES",
450                 .at_hwcap = AT_HWCAP,
451                 .hwcap_bit = HWCAP_AES,
452                 .cpuinfo = "aes",
453                 .sigill_fn = aes_sigill,
454         },
455         {
456                 .name = "CRC32",
457                 .at_hwcap = AT_HWCAP,
458                 .hwcap_bit = HWCAP_CRC32,
459                 .cpuinfo = "crc32",
460                 .sigill_fn = crc32_sigill,
461         },
462         {
463                 .name = "CSSC",
464                 .at_hwcap = AT_HWCAP2,
465                 .hwcap_bit = HWCAP2_CSSC,
466                 .cpuinfo = "cssc",
467                 .sigill_fn = cssc_sigill,
468         },
469         {
470                 .name = "F8CVT",
471                 .at_hwcap = AT_HWCAP2,
472                 .hwcap_bit = HWCAP2_F8CVT,
473                 .cpuinfo = "f8cvt",
474                 .sigill_fn = f8cvt_sigill,
475         },
476         {
477                 .name = "F8DP4",
478                 .at_hwcap = AT_HWCAP2,
479                 .hwcap_bit = HWCAP2_F8DP4,
480                 .cpuinfo = "f8dp4",
481                 .sigill_fn = f8dp4_sigill,
482         },
483         {
484                 .name = "F8DP2",
485                 .at_hwcap = AT_HWCAP2,
486                 .hwcap_bit = HWCAP2_F8DP2,
487                 .cpuinfo = "f8dp4",
488                 .sigill_fn = f8dp2_sigill,
489         },
490         {
491                 .name = "F8E5M2",
492                 .at_hwcap = AT_HWCAP2,
493                 .hwcap_bit = HWCAP2_F8E5M2,
494                 .cpuinfo = "f8e5m2",
495         },
496         {
497                 .name = "F8E4M3",
498                 .at_hwcap = AT_HWCAP2,
499                 .hwcap_bit = HWCAP2_F8E4M3,
500                 .cpuinfo = "f8e4m3",
501         },
502         {
503                 .name = "F8FMA",
504                 .at_hwcap = AT_HWCAP2,
505                 .hwcap_bit = HWCAP2_F8FMA,
506                 .cpuinfo = "f8fma",
507                 .sigill_fn = f8fma_sigill,
508         },
509         {
510                 .name = "FAMINMAX",
511                 .at_hwcap = AT_HWCAP2,
512                 .hwcap_bit = HWCAP2_FAMINMAX,
513                 .cpuinfo = "faminmax",
514                 .sigill_fn = faminmax_sigill,
515         },
516         {
517                 .name = "FP",
518                 .at_hwcap = AT_HWCAP,
519                 .hwcap_bit = HWCAP_FP,
520                 .cpuinfo = "fp",
521                 .sigill_fn = fp_sigill,
522         },
523         {
524                 .name = "FPMR",
525                 .at_hwcap = AT_HWCAP2,
526                 .hwcap_bit = HWCAP2_FPMR,
527                 .cpuinfo = "fpmr",
528                 .sigill_fn = fpmr_sigill,
529                 .sigill_reliable = true,
530         },
531         {
532                 .name = "JSCVT",
533                 .at_hwcap = AT_HWCAP,
534                 .hwcap_bit = HWCAP_JSCVT,
535                 .cpuinfo = "jscvt",
536                 .sigill_fn = jscvt_sigill,
537         },
538         {
539                 .name = "LRCPC",
540                 .at_hwcap = AT_HWCAP,
541                 .hwcap_bit = HWCAP_LRCPC,
542                 .cpuinfo = "lrcpc",
543                 .sigill_fn = lrcpc_sigill,
544         },
545         {
546                 .name = "LRCPC2",
547                 .at_hwcap = AT_HWCAP,
548                 .hwcap_bit = HWCAP_ILRCPC,
549                 .cpuinfo = "ilrcpc",
550                 .sigill_fn = ilrcpc_sigill,
551         },
552         {
553                 .name = "LRCPC3",
554                 .at_hwcap = AT_HWCAP2,
555                 .hwcap_bit = HWCAP2_LRCPC3,
556                 .cpuinfo = "lrcpc3",
557                 .sigill_fn = lrcpc3_sigill,
558         },
559         {
560                 .name = "LSE",
561                 .at_hwcap = AT_HWCAP,
562                 .hwcap_bit = HWCAP_ATOMICS,
563                 .cpuinfo = "atomics",
564                 .sigill_fn = atomics_sigill,
565         },
566         {
567                 .name = "LSE2",
568                 .at_hwcap = AT_HWCAP,
569                 .hwcap_bit = HWCAP_USCAT,
570                 .cpuinfo = "uscat",
571                 .sigill_fn = atomics_sigill,
572                 .sigbus_fn = uscat_sigbus,
573                 .sigbus_reliable = true,
574         },
575         {
576                 .name = "LSE128",
577                 .at_hwcap = AT_HWCAP2,
578                 .hwcap_bit = HWCAP2_LSE128,
579                 .cpuinfo = "lse128",
580                 .sigill_fn = lse128_sigill,
581         },
582         {
583                 .name = "LUT",
584                 .at_hwcap = AT_HWCAP2,
585                 .hwcap_bit = HWCAP2_LUT,
586                 .cpuinfo = "lut",
587                 .sigill_fn = lut_sigill,
588         },
589         {
590                 .name = "MOPS",
591                 .at_hwcap = AT_HWCAP2,
592                 .hwcap_bit = HWCAP2_MOPS,
593                 .cpuinfo = "mops",
594                 .sigill_fn = mops_sigill,
595                 .sigill_reliable = true,
596         },
597         {
598                 .name = "PMULL",
599                 .at_hwcap = AT_HWCAP,
600                 .hwcap_bit = HWCAP_PMULL,
601                 .cpuinfo = "pmull",
602                 .sigill_fn = pmull_sigill,
603         },
604         {
605                 .name = "RNG",
606                 .at_hwcap = AT_HWCAP2,
607                 .hwcap_bit = HWCAP2_RNG,
608                 .cpuinfo = "rng",
609                 .sigill_fn = rng_sigill,
610         },
611         {
612                 .name = "RPRFM",
613                 .at_hwcap = AT_HWCAP2,
614                 .hwcap_bit = HWCAP2_RPRFM,
615                 .cpuinfo = "rprfm",
616         },
617         {
618                 .name = "SHA1",
619                 .at_hwcap = AT_HWCAP,
620                 .hwcap_bit = HWCAP_SHA1,
621                 .cpuinfo = "sha1",
622                 .sigill_fn = sha1_sigill,
623         },
624         {
625                 .name = "SHA2",
626                 .at_hwcap = AT_HWCAP,
627                 .hwcap_bit = HWCAP_SHA2,
628                 .cpuinfo = "sha2",
629                 .sigill_fn = sha2_sigill,
630         },
631         {
632                 .name = "SHA512",
633                 .at_hwcap = AT_HWCAP,
634                 .hwcap_bit = HWCAP_SHA512,
635                 .cpuinfo = "sha512",
636                 .sigill_fn = sha512_sigill,
637         },
638         {
639                 .name = "SME",
640                 .at_hwcap = AT_HWCAP2,
641                 .hwcap_bit = HWCAP2_SME,
642                 .cpuinfo = "sme",
643                 .sigill_fn = sme_sigill,
644                 .sigill_reliable = true,
645         },
646         {
647                 .name = "SME2",
648                 .at_hwcap = AT_HWCAP2,
649                 .hwcap_bit = HWCAP2_SME2,
650                 .cpuinfo = "sme2",
651                 .sigill_fn = sme2_sigill,
652                 .sigill_reliable = true,
653         },
654         {
655                 .name = "SME 2.1",
656                 .at_hwcap = AT_HWCAP2,
657                 .hwcap_bit = HWCAP2_SME2P1,
658                 .cpuinfo = "sme2p1",
659                 .sigill_fn = sme2p1_sigill,
660         },
661         {
662                 .name = "SME I16I32",
663                 .at_hwcap = AT_HWCAP2,
664                 .hwcap_bit = HWCAP2_SME_I16I32,
665                 .cpuinfo = "smei16i32",
666                 .sigill_fn = smei16i32_sigill,
667         },
668         {
669                 .name = "SME BI32I32",
670                 .at_hwcap = AT_HWCAP2,
671                 .hwcap_bit = HWCAP2_SME_BI32I32,
672                 .cpuinfo = "smebi32i32",
673                 .sigill_fn = smebi32i32_sigill,
674         },
675         {
676                 .name = "SME B16B16",
677                 .at_hwcap = AT_HWCAP2,
678                 .hwcap_bit = HWCAP2_SME_B16B16,
679                 .cpuinfo = "smeb16b16",
680                 .sigill_fn = smeb16b16_sigill,
681         },
682         {
683                 .name = "SME F16F16",
684                 .at_hwcap = AT_HWCAP2,
685                 .hwcap_bit = HWCAP2_SME_F16F16,
686                 .cpuinfo = "smef16f16",
687                 .sigill_fn = smef16f16_sigill,
688         },
689         {
690                 .name = "SME F8F16",
691                 .at_hwcap = AT_HWCAP2,
692                 .hwcap_bit = HWCAP2_SME_F8F16,
693                 .cpuinfo = "smef8f16",
694                 .sigill_fn = smef8f16_sigill,
695         },
696         {
697                 .name = "SME F8F32",
698                 .at_hwcap = AT_HWCAP2,
699                 .hwcap_bit = HWCAP2_SME_F8F32,
700                 .cpuinfo = "smef8f32",
701                 .sigill_fn = smef8f32_sigill,
702         },
703         {
704                 .name = "SME LUTV2",
705                 .at_hwcap = AT_HWCAP2,
706                 .hwcap_bit = HWCAP2_SME_LUTV2,
707                 .cpuinfo = "smelutv2",
708                 .sigill_fn = smelutv2_sigill,
709         },
710         {
711                 .name = "SME SF8FMA",
712                 .at_hwcap = AT_HWCAP2,
713                 .hwcap_bit = HWCAP2_SME_SF8FMA,
714                 .cpuinfo = "smesf8fma",
715                 .sigill_fn = smesf8fma_sigill,
716         },
717         {
718                 .name = "SME SF8DP2",
719                 .at_hwcap = AT_HWCAP2,
720                 .hwcap_bit = HWCAP2_SME_SF8DP2,
721                 .cpuinfo = "smesf8dp2",
722                 .sigill_fn = smesf8dp2_sigill,
723         },
724         {
725                 .name = "SME SF8DP4",
726                 .at_hwcap = AT_HWCAP2,
727                 .hwcap_bit = HWCAP2_SME_SF8DP4,
728                 .cpuinfo = "smesf8dp4",
729                 .sigill_fn = smesf8dp4_sigill,
730         },
731         {
732                 .name = "SVE",
733                 .at_hwcap = AT_HWCAP,
734                 .hwcap_bit = HWCAP_SVE,
735                 .cpuinfo = "sve",
736                 .sigill_fn = sve_sigill,
737                 .sigill_reliable = true,
738         },
739         {
740                 .name = "SVE 2",
741                 .at_hwcap = AT_HWCAP2,
742                 .hwcap_bit = HWCAP2_SVE2,
743                 .cpuinfo = "sve2",
744                 .sigill_fn = sve2_sigill,
745         },
746         {
747                 .name = "SVE 2.1",
748                 .at_hwcap = AT_HWCAP2,
749                 .hwcap_bit = HWCAP2_SVE2P1,
750                 .cpuinfo = "sve2p1",
751                 .sigill_fn = sve2p1_sigill,
752         },
753         {
754                 .name = "SVE AES",
755                 .at_hwcap = AT_HWCAP2,
756                 .hwcap_bit = HWCAP2_SVEAES,
757                 .cpuinfo = "sveaes",
758                 .sigill_fn = sveaes_sigill,
759         },
760         {
761                 .name = "SVE2 B16B16",
762                 .at_hwcap = AT_HWCAP2,
763                 .hwcap_bit = HWCAP2_SVE_B16B16,
764                 .cpuinfo = "sveb16b16",
765                 .sigill_fn = sveb16b16_sigill,
766         },
767         {
768                 .name = "SVE2 PMULL",
769                 .at_hwcap = AT_HWCAP2,
770                 .hwcap_bit = HWCAP2_SVEPMULL,
771                 .cpuinfo = "svepmull",
772                 .sigill_fn = svepmull_sigill,
773         },
774         {
775                 .name = "SVE2 BITPERM",
776                 .at_hwcap = AT_HWCAP2,
777                 .hwcap_bit = HWCAP2_SVEBITPERM,
778                 .cpuinfo = "svebitperm",
779                 .sigill_fn = svebitperm_sigill,
780         },
781         {
782                 .name = "SVE2 SHA3",
783                 .at_hwcap = AT_HWCAP2,
784                 .hwcap_bit = HWCAP2_SVESHA3,
785                 .cpuinfo = "svesha3",
786                 .sigill_fn = svesha3_sigill,
787         },
788         {
789                 .name = "SVE2 SM4",
790                 .at_hwcap = AT_HWCAP2,
791                 .hwcap_bit = HWCAP2_SVESM4,
792                 .cpuinfo = "svesm4",
793                 .sigill_fn = svesm4_sigill,
794         },
795         {
796                 .name = "SVE2 I8MM",
797                 .at_hwcap = AT_HWCAP2,
798                 .hwcap_bit = HWCAP2_SVEI8MM,
799                 .cpuinfo = "svei8mm",
800                 .sigill_fn = svei8mm_sigill,
801         },
802         {
803                 .name = "SVE2 F32MM",
804                 .at_hwcap = AT_HWCAP2,
805                 .hwcap_bit = HWCAP2_SVEF32MM,
806                 .cpuinfo = "svef32mm",
807                 .sigill_fn = svef32mm_sigill,
808         },
809         {
810                 .name = "SVE2 F64MM",
811                 .at_hwcap = AT_HWCAP2,
812                 .hwcap_bit = HWCAP2_SVEF64MM,
813                 .cpuinfo = "svef64mm",
814                 .sigill_fn = svef64mm_sigill,
815         },
816         {
817                 .name = "SVE2 BF16",
818                 .at_hwcap = AT_HWCAP2,
819                 .hwcap_bit = HWCAP2_SVEBF16,
820                 .cpuinfo = "svebf16",
821                 .sigill_fn = svebf16_sigill,
822         },
823         {
824                 .name = "SVE2 EBF16",
825                 .at_hwcap = AT_HWCAP2,
826                 .hwcap_bit = HWCAP2_SVE_EBF16,
827                 .cpuinfo = "sveebf16",
828         },
829         {
830                 .name = "HBC",
831                 .at_hwcap = AT_HWCAP2,
832                 .hwcap_bit = HWCAP2_HBC,
833                 .cpuinfo = "hbc",
834                 .sigill_fn = hbc_sigill,
835                 .sigill_reliable = true,
836         },
837 };
838 
839 typedef void (*sighandler_fn)(int, siginfo_t *, void *);
840 
841 #define DEF_SIGHANDLER_FUNC(SIG, NUM)                                   \
842 static bool seen_##SIG;                                                 \
843 static void handle_##SIG(int sig, siginfo_t *info, void *context)       \
844 {                                                                       \
845         ucontext_t *uc = context;                                       \
846                                                                         \
847         seen_##SIG = true;                                              \
848         /* Skip over the offending instruction */                       \
849         uc->uc_mcontext.pc += 4;                                        \
850 }
851 
852 DEF_SIGHANDLER_FUNC(sigill, SIGILL);
853 DEF_SIGHANDLER_FUNC(sigbus, SIGBUS);
854 
855 bool cpuinfo_present(const char *name)
856 {
857         FILE *f;
858         char buf[2048], name_space[30], name_newline[30];
859         char *s;
860 
861         /*
862          * The feature should appear with a leading space and either a
863          * trailing space or a newline.
864          */
865         snprintf(name_space, sizeof(name_space), " %s ", name);
866         snprintf(name_newline, sizeof(name_newline), " %s\n", name);
867 
868         f = fopen("/proc/cpuinfo", "r");
869         if (!f) {
870                 ksft_print_msg("Failed to open /proc/cpuinfo\n");
871                 return false;
872         }
873 
874         while (fgets(buf, sizeof(buf), f)) {
875                 /* Features: line? */
876                 if (strncmp(buf, "Features\t:", strlen("Features\t:")) != 0)
877                         continue;
878 
879                 /* All CPUs should be symmetric, don't read any more */
880                 fclose(f);
881 
882                 s = strstr(buf, name_space);
883                 if (s)
884                         return true;
885                 s = strstr(buf, name_newline);
886                 if (s)
887                         return true;
888 
889                 return false;
890         }
891 
892         ksft_print_msg("Failed to find Features in /proc/cpuinfo\n");
893         fclose(f);
894         return false;
895 }
896 
897 static int install_sigaction(int signum, sighandler_fn handler)
898 {
899         int ret;
900         struct sigaction sa;
901 
902         memset(&sa, 0, sizeof(sa));
903         sa.sa_sigaction = handler;
904         sa.sa_flags = SA_RESTART | SA_SIGINFO;
905         sigemptyset(&sa.sa_mask);
906         ret = sigaction(signum, &sa, NULL);
907         if (ret < 0)
908                 ksft_exit_fail_msg("Failed to install SIGNAL handler: %s (%d)\n",
909                                    strerror(errno), errno);
910 
911         return ret;
912 }
913 
914 static void uninstall_sigaction(int signum)
915 {
916         if (sigaction(signum, NULL, NULL) < 0)
917                 ksft_exit_fail_msg("Failed to uninstall SIGNAL handler: %s (%d)\n",
918                                    strerror(errno), errno);
919 }
920 
921 #define DEF_INST_RAISE_SIG(SIG, NUM)                                    \
922 static bool inst_raise_##SIG(const struct hwcap_data *hwcap,            \
923                                 bool have_hwcap)                        \
924 {                                                                       \
925         if (!hwcap->SIG##_fn) {                                         \
926                 ksft_test_result_skip(#SIG"_%s\n", hwcap->name);        \
927                 /* assume that it would raise exception in default */   \
928                 return true;                                            \
929         }                                                               \
930                                                                         \
931         install_sigaction(NUM, handle_##SIG);                           \
932                                                                         \
933         seen_##SIG = false;                                             \
934         hwcap->SIG##_fn();                                              \
935                                                                         \
936         if (have_hwcap) {                                               \
937                 /* Should be able to use the extension */               \
938                 ksft_test_result(!seen_##SIG,                           \
939                                 #SIG"_%s\n", hwcap->name);              \
940         } else if (hwcap->SIG##_reliable) {                             \
941                 /* Guaranteed a SIGNAL */                               \
942                 ksft_test_result(seen_##SIG,                            \
943                                 #SIG"_%s\n", hwcap->name);              \
944         } else {                                                        \
945                 /* Missing SIGNAL might be fine */                      \
946                 ksft_print_msg(#SIG"_%sreported for %s\n",              \
947                                 seen_##SIG ? "" : "not ",               \
948                                 hwcap->name);                           \
949                 ksft_test_result_skip(#SIG"_%s\n",                      \
950                                         hwcap->name);                   \
951         }                                                               \
952                                                                         \
953         uninstall_sigaction(NUM);                                       \
954         return seen_##SIG;                                              \
955 }
956 
957 DEF_INST_RAISE_SIG(sigill, SIGILL);
958 DEF_INST_RAISE_SIG(sigbus, SIGBUS);
959 
960 int main(void)
961 {
962         int i;
963         const struct hwcap_data *hwcap;
964         bool have_cpuinfo, have_hwcap, raise_sigill;
965 
966         ksft_print_header();
967         ksft_set_plan(ARRAY_SIZE(hwcaps) * TESTS_PER_HWCAP);
968 
969         for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
970                 hwcap = &hwcaps[i];
971 
972                 have_hwcap = getauxval(hwcap->at_hwcap) & hwcap->hwcap_bit;
973                 have_cpuinfo = cpuinfo_present(hwcap->cpuinfo);
974 
975                 if (have_hwcap)
976                         ksft_print_msg("%s present\n", hwcap->name);
977 
978                 ksft_test_result(have_hwcap == have_cpuinfo,
979                                  "cpuinfo_match_%s\n", hwcap->name);
980 
981                 /*
982                  * Testing for SIGBUS only makes sense after make sure
983                  * that the instruction does not cause a SIGILL signal.
984                  */
985                 raise_sigill = inst_raise_sigill(hwcap, have_hwcap);
986                 if (!raise_sigill)
987                         inst_raise_sigbus(hwcap, have_hwcap);
988                 else
989                         ksft_test_result_skip("sigbus_%s\n", hwcap->name);
990         }
991 
992         ksft_print_cnts();
993 
994         return 0;
995 }
996 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php