Adding tests for Realm payload

This testing patch has the following test scenarios for realm payload:

1. Query the RMI Version on a single CPU.
2. Multi CPU version query.
3. Test to delegate and undelegate a buffer using RMI Delegate and
Undelegate commands.

Signed-off-by: Mark Dykes <mark.dykes@arm.com>
Change-Id: I3404b903b5b4f044a91ce824a408e7cf355a7589
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index 85e8cd8..4350fbd 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -145,6 +145,11 @@
 #define ID_AA64PFR0_CSV2_SHIFT	U(56)
 #define ID_AA64PFR0_CSV2_MASK	ULL(0xf)
 #define ID_AA64PFR0_CSV2_LENGTH	U(4)
+#define ID_AA64PFR0_FEAT_RME_SHIFT		U(52)
+#define ID_AA64PFR0_FEAT_RME_MASK		ULL(0xf)
+#define ID_AA64PFR0_FEAT_RME_LENGTH		U(4)
+#define ID_AA64PFR0_FEAT_RME_NOT_SUPPORTED	U(0)
+#define ID_AA64PFR0_FEAT_RME_V1			U(1)
 
 /* ID_AA64DFR0_EL1.PMS definitions (for ARMv8.2+) */
 #define ID_AA64DFR0_PMS_SHIFT	U(32)
diff --git a/include/lib/aarch64/arch_features.h b/include/lib/aarch64/arch_features.h
index edc40f0..1002936 100644
--- a/include/lib/aarch64/arch_features.h
+++ b/include/lib/aarch64/arch_features.h
@@ -125,4 +125,15 @@
 		ID_AA64DFR0_TRACEVER_SUPPORTED;
 }
 
+static inline unsigned int get_armv9_2_feat_rme_support(void)
+{
+	/*
+	 * Return the RME version, zero if not supported.  This function can be
+	 * used as both an integer value for the RME version or compared to zero
+	 * to detect RME presence.
+	 */
+	return (unsigned int)(read_id_aa64pfr0_el1() >>
+		ID_AA64PFR0_FEAT_RME_SHIFT) & ID_AA64PFR0_FEAT_RME_MASK;
+}
+
 #endif /* ARCH_FEATURES_H */
diff --git a/include/runtime_services/realm_payload/realm_payload_test.h b/include/runtime_services/realm_payload/realm_payload_test.h
new file mode 100644
index 0000000..27918bc
--- /dev/null
+++ b/include/runtime_services/realm_payload/realm_payload_test.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <smccc.h>
+#include <tftf_lib.h>
+
+#define RMI_FNUM_MIN_VALUE	U(0x00)
+#define RMI_FNUM_MAX_VALUE	U(0x20)
+
+/* Get RMI fastcall std FID from function number */
+#define RMI_FID(smc_cc, func_num)			\
+	((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT)	|	\
+	((smc_cc) << FUNCID_CC_SHIFT)		|	\
+	(OEN_ARM_START << FUNCID_OEN_SHIFT)	|	\
+	((func_num) << FUNCID_NUM_SHIFT))
+
+/*
+ * SMC_RMM_INIT_COMPLETE is the only function in the RMI that originates from
+ * the Realm world and is handled by the RMMD. The remaining functions are
+ * always invoked by the Normal world, forwarded by RMMD and handled by the
+ * RMM
+ */
+#define RMI_FNUM_VERSION_REQ		U(0)
+
+#define RMI_FNUM_GRAN_NS_REALM		U(1)
+#define RMI_FNUM_GRAN_REALM_NS		U(2)
+
+/********************************************************************************/
+
+
+/* RMI SMC64 FIDs handled by the RMMD */
+#define RMI_RMM_REQ_VERSION		RMI_FID(SMC_64, RMI_FNUM_VERSION_REQ)
+
+#define SMC_RMM_GRANULE_DELEGATE	RMI_FID(SMC_64, RMI_FNUM_GRAN_NS_REALM)
+#define SMC_RMM_GRANULE_UNDELEGATE	RMI_FID(SMC_64, RMI_FNUM_GRAN_REALM_NS)
+
+#define RMI_ABI_VERSION_GET_MAJOR(_version) ((_version) >> 16)
+#define RMI_ABI_VERSION_GET_MINOR(_version) ((_version) & 0xFFFF)
+
+#define GRANULE_SIZE 			4096
+
+u_register_t realm_version(void);
+u_register_t realm_granule_delegate(uintptr_t);
+u_register_t realm_granule_undelegate(uintptr_t);
+test_result_t realm_multi_cpu_payload_test(void);
diff --git a/tftf/tests/runtime_services/realm_payload/realm_payload_test.c b/tftf/tests/runtime_services/realm_payload/realm_payload_test.c
new file mode 100644
index 0000000..40cdb60
--- /dev/null
+++ b/tftf/tests/runtime_services/realm_payload/realm_payload_test.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_features.h>
+#include <plat_topology.h>
+#include <power_management.h>
+#include <runtime_services/realm_payload/realm_payload_test.h>
+
+static char bufferdelegate[GRANULE_SIZE] __aligned(GRANULE_SIZE);
+
+/*
+ * Overall test for realm payload in three sections:
+ * 1. Single CPU version check: SMC call to realm payload to return
+ * version information
+ * 2. Multi CPU version check: SMC call to realm payload to return
+ * version information from all CPU's in system
+ * 3. Delegate and Undelegate Non-Secure granule via
+ * SMC call to realm payload
+ */
+
+/*
+ * Single CPU version check function
+ */
+test_result_t realm_version_single_cpu(void)
+{
+
+	u_register_t retrmm;
+
+	if (get_armv9_2_feat_rme_support() == 0U) {
+		return TEST_RESULT_SKIPPED;
+	}
+
+	retrmm = realm_version();
+
+	tftf_testcase_printf("RMM version is: %lu.%lu\n",
+			RMI_ABI_VERSION_GET_MAJOR(retrmm),
+			RMI_ABI_VERSION_GET_MINOR(retrmm));
+
+	return TEST_RESULT_SUCCESS;
+}
+
+/*
+ * Multi CPU version check function in parallel.
+ */
+test_result_t realm_version_multi_cpu(void)
+{
+
+	u_register_t lead_mpid, target_mpid;
+	int cpu_node;
+	long long ret;
+
+	if (get_armv9_2_feat_rme_support() == 0U) {
+		return TEST_RESULT_SKIPPED;
+	}
+
+	lead_mpid = read_mpidr_el1() & MPID_MASK;
+
+	for_each_cpu(cpu_node) {
+		target_mpid = tftf_get_mpidr_from_node(cpu_node) & MPID_MASK;
+
+		if (lead_mpid == target_mpid) {
+			continue;
+		}
+
+		ret = tftf_cpu_on(target_mpid,
+			(uintptr_t)realm_multi_cpu_payload_test, 0);
+
+		if (ret != PSCI_E_SUCCESS) {
+			ERROR("CPU ON failed for 0x%llx\n",
+				(unsigned long long)target_mpid);
+			return TEST_RESULT_FAIL;
+		}
+
+	}
+
+	ret = realm_multi_cpu_payload_test();
+
+	for_each_cpu(cpu_node) {
+		target_mpid = tftf_get_mpidr_from_node(cpu_node) & MPID_MASK;
+
+		if (lead_mpid == target_mpid) {
+			continue;
+		}
+
+		while (tftf_psci_affinity_info(target_mpid, MPIDR_AFFLVL0) !=
+				PSCI_STATE_OFF) {
+			continue;
+		}
+	}
+
+	return ret;
+}
+
+/*
+ * Delegate and Undelegate Non Secure Granule
+ */
+test_result_t realm_delegate_undelegate(void)
+{
+
+	u_register_t retrmm;
+
+	if (get_armv9_2_feat_rme_support() == 0U) {
+		return TEST_RESULT_SKIPPED;
+	}
+
+	retrmm = realm_granule_delegate((u_register_t)bufferdelegate);
+	if (retrmm != 0UL) {
+		tftf_testcase_printf("Delegate operation returns fail, %lx\n", retrmm);
+		return TEST_RESULT_FAIL;
+	}
+	retrmm = realm_granule_undelegate((u_register_t)bufferdelegate);
+	if (retrmm != 0UL) {
+		tftf_testcase_printf("Undelegate operation returns fail, %lx\n", retrmm);
+		return TEST_RESULT_FAIL;
+	}
+	tftf_testcase_printf("Delegate and undelegate of buffer 0x%lx succeeded\n",
+			(uintptr_t)bufferdelegate);
+
+	return TEST_RESULT_SUCCESS;
+}
+
+test_result_t realm_multi_cpu_payload_test(void)
+{
+	u_register_t retrmm = realm_version();
+
+	tftf_testcase_printf("Multi CPU RMM version on CPU %llx is: %lu.%lu\n",
+			read_mpidr_el1() & MPID_MASK, RMI_ABI_VERSION_GET_MAJOR(retrmm),
+			RMI_ABI_VERSION_GET_MINOR(retrmm));
+
+	return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/runtime_services/realm_payload/realm_payload_test_helpers.c b/tftf/tests/runtime_services/realm_payload/realm_payload_test_helpers.c
new file mode 100644
index 0000000..e6aa10b
--- /dev/null
+++ b/tftf/tests/runtime_services/realm_payload/realm_payload_test_helpers.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <runtime_services/realm_payload/realm_payload_test.h>
+
+u_register_t realm_version(void)
+{
+	smc_args args = { RMI_RMM_REQ_VERSION };
+	smc_ret_values ret;
+
+	ret = tftf_smc(&args);
+	return ret.ret0;
+}
+
+u_register_t realm_granule_delegate(u_register_t add)
+{
+	smc_args args = { 0 };
+	smc_ret_values ret;
+
+	args.fid = SMC_RMM_GRANULE_DELEGATE;
+	args.arg1 = add;
+
+	ret = tftf_smc(&args);
+	return ret.ret0;
+}
+
+u_register_t realm_granule_undelegate(u_register_t add)
+{
+	smc_args args = { 0 };
+	smc_ret_values ret;
+
+	args.fid = SMC_RMM_GRANULE_UNDELEGATE;
+	args.arg1 = add;
+
+	ret = tftf_smc(&args);
+	return ret.ret0;
+}
diff --git a/tftf/tests/tests-realm-payload.mk b/tftf/tests/tests-realm-payload.mk
new file mode 100644
index 0000000..91bf081
--- /dev/null
+++ b/tftf/tests/tests-realm-payload.mk
@@ -0,0 +1,11 @@
+#
+# Copyright (c) 2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+TESTS_SOURCES	+=							\
+	$(addprefix tftf/tests/runtime_services/realm_payload/,		\
+		realm_payload_test_helpers.c				\
+		realm_payload_test.c					\
+	)
diff --git a/tftf/tests/tests-realm-payload.xml b/tftf/tests/tests-realm-payload.xml
new file mode 100644
index 0000000..8acdc2e
--- /dev/null
+++ b/tftf/tests/tests-realm-payload.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright (c) 2021, Arm Limited. All rights reserved.
+
+  SPDX-License-Identifier: BSD-3-Clause
+-->
+
+<testsuites>
+
+  <testsuite name="Realm payload tests" description="Tests for Realm management interface">
+	  <testcase name="Realm payload boot" function="realm_version_single_cpu" />
+	  <testcase name="Realm payload multi CPU request" function="realm_version_multi_cpu" />
+	  <testcase name="Realm payload Delegate and Undelegate" function="realm_delegate_undelegate" />
+  </testsuite>
+
+</testsuites>
diff --git a/tftf/tests/tests-standard.mk b/tftf/tests/tests-standard.mk
index c6c9029..a722077 100644
--- a/tftf/tests/tests-standard.mk
+++ b/tftf/tests/tests-standard.mk
@@ -23,6 +23,7 @@
 	tests-tsp.mk				\
 	tests-uncontainable.mk			\
 	tests-debugfs.mk                        \
+	tests-realm-payload.mk			\
 )
 
 include ${TESTS_MAKEFILE}
diff --git a/tftf/tests/tests-standard.xml b/tftf/tests/tests-standard.xml
index 8c66cda..384a5f4 100644
--- a/tftf/tests/tests-standard.xml
+++ b/tftf/tests/tests-standard.xml
@@ -24,6 +24,7 @@
   <!ENTITY tests-spm SYSTEM "tests-spm.xml">
   <!ENTITY tests-pmu-leakage SYSTEM "tests-pmu-leakage.xml">
   <!ENTITY tests-debugfs SYSTEM "tests-debugfs.xml">
+  <!ENTITY tests-realm-payload SYSTEM "tests-realm-payload.xml">
 ]>
 
 <testsuites>
@@ -43,5 +44,6 @@
   &tests-spm;
   &tests-pmu-leakage;
   &tests-debugfs;
+  &tests-realm-payload;
 
 </testsuites>