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