blob: e0388db947c2af672b5d0a061e5998c0564959a4 [file] [log] [blame]
Antonio Nino Diaz652d20a2018-12-10 17:17:33 +00001/*
Karl Meakin92aa7702023-10-11 18:48:01 +01002 * Copyright (c) 2018-2023, Arm Limited. All rights reserved.
Antonio Nino Diaz652d20a2018-12-10 17:17:33 +00003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
Maksims Svecovs0b452232022-05-24 11:30:34 +01006#include <assert.h>
Max Shvetsov103e0562021-02-04 16:58:31 +00007
J-Alves8f4a56f2020-10-28 10:29:05 +00008#include <ffa_endpoints.h>
J-Alves7581c382020-05-07 18:34:20 +01009#include <ffa_helpers.h>
10#include <ffa_svc.h>
Maksims Svecovs0b452232022-05-24 11:30:34 +010011#include <smccc.h>
Antonio Nino Diaz652d20a2018-12-10 17:17:33 +000012
Daniel Boulbyce386b12022-03-29 18:36:36 +010013struct ffa_value ffa_service_call(struct ffa_value *args)
14{
15#if IMAGE_IVY
16 ffa_svc(args);
17#else
18 ffa_smc(args);
19#endif
20 return *args;
21}
22
Olivier Deprez61be4c12019-12-06 17:45:07 +010023/*-----------------------------------------------------------------------------
J-Alves7581c382020-05-07 18:34:20 +010024 * FFA_RUN
Olivier Deprez61be4c12019-12-06 17:45:07 +010025 *
26 * Parameters
27 * uint32 Function ID (w0): 0x8400006D
28 * uint32 Target information (w1): Information to identify target SP/VM
29 * -Bits[31:16]: ID of SP/VM.
30 * -Bits[15:0]: ID of vCPU of SP/VM to run.
31 * Other Parameter registers w2-w7/x2-x7: Reserved (MBZ)
32 *
J-Alves7581c382020-05-07 18:34:20 +010033 * On failure, returns FFA_ERROR in w0 and error code in w2:
Olivier Deprez61be4c12019-12-06 17:45:07 +010034 * -INVALID_PARAMETERS: Unrecognized endpoint or vCPU ID
J-Alves7581c382020-05-07 18:34:20 +010035 * -NOT_SUPPORTED: This function is not implemented at this FFA instance
Olivier Deprez61be4c12019-12-06 17:45:07 +010036 * -DENIED: Callee is not in a state to handle this request
37 * -BUSY: vCPU is busy and caller must retry later
38 * -ABORTED: vCPU or VM ran into an unexpected error and has aborted
Antonio Nino Diazad8fcee2018-12-18 10:51:36 +000039 */
Daniel Boulbyce386b12022-03-29 18:36:36 +010040struct ffa_value ffa_run(uint32_t dest_id, uint32_t vcpu_id)
Antonio Nino Diazad8fcee2018-12-18 10:51:36 +000041{
Daniel Boulbyce386b12022-03-29 18:36:36 +010042 struct ffa_value args = {
Olivier Deprez56b270f2022-08-23 17:18:55 +020043 FFA_RUN,
Olivier Deprez61be4c12019-12-06 17:45:07 +010044 (dest_id << 16) | vcpu_id,
45 0, 0, 0, 0, 0, 0
Antonio Nino Diazad8fcee2018-12-18 10:51:36 +000046 };
47
Daniel Boulbyce386b12022-03-29 18:36:36 +010048 return ffa_service_call(&args);
Antonio Nino Diazad8fcee2018-12-18 10:51:36 +000049}
50
Olivier Deprez61be4c12019-12-06 17:45:07 +010051/*-----------------------------------------------------------------------------
J-Alves7581c382020-05-07 18:34:20 +010052 * FFA_MSG_SEND_DIRECT_REQ
Olivier Deprez61be4c12019-12-06 17:45:07 +010053 *
54 * Parameters
55 * uint32 Function ID (w0): 0x8400006F / 0xC400006F
56 * uint32 Source/Destination IDs (w1): Source and destination endpoint IDs
57 * -Bit[31:16]: Source endpoint ID
58 * -Bit[15:0]: Destination endpoint ID
59 * uint32/uint64 (w2/x2) - RFU MBZ
60 * w3-w7 - Implementation defined
61 *
J-Alves7581c382020-05-07 18:34:20 +010062 * On failure, returns FFA_ERROR in w0 and error code in w2:
Olivier Deprez61be4c12019-12-06 17:45:07 +010063 * -INVALID_PARAMETERS: Invalid endpoint ID or non-zero reserved register
64 * -DENIED: Callee is not in a state to handle this request
J-Alves7581c382020-05-07 18:34:20 +010065 * -NOT_SUPPORTED: This function is not implemented at this FFA instance
Olivier Deprez61be4c12019-12-06 17:45:07 +010066 * -BUSY: Message target is busy
67 * -ABORTED: Message target ran into an unexpected error and has aborted
Antonio Nino Diazad8fcee2018-12-18 10:51:36 +000068 */
Daniel Boulbyce386b12022-03-29 18:36:36 +010069struct ffa_value ffa_msg_send_direct_req64(ffa_id_t source_id,
70 ffa_id_t dest_id, uint64_t arg0,
71 uint64_t arg1, uint64_t arg2,
72 uint64_t arg3, uint64_t arg4)
Antonio Nino Diazad8fcee2018-12-18 10:51:36 +000073{
Daniel Boulbyce386b12022-03-29 18:36:36 +010074 struct ffa_value args = {
J-Alvesecd30742021-02-19 18:31:06 +000075 .fid = FFA_MSG_SEND_DIRECT_REQ_SMC64,
76 .arg1 = ((uint32_t)(source_id << 16)) | (dest_id),
77 .arg2 = 0,
78 .arg3 = arg0,
79 .arg4 = arg1,
80 .arg5 = arg2,
81 .arg6 = arg3,
82 .arg7 = arg4,
Antonio Nino Diazad8fcee2018-12-18 10:51:36 +000083 };
84
Daniel Boulbyce386b12022-03-29 18:36:36 +010085 return ffa_service_call(&args);
Antonio Nino Diazad8fcee2018-12-18 10:51:36 +000086}
87
Daniel Boulbyce386b12022-03-29 18:36:36 +010088struct ffa_value ffa_msg_send_direct_req32(ffa_id_t source_id,
89 ffa_id_t dest_id, uint32_t arg0,
90 uint32_t arg1, uint32_t arg2,
91 uint32_t arg3, uint32_t arg4)
Olivier Deprez61be4c12019-12-06 17:45:07 +010092{
Daniel Boulbyce386b12022-03-29 18:36:36 +010093 struct ffa_value args = {
J-Alvesecd30742021-02-19 18:31:06 +000094 .fid = FFA_MSG_SEND_DIRECT_REQ_SMC32,
95 .arg1 = ((uint32_t)(source_id << 16)) | (dest_id),
96 .arg2 = 0,
97 .arg3 = arg0,
98 .arg4 = arg1,
99 .arg5 = arg2,
100 .arg6 = arg3,
101 .arg7 = arg4,
Antonio Nino Diazad8fcee2018-12-18 10:51:36 +0000102 };
103
Daniel Boulbyce386b12022-03-29 18:36:36 +0100104 return ffa_service_call(&args);
Olivier Deprez61be4c12019-12-06 17:45:07 +0100105}
Antonio Nino Diazad8fcee2018-12-18 10:51:36 +0000106
Daniel Boulbyce386b12022-03-29 18:36:36 +0100107struct ffa_value ffa_msg_send_direct_resp64(ffa_id_t source_id,
108 ffa_id_t dest_id, uint64_t arg0,
109 uint64_t arg1, uint64_t arg2,
110 uint64_t arg3, uint64_t arg4)
Olivier Deprez61be4c12019-12-06 17:45:07 +0100111{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100112 struct ffa_value args = {
J-Alvesecd30742021-02-19 18:31:06 +0000113 .fid = FFA_MSG_SEND_DIRECT_RESP_SMC64,
114 .arg1 = ((uint32_t)(source_id << 16)) | (dest_id),
115 .arg2 = 0,
116 .arg3 = arg0,
117 .arg4 = arg1,
118 .arg5 = arg2,
119 .arg6 = arg3,
120 .arg7 = arg4,
121 };
122
Daniel Boulbyce386b12022-03-29 18:36:36 +0100123 return ffa_service_call(&args);
Antonio Nino Diazad8fcee2018-12-18 10:51:36 +0000124}
J-Alves8f08a052020-05-26 17:14:40 +0100125
Daniel Boulbyce386b12022-03-29 18:36:36 +0100126struct ffa_value ffa_msg_send_direct_resp32(ffa_id_t source_id,
127 ffa_id_t dest_id, uint32_t arg0,
128 uint32_t arg1, uint32_t arg2,
129 uint32_t arg3, uint32_t arg4)
J-Alvesecd30742021-02-19 18:31:06 +0000130{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100131 struct ffa_value args = {
J-Alvesecd30742021-02-19 18:31:06 +0000132 .fid = FFA_MSG_SEND_DIRECT_RESP_SMC32,
133 .arg1 = ((uint32_t)(source_id << 16)) | (dest_id),
134 .arg2 = 0,
135 .arg3 = arg0,
136 .arg4 = arg1,
137 .arg5 = arg2,
138 .arg6 = arg3,
139 .arg7 = arg4,
140 };
141
Daniel Boulbyce386b12022-03-29 18:36:36 +0100142 return ffa_service_call(&args);
J-Alvesecd30742021-02-19 18:31:06 +0000143}
144
Karl Meakin1331a8c2023-09-14 16:25:15 +0100145void ffa_memory_region_init_header(struct ffa_memory_region *memory_region,
146 ffa_id_t sender,
147 ffa_memory_attributes_t attributes,
148 ffa_memory_region_flags_t flags,
149 ffa_memory_handle_t handle, uint32_t tag,
150 uint32_t receiver_count)
J-Alvesf3a393c2020-10-23 16:00:39 +0100151{
152 memory_region->sender = sender;
153 memory_region->attributes = attributes;
J-Alvesf3a393c2020-10-23 16:00:39 +0100154 memory_region->flags = flags;
155 memory_region->handle = handle;
156 memory_region->tag = tag;
J-Alvesb42d17f2022-07-04 12:42:13 +0100157 memory_region->memory_access_desc_size =
158 sizeof(struct ffa_memory_access);
Karl Meakin1331a8c2023-09-14 16:25:15 +0100159 memory_region->receiver_count = receiver_count;
160 memory_region->receivers_offset =
161 offsetof(struct ffa_memory_region, receivers);
J-Alvesb42d17f2022-07-04 12:42:13 +0100162 memset(memory_region->reserved, 0, sizeof(memory_region->reserved));
J-Alvesf3a393c2020-10-23 16:00:39 +0100163}
164
165/**
Karl Meakin1331a8c2023-09-14 16:25:15 +0100166 * Copies as many as possible of the given constituents to the respective
167 * memory region and sets the respective offset.
J-Alvesf3a393c2020-10-23 16:00:39 +0100168 *
169 * Returns the number of constituents remaining which wouldn't fit, and (via
170 * return parameters) the size in bytes of the first fragment of data copied to
171 * `memory_region` (attributes, constituents and memory region header size), and
172 * the total size of the memory sharing message including all constituents.
173 */
Karl Meakin1331a8c2023-09-14 16:25:15 +0100174static uint32_t ffa_memory_region_init_constituents(
J-Alvesf3a393c2020-10-23 16:00:39 +0100175 struct ffa_memory_region *memory_region, size_t memory_region_max_size,
J-Alvesf3a393c2020-10-23 16:00:39 +0100176 const struct ffa_memory_region_constituent constituents[],
Karl Meakin1331a8c2023-09-14 16:25:15 +0100177 uint32_t constituent_count, uint32_t *total_length,
J-Alvesf3a393c2020-10-23 16:00:39 +0100178 uint32_t *fragment_length)
179{
J-Alvesf3a393c2020-10-23 16:00:39 +0100180 struct ffa_composite_memory_region *composite_memory_region;
181 uint32_t fragment_max_constituents;
J-Alvesf3a393c2020-10-23 16:00:39 +0100182 uint32_t constituents_offset;
Karl Meakin1331a8c2023-09-14 16:25:15 +0100183 uint32_t count_to_copy;
J-Alvesf3a393c2020-10-23 16:00:39 +0100184
J-Alvesf3a393c2020-10-23 16:00:39 +0100185 /*
186 * Note that `sizeof(struct_ffa_memory_region)` and `sizeof(struct
187 * ffa_memory_access)` must both be multiples of 16 (as verified by the
188 * asserts in `ffa_memory.c`, so it is guaranteed that the offset we
189 * calculate here is aligned to a 64-bit boundary and so 64-bit values
190 * can be copied without alignment faults.
Karl Meakin1331a8c2023-09-14 16:25:15 +0100191 * If there are multiple receiver endpoints, their respective access
192 * structure should point to the same offset value.
J-Alvesf3a393c2020-10-23 16:00:39 +0100193 */
Karl Meakin1331a8c2023-09-14 16:25:15 +0100194 for (uint32_t i = 0; i < memory_region->receiver_count; i++) {
195 memory_region->receivers[i].composite_memory_region_offset =
196 sizeof(struct ffa_memory_region) +
197 memory_region->receiver_count *
198 sizeof(struct ffa_memory_access);
199 }
J-Alvesf3a393c2020-10-23 16:00:39 +0100200
201 composite_memory_region =
202 ffa_memory_region_get_composite(memory_region, 0);
203 composite_memory_region->page_count = 0;
204 composite_memory_region->constituent_count = constituent_count;
205 composite_memory_region->reserved_0 = 0;
206
207 constituents_offset =
208 memory_region->receivers[0].composite_memory_region_offset +
209 sizeof(struct ffa_composite_memory_region);
210 fragment_max_constituents =
211 (memory_region_max_size - constituents_offset) /
212 sizeof(struct ffa_memory_region_constituent);
213
214 count_to_copy = constituent_count;
215 if (count_to_copy > fragment_max_constituents) {
216 count_to_copy = fragment_max_constituents;
217 }
218
Karl Meakin1331a8c2023-09-14 16:25:15 +0100219 for (uint32_t i = 0; i < constituent_count; ++i) {
J-Alvesf3a393c2020-10-23 16:00:39 +0100220 if (i < count_to_copy) {
221 composite_memory_region->constituents[i] =
222 constituents[i];
223 }
224 composite_memory_region->page_count +=
225 constituents[i].page_count;
226 }
227
228 if (total_length != NULL) {
229 *total_length =
230 constituents_offset +
231 composite_memory_region->constituent_count *
232 sizeof(struct ffa_memory_region_constituent);
233 }
234 if (fragment_length != NULL) {
235 *fragment_length =
236 constituents_offset +
237 count_to_copy *
238 sizeof(struct ffa_memory_region_constituent);
239 }
240
241 return composite_memory_region->constituent_count - count_to_copy;
242}
243
244/**
245 * Initialises the given `ffa_memory_region` to be used for an
246 * `FFA_MEM_RETRIEVE_REQ` by the receiver of a memory transaction.
Karl Meakin1331a8c2023-09-14 16:25:15 +0100247 * Initialises the given `ffa_memory_region` and copies as many as possible of
248 * the given constituents to it.
J-Alvesf3a393c2020-10-23 16:00:39 +0100249 *
Karl Meakin1331a8c2023-09-14 16:25:15 +0100250 * Returns the number of constituents remaining which wouldn't fit, and (via
251 * return parameters) the size in bytes of the first fragment of data copied to
252 * `memory_region` (attributes, constituents and memory region header size), and
253 * the total size of the memory sharing message including all constituents.
J-Alvesf3a393c2020-10-23 16:00:39 +0100254 */
Karl Meakin1331a8c2023-09-14 16:25:15 +0100255uint32_t ffa_memory_region_init(
256 struct ffa_memory_region *memory_region, size_t memory_region_max_size,
257 ffa_id_t sender, struct ffa_memory_access receivers[],
258 uint32_t receiver_count,
259 const struct ffa_memory_region_constituent constituents[],
260 uint32_t constituent_count, uint32_t tag,
261 ffa_memory_region_flags_t flags, enum ffa_memory_type type,
262 enum ffa_memory_cacheability cacheability,
263 enum ffa_memory_shareability shareability, uint32_t *total_length,
264 uint32_t *fragment_length)
J-Alvesf3a393c2020-10-23 16:00:39 +0100265{
Karl Meakin92aa7702023-10-11 18:48:01 +0100266 ffa_memory_attributes_t attributes = {
267 .type = type,
268 .cacheability = cacheability,
269 .shareability = shareability,
270 };
J-Alvesf3a393c2020-10-23 16:00:39 +0100271
272 ffa_memory_region_init_header(memory_region, sender, attributes, flags,
Karl Meakin1331a8c2023-09-14 16:25:15 +0100273 0, tag, receiver_count);
274
275 memcpy(memory_region->receivers, receivers,
276 receiver_count * sizeof(struct ffa_memory_access));
277
278 return ffa_memory_region_init_constituents(
279 memory_region, memory_region_max_size, constituents,
280 constituent_count, total_length, fragment_length);
281}
282
Karl Meakin0d4f5ff2023-10-13 20:03:16 +0100283uint32_t ffa_memory_fragment_init(
284 struct ffa_memory_region_constituent *fragment,
285 size_t fragment_max_size,
286 const struct ffa_memory_region_constituent constituents[],
287 uint32_t constituent_count, uint32_t *fragment_length)
288{
289 const uint32_t fragment_max_constituents =
290 fragment_max_size /
291 sizeof(struct ffa_memory_region_constituent);
292
293 uint32_t count_to_copy =
294 MIN(constituent_count, fragment_max_constituents);
295
296 for (uint32_t i = 0; i < count_to_copy; ++i) {
297 fragment[i] = constituents[i];
298 }
299
300 if (fragment_length != NULL) {
301 *fragment_length = count_to_copy *
302 sizeof(struct ffa_memory_region_constituent);
303 }
304
305 return constituent_count - count_to_copy;
306}
307
Karl Meakin1331a8c2023-09-14 16:25:15 +0100308/**
309 * Initialises the given `ffa_memory_region` to be used for an
310 * `FFA_MEM_RETRIEVE_REQ` by the receiver of a memory transaction.
311 *
312 * Returns the size of the message written.
313 */
314uint32_t ffa_memory_retrieve_request_init(
315 struct ffa_memory_region *memory_region, ffa_memory_handle_t handle,
316 ffa_id_t sender, struct ffa_memory_access receivers[],
317 uint32_t receiver_count, uint32_t tag, ffa_memory_region_flags_t flags,
318 enum ffa_memory_type type, enum ffa_memory_cacheability cacheability,
319 enum ffa_memory_shareability shareability)
320{
321 ffa_memory_attributes_t attributes = {
322 .type = type,
323 .cacheability = cacheability,
324 .shareability = shareability,
325 };
326
327 ffa_memory_region_init_header(memory_region, sender, attributes, flags,
328 handle, tag, receiver_count);
329
330 memcpy(memory_region->receivers, receivers,
331 receiver_count * sizeof(struct ffa_memory_access));
332
J-Alvesf3a393c2020-10-23 16:00:39 +0100333 /*
334 * Offset 0 in this case means that the hypervisor should allocate the
335 * address ranges. This is the only configuration supported by Hafnium,
336 * as it enforces 1:1 mappings in the stage 2 page tables.
337 */
Karl Meakin1331a8c2023-09-14 16:25:15 +0100338 for (uint32_t i = 0; i < receiver_count; i++) {
339 memory_region->receivers[i].composite_memory_region_offset = 0;
340 memory_region->receivers[i].reserved_0 = 0;
341 }
J-Alvesf3a393c2020-10-23 16:00:39 +0100342
343 return sizeof(struct ffa_memory_region) +
344 memory_region->receiver_count * sizeof(struct ffa_memory_access);
345}
346
Karl Meakin3d879b82023-06-16 10:32:08 +0100347/**
348 * Configure `region` for a hypervisor retrieve request - i.e. all fields except
349 * `handle` are initialized to 0.
350 */
351void ffa_hypervisor_retrieve_request_init(struct ffa_memory_region *region,
352 ffa_memory_handle_t handle)
353{
354 memset(region, 0, sizeof(struct ffa_memory_region));
355 region->handle = handle;
356}
357
Max Shvetsovc17c1d32020-06-11 15:03:01 +0100358/*
J-Alves5aecd982020-06-11 10:25:33 +0100359 * FFA Version ABI helper.
360 * Version fields:
361 * -Bits[30:16]: Major version.
362 * -Bits[15:0]: Minor version.
363 */
Daniel Boulbyce386b12022-03-29 18:36:36 +0100364struct ffa_value ffa_version(uint32_t input_version)
J-Alves8f08a052020-05-26 17:14:40 +0100365{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100366 struct ffa_value args = {
J-Alves8f08a052020-05-26 17:14:40 +0100367 .fid = FFA_VERSION,
368 .arg1 = input_version
369 };
370
Daniel Boulbyce386b12022-03-29 18:36:36 +0100371 return ffa_service_call(&args);
J-Alves8f08a052020-05-26 17:14:40 +0100372}
J-Alves5aecd982020-06-11 10:25:33 +0100373
Daniel Boulbyce386b12022-03-29 18:36:36 +0100374struct ffa_value ffa_id_get(void)
J-Alves5aecd982020-06-11 10:25:33 +0100375{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100376 struct ffa_value args = {
J-Alves5aecd982020-06-11 10:25:33 +0100377 .fid = FFA_ID_GET
378 };
379
Daniel Boulbyce386b12022-03-29 18:36:36 +0100380 return ffa_service_call(&args);
J-Alves5aecd982020-06-11 10:25:33 +0100381}
382
Daniel Boulbyce386b12022-03-29 18:36:36 +0100383struct ffa_value ffa_spm_id_get(void)
Daniel Boulby198deda2021-03-03 11:35:25 +0000384{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100385 struct ffa_value args = {
Daniel Boulby198deda2021-03-03 11:35:25 +0000386 .fid = FFA_SPM_ID_GET
387 };
388
Daniel Boulbyce386b12022-03-29 18:36:36 +0100389 return ffa_service_call(&args);
Daniel Boulby198deda2021-03-03 11:35:25 +0000390}
391
Daniel Boulbyce386b12022-03-29 18:36:36 +0100392struct ffa_value ffa_msg_wait(void)
J-Alves5aecd982020-06-11 10:25:33 +0100393{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100394 struct ffa_value args = {
J-Alves5aecd982020-06-11 10:25:33 +0100395 .fid = FFA_MSG_WAIT
396 };
397
Daniel Boulbyce386b12022-03-29 18:36:36 +0100398 return ffa_service_call(&args);
J-Alves5aecd982020-06-11 10:25:33 +0100399}
400
Daniel Boulbyce386b12022-03-29 18:36:36 +0100401struct ffa_value ffa_error(int32_t error_code)
J-Alves5aecd982020-06-11 10:25:33 +0100402{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100403 struct ffa_value args = {
J-Alves5aecd982020-06-11 10:25:33 +0100404 .fid = FFA_ERROR,
405 .arg1 = 0,
406 .arg2 = error_code
407 };
408
Daniel Boulbyce386b12022-03-29 18:36:36 +0100409 return ffa_service_call(&args);
J-Alves5aecd982020-06-11 10:25:33 +0100410}
Max Shvetsovc17c1d32020-06-11 15:03:01 +0100411
412/* Query the higher EL if the requested FF-A feature is implemented. */
Daniel Boulbyce386b12022-03-29 18:36:36 +0100413struct ffa_value ffa_features(uint32_t feature)
Max Shvetsovc17c1d32020-06-11 15:03:01 +0100414{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100415 struct ffa_value args = {
Max Shvetsovc17c1d32020-06-11 15:03:01 +0100416 .fid = FFA_FEATURES,
417 .arg1 = feature
418 };
419
Daniel Boulbyce386b12022-03-29 18:36:36 +0100420 return ffa_service_call(&args);
Max Shvetsovc17c1d32020-06-11 15:03:01 +0100421}
Max Shvetsovc32f4782020-06-23 09:41:15 +0100422
Karl Meakin31b81772023-03-14 15:38:17 +0000423/* Query the higher EL if the requested FF-A feature is implemented. */
424struct ffa_value ffa_features_with_input_property(uint32_t feature, uint32_t param)
425{
426 struct ffa_value args = {
427 .fid = FFA_FEATURES,
428 .arg1 = feature,
429 .arg2 = param,
430 };
431
432 return ffa_service_call(&args);
433}
434
Raghu Krishnamurthyab5321a2023-04-23 16:14:28 -0700435/* Get information about VMs or SPs based on UUID, using registers. */
436struct ffa_value ffa_partition_info_get_regs(const struct ffa_uuid uuid,
437 const uint16_t start_index,
438 const uint16_t tag)
439{
440 uint64_t arg1 = (uint64_t)uuid.uuid[1] << 32 | uuid.uuid[0];
441 uint64_t arg2 = (uint64_t)uuid.uuid[3] << 32 | uuid.uuid[2];
442 uint64_t arg3 = start_index | (uint64_t)tag << 16;
443
444 struct ffa_value args = {
445 .fid = FFA_PARTITION_INFO_GET_REGS_SMC64,
446 .arg1 = arg1,
447 .arg2 = arg2,
448 .arg3 = arg3,
449 };
450
451 return ffa_service_call(&args);
452}
453
Max Shvetsovc32f4782020-06-23 09:41:15 +0100454/* Get information about VMs or SPs based on UUID */
Daniel Boulbyce386b12022-03-29 18:36:36 +0100455struct ffa_value ffa_partition_info_get(const struct ffa_uuid uuid)
Max Shvetsovc32f4782020-06-23 09:41:15 +0100456{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100457 struct ffa_value args = {
Max Shvetsovc32f4782020-06-23 09:41:15 +0100458 .fid = FFA_PARTITION_INFO_GET,
Max Shvetsov0b7d25f2021-03-05 13:46:42 +0000459 .arg1 = uuid.uuid[0],
460 .arg2 = uuid.uuid[1],
461 .arg3 = uuid.uuid[2],
462 .arg4 = uuid.uuid[3]
Max Shvetsovc32f4782020-06-23 09:41:15 +0100463 };
464
Daniel Boulbyce386b12022-03-29 18:36:36 +0100465 return ffa_service_call(&args);
Max Shvetsovc32f4782020-06-23 09:41:15 +0100466}
467
J-Alves067daca2024-04-08 17:31:54 +0100468/* Querying the SPMC to release the rx buffers of the VM ID. */
469struct ffa_value ffa_rx_release_with_id(ffa_id_t vm_id)
Max Shvetsovc32f4782020-06-23 09:41:15 +0100470{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100471 struct ffa_value args = {
J-Alves067daca2024-04-08 17:31:54 +0100472 .fid = FFA_RX_RELEASE,
473 .arg1 = (uint64_t)vm_id,
Max Shvetsovc32f4782020-06-23 09:41:15 +0100474 };
475
Daniel Boulbyce386b12022-03-29 18:36:36 +0100476 return ffa_service_call(&args);
Max Shvetsovc32f4782020-06-23 09:41:15 +0100477}
Ruari Phippsbd0a7e42020-07-17 16:42:21 +0100478
J-Alves067daca2024-04-08 17:31:54 +0100479/* Query SPMC that the rx buffer of the partition can be released */
480struct ffa_value ffa_rx_release(void)
481{
482 return ffa_rx_release_with_id(0);
483}
484
Ruari Phippsbd0a7e42020-07-17 16:42:21 +0100485/* Map the RXTX buffer */
Daniel Boulbyce386b12022-03-29 18:36:36 +0100486struct ffa_value ffa_rxtx_map(uintptr_t send, uintptr_t recv, uint32_t pages)
Ruari Phippsbd0a7e42020-07-17 16:42:21 +0100487{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100488 struct ffa_value args = {
Ruari Phippsbd0a7e42020-07-17 16:42:21 +0100489 .fid = FFA_RXTX_MAP_SMC64,
490 .arg1 = send,
491 .arg2 = recv,
Daniel Boulbyd4da3dd2021-07-27 13:46:07 +0100492 .arg3 = pages,
493 .arg4 = FFA_PARAM_MBZ,
494 .arg5 = FFA_PARAM_MBZ,
495 .arg6 = FFA_PARAM_MBZ,
496 .arg7 = FFA_PARAM_MBZ
Ruari Phippsbd0a7e42020-07-17 16:42:21 +0100497 };
498
Daniel Boulbyce386b12022-03-29 18:36:36 +0100499 return ffa_service_call(&args);
Ruari Phippsbd0a7e42020-07-17 16:42:21 +0100500}
J-Alves3ea46d12020-09-09 11:13:05 +0100501
Daniel Boulbye0602902021-07-07 11:14:39 +0100502/* Unmap the RXTX buffer allocated by the given FF-A component */
Daniel Boulbyce386b12022-03-29 18:36:36 +0100503struct ffa_value ffa_rxtx_unmap(void)
Daniel Boulbye0602902021-07-07 11:14:39 +0100504{
Karl Meakinbff9b3c2024-01-18 16:08:35 +0000505 return ffa_rxtx_unmap_with_id(0);
506}
507
508struct ffa_value ffa_rxtx_unmap_with_id(uint32_t id)
509{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100510 struct ffa_value args = {
Daniel Boulbye0602902021-07-07 11:14:39 +0100511 .fid = FFA_RXTX_UNMAP,
Karl Meakinbff9b3c2024-01-18 16:08:35 +0000512 .arg1 = id << 16,
Daniel Boulbye0602902021-07-07 11:14:39 +0100513 .arg2 = FFA_PARAM_MBZ,
514 .arg3 = FFA_PARAM_MBZ,
515 .arg4 = FFA_PARAM_MBZ,
516 .arg5 = FFA_PARAM_MBZ,
517 .arg6 = FFA_PARAM_MBZ,
Karl Meakinbff9b3c2024-01-18 16:08:35 +0000518 .arg7 = FFA_PARAM_MBZ,
Daniel Boulbye0602902021-07-07 11:14:39 +0100519 };
520
Daniel Boulbyce386b12022-03-29 18:36:36 +0100521 return ffa_service_call(&args);
Daniel Boulbye0602902021-07-07 11:14:39 +0100522}
523
J-Alves779fba62024-04-05 14:14:40 +0100524/**
525 * Copies data from the sender's send buffer to the recipient's receive buffer
526 * and notifies the receiver.
527 *
528 * `flags` may include a 'Delay Schedule Receiver interrupt'.
529 *
530 * Returns FFA_SUCCESS if the message is sent, or an error code otherwise:
531 * - INVALID_PARAMETERS: one or more of the parameters do not conform.
532 * - BUSY: receiver's mailbox was full.
533 * - DENIED: receiver is not in a state to handle the request or doesn't
534 * support indirect messages.
535 */
J-Alvesffdfafb2024-04-09 12:07:11 +0100536struct ffa_value ffa_msg_send2_with_id(uint32_t flags, ffa_id_t sender)
J-Alves779fba62024-04-05 14:14:40 +0100537{
538 struct ffa_value args = {
539 .fid = FFA_MSG_SEND2,
J-Alvesffdfafb2024-04-09 12:07:11 +0100540 .arg1 = sender << 16,
J-Alves779fba62024-04-05 14:14:40 +0100541 .arg2 = flags,
542 .arg3 = FFA_PARAM_MBZ,
543 .arg4 = FFA_PARAM_MBZ,
544 .arg5 = FFA_PARAM_MBZ,
545 .arg6 = FFA_PARAM_MBZ,
546 .arg7 = FFA_PARAM_MBZ
547 };
548
549 return ffa_service_call(&args);
550}
551
J-Alvesffdfafb2024-04-09 12:07:11 +0100552struct ffa_value ffa_msg_send2(uint32_t flags)
553{
554 return ffa_msg_send2_with_id(flags, 0);
555}
556
J-Alves3ea46d12020-09-09 11:13:05 +0100557/* Donate memory to another partition */
Daniel Boulbyce386b12022-03-29 18:36:36 +0100558struct ffa_value ffa_mem_donate(uint32_t descriptor_length,
J-Alves3ea46d12020-09-09 11:13:05 +0100559 uint32_t fragment_length)
560{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100561 struct ffa_value args = {
J-Alves8984e722024-05-07 22:21:54 +0100562 .fid = FFA_MEM_DONATE_SMC64,
J-Alves3ea46d12020-09-09 11:13:05 +0100563 .arg1 = descriptor_length,
564 .arg2 = fragment_length,
565 .arg3 = FFA_PARAM_MBZ,
566 .arg4 = FFA_PARAM_MBZ
567 };
568
Daniel Boulbyce386b12022-03-29 18:36:36 +0100569 return ffa_service_call(&args);
J-Alves3ea46d12020-09-09 11:13:05 +0100570}
571
572/* Lend memory to another partition */
Daniel Boulbyce386b12022-03-29 18:36:36 +0100573struct ffa_value ffa_mem_lend(uint32_t descriptor_length,
574 uint32_t fragment_length)
J-Alves3ea46d12020-09-09 11:13:05 +0100575{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100576 struct ffa_value args = {
J-Alves8984e722024-05-07 22:21:54 +0100577 .fid = FFA_MEM_LEND_SMC64,
J-Alves3ea46d12020-09-09 11:13:05 +0100578 .arg1 = descriptor_length,
579 .arg2 = fragment_length,
580 .arg3 = FFA_PARAM_MBZ,
581 .arg4 = FFA_PARAM_MBZ
582 };
583
Daniel Boulbyce386b12022-03-29 18:36:36 +0100584 return ffa_service_call(&args);
J-Alves3ea46d12020-09-09 11:13:05 +0100585}
586
587/* Share memory with another partition */
Daniel Boulbyce386b12022-03-29 18:36:36 +0100588struct ffa_value ffa_mem_share(uint32_t descriptor_length,
589 uint32_t fragment_length)
J-Alves3ea46d12020-09-09 11:13:05 +0100590{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100591 struct ffa_value args = {
J-Alves8984e722024-05-07 22:21:54 +0100592 .fid = FFA_MEM_SHARE_SMC64,
J-Alves3ea46d12020-09-09 11:13:05 +0100593 .arg1 = descriptor_length,
594 .arg2 = fragment_length,
595 .arg3 = FFA_PARAM_MBZ,
596 .arg4 = FFA_PARAM_MBZ
597 };
598
Daniel Boulbyce386b12022-03-29 18:36:36 +0100599 return ffa_service_call(&args);
J-Alves3ea46d12020-09-09 11:13:05 +0100600}
601
602/* Retrieve memory shared by another partition */
Daniel Boulbyce386b12022-03-29 18:36:36 +0100603struct ffa_value ffa_mem_retrieve_req(uint32_t descriptor_length,
604 uint32_t fragment_length)
J-Alves3ea46d12020-09-09 11:13:05 +0100605{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100606 struct ffa_value args = {
J-Alves8984e722024-05-07 22:21:54 +0100607 .fid = FFA_MEM_RETRIEVE_REQ_SMC64,
J-Alves3ea46d12020-09-09 11:13:05 +0100608 .arg1 = descriptor_length,
609 .arg2 = fragment_length,
610 .arg3 = FFA_PARAM_MBZ,
611 .arg4 = FFA_PARAM_MBZ,
612 .arg5 = FFA_PARAM_MBZ,
613 .arg6 = FFA_PARAM_MBZ,
614 .arg7 = FFA_PARAM_MBZ
615 };
616
Daniel Boulbyce386b12022-03-29 18:36:36 +0100617 return ffa_service_call(&args);
J-Alves3ea46d12020-09-09 11:13:05 +0100618}
619
620/* Relinquish access to memory region */
Daniel Boulbyce386b12022-03-29 18:36:36 +0100621struct ffa_value ffa_mem_relinquish(void)
J-Alves3ea46d12020-09-09 11:13:05 +0100622{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100623 struct ffa_value args = {
J-Alves3ea46d12020-09-09 11:13:05 +0100624 .fid = FFA_MEM_RELINQUISH,
625 };
626
Daniel Boulbyce386b12022-03-29 18:36:36 +0100627 return ffa_service_call(&args);
J-Alves3ea46d12020-09-09 11:13:05 +0100628}
629
630/* Reclaim exclusive access to owned memory region */
Daniel Boulbyce386b12022-03-29 18:36:36 +0100631struct ffa_value ffa_mem_reclaim(uint64_t handle, uint32_t flags)
J-Alves3ea46d12020-09-09 11:13:05 +0100632{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100633 struct ffa_value args = {
J-Alves3ea46d12020-09-09 11:13:05 +0100634 .fid = FFA_MEM_RECLAIM,
635 .arg1 = (uint32_t) handle,
636 .arg2 = (uint32_t) (handle >> 32),
637 .arg3 = flags
638 };
639
Daniel Boulbyce386b12022-03-29 18:36:36 +0100640 return ffa_service_call(&args);
J-Alves3ea46d12020-09-09 11:13:05 +0100641}
J-Alvesbcb1f972021-03-11 14:03:54 +0000642
Karl Meakin0d4f5ff2023-10-13 20:03:16 +0100643struct ffa_value ffa_mem_frag_rx(ffa_memory_handle_t handle,
644 uint32_t fragment_offset)
645{
646 /* Note that sender MBZ at virtual instance. */
647 struct ffa_value args = {
648 .fid = FFA_MEM_FRAG_RX,
649 .arg1 = (uint32_t)handle,
650 .arg2 = (uint32_t)(handle >> 32),
651 .arg3 = fragment_offset,
652 };
653
654 return ffa_service_call(&args);
655}
656
657struct ffa_value ffa_mem_frag_tx(ffa_memory_handle_t handle,
658 uint32_t fragment_length)
659{
660 struct ffa_value args = {
661 .fid = FFA_MEM_FRAG_TX,
662 .arg1 = (uint32_t)handle,
663 .arg2 = (uint32_t)(handle >> 32),
664 .arg3 = fragment_length,
665 };
666
667 /* Note that sender MBZ at virtual instance. */
668 return ffa_service_call(&args);
669}
670
J-Alvesbcb1f972021-03-11 14:03:54 +0000671/** Create Notifications Bitmap for the given VM */
Daniel Boulbyce386b12022-03-29 18:36:36 +0100672struct ffa_value ffa_notification_bitmap_create(ffa_id_t vm_id,
673 ffa_vcpu_count_t vcpu_count)
J-Alvesbcb1f972021-03-11 14:03:54 +0000674{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100675 struct ffa_value args = {
J-Alvesbcb1f972021-03-11 14:03:54 +0000676 .fid = FFA_NOTIFICATION_BITMAP_CREATE,
677 .arg1 = vm_id,
678 .arg2 = vcpu_count,
679 .arg3 = FFA_PARAM_MBZ,
680 .arg4 = FFA_PARAM_MBZ,
681 .arg5 = FFA_PARAM_MBZ,
682 .arg6 = FFA_PARAM_MBZ,
683 .arg7 = FFA_PARAM_MBZ,
684 };
685
Daniel Boulbyce386b12022-03-29 18:36:36 +0100686 return ffa_service_call(&args);
J-Alvesbcb1f972021-03-11 14:03:54 +0000687}
688
689/** Destroy Notifications Bitmap for the given VM */
Daniel Boulbyce386b12022-03-29 18:36:36 +0100690struct ffa_value ffa_notification_bitmap_destroy(ffa_id_t vm_id)
J-Alvesbcb1f972021-03-11 14:03:54 +0000691{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100692 struct ffa_value args = {
J-Alvesbcb1f972021-03-11 14:03:54 +0000693 .fid = FFA_NOTIFICATION_BITMAP_DESTROY,
694 .arg1 = vm_id,
695 .arg2 = FFA_PARAM_MBZ,
696 .arg3 = FFA_PARAM_MBZ,
697 .arg4 = FFA_PARAM_MBZ,
698 .arg5 = FFA_PARAM_MBZ,
699 .arg6 = FFA_PARAM_MBZ,
700 .arg7 = FFA_PARAM_MBZ,
701 };
702
Daniel Boulbyce386b12022-03-29 18:36:36 +0100703 return ffa_service_call(&args);
J-Alvesbcb1f972021-03-11 14:03:54 +0000704}
705
J-Alves18c28052021-03-09 09:58:53 +0000706/** Bind VM to all the notifications in the bitmap */
Daniel Boulbyce386b12022-03-29 18:36:36 +0100707struct ffa_value ffa_notification_bind(ffa_id_t sender, ffa_id_t receiver,
708 uint32_t flags,
709 ffa_notification_bitmap_t bitmap)
J-Alves18c28052021-03-09 09:58:53 +0000710{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100711 struct ffa_value args = {
J-Alves18c28052021-03-09 09:58:53 +0000712 .fid = FFA_NOTIFICATION_BIND,
713 .arg1 = (sender << 16) | (receiver),
714 .arg2 = flags,
715 .arg3 = (uint32_t)(bitmap & 0xFFFFFFFFU),
716 .arg4 = (uint32_t)(bitmap >> 32),
717 .arg5 = FFA_PARAM_MBZ,
718 .arg6 = FFA_PARAM_MBZ,
719 .arg7 = FFA_PARAM_MBZ,
720 };
721
Daniel Boulbyce386b12022-03-29 18:36:36 +0100722 return ffa_service_call(&args);
J-Alves18c28052021-03-09 09:58:53 +0000723}
724
725/** Unbind previously bound VM from notifications in bitmap */
Daniel Boulbyce386b12022-03-29 18:36:36 +0100726struct ffa_value ffa_notification_unbind(ffa_id_t sender,
727 ffa_id_t receiver,
728 ffa_notification_bitmap_t bitmap)
J-Alves18c28052021-03-09 09:58:53 +0000729{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100730 struct ffa_value args = {
J-Alves18c28052021-03-09 09:58:53 +0000731 .fid = FFA_NOTIFICATION_UNBIND,
732 .arg1 = (sender << 16) | (receiver),
733 .arg2 = FFA_PARAM_MBZ,
734 .arg3 = (uint32_t)(bitmap),
735 .arg4 = (uint32_t)(bitmap >> 32),
736 .arg5 = FFA_PARAM_MBZ,
737 .arg6 = FFA_PARAM_MBZ,
738 .arg7 = FFA_PARAM_MBZ,
739 };
740
Daniel Boulbyce386b12022-03-29 18:36:36 +0100741 return ffa_service_call(&args);
J-Alves18c28052021-03-09 09:58:53 +0000742}
J-Alvesf156ae92021-10-08 12:10:05 +0100743
Daniel Boulbyce386b12022-03-29 18:36:36 +0100744struct ffa_value ffa_notification_set(ffa_id_t sender, ffa_id_t receiver,
745 uint32_t flags,
746 ffa_notification_bitmap_t bitmap)
J-Alvesf156ae92021-10-08 12:10:05 +0100747{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100748 struct ffa_value args = {
J-Alvesf156ae92021-10-08 12:10:05 +0100749 .fid = FFA_NOTIFICATION_SET,
750 .arg1 = (sender << 16) | (receiver),
751 .arg2 = flags,
752 .arg3 = (uint32_t)(bitmap & 0xFFFFFFFFU),
753 .arg4 = (uint32_t)(bitmap >> 32),
754 .arg5 = FFA_PARAM_MBZ,
755 .arg6 = FFA_PARAM_MBZ,
756 .arg7 = FFA_PARAM_MBZ
757 };
758
Daniel Boulbyce386b12022-03-29 18:36:36 +0100759 return ffa_service_call(&args);
J-Alvesf156ae92021-10-08 12:10:05 +0100760}
761
Daniel Boulbyce386b12022-03-29 18:36:36 +0100762struct ffa_value ffa_notification_get(ffa_id_t receiver, uint32_t vcpu_id,
763 uint32_t flags)
J-Alvesf156ae92021-10-08 12:10:05 +0100764{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100765 struct ffa_value args = {
J-Alvesf156ae92021-10-08 12:10:05 +0100766 .fid = FFA_NOTIFICATION_GET,
J-Alves37277192021-11-30 14:59:03 +0000767 .arg1 = (vcpu_id << 16) | (receiver),
J-Alvesf156ae92021-10-08 12:10:05 +0100768 .arg2 = flags,
769 .arg3 = FFA_PARAM_MBZ,
770 .arg4 = FFA_PARAM_MBZ,
771 .arg5 = FFA_PARAM_MBZ,
772 .arg6 = FFA_PARAM_MBZ,
773 .arg7 = FFA_PARAM_MBZ
774 };
775
Daniel Boulbyce386b12022-03-29 18:36:36 +0100776 return ffa_service_call(&args);
J-Alvesf156ae92021-10-08 12:10:05 +0100777}
J-Alves5bce2502021-06-14 14:27:45 +0100778
Daniel Boulbyce386b12022-03-29 18:36:36 +0100779struct ffa_value ffa_notification_info_get(void)
J-Alves5bce2502021-06-14 14:27:45 +0100780{
Daniel Boulbyce386b12022-03-29 18:36:36 +0100781 struct ffa_value args = {
J-Alves5bce2502021-06-14 14:27:45 +0100782 .fid = FFA_NOTIFICATION_INFO_GET_SMC64,
783 .arg1 = FFA_PARAM_MBZ,
784 .arg2 = FFA_PARAM_MBZ,
785 .arg3 = FFA_PARAM_MBZ,
786 .arg4 = FFA_PARAM_MBZ,
787 .arg5 = FFA_PARAM_MBZ,
788 .arg6 = FFA_PARAM_MBZ,
789 .arg7 = FFA_PARAM_MBZ
790 };
791
Daniel Boulbyce386b12022-03-29 18:36:36 +0100792 return ffa_service_call(&args);
J-Alves5bce2502021-06-14 14:27:45 +0100793}
Maksims Svecovs0b452232022-05-24 11:30:34 +0100794
795static size_t char_to_arg_helper(const char *message, size_t size,
796 u_register_t *arg)
797{
798 size_t to_write = size > sizeof(uint64_t) ? sizeof(uint64_t) : size;
799
800 for (int i = 0; i < to_write; i++) {
801 ((char *)arg)[i] = message[i];
802 }
803 return to_write;
804}
805
806struct ffa_value ffa_console_log(const char *message, size_t char_count)
807{
808 struct ffa_value args = {
809 .fid = FFA_CONSOLE_LOG_SMC64,
810 .arg1 = char_count,
811 };
812 size_t written = 0;
813
814 assert(char_count <= sizeof(uint64_t) * 6);
815
816 written += char_to_arg_helper(&message[written], char_count - written,
817 &args.arg2);
818 written += char_to_arg_helper(&message[written], char_count - written,
819 &args.arg3);
820 written += char_to_arg_helper(&message[written], char_count - written,
821 &args.arg4);
822 written += char_to_arg_helper(&message[written], char_count - written,
823 &args.arg5);
824 written += char_to_arg_helper(&message[written], char_count - written,
825 &args.arg6);
826 char_to_arg_helper(&message[written], char_count - written,
827 &args.arg7);
828
829 return ffa_service_call(&args);
830}
Karl Meakin367ff542023-11-01 15:05:37 +0000831
832/**
833 * Initializes receiver permissions in a memory transaction descriptor.
834 */
Daniel Boulbya24f23a2023-11-15 18:23:40 +0000835struct ffa_memory_access ffa_memory_access_init(
Karl Meakin367ff542023-11-01 15:05:37 +0000836 ffa_id_t receiver_id, enum ffa_data_access data_access,
837 enum ffa_instruction_access instruction_access,
Daniel Boulbya24f23a2023-11-15 18:23:40 +0000838 ffa_memory_receiver_flags_t flags,
839 struct ffa_memory_access_impdef *impdef)
Karl Meakin367ff542023-11-01 15:05:37 +0000840{
841 struct ffa_memory_access access;
842 access.reserved_0 = 0;
843 access.composite_memory_region_offset = 0;
844 access.receiver_permissions.flags = flags;
845 access.receiver_permissions.receiver = receiver_id;
846 access.receiver_permissions.permissions.data_access = data_access;
847 access.receiver_permissions.permissions.instruction_access =
848 instruction_access;
Daniel Boulbya24f23a2023-11-15 18:23:40 +0000849 access.impdef = impdef != NULL ? *impdef :
850 (struct ffa_memory_access_impdef){{0, 0}};
Karl Meakin367ff542023-11-01 15:05:37 +0000851
852 return access;
853}
Karl Meakinbff9b3c2024-01-18 16:08:35 +0000854
855/**
856 * Initialises the given `ffa_composite_memory_region` to be used for an
857 * `FFA_RXTX_MAP` forwarding in the case when Hypervisor needs the SPMC to map a
858 * VM's RXTX pair.
859 */
860static void
861ffa_composite_memory_region_init(struct ffa_composite_memory_region *composite,
862 void *address, uint32_t page_count)
863{
864 composite->page_count = page_count;
865 composite->constituent_count = 1;
866 composite->reserved_0 = 0;
867
868 composite->constituents[0].page_count = page_count;
869 composite->constituents[0].address = (void *)address;
870 composite->constituents[0].reserved = 0;
871}
872
873/**
874 * Initialises the given `ffa_endpoint_rx_tx_descriptor` to be used for an
875 * `FFA_RXTX_MAP` forwarding in the case when Hypervisor needs the SPMC to map a
876 * VM's RXTX pair.
877 *
878 * Each buffer is described by an `ffa_composite_memory_region` containing
879 * one `ffa_memory_region_constituent`.
880 */
881void ffa_endpoint_rxtx_descriptor_init(
882 struct ffa_endpoint_rxtx_descriptor *desc, ffa_id_t endpoint_id,
883 void *rx_address, void *tx_address)
884{
885 desc->endpoint_id = endpoint_id;
886 desc->reserved = 0;
887 desc->pad = 0;
888
889 /*
890 * RX's composite descriptor is allocated after the enpoint descriptor.
891 * `sizeof(struct ffa_endpoint_rx_tx_descriptor)` is guaranteed to be
892 * 16-byte aligned.
893 */
894 desc->rx_offset = sizeof(struct ffa_endpoint_rxtx_descriptor);
895
896 ffa_composite_memory_region_init(
897 (struct ffa_composite_memory_region *)((uintptr_t)desc +
898 desc->rx_offset),
899 rx_address, 1);
900
901 /*
902 * TX's composite descriptor is allocated after the RX descriptor.
903 * `sizeof(struct ffa_composite_memory_region)` and
904 * `sizeof(struct ffa_memory_region_constituent)` are guaranteed to be
905 * 16-byte aligned in ffa_memory.c.
906 */
907 desc->tx_offset = desc->rx_offset +
908 sizeof(struct ffa_composite_memory_region) +
909 sizeof(struct ffa_memory_region_constituent);
910
911 ffa_composite_memory_region_init(
912 (struct ffa_composite_memory_region *)((uintptr_t)desc +
913 desc->tx_offset),
914 tx_address, 1);
915}
916
917/**
918 * Mimics a forwarded FFA_RXTX_MAP call from a hypervisor.
919 */
920struct ffa_value ffa_rxtx_map_forward(struct ffa_endpoint_rxtx_descriptor *desc,
921 ffa_id_t endpoint_id,
922 void *rx_address, void *tx_address)
923{
924 ffa_endpoint_rxtx_descriptor_init(desc, endpoint_id, rx_address, tx_address);
925 return ffa_rxtx_map(0, 0, 0);
926}