aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Walbran <qwandor@google.com>2020-05-18 20:05:38 +0100
committerAndrew Walbran <qwandor@google.com>2020-09-22 17:23:29 +0100
commit6feffaba0133640c4a3fb225527920ba5ac27ae4 (patch)
treeb4a0316f4c91fa61a6012374283b2c1d6b3ff9c3
parentc8a0197dd5fa349f8d88e9323762b035881ed173 (diff)
downloadhafnium-6feffaba0133640c4a3fb225527920ba5ac27ae4.tar.gz
Test fragmented memory sharing with Trusty.
Bug: 132429380 Change-Id: Icb984f859945eacd18bb75be84bb999e7c70c118
-rw-r--r--test/inc/test/vmapi/ffa.h7
-rw-r--r--test/vmapi/arch/aarch64/trusty/trusty.c153
-rw-r--r--test/vmapi/primary_with_secondaries/memory_sharing.c7
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];