blob: cae246d1c250a060c64d262f28cbe1cf13931818 [file] [log] [blame]
Imre Kis9fcf8412020-11-23 03:15:45 +01001// SPDX-License-Identifier: BSD-3-Clause
2/*
Imre Kis1eb045b2025-01-27 13:30:33 +01003 * Copyright (c) 2020-2025, 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
Imre Kise56c7b12023-06-01 13:33:40 +02009#include <string.h> // for memcpy
Imre Kis9fcf8412020-11-23 03:15:45 +010010#include "ffa_api.h" // for FFA_OK, ffa_interrupt_handler, ffa_fea...
11#include "ffa_api_defines.h" // for FFA_PARAM_MBZ, FFA_OK, FFA_ERROR, FFA_...
12#include "ffa_api_types.h" // for ffa_result, ffa_direct_msg, ffa_uuid
13#include "ffa_internal_api.h" // for ffa_params, ffa_svc
14#include "util.h" // for GENMASK_32, SHIFT_U32, BIT
15
16/*
17 * Unpacks the error code from the FFA_ERROR message. It is a signed 32 bit
18 * value in an unsigned 64 bit field so proper casting must be used to avoid
19 * compiler dependent behavior.
20 */
21static inline ffa_result ffa_get_errorcode(struct ffa_params *result)
22{
23 uint32_t raw_value = result->a2;
24
25 return *(ffa_result *)(&raw_value);
26}
27
28/*
29 * Unpacks the content of the SVC result into an ffa_direct_msg structure.
30 */
31static inline void ffa_unpack_direct_msg(struct ffa_params *svc_result,
32 struct ffa_direct_msg *msg)
33{
34 msg->function_id = svc_result->a0;
35 msg->source_id = (svc_result->a1 >> 16);
36 msg->destination_id = svc_result->a1;
Imre Kis1bc4a622022-07-19 17:38:00 +020037
38 if (FFA_IS_32_BIT_FUNC(msg->function_id)) {
39 msg->args.args32[0] = svc_result->a3;
40 msg->args.args32[1] = svc_result->a4;
41 msg->args.args32[2] = svc_result->a5;
42 msg->args.args32[3] = svc_result->a6;
43 msg->args.args32[4] = svc_result->a7;
44 } else {
45 msg->args.args64[0] = svc_result->a3;
46 msg->args.args64[1] = svc_result->a4;
47 msg->args.args64[2] = svc_result->a5;
48 msg->args.args64[3] = svc_result->a6;
49 msg->args.args64[4] = svc_result->a7;
50 }
Imre Kis9fcf8412020-11-23 03:15:45 +010051}
52
53/*
54 * The end of the interrupt handler is indicated by an FFA_MSG_WAIT call.
55 */
56static inline void ffa_return_from_interrupt(struct ffa_params *result)
57{
58 ffa_svc(FFA_MSG_WAIT, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
59 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
60 result);
61}
62
63static inline void ffa_uuid_to_abi_format(const struct ffa_uuid *uuid,
64 uint32_t *result)
65{
66 size_t i = 0;
67
68 for (i = 0; i < 4; i++) {
69 result[i] = uuid->uuid[4 * i];
70 result[i] |= SHIFT_U32(uuid->uuid[4 * i + 1], 8);
71 result[i] |= SHIFT_U32(uuid->uuid[4 * i + 2], 16);
72 result[i] |= SHIFT_U32(uuid->uuid[4 * i + 3], 24);
73 }
74}
75
76ffa_result ffa_version(uint32_t *version)
77{
78 struct ffa_params result = {0};
79 uint32_t self_version = 0;
80
81 self_version = (FFA_VERSION_MAJOR << FFA_VERSION_MAJOR_SHIFT) |
Imre Kis1f5b1c62024-01-15 12:51:03 +010082 (FFA_VERSION_MINOR << FFA_VERSION_MINOR_SHIFT);
Imre Kis9fcf8412020-11-23 03:15:45 +010083
84 ffa_svc(FFA_VERSION, self_version, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
85 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
86 &result);
87
88 if (result.a0 & BIT(31)) {
89 uint32_t raw_error = result.a0;
90
91 *version = 0;
92
93 return *(ffa_result *)(&raw_error);
94 }
95
96 *version = result.a0;
97 return FFA_OK;
98}
99
100ffa_result ffa_features(uint32_t ffa_function_id,
101 struct ffa_interface_properties *interface_properties)
102{
103 struct ffa_params result = {0};
104
105 ffa_svc(FFA_FEATURES, ffa_function_id, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
106 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
107 &result);
108
109 if (result.a0 == FFA_ERROR) {
110 interface_properties->interface_properties[0] = 0;
111 interface_properties->interface_properties[1] = 0;
112 return ffa_get_errorcode(&result);
113 }
114
115 assert(result.a0 == FFA_SUCCESS_32);
116 interface_properties->interface_properties[0] = result.a2;
117 interface_properties->interface_properties[1] = result.a3;
118 return FFA_OK;
119}
120
121ffa_result ffa_rx_release(void)
122{
123 struct ffa_params result = {0};
124
125 ffa_svc(FFA_RX_RELEASE, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
126 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
127 &result);
128
129 if (result.a0 == FFA_ERROR)
130 return ffa_get_errorcode(&result);
131
132 assert(result.a0 == FFA_SUCCESS_32);
133 return FFA_OK;
134}
135
136ffa_result ffa_rxtx_map(const void *tx_buffer, const void *rx_buffer,
137 uint32_t page_count)
138{
139 struct ffa_params result = {0};
140
141 assert(page_count <= FFA_RXTX_MAP_PAGE_COUNT_MAX);
142
143 page_count = SHIFT_U32(page_count & FFA_RXTX_MAP_PAGE_COUNT_MASK,
144 FFA_RXTX_MAP_PAGE_COUNT_SHIFT);
145
Balint Dobszay40410ab2022-01-19 16:31:02 +0100146 ffa_svc(FFA_RXTX_MAP_64, (uintptr_t)tx_buffer, (uintptr_t)rx_buffer,
Imre Kis9fcf8412020-11-23 03:15:45 +0100147 page_count, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
148 FFA_PARAM_MBZ, &result);
149
150 if (result.a0 == FFA_ERROR)
151 return ffa_get_errorcode(&result);
152
Balint Dobszay40410ab2022-01-19 16:31:02 +0100153 /*
154 * There are no 64-bit parameters returned with FFA_SUCCESS, the SPMC
155 * will use the default 32-bit version.
156 */
Imre Kis9fcf8412020-11-23 03:15:45 +0100157 assert(result.a0 == FFA_SUCCESS_32);
158 return FFA_OK;
159}
160
161ffa_result ffa_rxtx_unmap(uint16_t id)
162{
163 struct ffa_params result = {0};
164
165 ffa_svc(FFA_RXTX_UNMAP, SHIFT_U32(id, FFA_RXTX_UNMAP_ID_SHIFT),
166 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
167 FFA_PARAM_MBZ, FFA_PARAM_MBZ, &result);
168
169 if (result.a0 == FFA_ERROR)
170 return ffa_get_errorcode(&result);
171
172 assert(result.a0 == FFA_SUCCESS_32);
173 return FFA_OK;
174}
175
Imre Kis595c5d02024-01-15 15:28:19 +0100176#if CFG_FFA_VERSION == FFA_VERSION_1_0
Imre Kis9fcf8412020-11-23 03:15:45 +0100177ffa_result ffa_partition_info_get(const struct ffa_uuid *uuid, uint32_t *count)
178{
179 struct ffa_params result = {0};
180 uint32_t abi_uuid[4] = {0};
181
182 ffa_uuid_to_abi_format(uuid, abi_uuid);
183
184 ffa_svc(FFA_PARTITION_INFO_GET, abi_uuid[0], abi_uuid[1], abi_uuid[2],
185 abi_uuid[3], FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
186 &result);
187
188 if (result.a0 == FFA_ERROR) {
189 *count = UINT32_C(0);
190 return ffa_get_errorcode(&result);
191 }
192
193 assert(result.a0 == FFA_SUCCESS_32);
194 *count = result.a2;
195 return FFA_OK;
196}
Imre Kis595c5d02024-01-15 15:28:19 +0100197#elif CFG_FFA_VERSION >= FFA_VERSION_1_1
198ffa_result ffa_partition_info_get(const struct ffa_uuid *uuid, uint32_t flags, uint32_t *count,
199 uint32_t *size)
200{
201 struct ffa_params result = {0};
202 uint32_t abi_uuid[4] = {0};
203
204 ffa_uuid_to_abi_format(uuid, abi_uuid);
205
206 ffa_svc(FFA_PARTITION_INFO_GET, abi_uuid[0], abi_uuid[1], abi_uuid[2],
207 abi_uuid[3], flags, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
208 &result);
209
210 if (result.a0 == FFA_ERROR) {
211 *count = UINT32_C(0);
212 *size = UINT32_C(0);
213 return ffa_get_errorcode(&result);
214 }
215
216 assert(result.a0 == FFA_SUCCESS_32);
217 *count = result.a2;
218 *size = result.a3;
219 return FFA_OK;
220}
221#endif /* CFG_FFA_VERSION */
Imre Kis9fcf8412020-11-23 03:15:45 +0100222
223ffa_result ffa_id_get(uint16_t *id)
224{
225 struct ffa_params result = {0};
226
227 ffa_svc(FFA_ID_GET, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
228 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
229 &result);
230
231 if (result.a0 == FFA_ERROR) {
232 *id = FFA_ID_GET_ID_MASK;
233 return ffa_get_errorcode(&result);
234 }
235
236 assert(result.a0 == FFA_SUCCESS_32);
237 *id = (result.a2 >> FFA_ID_GET_ID_SHIFT) & FFA_ID_GET_ID_MASK;
238 return FFA_OK;
239}
240
Balint Dobszayac721da2024-07-02 16:33:59 +0200241static void handle_framework_msg(struct ffa_params *result)
242{
243 if (result->a0 == FFA_INTERRUPT) {
244 ffa_interrupt_handler(result->a2);
245 ffa_return_from_interrupt(result);
246 } else if (result->a0 == FFA_MSG_SEND_DIRECT_REQ_32 && FFA_IS_FRAMEWORK_MSG(result->a2)) {
247 ffa_result res = FFA_OK;
248 uint16_t src_id = result->a1 >> 16;
249 uint16_t dst_id = result->a1;
250 uint64_t handle = reg_pair_to_64(result->a4, result->a3);
251 uint16_t vm_id = result->a5;
252
253 switch (result->a2 & FFA_FRAMEWORK_MSG_TYPE_MASK) {
254 case FFA_FRAMEWORK_MSG_VM_CREATED:
255 res = ffa_vm_created_handler(vm_id, handle);
256 ffa_svc(FFA_MSG_SEND_DIRECT_RESP_32, ((uint32_t)dst_id << 16) | src_id,
257 FFA_MSG_FLAG_FRAMEWORK | FFA_FRAMEWORK_MSG_VM_CREATED_ACK,
258 (uint64_t)res, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
259 FFA_PARAM_MBZ, result);
260 break;
261 case FFA_FRAMEWORK_MSG_VM_DESTROYED:
262 res = ffa_vm_destroyed_handler(vm_id, handle);
263 ffa_svc(FFA_MSG_SEND_DIRECT_RESP_32, ((uint32_t)dst_id << 16) | src_id,
264 FFA_MSG_FLAG_FRAMEWORK | FFA_FRAMEWORK_MSG_VM_DESTROYED_ACK,
265 (uint64_t)res, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
266 FFA_PARAM_MBZ, result);
267 break;
268 default:
269 ffa_svc(FFA_ERROR, FFA_PARAM_MBZ, FFA_INVALID_PARAMETERS, FFA_PARAM_MBZ,
270 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, result);
271 break;
272 }
273 }
274}
275
Imre Kis9fcf8412020-11-23 03:15:45 +0100276ffa_result ffa_msg_wait(struct ffa_direct_msg *msg)
277{
278 struct ffa_params result = {0};
279
280 ffa_svc(FFA_MSG_WAIT, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
281 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
282 &result);
283
Balint Dobszayac721da2024-07-02 16:33:59 +0200284 /* FF-A framework messages are handled outside of the main partition message handler loop */
285 while ((result.a0 == FFA_INTERRUPT) ||
286 (result.a0 == FFA_MSG_SEND_DIRECT_REQ_32 && FFA_IS_FRAMEWORK_MSG(result.a2))) {
287 handle_framework_msg(&result);
Imre Kis9fcf8412020-11-23 03:15:45 +0100288 }
289
290 if (result.a0 == FFA_ERROR) {
291 return ffa_get_errorcode(&result);
Imre Kis1bc4a622022-07-19 17:38:00 +0200292 } else if (FFA_TO_32_BIT_FUNC(result.a0) == FFA_MSG_SEND_DIRECT_REQ_32) {
Imre Kis9fcf8412020-11-23 03:15:45 +0100293 ffa_unpack_direct_msg(&result, msg);
294 } else {
295 assert(result.a0 == FFA_SUCCESS_32);
296 *msg = (struct ffa_direct_msg){.function_id = result.a0};
297 }
298
299 return FFA_OK;
300}
301
Gabor Toth0d6eb662025-03-11 10:44:43 +0100302ffa_result ffa_yield(void)
303{
304 struct ffa_params result = {0};
305
306 ffa_svc(FFA_YIELD, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
307 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
308 &result);
309
310 if (result.a0 == FFA_ERROR)
311 return ffa_get_errorcode(&result);
312
313 assert(result.a0 == FFA_RUN);
314
315 return FFA_OK;
316}
317
Imre Kis1bc4a622022-07-19 17:38:00 +0200318static ffa_result ffa_msg_send_direct_req(uint32_t function_id, uint32_t resp_id,
319 uint16_t source, uint16_t dest,
320 uint64_t a0, uint64_t a1, uint64_t a2,
321 uint64_t a3, uint64_t a4,
322 struct ffa_direct_msg *msg)
Imre Kis9fcf8412020-11-23 03:15:45 +0100323{
324 struct ffa_params result = {0};
325
Imre Kis1bc4a622022-07-19 17:38:00 +0200326 ffa_svc(function_id,
Imre Kis9fcf8412020-11-23 03:15:45 +0100327 SHIFT_U32(source, FFA_MSG_SEND_DIRECT_REQ_SOURCE_ID_SHIFT) |
328 dest, FFA_PARAM_MBZ, a0, a1, a2, a3, a4, &result);
329
330 while (result.a0 == FFA_INTERRUPT) {
Imre Kis1eb045b2025-01-27 13:30:33 +0100331 ffa_svc(FFA_RUN, result.a1, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
332 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
333 &result);
Imre Kis9fcf8412020-11-23 03:15:45 +0100334 }
335
336 if (result.a0 == FFA_ERROR) {
337 return ffa_get_errorcode(&result);
Imre Kis1bc4a622022-07-19 17:38:00 +0200338 } else if (result.a0 == resp_id) {
Imre Kis9fcf8412020-11-23 03:15:45 +0100339 ffa_unpack_direct_msg(&result, msg);
340 } else {
341 assert(result.a0 == FFA_SUCCESS_32);
342 *msg = (struct ffa_direct_msg){.function_id = result.a0};
343 }
344
345 return FFA_OK;
346}
347
Imre Kis1bc4a622022-07-19 17:38:00 +0200348ffa_result ffa_msg_send_direct_req_32(uint16_t source, uint16_t dest,
349 uint32_t a0, uint32_t a1, uint32_t a2,
350 uint32_t a3, uint32_t a4,
351 struct ffa_direct_msg *msg)
352{
353 return ffa_msg_send_direct_req(FFA_MSG_SEND_DIRECT_REQ_32,
354 FFA_MSG_SEND_DIRECT_RESP_32,
355 source, dest, a0, a1, a2, a3, a4, msg);
356}
357
358ffa_result ffa_msg_send_direct_req_64(uint16_t source, uint16_t dest,
359 uint64_t a0, uint64_t a1, uint64_t a2,
360 uint64_t a3, uint64_t a4,
361 struct ffa_direct_msg *msg)
362{
363 return ffa_msg_send_direct_req(FFA_MSG_SEND_DIRECT_REQ_64,
364 FFA_MSG_SEND_DIRECT_RESP_64,
365 source, dest, a0, a1, a2, a3, a4, msg);
366}
367
368static ffa_result ffa_msg_send_direct_resp(uint32_t function_id,
369 uint16_t source, uint16_t dest,
370 uint64_t a0, uint64_t a1,
371 uint64_t a2, uint64_t a3,
372 uint64_t a4,
373 struct ffa_direct_msg *msg)
Imre Kis9fcf8412020-11-23 03:15:45 +0100374{
375 struct ffa_params result = {0};
376
Imre Kis1bc4a622022-07-19 17:38:00 +0200377 ffa_svc(function_id,
Imre Kis9fcf8412020-11-23 03:15:45 +0100378 SHIFT_U32(source, FFA_MSG_SEND_DIRECT_RESP_SOURCE_ID_SHIFT) |
379 dest, FFA_PARAM_MBZ, a0, a1, a2, a3, a4, &result);
380
Balint Dobszayac721da2024-07-02 16:33:59 +0200381 /* FF-A framework messages are handled outside of the main partition message handler loop */
382 while ((result.a0 == FFA_INTERRUPT) ||
383 (result.a0 == FFA_MSG_SEND_DIRECT_REQ_32 && FFA_IS_FRAMEWORK_MSG(result.a2))) {
384 handle_framework_msg(&result);
Imre Kis9fcf8412020-11-23 03:15:45 +0100385 }
386
387 if (result.a0 == FFA_ERROR) {
388 return ffa_get_errorcode(&result);
Imre Kis1bc4a622022-07-19 17:38:00 +0200389 } else if (FFA_TO_32_BIT_FUNC(result.a0) == FFA_MSG_SEND_DIRECT_REQ_32) {
Imre Kis9fcf8412020-11-23 03:15:45 +0100390 ffa_unpack_direct_msg(&result, msg);
391 } else {
392 assert(result.a0 == FFA_SUCCESS_32);
393 *msg = (struct ffa_direct_msg){.function_id = result.a0};
394 }
395
396 return FFA_OK;
397}
Imre Kise3112e02020-11-23 03:15:46 +0100398
Imre Kis1bc4a622022-07-19 17:38:00 +0200399ffa_result ffa_msg_send_direct_resp_32(uint16_t source, uint16_t dest,
400 uint32_t a0, uint32_t a1, uint32_t a2,
401 uint32_t a3, uint32_t a4,
402 struct ffa_direct_msg *msg)
403{
404 return ffa_msg_send_direct_resp(FFA_MSG_SEND_DIRECT_RESP_32, source,
405 dest, a0, a1, a2, a3, a4, msg);
406}
407
408ffa_result ffa_msg_send_direct_resp_64(uint16_t source, uint16_t dest,
409 uint64_t a0, uint64_t a1, uint64_t a2,
410 uint64_t a3, uint64_t a4,
411 struct ffa_direct_msg *msg)
412{
413 return ffa_msg_send_direct_resp(FFA_MSG_SEND_DIRECT_RESP_64, source,
414 dest, a0, a1, a2, a3, a4, msg);
415}
416
Imre Kise3112e02020-11-23 03:15:46 +0100417ffa_result ffa_mem_donate(uint32_t total_length, uint32_t fragment_length,
418 void *buffer_address, uint32_t page_count,
419 uint64_t *handle)
420{
421 struct ffa_params result = {0};
422
Balint Dobszay40410ab2022-01-19 16:31:02 +0100423 ffa_svc((buffer_address) ? FFA_MEM_DONATE_64 : FFA_MEM_DONATE_32,
424 total_length, fragment_length, (uintptr_t)buffer_address,
425 page_count, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
426 &result);
Imre Kise3112e02020-11-23 03:15:46 +0100427
428 if (result.a0 == FFA_ERROR) {
429 *handle = 0U;
430 return ffa_get_errorcode(&result);
431 }
432
Balint Dobszay40410ab2022-01-19 16:31:02 +0100433 /*
434 * There are no 64-bit parameters returned with FFA_SUCCESS, the SPMC
435 * will use the default 32-bit version.
436 */
Imre Kise3112e02020-11-23 03:15:46 +0100437 assert(result.a0 == FFA_SUCCESS_32);
438 *handle = reg_pair_to_64(result.a3, result.a2);
439 return FFA_OK;
440}
441
442ffa_result ffa_mem_donate_rxtx(uint32_t total_length, uint32_t fragment_length,
443 uint64_t *handle)
444{
445 return ffa_mem_donate(total_length, fragment_length, NULL, 0, handle);
446}
447
448ffa_result ffa_mem_lend(uint32_t total_length, uint32_t fragment_length,
449 void *buffer_address, uint32_t page_count,
450 uint64_t *handle)
451{
452 struct ffa_params result = {0};
453
Balint Dobszay40410ab2022-01-19 16:31:02 +0100454 ffa_svc((buffer_address) ? FFA_MEM_LEND_64 : FFA_MEM_LEND_32,
455 total_length, fragment_length, (uintptr_t)buffer_address,
456 page_count, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
457 &result);
Imre Kise3112e02020-11-23 03:15:46 +0100458
459 if (result.a0 == FFA_ERROR) {
460 *handle = 0U;
461 return ffa_get_errorcode(&result);
462 }
463
Balint Dobszay40410ab2022-01-19 16:31:02 +0100464 /*
465 * There are no 64-bit parameters returned with FFA_SUCCESS, the SPMC
466 * will use the default 32-bit version.
467 */
Imre Kise3112e02020-11-23 03:15:46 +0100468 assert(result.a0 == FFA_SUCCESS_32);
469 *handle = reg_pair_to_64(result.a3, result.a2);
470 return FFA_OK;
471}
472
473ffa_result ffa_mem_lend_rxtx(uint32_t total_length, uint32_t fragment_length,
474 uint64_t *handle)
475{
476 return ffa_mem_lend(total_length, fragment_length, NULL, 0, handle);
477}
478
479ffa_result ffa_mem_share(uint32_t total_length, uint32_t fragment_length,
480 void *buffer_address, uint32_t page_count,
481 uint64_t *handle)
482{
483 struct ffa_params result = {0};
484
Balint Dobszay40410ab2022-01-19 16:31:02 +0100485 ffa_svc((buffer_address) ? FFA_MEM_SHARE_64 : FFA_MEM_SHARE_32,
486 total_length, fragment_length, (uintptr_t)buffer_address,
487 page_count, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
488 &result);
Imre Kise3112e02020-11-23 03:15:46 +0100489
490 if (result.a0 == FFA_ERROR) {
491 *handle = 0U;
492 return ffa_get_errorcode(&result);
493 }
494
Balint Dobszay40410ab2022-01-19 16:31:02 +0100495 /*
496 * There are no 64-bit parameters returned with FFA_SUCCESS, the SPMC
497 * will use the default 32-bit version.
498 */
Imre Kise3112e02020-11-23 03:15:46 +0100499 assert(result.a0 == FFA_SUCCESS_32);
500 *handle = reg_pair_to_64(result.a3, result.a2);
501 return FFA_OK;
502}
503
504ffa_result ffa_mem_share_rxtx(uint32_t total_length, uint32_t fragment_length,
505 uint64_t *handle)
506{
507 return ffa_mem_share(total_length, fragment_length, NULL, 0, handle);
508}
509
510ffa_result ffa_mem_retrieve_req(uint32_t total_length, uint32_t fragment_length,
511 void *buffer_address, uint32_t page_count,
512 uint32_t *resp_total_length,
513 uint32_t *resp_fragment_length)
514{
515 struct ffa_params result = {0};
516
Balint Dobszay40410ab2022-01-19 16:31:02 +0100517 ffa_svc((buffer_address) ? FFA_MEM_RETRIEVE_REQ_64 : FFA_MEM_RETRIEVE_REQ_32,
518 total_length, fragment_length, (uintptr_t)buffer_address,
519 page_count, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
520 &result);
Imre Kise3112e02020-11-23 03:15:46 +0100521
522 if (result.a0 == FFA_ERROR) {
523 *resp_total_length = 0U;
524 *resp_fragment_length = 0U;
525 return ffa_get_errorcode(&result);
526 }
527
528 assert(result.a0 == FFA_MEM_RETRIEVE_RESP);
529 *resp_total_length = result.a1;
530 *resp_fragment_length = result.a2;
531 return FFA_OK;
532}
533
534ffa_result ffa_mem_retrieve_req_rxtx(uint32_t total_length,
535 uint32_t fragment_length,
536 uint32_t *resp_total_length,
537 uint32_t *resp_fragment_length)
538{
539 return ffa_mem_retrieve_req(total_length, fragment_length, NULL, 0,
540 resp_total_length, resp_fragment_length);
541}
542
543ffa_result ffa_mem_relinquish(void)
544{
545 struct ffa_params result = {0};
546
547 ffa_svc(FFA_MEM_RELINQUISH, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
548 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
549 &result);
550
551 if (result.a0 == FFA_ERROR)
552 return ffa_get_errorcode(&result);
553
554 assert(result.a0 == FFA_SUCCESS_32);
555 return FFA_OK;
556}
557
558ffa_result ffa_mem_reclaim(uint64_t handle, uint32_t flags)
559{
560 struct ffa_params result = {0};
561 uint32_t handle_hi = 0;
562 uint32_t handle_lo = 0;
563
564 reg_pair_from_64(handle, &handle_hi, &handle_lo);
565
566 ffa_svc(FFA_MEM_RECLAIM, handle_lo, handle_hi, flags, FFA_PARAM_MBZ,
567 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, &result);
568
569 if (result.a0 == FFA_ERROR)
570 return ffa_get_errorcode(&result);
571
572 assert(result.a0 == FFA_SUCCESS_32);
573 return FFA_OK;
574}
Imre Kisa5201e42022-02-22 15:25:21 +0100575
576ffa_result ffa_mem_perm_get(const void *base_address, uint32_t *mem_perm)
577{
578 struct ffa_params result = {0};
579
580 ffa_svc(FFA_MEM_PERM_GET, (uintptr_t)base_address, FFA_PARAM_MBZ,
581 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
582 FFA_PARAM_MBZ, &result);
583
584 if (result.a0 == FFA_ERROR)
585 return ffa_get_errorcode(&result);
586
587 assert(result.a0 == FFA_SUCCESS_32);
588 *mem_perm = result.a2;
589 return FFA_OK;
590}
591
592ffa_result ffa_mem_perm_set(const void *base_address, uint32_t page_count,
593 uint32_t mem_perm)
594{
595 struct ffa_params result = {0};
596
597 assert((mem_perm & FFA_MEM_PERM_RESERVED_MASK) == 0);
598
599 ffa_svc(FFA_MEM_PERM_SET, (uintptr_t)base_address, page_count, mem_perm,
600 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
601 &result);
602
603 if (result.a0 == FFA_ERROR)
604 return ffa_get_errorcode(&result);
605
606 assert(result.a0 == FFA_SUCCESS_32);
607 return FFA_OK;
608}
Imre Kise56c7b12023-06-01 13:33:40 +0200609
610ffa_result ffa_console_log_32(const char *message, size_t length)
611{
612 struct ffa_params result = {0};
613 uint32_t char_lists[6] = {0};
614
615 assert(length > 0 && length <= sizeof(char_lists));
616
617 memcpy(char_lists, message, MIN(length, sizeof(char_lists)));
618
619 ffa_svc(FFA_CONSOLE_LOG_32, length, char_lists[0], char_lists[1],
620 char_lists[2], char_lists[3], char_lists[4], char_lists[5],
621 &result);
622
623 if (result.a0 == FFA_ERROR)
624 return ffa_get_errorcode(&result);
625
626 assert(result.a0 == FFA_SUCCESS_32);
627 return FFA_OK;
628}
629
630ffa_result ffa_console_log_64(const char *message, size_t length)
631{
632 struct ffa_params result = {0};
633 uint64_t char_lists[6] = {0};
634
635 assert(length > 0 && length <= sizeof(char_lists));
636
637 memcpy(char_lists, message, MIN(length, sizeof(char_lists)));
638
639 ffa_svc(FFA_CONSOLE_LOG_64, length, char_lists[0], char_lists[1],
640 char_lists[2], char_lists[3], char_lists[4], char_lists[5],
641 &result);
642
643 if (result.a0 == FFA_ERROR)
644 return ffa_get_errorcode(&result);
645
646 assert(result.a0 == FFA_SUCCESS_32);
647 return FFA_OK;
648}