blob: 03431ddd759153eb1313774cfb7ccd44f5f774cf [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
Imre Kis1bc4a622022-07-19 17:38:00 +0200302static ffa_result ffa_msg_send_direct_req(uint32_t function_id, uint32_t resp_id,
303 uint16_t source, uint16_t dest,
304 uint64_t a0, uint64_t a1, uint64_t a2,
305 uint64_t a3, uint64_t a4,
306 struct ffa_direct_msg *msg)
Imre Kis9fcf8412020-11-23 03:15:45 +0100307{
308 struct ffa_params result = {0};
309
Imre Kis1bc4a622022-07-19 17:38:00 +0200310 ffa_svc(function_id,
Imre Kis9fcf8412020-11-23 03:15:45 +0100311 SHIFT_U32(source, FFA_MSG_SEND_DIRECT_REQ_SOURCE_ID_SHIFT) |
312 dest, FFA_PARAM_MBZ, a0, a1, a2, a3, a4, &result);
313
314 while (result.a0 == FFA_INTERRUPT) {
Imre Kis1eb045b2025-01-27 13:30:33 +0100315 ffa_svc(FFA_RUN, result.a1, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
316 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
317 &result);
Imre Kis9fcf8412020-11-23 03:15:45 +0100318 }
319
320 if (result.a0 == FFA_ERROR) {
321 return ffa_get_errorcode(&result);
Imre Kis1bc4a622022-07-19 17:38:00 +0200322 } else if (result.a0 == resp_id) {
Imre Kis9fcf8412020-11-23 03:15:45 +0100323 ffa_unpack_direct_msg(&result, msg);
324 } else {
325 assert(result.a0 == FFA_SUCCESS_32);
326 *msg = (struct ffa_direct_msg){.function_id = result.a0};
327 }
328
329 return FFA_OK;
330}
331
Imre Kis1bc4a622022-07-19 17:38:00 +0200332ffa_result ffa_msg_send_direct_req_32(uint16_t source, uint16_t dest,
333 uint32_t a0, uint32_t a1, uint32_t a2,
334 uint32_t a3, uint32_t a4,
335 struct ffa_direct_msg *msg)
336{
337 return ffa_msg_send_direct_req(FFA_MSG_SEND_DIRECT_REQ_32,
338 FFA_MSG_SEND_DIRECT_RESP_32,
339 source, dest, a0, a1, a2, a3, a4, msg);
340}
341
342ffa_result ffa_msg_send_direct_req_64(uint16_t source, uint16_t dest,
343 uint64_t a0, uint64_t a1, uint64_t a2,
344 uint64_t a3, uint64_t a4,
345 struct ffa_direct_msg *msg)
346{
347 return ffa_msg_send_direct_req(FFA_MSG_SEND_DIRECT_REQ_64,
348 FFA_MSG_SEND_DIRECT_RESP_64,
349 source, dest, a0, a1, a2, a3, a4, msg);
350}
351
352static ffa_result ffa_msg_send_direct_resp(uint32_t function_id,
353 uint16_t source, uint16_t dest,
354 uint64_t a0, uint64_t a1,
355 uint64_t a2, uint64_t a3,
356 uint64_t a4,
357 struct ffa_direct_msg *msg)
Imre Kis9fcf8412020-11-23 03:15:45 +0100358{
359 struct ffa_params result = {0};
360
Imre Kis1bc4a622022-07-19 17:38:00 +0200361 ffa_svc(function_id,
Imre Kis9fcf8412020-11-23 03:15:45 +0100362 SHIFT_U32(source, FFA_MSG_SEND_DIRECT_RESP_SOURCE_ID_SHIFT) |
363 dest, FFA_PARAM_MBZ, a0, a1, a2, a3, a4, &result);
364
Balint Dobszayac721da2024-07-02 16:33:59 +0200365 /* FF-A framework messages are handled outside of the main partition message handler loop */
366 while ((result.a0 == FFA_INTERRUPT) ||
367 (result.a0 == FFA_MSG_SEND_DIRECT_REQ_32 && FFA_IS_FRAMEWORK_MSG(result.a2))) {
368 handle_framework_msg(&result);
Imre Kis9fcf8412020-11-23 03:15:45 +0100369 }
370
371 if (result.a0 == FFA_ERROR) {
372 return ffa_get_errorcode(&result);
Imre Kis1bc4a622022-07-19 17:38:00 +0200373 } else if (FFA_TO_32_BIT_FUNC(result.a0) == FFA_MSG_SEND_DIRECT_REQ_32) {
Imre Kis9fcf8412020-11-23 03:15:45 +0100374 ffa_unpack_direct_msg(&result, msg);
375 } else {
376 assert(result.a0 == FFA_SUCCESS_32);
377 *msg = (struct ffa_direct_msg){.function_id = result.a0};
378 }
379
380 return FFA_OK;
381}
Imre Kise3112e02020-11-23 03:15:46 +0100382
Imre Kis1bc4a622022-07-19 17:38:00 +0200383ffa_result ffa_msg_send_direct_resp_32(uint16_t source, uint16_t dest,
384 uint32_t a0, uint32_t a1, uint32_t a2,
385 uint32_t a3, uint32_t a4,
386 struct ffa_direct_msg *msg)
387{
388 return ffa_msg_send_direct_resp(FFA_MSG_SEND_DIRECT_RESP_32, source,
389 dest, a0, a1, a2, a3, a4, msg);
390}
391
392ffa_result ffa_msg_send_direct_resp_64(uint16_t source, uint16_t dest,
393 uint64_t a0, uint64_t a1, uint64_t a2,
394 uint64_t a3, uint64_t a4,
395 struct ffa_direct_msg *msg)
396{
397 return ffa_msg_send_direct_resp(FFA_MSG_SEND_DIRECT_RESP_64, source,
398 dest, a0, a1, a2, a3, a4, msg);
399}
400
Imre Kise3112e02020-11-23 03:15:46 +0100401ffa_result ffa_mem_donate(uint32_t total_length, uint32_t fragment_length,
402 void *buffer_address, uint32_t page_count,
403 uint64_t *handle)
404{
405 struct ffa_params result = {0};
406
Balint Dobszay40410ab2022-01-19 16:31:02 +0100407 ffa_svc((buffer_address) ? FFA_MEM_DONATE_64 : FFA_MEM_DONATE_32,
408 total_length, fragment_length, (uintptr_t)buffer_address,
409 page_count, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
410 &result);
Imre Kise3112e02020-11-23 03:15:46 +0100411
412 if (result.a0 == FFA_ERROR) {
413 *handle = 0U;
414 return ffa_get_errorcode(&result);
415 }
416
Balint Dobszay40410ab2022-01-19 16:31:02 +0100417 /*
418 * There are no 64-bit parameters returned with FFA_SUCCESS, the SPMC
419 * will use the default 32-bit version.
420 */
Imre Kise3112e02020-11-23 03:15:46 +0100421 assert(result.a0 == FFA_SUCCESS_32);
422 *handle = reg_pair_to_64(result.a3, result.a2);
423 return FFA_OK;
424}
425
426ffa_result ffa_mem_donate_rxtx(uint32_t total_length, uint32_t fragment_length,
427 uint64_t *handle)
428{
429 return ffa_mem_donate(total_length, fragment_length, NULL, 0, handle);
430}
431
432ffa_result ffa_mem_lend(uint32_t total_length, uint32_t fragment_length,
433 void *buffer_address, uint32_t page_count,
434 uint64_t *handle)
435{
436 struct ffa_params result = {0};
437
Balint Dobszay40410ab2022-01-19 16:31:02 +0100438 ffa_svc((buffer_address) ? FFA_MEM_LEND_64 : FFA_MEM_LEND_32,
439 total_length, fragment_length, (uintptr_t)buffer_address,
440 page_count, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
441 &result);
Imre Kise3112e02020-11-23 03:15:46 +0100442
443 if (result.a0 == FFA_ERROR) {
444 *handle = 0U;
445 return ffa_get_errorcode(&result);
446 }
447
Balint Dobszay40410ab2022-01-19 16:31:02 +0100448 /*
449 * There are no 64-bit parameters returned with FFA_SUCCESS, the SPMC
450 * will use the default 32-bit version.
451 */
Imre Kise3112e02020-11-23 03:15:46 +0100452 assert(result.a0 == FFA_SUCCESS_32);
453 *handle = reg_pair_to_64(result.a3, result.a2);
454 return FFA_OK;
455}
456
457ffa_result ffa_mem_lend_rxtx(uint32_t total_length, uint32_t fragment_length,
458 uint64_t *handle)
459{
460 return ffa_mem_lend(total_length, fragment_length, NULL, 0, handle);
461}
462
463ffa_result ffa_mem_share(uint32_t total_length, uint32_t fragment_length,
464 void *buffer_address, uint32_t page_count,
465 uint64_t *handle)
466{
467 struct ffa_params result = {0};
468
Balint Dobszay40410ab2022-01-19 16:31:02 +0100469 ffa_svc((buffer_address) ? FFA_MEM_SHARE_64 : FFA_MEM_SHARE_32,
470 total_length, fragment_length, (uintptr_t)buffer_address,
471 page_count, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
472 &result);
Imre Kise3112e02020-11-23 03:15:46 +0100473
474 if (result.a0 == FFA_ERROR) {
475 *handle = 0U;
476 return ffa_get_errorcode(&result);
477 }
478
Balint Dobszay40410ab2022-01-19 16:31:02 +0100479 /*
480 * There are no 64-bit parameters returned with FFA_SUCCESS, the SPMC
481 * will use the default 32-bit version.
482 */
Imre Kise3112e02020-11-23 03:15:46 +0100483 assert(result.a0 == FFA_SUCCESS_32);
484 *handle = reg_pair_to_64(result.a3, result.a2);
485 return FFA_OK;
486}
487
488ffa_result ffa_mem_share_rxtx(uint32_t total_length, uint32_t fragment_length,
489 uint64_t *handle)
490{
491 return ffa_mem_share(total_length, fragment_length, NULL, 0, handle);
492}
493
494ffa_result ffa_mem_retrieve_req(uint32_t total_length, uint32_t fragment_length,
495 void *buffer_address, uint32_t page_count,
496 uint32_t *resp_total_length,
497 uint32_t *resp_fragment_length)
498{
499 struct ffa_params result = {0};
500
Balint Dobszay40410ab2022-01-19 16:31:02 +0100501 ffa_svc((buffer_address) ? FFA_MEM_RETRIEVE_REQ_64 : FFA_MEM_RETRIEVE_REQ_32,
502 total_length, fragment_length, (uintptr_t)buffer_address,
503 page_count, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
504 &result);
Imre Kise3112e02020-11-23 03:15:46 +0100505
506 if (result.a0 == FFA_ERROR) {
507 *resp_total_length = 0U;
508 *resp_fragment_length = 0U;
509 return ffa_get_errorcode(&result);
510 }
511
512 assert(result.a0 == FFA_MEM_RETRIEVE_RESP);
513 *resp_total_length = result.a1;
514 *resp_fragment_length = result.a2;
515 return FFA_OK;
516}
517
518ffa_result ffa_mem_retrieve_req_rxtx(uint32_t total_length,
519 uint32_t fragment_length,
520 uint32_t *resp_total_length,
521 uint32_t *resp_fragment_length)
522{
523 return ffa_mem_retrieve_req(total_length, fragment_length, NULL, 0,
524 resp_total_length, resp_fragment_length);
525}
526
527ffa_result ffa_mem_relinquish(void)
528{
529 struct ffa_params result = {0};
530
531 ffa_svc(FFA_MEM_RELINQUISH, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
532 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
533 &result);
534
535 if (result.a0 == FFA_ERROR)
536 return ffa_get_errorcode(&result);
537
538 assert(result.a0 == FFA_SUCCESS_32);
539 return FFA_OK;
540}
541
542ffa_result ffa_mem_reclaim(uint64_t handle, uint32_t flags)
543{
544 struct ffa_params result = {0};
545 uint32_t handle_hi = 0;
546 uint32_t handle_lo = 0;
547
548 reg_pair_from_64(handle, &handle_hi, &handle_lo);
549
550 ffa_svc(FFA_MEM_RECLAIM, handle_lo, handle_hi, flags, FFA_PARAM_MBZ,
551 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, &result);
552
553 if (result.a0 == FFA_ERROR)
554 return ffa_get_errorcode(&result);
555
556 assert(result.a0 == FFA_SUCCESS_32);
557 return FFA_OK;
558}
Imre Kisa5201e42022-02-22 15:25:21 +0100559
560ffa_result ffa_mem_perm_get(const void *base_address, uint32_t *mem_perm)
561{
562 struct ffa_params result = {0};
563
564 ffa_svc(FFA_MEM_PERM_GET, (uintptr_t)base_address, FFA_PARAM_MBZ,
565 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
566 FFA_PARAM_MBZ, &result);
567
568 if (result.a0 == FFA_ERROR)
569 return ffa_get_errorcode(&result);
570
571 assert(result.a0 == FFA_SUCCESS_32);
572 *mem_perm = result.a2;
573 return FFA_OK;
574}
575
576ffa_result ffa_mem_perm_set(const void *base_address, uint32_t page_count,
577 uint32_t mem_perm)
578{
579 struct ffa_params result = {0};
580
581 assert((mem_perm & FFA_MEM_PERM_RESERVED_MASK) == 0);
582
583 ffa_svc(FFA_MEM_PERM_SET, (uintptr_t)base_address, page_count, mem_perm,
584 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
585 &result);
586
587 if (result.a0 == FFA_ERROR)
588 return ffa_get_errorcode(&result);
589
590 assert(result.a0 == FFA_SUCCESS_32);
591 return FFA_OK;
592}
Imre Kise56c7b12023-06-01 13:33:40 +0200593
594ffa_result ffa_console_log_32(const char *message, size_t length)
595{
596 struct ffa_params result = {0};
597 uint32_t char_lists[6] = {0};
598
599 assert(length > 0 && length <= sizeof(char_lists));
600
601 memcpy(char_lists, message, MIN(length, sizeof(char_lists)));
602
603 ffa_svc(FFA_CONSOLE_LOG_32, length, char_lists[0], char_lists[1],
604 char_lists[2], char_lists[3], char_lists[4], char_lists[5],
605 &result);
606
607 if (result.a0 == FFA_ERROR)
608 return ffa_get_errorcode(&result);
609
610 assert(result.a0 == FFA_SUCCESS_32);
611 return FFA_OK;
612}
613
614ffa_result ffa_console_log_64(const char *message, size_t length)
615{
616 struct ffa_params result = {0};
617 uint64_t char_lists[6] = {0};
618
619 assert(length > 0 && length <= sizeof(char_lists));
620
621 memcpy(char_lists, message, MIN(length, sizeof(char_lists)));
622
623 ffa_svc(FFA_CONSOLE_LOG_64, length, char_lists[0], char_lists[1],
624 char_lists[2], char_lists[3], char_lists[4], char_lists[5],
625 &result);
626
627 if (result.a0 == FFA_ERROR)
628 return ffa_get_errorcode(&result);
629
630 assert(result.a0 == FFA_SUCCESS_32);
631 return FFA_OK;
632}