test(tftf): prevent secure region access from Realm world

This change adds a TFTF test attempting an access to a memory region
marked Secure in the GPT from a Realm world.
RMM catches the GPF and return a proper code error which is used in
TFTF to assert the test result accordingly.

Signed-off-by: Nabil Kahlouche <nabil.kahlouche@arm.com>
Change-Id: I1c259e0db0910b5e4b72856c07613a8989ba9187
diff --git a/include/runtime_services/realm_payload/realm_payload_test.h b/include/runtime_services/realm_payload/realm_payload_test.h
index 8de3945..9b6e20e 100644
--- a/include/runtime_services/realm_payload/realm_payload_test.h
+++ b/include/runtime_services/realm_payload/realm_payload_test.h
@@ -26,6 +26,8 @@
 #define RMI_FNUM_VERSION_REQ		U(0x150)
 #define RMI_FNUM_GRANULE_DELEGATE	U(0x151)
 #define RMI_FNUM_GRANULE_UNDELEGATE	U(0x152)
+#define RMI_FNUM_REALM_CREATE		U(0x158)
+#define RMI_FNUM_REALM_DESTROY		U(0x159)
 
 /********************************************************************************/
 
@@ -37,6 +39,10 @@
 						RMI_FNUM_GRANULE_DELEGATE)
 #define SMC_RMM_GRANULE_UNDELEGATE	RMI_FID(SMC_64, \
 						RMI_FNUM_GRANULE_UNDELEGATE)
+#define SMC_RMM_REALM_CREATE		RMI_FID(SMC_64, \
+						RMI_FNUM_REALM_CREATE)
+#define SMC_RMM_REALM_DESTROY		RMI_FID(SMC_64, \
+						RMI_FNUM_REALM_DESTROY)
 
 #define RMI_ABI_VERSION_GET_MAJOR(_version) ((_version) >> 16)
 #define RMI_ABI_VERSION_GET_MINOR(_version) ((_version) & 0xFFFF)
@@ -49,7 +55,14 @@
 #define B_UNDELEGATED			1
 
 #define NUM_CPU_DED_SPM			PLATFORM_CORE_COUNT / 2
-
+/* 
+ * The error code 513 is the packed version of the
+ * rmm error {RMM_STATUS_ERROR_INPUT,2} 
+ * happened when Granule(params_ptr).pas != NS
+ */
+#define RMM_STATUS_ERROR_INPUT		513UL
 u_register_t realm_version(void);
 u_register_t realm_granule_delegate(uintptr_t);
 u_register_t realm_granule_undelegate(uintptr_t);
+u_register_t realm_create(uintptr_t, uintptr_t);
+u_register_t realm_destroy(uintptr_t);
\ No newline at end of file
diff --git a/tftf/tests/misc_tests/test_invalid_access.c b/tftf/tests/misc_tests/test_invalid_access.c
index 5cfc711..12cd4b5 100644
--- a/tftf/tests/misc_tests/test_invalid_access.c
+++ b/tftf/tests/misc_tests/test_invalid_access.c
@@ -215,6 +215,66 @@
 	return TEST_RESULT_SUCCESS;
 }
 
+static test_result_t memory_cannot_be_accessed_in_rl(u_register_t params)
+{
+	u_register_t retrmm;
+	static char rd[GRANULE_SIZE] __aligned(GRANULE_SIZE);
+
+	if (get_armv9_2_feat_rme_support() == 0U) {
+		return TEST_RESULT_SKIPPED;
+	}
+
+	retrmm = realm_version();
+
+	VERBOSE("RMM version is: %lu.%lu\n",
+			RMI_ABI_VERSION_GET_MAJOR(retrmm),
+			RMI_ABI_VERSION_GET_MINOR(retrmm));
+
+	/*
+	 * TODO: Remove this once SMC_RMM_REALM_CREATE is implemented in TRP
+	 * For the moment skip the test if RMM is TRP, TRP version is always null.
+	 */
+	if (retrmm == 0U) {
+		return TEST_RESULT_SKIPPED;
+	}
+
+	retrmm = realm_granule_delegate((u_register_t)&rd[0]);
+	if (retrmm != 0UL) {
+		ERROR("Delegate operation returns fail, %lx\n", retrmm);
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Create a realm using a parameter in a secure physical address space should fail. */
+	retrmm = realm_create((u_register_t)&rd[0], params);
+	if (retrmm == 0UL) {
+		ERROR("Realm create operation should fail, %lx\n", retrmm);
+		retrmm = realm_destroy((u_register_t)&rd[0]);
+		if (retrmm != 0UL) {
+			ERROR("Realm destroy operation returns fail, %lx\n", retrmm);
+			return TEST_RESULT_FAIL;
+		}
+		return TEST_RESULT_FAIL;
+	} else if (retrmm != RMM_STATUS_ERROR_INPUT) {
+		ERROR("Realm create operation should fail with code:%ld retrmm:%ld\n",
+		RMM_STATUS_ERROR_INPUT, retrmm);
+		return TEST_RESULT_FAIL;
+	}
+
+	retrmm = realm_granule_undelegate((u_register_t)&rd[0]);
+	if (retrmm != 0UL) {
+		INFO("Undelegate operation returns fail, %lx\n", retrmm);
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
+
+test_result_t s_memory_cannot_be_accessed_in_rl(void)
+{
+	u_register_t params = (u_register_t)SECURE_MEMORY_ACCESS_ADDR;
+	return memory_cannot_be_accessed_in_rl(params);
+}
+
 #else
 
 test_result_t el3_memory_cannot_be_accessed_in_ns(void)
@@ -234,4 +294,11 @@
 	tftf_testcase_printf("Test not ported to AArch32\n");
 	return TEST_RESULT_SKIPPED;
 }
+
+test_result_t s_memory_cannot_be_accessed_in_rl(void)
+{
+	tftf_testcase_printf("Test not ported to AArch32\n");
+	return TEST_RESULT_SKIPPED;
+}
+
 #endif /* __aarch64__ */
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
index e6aa10b..49bf674 100644
--- a/tftf/tests/runtime_services/realm_payload/realm_payload_test_helpers.c
+++ b/tftf/tests/runtime_services/realm_payload/realm_payload_test_helpers.c
@@ -38,3 +38,28 @@
 	ret = tftf_smc(&args);
 	return ret.ret0;
 }
+
+u_register_t realm_create(u_register_t rd_addr, u_register_t realm_params_addr)
+{
+	smc_args args = { 0 };
+	smc_ret_values ret;
+
+	args.fid = SMC_RMM_REALM_CREATE;
+	args.arg1 = rd_addr;
+	args.arg2 = realm_params_addr;
+
+	ret = tftf_smc(&args);
+	return ret.ret0;
+}
+
+u_register_t realm_destroy(u_register_t rd_addr)
+{
+	smc_args args = { 0 };
+	smc_ret_values ret;
+
+	args.fid = SMC_RMM_REALM_DESTROY;
+	args.arg1 = rd_addr;
+
+	ret = tftf_smc(&args);
+	return ret.ret0;
+}
\ No newline at end of file
diff --git a/tftf/tests/tests-invalid-access.xml b/tftf/tests/tests-invalid-access.xml
index deb429d..9b8a9ed 100644
--- a/tftf/tests/tests-invalid-access.xml
+++ b/tftf/tests/tests-invalid-access.xml
@@ -14,5 +14,7 @@
                 function="rl_memory_cannot_be_accessed_in_ns" />
       <testcase name="Access Secure memory from NS world"
                 function="s_memory_cannot_be_accessed_in_ns" />
+      <testcase name="Access Secure memory from Realm world"
+                function="s_memory_cannot_be_accessed_in_rl" />
   </testsuite>
 </testsuites>