test(memory share): hypervisor's TX is realm on retrieve
Recreate a memory share with multiple borrowers, in which one of the
borrowers is a VM. The Hypervisor's TX buffer was moved into realm PAS.
The retrieve request is expected to fail with FFA_ERROR_ABORTED.
Reset the TX buffer's PAS back to non-secure, and redo the retrieve
operation.
This time around, the test is expected to pass.
Signed-off-by: J-Alves <joao.alves@arm.com>
Change-Id: Id60f17804df4e200533dc1cd8066e64121e04dfd
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c b/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c
index a283f6a..332d544 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c
@@ -1334,3 +1334,89 @@
return TEST_RESULT_SUCCESS;
}
+
+/**
+ * Test that a retrieve request from the hypervisor would fail if the TX buffer
+ * was in realm state. This is recreating the situation in which the Hyp doesn't
+ * track the state of the operation, and it is forwarding the retrieve request
+ * to the SPMC.
+ */
+test_result_t test_ffa_memory_retrieve_request_fail_tx_realm(void)
+{
+ struct mailbox_buffers mb;
+ struct ffa_memory_access receivers[2] = {
+ ffa_memory_access_init_permissions_from_mem_func(VM_ID(1),
+ FFA_MEM_SHARE_SMC64),
+ ffa_memory_access_init_permissions_from_mem_func(SP_ID(2),
+ FFA_MEM_SHARE_SMC64),
+ };
+ ffa_memory_handle_t handle;
+ u_register_t ret_rmm;
+ struct ffa_value ret;
+ size_t descriptor_size;
+
+ GET_TFTF_MAILBOX(mb);
+
+ if (get_armv9_2_feat_rme_support() == 0U) {
+ return TEST_RESULT_SKIPPED;
+ }
+
+ CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
+
+ handle = base_memory_send_for_nwd_retrieve(&mb, receivers, ARRAY_SIZE(receivers));
+
+ if (handle == FFA_MEMORY_HANDLE_INVALID) {
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Prepare the descriptor before delegating the TX buffer. */
+ descriptor_size = ffa_memory_retrieve_request_init(
+ mb.send, handle, SENDER, receivers, ARRAY_SIZE(receivers), 0, 0,
+ FFA_MEMORY_NORMAL_MEM, FFA_MEMORY_CACHE_WRITE_BACK,
+ FFA_MEMORY_INNER_SHAREABLE);
+
+ /* Delegate TX buffer to realm. */
+ ret_rmm = host_rmi_granule_delegate((u_register_t)mb.send);
+
+ if (ret_rmm != 0UL) {
+ ERROR("Delegate operation returns %#lx for address %p\n",
+ ret_rmm, mb.send);
+ return TEST_RESULT_FAIL;
+ }
+
+ ret = ffa_mem_retrieve_req(descriptor_size, descriptor_size);
+
+ if (!is_expected_ffa_error(ret, FFA_ERROR_ABORTED)) {
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Undelegate to reestablish the same security state for PAS. */
+ ret_rmm = host_rmi_granule_undelegate((u_register_t)mb.send);
+
+ if (ret_rmm != 0UL) {
+ ERROR("Undelegate operation returns %#lx for address %p\n",
+ ret_rmm, mb.send);
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Retry the memory retrieve request, but this time expect success. */
+ ret = ffa_mem_retrieve_req(descriptor_size, descriptor_size);
+
+ if (is_ffa_call_error(ret)) {
+ return TEST_RESULT_FAIL;
+ }
+
+ ffa_rx_release();
+
+ if (!memory_relinquish(mb.send, handle, VM_ID(1))) {
+ ERROR("%s: Failed to relinquish.\n", __func__);
+ return TEST_RESULT_FAIL;
+ }
+
+ if (is_ffa_call_error(ffa_mem_reclaim(handle, 0))) {
+ ERROR("%s: Failed to reclaim memory.\n", __func__);
+ return TEST_RESULT_FAIL;
+ }
+
+ return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/tests-memory-access.xml b/tftf/tests/tests-memory-access.xml
index 6d0c48b..f0242f3 100644
--- a/tftf/tests/tests-memory-access.xml
+++ b/tftf/tests/tests-memory-access.xml
@@ -71,6 +71,8 @@
function="test_ffa_indirect_message_vm_to_sp_tx_realm_fail" />
<testcase name="FF-A Memory Sharing, NWd TX buffer is in realm PAS"
function="test_ffa_mem_share_tx_realm_expect_fail" />
+ <testcase name="FF-A Memory Retrieve, NWd TX buffer is in realm PAS"
+ function="test_ffa_memory_retrieve_request_fail_tx_realm" />
</testsuite>
</testsuites>