feat(memory sharing): retrieve response v1.0
Prepare retrieve response message depending on retriever's FF-A version.
If FF-A v1.0 prepare message using respective structures, else default
to FF-A v1.1 structures.
Change-Id: I1caeaea2159b054c252e1ec5f1185c7f33e626f4
Signed-off-by: J-Alves <joao.alves@arm.com>
diff --git a/src/ffa_memory.c b/src/ffa_memory.c
index 6ef64e1..a17000d 100644
--- a/src/ffa_memory.c
+++ b/src/ffa_memory.c
@@ -22,6 +22,8 @@
#include "hf/std.h"
#include "hf/vm.h"
+#include "vmapi/hf/ffa_v1_0.h"
+
/**
* All access to members of a `struct ffa_memory_share_state` must be guarded
* by this lock.
@@ -1666,6 +1668,121 @@
}
}
+/**
+ * Initialises the given memory region descriptor to be used for an
+ * `FFA_MEM_RETRIEVE_RESP`, including the given constituents for the first
+ * fragment.
+ * The memory region descriptor is initialized according to retriever's
+ * FF-A version.
+ *
+ * Returns true on success, or false if the given constituents won't all fit in
+ * the first fragment.
+ */
+static bool ffa_retrieved_memory_region_init(
+ void *response, uint32_t ffa_version, size_t response_max_size,
+ ffa_vm_id_t sender, ffa_memory_attributes_t attributes,
+ ffa_memory_region_flags_t flags, ffa_memory_handle_t handle,
+ ffa_vm_id_t receiver_id, ffa_memory_access_permissions_t permissions,
+ uint32_t page_count, uint32_t total_constituent_count,
+ const struct ffa_memory_region_constituent constituents[],
+ uint32_t fragment_constituent_count, uint32_t *total_length,
+ uint32_t *fragment_length)
+{
+ struct ffa_composite_memory_region *composite_memory_region;
+ struct ffa_memory_access *receiver;
+ uint32_t i;
+ uint32_t constituents_offset;
+ uint32_t receiver_count;
+
+ assert(response != NULL);
+
+ if (ffa_version == MAKE_FFA_VERSION(1, 0)) {
+ struct ffa_memory_region_v1_0 *retrieve_response =
+ (struct ffa_memory_region_v1_0 *)response;
+
+ ffa_memory_region_init_header_v1_0(retrieve_response, sender,
+ attributes, flags, handle, 0,
+ 1);
+
+ receiver = &retrieve_response->receivers[0];
+ receiver_count = retrieve_response->receiver_count;
+
+ receiver->composite_memory_region_offset =
+ sizeof(struct ffa_memory_region_v1_0) +
+ receiver_count * sizeof(struct ffa_memory_access);
+
+ composite_memory_region = ffa_memory_region_get_composite_v1_0(
+ retrieve_response, 0);
+ } else {
+ /* Default to FF-A v1.1 version. */
+ struct ffa_memory_region *retrieve_response =
+ (struct ffa_memory_region *)response;
+
+ ffa_memory_region_init_header(retrieve_response, sender,
+ attributes, flags, handle, 0, 1);
+
+ receiver = &retrieve_response->receivers[0];
+ receiver_count = retrieve_response->receiver_count;
+
+ /*
+ * Note that `sizeof(struct_ffa_memory_region)` and
+ * `sizeof(struct ffa_memory_access)` must both be multiples of
+ * 16 (as verified by the asserts in `ffa_memory.c`, so it is
+ * guaranteed that the offset we calculate here is aligned to a
+ * 64-bit boundary and so 64-bit values can be copied without
+ * alignment faults.
+ */
+ receiver->composite_memory_region_offset =
+ sizeof(struct ffa_memory_region) +
+ receiver_count * sizeof(struct ffa_memory_access);
+
+ composite_memory_region =
+ ffa_memory_region_get_composite(retrieve_response, 0);
+ }
+
+ assert(receiver != NULL);
+ assert(composite_memory_region != NULL);
+
+ /*
+ * Initialized here as in memory retrieve responses we currently expect
+ * one borrower to be specified.
+ */
+ ffa_memory_access_init_permissions(receiver, receiver_id, 0, 0, flags);
+ receiver->receiver_permissions.permissions = permissions;
+
+ composite_memory_region->page_count = page_count;
+ composite_memory_region->constituent_count = total_constituent_count;
+ composite_memory_region->reserved_0 = 0;
+
+ constituents_offset = receiver->composite_memory_region_offset +
+ sizeof(struct ffa_composite_memory_region);
+ if (constituents_offset +
+ fragment_constituent_count *
+ sizeof(struct ffa_memory_region_constituent) >
+ response_max_size) {
+ return false;
+ }
+
+ for (i = 0; i < fragment_constituent_count; ++i) {
+ composite_memory_region->constituents[i] = constituents[i];
+ }
+
+ if (total_length != NULL) {
+ *total_length =
+ constituents_offset +
+ composite_memory_region->constituent_count *
+ sizeof(struct ffa_memory_region_constituent);
+ }
+ if (fragment_length != NULL) {
+ *fragment_length =
+ constituents_offset +
+ fragment_constituent_count *
+ sizeof(struct ffa_memory_region_constituent);
+ }
+
+ return true;
+}
+
/*
* Gets the receiver's access permissions from 'struct ffa_memory_region' and
* returns its index in the receiver's array. If receiver's ID doesn't exist
@@ -2236,11 +2353,11 @@
* should never fail.
*/
CHECK(ffa_retrieved_memory_region_init(
- to_locked.vm->mailbox.recv, HF_MAILBOX_SIZE,
- memory_region->sender, memory_region->attributes,
- memory_region->flags, handle, receiver_id, permissions,
- composite->page_count, composite->constituent_count,
- share_state->fragments[0],
+ to_locked.vm->mailbox.recv, to_locked.vm->ffa_version,
+ HF_MAILBOX_SIZE, memory_region->sender,
+ memory_region->attributes, memory_region->flags, handle,
+ receiver_id, permissions, composite->page_count,
+ composite->constituent_count, share_state->fragments[0],
share_state->fragment_constituent_counts[0], &total_length,
&fragment_length));