xref: /aosp_15_r20/trusty/kernel/lib/arm_ffa/arm_ffa.c (revision 344aa361028b423587d4ef3fa52a23d194628137)
1*344aa361SAndroid Build Coastguard Worker /*
2*344aa361SAndroid Build Coastguard Worker  * Copyright (c) 2019-2020 LK Trusty Authors. All Rights Reserved.
3*344aa361SAndroid Build Coastguard Worker  * Copyright (c) 2022, Arm Limited. All rights reserved.
4*344aa361SAndroid Build Coastguard Worker  *
5*344aa361SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining
6*344aa361SAndroid Build Coastguard Worker  * a copy of this software and associated documentation files
7*344aa361SAndroid Build Coastguard Worker  * (the "Software"), to deal in the Software without restriction,
8*344aa361SAndroid Build Coastguard Worker  * including without limitation the rights to use, copy, modify, merge,
9*344aa361SAndroid Build Coastguard Worker  * publish, distribute, sublicense, and/or sell copies of the Software,
10*344aa361SAndroid Build Coastguard Worker  * and to permit persons to whom the Software is furnished to do so,
11*344aa361SAndroid Build Coastguard Worker  * subject to the following conditions:
12*344aa361SAndroid Build Coastguard Worker  *
13*344aa361SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be
14*344aa361SAndroid Build Coastguard Worker  * included in all copies or substantial portions of the Software.
15*344aa361SAndroid Build Coastguard Worker  *
16*344aa361SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17*344aa361SAndroid Build Coastguard Worker  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18*344aa361SAndroid Build Coastguard Worker  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19*344aa361SAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20*344aa361SAndroid Build Coastguard Worker  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21*344aa361SAndroid Build Coastguard Worker  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22*344aa361SAndroid Build Coastguard Worker  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23*344aa361SAndroid Build Coastguard Worker  */
24*344aa361SAndroid Build Coastguard Worker 
25*344aa361SAndroid Build Coastguard Worker #define LOCAL_TRACE 0
26*344aa361SAndroid Build Coastguard Worker 
27*344aa361SAndroid Build Coastguard Worker #include <assert.h>
28*344aa361SAndroid Build Coastguard Worker #include <err.h>
29*344aa361SAndroid Build Coastguard Worker #include <interface/arm_ffa/arm_ffa.h>
30*344aa361SAndroid Build Coastguard Worker #include <inttypes.h>
31*344aa361SAndroid Build Coastguard Worker #include <kernel/mutex.h>
32*344aa361SAndroid Build Coastguard Worker #include <kernel/vm.h>
33*344aa361SAndroid Build Coastguard Worker #include <lib/arm_ffa/arm_ffa.h>
34*344aa361SAndroid Build Coastguard Worker #include <lib/smc/smc.h>
35*344aa361SAndroid Build Coastguard Worker #include <lk/init.h>
36*344aa361SAndroid Build Coastguard Worker #include <lk/macros.h>
37*344aa361SAndroid Build Coastguard Worker #include <string.h>
38*344aa361SAndroid Build Coastguard Worker #include <sys/types.h>
39*344aa361SAndroid Build Coastguard Worker #include <trace.h>
40*344aa361SAndroid Build Coastguard Worker 
41*344aa361SAndroid Build Coastguard Worker static bool arm_ffa_init_is_success = false;
42*344aa361SAndroid Build Coastguard Worker static uint16_t ffa_local_id;
43*344aa361SAndroid Build Coastguard Worker static size_t ffa_buf_size;
44*344aa361SAndroid Build Coastguard Worker static void* ffa_tx;
45*344aa361SAndroid Build Coastguard Worker static void* ffa_rx;
46*344aa361SAndroid Build Coastguard Worker static bool supports_ns_bit = false;
47*344aa361SAndroid Build Coastguard Worker static bool supports_rx_release = false;
48*344aa361SAndroid Build Coastguard Worker static bool console_log_is_unsupported;
49*344aa361SAndroid Build Coastguard Worker 
50*344aa361SAndroid Build Coastguard Worker static mutex_t ffa_rxtx_buffer_lock = MUTEX_INITIAL_VALUE(ffa_rxtx_buffer_lock);
51*344aa361SAndroid Build Coastguard Worker 
arm_ffa_is_init(void)52*344aa361SAndroid Build Coastguard Worker bool arm_ffa_is_init(void) {
53*344aa361SAndroid Build Coastguard Worker     return arm_ffa_init_is_success;
54*344aa361SAndroid Build Coastguard Worker }
55*344aa361SAndroid Build Coastguard Worker 
arm_ffa_call_id_get(uint16_t * id)56*344aa361SAndroid Build Coastguard Worker static status_t arm_ffa_call_id_get(uint16_t* id) {
57*344aa361SAndroid Build Coastguard Worker     struct smc_ret8 smc_ret;
58*344aa361SAndroid Build Coastguard Worker 
59*344aa361SAndroid Build Coastguard Worker     smc_ret = smc8(SMC_FC_FFA_ID_GET, 0, 0, 0, 0, 0, 0, 0);
60*344aa361SAndroid Build Coastguard Worker 
61*344aa361SAndroid Build Coastguard Worker     switch (smc_ret.r0) {
62*344aa361SAndroid Build Coastguard Worker     case SMC_FC_FFA_SUCCESS:
63*344aa361SAndroid Build Coastguard Worker     case SMC_FC64_FFA_SUCCESS:
64*344aa361SAndroid Build Coastguard Worker         if (smc_ret.r2 & ~0xFFFFUL) {
65*344aa361SAndroid Build Coastguard Worker             TRACEF("Unexpected FFA_ID_GET result: %lx\n", smc_ret.r2);
66*344aa361SAndroid Build Coastguard Worker             return ERR_NOT_VALID;
67*344aa361SAndroid Build Coastguard Worker         }
68*344aa361SAndroid Build Coastguard Worker         *id = (uint16_t)(smc_ret.r2 & 0xFFFF);
69*344aa361SAndroid Build Coastguard Worker         return NO_ERROR;
70*344aa361SAndroid Build Coastguard Worker 
71*344aa361SAndroid Build Coastguard Worker     case SMC_FC_FFA_ERROR:
72*344aa361SAndroid Build Coastguard Worker         if (smc_ret.r2 == (ulong)FFA_ERROR_NOT_SUPPORTED) {
73*344aa361SAndroid Build Coastguard Worker             return ERR_NOT_SUPPORTED;
74*344aa361SAndroid Build Coastguard Worker         } else {
75*344aa361SAndroid Build Coastguard Worker             TRACEF("Unexpected FFA_ERROR: %lx\n", smc_ret.r2);
76*344aa361SAndroid Build Coastguard Worker             return ERR_NOT_VALID;
77*344aa361SAndroid Build Coastguard Worker         }
78*344aa361SAndroid Build Coastguard Worker 
79*344aa361SAndroid Build Coastguard Worker     default:
80*344aa361SAndroid Build Coastguard Worker         TRACEF("Unexpected FFA SMC: %lx\n", smc_ret.r0);
81*344aa361SAndroid Build Coastguard Worker         return ERR_NOT_VALID;
82*344aa361SAndroid Build Coastguard Worker     }
83*344aa361SAndroid Build Coastguard Worker }
84*344aa361SAndroid Build Coastguard Worker 
arm_ffa_call_version(uint16_t major,uint16_t minor,uint16_t * major_ret,uint16_t * minor_ret)85*344aa361SAndroid Build Coastguard Worker static status_t arm_ffa_call_version(uint16_t major,
86*344aa361SAndroid Build Coastguard Worker                                      uint16_t minor,
87*344aa361SAndroid Build Coastguard Worker                                      uint16_t* major_ret,
88*344aa361SAndroid Build Coastguard Worker                                      uint16_t* minor_ret) {
89*344aa361SAndroid Build Coastguard Worker     struct smc_ret8 smc_ret;
90*344aa361SAndroid Build Coastguard Worker 
91*344aa361SAndroid Build Coastguard Worker     uint32_t version = FFA_VERSION(major, minor);
92*344aa361SAndroid Build Coastguard Worker     /* Bit 31 must be cleared. */
93*344aa361SAndroid Build Coastguard Worker     ASSERT(!(version >> 31));
94*344aa361SAndroid Build Coastguard Worker     smc_ret = smc8(SMC_FC_FFA_VERSION, version, 0, 0, 0, 0, 0, 0);
95*344aa361SAndroid Build Coastguard Worker     if (smc_ret.r0 == (ulong)FFA_ERROR_NOT_SUPPORTED) {
96*344aa361SAndroid Build Coastguard Worker         return ERR_NOT_SUPPORTED;
97*344aa361SAndroid Build Coastguard Worker     }
98*344aa361SAndroid Build Coastguard Worker     *major_ret = FFA_VERSION_TO_MAJOR(smc_ret.r0);
99*344aa361SAndroid Build Coastguard Worker     *minor_ret = FFA_VERSION_TO_MINOR(smc_ret.r0);
100*344aa361SAndroid Build Coastguard Worker 
101*344aa361SAndroid Build Coastguard Worker     return NO_ERROR;
102*344aa361SAndroid Build Coastguard Worker }
103*344aa361SAndroid Build Coastguard Worker 
104*344aa361SAndroid Build Coastguard Worker /* TODO: When adding support for FFA version 1.1 feature ids should be added. */
arm_ffa_call_features(ulong id,bool * is_implemented,ffa_features2_t * features2,ffa_features3_t * features3)105*344aa361SAndroid Build Coastguard Worker static status_t arm_ffa_call_features(ulong id,
106*344aa361SAndroid Build Coastguard Worker                                       bool* is_implemented,
107*344aa361SAndroid Build Coastguard Worker                                       ffa_features2_t* features2,
108*344aa361SAndroid Build Coastguard Worker                                       ffa_features3_t* features3) {
109*344aa361SAndroid Build Coastguard Worker     struct smc_ret8 smc_ret;
110*344aa361SAndroid Build Coastguard Worker 
111*344aa361SAndroid Build Coastguard Worker     ASSERT(is_implemented);
112*344aa361SAndroid Build Coastguard Worker 
113*344aa361SAndroid Build Coastguard Worker     /*
114*344aa361SAndroid Build Coastguard Worker      * According to the FF-A spec section "Discovery of NS bit usage",
115*344aa361SAndroid Build Coastguard Worker      * NS_BIT is optionally set by a v1.0 SP such as Trusty, and must
116*344aa361SAndroid Build Coastguard Worker      * be set by a v1.1+ SP. Here, we set it unconditionally for the
117*344aa361SAndroid Build Coastguard Worker      * relevant feature.
118*344aa361SAndroid Build Coastguard Worker      */
119*344aa361SAndroid Build Coastguard Worker     bool request_ns_bit = (id == SMC_FC_FFA_MEM_RETRIEVE_REQ) ||
120*344aa361SAndroid Build Coastguard Worker                           (id == SMC_FC64_FFA_MEM_RETRIEVE_REQ);
121*344aa361SAndroid Build Coastguard Worker     smc_ret = smc8(SMC_FC_FFA_FEATURES, id,
122*344aa361SAndroid Build Coastguard Worker                    request_ns_bit ? FFA_FEATURES2_MEM_RETRIEVE_REQ_NS_BIT : 0,
123*344aa361SAndroid Build Coastguard Worker                    0, 0, 0, 0, 0);
124*344aa361SAndroid Build Coastguard Worker 
125*344aa361SAndroid Build Coastguard Worker     switch (smc_ret.r0) {
126*344aa361SAndroid Build Coastguard Worker     case SMC_FC_FFA_SUCCESS:
127*344aa361SAndroid Build Coastguard Worker     case SMC_FC64_FFA_SUCCESS:
128*344aa361SAndroid Build Coastguard Worker         *is_implemented = true;
129*344aa361SAndroid Build Coastguard Worker         if (features2) {
130*344aa361SAndroid Build Coastguard Worker             *features2 = (ffa_features2_t)smc_ret.r2;
131*344aa361SAndroid Build Coastguard Worker         }
132*344aa361SAndroid Build Coastguard Worker         if (features3) {
133*344aa361SAndroid Build Coastguard Worker             *features3 = (ffa_features3_t)smc_ret.r3;
134*344aa361SAndroid Build Coastguard Worker         }
135*344aa361SAndroid Build Coastguard Worker         return NO_ERROR;
136*344aa361SAndroid Build Coastguard Worker 
137*344aa361SAndroid Build Coastguard Worker     case SMC_FC_FFA_ERROR:
138*344aa361SAndroid Build Coastguard Worker         if (smc_ret.r2 == (ulong)FFA_ERROR_NOT_SUPPORTED) {
139*344aa361SAndroid Build Coastguard Worker             *is_implemented = false;
140*344aa361SAndroid Build Coastguard Worker             return NO_ERROR;
141*344aa361SAndroid Build Coastguard Worker         } else {
142*344aa361SAndroid Build Coastguard Worker             TRACEF("Unexpected FFA_ERROR: %lx\n", smc_ret.r2);
143*344aa361SAndroid Build Coastguard Worker             return ERR_NOT_VALID;
144*344aa361SAndroid Build Coastguard Worker         }
145*344aa361SAndroid Build Coastguard Worker 
146*344aa361SAndroid Build Coastguard Worker     default:
147*344aa361SAndroid Build Coastguard Worker         TRACEF("Unexpected FFA SMC: %lx\n", smc_ret.r0);
148*344aa361SAndroid Build Coastguard Worker         return ERR_NOT_VALID;
149*344aa361SAndroid Build Coastguard Worker     }
150*344aa361SAndroid Build Coastguard Worker }
151*344aa361SAndroid Build Coastguard Worker 
152*344aa361SAndroid Build Coastguard Worker /*
153*344aa361SAndroid Build Coastguard Worker  * Call with ffa_rxtx_buffer_lock acquired and the ffa_tx buffer already
154*344aa361SAndroid Build Coastguard Worker  * populated with struct ffa_mtd. Transmit in a single fragment.
155*344aa361SAndroid Build Coastguard Worker  */
arm_ffa_call_mem_retrieve_req(uint32_t * total_len,uint32_t * fragment_len)156*344aa361SAndroid Build Coastguard Worker static status_t arm_ffa_call_mem_retrieve_req(uint32_t* total_len,
157*344aa361SAndroid Build Coastguard Worker                                               uint32_t* fragment_len) {
158*344aa361SAndroid Build Coastguard Worker     struct smc_ret8 smc_ret;
159*344aa361SAndroid Build Coastguard Worker     struct ffa_mtd* req = ffa_tx;
160*344aa361SAndroid Build Coastguard Worker     size_t len;
161*344aa361SAndroid Build Coastguard Worker 
162*344aa361SAndroid Build Coastguard Worker     DEBUG_ASSERT(is_mutex_held(&ffa_rxtx_buffer_lock));
163*344aa361SAndroid Build Coastguard Worker 
164*344aa361SAndroid Build Coastguard Worker     len = offsetof(struct ffa_mtd, emad[0]) +
165*344aa361SAndroid Build Coastguard Worker           req->emad_count * sizeof(struct ffa_emad);
166*344aa361SAndroid Build Coastguard Worker 
167*344aa361SAndroid Build Coastguard Worker     smc_ret = smc8(SMC_FC_FFA_MEM_RETRIEVE_REQ, len, len, 0, 0, 0, 0, 0);
168*344aa361SAndroid Build Coastguard Worker 
169*344aa361SAndroid Build Coastguard Worker     long error;
170*344aa361SAndroid Build Coastguard Worker     switch (smc_ret.r0) {
171*344aa361SAndroid Build Coastguard Worker     case SMC_FC_FFA_MEM_RETRIEVE_RESP:
172*344aa361SAndroid Build Coastguard Worker         if (total_len) {
173*344aa361SAndroid Build Coastguard Worker             *total_len = (uint32_t)smc_ret.r1;
174*344aa361SAndroid Build Coastguard Worker         }
175*344aa361SAndroid Build Coastguard Worker         if (fragment_len) {
176*344aa361SAndroid Build Coastguard Worker             *fragment_len = (uint32_t)smc_ret.r2;
177*344aa361SAndroid Build Coastguard Worker         }
178*344aa361SAndroid Build Coastguard Worker         return NO_ERROR;
179*344aa361SAndroid Build Coastguard Worker     case SMC_FC_FFA_ERROR:
180*344aa361SAndroid Build Coastguard Worker         error = (long)smc_ret.r2;
181*344aa361SAndroid Build Coastguard Worker         switch (error) {
182*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_NOT_SUPPORTED:
183*344aa361SAndroid Build Coastguard Worker             return ERR_NOT_SUPPORTED;
184*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_INVALID_PARAMETERS:
185*344aa361SAndroid Build Coastguard Worker             return ERR_INVALID_ARGS;
186*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_NO_MEMORY:
187*344aa361SAndroid Build Coastguard Worker             return ERR_NO_MEMORY;
188*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_DENIED:
189*344aa361SAndroid Build Coastguard Worker             return ERR_BAD_STATE;
190*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_ABORTED:
191*344aa361SAndroid Build Coastguard Worker             return ERR_CANCELLED;
192*344aa361SAndroid Build Coastguard Worker         default:
193*344aa361SAndroid Build Coastguard Worker             TRACEF("Unknown error: 0x%lx\n", error);
194*344aa361SAndroid Build Coastguard Worker             return ERR_NOT_VALID;
195*344aa361SAndroid Build Coastguard Worker         }
196*344aa361SAndroid Build Coastguard Worker     default:
197*344aa361SAndroid Build Coastguard Worker         return ERR_NOT_VALID;
198*344aa361SAndroid Build Coastguard Worker     }
199*344aa361SAndroid Build Coastguard Worker }
200*344aa361SAndroid Build Coastguard Worker 
arm_ffa_call_mem_frag_rx(uint64_t handle,uint32_t offset,uint32_t * fragment_len)201*344aa361SAndroid Build Coastguard Worker static status_t arm_ffa_call_mem_frag_rx(uint64_t handle,
202*344aa361SAndroid Build Coastguard Worker                                          uint32_t offset,
203*344aa361SAndroid Build Coastguard Worker                                          uint32_t* fragment_len) {
204*344aa361SAndroid Build Coastguard Worker     struct smc_ret8 smc_ret;
205*344aa361SAndroid Build Coastguard Worker 
206*344aa361SAndroid Build Coastguard Worker     DEBUG_ASSERT(is_mutex_held(&ffa_rxtx_buffer_lock));
207*344aa361SAndroid Build Coastguard Worker 
208*344aa361SAndroid Build Coastguard Worker     smc_ret = smc8(SMC_FC_FFA_MEM_FRAG_RX, (uint32_t)handle, handle >> 32,
209*344aa361SAndroid Build Coastguard Worker                    offset, 0, 0, 0, 0);
210*344aa361SAndroid Build Coastguard Worker 
211*344aa361SAndroid Build Coastguard Worker     /* FRAG_RX is followed by FRAG_TX on successful completion. */
212*344aa361SAndroid Build Coastguard Worker     switch (smc_ret.r0) {
213*344aa361SAndroid Build Coastguard Worker     case SMC_FC_FFA_MEM_FRAG_TX: {
214*344aa361SAndroid Build Coastguard Worker         uint64_t handle_out = smc_ret.r1 + ((uint64_t)smc_ret.r2 << 32);
215*344aa361SAndroid Build Coastguard Worker         if (handle != handle_out) {
216*344aa361SAndroid Build Coastguard Worker             TRACEF("Handle for response doesn't match the request, %" PRId64
217*344aa361SAndroid Build Coastguard Worker                    " != %" PRId64,
218*344aa361SAndroid Build Coastguard Worker                    handle, handle_out);
219*344aa361SAndroid Build Coastguard Worker             return ERR_NOT_VALID;
220*344aa361SAndroid Build Coastguard Worker         }
221*344aa361SAndroid Build Coastguard Worker         *fragment_len = smc_ret.r3;
222*344aa361SAndroid Build Coastguard Worker         return NO_ERROR;
223*344aa361SAndroid Build Coastguard Worker     }
224*344aa361SAndroid Build Coastguard Worker     case SMC_FC_FFA_ERROR:
225*344aa361SAndroid Build Coastguard Worker         switch ((int)smc_ret.r2) {
226*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_NOT_SUPPORTED:
227*344aa361SAndroid Build Coastguard Worker             return ERR_NOT_SUPPORTED;
228*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_INVALID_PARAMETERS:
229*344aa361SAndroid Build Coastguard Worker             return ERR_INVALID_ARGS;
230*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_ABORTED:
231*344aa361SAndroid Build Coastguard Worker             return ERR_CANCELLED;
232*344aa361SAndroid Build Coastguard Worker         default:
233*344aa361SAndroid Build Coastguard Worker             TRACEF("Unexpected error %d\n", (int)smc_ret.r2);
234*344aa361SAndroid Build Coastguard Worker             return ERR_NOT_VALID;
235*344aa361SAndroid Build Coastguard Worker         }
236*344aa361SAndroid Build Coastguard Worker     default:
237*344aa361SAndroid Build Coastguard Worker         TRACEF("Unexpected function id returned 0x%08lx\n", smc_ret.r0);
238*344aa361SAndroid Build Coastguard Worker         return ERR_NOT_VALID;
239*344aa361SAndroid Build Coastguard Worker     }
240*344aa361SAndroid Build Coastguard Worker }
241*344aa361SAndroid Build Coastguard Worker 
arm_ffa_call_mem_relinquish(uint64_t handle,uint32_t flags,uint32_t endpoint_count,const ffa_endpoint_id16_t * endpoints)242*344aa361SAndroid Build Coastguard Worker static status_t arm_ffa_call_mem_relinquish(
243*344aa361SAndroid Build Coastguard Worker         uint64_t handle,
244*344aa361SAndroid Build Coastguard Worker         uint32_t flags,
245*344aa361SAndroid Build Coastguard Worker         uint32_t endpoint_count,
246*344aa361SAndroid Build Coastguard Worker         const ffa_endpoint_id16_t* endpoints) {
247*344aa361SAndroid Build Coastguard Worker     struct smc_ret8 smc_ret;
248*344aa361SAndroid Build Coastguard Worker     struct ffa_mem_relinquish_descriptor* req = ffa_tx;
249*344aa361SAndroid Build Coastguard Worker 
250*344aa361SAndroid Build Coastguard Worker     if (!req) {
251*344aa361SAndroid Build Coastguard Worker         TRACEF("ERROR: no FF-A tx buffer\n");
252*344aa361SAndroid Build Coastguard Worker         return ERR_NOT_CONFIGURED;
253*344aa361SAndroid Build Coastguard Worker     }
254*344aa361SAndroid Build Coastguard Worker     ASSERT(endpoint_count <=
255*344aa361SAndroid Build Coastguard Worker            (ffa_buf_size - sizeof(struct ffa_mem_relinquish_descriptor)) /
256*344aa361SAndroid Build Coastguard Worker                    sizeof(ffa_endpoint_id16_t));
257*344aa361SAndroid Build Coastguard Worker 
258*344aa361SAndroid Build Coastguard Worker     mutex_acquire(&ffa_rxtx_buffer_lock);
259*344aa361SAndroid Build Coastguard Worker 
260*344aa361SAndroid Build Coastguard Worker     req->handle = handle;
261*344aa361SAndroid Build Coastguard Worker     req->flags = flags;
262*344aa361SAndroid Build Coastguard Worker     req->endpoint_count = endpoint_count;
263*344aa361SAndroid Build Coastguard Worker 
264*344aa361SAndroid Build Coastguard Worker     memcpy(req->endpoint_array, endpoints,
265*344aa361SAndroid Build Coastguard Worker            endpoint_count * sizeof(ffa_endpoint_id16_t));
266*344aa361SAndroid Build Coastguard Worker 
267*344aa361SAndroid Build Coastguard Worker     smc_ret = smc8(SMC_FC_FFA_MEM_RELINQUISH, 0, 0, 0, 0, 0, 0, 0);
268*344aa361SAndroid Build Coastguard Worker 
269*344aa361SAndroid Build Coastguard Worker     mutex_release(&ffa_rxtx_buffer_lock);
270*344aa361SAndroid Build Coastguard Worker 
271*344aa361SAndroid Build Coastguard Worker     switch (smc_ret.r0) {
272*344aa361SAndroid Build Coastguard Worker     case SMC_FC_FFA_SUCCESS:
273*344aa361SAndroid Build Coastguard Worker     case SMC_FC64_FFA_SUCCESS:
274*344aa361SAndroid Build Coastguard Worker         return NO_ERROR;
275*344aa361SAndroid Build Coastguard Worker 
276*344aa361SAndroid Build Coastguard Worker     case SMC_FC_FFA_ERROR:
277*344aa361SAndroid Build Coastguard Worker         switch ((int)smc_ret.r2) {
278*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_NOT_SUPPORTED:
279*344aa361SAndroid Build Coastguard Worker             return ERR_NOT_SUPPORTED;
280*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_INVALID_PARAMETERS:
281*344aa361SAndroid Build Coastguard Worker             return ERR_INVALID_ARGS;
282*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_NO_MEMORY:
283*344aa361SAndroid Build Coastguard Worker             return ERR_NO_MEMORY;
284*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_DENIED:
285*344aa361SAndroid Build Coastguard Worker             return ERR_BAD_STATE;
286*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_ABORTED:
287*344aa361SAndroid Build Coastguard Worker             return ERR_CANCELLED;
288*344aa361SAndroid Build Coastguard Worker         default:
289*344aa361SAndroid Build Coastguard Worker             TRACEF("Unexpected FFA_ERROR: %lx\n", smc_ret.r2);
290*344aa361SAndroid Build Coastguard Worker             return ERR_NOT_VALID;
291*344aa361SAndroid Build Coastguard Worker         }
292*344aa361SAndroid Build Coastguard Worker     default:
293*344aa361SAndroid Build Coastguard Worker         TRACEF("Unexpected FFA SMC: %lx\n", smc_ret.r0);
294*344aa361SAndroid Build Coastguard Worker         return ERR_NOT_VALID;
295*344aa361SAndroid Build Coastguard Worker     }
296*344aa361SAndroid Build Coastguard Worker }
297*344aa361SAndroid Build Coastguard Worker 
arm_ffa_call_rxtx_map(paddr_t tx_paddr,paddr_t rx_paddr,size_t page_count)298*344aa361SAndroid Build Coastguard Worker static status_t arm_ffa_call_rxtx_map(paddr_t tx_paddr,
299*344aa361SAndroid Build Coastguard Worker                                       paddr_t rx_paddr,
300*344aa361SAndroid Build Coastguard Worker                                       size_t page_count) {
301*344aa361SAndroid Build Coastguard Worker     struct smc_ret8 smc_ret;
302*344aa361SAndroid Build Coastguard Worker 
303*344aa361SAndroid Build Coastguard Worker     /* Page count specified in bits [0:5] */
304*344aa361SAndroid Build Coastguard Worker     ASSERT(page_count);
305*344aa361SAndroid Build Coastguard Worker     ASSERT(page_count < (1 << 6));
306*344aa361SAndroid Build Coastguard Worker 
307*344aa361SAndroid Build Coastguard Worker #if ARCH_ARM64
308*344aa361SAndroid Build Coastguard Worker     smc_ret = smc8(SMC_FC64_FFA_RXTX_MAP, tx_paddr, rx_paddr, page_count, 0, 0,
309*344aa361SAndroid Build Coastguard Worker                    0, 0);
310*344aa361SAndroid Build Coastguard Worker #else
311*344aa361SAndroid Build Coastguard Worker     smc_ret = smc8(SMC_FC_FFA_RXTX_MAP, tx_paddr, rx_paddr, page_count, 0, 0, 0,
312*344aa361SAndroid Build Coastguard Worker                    0);
313*344aa361SAndroid Build Coastguard Worker #endif
314*344aa361SAndroid Build Coastguard Worker     switch (smc_ret.r0) {
315*344aa361SAndroid Build Coastguard Worker     case SMC_FC_FFA_SUCCESS:
316*344aa361SAndroid Build Coastguard Worker     case SMC_FC64_FFA_SUCCESS:
317*344aa361SAndroid Build Coastguard Worker         return NO_ERROR;
318*344aa361SAndroid Build Coastguard Worker 
319*344aa361SAndroid Build Coastguard Worker     case SMC_FC_FFA_ERROR:
320*344aa361SAndroid Build Coastguard Worker         switch ((int)smc_ret.r2) {
321*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_NOT_SUPPORTED:
322*344aa361SAndroid Build Coastguard Worker             return ERR_NOT_SUPPORTED;
323*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_INVALID_PARAMETERS:
324*344aa361SAndroid Build Coastguard Worker             return ERR_INVALID_ARGS;
325*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_NO_MEMORY:
326*344aa361SAndroid Build Coastguard Worker             return ERR_NO_MEMORY;
327*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_DENIED:
328*344aa361SAndroid Build Coastguard Worker             return ERR_ALREADY_EXISTS;
329*344aa361SAndroid Build Coastguard Worker         default:
330*344aa361SAndroid Build Coastguard Worker             TRACEF("Unexpected FFA_ERROR: %lx\n", smc_ret.r2);
331*344aa361SAndroid Build Coastguard Worker             return ERR_NOT_VALID;
332*344aa361SAndroid Build Coastguard Worker         }
333*344aa361SAndroid Build Coastguard Worker     default:
334*344aa361SAndroid Build Coastguard Worker         TRACEF("Unexpected FFA SMC: %lx\n", smc_ret.r0);
335*344aa361SAndroid Build Coastguard Worker         return ERR_NOT_VALID;
336*344aa361SAndroid Build Coastguard Worker     }
337*344aa361SAndroid Build Coastguard Worker }
338*344aa361SAndroid Build Coastguard Worker 
arm_ffa_call_rx_release(void)339*344aa361SAndroid Build Coastguard Worker static status_t arm_ffa_call_rx_release(void) {
340*344aa361SAndroid Build Coastguard Worker     struct smc_ret8 smc_ret;
341*344aa361SAndroid Build Coastguard Worker 
342*344aa361SAndroid Build Coastguard Worker     DEBUG_ASSERT(is_mutex_held(&ffa_rxtx_buffer_lock));
343*344aa361SAndroid Build Coastguard Worker 
344*344aa361SAndroid Build Coastguard Worker     smc_ret = smc8(SMC_FC_FFA_RX_RELEASE, 0, 0, 0, 0, 0, 0, 0);
345*344aa361SAndroid Build Coastguard Worker     switch (smc_ret.r0) {
346*344aa361SAndroid Build Coastguard Worker     case SMC_FC_FFA_SUCCESS:
347*344aa361SAndroid Build Coastguard Worker     case SMC_FC64_FFA_SUCCESS:
348*344aa361SAndroid Build Coastguard Worker         return NO_ERROR;
349*344aa361SAndroid Build Coastguard Worker 
350*344aa361SAndroid Build Coastguard Worker     case SMC_FC_FFA_ERROR:
351*344aa361SAndroid Build Coastguard Worker         switch ((int)smc_ret.r2) {
352*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_NOT_SUPPORTED:
353*344aa361SAndroid Build Coastguard Worker             return ERR_NOT_SUPPORTED;
354*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_DENIED:
355*344aa361SAndroid Build Coastguard Worker             return ERR_BAD_STATE;
356*344aa361SAndroid Build Coastguard Worker         default:
357*344aa361SAndroid Build Coastguard Worker             return ERR_NOT_VALID;
358*344aa361SAndroid Build Coastguard Worker         }
359*344aa361SAndroid Build Coastguard Worker     default:
360*344aa361SAndroid Build Coastguard Worker         return ERR_NOT_VALID;
361*344aa361SAndroid Build Coastguard Worker     }
362*344aa361SAndroid Build Coastguard Worker }
363*344aa361SAndroid Build Coastguard Worker 
364*344aa361SAndroid Build Coastguard Worker #if WITH_SMP
ffa_call_secondary_ep_register(void)365*344aa361SAndroid Build Coastguard Worker static status_t ffa_call_secondary_ep_register(void) {
366*344aa361SAndroid Build Coastguard Worker     struct smc_ret8 smc_ret;
367*344aa361SAndroid Build Coastguard Worker     paddr_t secondary_ep_paddr;
368*344aa361SAndroid Build Coastguard Worker     extern char _start[];
369*344aa361SAndroid Build Coastguard Worker 
370*344aa361SAndroid Build Coastguard Worker     secondary_ep_paddr = vaddr_to_paddr(_start);
371*344aa361SAndroid Build Coastguard Worker 
372*344aa361SAndroid Build Coastguard Worker     smc_ret = smc8(SMC_FC64_FFA_SECONDARY_EP_REGISTER, secondary_ep_paddr, 0, 0,
373*344aa361SAndroid Build Coastguard Worker                    0, 0, 0, 0);
374*344aa361SAndroid Build Coastguard Worker     switch ((uint32_t)smc_ret.r0) {
375*344aa361SAndroid Build Coastguard Worker     case SMC_FC_FFA_SUCCESS:
376*344aa361SAndroid Build Coastguard Worker     case SMC_FC64_FFA_SUCCESS:
377*344aa361SAndroid Build Coastguard Worker         return NO_ERROR;
378*344aa361SAndroid Build Coastguard Worker 
379*344aa361SAndroid Build Coastguard Worker     case SMC_FC_FFA_ERROR:
380*344aa361SAndroid Build Coastguard Worker         switch ((int)smc_ret.r2) {
381*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_NOT_SUPPORTED:
382*344aa361SAndroid Build Coastguard Worker             return ERR_NOT_SUPPORTED;
383*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_INVALID_PARAMETERS:
384*344aa361SAndroid Build Coastguard Worker             return ERR_INVALID_ARGS;
385*344aa361SAndroid Build Coastguard Worker         default:
386*344aa361SAndroid Build Coastguard Worker             return ERR_NOT_VALID;
387*344aa361SAndroid Build Coastguard Worker         }
388*344aa361SAndroid Build Coastguard Worker 
389*344aa361SAndroid Build Coastguard Worker     case SMC_UNKNOWN:
390*344aa361SAndroid Build Coastguard Worker         return ERR_NOT_SUPPORTED;
391*344aa361SAndroid Build Coastguard Worker 
392*344aa361SAndroid Build Coastguard Worker     default:
393*344aa361SAndroid Build Coastguard Worker         return ERR_NOT_VALID;
394*344aa361SAndroid Build Coastguard Worker     }
395*344aa361SAndroid Build Coastguard Worker }
396*344aa361SAndroid Build Coastguard Worker #endif /* WITH_SMP */
397*344aa361SAndroid Build Coastguard Worker 
arm_ffa_call_error(enum ffa_error err)398*344aa361SAndroid Build Coastguard Worker struct smc_ret8 arm_ffa_call_error(enum ffa_error err) {
399*344aa361SAndroid Build Coastguard Worker     long target = 0; /* Target must be zero (MBZ) at secure FF-A instances */
400*344aa361SAndroid Build Coastguard Worker     return smc8(SMC_FC_FFA_ERROR, target, (ulong)err, 0, 0, 0, 0, 0);
401*344aa361SAndroid Build Coastguard Worker }
402*344aa361SAndroid Build Coastguard Worker 
arm_ffa_call_msg_wait(void)403*344aa361SAndroid Build Coastguard Worker struct smc_ret8 arm_ffa_call_msg_wait(void) {
404*344aa361SAndroid Build Coastguard Worker     return smc8(SMC_FC_FFA_MSG_WAIT, 0, 0, 0, 0, 0, 0, 0);
405*344aa361SAndroid Build Coastguard Worker }
406*344aa361SAndroid Build Coastguard Worker 
arm_ffa_msg_send_direct_resp(const struct smc_ret8 * direct_req_regs,ulong a0,ulong a1,ulong a2,ulong a3,ulong a4)407*344aa361SAndroid Build Coastguard Worker struct smc_ret8 arm_ffa_msg_send_direct_resp(
408*344aa361SAndroid Build Coastguard Worker         const struct smc_ret8* direct_req_regs,
409*344aa361SAndroid Build Coastguard Worker         ulong a0,
410*344aa361SAndroid Build Coastguard Worker         ulong a1,
411*344aa361SAndroid Build Coastguard Worker         ulong a2,
412*344aa361SAndroid Build Coastguard Worker         ulong a3,
413*344aa361SAndroid Build Coastguard Worker         ulong a4) {
414*344aa361SAndroid Build Coastguard Worker     ulong fid;
415*344aa361SAndroid Build Coastguard Worker     uint32_t sender_receiver_id;
416*344aa361SAndroid Build Coastguard Worker     uint32_t flags;
417*344aa361SAndroid Build Coastguard Worker 
418*344aa361SAndroid Build Coastguard Worker     DEBUG_ASSERT(direct_req_regs);
419*344aa361SAndroid Build Coastguard Worker     switch (direct_req_regs->r0) {
420*344aa361SAndroid Build Coastguard Worker     case SMC_FC_FFA_MSG_SEND_DIRECT_REQ:
421*344aa361SAndroid Build Coastguard Worker         fid = SMC_FC_FFA_MSG_SEND_DIRECT_RESP;
422*344aa361SAndroid Build Coastguard Worker         break;
423*344aa361SAndroid Build Coastguard Worker     case SMC_FC64_FFA_MSG_SEND_DIRECT_REQ:
424*344aa361SAndroid Build Coastguard Worker         fid = SMC_FC64_FFA_MSG_SEND_DIRECT_RESP;
425*344aa361SAndroid Build Coastguard Worker         break;
426*344aa361SAndroid Build Coastguard Worker     default:
427*344aa361SAndroid Build Coastguard Worker         dprintf(CRITICAL, "Invalid direct request function id %lx\n",
428*344aa361SAndroid Build Coastguard Worker                 direct_req_regs->r0);
429*344aa361SAndroid Build Coastguard Worker         return arm_ffa_call_error(FFA_ERROR_INVALID_PARAMETERS);
430*344aa361SAndroid Build Coastguard Worker     }
431*344aa361SAndroid Build Coastguard Worker 
432*344aa361SAndroid Build Coastguard Worker     /* Copy and flip the sender from the direct message request */
433*344aa361SAndroid Build Coastguard Worker     sender_receiver_id =
434*344aa361SAndroid Build Coastguard Worker             (direct_req_regs->r1 >> 16) | ((uint32_t)ffa_local_id << 16);
435*344aa361SAndroid Build Coastguard Worker     /* Copy the flags as well */
436*344aa361SAndroid Build Coastguard Worker     flags = direct_req_regs->r2;
437*344aa361SAndroid Build Coastguard Worker 
438*344aa361SAndroid Build Coastguard Worker     return smc8(fid, sender_receiver_id, flags, a0, a1, a2, a3, a4);
439*344aa361SAndroid Build Coastguard Worker }
440*344aa361SAndroid Build Coastguard Worker 
arm_ffa_console_log(const char * buf,size_t len)441*344aa361SAndroid Build Coastguard Worker ssize_t arm_ffa_console_log(const char* buf, size_t len) {
442*344aa361SAndroid Build Coastguard Worker     struct smc_ret8 smc_ret;
443*344aa361SAndroid Build Coastguard Worker 
444*344aa361SAndroid Build Coastguard Worker     if (console_log_is_unsupported) {
445*344aa361SAndroid Build Coastguard Worker         return ERR_NOT_SUPPORTED;
446*344aa361SAndroid Build Coastguard Worker     }
447*344aa361SAndroid Build Coastguard Worker     if (!len) {
448*344aa361SAndroid Build Coastguard Worker         /* Nothing to print, just return */
449*344aa361SAndroid Build Coastguard Worker         return 0;
450*344aa361SAndroid Build Coastguard Worker     }
451*344aa361SAndroid Build Coastguard Worker     if (len != 1) {
452*344aa361SAndroid Build Coastguard Worker         /* TODO: support more than one character */
453*344aa361SAndroid Build Coastguard Worker         len = 1;
454*344aa361SAndroid Build Coastguard Worker     }
455*344aa361SAndroid Build Coastguard Worker 
456*344aa361SAndroid Build Coastguard Worker     smc_ret = smc8(SMC_FC_FFA_CONSOLE_LOG, len, (ulong)buf[0], 0, 0, 0, 0, 0);
457*344aa361SAndroid Build Coastguard Worker     switch ((uint32_t)smc_ret.r0) {
458*344aa361SAndroid Build Coastguard Worker     case SMC_FC_FFA_SUCCESS:
459*344aa361SAndroid Build Coastguard Worker     case SMC_FC64_FFA_SUCCESS:
460*344aa361SAndroid Build Coastguard Worker         return len;
461*344aa361SAndroid Build Coastguard Worker 
462*344aa361SAndroid Build Coastguard Worker     case SMC_FC_FFA_ERROR:
463*344aa361SAndroid Build Coastguard Worker         switch ((int32_t)smc_ret.r2) {
464*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_NOT_SUPPORTED:
465*344aa361SAndroid Build Coastguard Worker             console_log_is_unsupported = true;
466*344aa361SAndroid Build Coastguard Worker             return ERR_NOT_SUPPORTED;
467*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_INVALID_PARAMETERS:
468*344aa361SAndroid Build Coastguard Worker             return ERR_INVALID_ARGS;
469*344aa361SAndroid Build Coastguard Worker         case FFA_ERROR_RETRY:
470*344aa361SAndroid Build Coastguard Worker             /* FFA_ERROR_RETRY returns how many characters were printed */
471*344aa361SAndroid Build Coastguard Worker             return (uint32_t)smc_ret.r3;
472*344aa361SAndroid Build Coastguard Worker         default:
473*344aa361SAndroid Build Coastguard Worker             return ERR_NOT_VALID;
474*344aa361SAndroid Build Coastguard Worker         }
475*344aa361SAndroid Build Coastguard Worker 
476*344aa361SAndroid Build Coastguard Worker     case SMC_UNKNOWN:
477*344aa361SAndroid Build Coastguard Worker         console_log_is_unsupported = true;
478*344aa361SAndroid Build Coastguard Worker         return ERR_NOT_SUPPORTED;
479*344aa361SAndroid Build Coastguard Worker 
480*344aa361SAndroid Build Coastguard Worker     default:
481*344aa361SAndroid Build Coastguard Worker         return ERR_NOT_VALID;
482*344aa361SAndroid Build Coastguard Worker     }
483*344aa361SAndroid Build Coastguard Worker }
484*344aa361SAndroid Build Coastguard Worker 
arm_ffa_rx_release_is_implemented(bool * is_implemented)485*344aa361SAndroid Build Coastguard Worker static status_t arm_ffa_rx_release_is_implemented(bool* is_implemented) {
486*344aa361SAndroid Build Coastguard Worker     bool is_implemented_val;
487*344aa361SAndroid Build Coastguard Worker     status_t res = arm_ffa_call_features(SMC_FC_FFA_RX_RELEASE,
488*344aa361SAndroid Build Coastguard Worker                                          &is_implemented_val, NULL, NULL);
489*344aa361SAndroid Build Coastguard Worker     if (res != NO_ERROR) {
490*344aa361SAndroid Build Coastguard Worker         TRACEF("Failed to query for feature FFA_RX_RELEASE, err = %d\n", res);
491*344aa361SAndroid Build Coastguard Worker         return res;
492*344aa361SAndroid Build Coastguard Worker     }
493*344aa361SAndroid Build Coastguard Worker     if (is_implemented) {
494*344aa361SAndroid Build Coastguard Worker         *is_implemented = is_implemented_val;
495*344aa361SAndroid Build Coastguard Worker     }
496*344aa361SAndroid Build Coastguard Worker     return NO_ERROR;
497*344aa361SAndroid Build Coastguard Worker }
498*344aa361SAndroid Build Coastguard Worker 
arm_ffa_rxtx_map_is_implemented(bool * is_implemented,size_t * buf_size_log2)499*344aa361SAndroid Build Coastguard Worker static status_t arm_ffa_rxtx_map_is_implemented(bool* is_implemented,
500*344aa361SAndroid Build Coastguard Worker                                                 size_t* buf_size_log2) {
501*344aa361SAndroid Build Coastguard Worker     ffa_features2_t features2;
502*344aa361SAndroid Build Coastguard Worker     bool is_implemented_val = false;
503*344aa361SAndroid Build Coastguard Worker     status_t res;
504*344aa361SAndroid Build Coastguard Worker 
505*344aa361SAndroid Build Coastguard Worker     ASSERT(is_implemented);
506*344aa361SAndroid Build Coastguard Worker #if ARCH_ARM64
507*344aa361SAndroid Build Coastguard Worker     res = arm_ffa_call_features(SMC_FC64_FFA_RXTX_MAP, &is_implemented_val,
508*344aa361SAndroid Build Coastguard Worker                                 &features2, NULL);
509*344aa361SAndroid Build Coastguard Worker #else
510*344aa361SAndroid Build Coastguard Worker     res = arm_ffa_call_features(SMC_FC_FFA_RXTX_MAP, &is_implemented_val,
511*344aa361SAndroid Build Coastguard Worker                                 &features2, NULL);
512*344aa361SAndroid Build Coastguard Worker #endif
513*344aa361SAndroid Build Coastguard Worker     if (res != NO_ERROR) {
514*344aa361SAndroid Build Coastguard Worker         TRACEF("Failed to query for feature FFA_RXTX_MAP, err = %d\n", res);
515*344aa361SAndroid Build Coastguard Worker         return res;
516*344aa361SAndroid Build Coastguard Worker     }
517*344aa361SAndroid Build Coastguard Worker     if (!is_implemented_val) {
518*344aa361SAndroid Build Coastguard Worker         *is_implemented = false;
519*344aa361SAndroid Build Coastguard Worker         return NO_ERROR;
520*344aa361SAndroid Build Coastguard Worker     }
521*344aa361SAndroid Build Coastguard Worker     if (buf_size_log2) {
522*344aa361SAndroid Build Coastguard Worker         ulong buf_size_id = features2 & FFA_FEATURES2_RXTX_MAP_BUF_SIZE_MASK;
523*344aa361SAndroid Build Coastguard Worker         switch (buf_size_id) {
524*344aa361SAndroid Build Coastguard Worker         case FFA_FEATURES2_RXTX_MAP_BUF_SIZE_4K:
525*344aa361SAndroid Build Coastguard Worker             *buf_size_log2 = 12;
526*344aa361SAndroid Build Coastguard Worker             break;
527*344aa361SAndroid Build Coastguard Worker         case FFA_FEATURES2_RXTX_MAP_BUF_SIZE_16K:
528*344aa361SAndroid Build Coastguard Worker             *buf_size_log2 = 14;
529*344aa361SAndroid Build Coastguard Worker             break;
530*344aa361SAndroid Build Coastguard Worker         case FFA_FEATURES2_RXTX_MAP_BUF_SIZE_64K:
531*344aa361SAndroid Build Coastguard Worker             *buf_size_log2 = 16;
532*344aa361SAndroid Build Coastguard Worker             break;
533*344aa361SAndroid Build Coastguard Worker         default:
534*344aa361SAndroid Build Coastguard Worker             TRACEF("Unexpected rxtx buffer size identifier: %lx\n",
535*344aa361SAndroid Build Coastguard Worker                    buf_size_id);
536*344aa361SAndroid Build Coastguard Worker             return ERR_NOT_VALID;
537*344aa361SAndroid Build Coastguard Worker         }
538*344aa361SAndroid Build Coastguard Worker     }
539*344aa361SAndroid Build Coastguard Worker 
540*344aa361SAndroid Build Coastguard Worker     *is_implemented = true;
541*344aa361SAndroid Build Coastguard Worker     return NO_ERROR;
542*344aa361SAndroid Build Coastguard Worker }
543*344aa361SAndroid Build Coastguard Worker 
arm_ffa_mem_retrieve_req_is_implemented(bool * is_implemented,bool * dyn_alloc_supp,bool * has_ns_bit,size_t * ref_count_num_bits)544*344aa361SAndroid Build Coastguard Worker static status_t arm_ffa_mem_retrieve_req_is_implemented(
545*344aa361SAndroid Build Coastguard Worker         bool* is_implemented,
546*344aa361SAndroid Build Coastguard Worker         bool* dyn_alloc_supp,
547*344aa361SAndroid Build Coastguard Worker         bool* has_ns_bit,
548*344aa361SAndroid Build Coastguard Worker         size_t* ref_count_num_bits) {
549*344aa361SAndroid Build Coastguard Worker     ffa_features2_t features2;
550*344aa361SAndroid Build Coastguard Worker     ffa_features3_t features3;
551*344aa361SAndroid Build Coastguard Worker     bool is_implemented_val = false;
552*344aa361SAndroid Build Coastguard Worker     status_t res;
553*344aa361SAndroid Build Coastguard Worker 
554*344aa361SAndroid Build Coastguard Worker     ASSERT(is_implemented);
555*344aa361SAndroid Build Coastguard Worker 
556*344aa361SAndroid Build Coastguard Worker     res = arm_ffa_call_features(SMC_FC_FFA_MEM_RETRIEVE_REQ,
557*344aa361SAndroid Build Coastguard Worker                                 &is_implemented_val, &features2, &features3);
558*344aa361SAndroid Build Coastguard Worker     if (res != NO_ERROR) {
559*344aa361SAndroid Build Coastguard Worker         TRACEF("Failed to query for feature FFA_MEM_RETRIEVE_REQ, err = %d\n",
560*344aa361SAndroid Build Coastguard Worker                res);
561*344aa361SAndroid Build Coastguard Worker         return res;
562*344aa361SAndroid Build Coastguard Worker     }
563*344aa361SAndroid Build Coastguard Worker     if (!is_implemented_val) {
564*344aa361SAndroid Build Coastguard Worker         *is_implemented = false;
565*344aa361SAndroid Build Coastguard Worker         return NO_ERROR;
566*344aa361SAndroid Build Coastguard Worker     }
567*344aa361SAndroid Build Coastguard Worker     if (dyn_alloc_supp) {
568*344aa361SAndroid Build Coastguard Worker         *dyn_alloc_supp = !!(features2 & FFA_FEATURES2_MEM_DYNAMIC_BUFFER);
569*344aa361SAndroid Build Coastguard Worker     }
570*344aa361SAndroid Build Coastguard Worker     if (has_ns_bit) {
571*344aa361SAndroid Build Coastguard Worker         *has_ns_bit = !!(features2 & FFA_FEATURES2_MEM_RETRIEVE_REQ_NS_BIT);
572*344aa361SAndroid Build Coastguard Worker     }
573*344aa361SAndroid Build Coastguard Worker     if (ref_count_num_bits) {
574*344aa361SAndroid Build Coastguard Worker         *ref_count_num_bits =
575*344aa361SAndroid Build Coastguard Worker                 (features3 & FFA_FEATURES3_MEM_RETRIEVE_REQ_REFCOUNT_MASK) + 1;
576*344aa361SAndroid Build Coastguard Worker     }
577*344aa361SAndroid Build Coastguard Worker     *is_implemented = true;
578*344aa361SAndroid Build Coastguard Worker     return NO_ERROR;
579*344aa361SAndroid Build Coastguard Worker }
580*344aa361SAndroid Build Coastguard Worker 
581*344aa361SAndroid Build Coastguard Worker /* Helper function to set up the tx buffer with standard values
582*344aa361SAndroid Build Coastguard Worker    before calling FFA_MEM_RETRIEVE_REQ. */
arm_ffa_populate_receive_req_tx_buffer(uint16_t sender_id,uint64_t handle,uint64_t tag)583*344aa361SAndroid Build Coastguard Worker static void arm_ffa_populate_receive_req_tx_buffer(uint16_t sender_id,
584*344aa361SAndroid Build Coastguard Worker                                                    uint64_t handle,
585*344aa361SAndroid Build Coastguard Worker                                                    uint64_t tag) {
586*344aa361SAndroid Build Coastguard Worker     struct ffa_mtd* req = ffa_tx;
587*344aa361SAndroid Build Coastguard Worker     DEBUG_ASSERT(is_mutex_held(&ffa_rxtx_buffer_lock));
588*344aa361SAndroid Build Coastguard Worker 
589*344aa361SAndroid Build Coastguard Worker     memset(req, 0, sizeof(struct ffa_mtd));
590*344aa361SAndroid Build Coastguard Worker 
591*344aa361SAndroid Build Coastguard Worker     req->sender_id = sender_id;
592*344aa361SAndroid Build Coastguard Worker     req->handle = handle;
593*344aa361SAndroid Build Coastguard Worker     /* We must use the same tag as the one used by the sender to retrieve. */
594*344aa361SAndroid Build Coastguard Worker     req->tag = tag;
595*344aa361SAndroid Build Coastguard Worker 
596*344aa361SAndroid Build Coastguard Worker     /*
597*344aa361SAndroid Build Coastguard Worker      * We only support retrieving memory for ourselves for now.
598*344aa361SAndroid Build Coastguard Worker      * TODO: Also support stream endpoints. Possibly more than one.
599*344aa361SAndroid Build Coastguard Worker      */
600*344aa361SAndroid Build Coastguard Worker     req->emad_count = 1;
601*344aa361SAndroid Build Coastguard Worker     memset(req->emad, 0, sizeof(struct ffa_emad));
602*344aa361SAndroid Build Coastguard Worker     req->emad[0].mapd.endpoint_id = ffa_local_id;
603*344aa361SAndroid Build Coastguard Worker }
604*344aa361SAndroid Build Coastguard Worker 
605*344aa361SAndroid Build Coastguard Worker /* *desc_buffer is malloc'd and on success passes responsibility to free to
606*344aa361SAndroid Build Coastguard Worker    the caller. Populate the tx buffer before calling. */
arm_ffa_mem_retrieve(uint16_t sender_id,uint64_t handle,uint32_t * len,uint32_t * fragment_len)607*344aa361SAndroid Build Coastguard Worker static status_t arm_ffa_mem_retrieve(uint16_t sender_id,
608*344aa361SAndroid Build Coastguard Worker                                      uint64_t handle,
609*344aa361SAndroid Build Coastguard Worker                                      uint32_t* len,
610*344aa361SAndroid Build Coastguard Worker                                      uint32_t* fragment_len) {
611*344aa361SAndroid Build Coastguard Worker     status_t res = NO_ERROR;
612*344aa361SAndroid Build Coastguard Worker 
613*344aa361SAndroid Build Coastguard Worker     DEBUG_ASSERT(is_mutex_held(&ffa_rxtx_buffer_lock));
614*344aa361SAndroid Build Coastguard Worker     DEBUG_ASSERT(len);
615*344aa361SAndroid Build Coastguard Worker 
616*344aa361SAndroid Build Coastguard Worker     uint32_t len_out, fragment_len_out;
617*344aa361SAndroid Build Coastguard Worker     res = arm_ffa_call_mem_retrieve_req(&len_out, &fragment_len_out);
618*344aa361SAndroid Build Coastguard Worker     LTRACEF("total_len: %u, fragment_len: %u\n", len_out, fragment_len_out);
619*344aa361SAndroid Build Coastguard Worker     if (res != NO_ERROR) {
620*344aa361SAndroid Build Coastguard Worker         TRACEF("FF-A memory retrieve request failed, err = %d\n", res);
621*344aa361SAndroid Build Coastguard Worker         return res;
622*344aa361SAndroid Build Coastguard Worker     }
623*344aa361SAndroid Build Coastguard Worker     if (fragment_len_out > len_out) {
624*344aa361SAndroid Build Coastguard Worker         TRACEF("Fragment length larger than total length %u > %u\n",
625*344aa361SAndroid Build Coastguard Worker                fragment_len_out, len_out);
626*344aa361SAndroid Build Coastguard Worker         return ERR_IO;
627*344aa361SAndroid Build Coastguard Worker     }
628*344aa361SAndroid Build Coastguard Worker 
629*344aa361SAndroid Build Coastguard Worker     /* Check that the first fragment fits in our buffer */
630*344aa361SAndroid Build Coastguard Worker     if (fragment_len_out > ffa_buf_size) {
631*344aa361SAndroid Build Coastguard Worker         TRACEF("Fragment length %u larger than buffer size\n",
632*344aa361SAndroid Build Coastguard Worker                fragment_len_out);
633*344aa361SAndroid Build Coastguard Worker         return ERR_IO;
634*344aa361SAndroid Build Coastguard Worker     }
635*344aa361SAndroid Build Coastguard Worker 
636*344aa361SAndroid Build Coastguard Worker     if (fragment_len) {
637*344aa361SAndroid Build Coastguard Worker         *fragment_len = fragment_len_out;
638*344aa361SAndroid Build Coastguard Worker     }
639*344aa361SAndroid Build Coastguard Worker     if (len) {
640*344aa361SAndroid Build Coastguard Worker         *len = len_out;
641*344aa361SAndroid Build Coastguard Worker     }
642*344aa361SAndroid Build Coastguard Worker 
643*344aa361SAndroid Build Coastguard Worker     return NO_ERROR;
644*344aa361SAndroid Build Coastguard Worker }
645*344aa361SAndroid Build Coastguard Worker 
arm_ffa_mem_address_range_get(struct arm_ffa_mem_frag_info * frag_info,size_t index,paddr_t * addr,size_t * size)646*344aa361SAndroid Build Coastguard Worker status_t arm_ffa_mem_address_range_get(struct arm_ffa_mem_frag_info* frag_info,
647*344aa361SAndroid Build Coastguard Worker                                        size_t index,
648*344aa361SAndroid Build Coastguard Worker                                        paddr_t* addr,
649*344aa361SAndroid Build Coastguard Worker                                        size_t* size) {
650*344aa361SAndroid Build Coastguard Worker     uint32_t page_count;
651*344aa361SAndroid Build Coastguard Worker     size_t frag_idx;
652*344aa361SAndroid Build Coastguard Worker 
653*344aa361SAndroid Build Coastguard Worker     DEBUG_ASSERT(frag_info);
654*344aa361SAndroid Build Coastguard Worker 
655*344aa361SAndroid Build Coastguard Worker     if (index < frag_info->start_index ||
656*344aa361SAndroid Build Coastguard Worker         index >= frag_info->start_index + frag_info->count) {
657*344aa361SAndroid Build Coastguard Worker         return ERR_OUT_OF_RANGE;
658*344aa361SAndroid Build Coastguard Worker     }
659*344aa361SAndroid Build Coastguard Worker 
660*344aa361SAndroid Build Coastguard Worker     frag_idx = index - frag_info->start_index;
661*344aa361SAndroid Build Coastguard Worker 
662*344aa361SAndroid Build Coastguard Worker     page_count = frag_info->address_ranges[frag_idx].page_count;
663*344aa361SAndroid Build Coastguard Worker     LTRACEF("address %p, page_count 0x%x\n",
664*344aa361SAndroid Build Coastguard Worker             (void*)frag_info->address_ranges[frag_idx].address,
665*344aa361SAndroid Build Coastguard Worker             frag_info->address_ranges[frag_idx].page_count);
666*344aa361SAndroid Build Coastguard Worker     if (page_count < 1 || ((size_t)page_count > (SIZE_MAX / FFA_PAGE_SIZE))) {
667*344aa361SAndroid Build Coastguard Worker         TRACEF("bad page count 0x%x at %zu\n", page_count, index);
668*344aa361SAndroid Build Coastguard Worker         return ERR_IO;
669*344aa361SAndroid Build Coastguard Worker     }
670*344aa361SAndroid Build Coastguard Worker 
671*344aa361SAndroid Build Coastguard Worker     if (addr) {
672*344aa361SAndroid Build Coastguard Worker         *addr = (paddr_t)frag_info->address_ranges[frag_idx].address;
673*344aa361SAndroid Build Coastguard Worker     }
674*344aa361SAndroid Build Coastguard Worker     if (size) {
675*344aa361SAndroid Build Coastguard Worker         *size = page_count * FFA_PAGE_SIZE;
676*344aa361SAndroid Build Coastguard Worker     }
677*344aa361SAndroid Build Coastguard Worker 
678*344aa361SAndroid Build Coastguard Worker     return NO_ERROR;
679*344aa361SAndroid Build Coastguard Worker }
680*344aa361SAndroid Build Coastguard Worker 
arm_ffa_mem_retrieve_start(uint16_t sender_id,uint64_t handle,uint64_t tag,uint32_t * address_range_count,uint * arch_mmu_flags,struct arm_ffa_mem_frag_info * frag_info)681*344aa361SAndroid Build Coastguard Worker status_t arm_ffa_mem_retrieve_start(uint16_t sender_id,
682*344aa361SAndroid Build Coastguard Worker                                     uint64_t handle,
683*344aa361SAndroid Build Coastguard Worker                                     uint64_t tag,
684*344aa361SAndroid Build Coastguard Worker                                     uint32_t* address_range_count,
685*344aa361SAndroid Build Coastguard Worker                                     uint* arch_mmu_flags,
686*344aa361SAndroid Build Coastguard Worker                                     struct arm_ffa_mem_frag_info* frag_info) {
687*344aa361SAndroid Build Coastguard Worker     status_t res;
688*344aa361SAndroid Build Coastguard Worker     struct ffa_mtd* mtd;
689*344aa361SAndroid Build Coastguard Worker     struct ffa_emad* emad;
690*344aa361SAndroid Build Coastguard Worker     struct ffa_comp_mrd* comp_mrd;
691*344aa361SAndroid Build Coastguard Worker     uint32_t computed_len;
692*344aa361SAndroid Build Coastguard Worker     uint32_t header_size;
693*344aa361SAndroid Build Coastguard Worker 
694*344aa361SAndroid Build Coastguard Worker     uint32_t total_len;
695*344aa361SAndroid Build Coastguard Worker     uint32_t fragment_len;
696*344aa361SAndroid Build Coastguard Worker 
697*344aa361SAndroid Build Coastguard Worker     DEBUG_ASSERT(frag_info);
698*344aa361SAndroid Build Coastguard Worker 
699*344aa361SAndroid Build Coastguard Worker     mutex_acquire(&ffa_rxtx_buffer_lock);
700*344aa361SAndroid Build Coastguard Worker     arm_ffa_populate_receive_req_tx_buffer(sender_id, handle, tag);
701*344aa361SAndroid Build Coastguard Worker     res = arm_ffa_mem_retrieve(sender_id, handle, &total_len, &fragment_len);
702*344aa361SAndroid Build Coastguard Worker 
703*344aa361SAndroid Build Coastguard Worker     if (res != NO_ERROR) {
704*344aa361SAndroid Build Coastguard Worker         TRACEF("FF-A memory retrieve failed err=%d\n", res);
705*344aa361SAndroid Build Coastguard Worker         return res;
706*344aa361SAndroid Build Coastguard Worker     }
707*344aa361SAndroid Build Coastguard Worker 
708*344aa361SAndroid Build Coastguard Worker     if (fragment_len <
709*344aa361SAndroid Build Coastguard Worker         offsetof(struct ffa_mtd, emad) + sizeof(struct ffa_emad)) {
710*344aa361SAndroid Build Coastguard Worker         TRACEF("Fragment too short for memory transaction descriptor\n");
711*344aa361SAndroid Build Coastguard Worker         return ERR_IO;
712*344aa361SAndroid Build Coastguard Worker     }
713*344aa361SAndroid Build Coastguard Worker 
714*344aa361SAndroid Build Coastguard Worker     mtd = ffa_rx;
715*344aa361SAndroid Build Coastguard Worker     emad = mtd->emad;
716*344aa361SAndroid Build Coastguard Worker 
717*344aa361SAndroid Build Coastguard Worker     /*
718*344aa361SAndroid Build Coastguard Worker      * We don't retrieve the memory on behalf of anyone else, so we only
719*344aa361SAndroid Build Coastguard Worker      * expect one receiver address range descriptor.
720*344aa361SAndroid Build Coastguard Worker      */
721*344aa361SAndroid Build Coastguard Worker     if (mtd->emad_count != 1) {
722*344aa361SAndroid Build Coastguard Worker         TRACEF("unexpected response count %d != 1\n", mtd->emad_count);
723*344aa361SAndroid Build Coastguard Worker         return ERR_IO;
724*344aa361SAndroid Build Coastguard Worker     }
725*344aa361SAndroid Build Coastguard Worker 
726*344aa361SAndroid Build Coastguard Worker     LTRACEF("comp_mrd_offset: %u\n", emad->comp_mrd_offset);
727*344aa361SAndroid Build Coastguard Worker     if (emad->comp_mrd_offset + sizeof(*comp_mrd) > fragment_len) {
728*344aa361SAndroid Build Coastguard Worker         TRACEF("Fragment length %u too short for comp_mrd_offset %u\n",
729*344aa361SAndroid Build Coastguard Worker                fragment_len, emad->comp_mrd_offset);
730*344aa361SAndroid Build Coastguard Worker         return ERR_IO;
731*344aa361SAndroid Build Coastguard Worker     }
732*344aa361SAndroid Build Coastguard Worker 
733*344aa361SAndroid Build Coastguard Worker     comp_mrd = ffa_rx + emad->comp_mrd_offset;
734*344aa361SAndroid Build Coastguard Worker 
735*344aa361SAndroid Build Coastguard Worker     uint32_t address_range_count_out = comp_mrd->address_range_count;
736*344aa361SAndroid Build Coastguard Worker     frag_info->address_ranges = comp_mrd->address_range_array;
737*344aa361SAndroid Build Coastguard Worker     LTRACEF("address_range_count: %u\n", address_range_count_out);
738*344aa361SAndroid Build Coastguard Worker 
739*344aa361SAndroid Build Coastguard Worker     computed_len = emad->comp_mrd_offset +
740*344aa361SAndroid Build Coastguard Worker                    offsetof(struct ffa_comp_mrd, address_range_array) +
741*344aa361SAndroid Build Coastguard Worker                    sizeof(struct ffa_cons_mrd) * comp_mrd->address_range_count;
742*344aa361SAndroid Build Coastguard Worker     if (total_len != computed_len) {
743*344aa361SAndroid Build Coastguard Worker         TRACEF("Reported length %u != computed length %u\n", total_len,
744*344aa361SAndroid Build Coastguard Worker                computed_len);
745*344aa361SAndroid Build Coastguard Worker         return ERR_IO;
746*344aa361SAndroid Build Coastguard Worker     }
747*344aa361SAndroid Build Coastguard Worker 
748*344aa361SAndroid Build Coastguard Worker     header_size = emad->comp_mrd_offset +
749*344aa361SAndroid Build Coastguard Worker                   offsetof(struct ffa_comp_mrd, address_range_array);
750*344aa361SAndroid Build Coastguard Worker     frag_info->count =
751*344aa361SAndroid Build Coastguard Worker             (fragment_len - header_size) / sizeof(struct ffa_cons_mrd);
752*344aa361SAndroid Build Coastguard Worker     LTRACEF("Descriptors in fragment %u\n", frag_info->count);
753*344aa361SAndroid Build Coastguard Worker 
754*344aa361SAndroid Build Coastguard Worker     if (frag_info->count * sizeof(struct ffa_cons_mrd) + header_size !=
755*344aa361SAndroid Build Coastguard Worker         fragment_len) {
756*344aa361SAndroid Build Coastguard Worker         TRACEF("fragment length %u, contains partial descriptor\n",
757*344aa361SAndroid Build Coastguard Worker                fragment_len);
758*344aa361SAndroid Build Coastguard Worker         return ERR_IO;
759*344aa361SAndroid Build Coastguard Worker     }
760*344aa361SAndroid Build Coastguard Worker 
761*344aa361SAndroid Build Coastguard Worker     frag_info->received_len = fragment_len;
762*344aa361SAndroid Build Coastguard Worker     frag_info->start_index = 0;
763*344aa361SAndroid Build Coastguard Worker 
764*344aa361SAndroid Build Coastguard Worker     uint arch_mmu_flags_out = 0;
765*344aa361SAndroid Build Coastguard Worker 
766*344aa361SAndroid Build Coastguard Worker     switch (mtd->flags & FFA_MTD_FLAG_TYPE_MASK) {
767*344aa361SAndroid Build Coastguard Worker     case FFA_MTD_FLAG_TYPE_SHARE_MEMORY:
768*344aa361SAndroid Build Coastguard Worker         /*
769*344aa361SAndroid Build Coastguard Worker          * If memory is shared, assume it is not safe to execute out of. This
770*344aa361SAndroid Build Coastguard Worker          * specifically indicates that another party may have access to the
771*344aa361SAndroid Build Coastguard Worker          * memory.
772*344aa361SAndroid Build Coastguard Worker          */
773*344aa361SAndroid Build Coastguard Worker         arch_mmu_flags_out |= ARCH_MMU_FLAG_PERM_NO_EXECUTE;
774*344aa361SAndroid Build Coastguard Worker         break;
775*344aa361SAndroid Build Coastguard Worker     case FFA_MTD_FLAG_TYPE_LEND_MEMORY:
776*344aa361SAndroid Build Coastguard Worker         break;
777*344aa361SAndroid Build Coastguard Worker     case FFA_MTD_FLAG_TYPE_DONATE_MEMORY:
778*344aa361SAndroid Build Coastguard Worker         TRACEF("Unexpected donate memory transaction type is not supported\n");
779*344aa361SAndroid Build Coastguard Worker         return ERR_NOT_IMPLEMENTED;
780*344aa361SAndroid Build Coastguard Worker     default:
781*344aa361SAndroid Build Coastguard Worker         TRACEF("Unknown memory transaction type: 0x%x\n", mtd->flags);
782*344aa361SAndroid Build Coastguard Worker         return ERR_NOT_VALID;
783*344aa361SAndroid Build Coastguard Worker     }
784*344aa361SAndroid Build Coastguard Worker 
785*344aa361SAndroid Build Coastguard Worker     switch (mtd->memory_region_attributes & ~FFA_MEM_ATTR_NONSECURE) {
786*344aa361SAndroid Build Coastguard Worker     case FFA_MEM_ATTR_DEVICE_NGNRE:
787*344aa361SAndroid Build Coastguard Worker         arch_mmu_flags_out |= ARCH_MMU_FLAG_UNCACHED_DEVICE;
788*344aa361SAndroid Build Coastguard Worker         break;
789*344aa361SAndroid Build Coastguard Worker     case FFA_MEM_ATTR_NORMAL_MEMORY_UNCACHED:
790*344aa361SAndroid Build Coastguard Worker         arch_mmu_flags_out |= ARCH_MMU_FLAG_UNCACHED;
791*344aa361SAndroid Build Coastguard Worker         break;
792*344aa361SAndroid Build Coastguard Worker     case (FFA_MEM_ATTR_NORMAL_MEMORY_CACHED_WB | FFA_MEM_ATTR_INNER_SHAREABLE):
793*344aa361SAndroid Build Coastguard Worker         arch_mmu_flags_out |= ARCH_MMU_FLAG_CACHED;
794*344aa361SAndroid Build Coastguard Worker         break;
795*344aa361SAndroid Build Coastguard Worker     default:
796*344aa361SAndroid Build Coastguard Worker         TRACEF("Invalid memory attributes, 0x%x\n",
797*344aa361SAndroid Build Coastguard Worker                mtd->memory_region_attributes);
798*344aa361SAndroid Build Coastguard Worker         return ERR_NOT_VALID;
799*344aa361SAndroid Build Coastguard Worker     }
800*344aa361SAndroid Build Coastguard Worker 
801*344aa361SAndroid Build Coastguard Worker     if (!(emad->mapd.memory_access_permissions & FFA_MEM_PERM_RW)) {
802*344aa361SAndroid Build Coastguard Worker         arch_mmu_flags_out |= ARCH_MMU_FLAG_PERM_RO;
803*344aa361SAndroid Build Coastguard Worker     }
804*344aa361SAndroid Build Coastguard Worker     if (emad->mapd.memory_access_permissions & FFA_MEM_PERM_NX) {
805*344aa361SAndroid Build Coastguard Worker         /*
806*344aa361SAndroid Build Coastguard Worker          * Don't allow executable mappings if the stage 2 page tables don't
807*344aa361SAndroid Build Coastguard Worker          * allow it. The hardware allows the stage 2 NX bit to only apply to
808*344aa361SAndroid Build Coastguard Worker          * EL1, not EL0, but neither FF-A nor LK can currently express this, so
809*344aa361SAndroid Build Coastguard Worker          * disallow both if FFA_MEM_PERM_NX is set.
810*344aa361SAndroid Build Coastguard Worker          */
811*344aa361SAndroid Build Coastguard Worker         arch_mmu_flags_out |= ARCH_MMU_FLAG_PERM_NO_EXECUTE;
812*344aa361SAndroid Build Coastguard Worker     }
813*344aa361SAndroid Build Coastguard Worker 
814*344aa361SAndroid Build Coastguard Worker     if (!supports_ns_bit ||
815*344aa361SAndroid Build Coastguard Worker         (mtd->memory_region_attributes & FFA_MEM_ATTR_NONSECURE)) {
816*344aa361SAndroid Build Coastguard Worker         arch_mmu_flags_out |= ARCH_MMU_FLAG_NS;
817*344aa361SAndroid Build Coastguard Worker         /* Regardless of origin, we don't want to execute out of NS memory. */
818*344aa361SAndroid Build Coastguard Worker         arch_mmu_flags_out |= ARCH_MMU_FLAG_PERM_NO_EXECUTE;
819*344aa361SAndroid Build Coastguard Worker     }
820*344aa361SAndroid Build Coastguard Worker 
821*344aa361SAndroid Build Coastguard Worker     if (arch_mmu_flags) {
822*344aa361SAndroid Build Coastguard Worker         *arch_mmu_flags = arch_mmu_flags_out;
823*344aa361SAndroid Build Coastguard Worker     }
824*344aa361SAndroid Build Coastguard Worker     if (address_range_count) {
825*344aa361SAndroid Build Coastguard Worker         *address_range_count = address_range_count_out;
826*344aa361SAndroid Build Coastguard Worker     }
827*344aa361SAndroid Build Coastguard Worker 
828*344aa361SAndroid Build Coastguard Worker     return res;
829*344aa361SAndroid Build Coastguard Worker }
830*344aa361SAndroid Build Coastguard Worker 
831*344aa361SAndroid Build Coastguard Worker /* This assumes that the fragment is completely composed of memory
832*344aa361SAndroid Build Coastguard Worker    region descriptors (struct ffa_cons_mrd) */
arm_ffa_mem_retrieve_next_frag(uint64_t handle,struct arm_ffa_mem_frag_info * frag_info)833*344aa361SAndroid Build Coastguard Worker status_t arm_ffa_mem_retrieve_next_frag(
834*344aa361SAndroid Build Coastguard Worker         uint64_t handle,
835*344aa361SAndroid Build Coastguard Worker         struct arm_ffa_mem_frag_info* frag_info) {
836*344aa361SAndroid Build Coastguard Worker     status_t res;
837*344aa361SAndroid Build Coastguard Worker     uint32_t fragment_len;
838*344aa361SAndroid Build Coastguard Worker 
839*344aa361SAndroid Build Coastguard Worker     mutex_acquire(&ffa_rxtx_buffer_lock);
840*344aa361SAndroid Build Coastguard Worker 
841*344aa361SAndroid Build Coastguard Worker     res = arm_ffa_call_mem_frag_rx(handle, frag_info->received_len,
842*344aa361SAndroid Build Coastguard Worker                                    &fragment_len);
843*344aa361SAndroid Build Coastguard Worker 
844*344aa361SAndroid Build Coastguard Worker     if (res != NO_ERROR) {
845*344aa361SAndroid Build Coastguard Worker         TRACEF("Failed to get memory retrieve fragment, err = %d\n", res);
846*344aa361SAndroid Build Coastguard Worker         return res;
847*344aa361SAndroid Build Coastguard Worker     }
848*344aa361SAndroid Build Coastguard Worker 
849*344aa361SAndroid Build Coastguard Worker     frag_info->received_len += fragment_len;
850*344aa361SAndroid Build Coastguard Worker     frag_info->start_index += frag_info->count;
851*344aa361SAndroid Build Coastguard Worker 
852*344aa361SAndroid Build Coastguard Worker     frag_info->count = fragment_len / sizeof(struct ffa_cons_mrd);
853*344aa361SAndroid Build Coastguard Worker     if (frag_info->count * sizeof(struct ffa_cons_mrd) != fragment_len) {
854*344aa361SAndroid Build Coastguard Worker         TRACEF("fragment length %u, contains partial descriptor\n",
855*344aa361SAndroid Build Coastguard Worker                fragment_len);
856*344aa361SAndroid Build Coastguard Worker         return ERR_IO;
857*344aa361SAndroid Build Coastguard Worker     }
858*344aa361SAndroid Build Coastguard Worker 
859*344aa361SAndroid Build Coastguard Worker     frag_info->address_ranges = ffa_rx;
860*344aa361SAndroid Build Coastguard Worker 
861*344aa361SAndroid Build Coastguard Worker     return NO_ERROR;
862*344aa361SAndroid Build Coastguard Worker }
863*344aa361SAndroid Build Coastguard Worker 
arm_ffa_rx_release(void)864*344aa361SAndroid Build Coastguard Worker status_t arm_ffa_rx_release(void) {
865*344aa361SAndroid Build Coastguard Worker     status_t res;
866*344aa361SAndroid Build Coastguard Worker     ASSERT(is_mutex_held(&ffa_rxtx_buffer_lock));
867*344aa361SAndroid Build Coastguard Worker 
868*344aa361SAndroid Build Coastguard Worker     if (!supports_rx_release) {
869*344aa361SAndroid Build Coastguard Worker         res = NO_ERROR;
870*344aa361SAndroid Build Coastguard Worker     } else {
871*344aa361SAndroid Build Coastguard Worker         res = arm_ffa_call_rx_release();
872*344aa361SAndroid Build Coastguard Worker     }
873*344aa361SAndroid Build Coastguard Worker 
874*344aa361SAndroid Build Coastguard Worker     mutex_release(&ffa_rxtx_buffer_lock);
875*344aa361SAndroid Build Coastguard Worker 
876*344aa361SAndroid Build Coastguard Worker     if (res == ERR_NOT_SUPPORTED) {
877*344aa361SAndroid Build Coastguard Worker         TRACEF("Tried to release rx buffer when the operation is not supported!\n");
878*344aa361SAndroid Build Coastguard Worker     } else if (res != NO_ERROR) {
879*344aa361SAndroid Build Coastguard Worker         TRACEF("Failed to release rx buffer, err = %d\n", res);
880*344aa361SAndroid Build Coastguard Worker         return res;
881*344aa361SAndroid Build Coastguard Worker     }
882*344aa361SAndroid Build Coastguard Worker     return NO_ERROR;
883*344aa361SAndroid Build Coastguard Worker }
884*344aa361SAndroid Build Coastguard Worker 
arm_ffa_mem_relinquish(uint64_t handle)885*344aa361SAndroid Build Coastguard Worker status_t arm_ffa_mem_relinquish(uint64_t handle) {
886*344aa361SAndroid Build Coastguard Worker     status_t res;
887*344aa361SAndroid Build Coastguard Worker 
888*344aa361SAndroid Build Coastguard Worker     /* As flags are set to 0 no request to zero the memory is made */
889*344aa361SAndroid Build Coastguard Worker     res = arm_ffa_call_mem_relinquish(handle, 0, 1, &ffa_local_id);
890*344aa361SAndroid Build Coastguard Worker     if (res != NO_ERROR) {
891*344aa361SAndroid Build Coastguard Worker         TRACEF("Failed to relinquish memory region, err = %d\n", res);
892*344aa361SAndroid Build Coastguard Worker     }
893*344aa361SAndroid Build Coastguard Worker 
894*344aa361SAndroid Build Coastguard Worker     return res;
895*344aa361SAndroid Build Coastguard Worker }
896*344aa361SAndroid Build Coastguard Worker 
arm_ffa_setup(void)897*344aa361SAndroid Build Coastguard Worker static status_t arm_ffa_setup(void) {
898*344aa361SAndroid Build Coastguard Worker     status_t res;
899*344aa361SAndroid Build Coastguard Worker     uint16_t ver_major_ret;
900*344aa361SAndroid Build Coastguard Worker     uint16_t ver_minor_ret;
901*344aa361SAndroid Build Coastguard Worker     bool is_implemented;
902*344aa361SAndroid Build Coastguard Worker     size_t buf_size_log2;
903*344aa361SAndroid Build Coastguard Worker     size_t ref_count_num_bits;
904*344aa361SAndroid Build Coastguard Worker     size_t arch_page_count;
905*344aa361SAndroid Build Coastguard Worker     size_t ffa_page_count;
906*344aa361SAndroid Build Coastguard Worker     size_t count;
907*344aa361SAndroid Build Coastguard Worker     paddr_t tx_paddr;
908*344aa361SAndroid Build Coastguard Worker     paddr_t rx_paddr;
909*344aa361SAndroid Build Coastguard Worker     void* tx_vaddr;
910*344aa361SAndroid Build Coastguard Worker     void* rx_vaddr;
911*344aa361SAndroid Build Coastguard Worker     struct list_node page_list = LIST_INITIAL_VALUE(page_list);
912*344aa361SAndroid Build Coastguard Worker 
913*344aa361SAndroid Build Coastguard Worker     res = arm_ffa_call_version(FFA_CURRENT_VERSION_MAJOR,
914*344aa361SAndroid Build Coastguard Worker                                FFA_CURRENT_VERSION_MINOR, &ver_major_ret,
915*344aa361SAndroid Build Coastguard Worker                                &ver_minor_ret);
916*344aa361SAndroid Build Coastguard Worker     if (res != NO_ERROR) {
917*344aa361SAndroid Build Coastguard Worker         TRACEF("No compatible FF-A version found\n");
918*344aa361SAndroid Build Coastguard Worker         return res;
919*344aa361SAndroid Build Coastguard Worker     } else if (FFA_CURRENT_VERSION_MAJOR != ver_major_ret ||
920*344aa361SAndroid Build Coastguard Worker                FFA_CURRENT_VERSION_MINOR > ver_minor_ret) {
921*344aa361SAndroid Build Coastguard Worker         /* When trusty supports more FF-A versions downgrade may be possible */
922*344aa361SAndroid Build Coastguard Worker         TRACEF("Incompatible FF-A interface version, %" PRIu16 ".%" PRIu16 "\n",
923*344aa361SAndroid Build Coastguard Worker                ver_major_ret, ver_minor_ret);
924*344aa361SAndroid Build Coastguard Worker         return ERR_NOT_SUPPORTED;
925*344aa361SAndroid Build Coastguard Worker     }
926*344aa361SAndroid Build Coastguard Worker 
927*344aa361SAndroid Build Coastguard Worker     res = arm_ffa_call_id_get(&ffa_local_id);
928*344aa361SAndroid Build Coastguard Worker     if (res != NO_ERROR) {
929*344aa361SAndroid Build Coastguard Worker         TRACEF("Failed to get FF-A partition id (err=%d)\n", res);
930*344aa361SAndroid Build Coastguard Worker         return res;
931*344aa361SAndroid Build Coastguard Worker     }
932*344aa361SAndroid Build Coastguard Worker 
933*344aa361SAndroid Build Coastguard Worker     res = arm_ffa_rx_release_is_implemented(&is_implemented);
934*344aa361SAndroid Build Coastguard Worker     if (res != NO_ERROR) {
935*344aa361SAndroid Build Coastguard Worker         TRACEF("Error checking if FFA_RX_RELEASE is implemented (err=%d)\n",
936*344aa361SAndroid Build Coastguard Worker                res);
937*344aa361SAndroid Build Coastguard Worker         return res;
938*344aa361SAndroid Build Coastguard Worker     }
939*344aa361SAndroid Build Coastguard Worker     if (is_implemented) {
940*344aa361SAndroid Build Coastguard Worker         supports_rx_release = true;
941*344aa361SAndroid Build Coastguard Worker     } else {
942*344aa361SAndroid Build Coastguard Worker         LTRACEF("FFA_RX_RELEASE is not implemented\n");
943*344aa361SAndroid Build Coastguard Worker     }
944*344aa361SAndroid Build Coastguard Worker 
945*344aa361SAndroid Build Coastguard Worker     res = arm_ffa_rxtx_map_is_implemented(&is_implemented, &buf_size_log2);
946*344aa361SAndroid Build Coastguard Worker     if (res != NO_ERROR) {
947*344aa361SAndroid Build Coastguard Worker         TRACEF("Error checking if FFA_RXTX_MAP is implemented (err=%d)\n", res);
948*344aa361SAndroid Build Coastguard Worker         return res;
949*344aa361SAndroid Build Coastguard Worker     }
950*344aa361SAndroid Build Coastguard Worker     if (!is_implemented) {
951*344aa361SAndroid Build Coastguard Worker         TRACEF("FFA_RXTX_MAP is not implemented\n");
952*344aa361SAndroid Build Coastguard Worker         return ERR_NOT_SUPPORTED;
953*344aa361SAndroid Build Coastguard Worker     }
954*344aa361SAndroid Build Coastguard Worker 
955*344aa361SAndroid Build Coastguard Worker     res = arm_ffa_mem_retrieve_req_is_implemented(
956*344aa361SAndroid Build Coastguard Worker             &is_implemented, NULL, &supports_ns_bit, &ref_count_num_bits);
957*344aa361SAndroid Build Coastguard Worker     if (res != NO_ERROR) {
958*344aa361SAndroid Build Coastguard Worker         TRACEF("Error checking if FFA_MEM_RETRIEVE_REQ is implemented (err=%d)\n",
959*344aa361SAndroid Build Coastguard Worker                res);
960*344aa361SAndroid Build Coastguard Worker         return res;
961*344aa361SAndroid Build Coastguard Worker     }
962*344aa361SAndroid Build Coastguard Worker     if (!is_implemented) {
963*344aa361SAndroid Build Coastguard Worker         TRACEF("FFA_MEM_RETRIEVE_REQ is not implemented\n");
964*344aa361SAndroid Build Coastguard Worker         return ERR_NOT_SUPPORTED;
965*344aa361SAndroid Build Coastguard Worker     }
966*344aa361SAndroid Build Coastguard Worker 
967*344aa361SAndroid Build Coastguard Worker     if (ref_count_num_bits < 64) {
968*344aa361SAndroid Build Coastguard Worker         /*
969*344aa361SAndroid Build Coastguard Worker          * Expect 64 bit reference count. If we don't have it, future calls to
970*344aa361SAndroid Build Coastguard Worker          * SMC_FC_FFA_MEM_RETRIEVE_REQ can fail if we receive the same handle
971*344aa361SAndroid Build Coastguard Worker          * multiple times. Warn about this, but don't return an error as we only
972*344aa361SAndroid Build Coastguard Worker          * receive each handle once in the typical case.
973*344aa361SAndroid Build Coastguard Worker          */
974*344aa361SAndroid Build Coastguard Worker         TRACEF("Warning FFA_MEM_RETRIEVE_REQ does not have 64 bit reference count (%zu)\n",
975*344aa361SAndroid Build Coastguard Worker                ref_count_num_bits);
976*344aa361SAndroid Build Coastguard Worker     }
977*344aa361SAndroid Build Coastguard Worker 
978*344aa361SAndroid Build Coastguard Worker     ffa_buf_size = 1U << buf_size_log2;
979*344aa361SAndroid Build Coastguard Worker     ASSERT((ffa_buf_size % FFA_PAGE_SIZE) == 0);
980*344aa361SAndroid Build Coastguard Worker 
981*344aa361SAndroid Build Coastguard Worker     arch_page_count = DIV_ROUND_UP(ffa_buf_size, PAGE_SIZE);
982*344aa361SAndroid Build Coastguard Worker     ffa_page_count = ffa_buf_size / FFA_PAGE_SIZE;
983*344aa361SAndroid Build Coastguard Worker     count = pmm_alloc_contiguous(arch_page_count, buf_size_log2, &tx_paddr,
984*344aa361SAndroid Build Coastguard Worker                                  &page_list);
985*344aa361SAndroid Build Coastguard Worker     if (count != arch_page_count) {
986*344aa361SAndroid Build Coastguard Worker         TRACEF("Failed to allocate tx buffer %zx!=%zx\n", count,
987*344aa361SAndroid Build Coastguard Worker                arch_page_count);
988*344aa361SAndroid Build Coastguard Worker         res = ERR_NO_MEMORY;
989*344aa361SAndroid Build Coastguard Worker         goto err_alloc_tx;
990*344aa361SAndroid Build Coastguard Worker     }
991*344aa361SAndroid Build Coastguard Worker     tx_vaddr = paddr_to_kvaddr(tx_paddr);
992*344aa361SAndroid Build Coastguard Worker     ASSERT(tx_vaddr);
993*344aa361SAndroid Build Coastguard Worker 
994*344aa361SAndroid Build Coastguard Worker     count = pmm_alloc_contiguous(arch_page_count, buf_size_log2, &rx_paddr,
995*344aa361SAndroid Build Coastguard Worker                                  &page_list);
996*344aa361SAndroid Build Coastguard Worker     if (count != arch_page_count) {
997*344aa361SAndroid Build Coastguard Worker         TRACEF("Failed to allocate rx buffer %zx!=%zx\n", count,
998*344aa361SAndroid Build Coastguard Worker                arch_page_count);
999*344aa361SAndroid Build Coastguard Worker         res = ERR_NO_MEMORY;
1000*344aa361SAndroid Build Coastguard Worker         goto err_alloc_rx;
1001*344aa361SAndroid Build Coastguard Worker     }
1002*344aa361SAndroid Build Coastguard Worker     rx_vaddr = paddr_to_kvaddr(rx_paddr);
1003*344aa361SAndroid Build Coastguard Worker     ASSERT(rx_vaddr);
1004*344aa361SAndroid Build Coastguard Worker 
1005*344aa361SAndroid Build Coastguard Worker     res = arm_ffa_call_rxtx_map(tx_paddr, rx_paddr, ffa_page_count);
1006*344aa361SAndroid Build Coastguard Worker     if (res != NO_ERROR) {
1007*344aa361SAndroid Build Coastguard Worker         TRACEF("Failed to map tx @ %p, rx @ %p, page count 0x%zx (err=%d)\n",
1008*344aa361SAndroid Build Coastguard Worker                (void*)tx_paddr, (void*)rx_paddr, ffa_page_count, res);
1009*344aa361SAndroid Build Coastguard Worker         goto err_rxtx_map;
1010*344aa361SAndroid Build Coastguard Worker     }
1011*344aa361SAndroid Build Coastguard Worker 
1012*344aa361SAndroid Build Coastguard Worker     ffa_tx = tx_vaddr;
1013*344aa361SAndroid Build Coastguard Worker     ffa_rx = rx_vaddr;
1014*344aa361SAndroid Build Coastguard Worker 
1015*344aa361SAndroid Build Coastguard Worker     return res;
1016*344aa361SAndroid Build Coastguard Worker 
1017*344aa361SAndroid Build Coastguard Worker err_rxtx_map:
1018*344aa361SAndroid Build Coastguard Worker err_alloc_rx:
1019*344aa361SAndroid Build Coastguard Worker     pmm_free(&page_list);
1020*344aa361SAndroid Build Coastguard Worker err_alloc_tx:
1021*344aa361SAndroid Build Coastguard Worker     /* pmm_alloc_contiguous leaves the page list unchanged on failure */
1022*344aa361SAndroid Build Coastguard Worker 
1023*344aa361SAndroid Build Coastguard Worker     return res;
1024*344aa361SAndroid Build Coastguard Worker }
1025*344aa361SAndroid Build Coastguard Worker 
arm_ffa_init(uint level)1026*344aa361SAndroid Build Coastguard Worker static void arm_ffa_init(uint level) {
1027*344aa361SAndroid Build Coastguard Worker     status_t res;
1028*344aa361SAndroid Build Coastguard Worker 
1029*344aa361SAndroid Build Coastguard Worker     res = arm_ffa_setup();
1030*344aa361SAndroid Build Coastguard Worker 
1031*344aa361SAndroid Build Coastguard Worker     if (res == NO_ERROR) {
1032*344aa361SAndroid Build Coastguard Worker         arm_ffa_init_is_success = true;
1033*344aa361SAndroid Build Coastguard Worker 
1034*344aa361SAndroid Build Coastguard Worker #if WITH_SMP
1035*344aa361SAndroid Build Coastguard Worker         res = ffa_call_secondary_ep_register();
1036*344aa361SAndroid Build Coastguard Worker         if (res == ERR_NOT_SUPPORTED) {
1037*344aa361SAndroid Build Coastguard Worker             LTRACEF("FFA_SECONDARY_EP_REGISTER is not supported\n");
1038*344aa361SAndroid Build Coastguard Worker         } else if (res != NO_ERROR) {
1039*344aa361SAndroid Build Coastguard Worker             TRACEF("Failed to register secondary core entry point (err=%d)\n",
1040*344aa361SAndroid Build Coastguard Worker                    res);
1041*344aa361SAndroid Build Coastguard Worker         }
1042*344aa361SAndroid Build Coastguard Worker #endif
1043*344aa361SAndroid Build Coastguard Worker     } else {
1044*344aa361SAndroid Build Coastguard Worker         TRACEF("Failed to initialize FF-A (err=%d)\n", res);
1045*344aa361SAndroid Build Coastguard Worker     }
1046*344aa361SAndroid Build Coastguard Worker }
1047*344aa361SAndroid Build Coastguard Worker 
1048*344aa361SAndroid Build Coastguard Worker LK_INIT_HOOK(arm_ffa_init, arm_ffa_init, LK_INIT_LEVEL_PLATFORM - 2);
1049