test(tftf): prevent realm region access from nwd

This change adds a TFTF test attempting an access to a memory region
marked Realm in the GPT.
The PE is expected to trigger a GPF data abort caught by a
custom exception handler.
Exception is trapped at NS-EL2 within TFTF because HCR_EL2.GPF=0
(and SCR_EL3.GPF=0).

Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
Change-Id: I05134bb9a3e37fc5478f602844b7a6ad3b8a3293
diff --git a/tftf/tests/misc_tests/test_invalid_access.c b/tftf/tests/misc_tests/test_invalid_access.c
index d409274..2fb6542 100644
--- a/tftf/tests/misc_tests/test_invalid_access.c
+++ b/tftf/tests/misc_tests/test_invalid_access.c
@@ -4,6 +4,8 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <plat/common/platform.h>
+
 #include <arch.h>
 #include <arch_helpers.h>
 #include <arch_features.h>
@@ -12,8 +14,9 @@
 #include <sync.h>
 #endif
 #include <test_helpers.h>
+#include <lib/aarch64/arch_features.h>
+#include <runtime_services/realm_payload/realm_payload_test.h>
 #include <tftf_lib.h>
-
 #include <platform_def.h>
 
 /*
@@ -32,6 +35,8 @@
 static volatile bool sync_exception_triggered;
 static volatile bool data_abort_triggered;
 
+static __aligned(PAGE_SIZE) uint64_t share_page[PAGE_SIZE / sizeof(uint64_t)];
+
 static bool data_abort_handler(void)
 {
 	uint64_t esr_elx = IS_IN_EL2() ? read_esr_el2() : read_esr_el1();
@@ -91,10 +96,78 @@
 
 	return TEST_RESULT_SUCCESS;
 }
+
+/**
+ * @Test_Aim@ Check a realm region cannot be accessed from normal world.
+ *
+ * This test delegates a TFTF allocated buffer to Realm. It then attempts
+ * a read access to the region from normal world. This results in the PE
+ * triggering a GPF caught by a custom synchronous abort handler.
+ *
+ */
+test_result_t rl_memory_cannot_be_accessed_in_ns(void)
+{
+	test_result_t result = TEST_RESULT_FAIL;
+	u_register_t retmm;
+
+	if (get_armv9_2_feat_rme_support() == 0U) {
+		return TEST_RESULT_SKIPPED;
+	}
+
+	sync_exception_triggered = false;
+	data_abort_triggered = false;
+	register_custom_sync_exception_handler(data_abort_handler);
+
+	/* First read access to the test region must not fail. */
+	*((volatile uint64_t *)share_page);
+
+	if ((sync_exception_triggered != false) ||
+	    (data_abort_triggered != false)) {
+		goto out_unregister;
+	}
+
+	/* Delegate the shared page to Realm. */
+	retmm = realm_granule_delegate((u_register_t)&share_page);
+	if (retmm != 0UL) {
+		ERROR("Granule delegate failed!\n");
+		goto out_unregister;
+	}
+
+	/* This access shall trigger a GPF. */
+	*((volatile uint64_t *)share_page);
+
+	if ((sync_exception_triggered != true) ||
+	    (data_abort_triggered != true)) {
+		goto out_undelegate;
+	}
+
+	result = TEST_RESULT_SUCCESS;
+
+out_undelegate:
+	/* Undelegate the shared page. */
+	retmm = realm_granule_undelegate((u_register_t)&share_page);
+	if (retmm != 0UL) {
+		ERROR("Granule undelegate failed!\n");
+	}
+
+out_unregister:
+	unregister_custom_sync_exception_handler();
+
+	return result;
+}
+
 #else
+
 test_result_t access_el3_memory_from_ns(void)
 {
 	tftf_testcase_printf("Test not ported to AArch32\n");
 	return TEST_RESULT_SKIPPED;
 }
+
+test_result_t rl_memory_cannot_be_accessed_in_ns(void)
+{
+	tftf_testcase_printf("Test not ported to AArch32\n");
+	return TEST_RESULT_SKIPPED;
+}
+
 #endif /* __aarch64__ */