Merge "TFTF: Use MTE instructions in 'test_mte_instructions' test"
diff --git a/include/common/test_helpers.h b/include/common/test_helpers.h
index f9d41dd..4be9aba 100644
--- a/include/common/test_helpers.h
+++ b/include/common/test_helpers.h
@@ -4,8 +4,8 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef __TEST_HELPERS_H__
-#define __TEST_HELPERS_H__
+#ifndef TEST_HELPERS_H__
+#define TEST_HELPERS_H__
 
 #include <uuid.h>
 #include <arch_features.h>
@@ -202,9 +202,8 @@
 		}								\
 	} while (0)
 
-#define SKIP_TEST_IF_FFA_ENDPOINT_NOT_DEPLOYED(mb, uuid)			\
+#define SKIP_TEST_IF_FFA_ENDPOINT_NOT_DEPLOYED(mb, ffa_uuid)			\
 	do {									\
-		const uint32_t ffa_uuid[4] = uuid;				\
 		smc_ret_values smc_ret = ffa_partition_info_get(ffa_uuid);	\
 		ffa_rx_release();						\
 		if (smc_ret.ret0 == FFA_ERROR && 				\
@@ -217,6 +216,28 @@
 		}								\
 	} while (0)
 
+#define GET_TFTF_MAILBOX(mb)							\
+	do {									\
+		if (!get_tftf_mailbox(&mb)) {					\
+			ERROR("Mailbox not configured!\nThis test relies on"	\
+			" test suite \"FF-A RXTX Mapping\" to map/configure"	\
+			" RXTX buffers\n");					\
+			return TEST_RESULT_FAIL;				\
+		}								\
+	} while (false);
+
+#define CHECK_HAFNIUM_SPMC_TESTING_SETUP(ffa_major, ffa_minor, expected_uuids)	\
+	do {									\
+		const size_t expected_uuids_size =				\
+			 sizeof(expected_uuids) / sizeof(struct ffa_uuid);	\
+		test_result_t ret = check_hafnium_spmc_testing_set_up(		\
+			ffa_major, ffa_minor, expected_uuids, 			\
+			expected_uuids_size);					\
+		if (ret != TEST_RESULT_SUCCESS) {				\
+			return ret;						\
+		}								\
+	} while (false);
+
 /* Helper macro to verify if system suspend API is supported */
 #define is_psci_sys_susp_supported()	\
 		(tftf_get_psci_feature_info(SMC_PSCI_SYSTEM_SUSPEND)		\
@@ -267,4 +288,23 @@
 test_result_t map_test_unmap(const map_args_unmap_t *args,
 			     test_function_arg_t test);
 
+/*
+ * Helper function to set TFTF global mailbox for SPM related tests.
+ * This function should be invoked by the first TFTF test that requires
+ * RX and/or TX buffers.
+ */
+void set_tftf_mailbox(const struct mailbox_buffers *mb);
+
+/*
+ * Helper function to get TFTF global mailbox for SPM related tests.
+ * This function should be called by all tests that require access to RX or TX
+ * buffers, after the function 'set_tftf_mailbox' has been used by the first
+ * test to rely on RX and TX buffers.
+ */
+bool get_tftf_mailbox(struct mailbox_buffers *mb);
+
+test_result_t check_hafnium_spmc_testing_set_up(uint32_t ffa_version_major,
+	uint32_t ffa_version_minor, const struct ffa_uuid *ffa_uuids,
+	size_t ffa_uuids_size);
+
 #endif /* __TEST_HELPERS_H__ */
diff --git a/include/runtime_services/ffa_helpers.h b/include/runtime_services/ffa_helpers.h
index c68a014..e96787e 100644
--- a/include/runtime_services/ffa_helpers.h
+++ b/include/runtime_services/ffa_helpers.h
@@ -28,15 +28,40 @@
 /** Flags to indicate properties of receivers during memory region retrieval. */
 typedef uint8_t ffa_memory_receiver_flags_t;
 
+struct ffa_uuid {
+	const uint32_t uuid[4];
+};
+
 #ifndef __ASSEMBLY__
 
 #include <stdint.h>
 
 struct mailbox_buffers {
-	const void *recv;
+	void *recv;
 	void *send;
 };
 
+#define CONFIGURE_MAILBOX(mb_name, buffers_size) 				\
+	do {									\
+	/* Declare RX/TX buffers at virtual FF-A instance */			\
+	static struct {								\
+			uint8_t rx[buffers_size];				\
+			uint8_t tx[buffers_size];				\
+	} __aligned(PAGE_SIZE) mb_buffers;					\
+	mb_name.recv = (void *)mb_buffers.rx;					\
+	mb_name.send = (void *)mb_buffers.tx;					\
+	} while (false)
+
+#define CONFIGURE_AND_MAP_MAILBOX(mb_name, buffers_size, smc_ret)		\
+	do {									\
+	CONFIGURE_MAILBOX(mb_name, buffers_size);				\
+	smc_ret = ffa_rxtx_map(							\
+				(uintptr_t)mb_name.send,			\
+				(uintptr_t)mb_name.recv, 			\
+				buffers_size / PAGE_SIZE			\
+			);							\
+	} while (false)
+
 struct ffa_partition_info {
 	/** The ID of the VM the information is about */
 	ffa_vm_id_t id;
diff --git a/spm/cactus/cactus_main.c b/spm/cactus/cactus_main.c
index 7c70d67..58b7dad 100644
--- a/spm/cactus/cactus_main.c
+++ b/spm/cactus/cactus_main.c
@@ -218,6 +218,7 @@
 		NOTICE("Booting Primary Cactus Secure Partition\n%s\n%s\n",
 			build_message, version_string);
 	} else {
+		smc_ret_values ret;
 		set_putc_impl(HVC_CALL_AS_STDOUT);
 
 		NOTICE("Booting Secondary Cactus Secure Partition (ID: %u)\n%s\n%s\n",
@@ -225,26 +226,13 @@
 
 		if (ffa_id == (SPM_VM_ID_FIRST + 2)) {
 			NOTICE("Mapping RXTX Region\n");
-
-			/* Declare RX/TX buffers at virtual FF-A instance */
-			static struct {
-					uint8_t rx[PAGE_SIZE];
-					uint8_t tx[PAGE_SIZE];
-			} __aligned(PAGE_SIZE) ffa_buffers;
-
-			/* Map RX/TX buffers */
-			smc_ret_values ret = ffa_rxtx_map((uintptr_t) &ffa_buffers.tx,
-				(uintptr_t) &ffa_buffers.rx,
-				sizeof(ffa_buffers.rx) / PAGE_SIZE);
-
+			CONFIGURE_AND_MAP_MAILBOX(mb, PAGE_SIZE, ret);
 			if (ret.ret0 != FFA_SUCCESS_SMC32) {
-				ERROR("ffa_rxtx_map error (%lu)\n", ret.ret2);
+				ERROR(
+				    "Failed to map RXTX buffers. Error: %lx\n",
+				    ret.ret2);
 				panic();
 			}
-
-			/* Update mailbox with RX/TX buffer */
-			mb.send = (void *) &ffa_buffers.tx;
-			mb.recv = (void *) &ffa_buffers.rx;
 		}
 	}
 
diff --git a/spm/cactus/cactus_test_cmds.h b/spm/cactus/cactus_test_cmds.h
index 6329b6d..1fc4bba 100644
--- a/spm/cactus/cactus_test_cmds.h
+++ b/spm/cactus/cactus_test_cmds.h
@@ -13,8 +13,8 @@
 /**
  * Success and error return to be sent over a msg response.
  */
-#define CACTUS_SUCCESS	 0
-#define CACTUS_ERROR	-1
+#define CACTUS_SUCCESS	 U(0)
+#define CACTUS_ERROR	 U(-1)
 
 /**
  * Get command from struct smc_ret_values.
diff --git a/tftf/tests/common/test_helpers.c b/tftf/tests/common/test_helpers.c
index 8fdfded..9861070 100644
--- a/tftf/tests/common/test_helpers.c
+++ b/tftf/tests/common/test_helpers.c
@@ -1,16 +1,19 @@
 /*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <arch_helpers.h>
+#include <ffa_helpers.h>
 #include <plat_topology.h>
 #include <platform.h>
 #include <power_management.h>
 #include <test_helpers.h>
 #include <tftf_lib.h>
 
+static struct mailbox_buffers test_mb = {.send = NULL, .recv = NULL};
+
 int is_sys_suspend_state_ready(void)
 {
 	int aff_info;
@@ -128,3 +131,49 @@
 
 	return test_ret;
 }
+
+void set_tftf_mailbox(const struct mailbox_buffers *mb)
+{
+	if (mb != NULL) {
+		test_mb = *mb;
+	}
+}
+
+bool get_tftf_mailbox(struct mailbox_buffers *mb)
+{
+	if ((test_mb.recv != NULL) && (test_mb.send != NULL)) {
+		*mb = test_mb;
+		return true;
+	}
+	return false;
+}
+
+test_result_t check_hafnium_spmc_testing_set_up(
+	uint32_t ffa_version_major, uint32_t ffa_version_minor,
+	const struct ffa_uuid *ffa_uuids, size_t ffa_uuids_size)
+{
+	struct  mailbox_buffers mb;
+
+	if (ffa_uuids == NULL) {
+		ERROR("Invalid parameter ffa_uuids!\n");
+		return TEST_RESULT_FAIL;
+	}
+
+	SKIP_TEST_IF_FFA_VERSION_LESS_THAN(ffa_version_major,
+					   ffa_version_minor);
+
+	/**********************************************************************
+	 * If OP-TEE is SPMC skip the current test.
+	 **********************************************************************/
+	if (check_spmc_execution_level()) {
+		VERBOSE("OPTEE as SPMC at S-EL1. Skipping test!\n");
+		return TEST_RESULT_SKIPPED;
+	}
+
+	GET_TFTF_MAILBOX(mb);
+
+	for (unsigned int i = 0U; i < ffa_uuids_size; i++)
+		SKIP_TEST_IF_FFA_ENDPOINT_NOT_DEPLOYED(*mb, ffa_uuids[i].uuid);
+
+	return TEST_RESULT_SUCCESS;
+}
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 0ae8a8d..fded199 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
@@ -20,17 +20,6 @@
 /* Memory section to be sent over mem management ABIs */
 static __aligned(PAGE_SIZE) uint8_t share_page[PAGE_SIZE];
 
-static __aligned(PAGE_SIZE) uint8_t send_page[PAGE_SIZE];
-static __aligned(PAGE_SIZE) uint8_t recv_page[PAGE_SIZE];
-
-/* Within the same test the RXTX Buffers only need to be shared once */
-static bool rxtx_mapped;
-
-static struct mailbox_buffers mb = {
-					.recv = (void *)recv_page,
-					.send = (void *)send_page,
-				};
-
 static test_result_t test_memory_send_sp(uint32_t mem_func)
 {
 	smc_ret_values ret;
@@ -40,6 +29,8 @@
 	uint32_t sent_length;
 	ffa_memory_handle_t handle;
 	uint32_t *ptr;
+	struct mailbox_buffers mb;
+	const uint32_t primary_uuid[] = PRIMARY_UUID;
 
 	/**********************************************************************
 	 * Verify that FFA is there and that it has the correct version.
@@ -54,20 +45,18 @@
 		return TEST_RESULT_SKIPPED;
 	}
 
-	if (!rxtx_mapped) {
-		ret = ffa_rxtx_map((uintptr_t)mb.send, (uintptr_t)mb.recv, 1);
-
-		if (ret.ret0 != FFA_SUCCESS_SMC32) {
-			ERROR("ffa_rxtx_map failed (%lx)\n", ret.ret0);
-			return TEST_RESULT_FAIL;
-		}
-		rxtx_mapped = true;
+	if (!get_tftf_mailbox(&mb)) {
+		ERROR("Mailbox not configured!\n This test relies on"
+		      " test suite \"FF-A RXTX Mapping\" to map/configure"
+		      " RXTX buffers\n");
+		return TEST_RESULT_FAIL;
 	}
 
+
 	/**********************************************************************
 	 * Verify that cactus primary SP is deployed in the system.
 	 **********************************************************************/
-	SKIP_TEST_IF_FFA_ENDPOINT_NOT_DEPLOYED(mb, PRIMARY_UUID);
+	SKIP_TEST_IF_FFA_ENDPOINT_NOT_DEPLOYED(mb, primary_uuid);
 
 	struct ffa_memory_region_constituent constituents[] = {
 						{(void *)share_page, 1, 0}
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_rxtx_map.c b/tftf/tests/runtime_services/secure_service/test_ffa_rxtx_map.c
new file mode 100644
index 0000000..5251dc4
--- /dev/null
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_rxtx_map.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <ffa_helpers.h>
+#include <test_helpers.h>
+#include <xlat_tables_defs.h>
+
+static struct mailbox_buffers mb;
+
+static test_result_t test_ffa_rxtx_map(uint32_t expected_return)
+{
+	smc_ret_values ret;
+
+	/**********************************************************************
+	 * Verify that FFA is there and that it has the correct version.
+	 **********************************************************************/
+	SKIP_TEST_IF_FFA_VERSION_LESS_THAN(1, 0);
+
+	/**********************************************************************
+	 * If OP-TEE is SPMC skip this test.
+	 **********************************************************************/
+	if (check_spmc_execution_level()) {
+		VERBOSE("OP-TEE as SPMC at S-EL1. Skipping test!\n");
+		return TEST_RESULT_SKIPPED;
+	}
+
+	/*
+	 * Declare RXTX buffers, assign them to the mailbox and call
+	 * FFA_RXTX_MAP.
+	 */
+	CONFIGURE_AND_MAP_MAILBOX(mb, PAGE_SIZE, ret);
+	if (ret.ret0 != expected_return) {
+		ERROR("Failed to map RXTX buffers %lx!\n", ret.ret2);
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
+
+/**
+ * Test mapping RXTX buffers from NWd.
+ * This test also sets the Mailbox for other SPM related tests that need to use
+ * RXTX buffers.
+ */
+test_result_t test_ffa_rxtx_map_success(void)
+{
+	test_result_t ret = test_ffa_rxtx_map(FFA_SUCCESS_SMC32);
+
+	if (ret == TEST_RESULT_SUCCESS) {
+		INFO("Set RXTX Mailbox for remaining spm tests!\n");
+		set_tftf_mailbox(&mb);
+	}
+	return ret;
+}
+
+/**
+ * Test to verify that 2nd call to FFA_RXTX_MAP should fail.
+ */
+test_result_t test_ffa_rxtx_map_fail(void)
+{
+	INFO("This test expects error log.\n");
+	return test_ffa_rxtx_map(FFA_ERROR);
+}
diff --git a/tftf/tests/tests-spm.mk b/tftf/tests/tests-spm.mk
index ee339b5..c6b304a 100644
--- a/tftf/tests/tests-spm.mk
+++ b/tftf/tests/tests-spm.mk
@@ -11,4 +11,5 @@
 		test_ffa_version.c					\
 		test_ffa_features.c					\
 		test_ffa_memory_sharing.c				\
+		test_ffa_rxtx_map.c					\
 	)
diff --git a/tftf/tests/tests-spm.xml b/tftf/tests/tests-spm.xml
index 85001f2..981ce71 100644
--- a/tftf/tests/tests-spm.xml
+++ b/tftf/tests/tests-spm.xml
@@ -30,6 +30,14 @@
 
   </testsuite>
 
+  <testsuite name="FF-A RXTX Mapping"
+             description="Test to FF-A RXTX mapping ABI" >
+     <testcase name="FF-A RXTX Map API success"
+               function="test_ffa_rxtx_map_success" />
+     <testcase name="FF-A RXTX Map API consecutive"
+               function="test_ffa_rxtx_map_fail" />
+  </testsuite>
+
   <testsuite name="FF-A Memory Sharing"
              description="Test FF-A Memory Sharing ABIs" >
   <testcase name="Lend Memory to Secure World"