test(memory sharing): force fragmented ff-a v1.0
Force a fragmented memory share operation, using FF-A v1.0 memory
transaction descriptors.
Change-Id: I1a06ec58601c82135a534a0a29ec6e5677a17744
Signed-off-by: J-Alves <joao.alves@arm.com>
diff --git a/test/inc/test/vmapi/ffa.h b/test/inc/test/vmapi/ffa.h
index 5b18aa2..8c01f72 100644
--- a/test/inc/test/vmapi/ffa.h
+++ b/test/inc/test/vmapi/ffa.h
@@ -102,6 +102,12 @@
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_vm_id_t recipient);
+void send_fragmented_memory_region(
+ struct ffa_value *send_ret, void *tx_buffer,
+ struct ffa_memory_region_constituent constituents[],
+ uint32_t constituent_count, uint32_t remaining_constituent_count,
+ uint32_t sent_length, uint32_t total_length,
+ ffa_memory_handle_t *handle, uint64_t allocator_mask);
ffa_vm_id_t retrieve_memory_from_message(
void *recv_buf, void *send_buf, ffa_memory_handle_t *handle,
struct ffa_memory_region *memory_region_ret,
diff --git a/test/vmapi/common/ffa.c b/test/vmapi/common/ffa.c
index a134d20..ee3f23b 100644
--- a/test/vmapi/common/ffa.c
+++ b/test/vmapi/common/ffa.c
@@ -99,7 +99,7 @@
EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
}
-static void send_fragmented_memory_region(
+void send_fragmented_memory_region(
struct ffa_value *send_ret, void *tx_buffer,
struct ffa_memory_region_constituent constituents[],
uint32_t constituent_count, uint32_t remaining_constituent_count,
diff --git a/test/vmapi/primary_with_secondaries/memory_sharing.c b/test/vmapi/primary_with_secondaries/memory_sharing.c
index 4d619a2..04d9795 100644
--- a/test/vmapi/primary_with_secondaries/memory_sharing.c
+++ b/test/vmapi/primary_with_secondaries/memory_sharing.c
@@ -3291,3 +3291,89 @@
EXPECT_EQ(ffa_run(service1_info->vm_id, 0).func, FFA_YIELD_32);
}
+
+TEST(memory_sharing, force_fragmented_ffa_v1_0)
+{
+ struct ffa_value ret;
+ struct mailbox_buffers mb = set_up_mailbox();
+ uint32_t msg_size;
+ ffa_memory_handle_t handle;
+ struct ffa_memory_access receiver;
+ struct ffa_memory_region_constituent constituents[] = {
+ {.address = (uint64_t)pages, .page_count = 2},
+ {.address = (uint64_t)pages + PAGE_SIZE * 3, .page_count = 1},
+ };
+ uint32_t remaining_constituent_count;
+ struct ffa_partition_info *service1_info = service1(mb.recv);
+ struct ffa_partition_msg *retrieve_message = mb.send;
+ uint32_t fragment_length;
+ uint32_t total_length;
+ uint64_t allocator_mask;
+ uint8_t *ptr = pages;
+
+ /* Set current version to FF-A v1.0. */
+ EXPECT_NE(ffa_version(MAKE_FFA_VERSION(1, 0)), FFA_ERROR_32);
+
+ SERVICE_SELECT(service1_info->vm_id, "retrieve_ffa_v1_0", mb.send);
+
+ ffa_memory_access_init_permissions(
+ &receiver, service1_info->vm_id, FFA_DATA_ACCESS_RW,
+ FFA_INSTRUCTION_ACCESS_NOT_SPECIFIED, 0);
+
+ /* Initialize memory sharing test according to v1.0. */
+ remaining_constituent_count = ffa_memory_region_init_v1_0(
+ (struct ffa_memory_region_v1_0 *)mb.send, HF_MAILBOX_SIZE,
+ hf_vm_get_id(), &receiver, 1, constituents,
+ ARRAY_SIZE(constituents), 0, 0, FFA_MEMORY_NORMAL_MEM,
+ FFA_MEMORY_CACHE_WRITE_BACK, FFA_MEMORY_INNER_SHAREABLE,
+ &total_length, &fragment_length);
+
+ EXPECT_EQ(remaining_constituent_count, 0);
+ EXPECT_EQ(total_length, fragment_length);
+
+ /* Don't include the last constituent in the first fragment. */
+ fragment_length -= sizeof(struct ffa_memory_region_constituent);
+ remaining_constituent_count = 1;
+
+ ret = ffa_mem_share(total_length, fragment_length);
+ EXPECT_EQ(ret.func, FFA_MEM_FRAG_RX_32);
+ handle = ffa_frag_handle(ret);
+ EXPECT_NE(handle, FFA_MEMORY_HANDLE_INVALID);
+
+ allocator_mask =
+ (IS_SP_ID(hf_vm_get_id()) || IS_SP_ID(service1_info->vm_id))
+ ? FFA_MEMORY_HANDLE_ALLOCATOR_SPMC
+ : FFA_MEMORY_HANDLE_ALLOCATOR_HYPERVISOR;
+
+ send_fragmented_memory_region(
+ &ret, mb.send, constituents, ARRAY_SIZE(constituents),
+ remaining_constituent_count, fragment_length, total_length,
+ &handle, allocator_mask);
+
+ msg_size = ffa_memory_retrieve_request_init_v1_0(
+ (struct ffa_memory_region_v1_0 *)retrieve_message->payload,
+ handle, hf_vm_get_id(), &receiver, 1, 0,
+ FFA_MEMORY_REGION_TRANSACTION_TYPE_SHARE, FFA_MEMORY_NORMAL_MEM,
+ FFA_MEMORY_CACHE_WRITE_BACK, FFA_MEMORY_INNER_SHAREABLE);
+ ffa_rxtx_header_init(hf_vm_get_id(), service1_info->vm_id, msg_size,
+ &retrieve_message->header);
+ EXPECT_LE(msg_size, HF_MAILBOX_SIZE);
+ EXPECT_EQ(ffa_msg_send2(0).func, FFA_SUCCESS_32);
+
+ /* Run service1 to retrieve memory. */
+ EXPECT_EQ(ffa_run(service1_info->vm_id, 0).func, FFA_YIELD_32);
+
+ /* Initialise the memory before giving it. */
+ for (uint32_t i = 0; i < PAGE_SIZE; i++) {
+ ptr[i] = i;
+ }
+
+ /* Run service1 to access memory. */
+ EXPECT_EQ(ffa_run(service1_info->vm_id, 0).func, FFA_YIELD_32);
+
+ /* Validate service1 access to the memory. */
+ for (uint32_t i = 0; i < PAGE_SIZE; i++) {
+ uint8_t val = i + 1;
+ ASSERT_EQ(ptr[i], val);
+ }
+}
diff --git a/test/vmapi/primary_with_secondaries/services/memory.c b/test/vmapi/primary_with_secondaries/services/memory.c
index dd6c14c..022bd6a 100644
--- a/test/vmapi/primary_with_secondaries/services/memory.c
+++ b/test/vmapi/primary_with_secondaries/services/memory.c
@@ -938,12 +938,17 @@
void *recv_buf = SERVICE_RECV_BUFFER();
void *send_buf = SERVICE_SEND_BUFFER();
struct ffa_memory_region_v1_0 *memory_region =
- (struct ffa_memory_region_v1_0 *)recv_buf;
+ (struct ffa_memory_region_v1_0 *)retrieve_buffer;
struct ffa_composite_memory_region *composite;
ffa_vm_id_t own_id = hf_vm_get_id();
const struct ffa_partition_msg *retrv_message =
(struct ffa_partition_msg *)recv_buf;
struct ffa_value ret;
+ uint32_t fragment_length;
+ uint32_t total_length;
+ uint32_t memory_region_max_size = HF_MAILBOX_SIZE;
+ uint32_t fragment_offset;
+ ffa_memory_handle_t handle;
/* Set Version to v1.0. */
ffa_version(MAKE_FFA_VERSION(1, 0));
@@ -964,9 +969,39 @@
ret = ffa_mem_retrieve_req(msg_size, msg_size);
EXPECT_EQ(ret.func, FFA_MEM_RETRIEVE_RESP_32);
+ fragment_length = ret.arg2;
+ total_length = ret.arg1;
+ memcpy_s(memory_region, memory_region_max_size, recv_buf,
+ fragment_length);
+
+ handle = memory_region->handle;
+
+ /* Copy first fragment. */
+ ASSERT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
+
+ fragment_offset = fragment_length;
+
+ while (fragment_offset < total_length) {
+ ret = ffa_mem_frag_rx(handle, fragment_offset);
+ EXPECT_EQ(ret.func, FFA_MEM_FRAG_TX_32);
+ EXPECT_EQ(ffa_frag_handle(ret), handle);
+ fragment_length = ret.arg3;
+ EXPECT_GT(fragment_length, 0);
+ ASSERT_LE(fragment_offset + fragment_length,
+ memory_region_max_size);
+ /* Copy received fragment. */
+ memcpy_s((uint8_t *)memory_region + fragment_offset,
+ memory_region_max_size - fragment_offset, recv_buf,
+ fragment_length);
+ fragment_offset += fragment_length;
+ ASSERT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
+ }
+
+ /* Retrieved all the fragments. */
ffa_yield();
+ /* Point to the whole copied structure. */
composite = ffa_memory_region_get_composite_v1_0(memory_region, 0);
update_mm_security_state(composite, arch_mm_extra_attributes_from_vm(