diff options
author | Andrew Walbran <qwandor@google.com> | 2020-05-18 20:05:38 +0100 |
---|---|---|
committer | Andrew Walbran <qwandor@google.com> | 2020-09-22 17:23:29 +0100 |
commit | 6feffaba0133640c4a3fb225527920ba5ac27ae4 (patch) | |
tree | b4a0316f4c91fa61a6012374283b2c1d6b3ff9c3 | |
parent | c8a0197dd5fa349f8d88e9323762b035881ed173 (diff) | |
download | hafnium-6feffaba0133640c4a3fb225527920ba5ac27ae4.tar.gz |
Test fragmented memory sharing with Trusty.
Bug: 132429380
Change-Id: Icb984f859945eacd18bb75be84bb999e7c70c118
-rw-r--r-- | test/inc/test/vmapi/ffa.h | 7 | ||||
-rw-r--r-- | test/vmapi/arch/aarch64/trusty/trusty.c | 153 | ||||
-rw-r--r-- | test/vmapi/primary_with_secondaries/memory_sharing.c | 7 |
3 files changed, 159 insertions, 8 deletions
diff --git a/test/inc/test/vmapi/ffa.h b/test/inc/test/vmapi/ffa.h index fc3c10b1f..c2add9e1f 100644 --- a/test/inc/test/vmapi/ffa.h +++ b/test/inc/test/vmapi/ffa.h @@ -10,6 +10,13 @@ #include "vmapi/hf/ffa.h" +/* + * A number of pages that is large enough that it must take two fragments to + * share. + */ +#define FRAGMENTED_SHARE_PAGE_COUNT \ + (PAGE_SIZE / sizeof(struct ffa_memory_region_constituent)) + #define EXPECT_FFA_ERROR(value, ffa_error) \ do { \ struct ffa_value v = (value); \ diff --git a/test/vmapi/arch/aarch64/trusty/trusty.c b/test/vmapi/arch/aarch64/trusty/trusty.c index a56ba86d2..d1bf3a407 100644 --- a/test/vmapi/arch/aarch64/trusty/trusty.c +++ b/test/vmapi/arch/aarch64/trusty/trusty.c @@ -16,7 +16,8 @@ #include "test/hftest.h" #include "test/vmapi/ffa.h" -alignas(PAGE_SIZE) static uint8_t pages[4 * PAGE_SIZE]; +alignas(PAGE_SIZE) static uint8_t + pages[FRAGMENTED_SHARE_PAGE_COUNT * PAGE_SIZE]; static ffa_memory_handle_t init_and_send( struct mailbox_buffers mb, @@ -78,6 +79,59 @@ TEST(trusty, memory_share) } /** + * Memory can be shared to Trusty SPD in multiple fragments. + */ +TEST(trusty, memory_share_fragmented) +{ + struct ffa_value ret; + ffa_memory_handle_t handle; + struct mailbox_buffers mb = set_up_mailbox(); + uint32_t total_length; + uint32_t fragment_length; + struct ffa_memory_region_constituent constituents[] = { + {.address = (uint64_t)pages, .page_count = 1}, + {.address = (uint64_t)pages + PAGE_SIZE, .page_count = 1}, + }; + + /* Dirty the memory before sharing it. */ + memset_s(pages, sizeof(pages), 'b', PAGE_SIZE * 2); + + EXPECT_EQ(ffa_memory_region_init( + mb.send, HF_MAILBOX_SIZE, HF_PRIMARY_VM_ID, + HF_TEE_VM_ID, constituents, ARRAY_SIZE(constituents), + 0, 0, FFA_DATA_ACCESS_RW, + FFA_INSTRUCTION_ACCESS_NOT_SPECIFIED, + FFA_MEMORY_NORMAL_MEM, FFA_MEMORY_CACHE_WRITE_BACK, + FFA_MEMORY_OUTER_SHAREABLE, &total_length, + &fragment_length), + 0); + /* Send the first fragment without the last constituent. */ + fragment_length -= sizeof(struct ffa_memory_region_constituent); + ret = ffa_mem_share(total_length, fragment_length); + EXPECT_EQ(ret.func, FFA_MEM_FRAG_RX_32); + EXPECT_EQ(ret.arg3, fragment_length); + handle = ffa_frag_handle(ret); + + /* Send second fragment. */ + EXPECT_EQ( + ffa_memory_fragment_init(mb.send, HF_MAILBOX_SIZE, + constituents + 1, 1, &fragment_length), + 0); + ret = ffa_mem_frag_tx(handle, fragment_length); + EXPECT_EQ(ret.func, FFA_SUCCESS_32); + EXPECT_EQ(ffa_mem_success_handle(ret), handle); + dlog("Got handle %#x.\n", handle); + EXPECT_NE(handle, 0); + EXPECT_NE(handle & FFA_MEMORY_HANDLE_ALLOCATOR_MASK, + FFA_MEMORY_HANDLE_ALLOCATOR_HYPERVISOR); + + /* Make sure we can still write to it. */ + for (int i = 0; i < PAGE_SIZE * 2; ++i) { + pages[i] = i; + } +} + +/** * Multiple memory regions can be sent without blocking. */ TEST(trusty, share_twice) @@ -134,3 +188,100 @@ TEST(trusty, memory_reclaim) ret = ffa_mem_reclaim(handle, 0); EXPECT_EQ(ret.func, FFA_SUCCESS_32); } + +/** + * Memory which was shared in multiple fragments can be reclaimed and sent + * again. + */ +TEST(trusty, memory_reclaim_reshare_fragmented) +{ + struct mailbox_buffers mb = set_up_mailbox(); + uint8_t *ptr = pages; + uint32_t i; + struct ffa_memory_region_constituent + constituents[FRAGMENTED_SHARE_PAGE_COUNT]; + uint32_t remaining_constituent_count; + uint32_t total_length; + uint32_t fragment_length; + struct ffa_value ret; + ffa_memory_handle_t handle; + + /* Initialise the memory before giving it. */ + memset_s(ptr, sizeof(pages), 'b', + PAGE_SIZE * FRAGMENTED_SHARE_PAGE_COUNT); + + for (i = 0; i < ARRAY_SIZE(constituents); ++i) { + constituents[i].address = (uint64_t)pages + i * PAGE_SIZE; + constituents[i].page_count = 1; + constituents[i].reserved = 0; + } + + remaining_constituent_count = ffa_memory_region_init( + mb.send, HF_MAILBOX_SIZE, HF_PRIMARY_VM_ID, HF_TEE_VM_ID, + constituents, ARRAY_SIZE(constituents), 0, 0, + FFA_DATA_ACCESS_RW, FFA_INSTRUCTION_ACCESS_NOT_SPECIFIED, + FFA_MEMORY_NORMAL_MEM, FFA_MEMORY_CACHE_WRITE_BACK, + FFA_MEMORY_OUTER_SHAREABLE, &total_length, &fragment_length); + EXPECT_GT(remaining_constituent_count, 0); + EXPECT_GT(total_length, fragment_length); + /* Send the first fragment. */ + ret = ffa_mem_share(total_length, fragment_length); + EXPECT_EQ(ret.func, FFA_MEM_FRAG_RX_32); + EXPECT_EQ(ret.arg3, fragment_length); + handle = ffa_frag_handle(ret); + dlog("Got handle %#x.\n", handle); + EXPECT_NE(handle, 0); + EXPECT_NE(handle & FFA_MEMORY_HANDLE_ALLOCATOR_MASK, + FFA_MEMORY_HANDLE_ALLOCATOR_HYPERVISOR); + + /* Send the second fragment. */ + EXPECT_EQ(ffa_memory_fragment_init( + mb.send, HF_MAILBOX_SIZE, + constituents + ARRAY_SIZE(constituents) - + remaining_constituent_count, + remaining_constituent_count, &fragment_length), + 0); + ret = ffa_mem_frag_tx(handle, fragment_length); + EXPECT_EQ(ret.func, FFA_SUCCESS_32); + EXPECT_EQ(ffa_mem_success_handle(ret), handle); + + /* Make sure we can still write to it. */ + for (i = 0; i < PAGE_SIZE; ++i) { + pages[i] = i; + } + + dlog("Reclaiming handle %#x.\n", handle); + ret = ffa_mem_reclaim(handle, 0); + EXPECT_EQ(ret.func, FFA_SUCCESS_32); + + /* Share it again. */ + remaining_constituent_count = ffa_memory_region_init( + mb.send, HF_MAILBOX_SIZE, HF_PRIMARY_VM_ID, HF_TEE_VM_ID, + constituents, ARRAY_SIZE(constituents), 0, 0, + FFA_DATA_ACCESS_RW, FFA_INSTRUCTION_ACCESS_NOT_SPECIFIED, + FFA_MEMORY_NORMAL_MEM, FFA_MEMORY_CACHE_WRITE_BACK, + FFA_MEMORY_OUTER_SHAREABLE, &total_length, &fragment_length); + EXPECT_GT(remaining_constituent_count, 0); + EXPECT_GT(total_length, fragment_length); + + /* Send the first fragment. */ + ret = ffa_mem_share(total_length, fragment_length); + EXPECT_EQ(ret.func, FFA_MEM_FRAG_RX_32); + EXPECT_EQ(ret.arg3, fragment_length); + handle = ffa_frag_handle(ret); + dlog("Got handle %#x.\n", handle); + EXPECT_NE(handle, 0); + EXPECT_NE(handle & FFA_MEMORY_HANDLE_ALLOCATOR_MASK, + FFA_MEMORY_HANDLE_ALLOCATOR_HYPERVISOR); + + /* Send the second fragment. */ + EXPECT_EQ(ffa_memory_fragment_init( + mb.send, HF_MAILBOX_SIZE, + constituents + ARRAY_SIZE(constituents) - + remaining_constituent_count, + remaining_constituent_count, &fragment_length), + 0); + ret = ffa_mem_frag_tx(handle, fragment_length); + EXPECT_EQ(ret.func, FFA_SUCCESS_32); + EXPECT_EQ(ffa_mem_success_handle(ret), handle); +} diff --git a/test/vmapi/primary_with_secondaries/memory_sharing.c b/test/vmapi/primary_with_secondaries/memory_sharing.c index 020de8039..7dd567f68 100644 --- a/test/vmapi/primary_with_secondaries/memory_sharing.c +++ b/test/vmapi/primary_with_secondaries/memory_sharing.c @@ -18,13 +18,6 @@ #include "test/vmapi/exception_handler.h" #include "test/vmapi/ffa.h" -/* - * A number of pages that is large enough that it must take two fragments to - * share. - */ -#define FRAGMENTED_SHARE_PAGE_COUNT \ - (PAGE_SIZE / sizeof(struct ffa_memory_region_constituent)) - alignas(PAGE_SIZE) static uint8_t pages[FRAGMENTED_SHARE_PAGE_COUNT * PAGE_SIZE]; static uint8_t retrieve_buffer[HF_MAILBOX_SIZE]; |