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