blob: 6af076075e9011197689f9ef2af409060646e20d [file] [log] [blame]
Imre Kis9fcf8412020-11-23 03:15:45 +01001// SPDX-License-Identifier: BSD-3-Clause
2/*
Balint Dobszay40410ab2022-01-19 16:31:02 +01003 * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
Imre Kis9fcf8412020-11-23 03:15:45 +01004 */
5
6#include <assert.h> // for assert
7#include <stddef.h> // for size_t
8#include <stdint.h> // for uint32_t, uint16_t, uintptr_t, U
9#include "ffa_api.h" // for FFA_OK, ffa_interrupt_handler, ffa_fea...
10#include "ffa_api_defines.h" // for FFA_PARAM_MBZ, FFA_OK, FFA_ERROR, FFA_...
11#include "ffa_api_types.h" // for ffa_result, ffa_direct_msg, ffa_uuid
12#include "ffa_internal_api.h" // for ffa_params, ffa_svc
13#include "util.h" // for GENMASK_32, SHIFT_U32, BIT
14
15/*
16 * Unpacks the error code from the FFA_ERROR message. It is a signed 32 bit
17 * value in an unsigned 64 bit field so proper casting must be used to avoid
18 * compiler dependent behavior.
19 */
20static inline ffa_result ffa_get_errorcode(struct ffa_params *result)
21{
22 uint32_t raw_value = result->a2;
23
24 return *(ffa_result *)(&raw_value);
25}
26
27/*
28 * Unpacks the content of the SVC result into an ffa_direct_msg structure.
29 */
30static inline void ffa_unpack_direct_msg(struct ffa_params *svc_result,
31 struct ffa_direct_msg *msg)
32{
33 msg->function_id = svc_result->a0;
34 msg->source_id = (svc_result->a1 >> 16);
35 msg->destination_id = svc_result->a1;
36 msg->args[0] = svc_result->a3;
37 msg->args[1] = svc_result->a4;
38 msg->args[2] = svc_result->a5;
39 msg->args[3] = svc_result->a6;
40 msg->args[4] = svc_result->a7;
41}
42
43/*
44 * The end of the interrupt handler is indicated by an FFA_MSG_WAIT call.
45 */
46static inline void ffa_return_from_interrupt(struct ffa_params *result)
47{
48 ffa_svc(FFA_MSG_WAIT, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
49 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
50 result);
51}
52
53static inline void ffa_uuid_to_abi_format(const struct ffa_uuid *uuid,
54 uint32_t *result)
55{
56 size_t i = 0;
57
58 for (i = 0; i < 4; i++) {
59 result[i] = uuid->uuid[4 * i];
60 result[i] |= SHIFT_U32(uuid->uuid[4 * i + 1], 8);
61 result[i] |= SHIFT_U32(uuid->uuid[4 * i + 2], 16);
62 result[i] |= SHIFT_U32(uuid->uuid[4 * i + 3], 24);
63 }
64}
65
66ffa_result ffa_version(uint32_t *version)
67{
68 struct ffa_params result = {0};
69 uint32_t self_version = 0;
70
71 self_version = (FFA_VERSION_MAJOR << FFA_VERSION_MAJOR_SHIFT) |
72 (FFA_VERSION_MINOR << FFA_VERSION_MINOR);
73
74 ffa_svc(FFA_VERSION, self_version, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
75 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
76 &result);
77
78 if (result.a0 & BIT(31)) {
79 uint32_t raw_error = result.a0;
80
81 *version = 0;
82
83 return *(ffa_result *)(&raw_error);
84 }
85
86 *version = result.a0;
87 return FFA_OK;
88}
89
90ffa_result ffa_features(uint32_t ffa_function_id,
91 struct ffa_interface_properties *interface_properties)
92{
93 struct ffa_params result = {0};
94
95 ffa_svc(FFA_FEATURES, ffa_function_id, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
96 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
97 &result);
98
99 if (result.a0 == FFA_ERROR) {
100 interface_properties->interface_properties[0] = 0;
101 interface_properties->interface_properties[1] = 0;
102 return ffa_get_errorcode(&result);
103 }
104
105 assert(result.a0 == FFA_SUCCESS_32);
106 interface_properties->interface_properties[0] = result.a2;
107 interface_properties->interface_properties[1] = result.a3;
108 return FFA_OK;
109}
110
111ffa_result ffa_rx_release(void)
112{
113 struct ffa_params result = {0};
114
115 ffa_svc(FFA_RX_RELEASE, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
116 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
117 &result);
118
119 if (result.a0 == FFA_ERROR)
120 return ffa_get_errorcode(&result);
121
122 assert(result.a0 == FFA_SUCCESS_32);
123 return FFA_OK;
124}
125
126ffa_result ffa_rxtx_map(const void *tx_buffer, const void *rx_buffer,
127 uint32_t page_count)
128{
129 struct ffa_params result = {0};
130
131 assert(page_count <= FFA_RXTX_MAP_PAGE_COUNT_MAX);
132
133 page_count = SHIFT_U32(page_count & FFA_RXTX_MAP_PAGE_COUNT_MASK,
134 FFA_RXTX_MAP_PAGE_COUNT_SHIFT);
135
Balint Dobszay40410ab2022-01-19 16:31:02 +0100136 ffa_svc(FFA_RXTX_MAP_64, (uintptr_t)tx_buffer, (uintptr_t)rx_buffer,
Imre Kis9fcf8412020-11-23 03:15:45 +0100137 page_count, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
138 FFA_PARAM_MBZ, &result);
139
140 if (result.a0 == FFA_ERROR)
141 return ffa_get_errorcode(&result);
142
Balint Dobszay40410ab2022-01-19 16:31:02 +0100143 /*
144 * There are no 64-bit parameters returned with FFA_SUCCESS, the SPMC
145 * will use the default 32-bit version.
146 */
Imre Kis9fcf8412020-11-23 03:15:45 +0100147 assert(result.a0 == FFA_SUCCESS_32);
148 return FFA_OK;
149}
150
151ffa_result ffa_rxtx_unmap(uint16_t id)
152{
153 struct ffa_params result = {0};
154
155 ffa_svc(FFA_RXTX_UNMAP, SHIFT_U32(id, FFA_RXTX_UNMAP_ID_SHIFT),
156 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
157 FFA_PARAM_MBZ, FFA_PARAM_MBZ, &result);
158
159 if (result.a0 == FFA_ERROR)
160 return ffa_get_errorcode(&result);
161
162 assert(result.a0 == FFA_SUCCESS_32);
163 return FFA_OK;
164}
165
166ffa_result ffa_partition_info_get(const struct ffa_uuid *uuid, uint32_t *count)
167{
168 struct ffa_params result = {0};
169 uint32_t abi_uuid[4] = {0};
170
171 ffa_uuid_to_abi_format(uuid, abi_uuid);
172
173 ffa_svc(FFA_PARTITION_INFO_GET, abi_uuid[0], abi_uuid[1], abi_uuid[2],
174 abi_uuid[3], FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
175 &result);
176
177 if (result.a0 == FFA_ERROR) {
178 *count = UINT32_C(0);
179 return ffa_get_errorcode(&result);
180 }
181
182 assert(result.a0 == FFA_SUCCESS_32);
183 *count = result.a2;
184 return FFA_OK;
185}
186
187ffa_result ffa_id_get(uint16_t *id)
188{
189 struct ffa_params result = {0};
190
191 ffa_svc(FFA_ID_GET, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
192 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
193 &result);
194
195 if (result.a0 == FFA_ERROR) {
196 *id = FFA_ID_GET_ID_MASK;
197 return ffa_get_errorcode(&result);
198 }
199
200 assert(result.a0 == FFA_SUCCESS_32);
201 *id = (result.a2 >> FFA_ID_GET_ID_SHIFT) & FFA_ID_GET_ID_MASK;
202 return FFA_OK;
203}
204
205ffa_result ffa_msg_wait(struct ffa_direct_msg *msg)
206{
207 struct ffa_params result = {0};
208
209 ffa_svc(FFA_MSG_WAIT, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
210 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
211 &result);
212
213 while (result.a0 == FFA_INTERRUPT) {
214 ffa_interrupt_handler(result.a2);
215 ffa_return_from_interrupt(&result);
216 }
217
218 if (result.a0 == FFA_ERROR) {
219 return ffa_get_errorcode(&result);
220 } else if (result.a0 == FFA_MSG_SEND_DIRECT_REQ_32) {
221 ffa_unpack_direct_msg(&result, msg);
222 } else {
223 assert(result.a0 == FFA_SUCCESS_32);
224 *msg = (struct ffa_direct_msg){.function_id = result.a0};
225 }
226
227 return FFA_OK;
228}
229
230ffa_result ffa_msg_send_direct_req(uint16_t source, uint16_t dest, uint32_t a0,
231 uint32_t a1, uint32_t a2, uint32_t a3,
232 uint32_t a4, struct ffa_direct_msg *msg)
233{
234 struct ffa_params result = {0};
235
236 ffa_svc(FFA_MSG_SEND_DIRECT_REQ_32,
237 SHIFT_U32(source, FFA_MSG_SEND_DIRECT_REQ_SOURCE_ID_SHIFT) |
238 dest, FFA_PARAM_MBZ, a0, a1, a2, a3, a4, &result);
239
240 while (result.a0 == FFA_INTERRUPT) {
241 ffa_interrupt_handler(result.a2);
242 ffa_return_from_interrupt(&result);
243 }
244
245 if (result.a0 == FFA_ERROR) {
246 return ffa_get_errorcode(&result);
247 } else if (result.a0 == FFA_MSG_SEND_DIRECT_RESP_32) {
248 ffa_unpack_direct_msg(&result, msg);
249 } else {
250 assert(result.a0 == FFA_SUCCESS_32);
251 *msg = (struct ffa_direct_msg){.function_id = result.a0};
252 }
253
254 return FFA_OK;
255}
256
257ffa_result ffa_msg_send_direct_resp(uint16_t source, uint16_t dest, uint32_t a0,
258 uint32_t a1, uint32_t a2, uint32_t a3,
259 uint32_t a4, struct ffa_direct_msg *msg)
260{
261 struct ffa_params result = {0};
262
263 ffa_svc(FFA_MSG_SEND_DIRECT_RESP_32,
264 SHIFT_U32(source, FFA_MSG_SEND_DIRECT_RESP_SOURCE_ID_SHIFT) |
265 dest, FFA_PARAM_MBZ, a0, a1, a2, a3, a4, &result);
266
267 while (result.a0 == FFA_INTERRUPT) {
268 ffa_interrupt_handler(result.a2);
269 ffa_return_from_interrupt(&result);
270 }
271
272 if (result.a0 == FFA_ERROR) {
273 return ffa_get_errorcode(&result);
274 } else if (result.a0 == FFA_MSG_SEND_DIRECT_REQ_32) {
275 ffa_unpack_direct_msg(&result, msg);
276 } else {
277 assert(result.a0 == FFA_SUCCESS_32);
278 *msg = (struct ffa_direct_msg){.function_id = result.a0};
279 }
280
281 return FFA_OK;
282}
Imre Kise3112e02020-11-23 03:15:46 +0100283
284ffa_result ffa_mem_donate(uint32_t total_length, uint32_t fragment_length,
285 void *buffer_address, uint32_t page_count,
286 uint64_t *handle)
287{
288 struct ffa_params result = {0};
289
Balint Dobszay40410ab2022-01-19 16:31:02 +0100290 ffa_svc((buffer_address) ? FFA_MEM_DONATE_64 : FFA_MEM_DONATE_32,
291 total_length, fragment_length, (uintptr_t)buffer_address,
292 page_count, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
293 &result);
Imre Kise3112e02020-11-23 03:15:46 +0100294
295 if (result.a0 == FFA_ERROR) {
296 *handle = 0U;
297 return ffa_get_errorcode(&result);
298 }
299
Balint Dobszay40410ab2022-01-19 16:31:02 +0100300 /*
301 * There are no 64-bit parameters returned with FFA_SUCCESS, the SPMC
302 * will use the default 32-bit version.
303 */
Imre Kise3112e02020-11-23 03:15:46 +0100304 assert(result.a0 == FFA_SUCCESS_32);
305 *handle = reg_pair_to_64(result.a3, result.a2);
306 return FFA_OK;
307}
308
309ffa_result ffa_mem_donate_rxtx(uint32_t total_length, uint32_t fragment_length,
310 uint64_t *handle)
311{
312 return ffa_mem_donate(total_length, fragment_length, NULL, 0, handle);
313}
314
315ffa_result ffa_mem_lend(uint32_t total_length, uint32_t fragment_length,
316 void *buffer_address, uint32_t page_count,
317 uint64_t *handle)
318{
319 struct ffa_params result = {0};
320
Balint Dobszay40410ab2022-01-19 16:31:02 +0100321 ffa_svc((buffer_address) ? FFA_MEM_LEND_64 : FFA_MEM_LEND_32,
322 total_length, fragment_length, (uintptr_t)buffer_address,
323 page_count, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
324 &result);
Imre Kise3112e02020-11-23 03:15:46 +0100325
326 if (result.a0 == FFA_ERROR) {
327 *handle = 0U;
328 return ffa_get_errorcode(&result);
329 }
330
Balint Dobszay40410ab2022-01-19 16:31:02 +0100331 /*
332 * There are no 64-bit parameters returned with FFA_SUCCESS, the SPMC
333 * will use the default 32-bit version.
334 */
Imre Kise3112e02020-11-23 03:15:46 +0100335 assert(result.a0 == FFA_SUCCESS_32);
336 *handle = reg_pair_to_64(result.a3, result.a2);
337 return FFA_OK;
338}
339
340ffa_result ffa_mem_lend_rxtx(uint32_t total_length, uint32_t fragment_length,
341 uint64_t *handle)
342{
343 return ffa_mem_lend(total_length, fragment_length, NULL, 0, handle);
344}
345
346ffa_result ffa_mem_share(uint32_t total_length, uint32_t fragment_length,
347 void *buffer_address, uint32_t page_count,
348 uint64_t *handle)
349{
350 struct ffa_params result = {0};
351
Balint Dobszay40410ab2022-01-19 16:31:02 +0100352 ffa_svc((buffer_address) ? FFA_MEM_SHARE_64 : FFA_MEM_SHARE_32,
353 total_length, fragment_length, (uintptr_t)buffer_address,
354 page_count, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
355 &result);
Imre Kise3112e02020-11-23 03:15:46 +0100356
357 if (result.a0 == FFA_ERROR) {
358 *handle = 0U;
359 return ffa_get_errorcode(&result);
360 }
361
Balint Dobszay40410ab2022-01-19 16:31:02 +0100362 /*
363 * There are no 64-bit parameters returned with FFA_SUCCESS, the SPMC
364 * will use the default 32-bit version.
365 */
Imre Kise3112e02020-11-23 03:15:46 +0100366 assert(result.a0 == FFA_SUCCESS_32);
367 *handle = reg_pair_to_64(result.a3, result.a2);
368 return FFA_OK;
369}
370
371ffa_result ffa_mem_share_rxtx(uint32_t total_length, uint32_t fragment_length,
372 uint64_t *handle)
373{
374 return ffa_mem_share(total_length, fragment_length, NULL, 0, handle);
375}
376
377ffa_result ffa_mem_retrieve_req(uint32_t total_length, uint32_t fragment_length,
378 void *buffer_address, uint32_t page_count,
379 uint32_t *resp_total_length,
380 uint32_t *resp_fragment_length)
381{
382 struct ffa_params result = {0};
383
Balint Dobszay40410ab2022-01-19 16:31:02 +0100384 ffa_svc((buffer_address) ? FFA_MEM_RETRIEVE_REQ_64 : FFA_MEM_RETRIEVE_REQ_32,
385 total_length, fragment_length, (uintptr_t)buffer_address,
386 page_count, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
387 &result);
Imre Kise3112e02020-11-23 03:15:46 +0100388
389 if (result.a0 == FFA_ERROR) {
390 *resp_total_length = 0U;
391 *resp_fragment_length = 0U;
392 return ffa_get_errorcode(&result);
393 }
394
395 assert(result.a0 == FFA_MEM_RETRIEVE_RESP);
396 *resp_total_length = result.a1;
397 *resp_fragment_length = result.a2;
398 return FFA_OK;
399}
400
401ffa_result ffa_mem_retrieve_req_rxtx(uint32_t total_length,
402 uint32_t fragment_length,
403 uint32_t *resp_total_length,
404 uint32_t *resp_fragment_length)
405{
406 return ffa_mem_retrieve_req(total_length, fragment_length, NULL, 0,
407 resp_total_length, resp_fragment_length);
408}
409
410ffa_result ffa_mem_relinquish(void)
411{
412 struct ffa_params result = {0};
413
414 ffa_svc(FFA_MEM_RELINQUISH, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
415 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
416 &result);
417
418 if (result.a0 == FFA_ERROR)
419 return ffa_get_errorcode(&result);
420
421 assert(result.a0 == FFA_SUCCESS_32);
422 return FFA_OK;
423}
424
425ffa_result ffa_mem_reclaim(uint64_t handle, uint32_t flags)
426{
427 struct ffa_params result = {0};
428 uint32_t handle_hi = 0;
429 uint32_t handle_lo = 0;
430
431 reg_pair_from_64(handle, &handle_hi, &handle_lo);
432
433 ffa_svc(FFA_MEM_RECLAIM, handle_lo, handle_hi, flags, FFA_PARAM_MBZ,
434 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, &result);
435
436 if (result.a0 == FFA_ERROR)
437 return ffa_get_errorcode(&result);
438
439 assert(result.a0 == FFA_SUCCESS_32);
440 return FFA_OK;
441}