aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/runtime_services/ffa_helpers.h10
-rw-r--r--include/runtime_services/spm_common.h26
-rw-r--r--spm/cactus/cactus_ffa_tests.c161
-rw-r--r--spm/cactus/cactus_tests.h13
-rw-r--r--spm/cactus/cactus_tests/cactus_test_memory_sharing.c98
-rw-r--r--tftf/tests/runtime_services/secure_service/ffa_helpers.c85
-rw-r--r--tftf/tests/runtime_services/secure_service/spm_common.c175
-rw-r--r--tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c2
8 files changed, 291 insertions, 279 deletions
diff --git a/include/runtime_services/ffa_helpers.h b/include/runtime_services/ffa_helpers.h
index 17587b3be..064b5a3fe 100644
--- a/include/runtime_services/ffa_helpers.h
+++ b/include/runtime_services/ffa_helpers.h
@@ -364,16 +364,6 @@ uint32_t ffa_memory_region_init(
enum ffa_memory_shareability shareability, uint32_t *total_length,
uint32_t *fragment_length);
-ffa_memory_handle_t ffa_memory_send(
- struct ffa_memory_region *memory_region, uint32_t mem_func,
- uint32_t fragment_length, uint32_t total_length);
-
-ffa_memory_handle_t ffa_memory_init_and_send(
- struct ffa_memory_region *memory_region, size_t memory_region_max_size,
- ffa_vm_id_t sender, ffa_vm_id_t receiver,
- const struct ffa_memory_region_constituent* constituents,
- uint32_t constituents_count, uint32_t mem_func);
-
static inline ffa_vm_id_t ffa_dir_msg_dest(smc_ret_values val) {
return (ffa_vm_id_t)val.ret1 & U(0xFFFF);
}
diff --git a/include/runtime_services/spm_common.h b/include/runtime_services/spm_common.h
index b09000238..74a2b2746 100644
--- a/include/runtime_services/spm_common.h
+++ b/include/runtime_services/spm_common.h
@@ -82,4 +82,30 @@ bool check_spmc_execution_level(void);
unsigned int get_ffa_feature_test_target(const struct ffa_features_test **test_target);
+/**
+ * Helper to conduct a memory retrieve. This is to be called by the receiver
+ * of a memory share operation.
+ */
+bool memory_retrieve(struct mailbox_buffers *mb,
+ struct ffa_memory_region **retrieved, uint64_t handle,
+ ffa_vm_id_t sender, ffa_vm_id_t receiver,
+ uint32_t mem_func);
+
+/**
+ * Helper to conduct a memory relinquish. The caller is usually the receiver,
+ * after it being done with the memory shared, identified by the 'handle'.
+ */
+bool memory_relinquish(struct ffa_mem_relinquish *m, uint64_t handle,
+ ffa_vm_id_t id);
+
+ffa_memory_handle_t memory_send(
+ struct ffa_memory_region *memory_region, uint32_t mem_func,
+ uint32_t fragment_length, uint32_t total_length);
+
+ffa_memory_handle_t memory_init_and_send(
+ struct ffa_memory_region *memory_region, size_t memory_region_max_size,
+ ffa_vm_id_t sender, ffa_vm_id_t receiver,
+ const struct ffa_memory_region_constituent* constituents,
+ uint32_t constituents_count, uint32_t mem_func);
+
#endif /* SPM_COMMON_H */
diff --git a/spm/cactus/cactus_ffa_tests.c b/spm/cactus/cactus_ffa_tests.c
index 8d34e3759..c1ba78350 100644
--- a/spm/cactus/cactus_ffa_tests.c
+++ b/spm/cactus/cactus_ffa_tests.c
@@ -14,7 +14,6 @@
#include <spm_common.h>
#include <lib/libc/string.h>
-#include <lib/xlat_tables/xlat_tables_v2.h>
/* FFA version test helpers */
#define FFA_MAJOR 1U
@@ -163,166 +162,6 @@ void ffa_version_test(void)
announce_test_end(test_ffa_version);
}
-bool ffa_memory_retrieve_test(struct mailbox_buffers *mb,
- struct ffa_memory_region **retrieved,
- uint64_t handle, ffa_vm_id_t sender,
- ffa_vm_id_t receiver, uint32_t mem_func)
-{
- smc_ret_values ret;
- uint32_t fragment_size;
- uint32_t total_size;
- uint32_t descriptor_size;
-
- if (retrieved == NULL || mb == NULL) {
- ERROR("Invalid parameters!\n");
- return false;
- }
-
- /*
- * TODO: Revise shareability attribute in function call
- * below.
- * https://lists.trustedfirmware.org/pipermail/hafnium/2020-June/000023.html
- */
- descriptor_size = ffa_memory_retrieve_request_init(
- mb->send, handle, sender, receiver, 0, 0,
- FFA_DATA_ACCESS_RW,
- FFA_INSTRUCTION_ACCESS_NX,
- FFA_MEMORY_NORMAL_MEM,
- FFA_MEMORY_CACHE_WRITE_BACK,
- FFA_MEMORY_OUTER_SHAREABLE);
-
- ret = ffa_mem_retrieve_req(descriptor_size, descriptor_size);
-
- if (ffa_func_id(ret) != FFA_MEM_RETRIEVE_RESP) {
- ERROR("Couldn't retrieve the memory page. Error: %lx\n",
- ret.ret2);
- return false;
- }
-
- /*
- * Following total_size and fragment_size are useful to keep track
- * of the state of transaction. When the sum of all fragment_size of all
- * fragments is equal to total_size, the memory transaction has been
- * completed.
- * This is a simple test with only one segment. As such, upon
- * successful ffa_mem_retrieve_req, total_size must be equal to
- * fragment_size.
- */
- total_size = ret.ret1;
- fragment_size = ret.ret2;
-
- if (total_size != fragment_size) {
- ERROR("Only expect one memory segment to be sent!\n");
- return false;
- }
-
- if (fragment_size > PAGE_SIZE) {
- ERROR("Fragment should be smaller than RX buffer!\n");
- return false;
- }
-
- *retrieved = (struct ffa_memory_region *)mb->recv;
-
- if ((*retrieved)->receiver_count > MAX_MEM_SHARE_RECIPIENTS) {
- VERBOSE("SPMC memory sharing operations support max of %u "
- "receivers!\n", MAX_MEM_SHARE_RECIPIENTS);
- return false;
- }
-
- VERBOSE("Memory Retrieved!\n");
-
- return true;
-}
-
-bool ffa_memory_relinquish_test(struct ffa_mem_relinquish *m,
- uint64_t handle,
- ffa_vm_id_t id)
-{
- smc_ret_values ret;
-
- ffa_mem_relinquish_init(m, handle, 0, id);
- ret = ffa_mem_relinquish();
- if (ffa_func_id(ret) != FFA_SUCCESS_SMC32) {
- ERROR("%s failed to relinquish memory! error: %x\n",
- __func__, ffa_error_code(ret));
- return false;
- }
-
- VERBOSE("Memory Relinquished!\n");
- return true;
-}
-
-void ffa_memory_management_test(struct mailbox_buffers *mb, ffa_vm_id_t vm_id,
- ffa_vm_id_t sender, uint32_t mem_func,
- uint64_t handle)
-{
- const char *test_ffa = "Memory Management";
- struct ffa_memory_region *m;
- struct ffa_composite_memory_region *composite;
- int ret;
- unsigned int mem_attrs;
- uint32_t *ptr;
-
- announce_test_section_start(test_ffa);
-
- expect(ffa_memory_retrieve_test(
- mb, &m, handle, sender, vm_id, mem_func),
- true);
-
- composite = ffa_memory_region_get_composite(m, 0);
-
- VERBOSE("Address: %p; page_count: %x %x\n",
- composite->constituents[0].address,
- composite->constituents[0].page_count, PAGE_SIZE);
-
- /* This test is only concerned with RW permissions. */
- expect(ffa_get_data_access_attr(
- m->receivers[0].receiver_permissions.permissions),
- FFA_DATA_ACCESS_RW);
-
- mem_attrs = MT_RW_DATA | MT_EXECUTE_NEVER;
-
- if (!IS_SP_ID(sender)) {
- mem_attrs |= MT_NS;
- }
-
- ret = mmap_add_dynamic_region(
- (uint64_t)composite->constituents[0].address,
- (uint64_t)composite->constituents[0].address,
- composite->constituents[0].page_count * PAGE_SIZE,
- mem_attrs);
- expect(ret, 0);
-
- VERBOSE("Memory has been mapped\n");
-
- ptr = (uint32_t *) composite->constituents[0].address;
-
- /* Write mem_func to retrieved memory region for validation purposes. */
- VERBOSE("Writing: %x\n", mem_func);
- for (unsigned int i = 0U; i < 5U; i++)
- ptr[i] = mem_func;
-
- /*
- * A FFA_MEM_DONATE changes the ownership of the page, as such no
- * relinquish is needed.
- */
- if (mem_func != FFA_MEM_DONATE_SMC32) {
- ret = mmap_remove_dynamic_region(
- (uint64_t)composite->constituents[0].address,
- composite->constituents[0].page_count * PAGE_SIZE);
- expect(ret, 0);
-
- expect(ffa_memory_relinquish_test(
- (struct ffa_mem_relinquish *)mb->send,
- m->handle, vm_id),
- true);
- }
-
- expect(ffa_func_id(ffa_rx_release()), FFA_SUCCESS_SMC32);
-
- announce_test_section_end(test_ffa);
-}
-
void ffa_tests(struct mailbox_buffers *mb)
{
const char *test_ffa = "FFA Interfaces";
diff --git a/spm/cactus/cactus_tests.h b/spm/cactus/cactus_tests.h
index c0c235ec0..1039ba5d7 100644
--- a/spm/cactus/cactus_tests.h
+++ b/spm/cactus/cactus_tests.h
@@ -13,19 +13,6 @@
* Test functions
*/
-/*
- * Alter SIMD vectors to check saving of the context while switching between
- * the normal world and the secure world.
- */
-void fill_simd_vectors(void);
-
-/*
- * Test to FFA interfaces.
- */
-void ffa_memory_management_test(struct mailbox_buffers *mb, ffa_vm_id_t vm_id,
- ffa_vm_id_t sender, uint32_t mem_func,
- uint64_t handle);
-
void ffa_tests(struct mailbox_buffers *mb);
/*
diff --git a/spm/cactus/cactus_tests/cactus_test_memory_sharing.c b/spm/cactus/cactus_tests/cactus_test_memory_sharing.c
index 63c3d1387..82cdac394 100644
--- a/spm/cactus/cactus_tests/cactus_test_memory_sharing.c
+++ b/spm/cactus/cactus_tests/cactus_test_memory_sharing.c
@@ -4,25 +4,101 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-#include "cactus_def.h"
+#include <cactus_def.h>
#include "cactus_test_cmds.h"
#include "cactus_tests.h"
#include <ffa_helpers.h>
#include <sp_helpers.h>
#include <xlat_tables_defs.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
/* Memory section to be used for memory share operations */
static __aligned(PAGE_SIZE) uint8_t share_page[PAGE_SIZE];
CACTUS_CMD_HANDLER(mem_send_cmd, CACTUS_MEM_SEND_CMD)
{
- ffa_memory_management_test(
- mb, ffa_dir_msg_dest(*args), ffa_dir_msg_source(*args),
- cactus_req_mem_send_get_mem_func(*args),
- cactus_mem_send_get_handle(*args));
+ struct ffa_memory_region *m;
+ struct ffa_composite_memory_region *composite;
+ int ret;
+ unsigned int mem_attrs;
+ uint32_t *ptr;
+ ffa_vm_id_t source = ffa_dir_msg_source(*args);
+ ffa_vm_id_t vm_id = ffa_dir_msg_dest(*args);
+ uint32_t mem_func = cactus_req_mem_send_get_mem_func(*args);
+ uint64_t handle = cactus_mem_send_get_handle(*args);
+
+ expect(memory_retrieve(mb, &m, handle, source, vm_id, mem_func), true);
+
+ composite = ffa_memory_region_get_composite(m, 0);
+
+ VERBOSE("Address: %p; page_count: %x %x\n",
+ composite->constituents[0].address,
+ composite->constituents[0].page_count, PAGE_SIZE);
+
+ /* This test is only concerned with RW permissions. */
+ if (ffa_get_data_access_attr(
+ m->receivers[0].receiver_permissions.permissions) !=
+ FFA_DATA_ACCESS_RW) {
+ ERROR("Permissions not expected!\n");
+ return cactus_error_resp(vm_id, source, CACTUS_ERROR_TEST);
+ }
+
+ mem_attrs = MT_RW_DATA | MT_EXECUTE_NEVER;
+
+ if (!IS_SP_ID(source)) {
+ mem_attrs |= MT_NS;
+ }
+
+ ret = mmap_add_dynamic_region(
+ (uint64_t)composite->constituents[0].address,
+ (uint64_t)composite->constituents[0].address,
+ composite->constituents[0].page_count * PAGE_SIZE,
+ mem_attrs);
+
+ if (ret != 0) {
+ ERROR("Failed first mmap_add_dynamic_region!\n");
+ return cactus_error_resp(vm_id, source, CACTUS_ERROR_TEST);
+ }
+
+ VERBOSE("Memory has been mapped\n");
+
+ ptr = (uint32_t *) composite->constituents[0].address;
- return cactus_success_resp(ffa_dir_msg_dest(*args),
- ffa_dir_msg_source(*args), 0);
+ /* Write mem_func to retrieved memory region for validation purposes. */
+ VERBOSE("Writing: %x\n", mem_func);
+ for (unsigned int i = 0U; i < 5U; i++)
+ ptr[i] = mem_func;
+
+ /*
+ * A FFA_MEM_DONATE changes the ownership of the page, as such no
+ * relinquish is needed.
+ */
+ if (mem_func != FFA_MEM_DONATE_SMC32) {
+ ret = mmap_remove_dynamic_region(
+ (uint64_t)composite->constituents[0].address,
+ composite->constituents[0].page_count * PAGE_SIZE);
+
+ if (ret != 0) {
+ ERROR("Failed first mmap_add_dynamic_region!\n");
+ return cactus_error_resp(vm_id, source,
+ CACTUS_ERROR_TEST);
+ }
+
+ if (!memory_relinquish((struct ffa_mem_relinquish *)mb->send,
+ m->handle, vm_id)) {
+ return cactus_error_resp(vm_id, source,
+ CACTUS_ERROR_TEST);
+ }
+ }
+
+ if (ffa_func_id(ffa_rx_release()) != FFA_SUCCESS_SMC32) {
+ ERROR("Failed to release buffer!\n");
+ return cactus_error_resp(vm_id, source,
+ CACTUS_ERROR_FFA_CALL);
+ }
+
+ return cactus_success_resp(vm_id,
+ source, 0);
}
CACTUS_CMD_HANDLER(req_mem_send_cmd, CACTUS_REQ_MEM_SEND_CMD)
@@ -44,7 +120,7 @@ CACTUS_CMD_HANDLER(req_mem_send_cmd, CACTUS_REQ_MEM_SEND_CMD)
const uint32_t constituents_count = (sizeof(constituents) /
sizeof(constituents[0]));
- handle = ffa_memory_init_and_send(
+ handle = memory_init_and_send(
(struct ffa_memory_region *)mb->send, PAGE_SIZE,
vm_id, receiver, constituents,
constituents_count, mem_func);
@@ -52,7 +128,11 @@ CACTUS_CMD_HANDLER(req_mem_send_cmd, CACTUS_REQ_MEM_SEND_CMD)
/*
* If returned an invalid handle, we should break the test.
*/
- expect(handle != FFA_MEMORY_HANDLE_INVALID, true);
+ if (handle == FFA_MEMORY_HANDLE_INVALID) {
+ ERROR("Received an invalid FF-A memory Handle!\n");
+ return cactus_error_resp(vm_id, source,
+ CACTUS_ERROR_TEST);
+ }
ffa_ret = cactus_mem_send_cmd(vm_id, receiver, mem_func, handle);
diff --git a/tftf/tests/runtime_services/secure_service/ffa_helpers.c b/tftf/tests/runtime_services/secure_service/ffa_helpers.c
index f3da55f52..9567debd1 100644
--- a/tftf/tests/runtime_services/secure_service/ffa_helpers.c
+++ b/tftf/tests/runtime_services/secure_service/ffa_helpers.c
@@ -268,91 +268,6 @@ uint32_t ffa_memory_retrieve_request_init(
memory_region->receiver_count * sizeof(struct ffa_memory_access);
}
-/**
- * Helper to call memory send function whose func id is passed as a parameter.
- * Returns a valid handle in case of successful operation or
- * FFA_MEMORY_HANDLE_INVALID if something goes wrong.
- *
- * TODO: Do memory send with 'ffa_memory_region' taking multiple segments
- */
-ffa_memory_handle_t ffa_memory_send(
- struct ffa_memory_region *memory_region, uint32_t mem_func,
- uint32_t fragment_length, uint32_t total_length)
-{
- smc_ret_values ret;
- ffa_vm_id_t receiver =
- memory_region->receivers[0].receiver_permissions.receiver;
-
- if (fragment_length != total_length) {
- ERROR("For now, fragment_length and total_length need to be"
- " equal");
- return FFA_MEMORY_HANDLE_INVALID;
- }
-
- switch (mem_func) {
- case FFA_MEM_SHARE_SMC32:
- ret = ffa_mem_share(total_length, fragment_length);
- break;
- case FFA_MEM_LEND_SMC32:
- ret = ffa_mem_lend(total_length, fragment_length);
- break;
- case FFA_MEM_DONATE_SMC32:
- ret = ffa_mem_donate(total_length, fragment_length);
- break;
- default:
- ERROR("TFTF - Invalid func id %x!\n", mem_func);
- return FFA_MEMORY_HANDLE_INVALID;
- }
-
- if (ffa_func_id(ret) != FFA_SUCCESS_SMC32) {
- ERROR("Failed to send memory to %x, error: %x.\n",
- receiver, ffa_error_code(ret));
- return FFA_MEMORY_HANDLE_INVALID;
- }
-
- return ffa_mem_success_handle(ret);
-;
-}
-
-/**
- * Helper that initializes and sends a memory region. The memory region's
- * configuration is statically defined and is implementation specific. However,
- * doing it in this file for simplicity and for testing purposes.
- */
-ffa_memory_handle_t ffa_memory_init_and_send(
- struct ffa_memory_region *memory_region, size_t memory_region_max_size,
- ffa_vm_id_t sender, ffa_vm_id_t receiver,
- const struct ffa_memory_region_constituent *constituents,
- uint32_t constituents_count, uint32_t mem_func)
-{
- uint32_t remaining_constituent_count;
- uint32_t total_length;
- uint32_t fragment_length;
-
- enum ffa_data_access data_access = (mem_func == FFA_MEM_DONATE_SMC32) ?
- FFA_DATA_ACCESS_NOT_SPECIFIED :
- FFA_DATA_ACCESS_RW;
-
- remaining_constituent_count = ffa_memory_region_init(
- memory_region, memory_region_max_size, sender, receiver, constituents,
- constituents_count, 0, 0, data_access,
- FFA_INSTRUCTION_ACCESS_NOT_SPECIFIED,
- FFA_MEMORY_NORMAL_MEM, FFA_MEMORY_CACHE_WRITE_BACK,
- FFA_MEMORY_INNER_SHAREABLE, &total_length, &fragment_length
- );
-
- /*
- * For simplicity of the test, and at least for the time being,
- * the following condition needs to be true.
- */
- if (remaining_constituent_count != 0U) {
- ERROR("Remaining constituent should be 0\n");
- return FFA_MEMORY_HANDLE_INVALID;
- }
-
- return ffa_memory_send(memory_region, mem_func, fragment_length,
- total_length);
-}
/*
* FFA Version ABI helper.
diff --git a/tftf/tests/runtime_services/secure_service/spm_common.c b/tftf/tests/runtime_services/secure_service/spm_common.c
index cc3ed5df4..541ec922d 100644
--- a/tftf/tests/runtime_services/secure_service/spm_common.c
+++ b/tftf/tests/runtime_services/secure_service/spm_common.c
@@ -4,8 +4,10 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <debug.h>
#include <ffa_endpoints.h>
#include <spm_common.h>
+#include <xlat_tables_v2.h>
#define __STR(x) #x
#define STR(x) __STR(x)
@@ -146,3 +148,176 @@ unsigned int get_ffa_feature_test_target(
return sizeof(ffa_feature_test_target) /
sizeof(struct ffa_features_test);
}
+
+bool memory_retrieve(struct mailbox_buffers *mb,
+ struct ffa_memory_region **retrieved, uint64_t handle,
+ ffa_vm_id_t sender, ffa_vm_id_t receiver,
+ uint32_t mem_func)
+{
+ smc_ret_values ret;
+ uint32_t fragment_size;
+ uint32_t total_size;
+ uint32_t descriptor_size;
+
+ if (retrieved == NULL || mb == NULL) {
+ ERROR("Invalid parameters!\n");
+ return false;
+ }
+
+ /*
+ * TODO: Revise shareability attribute in function call
+ * below.
+ * https://lists.trustedfirmware.org/pipermail/hafnium/2020-June/000023.html
+ */
+ descriptor_size = ffa_memory_retrieve_request_init(
+ mb->send, handle, sender, receiver, 0, 0,
+ FFA_DATA_ACCESS_RW,
+ FFA_INSTRUCTION_ACCESS_NX,
+ FFA_MEMORY_NORMAL_MEM,
+ FFA_MEMORY_CACHE_WRITE_BACK,
+ FFA_MEMORY_OUTER_SHAREABLE);
+
+ ret = ffa_mem_retrieve_req(descriptor_size, descriptor_size);
+
+ if (ffa_func_id(ret) != FFA_MEM_RETRIEVE_RESP) {
+ ERROR("Couldn't retrieve the memory page. Error: %x\n",
+ ffa_error_code(ret));
+ return false;
+ }
+
+ /*
+ * Following total_size and fragment_size are useful to keep track
+ * of the state of transaction. When the sum of all fragment_size of all
+ * fragments is equal to total_size, the memory transaction has been
+ * completed.
+ * This is a simple test with only one segment. As such, upon
+ * successful ffa_mem_retrieve_req, total_size must be equal to
+ * fragment_size.
+ */
+ total_size = ret.ret1;
+ fragment_size = ret.ret2;
+
+ if (total_size != fragment_size) {
+ ERROR("Only expect one memory segment to be sent!\n");
+ return false;
+ }
+
+ if (fragment_size > PAGE_SIZE) {
+ ERROR("Fragment should be smaller than RX buffer!\n");
+ return false;
+ }
+
+ *retrieved = (struct ffa_memory_region *)mb->recv;
+
+ if ((*retrieved)->receiver_count > MAX_MEM_SHARE_RECIPIENTS) {
+ VERBOSE("SPMC memory sharing operations support max of %u "
+ "receivers!\n", MAX_MEM_SHARE_RECIPIENTS);
+ return false;
+ }
+
+ VERBOSE("Memory Retrieved!\n");
+
+ return true;
+}
+
+bool memory_relinquish(struct ffa_mem_relinquish *m, uint64_t handle,
+ ffa_vm_id_t id)
+{
+ smc_ret_values ret;
+
+ ffa_mem_relinquish_init(m, handle, 0, id);
+ ret = ffa_mem_relinquish();
+ if (ffa_func_id(ret) != FFA_SUCCESS_SMC32) {
+ ERROR("%s failed to relinquish memory! error: %x\n",
+ __func__, ffa_error_code(ret));
+ return false;
+ }
+
+ VERBOSE("Memory Relinquished!\n");
+ return true;
+}
+
+/**
+ * Helper to call memory send function whose func id is passed as a parameter.
+ * Returns a valid handle in case of successful operation or
+ * FFA_MEMORY_HANDLE_INVALID if something goes wrong.
+ *
+ * TODO: Do memory send with 'ffa_memory_region' taking multiple segments
+ */
+ffa_memory_handle_t memory_send(
+ struct ffa_memory_region *memory_region, uint32_t mem_func,
+ uint32_t fragment_length, uint32_t total_length)
+{
+ smc_ret_values ret;
+ ffa_vm_id_t receiver =
+ memory_region->receivers[0].receiver_permissions.receiver;
+
+ if (fragment_length != total_length) {
+ ERROR("For now, fragment_length and total_length need to be"
+ " equal");
+ return FFA_MEMORY_HANDLE_INVALID;
+ }
+
+ switch (mem_func) {
+ case FFA_MEM_SHARE_SMC32:
+ ret = ffa_mem_share(total_length, fragment_length);
+ break;
+ case FFA_MEM_LEND_SMC32:
+ ret = ffa_mem_lend(total_length, fragment_length);
+ break;
+ case FFA_MEM_DONATE_SMC32:
+ ret = ffa_mem_donate(total_length, fragment_length);
+ break;
+ default:
+ ERROR("TFTF - Invalid func id %x!\n", mem_func);
+ return FFA_MEMORY_HANDLE_INVALID;
+ }
+
+ if (ffa_func_id(ret) != FFA_SUCCESS_SMC32) {
+ ERROR("Failed to send memory to %x, error: %x.\n",
+ receiver, ffa_error_code(ret));
+ return FFA_MEMORY_HANDLE_INVALID;
+ }
+
+ return ffa_mem_success_handle(ret);
+}
+
+/**
+ * Helper that initializes and sends a memory region. The memory region's
+ * configuration is statically defined and is implementation specific. However,
+ * doing it in this file for simplicity and for testing purposes.
+ */
+ffa_memory_handle_t memory_init_and_send(
+ struct ffa_memory_region *memory_region, size_t memory_region_max_size,
+ ffa_vm_id_t sender, ffa_vm_id_t receiver,
+ const struct ffa_memory_region_constituent *constituents,
+ uint32_t constituents_count, uint32_t mem_func)
+{
+ uint32_t remaining_constituent_count;
+ uint32_t total_length;
+ uint32_t fragment_length;
+
+ enum ffa_data_access data_access = (mem_func == FFA_MEM_DONATE_SMC32) ?
+ FFA_DATA_ACCESS_NOT_SPECIFIED :
+ FFA_DATA_ACCESS_RW;
+
+ remaining_constituent_count = ffa_memory_region_init(
+ memory_region, memory_region_max_size, sender, receiver, constituents,
+ constituents_count, 0, 0, data_access,
+ FFA_INSTRUCTION_ACCESS_NOT_SPECIFIED,
+ FFA_MEMORY_NORMAL_MEM, FFA_MEMORY_CACHE_WRITE_BACK,
+ FFA_MEMORY_INNER_SHAREABLE, &total_length, &fragment_length
+ );
+
+ /*
+ * For simplicity of the test, and at least for the time being,
+ * the following condition needs to be true.
+ */
+ if (remaining_constituent_count != 0U) {
+ ERROR("Remaining constituent should be 0\n");
+ return FFA_MEMORY_HANDLE_INVALID;
+ }
+
+ return memory_send(memory_region, mem_func, fragment_length,
+ total_length);
+}
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c b/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c
index 67ffb53be..61b6edd5e 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c
@@ -63,7 +63,7 @@ static test_result_t test_memory_send_sp(uint32_t mem_func)
const uint32_t constituents_count = sizeof(constituents) /
sizeof(struct ffa_memory_region_constituent);
- handle = ffa_memory_init_and_send((struct ffa_memory_region *)mb.send,
+ handle = memory_init_and_send((struct ffa_memory_region *)mb.send,
MAILBOX_SIZE, SENDER, RECEIVER,
constituents, constituents_count,
mem_func);