aboutsummaryrefslogtreecommitdiff
path: root/spm/cactus/cactus_ffa_tests.c
diff options
context:
space:
mode:
authorJ-Alves <joao.alves@arm.com>2020-10-08 17:22:45 +0100
committerJ-Alves <joao.alves@arm.com>2020-10-27 19:43:15 +0000
commit63cdaa7db7e132ade67b03e31ad73ae1bbcfa434 (patch)
tree2401b0c0e4d0e5519b13fce027d4f496f241172e /spm/cactus/cactus_ffa_tests.c
parentd1aae29e68abf456965458a300ea9807fa4213a1 (diff)
downloadtf-a-tests-63cdaa7db7e132ade67b03e31ad73ae1bbcfa434.tar.gz
cactus: adding memory sharing tests
Added tests to FF-A memory sharing interface. To enable them: - The message loop was refactored to support multiple requests/commands coming through direct messaging, leveraging command wrappers from the previous commit. - Enabled adding dynamic memory regions to translation table, according to xlat_tables_v2 library documentation [1]; - Mapped translation tables into cactus memory mapping so that they can be updated after a memory retrieve. [1] https://trustedfirmware-a.readthedocs.io/en/latest/components/xlat-tables-lib-v2-design.html?highlight=xlat Signed-off-by: J-Alves <joao.alves@arm.com> Change-Id: I73c9ba66dd89c53c50eca6ba6aca2e0ad115cb35
Diffstat (limited to 'spm/cactus/cactus_ffa_tests.c')
-rw-r--r--spm/cactus/cactus_ffa_tests.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/spm/cactus/cactus_ffa_tests.c b/spm/cactus/cactus_ffa_tests.c
index 28555afd4..1b12fb7cf 100644
--- a/spm/cactus/cactus_ffa_tests.c
+++ b/spm/cactus/cactus_ffa_tests.c
@@ -11,6 +11,9 @@
#include <ffa_helpers.h>
#include <sp_helpers.h>
+#include <lib/libc/string.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
/* FFA version test helpers */
#define FFA_MAJOR 1U
#define FFA_MINOR 0U
@@ -189,6 +192,161 @@ 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 (ret.ret0 != FFA_MEM_RETRIEVE_RESP) {
+ ERROR("Couldn't retrieve the memory page!\n");
+ 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;
+ }
+
+ memcpy((void *)retrieved, mb->recv, fragment_size);
+
+ if (ffa_rx_release().ret0 != FFA_SUCCESS_SMC32) {
+ ERROR("Failed to release Rx buffer!\n");
+ return false;
+ }
+
+ if (retrieved->receiver_count != 1) {
+ VERBOSE("This memory has been shared with multiple"
+ " receivers!\n");
+ }
+
+ NOTICE("Memory Retrieved!\n");
+
+ return true;
+}
+
+bool ffa_memory_relinquish_test(struct ffa_mem_relinquish *m,
+ uint64_t handle,
+ ffa_vm_id_t id)
+{
+ ffa_mem_relinquish_init(m, handle, 0, id);
+
+ if (ffa_mem_relinquish().ret0 != FFA_SUCCESS_SMC32) {
+ ERROR("%s failed to relinquish memory!\n", __func__);
+ return false;
+ }
+
+ NOTICE("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);
+
+ NOTICE("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_NS | MT_EXECUTE_NEVER;
+
+ 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);
+ }
+
+ announce_test_section_end(test_ffa);
+}
+
void ffa_tests(struct mailbox_buffers *mb)
{
const char *test_ffa = "FFA Interfaces";