test(indirect message): aborted send from SP to VM

Test that if the RX buffer of VM is put on the realm
PAS and an SP attempts to send a message to it, the
operation terminates smoothly.

Change-Id: Ie7fd316a6256b1c3445dfb7cb8fe1bbd09fffb6e
Signed-off-by: J-Alves <joao.alves@arm.com>
diff --git a/spm/cactus/cactus_tests/cactus_test_indirect_message.c b/spm/cactus/cactus_tests/cactus_test_indirect_message.c
index 3b8b46c..085d72f 100644
--- a/spm/cactus/cactus_tests/cactus_test_indirect_message.c
+++ b/spm/cactus/cactus_tests/cactus_test_indirect_message.c
@@ -31,7 +31,7 @@
 		ERROR("Failed to send indirect message.\n");
 		return cactus_error_resp(vm_id,
 					 source,
-					 CACTUS_ERROR_TEST);
+					 ffa_error_code(ret));
 	}
 
 	return cactus_success_resp(vm_id, source, 0);
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_indirect_messaging.c b/tftf/tests/runtime_services/secure_service/test_ffa_indirect_messaging.c
index cb1029e..35c8301 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_indirect_messaging.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_indirect_messaging.c
@@ -13,6 +13,7 @@
 #include <cactus_test_cmds.h>
 #include <ffa_endpoints.h>
 #include <ffa_svc.h>
+#include <host_realm_helper.h>
 #include <platform.h>
 #include <spm_test_helpers.h>
 #include <test_helpers.h>
@@ -21,6 +22,8 @@
 		{PRIMARY_UUID},
 	};
 
+const char expected_msg[] = "Testing FF-A message.";
+
 /*
  *
  * Used as the RX/TX buffers belonging to VM 1 in the forwarding FFA_RXTX_MAP
@@ -36,7 +39,6 @@
 	ffa_id_t header_sender;
 	const ffa_id_t vm_id = 1;
 	const ffa_id_t sender = SP_ID(1);
-	const char expected_msg[] = "Testing FF-A message.";
 	char msg[300];
 
 	/**********************************************************************
@@ -99,3 +101,134 @@
 
 	return TEST_RESULT_SUCCESS;
 }
+
+/**
+ * Test message sent from SP to VM when VM's RX is realm, the operation fails
+ * smoothly.
+ */
+test_result_t test_ffa_indirect_message_sp_to_vm_rx_realm_fail(void)
+{
+	struct ffa_value ret;
+	struct mailbox_buffers mb;
+	const ffa_id_t vm_id = 1;
+	const ffa_id_t sender = SP_ID(1);
+	ffa_id_t header_sender;
+	u_register_t ret_rmm;
+	char msg[300];
+
+	if (get_armv9_2_feat_rme_support() == 0U) {
+		return TEST_RESULT_SKIPPED;
+	}
+
+	/**********************************************************************
+	 * Check SPMC has ffa_version and expected FF-A endpoints are deployed.
+	 **********************************************************************/
+	CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
+
+	GET_TFTF_MAILBOX(mb);
+
+	/* Map RXTX buffers into SPMC translation. */
+	ret = ffa_rxtx_map_forward(mb.send, vm_id, vm1_rx_buffer,
+				   vm1_tx_buffer);
+
+	if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
+		ERROR("Failed to map buffers RX %p TX %p for VM %x\n",
+		      vm1_rx_buffer, vm1_tx_buffer, vm_id);
+		return TEST_RESULT_FAIL;
+	}
+
+	/*
+	 * Create bitmap only to then demonstrate that the message can't
+	 * be sent, as there are no pending notifications to the VM.
+	 */
+	ret = ffa_notification_bitmap_create(vm_id, PLATFORM_CORE_COUNT);
+
+	if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
+		ERROR("Failed to create bitmap for vm %x\n", vm_id);
+		return TEST_RESULT_FAIL;
+	}
+
+	/*
+	 * Delegate RX buffer of VM to realm.
+	 */
+	ret_rmm = host_rmi_granule_delegate((u_register_t)vm1_rx_buffer);
+
+	if (ret_rmm != 0UL) {
+		INFO("Delegate operation returns %#lx for address %p\n",
+		     ret_rmm, mb.send);
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Request SP to send message. */
+	ret = cactus_req_ind_msg_send_cmd(
+			HYP_ID, sender, vm_id, sender, 0);
+
+	if (!is_ffa_direct_response(ret) &&
+	    cactus_get_response(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)vm1_rx_buffer);
+
+	if (ret_rmm != 0UL) {
+		INFO("Undelegate operation returns %#lx for address %p\n",
+		     ret_rmm, mb.send);
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Expect that attempting to receive message shall fail. */
+	if (receive_indirect_message(&msg, ARRAY_SIZE(msg), (void *)vm1_rx_buffer,
+				     NULL, vm_id, 0)) {
+		return TEST_RESULT_FAIL;
+	}
+
+	/*
+	 * Redo the test so we check after undelegating the memory.
+	 * After undelegating, the SPMC should be able to complete the
+	 * operation.
+	 */
+	ret = cactus_req_ind_msg_send_cmd(
+			HYP_ID, sender, vm_id, sender, 0);
+
+	if (!is_ffa_direct_response(ret) &&
+	    cactus_get_response(ret) != CACTUS_SUCCESS) {
+		return TEST_RESULT_FAIL;
+	}
+
+	if (!receive_indirect_message(&msg, ARRAY_SIZE(msg), (void *)vm1_rx_buffer,
+				      &header_sender, vm_id, 0)) {
+		return TEST_RESULT_FAIL;
+	}
+
+	if (strncmp(msg, expected_msg, ARRAY_SIZE(expected_msg)) != 0) {
+		ERROR("Unexpected message: %s, expected: %s\n", msg, expected_msg);
+		return TEST_RESULT_FAIL;
+	}
+
+	if (header_sender != sender) {
+		ERROR("Unexpected endpoints. Sender: %x Expected: %x\n",
+		      header_sender, sender);
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Cleaning up after the test: */
+
+	/* Destroy bitmap of VM. */
+	ret = ffa_notification_bitmap_destroy(vm_id);
+
+	if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
+		ERROR("Failed to destroy bitmap for vm %x\n", vm_id);
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Unmap RXTX buffers into SPMC translation. */
+	ret = ffa_rxtx_unmap_with_id(vm_id);
+
+	if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
+		ERROR("Failed to unmap RXTX for vm %x\n", vm_id);
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/tests-memory-access.mk b/tftf/tests/tests-memory-access.mk
index 82ea094..5c71b2e 100644
--- a/tftf/tests/tests-memory-access.mk
+++ b/tftf/tests/tests-memory-access.mk
@@ -28,4 +28,5 @@
 		test_ffa_setup_and_discovery.c				\
 		spm_test_helpers.c					\
 		test_ffa_exceptions.c					\
+		test_ffa_indirect_messaging.c				\
 )
diff --git a/tftf/tests/tests-memory-access.xml b/tftf/tests/tests-memory-access.xml
index 3ed3bfa..360e07f 100644
--- a/tftf/tests/tests-memory-access.xml
+++ b/tftf/tests/tests-memory-access.xml
@@ -65,6 +65,8 @@
                 function="test_ffa_mem_lend_sp_realm_memory_separate_constituent" />
       <testcase name="FF-A partition info get after NWd RX is in realm PAS"
                 function="test_ffa_rxtx_to_realm_pas" />
+      <testcase name="FF-A Indirect message fails if VM RX is realm"
+                function="test_ffa_indirect_message_sp_to_vm_rx_realm_fail" />
   </testsuite>
 
 </testsuites>