1*043036a2SApple OSS Distributions /*
2*043036a2SApple OSS Distributions * Copyright (c) 2022 Apple Computer, Inc. All rights reserved.
3*043036a2SApple OSS Distributions *
4*043036a2SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*043036a2SApple OSS Distributions *
6*043036a2SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7*043036a2SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8*043036a2SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9*043036a2SApple OSS Distributions * compliance with the License. The rights granted to you under the License
10*043036a2SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11*043036a2SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12*043036a2SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13*043036a2SApple OSS Distributions * terms of an Apple operating system software license agreement.
14*043036a2SApple OSS Distributions *
15*043036a2SApple OSS Distributions * Please obtain a copy of the License at
16*043036a2SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*043036a2SApple OSS Distributions *
18*043036a2SApple OSS Distributions * The Original Code and all software distributed under the License are
19*043036a2SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*043036a2SApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*043036a2SApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*043036a2SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*043036a2SApple OSS Distributions * Please see the License for the specific language governing rights and
24*043036a2SApple OSS Distributions * limitations under the License.
25*043036a2SApple OSS Distributions *
26*043036a2SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*043036a2SApple OSS Distributions */
28*043036a2SApple OSS Distributions
29*043036a2SApple OSS Distributions #include <mach/thread_act.h>
30*043036a2SApple OSS Distributions #include <stdint.h>
31*043036a2SApple OSS Distributions #include <stdlib.h>
32*043036a2SApple OSS Distributions #include <sys/sysctl.h>
33*043036a2SApple OSS Distributions
34*043036a2SApple OSS Distributions #include "arm_matrix.h"
35*043036a2SApple OSS Distributions
36*043036a2SApple OSS Distributions const static unsigned int SME_Z_VECTORS = 32;
37*043036a2SApple OSS Distributions const static unsigned int SME_P_VECTORS = 16;
38*043036a2SApple OSS Distributions
39*043036a2SApple OSS Distributions static unsigned int
sme_version(void)40*043036a2SApple OSS Distributions sme_version(void)
41*043036a2SApple OSS Distributions {
42*043036a2SApple OSS Distributions static unsigned int ret = 0;
43*043036a2SApple OSS Distributions static bool already_read = false;
44*043036a2SApple OSS Distributions
45*043036a2SApple OSS Distributions if (!already_read) {
46*043036a2SApple OSS Distributions size_t size = sizeof(unsigned int);
47*043036a2SApple OSS Distributions unsigned int feat_sme, feat_sme2;
48*043036a2SApple OSS Distributions sysctlbyname("hw.optional.arm.FEAT_SME", &feat_sme, &size, NULL, 0);
49*043036a2SApple OSS Distributions sysctlbyname("hw.optional.arm.FEAT_SME2", &feat_sme2, &size, NULL, 0);
50*043036a2SApple OSS Distributions
51*043036a2SApple OSS Distributions if (feat_sme2) {
52*043036a2SApple OSS Distributions ret = 2;
53*043036a2SApple OSS Distributions } else if (feat_sme) {
54*043036a2SApple OSS Distributions ret = 1;
55*043036a2SApple OSS Distributions } else {
56*043036a2SApple OSS Distributions ret = 0;
57*043036a2SApple OSS Distributions }
58*043036a2SApple OSS Distributions
59*043036a2SApple OSS Distributions already_read = true;
60*043036a2SApple OSS Distributions }
61*043036a2SApple OSS Distributions
62*043036a2SApple OSS Distributions return ret;
63*043036a2SApple OSS Distributions }
64*043036a2SApple OSS Distributions
65*043036a2SApple OSS Distributions static uint16_t
arm_sme_svl_b(void)66*043036a2SApple OSS Distributions arm_sme_svl_b(void)
67*043036a2SApple OSS Distributions {
68*043036a2SApple OSS Distributions uint64_t ret = 0;
69*043036a2SApple OSS Distributions asm volatile (
70*043036a2SApple OSS Distributions "rdsvl %[ret], #1"
71*043036a2SApple OSS Distributions : [ret] "=r"(ret)
72*043036a2SApple OSS Distributions );
73*043036a2SApple OSS Distributions return (uint16_t)ret;
74*043036a2SApple OSS Distributions }
75*043036a2SApple OSS Distributions
76*043036a2SApple OSS Distributions static size_t
sme_za_size(void)77*043036a2SApple OSS Distributions sme_za_size(void)
78*043036a2SApple OSS Distributions {
79*043036a2SApple OSS Distributions return arm_sme_svl_b() * arm_sme_svl_b();
80*043036a2SApple OSS Distributions }
81*043036a2SApple OSS Distributions
82*043036a2SApple OSS Distributions static size_t
sme_z_size(void)83*043036a2SApple OSS Distributions sme_z_size(void)
84*043036a2SApple OSS Distributions {
85*043036a2SApple OSS Distributions return arm_sme_svl_b() * SME_Z_VECTORS;
86*043036a2SApple OSS Distributions }
87*043036a2SApple OSS Distributions
88*043036a2SApple OSS Distributions static size_t
sme_p_size(void)89*043036a2SApple OSS Distributions sme_p_size(void)
90*043036a2SApple OSS Distributions {
91*043036a2SApple OSS Distributions return arm_sme_svl_b() * SME_P_VECTORS / 8;
92*043036a2SApple OSS Distributions }
93*043036a2SApple OSS Distributions
94*043036a2SApple OSS Distributions static size_t
sme_zt0_size(void)95*043036a2SApple OSS Distributions sme_zt0_size(void)
96*043036a2SApple OSS Distributions {
97*043036a2SApple OSS Distributions if (sme_version() >= 2) {
98*043036a2SApple OSS Distributions return 64;
99*043036a2SApple OSS Distributions } else {
100*043036a2SApple OSS Distributions return 0;
101*043036a2SApple OSS Distributions }
102*043036a2SApple OSS Distributions }
103*043036a2SApple OSS Distributions
104*043036a2SApple OSS Distributions static size_t
sme_tpidr2_size(void)105*043036a2SApple OSS Distributions sme_tpidr2_size(void)
106*043036a2SApple OSS Distributions {
107*043036a2SApple OSS Distributions return sizeof(uint64_t);
108*043036a2SApple OSS Distributions }
109*043036a2SApple OSS Distributions
110*043036a2SApple OSS Distributions static inline uint8_t *
sme_za(void * addr)111*043036a2SApple OSS Distributions sme_za(void *addr)
112*043036a2SApple OSS Distributions {
113*043036a2SApple OSS Distributions return addr;
114*043036a2SApple OSS Distributions }
115*043036a2SApple OSS Distributions
116*043036a2SApple OSS Distributions static inline const uint8_t *
const_sme_za(const void * addr)117*043036a2SApple OSS Distributions const_sme_za(const void *addr)
118*043036a2SApple OSS Distributions {
119*043036a2SApple OSS Distributions return addr;
120*043036a2SApple OSS Distributions }
121*043036a2SApple OSS Distributions
122*043036a2SApple OSS Distributions static inline uint8_t *
sme_zt0(void * addr)123*043036a2SApple OSS Distributions sme_zt0(void *addr)
124*043036a2SApple OSS Distributions {
125*043036a2SApple OSS Distributions return sme_za(addr) + sme_za_size();
126*043036a2SApple OSS Distributions }
127*043036a2SApple OSS Distributions
128*043036a2SApple OSS Distributions static inline const uint8_t *
const_sme_zt0(const void * addr)129*043036a2SApple OSS Distributions const_sme_zt0(const void *addr)
130*043036a2SApple OSS Distributions {
131*043036a2SApple OSS Distributions return const_sme_za(addr) + sme_za_size();
132*043036a2SApple OSS Distributions }
133*043036a2SApple OSS Distributions
134*043036a2SApple OSS Distributions static inline uint8_t *
sme_tpidr2_el0(void * addr)135*043036a2SApple OSS Distributions sme_tpidr2_el0(void *addr)
136*043036a2SApple OSS Distributions {
137*043036a2SApple OSS Distributions return sme_zt0(addr) + sme_zt0_size();
138*043036a2SApple OSS Distributions }
139*043036a2SApple OSS Distributions
140*043036a2SApple OSS Distributions static inline const uint8_t *
const_sme_tpidr2_el0(const void * addr)141*043036a2SApple OSS Distributions const_sme_tpidr2_el0(const void *addr)
142*043036a2SApple OSS Distributions {
143*043036a2SApple OSS Distributions return const_sme_zt0(addr) + sme_zt0_size();
144*043036a2SApple OSS Distributions }
145*043036a2SApple OSS Distributions
146*043036a2SApple OSS Distributions static inline uint8_t *
sme_z(void * addr)147*043036a2SApple OSS Distributions sme_z(void *addr)
148*043036a2SApple OSS Distributions {
149*043036a2SApple OSS Distributions return sme_tpidr2_el0(addr) + sizeof(uint64_t);
150*043036a2SApple OSS Distributions }
151*043036a2SApple OSS Distributions
152*043036a2SApple OSS Distributions static inline const uint8_t *
const_sme_z(const void * addr)153*043036a2SApple OSS Distributions const_sme_z(const void *addr)
154*043036a2SApple OSS Distributions {
155*043036a2SApple OSS Distributions return const_sme_tpidr2_el0(addr) + sizeof(uint64_t);
156*043036a2SApple OSS Distributions }
157*043036a2SApple OSS Distributions
158*043036a2SApple OSS Distributions static inline uint8_t *
sme_p(void * addr)159*043036a2SApple OSS Distributions sme_p(void *addr)
160*043036a2SApple OSS Distributions {
161*043036a2SApple OSS Distributions return sme_z(addr) + sme_z_size();
162*043036a2SApple OSS Distributions }
163*043036a2SApple OSS Distributions
164*043036a2SApple OSS Distributions static inline const uint8_t *
const_sme_p(const void * addr)165*043036a2SApple OSS Distributions const_sme_p(const void *addr)
166*043036a2SApple OSS Distributions {
167*043036a2SApple OSS Distributions return const_sme_z(addr) + sme_z_size();
168*043036a2SApple OSS Distributions }
169*043036a2SApple OSS Distributions
170*043036a2SApple OSS Distributions static size_t
sme_data_size(void)171*043036a2SApple OSS Distributions sme_data_size(void)
172*043036a2SApple OSS Distributions {
173*043036a2SApple OSS Distributions return sme_za_size() + sme_zt0_size() + sme_tpidr2_size() + sme_z_size() + sme_p_size();
174*043036a2SApple OSS Distributions }
175*043036a2SApple OSS Distributions
176*043036a2SApple OSS Distributions static size_t
sme_za_data_size(void)177*043036a2SApple OSS Distributions sme_za_data_size(void)
178*043036a2SApple OSS Distributions {
179*043036a2SApple OSS Distributions return sme_za_size() + sme_zt0_size() + sme_tpidr2_size();
180*043036a2SApple OSS Distributions }
181*043036a2SApple OSS Distributions
182*043036a2SApple OSS Distributions static inline void
set_sme_tpidr2_el0(void * addr,uint64_t val)183*043036a2SApple OSS Distributions set_sme_tpidr2_el0(void *addr, uint64_t val)
184*043036a2SApple OSS Distributions {
185*043036a2SApple OSS Distributions uint64_t *ptr = (uint64_t *)(sme_tpidr2_el0(addr));
186*043036a2SApple OSS Distributions *ptr = val;
187*043036a2SApple OSS Distributions }
188*043036a2SApple OSS Distributions
189*043036a2SApple OSS Distributions static inline uint64_t
get_sme_tpidr2_el0(const void * addr)190*043036a2SApple OSS Distributions get_sme_tpidr2_el0(const void *addr)
191*043036a2SApple OSS Distributions {
192*043036a2SApple OSS Distributions const uint64_t *ptr = (const uint64_t *)(const_sme_tpidr2_el0(addr));
193*043036a2SApple OSS Distributions return *ptr;
194*043036a2SApple OSS Distributions }
195*043036a2SApple OSS Distributions
196*043036a2SApple OSS Distributions static void *
sme_alloc_data(void)197*043036a2SApple OSS Distributions sme_alloc_data(void)
198*043036a2SApple OSS Distributions {
199*043036a2SApple OSS Distributions return malloc(sme_data_size());
200*043036a2SApple OSS Distributions }
201*043036a2SApple OSS Distributions
202*043036a2SApple OSS Distributions static void *
sme_za_alloc_data(void)203*043036a2SApple OSS Distributions sme_za_alloc_data(void)
204*043036a2SApple OSS Distributions {
205*043036a2SApple OSS Distributions return malloc(sme_za_data_size());
206*043036a2SApple OSS Distributions }
207*043036a2SApple OSS Distributions
208*043036a2SApple OSS Distributions static bool
sme_is_available(void)209*043036a2SApple OSS Distributions sme_is_available(void)
210*043036a2SApple OSS Distributions {
211*043036a2SApple OSS Distributions return sme_version() > 0;
212*043036a2SApple OSS Distributions }
213*043036a2SApple OSS Distributions
214*043036a2SApple OSS Distributions static void
sme_start(void)215*043036a2SApple OSS Distributions sme_start(void)
216*043036a2SApple OSS Distributions {
217*043036a2SApple OSS Distributions asm volatile ("smstart");
218*043036a2SApple OSS Distributions }
219*043036a2SApple OSS Distributions
220*043036a2SApple OSS Distributions static void
sme_za_start(void)221*043036a2SApple OSS Distributions sme_za_start(void)
222*043036a2SApple OSS Distributions {
223*043036a2SApple OSS Distributions asm volatile ("smstart za");
224*043036a2SApple OSS Distributions }
225*043036a2SApple OSS Distributions
226*043036a2SApple OSS Distributions static void
sme_stop(void)227*043036a2SApple OSS Distributions sme_stop(void)
228*043036a2SApple OSS Distributions {
229*043036a2SApple OSS Distributions asm volatile ("smstop");
230*043036a2SApple OSS Distributions }
231*043036a2SApple OSS Distributions
232*043036a2SApple OSS Distributions static void
sme_za_stop(void)233*043036a2SApple OSS Distributions sme_za_stop(void)
234*043036a2SApple OSS Distributions {
235*043036a2SApple OSS Distributions asm volatile ("smstop za");
236*043036a2SApple OSS Distributions }
237*043036a2SApple OSS Distributions
238*043036a2SApple OSS Distributions static void
sme_load_one_vector(const void * addr)239*043036a2SApple OSS Distributions sme_load_one_vector(const void *addr)
240*043036a2SApple OSS Distributions {
241*043036a2SApple OSS Distributions asm volatile (
242*043036a2SApple OSS Distributions "mov w12, #0" "\n"
243*043036a2SApple OSS Distributions "ldr za[w12, #0], [%[addr]]" "\n"
244*043036a2SApple OSS Distributions :
245*043036a2SApple OSS Distributions : [addr] "r"(addr)
246*043036a2SApple OSS Distributions : "w12"
247*043036a2SApple OSS Distributions );
248*043036a2SApple OSS Distributions }
249*043036a2SApple OSS Distributions
250*043036a2SApple OSS Distributions static void
sme_za_load_data(const void * addr)251*043036a2SApple OSS Distributions sme_za_load_data(const void *addr)
252*043036a2SApple OSS Distributions {
253*043036a2SApple OSS Distributions const uint8_t *za = const_sme_za(addr);
254*043036a2SApple OSS Distributions uint16_t svl_b = arm_sme_svl_b();
255*043036a2SApple OSS Distributions
256*043036a2SApple OSS Distributions for (register uint16_t i asm("w12") = 0; i < svl_b; i += 16) {
257*043036a2SApple OSS Distributions asm volatile (
258*043036a2SApple OSS Distributions "ldr za[%w[i], #0], [%[addr], #0, mul vl]" "\n"
259*043036a2SApple OSS Distributions "ldr za[%w[i], #1], [%[addr], #1, mul vl]" "\n"
260*043036a2SApple OSS Distributions "ldr za[%w[i], #2], [%[addr], #2, mul vl]" "\n"
261*043036a2SApple OSS Distributions "ldr za[%w[i], #3], [%[addr], #3, mul vl]" "\n"
262*043036a2SApple OSS Distributions "ldr za[%w[i], #4], [%[addr], #4, mul vl]" "\n"
263*043036a2SApple OSS Distributions "ldr za[%w[i], #5], [%[addr], #5, mul vl]" "\n"
264*043036a2SApple OSS Distributions "ldr za[%w[i], #6], [%[addr], #6, mul vl]" "\n"
265*043036a2SApple OSS Distributions "ldr za[%w[i], #7], [%[addr], #7, mul vl]" "\n"
266*043036a2SApple OSS Distributions "ldr za[%w[i], #8], [%[addr], #8, mul vl]" "\n"
267*043036a2SApple OSS Distributions "ldr za[%w[i], #9], [%[addr], #9, mul vl]" "\n"
268*043036a2SApple OSS Distributions "ldr za[%w[i], #10], [%[addr], #10, mul vl]" "\n"
269*043036a2SApple OSS Distributions "ldr za[%w[i], #11], [%[addr], #11, mul vl]" "\n"
270*043036a2SApple OSS Distributions "ldr za[%w[i], #12], [%[addr], #12, mul vl]" "\n"
271*043036a2SApple OSS Distributions "ldr za[%w[i], #13], [%[addr], #13, mul vl]" "\n"
272*043036a2SApple OSS Distributions "ldr za[%w[i], #14], [%[addr], #14, mul vl]" "\n"
273*043036a2SApple OSS Distributions "ldr za[%w[i], #15], [%[addr], #15, mul vl]" "\n"
274*043036a2SApple OSS Distributions :
275*043036a2SApple OSS Distributions : [i] "r"(i),
276*043036a2SApple OSS Distributions [addr] "r"(za + (i * svl_b))
277*043036a2SApple OSS Distributions );
278*043036a2SApple OSS Distributions }
279*043036a2SApple OSS Distributions
280*043036a2SApple OSS Distributions if (sme_zt0_size()) {
281*043036a2SApple OSS Distributions const uint8_t *zt0 = const_sme_zt0(addr);
282*043036a2SApple OSS Distributions asm volatile (
283*043036a2SApple OSS Distributions "ldr zt0, [%[zt0]]"
284*043036a2SApple OSS Distributions :
285*043036a2SApple OSS Distributions : [zt0] "r"(zt0)
286*043036a2SApple OSS Distributions );
287*043036a2SApple OSS Distributions }
288*043036a2SApple OSS Distributions
289*043036a2SApple OSS Distributions __builtin_arm_wsr64("TPIDR2_EL0", get_sme_tpidr2_el0(addr));
290*043036a2SApple OSS Distributions }
291*043036a2SApple OSS Distributions
292*043036a2SApple OSS Distributions static void
sme_load_data(const void * addr)293*043036a2SApple OSS Distributions sme_load_data(const void *addr)
294*043036a2SApple OSS Distributions {
295*043036a2SApple OSS Distributions const uint8_t *z = const_sme_z(addr);
296*043036a2SApple OSS Distributions const uint8_t *p = const_sme_p(addr);
297*043036a2SApple OSS Distributions
298*043036a2SApple OSS Distributions sme_za_load_data(addr);
299*043036a2SApple OSS Distributions
300*043036a2SApple OSS Distributions asm volatile (
301*043036a2SApple OSS Distributions "ldr z0, [%[z], #0, mul vl]" "\n"
302*043036a2SApple OSS Distributions "ldr z1, [%[z], #1, mul vl]" "\n"
303*043036a2SApple OSS Distributions "ldr z2, [%[z], #2, mul vl]" "\n"
304*043036a2SApple OSS Distributions "ldr z3, [%[z], #3, mul vl]" "\n"
305*043036a2SApple OSS Distributions "ldr z4, [%[z], #4, mul vl]" "\n"
306*043036a2SApple OSS Distributions "ldr z5, [%[z], #5, mul vl]" "\n"
307*043036a2SApple OSS Distributions "ldr z6, [%[z], #6, mul vl]" "\n"
308*043036a2SApple OSS Distributions "ldr z7, [%[z], #7, mul vl]" "\n"
309*043036a2SApple OSS Distributions "ldr z8, [%[z], #8, mul vl]" "\n"
310*043036a2SApple OSS Distributions "ldr z9, [%[z], #9, mul vl]" "\n"
311*043036a2SApple OSS Distributions "ldr z10, [%[z], #10, mul vl]" "\n"
312*043036a2SApple OSS Distributions "ldr z11, [%[z], #11, mul vl]" "\n"
313*043036a2SApple OSS Distributions "ldr z12, [%[z], #12, mul vl]" "\n"
314*043036a2SApple OSS Distributions "ldr z13, [%[z], #13, mul vl]" "\n"
315*043036a2SApple OSS Distributions "ldr z14, [%[z], #14, mul vl]" "\n"
316*043036a2SApple OSS Distributions "ldr z15, [%[z], #15, mul vl]" "\n"
317*043036a2SApple OSS Distributions "ldr z16, [%[z], #16, mul vl]" "\n"
318*043036a2SApple OSS Distributions "ldr z17, [%[z], #17, mul vl]" "\n"
319*043036a2SApple OSS Distributions "ldr z18, [%[z], #18, mul vl]" "\n"
320*043036a2SApple OSS Distributions "ldr z19, [%[z], #19, mul vl]" "\n"
321*043036a2SApple OSS Distributions "ldr z20, [%[z], #20, mul vl]" "\n"
322*043036a2SApple OSS Distributions "ldr z21, [%[z], #21, mul vl]" "\n"
323*043036a2SApple OSS Distributions "ldr z22, [%[z], #22, mul vl]" "\n"
324*043036a2SApple OSS Distributions "ldr z23, [%[z], #23, mul vl]" "\n"
325*043036a2SApple OSS Distributions "ldr z24, [%[z], #24, mul vl]" "\n"
326*043036a2SApple OSS Distributions "ldr z25, [%[z], #25, mul vl]" "\n"
327*043036a2SApple OSS Distributions "ldr z26, [%[z], #26, mul vl]" "\n"
328*043036a2SApple OSS Distributions "ldr z27, [%[z], #27, mul vl]" "\n"
329*043036a2SApple OSS Distributions "ldr z28, [%[z], #28, mul vl]" "\n"
330*043036a2SApple OSS Distributions "ldr z29, [%[z], #29, mul vl]" "\n"
331*043036a2SApple OSS Distributions "ldr z30, [%[z], #30, mul vl]" "\n"
332*043036a2SApple OSS Distributions "ldr z31, [%[z], #31, mul vl]" "\n"
333*043036a2SApple OSS Distributions :
334*043036a2SApple OSS Distributions : [z] "r"(z)
335*043036a2SApple OSS Distributions );
336*043036a2SApple OSS Distributions
337*043036a2SApple OSS Distributions asm volatile (
338*043036a2SApple OSS Distributions "ldr p0, [%[p], #0, mul vl]" "\n"
339*043036a2SApple OSS Distributions "ldr p1, [%[p], #1, mul vl]" "\n"
340*043036a2SApple OSS Distributions "ldr p2, [%[p], #2, mul vl]" "\n"
341*043036a2SApple OSS Distributions "ldr p3, [%[p], #3, mul vl]" "\n"
342*043036a2SApple OSS Distributions "ldr p4, [%[p], #4, mul vl]" "\n"
343*043036a2SApple OSS Distributions "ldr p5, [%[p], #5, mul vl]" "\n"
344*043036a2SApple OSS Distributions "ldr p6, [%[p], #6, mul vl]" "\n"
345*043036a2SApple OSS Distributions "ldr p7, [%[p], #7, mul vl]" "\n"
346*043036a2SApple OSS Distributions "ldr p8, [%[p], #8, mul vl]" "\n"
347*043036a2SApple OSS Distributions "ldr p9, [%[p], #9, mul vl]" "\n"
348*043036a2SApple OSS Distributions "ldr p10, [%[p], #10, mul vl]" "\n"
349*043036a2SApple OSS Distributions "ldr p11, [%[p], #11, mul vl]" "\n"
350*043036a2SApple OSS Distributions "ldr p12, [%[p], #12, mul vl]" "\n"
351*043036a2SApple OSS Distributions "ldr p13, [%[p], #13, mul vl]" "\n"
352*043036a2SApple OSS Distributions "ldr p14, [%[p], #14, mul vl]" "\n"
353*043036a2SApple OSS Distributions "ldr p15, [%[p], #15, mul vl]" "\n"
354*043036a2SApple OSS Distributions :
355*043036a2SApple OSS Distributions : [p] "r"(p)
356*043036a2SApple OSS Distributions );
357*043036a2SApple OSS Distributions }
358*043036a2SApple OSS Distributions
359*043036a2SApple OSS Distributions static void
sme_za_store_data(void * addr)360*043036a2SApple OSS Distributions sme_za_store_data(void *addr)
361*043036a2SApple OSS Distributions {
362*043036a2SApple OSS Distributions uint8_t *za = sme_za(addr);
363*043036a2SApple OSS Distributions uint16_t svl_b = arm_sme_svl_b();
364*043036a2SApple OSS Distributions
365*043036a2SApple OSS Distributions for (register uint16_t i asm("w12") = 0; i < svl_b; i += 16) {
366*043036a2SApple OSS Distributions asm volatile (
367*043036a2SApple OSS Distributions "str za[%w[i], #0], [%[addr], #0, mul vl]" "\n"
368*043036a2SApple OSS Distributions "str za[%w[i], #1], [%[addr], #1, mul vl]" "\n"
369*043036a2SApple OSS Distributions "str za[%w[i], #2], [%[addr], #2, mul vl]" "\n"
370*043036a2SApple OSS Distributions "str za[%w[i], #3], [%[addr], #3, mul vl]" "\n"
371*043036a2SApple OSS Distributions "str za[%w[i], #4], [%[addr], #4, mul vl]" "\n"
372*043036a2SApple OSS Distributions "str za[%w[i], #5], [%[addr], #5, mul vl]" "\n"
373*043036a2SApple OSS Distributions "str za[%w[i], #6], [%[addr], #6, mul vl]" "\n"
374*043036a2SApple OSS Distributions "str za[%w[i], #7], [%[addr], #7, mul vl]" "\n"
375*043036a2SApple OSS Distributions "str za[%w[i], #8], [%[addr], #8, mul vl]" "\n"
376*043036a2SApple OSS Distributions "str za[%w[i], #9], [%[addr], #9, mul vl]" "\n"
377*043036a2SApple OSS Distributions "str za[%w[i], #10], [%[addr], #10, mul vl]" "\n"
378*043036a2SApple OSS Distributions "str za[%w[i], #11], [%[addr], #11, mul vl]" "\n"
379*043036a2SApple OSS Distributions "str za[%w[i], #12], [%[addr], #12, mul vl]" "\n"
380*043036a2SApple OSS Distributions "str za[%w[i], #13], [%[addr], #13, mul vl]" "\n"
381*043036a2SApple OSS Distributions "str za[%w[i], #14], [%[addr], #14, mul vl]" "\n"
382*043036a2SApple OSS Distributions "str za[%w[i], #15], [%[addr], #15, mul vl]" "\n"
383*043036a2SApple OSS Distributions :
384*043036a2SApple OSS Distributions : [i] "r"(i),
385*043036a2SApple OSS Distributions [addr] "r"(za + (i * svl_b))
386*043036a2SApple OSS Distributions );
387*043036a2SApple OSS Distributions }
388*043036a2SApple OSS Distributions
389*043036a2SApple OSS Distributions if (sme_zt0_size()) {
390*043036a2SApple OSS Distributions uint8_t *zt0 = sme_zt0(addr);
391*043036a2SApple OSS Distributions asm volatile (
392*043036a2SApple OSS Distributions "str zt0, [%[zt0]]"
393*043036a2SApple OSS Distributions :
394*043036a2SApple OSS Distributions : [zt0] "r"(zt0)
395*043036a2SApple OSS Distributions );
396*043036a2SApple OSS Distributions }
397*043036a2SApple OSS Distributions
398*043036a2SApple OSS Distributions set_sme_tpidr2_el0(addr, __builtin_arm_rsr64("TPIDR2_EL0"));
399*043036a2SApple OSS Distributions }
400*043036a2SApple OSS Distributions
401*043036a2SApple OSS Distributions static void
sme_store_data(void * addr)402*043036a2SApple OSS Distributions sme_store_data(void *addr)
403*043036a2SApple OSS Distributions {
404*043036a2SApple OSS Distributions uint8_t *z = sme_z(addr);
405*043036a2SApple OSS Distributions uint8_t *p = sme_p(addr);
406*043036a2SApple OSS Distributions
407*043036a2SApple OSS Distributions sme_za_store_data(addr);
408*043036a2SApple OSS Distributions
409*043036a2SApple OSS Distributions asm volatile (
410*043036a2SApple OSS Distributions "str z0, [%[z], #0, mul vl]" "\n"
411*043036a2SApple OSS Distributions "str z1, [%[z], #1, mul vl]" "\n"
412*043036a2SApple OSS Distributions "str z2, [%[z], #2, mul vl]" "\n"
413*043036a2SApple OSS Distributions "str z3, [%[z], #3, mul vl]" "\n"
414*043036a2SApple OSS Distributions "str z4, [%[z], #4, mul vl]" "\n"
415*043036a2SApple OSS Distributions "str z5, [%[z], #5, mul vl]" "\n"
416*043036a2SApple OSS Distributions "str z6, [%[z], #6, mul vl]" "\n"
417*043036a2SApple OSS Distributions "str z7, [%[z], #7, mul vl]" "\n"
418*043036a2SApple OSS Distributions "str z8, [%[z], #8, mul vl]" "\n"
419*043036a2SApple OSS Distributions "str z9, [%[z], #9, mul vl]" "\n"
420*043036a2SApple OSS Distributions "str z10, [%[z], #10, mul vl]" "\n"
421*043036a2SApple OSS Distributions "str z11, [%[z], #11, mul vl]" "\n"
422*043036a2SApple OSS Distributions "str z12, [%[z], #12, mul vl]" "\n"
423*043036a2SApple OSS Distributions "str z13, [%[z], #13, mul vl]" "\n"
424*043036a2SApple OSS Distributions "str z14, [%[z], #14, mul vl]" "\n"
425*043036a2SApple OSS Distributions "str z15, [%[z], #15, mul vl]" "\n"
426*043036a2SApple OSS Distributions "str z16, [%[z], #16, mul vl]" "\n"
427*043036a2SApple OSS Distributions "str z17, [%[z], #17, mul vl]" "\n"
428*043036a2SApple OSS Distributions "str z18, [%[z], #18, mul vl]" "\n"
429*043036a2SApple OSS Distributions "str z19, [%[z], #19, mul vl]" "\n"
430*043036a2SApple OSS Distributions "str z20, [%[z], #20, mul vl]" "\n"
431*043036a2SApple OSS Distributions "str z21, [%[z], #21, mul vl]" "\n"
432*043036a2SApple OSS Distributions "str z22, [%[z], #22, mul vl]" "\n"
433*043036a2SApple OSS Distributions "str z23, [%[z], #23, mul vl]" "\n"
434*043036a2SApple OSS Distributions "str z24, [%[z], #24, mul vl]" "\n"
435*043036a2SApple OSS Distributions "str z25, [%[z], #25, mul vl]" "\n"
436*043036a2SApple OSS Distributions "str z26, [%[z], #26, mul vl]" "\n"
437*043036a2SApple OSS Distributions "str z27, [%[z], #27, mul vl]" "\n"
438*043036a2SApple OSS Distributions "str z28, [%[z], #28, mul vl]" "\n"
439*043036a2SApple OSS Distributions "str z29, [%[z], #29, mul vl]" "\n"
440*043036a2SApple OSS Distributions "str z30, [%[z], #30, mul vl]" "\n"
441*043036a2SApple OSS Distributions "str z31, [%[z], #31, mul vl]" "\n"
442*043036a2SApple OSS Distributions :
443*043036a2SApple OSS Distributions : [z] "r"(z)
444*043036a2SApple OSS Distributions );
445*043036a2SApple OSS Distributions
446*043036a2SApple OSS Distributions asm volatile (
447*043036a2SApple OSS Distributions "str p0, [%[p], #0, mul vl]" "\n"
448*043036a2SApple OSS Distributions "str p1, [%[p], #1, mul vl]" "\n"
449*043036a2SApple OSS Distributions "str p2, [%[p], #2, mul vl]" "\n"
450*043036a2SApple OSS Distributions "str p3, [%[p], #3, mul vl]" "\n"
451*043036a2SApple OSS Distributions "str p4, [%[p], #4, mul vl]" "\n"
452*043036a2SApple OSS Distributions "str p5, [%[p], #5, mul vl]" "\n"
453*043036a2SApple OSS Distributions "str p6, [%[p], #6, mul vl]" "\n"
454*043036a2SApple OSS Distributions "str p7, [%[p], #7, mul vl]" "\n"
455*043036a2SApple OSS Distributions "str p8, [%[p], #8, mul vl]" "\n"
456*043036a2SApple OSS Distributions "str p9, [%[p], #9, mul vl]" "\n"
457*043036a2SApple OSS Distributions "str p10, [%[p], #10, mul vl]" "\n"
458*043036a2SApple OSS Distributions "str p11, [%[p], #11, mul vl]" "\n"
459*043036a2SApple OSS Distributions "str p12, [%[p], #12, mul vl]" "\n"
460*043036a2SApple OSS Distributions "str p13, [%[p], #13, mul vl]" "\n"
461*043036a2SApple OSS Distributions "str p14, [%[p], #14, mul vl]" "\n"
462*043036a2SApple OSS Distributions "str p15, [%[p], #15, mul vl]" "\n"
463*043036a2SApple OSS Distributions :
464*043036a2SApple OSS Distributions : [p] "r"(p)
465*043036a2SApple OSS Distributions );
466*043036a2SApple OSS Distributions }
467*043036a2SApple OSS Distributions
468*043036a2SApple OSS Distributions static kern_return_t
sme_thread_get_state(thread_act_t thread,void * addr)469*043036a2SApple OSS Distributions sme_thread_get_state(thread_act_t thread, void *addr)
470*043036a2SApple OSS Distributions {
471*043036a2SApple OSS Distributions uint8_t *za = sme_za(addr);
472*043036a2SApple OSS Distributions uint8_t *z = sme_z(addr);
473*043036a2SApple OSS Distributions uint8_t *p = sme_p(addr);
474*043036a2SApple OSS Distributions uint16_t svl_b = arm_sme_svl_b();
475*043036a2SApple OSS Distributions
476*043036a2SApple OSS Distributions arm_sme_state_t sme_state;
477*043036a2SApple OSS Distributions mach_msg_type_number_t sme_count = ARM_SME_STATE_COUNT;
478*043036a2SApple OSS Distributions kern_return_t err = thread_get_state(thread, ARM_SME_STATE, (thread_state_t)&sme_state, &sme_count);
479*043036a2SApple OSS Distributions if (err) {
480*043036a2SApple OSS Distributions return err;
481*043036a2SApple OSS Distributions }
482*043036a2SApple OSS Distributions set_sme_tpidr2_el0(addr, sme_state.__tpidr2_el0);
483*043036a2SApple OSS Distributions
484*043036a2SApple OSS Distributions arm_sme_za_state_t za_state;
485*043036a2SApple OSS Distributions mach_msg_type_number_t za_count = ARM_SME_ZA_STATE_COUNT;
486*043036a2SApple OSS Distributions err = thread_get_state(thread, ARM_SME_ZA_STATE1, (thread_state_t)&za_state, &za_count);
487*043036a2SApple OSS Distributions if (err) {
488*043036a2SApple OSS Distributions return err;
489*043036a2SApple OSS Distributions }
490*043036a2SApple OSS Distributions
491*043036a2SApple OSS Distributions arm_sve_z_state_t z_state1, z_state2;
492*043036a2SApple OSS Distributions mach_msg_type_number_t z_streaming_count = ARM_SVE_Z_STATE_COUNT;
493*043036a2SApple OSS Distributions err = thread_get_state(thread, ARM_SVE_Z_STATE1, (thread_state_t)&z_state1, &z_streaming_count);
494*043036a2SApple OSS Distributions if (err) {
495*043036a2SApple OSS Distributions return err;
496*043036a2SApple OSS Distributions }
497*043036a2SApple OSS Distributions err = thread_get_state(thread, ARM_SVE_Z_STATE2, (thread_state_t)&z_state2, &z_streaming_count);
498*043036a2SApple OSS Distributions if (err) {
499*043036a2SApple OSS Distributions return err;
500*043036a2SApple OSS Distributions }
501*043036a2SApple OSS Distributions
502*043036a2SApple OSS Distributions arm_sve_p_state_t p_state;
503*043036a2SApple OSS Distributions mach_msg_type_number_t p_streaming_count = ARM_SVE_P_STATE_COUNT;
504*043036a2SApple OSS Distributions err = thread_get_state(thread, ARM_SVE_P_STATE, (thread_state_t)&p_state, &p_streaming_count);
505*043036a2SApple OSS Distributions if (err) {
506*043036a2SApple OSS Distributions return err;
507*043036a2SApple OSS Distributions }
508*043036a2SApple OSS Distributions
509*043036a2SApple OSS Distributions memcpy(za, za_state.__za, svl_b * svl_b);
510*043036a2SApple OSS Distributions
511*043036a2SApple OSS Distributions size_t z_elem_size = svl_b;
512*043036a2SApple OSS Distributions for (int i = 0; i < 16; i++) {
513*043036a2SApple OSS Distributions memcpy(z, z_state1.__z[i], z_elem_size);
514*043036a2SApple OSS Distributions z += z_elem_size;
515*043036a2SApple OSS Distributions }
516*043036a2SApple OSS Distributions for (int i = 0; i < 16; i++) {
517*043036a2SApple OSS Distributions memcpy(z, z_state2.__z[i], z_elem_size);
518*043036a2SApple OSS Distributions z += z_elem_size;
519*043036a2SApple OSS Distributions }
520*043036a2SApple OSS Distributions
521*043036a2SApple OSS Distributions size_t p_elem_size = svl_b / 8;
522*043036a2SApple OSS Distributions for (int i = 0; i < 16; i++) {
523*043036a2SApple OSS Distributions memcpy(p, p_state.__p[i], p_elem_size);
524*043036a2SApple OSS Distributions p += p_elem_size;
525*043036a2SApple OSS Distributions }
526*043036a2SApple OSS Distributions
527*043036a2SApple OSS Distributions if (sme_zt0_size()) {
528*043036a2SApple OSS Distributions uint8_t *zt0 = sme_zt0(addr);
529*043036a2SApple OSS Distributions
530*043036a2SApple OSS Distributions arm_sme2_state_t sme2_state;
531*043036a2SApple OSS Distributions mach_msg_type_number_t sme2_count = ARM_SME2_STATE_COUNT;
532*043036a2SApple OSS Distributions err = thread_get_state(thread, ARM_SME2_STATE, (thread_state_t)&sme2_state, &sme2_count);
533*043036a2SApple OSS Distributions if (err) {
534*043036a2SApple OSS Distributions return err;
535*043036a2SApple OSS Distributions }
536*043036a2SApple OSS Distributions
537*043036a2SApple OSS Distributions memcpy(zt0, sme2_state.__zt0, sizeof(sme2_state.__zt0));
538*043036a2SApple OSS Distributions }
539*043036a2SApple OSS Distributions
540*043036a2SApple OSS Distributions return KERN_SUCCESS;
541*043036a2SApple OSS Distributions }
542*043036a2SApple OSS Distributions
543*043036a2SApple OSS Distributions static kern_return_t
sme_thread_set_state(thread_act_t thread,const void * addr)544*043036a2SApple OSS Distributions sme_thread_set_state(thread_act_t thread, const void *addr)
545*043036a2SApple OSS Distributions {
546*043036a2SApple OSS Distributions const uint8_t *za = const_sme_za(addr);
547*043036a2SApple OSS Distributions const uint8_t *z = const_sme_z(addr);
548*043036a2SApple OSS Distributions const uint8_t *p = const_sme_p(addr);
549*043036a2SApple OSS Distributions uint16_t svl_b = arm_sme_svl_b();
550*043036a2SApple OSS Distributions
551*043036a2SApple OSS Distributions arm_sme_state_t sme_state;
552*043036a2SApple OSS Distributions sme_state.__svcr = 0x3;
553*043036a2SApple OSS Distributions sme_state.__svl_b = svl_b;
554*043036a2SApple OSS Distributions sme_state.__tpidr2_el0 = get_sme_tpidr2_el0(addr);
555*043036a2SApple OSS Distributions
556*043036a2SApple OSS Distributions arm_sme_za_state_t za_state;
557*043036a2SApple OSS Distributions memcpy(za_state.__za, za, svl_b * svl_b);
558*043036a2SApple OSS Distributions
559*043036a2SApple OSS Distributions arm_sve_z_state_t z_state1, z_state2;
560*043036a2SApple OSS Distributions size_t z_elem_size = svl_b;
561*043036a2SApple OSS Distributions for (int i = 0; i < 16; i++) {
562*043036a2SApple OSS Distributions memcpy(z_state1.__z[i], z, z_elem_size);
563*043036a2SApple OSS Distributions z += z_elem_size;
564*043036a2SApple OSS Distributions }
565*043036a2SApple OSS Distributions for (int i = 0; i < 16; i++) {
566*043036a2SApple OSS Distributions memcpy(z_state2.__z[i], z, z_elem_size);
567*043036a2SApple OSS Distributions z += z_elem_size;
568*043036a2SApple OSS Distributions }
569*043036a2SApple OSS Distributions
570*043036a2SApple OSS Distributions arm_sve_p_state_t p_state;
571*043036a2SApple OSS Distributions size_t p_elem_size = svl_b / 8;
572*043036a2SApple OSS Distributions for (int i = 0; i < 16; i++) {
573*043036a2SApple OSS Distributions memcpy(p_state.__p[i], p, p_elem_size);
574*043036a2SApple OSS Distributions p += p_elem_size;
575*043036a2SApple OSS Distributions }
576*043036a2SApple OSS Distributions
577*043036a2SApple OSS Distributions kern_return_t err = thread_set_state(thread, ARM_SME_STATE, (thread_state_t)&sme_state, ARM_SME_STATE_COUNT);
578*043036a2SApple OSS Distributions if (err) {
579*043036a2SApple OSS Distributions return err;
580*043036a2SApple OSS Distributions }
581*043036a2SApple OSS Distributions
582*043036a2SApple OSS Distributions err = thread_set_state(thread, ARM_SVE_Z_STATE1, (thread_state_t)&z_state1, ARM_SVE_Z_STATE_COUNT);
583*043036a2SApple OSS Distributions if (err) {
584*043036a2SApple OSS Distributions return err;
585*043036a2SApple OSS Distributions }
586*043036a2SApple OSS Distributions
587*043036a2SApple OSS Distributions err = thread_set_state(thread, ARM_SVE_Z_STATE2, (thread_state_t)&z_state2, ARM_SVE_Z_STATE_COUNT);
588*043036a2SApple OSS Distributions if (err) {
589*043036a2SApple OSS Distributions return err;
590*043036a2SApple OSS Distributions }
591*043036a2SApple OSS Distributions
592*043036a2SApple OSS Distributions err = thread_set_state(thread, ARM_SVE_P_STATE, (thread_state_t)&p_state, ARM_SVE_P_STATE_COUNT);
593*043036a2SApple OSS Distributions if (err) {
594*043036a2SApple OSS Distributions return err;
595*043036a2SApple OSS Distributions }
596*043036a2SApple OSS Distributions
597*043036a2SApple OSS Distributions err = thread_set_state(thread, ARM_SME_ZA_STATE1, (thread_state_t)&za_state, ARM_SME_ZA_STATE_COUNT);
598*043036a2SApple OSS Distributions if (err) {
599*043036a2SApple OSS Distributions return err;
600*043036a2SApple OSS Distributions }
601*043036a2SApple OSS Distributions
602*043036a2SApple OSS Distributions if (sme_zt0_size()) {
603*043036a2SApple OSS Distributions const uint8_t *zt0 = const_sme_zt0(addr);
604*043036a2SApple OSS Distributions
605*043036a2SApple OSS Distributions arm_sme2_state_t sme2_state;
606*043036a2SApple OSS Distributions memcpy(sme2_state.__zt0, zt0, sizeof(sme2_state.__zt0));
607*043036a2SApple OSS Distributions
608*043036a2SApple OSS Distributions err = thread_set_state(thread, ARM_SME2_STATE, (thread_state_t)&sme2_state, ARM_SME2_STATE_COUNT);
609*043036a2SApple OSS Distributions if (err) {
610*043036a2SApple OSS Distributions return err;
611*043036a2SApple OSS Distributions }
612*043036a2SApple OSS Distributions }
613*043036a2SApple OSS Distributions
614*043036a2SApple OSS Distributions return KERN_SUCCESS;
615*043036a2SApple OSS Distributions }
616*043036a2SApple OSS Distributions
617*043036a2SApple OSS Distributions const struct arm_matrix_operations sme_operations = {
618*043036a2SApple OSS Distributions .name = "SME",
619*043036a2SApple OSS Distributions
620*043036a2SApple OSS Distributions .data_size = sme_data_size,
621*043036a2SApple OSS Distributions .alloc_data = sme_alloc_data,
622*043036a2SApple OSS Distributions
623*043036a2SApple OSS Distributions .is_available = sme_is_available,
624*043036a2SApple OSS Distributions .start = sme_start,
625*043036a2SApple OSS Distributions .stop = sme_stop,
626*043036a2SApple OSS Distributions
627*043036a2SApple OSS Distributions .load_one_vector = sme_load_one_vector,
628*043036a2SApple OSS Distributions .load_data = sme_load_data,
629*043036a2SApple OSS Distributions .store_data = sme_store_data,
630*043036a2SApple OSS Distributions
631*043036a2SApple OSS Distributions .thread_get_state = sme_thread_get_state,
632*043036a2SApple OSS Distributions .thread_set_state = sme_thread_set_state,
633*043036a2SApple OSS Distributions };
634*043036a2SApple OSS Distributions
635*043036a2SApple OSS Distributions const struct arm_matrix_operations sme_za_operations = {
636*043036a2SApple OSS Distributions .name = "SME (SVCR.ZA only)",
637*043036a2SApple OSS Distributions
638*043036a2SApple OSS Distributions .data_size = sme_za_data_size,
639*043036a2SApple OSS Distributions .alloc_data = sme_za_alloc_data,
640*043036a2SApple OSS Distributions
641*043036a2SApple OSS Distributions .is_available = sme_is_available,
642*043036a2SApple OSS Distributions .start = sme_za_start,
643*043036a2SApple OSS Distributions .stop = sme_za_stop,
644*043036a2SApple OSS Distributions
645*043036a2SApple OSS Distributions .load_one_vector = NULL, /* currently unused */
646*043036a2SApple OSS Distributions .load_data = sme_za_load_data,
647*043036a2SApple OSS Distributions .store_data = sme_za_store_data,
648*043036a2SApple OSS Distributions
649*043036a2SApple OSS Distributions .thread_get_state = NULL, /* currently unused */
650*043036a2SApple OSS Distributions .thread_set_state = NULL, /* currently unused */
651*043036a2SApple OSS Distributions };
652