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__ */