diff options
author | J-Alves <joao.alves@arm.com> | 2020-10-08 17:22:45 +0100 |
---|---|---|
committer | J-Alves <joao.alves@arm.com> | 2020-10-27 19:43:15 +0000 |
commit | 63cdaa7db7e132ade67b03e31ad73ae1bbcfa434 (patch) | |
tree | 2401b0c0e4d0e5519b13fce027d4f496f241172e /spm/cactus/cactus_ffa_tests.c | |
parent | d1aae29e68abf456965458a300ea9807fa4213a1 (diff) | |
download | tf-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.c | 158 |
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"; |