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>