xref: /xnu-12377.61.12/tests/arm_cpu_capabilities.c (revision 4d495c6e23c53686cf65f45067f79024cf5dcee8)
1 /*
2  * Copyright (c) 2020 Apple Computer, Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #include <cpu_capabilities_public.h>
30 #include <darwintest.h>
31 #include <machine/cpu_capabilities.h>
32 #include <stdlib.h>
33 #include <sys/sysctl.h>
34 
35 #include "exc_helpers.h"
36 
37 T_GLOBAL_META(
38 	T_META_NAMESPACE("xnu.arm"),
39 	T_META_RADAR_COMPONENT_NAME("xnu"),
40 	T_META_RADAR_COMPONENT_VERSION("arm"),
41 	T_META_OWNER("ghackmann"),
42 	T_META_RUN_CONCURRENTLY(true),
43 	T_META_TAG("SoCSpecific")
44 	);
45 
46 static volatile bool cap_usable;
47 
48 static size_t
bad_instruction_handler(mach_port_t task __unused,mach_port_t thread __unused,exception_type_t type __unused,mach_exception_data_t codes __unused,uint64_t exception_pc __unused)49 bad_instruction_handler(mach_port_t task __unused, mach_port_t thread __unused,
50     exception_type_t type __unused, mach_exception_data_t codes __unused,
51     uint64_t exception_pc __unused)
52 {
53 	cap_usable = false;
54 	return 4;
55 }
56 
57 static void
try_fp16(void)58 try_fp16(void)
59 {
60 	asm volatile (
61                 "fmov	h0, #0" "\n"
62                 :
63                 :
64                 : "v0"
65         );
66 }
67 
68 static void
try_atomics(void)69 try_atomics(void)
70 {
71 	uint64_t dword;
72 	asm volatile (
73                 "swp	xzr, xzr, [%[dword]]"
74                 :
75                 : [dword]"r"(&dword)
76         );
77 }
78 
79 static void
try_crc32(void)80 try_crc32(void)
81 {
82 	asm volatile ( "crc32b	wzr, wzr, wzr");
83 }
84 
85 static void
try_fhm(void)86 try_fhm(void)
87 {
88 	asm volatile (
89                 "fmov	d0, #0"                 "\n"
90                 "fmlal	v0.2s, v0.2h, v0.2h"    "\n"
91                 :
92                 :
93                 : "v0"
94         );
95 }
96 
97 static void
try_sha512(void)98 try_sha512(void)
99 {
100 	asm volatile (
101                 "fmov		d0, #0"                 "\n"
102                 "fmov		d1, #0"                 "\n"
103                 "sha512h	q0, q0, v0.2d"          "\n"
104                 :
105                 :
106                 : "v0"
107         );
108 }
109 
110 static void
try_sha3(void)111 try_sha3(void)
112 {
113 	asm volatile (
114                 "fmov	d0, #0"                         "\n"
115                 "fmov	d1, #0"                         "\n"
116                 "eor3	v0.16b, v0.16b, v0.16b, v0.16b" "\n"
117                 :
118                 :
119                 : "v0"
120         );
121 }
122 
123 static void
try_sha1(void)124 try_sha1(void)
125 {
126 	asm volatile (
127                 "fmov		s0, #0"         "\n"
128                 "sha1h		s0, s0"         "\n"
129                 :
130                 :
131                 : "v0"
132         );
133 }
134 
135 static void
try_pmull(void)136 try_pmull(void)
137 {
138 	asm volatile (
139                 "fmov	d0, #0"                 "\n"
140                 "pmull	v0.1q, v0.1d, v0.1d"    "\n"
141                 :
142                 :
143                 : "v0"
144         );
145 }
146 
147 static void
try_aes(void)148 try_aes(void)
149 {
150 	asm volatile (
151                 "fmov		d0, #0"                 "\n"
152                 "fmov		d1, #0"                 "\n"
153                 "aesd		v0.16B, v0.16B"         "\n"
154                 :
155                 :
156                 : "v0"
157         );
158 }
159 
160 
161 static void
try_sha256(void)162 try_sha256(void)
163 {
164 	asm volatile (
165                 "fmov           d0, #0"                 "\n"
166                 "fmov           d1, #0"                 "\n"
167                 "sha256h        q0, q0, v0.4s"          "\n"
168                 :
169                 :
170                 : "v0"
171         );
172 }
173 
174 
175 static void
try_compnum(void)176 try_compnum(void)
177 {
178 	asm volatile (
179                 "fmov	d0, #0"                         "\n"
180                 "fcadd	v0.2s, v0.2s, v0.2s, #90"       "\n"
181                 :
182                 :
183                 : "v0"
184         );
185 }
186 
187 
188 static void
try_flagm(void)189 try_flagm(void)
190 {
191 	asm volatile (
192                 "cfinv"        "\n"
193                 "cfinv"        "\n"
194         );
195 }
196 
197 static void
try_flagm2(void)198 try_flagm2(void)
199 {
200 	asm volatile (
201                 "axflag"        "\n"
202                 "xaflag"        "\n"
203         );
204 }
205 
206 static void
try_dotprod(void)207 try_dotprod(void)
208 {
209 	asm volatile (
210                 "udot v0.4S,v1.16B,v2.16B"
211                 :
212                 :
213                 : "v0"
214         );
215 }
216 
217 static void
try_rdm(void)218 try_rdm(void)
219 {
220 	asm volatile (
221                 "sqrdmlah s0, s1, s2"
222                 :
223                 :
224                 : "s0"
225         );
226 }
227 
228 static void
try_sb(void)229 try_sb(void)
230 {
231 	asm volatile (
232                 "sb"
233         );
234 }
235 
236 static void
try_frintts(void)237 try_frintts(void)
238 {
239 	asm volatile (
240                 "frint32x s0, s0"
241                 :
242                 :
243                 : "s0"
244         );
245 }
246 
247 static void
try_jscvt(void)248 try_jscvt(void)
249 {
250 	asm volatile (
251                 "fmov	d0, #0"      "\n"
252                 "fjcvtzs w1, d0"     "\n"
253                 :
254                 :
255                 : "w1", "d0"
256         );
257 }
258 
259 static void
try_pauth(void)260 try_pauth(void)
261 {
262 	asm volatile (
263                 "pacga x0, x0, x0"
264                 :
265                 :
266                 : "x0"
267         );
268 }
269 
270 static void
try_dpb(void)271 try_dpb(void)
272 {
273 	int x;
274 	asm volatile (
275                 "dc cvap, %0"
276                 :
277                 : "r" (&x)
278         );
279 }
280 
281 static void
try_dpb2(void)282 try_dpb2(void)
283 {
284 	int x;
285 	asm volatile (
286                 "dc cvadp, %0"
287                 :
288                 : "r" (&x)
289         );
290 }
291 
292 static void
try_lrcpc(void)293 try_lrcpc(void)
294 {
295 	int x;
296 	asm volatile (
297                 "ldaprb w0, [%0]"
298                 :
299                 : "r" (&x)
300                 : "w0"
301         );
302 }
303 
304 static void
try_lrcpc2(void)305 try_lrcpc2(void)
306 {
307 	int x;
308 	asm volatile (
309                 "ldapurb w0, [%0]"
310                 :
311                 : "r" (&x)
312                 : "w0"
313         );
314 }
315 
316 
317 static void
try_specres(void)318 try_specres(void)
319 {
320 	int x;
321 	asm volatile (
322                 "cfp rctx, %0"
323                 :
324                 : "r" (&x)
325         );
326 }
327 
328 static void
try_bf16(void)329 try_bf16(void)
330 {
331 	asm volatile (
332                 "bfdot v0.4S,v1.8H,v2.8H"
333                 :
334                 :
335                 : "v0"
336         );
337 }
338 
339 static void
try_i8mm(void)340 try_i8mm(void)
341 {
342 	asm volatile (
343                 "sudot v0.4S,v1.16B,v2.4B[0]"
344                 :
345                 :
346                 : "v0"
347         );
348 }
349 
350 static void
try_ecv(void)351 try_ecv(void)
352 {
353 	/*
354 	 * These registers are present only when FEAT_ECV is implemented.
355 	 * Otherwise, direct accesses to CNTPCTSS_EL0 or CNTVCTSS_EL0 are UNDEFINED.
356 	 */
357 	(void)__builtin_arm_rsr64("CNTPCTSS_EL0");
358 	(void)__builtin_arm_rsr64("CNTVCTSS_EL0");
359 }
360 
361 static void
try_afp(void)362 try_afp(void)
363 {
364 	/*
365 	 * FEAT_AFP can be detected via three new FPCR bits which were
366 	 * previously marked read-as-zero.
367 	 */
368 	const uint64_t FPCR_AFP_FLAGS = (1 << 0) | (1 << 1) | (1 << 2);
369 
370 	uint64_t old_fpcr = __builtin_arm_rsr64("FPCR");
371 	__builtin_arm_wsr64("FPCR", old_fpcr | FPCR_AFP_FLAGS);
372 	uint64_t new_fpcr = __builtin_arm_rsr64("FPCR");
373 	__builtin_arm_wsr64("FPCR", old_fpcr);
374 
375 	if ((new_fpcr & FPCR_AFP_FLAGS) != FPCR_AFP_FLAGS) {
376 		cap_usable = false;
377 	}
378 }
379 
380 static void
try_rpres(void)381 try_rpres(void)
382 {
383 	/*
384 	 * When FEAT_RPRES is enabled via FPCR.AH, floating-point reciprocal
385 	 * estimate instructions increase precision from 8 mantissa bits to 12
386 	 * mantissa bits.  This can be detected by estimating 1/10.0 (which has
387 	 * no exact floating-point representation) and checking bits 11-14.
388 	 */
389 	const uint64_t FPCR_AH = (1 << 1);
390 	const uint32_t EXTRA_MANTISSA_BITS = (0xf << 11);
391 
392 	uint32_t recip;
393 	uint64_t old_fpcr = __builtin_arm_rsr64("FPCR");
394 	__builtin_arm_wsr64("FPCR", old_fpcr | FPCR_AH);
395 	asm volatile (
396                 "fmov	s0, #10.0"      "\n"
397                 "frecpe s0, s0"         "\n"
398                 "fmov   %w0, s0"        "\n"
399                 : "=r"(recip)
400                 :
401                 : "s0"
402         );
403 	__builtin_arm_wsr64("FPCR", old_fpcr);
404 
405 	if ((recip & EXTRA_MANTISSA_BITS) == 0) {
406 		cap_usable = false;
407 	}
408 }
409 
410 __attribute__((target("wfxt")))
411 static void
try_wfxt(void)412 try_wfxt(void)
413 {
414 	asm volatile ("wfet xzr");
415 }
416 
417 static void
try_sme(void)418 try_sme(void)
419 {
420 	asm volatile (
421                "rdsvl	x0, #1"
422                :
423                :
424                : "x0"
425         );
426 }
427 
428 static void
try_sme2(void)429 try_sme2(void)
430 {
431 	asm volatile (
432                "smstart za"             "\n"
433                "zero    { zt0 }"        "\n"
434                "smstop  za"             "\n"
435         );
436 }
437 
438 static void
try_sme_f32f32(void)439 try_sme_f32f32(void)
440 {
441 	asm volatile (
442                "smstart"                                "\n"
443                "fmopa   za0.s, p0/m, p0/m, z0.s, z0.s"  "\n"
444                "smstop"                                 "\n"
445         );
446 }
447 
448 static void
try_sme_bi32i32(void)449 try_sme_bi32i32(void)
450 {
451 	asm volatile (
452                "smstart"                                "\n"
453                "bmopa   za0.s, p0/m, p0/m, z0.s, z0.s"  "\n"
454                "smstop"                                 "\n"
455         );
456 }
457 
458 static void
try_sme_b16f32(void)459 try_sme_b16f32(void)
460 {
461 	asm volatile (
462                "smstart"                                "\n"
463                "bfmopa  za0.s, p0/m, p0/m, z0.h, z0.h"  "\n"
464                "smstop"                                 "\n"
465         );
466 }
467 
468 static void
try_sme_f16f32(void)469 try_sme_f16f32(void)
470 {
471 	asm volatile (
472                "smstart"                                "\n"
473                "fmopa   za0.s, p0/m, p0/m, z0.h, z0.h"  "\n"
474                "smstop"                                 "\n"
475         );
476 }
477 
478 static void
try_sme_i8i32(void)479 try_sme_i8i32(void)
480 {
481 	asm volatile (
482                "smstart"                                "\n"
483                "smopa   za0.s, p0/m, p0/m, z0.b, z0.b"  "\n"
484                "smstop"                                 "\n"
485         );
486 }
487 
488 static void
try_sme_i16i32(void)489 try_sme_i16i32(void)
490 {
491 	asm volatile (
492                "smstart"                                "\n"
493                "smopa   za0.s, p0/m, p0/m, z0.h, z0.h"  "\n"
494                "smstop"                                 "\n"
495         );
496 }
497 
498 __attribute__((target("sme-f64f64")))
499 static void
try_sme_f64f64(void)500 try_sme_f64f64(void)
501 {
502 	asm volatile (
503                "smstart"                                "\n"
504                "fmopa   za0.d, p0/m, p0/m, z0.d, z0.d"  "\n"
505                "smstop"                                 "\n"
506         );
507 }
508 
509 __attribute__((target("sme-i16i64")))
510 static void
try_sme_i16i64(void)511 try_sme_i16i64(void)
512 {
513 	asm volatile (
514                "smstart"                                "\n"
515                "smopa   za0.d, p0/m, p0/m, z0.h, z0.h"  "\n"
516                "smstop"                                 "\n"
517         );
518 }
519 
520 __attribute__((target("sme2p1")))
521 static void
try_sme2p1(void)522 try_sme2p1(void)
523 {
524 	asm volatile (
525                 "mov    x8, #0"                 "\n"
526                 "smstart"                       "\n"
527                 "zero   za.d[w8, #0, VGx2]"     "\n"
528                 "smstop"                        "\n"
529                 :
530                 :
531                 : "x8"
532         );
533 }
534 
535 __attribute__((target("sme2p1,sme-f16f16")))
536 static void
try_sme_f16f16(void)537 try_sme_f16f16(void)
538 {
539 	asm volatile (
540                "smstart"                                "\n"
541                "fmopa   za0.h, p0/m, p0/m, z0.h, z0.h"  "\n"
542                "smstop"                                 "\n"
543         );
544 }
545 
546 __attribute__((target("sme2p1,b16b16,sme-b16b16")))
547 static void
try_sme_b16b16(void)548 try_sme_b16b16(void)
549 {
550 	asm volatile (
551                "smstart"                                "\n"
552                "bfmopa  za0.h, p0/m, p0/m, z0.h, z0.h"  "\n"
553                "smstop"                                 "\n"
554         );
555 }
556 
557 
558 static void
try_fpexcp(void)559 try_fpexcp(void)
560 {
561 	/* FP Exceptions are supported if all exceptions bit can be set. */
562 	const uint64_t flags = (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) | (1 << 15);
563 
564 	uint64_t old_fpcr = __builtin_arm_rsr64("FPCR");
565 	__builtin_arm_wsr64("FPCR", old_fpcr | flags);
566 	uint64_t new_fpcr = __builtin_arm_rsr64("FPCR");
567 	__builtin_arm_wsr64("FPCR", old_fpcr);
568 
569 	if ((new_fpcr & flags) != flags) {
570 		cap_usable = false;
571 	}
572 }
573 
574 static void
try_dit(void)575 try_dit(void)
576 {
577 	asm volatile (
578                 "msr DIT, x0"
579                 :
580                 :
581                 : "x0"
582         );
583 }
584 
585 static mach_port_t exc_port;
586 
587 static uint8_t hw_optional_arm_caps[(CAP_BIT_NB + 7) / 8];
588 
589 static void
test_cpu_capability(const char * cap_name,uint64_t commpage_flag,const char * cap_sysctl,int cap_bit,void (* try_cpu_capability)(void))590 test_cpu_capability(const char *cap_name, uint64_t commpage_flag, const char *cap_sysctl, int cap_bit, void (*try_cpu_capability)(void))
591 {
592 	bool has_commpage_flag = commpage_flag != 0;
593 	uint64_t commpage_caps = _get_cpu_capabilities();
594 	bool commpage_flag_set = false;
595 	if (has_commpage_flag) {
596 		commpage_flag_set = (commpage_caps & commpage_flag);
597 	}
598 
599 	bool has_sysctl = cap_sysctl != NULL;
600 	int sysctl_val;
601 	bool sysctl_flag_set = false;
602 	if (has_sysctl) {
603 		size_t sysctl_size = sizeof(sysctl_val);
604 		int err = sysctlbyname(cap_sysctl, &sysctl_val, &sysctl_size, NULL, 0);
605 		sysctl_flag_set = (err == 0 && sysctl_val > 0);
606 	}
607 
608 	bool has_cap_bit = (cap_bit != -1);
609 	bool cap_bit_set = false;
610 	if (has_cap_bit) {
611 		size_t idx = (unsigned int)cap_bit / 8;
612 		unsigned int bit = 1U << (cap_bit % 8);
613 		cap_bit_set = (hw_optional_arm_caps[idx] & bit);
614 	}
615 
616 	bool has_capability = has_commpage_flag ? commpage_flag_set : sysctl_flag_set;
617 
618 	if (!has_commpage_flag && !has_sysctl) {
619 		T_FAIL("Tested capability must have either sysctl or commpage flag");
620 		return;
621 	}
622 
623 	if (has_commpage_flag && has_sysctl) {
624 		T_EXPECT_EQ(commpage_flag_set, sysctl_flag_set, "%s commpage flag matches sysctl flag", cap_name);
625 	}
626 	if (has_commpage_flag && has_cap_bit) {
627 		T_EXPECT_EQ(commpage_flag_set, cap_bit_set, "%s commpage flag matches hw.optional.arm.caps bit", cap_name);
628 	}
629 	if (has_sysctl && has_cap_bit) {
630 		T_EXPECT_EQ(sysctl_flag_set, cap_bit_set, "%s sysctl flag matches hw.optional.arm.caps bit", cap_name);
631 	}
632 
633 	if (try_cpu_capability != NULL) {
634 		cap_usable = true;
635 		try_cpu_capability();
636 		T_EXPECT_EQ(has_capability, cap_usable, "%s capability matches actual usability", cap_name);
637 	}
638 }
639 
640 static inline void
test_deprecated_sysctl(const char * cap_name,uint64_t commpage_flag,const char * deprecated_sysctl)641 test_deprecated_sysctl(const char *cap_name, uint64_t commpage_flag, const char *deprecated_sysctl)
642 {
643 	char *deprecated_cap_name;
644 	int err = asprintf(&deprecated_cap_name, "%s (deprecated sysctl)", cap_name);
645 	T_QUIET; T_ASSERT_NE(err, -1, "asprintf");
646 	test_cpu_capability(deprecated_cap_name, commpage_flag, deprecated_sysctl, -1, NULL);
647 	free(deprecated_cap_name);
648 }
649 
650 T_DECL(cpu_capabilities, "Verify ARM CPU capabilities", T_META_TAG_VM_NOT_ELIGIBLE) {
651 	T_SETUPBEGIN;
652 	size_t hw_optional_arm_caps_size = sizeof(hw_optional_arm_caps);
653 	int err = sysctlbyname("hw.optional.arm.caps", hw_optional_arm_caps, &hw_optional_arm_caps_size, NULL, 0);
654 	T_QUIET; T_ASSERT_POSIX_SUCCESS(err, "sysctlbyname(\"hw.optional.arm.caps\")");
655 
656 	exc_port = create_exception_port(EXC_MASK_BAD_INSTRUCTION);
657 	T_SETUPEND;
658 
659 	repeat_exception_handler(exc_port, bad_instruction_handler);
660 
661 	test_deprecated_sysctl("FP16", kHasFeatFP16, "hw.optional.neon_fp16");
662 	test_cpu_capability("FP16", kHasFeatFP16, "hw.optional.arm.FEAT_FP16", CAP_BIT_FEAT_FP16, try_fp16);
663 	test_deprecated_sysctl("LSE", kHasFeatLSE, "hw.optional.armv8_1_atomics");
664 	test_cpu_capability("LSE", kHasFeatLSE, "hw.optional.arm.FEAT_LSE", CAP_BIT_FEAT_LSE, try_atomics);
665 	test_deprecated_sysctl("CRC32", kHasARMv8Crc32, "hw.optional.armv8_crc32");
666 	test_cpu_capability("CRC32", kHasARMv8Crc32, "hw.optional.arm.FEAT_CRC32", CAP_BIT_FEAT_CRC32, try_crc32);
667 	test_deprecated_sysctl("FHM", kHasFeatFHM, "hw.optional.armv8_2_fhm");
668 	test_cpu_capability("FHM", kHasFeatFHM, "hw.optional.arm.FEAT_FHM", CAP_BIT_FEAT_FHM, try_fhm);
669 	test_deprecated_sysctl("SHA512", kHasFeatSHA512, "hw.optional.armv8_2_sha512");
670 	test_cpu_capability("SHA512", kHasFeatSHA512, "hw.optional.arm.FEAT_SHA512", CAP_BIT_FEAT_SHA512, try_sha512);
671 	test_deprecated_sysctl("SHA3", kHasFeatSHA3, "hw.optional.armv8_2_sha3");
672 	test_cpu_capability("SHA3", kHasFeatSHA3, "hw.optional.arm.FEAT_SHA3", CAP_BIT_FEAT_SHA3, try_sha3);
673 	test_cpu_capability("AES", kHasFeatAES, "hw.optional.arm.FEAT_AES", CAP_BIT_FEAT_AES, try_aes);
674 	test_cpu_capability("SHA1", kHasFeatSHA1, "hw.optional.arm.FEAT_SHA1", CAP_BIT_FEAT_SHA1, try_sha1);
675 	test_cpu_capability("SHA256", kHasFeatSHA256, "hw.optional.arm.FEAT_SHA256", CAP_BIT_FEAT_SHA256, try_sha256);
676 	test_cpu_capability("PMULL", kHasFeatPMULL, "hw.optional.arm.FEAT_PMULL", CAP_BIT_FEAT_PMULL, try_pmull);
677 	test_deprecated_sysctl("FCMA", kHasFeatFCMA, "hw.optional.armv8_3_compnum");
678 	test_cpu_capability("FCMA", kHasFeatFCMA, "hw.optional.arm.FEAT_FCMA", CAP_BIT_FEAT_FCMA, try_compnum);
679 	test_cpu_capability("FlagM", kHasFEATFlagM, "hw.optional.arm.FEAT_FlagM", CAP_BIT_FEAT_FlagM, try_flagm);
680 	test_cpu_capability("FlagM2", kHasFEATFlagM2, "hw.optional.arm.FEAT_FlagM2", CAP_BIT_FEAT_FlagM2, try_flagm2);
681 	test_cpu_capability("DotProd", kHasFeatDotProd, "hw.optional.arm.FEAT_DotProd", CAP_BIT_FEAT_DotProd, try_dotprod);
682 	test_cpu_capability("RDM", kHasFeatRDM, "hw.optional.arm.FEAT_RDM", CAP_BIT_FEAT_RDM, try_rdm);
683 	test_cpu_capability("SB", kHasFeatSB, "hw.optional.arm.FEAT_SB", CAP_BIT_FEAT_SB, try_sb);
684 	test_cpu_capability("FRINTTS", kHasFeatFRINTTS, "hw.optional.arm.FEAT_FRINTTS", CAP_BIT_FEAT_FRINTTS, try_frintts);
685 	test_cpu_capability("JSCVT", kHasFeatJSCVT, "hw.optional.arm.FEAT_JSCVT", CAP_BIT_FEAT_JSCVT, try_jscvt);
686 	test_cpu_capability("PAuth", kHasFeatPAuth, "hw.optional.arm.FEAT_PAuth", CAP_BIT_FEAT_PAuth, try_pauth);
687 	test_cpu_capability("DBP", kHasFeatDPB, "hw.optional.arm.FEAT_DPB", CAP_BIT_FEAT_DPB, try_dpb);
688 	test_cpu_capability("DBP2", kHasFeatDPB2, "hw.optional.arm.FEAT_DPB2", CAP_BIT_FEAT_DPB2, try_dpb2);
689 	test_cpu_capability("SPECRES", kHasFeatSPECRES, "hw.optional.arm.FEAT_SPECRES", CAP_BIT_FEAT_SPECRES, try_specres);
690 	test_cpu_capability("LRCPC", kHasFeatLRCPC, "hw.optional.arm.FEAT_LRCPC", CAP_BIT_FEAT_LRCPC, try_lrcpc);
691 	test_cpu_capability("LRCPC2", kHasFeatLRCPC2, "hw.optional.arm.FEAT_LRCPC2", CAP_BIT_FEAT_LRCPC2, try_lrcpc2);
692 	test_cpu_capability("AFP", kHasFeatAFP, "hw.optional.arm.FEAT_AFP", CAP_BIT_FEAT_AFP, try_afp);
693 	test_cpu_capability("DIT", kHasFeatDIT, "hw.optional.arm.FEAT_DIT", CAP_BIT_FEAT_DIT, try_dit);
694 	test_cpu_capability("FP16", kHasFP_SyncExceptions, "hw.optional.arm.FP_SyncExceptions", -1, try_fpexcp);
695 	test_cpu_capability("SME", kHasFeatSME, "hw.optional.arm.FEAT_SME", CAP_BIT_FEAT_SME, try_sme);
696 	test_cpu_capability("SME2", kHasFeatSME2, "hw.optional.arm.FEAT_SME2", CAP_BIT_FEAT_SME2, try_sme2);
697 	test_cpu_capability("SME2.1", kHasFeatSME2p1, "hw.optional.arm.FEAT_SME2p1", CAP_BIT_FEAT_SME2p1, try_sme2p1);
698 
699 	// The following features do not have a commpage entry
700 	test_cpu_capability("BF16", 0, "hw.optional.arm.FEAT_BF16", CAP_BIT_FEAT_BF16, try_bf16);
701 	test_cpu_capability("I8MM", 0, "hw.optional.arm.FEAT_I8MM", CAP_BIT_FEAT_I8MM, try_i8mm);
702 	test_cpu_capability("ECV", 0, "hw.optional.arm.FEAT_ECV", CAP_BIT_FEAT_ECV, try_ecv);
703 	test_cpu_capability("RPRES", 0, "hw.optional.arm.FEAT_RPRES", CAP_BIT_FEAT_RPRES, try_rpres);
704 	test_cpu_capability("WFxT", 0, "hw.optional.arm.FEAT_WFxT", CAP_BIT_FEAT_WFxT, try_wfxt);
705 	test_cpu_capability("SME_F32F32", 0, "hw.optional.arm.SME_F32F32", CAP_BIT_SME_F32F32, try_sme_f32f32);
706 	test_cpu_capability("SME_BI32I32", 0, "hw.optional.arm.SME_BI32I32", CAP_BIT_SME_BI32I32, try_sme_bi32i32);
707 	test_cpu_capability("SME_B16F32", 0, "hw.optional.arm.SME_B16F32", CAP_BIT_SME_B16F32, try_sme_b16f32);
708 	test_cpu_capability("SME_F16F32", 0, "hw.optional.arm.SME_F16F32", CAP_BIT_SME_F16F32, try_sme_f16f32);
709 	test_cpu_capability("SME_I8I32", 0, "hw.optional.arm.SME_I8I32", CAP_BIT_SME_I8I32, try_sme_i8i32);
710 	test_cpu_capability("SME_I16I32", 0, "hw.optional.arm.SME_I16I32", CAP_BIT_SME_I16I32, try_sme_i16i32);
711 	test_cpu_capability("SME_F64F64", 0, "hw.optional.arm.FEAT_SME_F64F64", CAP_BIT_FEAT_SME_F64F64, try_sme_f64f64);
712 	test_cpu_capability("SME_I16I64", 0, "hw.optional.arm.FEAT_SME_I16I64", CAP_BIT_FEAT_SME_I16I64, try_sme_i16i64);
713 	test_cpu_capability("SME_F16F16", 0, "hw.optional.arm.FEAT_SME_F16F16", CAP_BIT_FEAT_SME_F16F16, try_sme_f16f16);
714 	test_cpu_capability("SME_B16B16", 0, "hw.optional.arm.FEAT_SME_B16B16", CAP_BIT_FEAT_SME_B16B16, try_sme_b16b16);
715 
716 	// The following features do not add instructions or registers to test for the presence of
717 	test_deprecated_sysctl("PACIMP", kHasArmv8GPI, "hw.optional.armv8_gpi");
718 	test_cpu_capability("PACIMP", kHasArmv8GPI, "hw.optional.arm.FEAT_PACIMP", CAP_BIT_FEAT_PACIMP, NULL);
719 	test_cpu_capability("LSE2", kHasFeatLSE2, "hw.optional.arm.FEAT_LSE2", CAP_BIT_FEAT_LSE2, NULL);
720 	test_cpu_capability("CSV2", kHasFeatCSV2, "hw.optional.arm.FEAT_CSV2", CAP_BIT_FEAT_CSV2, NULL);
721 	test_cpu_capability("CSV3", kHasFeatCSV3, "hw.optional.arm.FEAT_CSV3", CAP_BIT_FEAT_CSV3, NULL);
722 }
723