diff options
author | Raghu Krishnamurthy <raghu.ncstate@icloud.com> | 2021-04-04 19:25:46 -0700 |
---|---|---|
committer | Olivier Deprez <olivier.deprez@arm.com> | 2021-04-08 16:54:00 +0200 |
commit | 2904b2c5361f06d35c324f37d2e71e3278d351a7 (patch) | |
tree | fdebaf04a0f6859e93008963950e2bf6a75cb2a9 | |
parent | 4369bd9745c9f2fe12a1281ffa91e52c044bc2f3 (diff) | |
download | hafnium-2904b2c5361f06d35c324f37d2e71e3278d351a7.tar.gz |
Bug Fix: Fix memory relend test
The relend_after_return memory test has a bug where it lends memory to
the secondary VM twice and expects the secondary VM to access it, and
then NOT fault. However, the secondary VM runs the
ffa_memory_lend_relinquish function that does not retrieve the second
memory lend request, causing it to fault. The secondary VM function
registers an exception handler, which uses FFA_MSG_SEND to send the
exception count back to the primary VM, and the primary VM does not
check to ensure the exception count is 0. The test logs clearly show the
secondary VM faulting but the test still passes.
This patch fixes the issue by changing the primary VM to ensure that the
arguments for the message send from the secondary VM is 0 (since
exception handlers return the count in the rx/tx buffers with count of
4). The secondary VM code is updated to add a
ffa_memory_lend_relinquish_relend function that enters a loop where it
accepts and relinquishes memory requests.
Signed-off-by: Raghu Krishnamurthy <raghu.ncstate@icloud.com>
Change-Id: I007e12cea8ca70f6094ccce3a54db42fa988a6a8
-rw-r--r-- | test/vmapi/primary_with_secondaries/memory_sharing.c | 7 | ||||
-rw-r--r-- | test/vmapi/primary_with_secondaries/services/memory.c | 47 |
2 files changed, 53 insertions, 1 deletions
diff --git a/test/vmapi/primary_with_secondaries/memory_sharing.c b/test/vmapi/primary_with_secondaries/memory_sharing.c index 393dfc3f2..77a90aa2d 100644 --- a/test/vmapi/primary_with_secondaries/memory_sharing.c +++ b/test/vmapi/primary_with_secondaries/memory_sharing.c @@ -579,7 +579,8 @@ TEST(memory_sharing, relend_after_return) {.address = (uint64_t)pages, .page_count = 1}, }; - SERVICE_SELECT(SERVICE_VM1, "ffa_memory_lend_relinquish", mb.send); + SERVICE_SELECT(SERVICE_VM1, "ffa_memory_lend_relinquish_relend", + mb.send); /* Lend the memory initially. */ handle = send_memory_and_retrieve_request( @@ -591,6 +592,8 @@ TEST(memory_sharing, relend_after_return) /* Let the memory be returned. */ run_res = ffa_run(SERVICE_VM1, 0); EXPECT_EQ(run_res.func, FFA_MSG_SEND_32); + EXPECT_EQ(run_res.arg2, 0); + EXPECT_EQ(run_res.arg3, 0); EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32); EXPECT_EQ(ffa_mem_reclaim(handle, 0).func, FFA_SUCCESS_32); @@ -604,6 +607,8 @@ TEST(memory_sharing, relend_after_return) /* Observe the service doesn't fault when accessing the memory. */ run_res = ffa_run(SERVICE_VM1, 0); EXPECT_EQ(run_res.func, FFA_MSG_SEND_32); + EXPECT_EQ(run_res.arg2, 0); + EXPECT_EQ(run_res.arg3, 0); EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32); EXPECT_EQ(ffa_mem_reclaim(handle, 0).func, FFA_SUCCESS_32); } diff --git a/test/vmapi/primary_with_secondaries/services/memory.c b/test/vmapi/primary_with_secondaries/services/memory.c index 2a7ede99e..d25bd7dad 100644 --- a/test/vmapi/primary_with_secondaries/services/memory.c +++ b/test/vmapi/primary_with_secondaries/services/memory.c @@ -359,6 +359,53 @@ TEST_SERVICE(ffa_donate_invalid_source) ffa_yield(); } +TEST_SERVICE(ffa_memory_lend_relinquish_relend) +{ + exception_setup(NULL, exception_handler_yield_data_abort); + + /* Loop, giving memory back to the sender. */ + for (;;) { + size_t i; + ffa_memory_handle_t handle; + + void *recv_buf = SERVICE_RECV_BUFFER(); + void *send_buf = SERVICE_SEND_BUFFER(); + + struct ffa_value ret = ffa_msg_wait(); + struct ffa_memory_region *memory_region = + (struct ffa_memory_region *)retrieve_buffer; + ffa_vm_id_t sender = retrieve_memory_from_message( + recv_buf, send_buf, ret, &handle, memory_region, + sizeof(retrieve_buffer)); + struct ffa_composite_memory_region *composite = + ffa_memory_region_get_composite(memory_region, 0); + struct ffa_memory_region_constituent *constituents; + + /* ASSERT_TRUE isn't enough for clang-analyze. */ + CHECK(composite != NULL); + constituents = composite->constituents; + + /* + * Check that we can read and write every page that was shared. + */ + for (i = 0; i < composite->constituent_count; ++i) { + uint8_t *ptr = (uint8_t *)constituents[i].address; + uint32_t count = constituents[i].page_count; + size_t j; + + for (j = 0; j < PAGE_SIZE * count; ++j) { + ptr[j]++; + } + } + + /* Give the memory back and notify the sender. */ + ffa_mem_relinquish_init(send_buf, handle, 0, hf_vm_get_id()); + EXPECT_EQ(ffa_mem_relinquish().func, FFA_SUCCESS_32); + EXPECT_EQ(ffa_msg_send(hf_vm_get_id(), sender, 0, 0).func, + FFA_SUCCESS_32); + } +} + TEST_SERVICE(ffa_memory_lend_relinquish) { exception_setup(NULL, exception_handler_yield_data_abort); |