test(memory share): relinquish fails if TX is in realm
Test that if there is a GPF when the SPMC copies the relinquish
descriptor from Hypervisor's TX buffer, the handling fails
smoothly with error FFA_ERROR_ABORTED.
Signed-off-by: J-Alves <joao.alves@arm.com>
Change-Id: I45b41a6bdd0efa1f0b01645c944d482ecf993a73
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 04c8fde..9a526ce 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
@@ -1442,3 +1442,86 @@
{
return base_ffa_memory_retrieve_request_fail_buffer_realm(true);
}
+
+/**
+ * Test that a memory relinquish call fails smoothly if the TX buffer of the
+ * Hypervisor is on realm PAS.
+ */
+test_result_t test_ffa_memory_relinquish_fail_tx_realm(void)
+{
+ struct mailbox_buffers mb;
+ struct ffa_memory_region *m;
+ const ffa_id_t vm_id = VM_ID(1);
+ struct ffa_memory_access receivers[2] = {
+ ffa_memory_access_init_permissions_from_mem_func(vm_id,
+ FFA_MEM_SHARE_SMC64),
+ ffa_memory_access_init_permissions_from_mem_func(SP_ID(2),
+ FFA_MEM_SHARE_SMC64),
+ };
+ struct ffa_value ret;
+ ffa_memory_handle_t handle;
+ u_register_t ret_rmm;
+
+ 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;
+ }
+
+ if (!memory_retrieve(&mb, &m, handle, 0, receivers, ARRAY_SIZE(receivers), 0)) {
+ ERROR("Failed to retrieve the memory.\n");
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Prepare relinquish descriptor before calling ffa_mem_relinquish. */
+ ffa_mem_relinquish_init(mb.send, handle, 0, vm_id);
+
+ /*
+ * Delegate page to a realm. This should make memory sharing operation
+ * fail.
+ */
+ ret_rmm = host_rmi_granule_delegate((u_register_t)mb.send);
+ if (ret_rmm != 0UL) {
+ ERROR("Delegate operation returns 0x%lx for address %llx\n",
+ ret_rmm, (uint64_t)mb.send);
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Access to Realm region from SPMC should return FFA_ERROR_ABORTED. */
+ ret = ffa_mem_relinquish();
+ 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 0x%lx for address %llx\n",
+ ret_rmm, (uint64_t)mb.send);
+ return TEST_RESULT_FAIL;
+ }
+
+ /* After undelegate the relinquish is expected to succeed. */
+ ret = ffa_mem_relinquish();
+
+ if (is_ffa_call_error(ret)) {
+ ERROR("Expected relinquish to succeed\n");
+ return TEST_RESULT_FAIL;
+ }
+
+ ret = ffa_mem_reclaim(handle, 0);
+ if (is_ffa_call_error(ret)) {
+ ERROR("Memory reclaim failed!\n");
+ 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 d671b51..a0e9f42 100644
--- a/tftf/tests/tests-memory-access.xml
+++ b/tftf/tests/tests-memory-access.xml
@@ -71,10 +71,12 @@
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" />
<testcase name="FF-A Memory Retrieve, NWd RX buffer is in realm PAS"
function="test_ffa_memory_retrieve_request_fail_rx_realm" />
+ <testcase name="FF-A Memory Retrieve, NWd TX buffer is in realm PAS"
+ function="test_ffa_memory_retrieve_request_fail_tx_realm" />
+ <testcase name="FF-A Memory Relinquish, NWd TX buffer is in realm PAS"
+ function="test_ffa_memory_relinquish_fail_tx_realm" />
</testsuite>
</testsuites>