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>