aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaghu Krishnamurthy <raghu.ncstate@icloud.com>2021-04-04 19:25:46 -0700
committerOlivier Deprez <olivier.deprez@arm.com>2021-04-08 16:54:00 +0200
commit2904b2c5361f06d35c324f37d2e71e3278d351a7 (patch)
treefdebaf04a0f6859e93008963950e2bf6a75cb2a9
parent4369bd9745c9f2fe12a1281ffa91e52c044bc2f3 (diff)
downloadhafnium-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.c7
-rw-r--r--test/vmapi/primary_with_secondaries/services/memory.c47
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);