refactor(memory share): init descriptor for memory retrieve

Made the ffa_memory_retrieve_request_init be capable of initializing
the memory region descriptor with multiple receivers.
Kept an initialization function for tests with a single receiver,
to avoid having to refactor most tests.

Change-Id: I1eecae52ede91a93b03a2772cc1791cc9bf05165
Signed-off-by: J-Alves <joao.alves@arm.com>
diff --git a/inc/vmapi/hf/ffa.h b/inc/vmapi/hf/ffa.h
index 9e97684..e30821d 100644
--- a/inc/vmapi/hf/ffa.h
+++ b/inc/vmapi/hf/ffa.h
@@ -987,6 +987,12 @@
 	uint32_t *total_length);
 uint32_t ffa_memory_retrieve_request_init(
 	struct ffa_memory_region *memory_region, ffa_memory_handle_t handle,
+	ffa_vm_id_t sender, struct ffa_memory_access receivers[],
+	uint32_t receiver_count, uint32_t tag, ffa_memory_region_flags_t flags,
+	enum ffa_memory_type type, enum ffa_memory_cacheability cacheability,
+	enum ffa_memory_shareability shareability);
+uint32_t ffa_memory_retrieve_request_init_single_receiver(
+	struct ffa_memory_region *memory_region, ffa_memory_handle_t handle,
 	ffa_vm_id_t sender, ffa_vm_id_t receiver, uint32_t tag,
 	ffa_memory_region_flags_t flags, enum ffa_data_access data_access,
 	enum ffa_instruction_access instruction_access,
diff --git a/test/vmapi/common/ffa.c b/test/vmapi/common/ffa.c
index 42b0e48..76f6f23 100644
--- a/test/vmapi/common/ffa.c
+++ b/test/vmapi/common/ffa.c
@@ -130,7 +130,7 @@
 	 * Send the appropriate retrieve request to the VM so that it can use it
 	 * to retrieve the memory.
 	 */
-	msg_size = ffa_memory_retrieve_request_init(
+	msg_size = ffa_memory_retrieve_request_init_single_receiver(
 		tx_buffer, handle, sender, recipient, 0, retrieve_flags,
 		retrieve_data_access, retrieve_instruction_access,
 		FFA_MEMORY_NORMAL_MEM, FFA_MEMORY_CACHE_WRITE_BACK,
@@ -212,7 +212,7 @@
 	 * Send the appropriate retrieve request to the VM so that it can use it
 	 * to retrieve the memory.
 	 */
-	msg_size = ffa_memory_retrieve_request_init(
+	msg_size = ffa_memory_retrieve_request_init_single_receiver(
 		tx_buffer, handle, sender, recipient, 0, 0,
 		retrieve_data_access, retrieve_instruction_access,
 		FFA_MEMORY_NORMAL_MEM, FFA_MEMORY_CACHE_WRITE_BACK,
diff --git a/test/vmapi/el0_partitions/memory_sharing.c b/test/vmapi/el0_partitions/memory_sharing.c
index 65775fc..6a84137 100644
--- a/test/vmapi/el0_partitions/memory_sharing.c
+++ b/test/vmapi/el0_partitions/memory_sharing.c
@@ -2250,7 +2250,7 @@
 
 		handle = ffa_mem_success_handle(ret);
 
-		msg_size = ffa_memory_retrieve_request_init(
+		msg_size = ffa_memory_retrieve_request_init_single_receiver(
 			mb.send, handle, HF_PRIMARY_VM_ID, SERVICE_VM1, 0,
 			0xFFFFFFFF, FFA_DATA_ACCESS_RW,
 			FFA_INSTRUCTION_ACCESS_NOT_SPECIFIED,
@@ -2331,13 +2331,16 @@
 		handle = ffa_mem_success_handle(ret);
 
 		for (uint32_t j = 0; j < ARRAY_SIZE(invalid_attributes); ++j) {
-			msg_size = ffa_memory_retrieve_request_init(
-				mb.send, handle, HF_PRIMARY_VM_ID, SERVICE_VM1,
-				0, 0, FFA_DATA_ACCESS_RW,
-				FFA_INSTRUCTION_ACCESS_NOT_SPECIFIED,
-				invalid_attributes[j].memory_type,
-				invalid_attributes[j].memory_cacheability,
-				invalid_attributes[j].memory_shareability);
+			msg_size =
+				ffa_memory_retrieve_request_init_single_receiver(
+					mb.send, handle, HF_PRIMARY_VM_ID,
+					SERVICE_VM1, 0, 0, FFA_DATA_ACCESS_RW,
+					FFA_INSTRUCTION_ACCESS_NOT_SPECIFIED,
+					invalid_attributes[j].memory_type,
+					invalid_attributes[j]
+						.memory_cacheability,
+					invalid_attributes[j]
+						.memory_shareability);
 
 			EXPECT_LE(msg_size, HF_MAILBOX_SIZE);
 
@@ -2406,7 +2409,7 @@
 	handle = ffa_mem_success_handle(ret);
 
 	/* Prepare retrieve request setting clear memory flags. */
-	msg_size = ffa_memory_retrieve_request_init(
+	msg_size = ffa_memory_retrieve_request_init_single_receiver(
 		mb.send, handle, HF_PRIMARY_VM_ID, SERVICE_VM1, 0,
 		FFA_MEMORY_REGION_FLAG_CLEAR |
 			FFA_MEMORY_REGION_FLAG_CLEAR_RELINQUISH,
@@ -2462,7 +2465,7 @@
 	 * Prepare retrieve request with RO, and setting flag to clear memory.
 	 * Should fail at the receiver's FFA_MEM_RETRIEVE call.
 	 */
-	msg_size = ffa_memory_retrieve_request_init(
+	msg_size = ffa_memory_retrieve_request_init_single_receiver(
 		mb.send, handle, HF_PRIMARY_VM_ID, SERVICE_VM1, 0,
 		FFA_MEMORY_REGION_FLAG_CLEAR, FFA_DATA_ACCESS_RO,
 		FFA_INSTRUCTION_ACCESS_NOT_SPECIFIED, FFA_MEMORY_NORMAL_MEM,
diff --git a/test/vmapi/primary_with_secondaries/memory_sharing.c b/test/vmapi/primary_with_secondaries/memory_sharing.c
index 27d3997..0592f8e 100644
--- a/test/vmapi/primary_with_secondaries/memory_sharing.c
+++ b/test/vmapi/primary_with_secondaries/memory_sharing.c
@@ -372,7 +372,7 @@
 	 * to retrieve the memory.
 	 * The retrieve request doesn't specify the memory type.
 	 */
-	msg_size = ffa_memory_retrieve_request_init(
+	msg_size = ffa_memory_retrieve_request_init_single_receiver(
 		mb.send, handle, HF_PRIMARY_VM_ID, SERVICE_VM1, 0, 0,
 		FFA_DATA_ACCESS_RW, FFA_INSTRUCTION_ACCESS_NOT_SPECIFIED,
 		FFA_MEMORY_NOT_SPECIFIED_MEM, 0, 0);
@@ -2357,13 +2357,15 @@
 		handle = ffa_mem_success_handle(ret);
 
 		for (unsigned int j = 0; j < ARRAY_SIZE(invalid_flags); ++j) {
-			msg_size = ffa_memory_retrieve_request_init(
-				mb.send, handle, HF_PRIMARY_VM_ID, SERVICE_VM1,
-				0, invalid_flags[j], FFA_DATA_ACCESS_RW,
-				FFA_INSTRUCTION_ACCESS_NOT_SPECIFIED,
-				FFA_MEMORY_NORMAL_MEM,
-				FFA_MEMORY_CACHE_WRITE_BACK,
-				FFA_MEMORY_INNER_SHAREABLE);
+			msg_size =
+				ffa_memory_retrieve_request_init_single_receiver(
+					mb.send, handle, HF_PRIMARY_VM_ID,
+					SERVICE_VM1, 0, invalid_flags[j],
+					FFA_DATA_ACCESS_RW,
+					FFA_INSTRUCTION_ACCESS_NOT_SPECIFIED,
+					FFA_MEMORY_NORMAL_MEM,
+					FFA_MEMORY_CACHE_WRITE_BACK,
+					FFA_MEMORY_INNER_SHAREABLE);
 
 			EXPECT_LE(msg_size, HF_MAILBOX_SIZE);
 
@@ -2440,13 +2442,16 @@
 		handle = ffa_mem_success_handle(ret);
 
 		for (uint32_t j = 0; j < ARRAY_SIZE(invalid_attributes); ++j) {
-			msg_size = ffa_memory_retrieve_request_init(
-				mb.send, handle, HF_PRIMARY_VM_ID, SERVICE_VM1,
-				0, 0, FFA_DATA_ACCESS_RW,
-				FFA_INSTRUCTION_ACCESS_NOT_SPECIFIED,
-				invalid_attributes[j].memory_type,
-				invalid_attributes[j].memory_cacheability,
-				invalid_attributes[j].memory_shareability);
+			msg_size =
+				ffa_memory_retrieve_request_init_single_receiver(
+					mb.send, handle, HF_PRIMARY_VM_ID,
+					SERVICE_VM1, 0, 0, FFA_DATA_ACCESS_RW,
+					FFA_INSTRUCTION_ACCESS_NOT_SPECIFIED,
+					invalid_attributes[j].memory_type,
+					invalid_attributes[j]
+						.memory_cacheability,
+					invalid_attributes[j]
+						.memory_shareability);
 
 			EXPECT_LE(msg_size, HF_MAILBOX_SIZE);
 
@@ -2515,7 +2520,7 @@
 	handle = ffa_mem_success_handle(ret);
 
 	/* Prepare retrieve request setting clear memory flags. */
-	msg_size = ffa_memory_retrieve_request_init(
+	msg_size = ffa_memory_retrieve_request_init_single_receiver(
 		mb.send, handle, HF_PRIMARY_VM_ID, SERVICE_VM1, 0,
 		FFA_MEMORY_REGION_FLAG_CLEAR |
 			FFA_MEMORY_REGION_FLAG_CLEAR_RELINQUISH,
@@ -2571,7 +2576,7 @@
 	 * Prepare retrieve request with RO, and setting flag to clear memory.
 	 * Should fail at the receiver's FFA_MEM_RETRIEVE call.
 	 */
-	msg_size = ffa_memory_retrieve_request_init(
+	msg_size = ffa_memory_retrieve_request_init_single_receiver(
 		mb.send, handle, HF_PRIMARY_VM_ID, SERVICE_VM1, 0,
 		FFA_MEMORY_REGION_FLAG_CLEAR, FFA_DATA_ACCESS_RO,
 		FFA_INSTRUCTION_ACCESS_NOT_SPECIFIED, FFA_MEMORY_NORMAL_MEM,
@@ -2639,7 +2644,7 @@
 		 * memory. Should fail at the receiver's FFA_MEM_RETRIEVE_REQ
 		 * call with FFA_DENIED.
 		 */
-		msg_size = ffa_memory_retrieve_request_init(
+		msg_size = ffa_memory_retrieve_request_init_single_receiver(
 			mb.send, handle, HF_PRIMARY_VM_ID, SERVICE_VM1, 0,
 			FFA_MEMORY_REGION_FLAG_CLEAR, FFA_DATA_ACCESS_RW,
 			/* Different args for lend and donate. */
@@ -2715,7 +2720,7 @@
 		 * Should fail at the receiver's FFA_MEM_RETRIEVE_REQ
 		 * call with FFA_INVALID_PARAMETERS.
 		 */
-		msg_size = ffa_memory_retrieve_request_init(
+		msg_size = ffa_memory_retrieve_request_init_single_receiver(
 			mb.send, handle, HF_PRIMARY_VM_ID, SERVICE_VM1, 0,
 			send_function[i] == ffa_mem_share
 				? FFA_MEMORY_REGION_TRANSACTION_TYPE_LEND
diff --git a/vmlib/ffa.c b/vmlib/ffa.c
index 69ce8b2..51e8b87 100644
--- a/vmlib/ffa.c
+++ b/vmlib/ffa.c
@@ -228,7 +228,7 @@
  *
  * Returns the size of the message written.
  */
-uint32_t ffa_memory_retrieve_request_init(
+uint32_t ffa_memory_retrieve_request_init_single_receiver(
 	struct ffa_memory_region *memory_region, ffa_memory_handle_t handle,
 	ffa_vm_id_t sender, ffa_vm_id_t receiver, uint32_t tag,
 	ffa_memory_region_flags_t flags, enum ffa_data_access data_access,
@@ -236,7 +236,25 @@
 	enum ffa_memory_type type, enum ffa_memory_cacheability cacheability,
 	enum ffa_memory_shareability shareability)
 {
+	struct ffa_memory_access receiver_permissions;
+
+	ffa_memory_access_init_permissions(&receiver_permissions, receiver,
+					   data_access, instruction_access, 0);
+
+	return ffa_memory_retrieve_request_init(
+		memory_region, handle, sender, &receiver_permissions, 1, tag,
+		flags, type, cacheability, shareability);
+}
+
+uint32_t ffa_memory_retrieve_request_init(
+	struct ffa_memory_region *memory_region, ffa_memory_handle_t handle,
+	ffa_vm_id_t sender, struct ffa_memory_access receivers[],
+	uint32_t receiver_count, uint32_t tag, ffa_memory_region_flags_t flags,
+	enum ffa_memory_type type, enum ffa_memory_cacheability cacheability,
+	enum ffa_memory_shareability shareability)
+{
 	ffa_memory_attributes_t attributes = 0;
+	uint32_t i;
 
 	/* Set memory region's page attributes. */
 	ffa_set_memory_type_attr(&attributes, type);
@@ -244,18 +262,20 @@
 	ffa_set_memory_shareability_attr(&attributes, shareability);
 
 	ffa_memory_region_init_header(memory_region, sender, attributes, flags,
-				      handle, tag, 1);
-	ffa_memory_access_init_permissions(&memory_region->receivers[0],
-					   receiver, data_access,
-					   instruction_access, 0);
+				      handle, tag, receiver_count);
 
-	/*
-	 * Offset 0 in this case means that the hypervisor should allocate the
-	 * address ranges. This is the only configuration supported by Hafnium,
-	 * as it enforces 1:1 mappings in the stage 2 page tables.
-	 */
-	memory_region->receivers[0].composite_memory_region_offset = 0;
-	memory_region->receivers[0].reserved_0 = 0;
+#if defined(__linux__) && defined(__KERNEL__)
+	memcpy(memory_region->receivers, receivers,
+	       receiver_count * sizeof(struct ffa_memory_access));
+#else
+	memcpy_s(memory_region->receivers,
+		 MAX_MEM_SHARE_RECIPIENTS * sizeof(struct ffa_memory_access),
+		 receivers, receiver_count * sizeof(struct ffa_memory_access));
+#endif
+	/* Zero the composite offset for all receivers */
+	for (i = 0U; i < receiver_count; i++) {
+		memory_region->receivers[i].composite_memory_region_offset = 0U;
+	}
 
 	return sizeof(struct ffa_memory_region) +
 	       memory_region->receiver_count * sizeof(struct ffa_memory_access);