feat(rme): add dev granules tests
Add tests for RMI_GRANULE_DELEGATE and
RMI_GRANULE_UNDELEGATE commands using
device granules.
Add plat_get_dev_region() function to
retrieve platform PCIe memory region info.
Change-Id: Ie59361dd28e11db348c30b033c156de044aa0ffc
Signed-off-by: AlexeiFedorov <Alexei.Fedorov@arm.com>
diff --git a/include/common/test_helpers.h b/include/common/test_helpers.h
index 1ab35ba..6482d6d 100644
--- a/include/common/test_helpers.h
+++ b/include/common/test_helpers.h
@@ -391,7 +391,7 @@
do { \
u_register_t retrmm = 0U; \
\
- if (!get_armv9_2_feat_rme_support()) { \
+ if (get_armv9_2_feat_rme_support() == 0U) { \
tftf_testcase_printf("FEAT_RME not supported\n"); \
return TEST_RESULT_SKIPPED; \
} \
diff --git a/include/lib/pcie/pcie_doe.h b/include/lib/pcie/pcie_doe.h
index bac0dbf..777309a 100644
--- a/include/lib/pcie/pcie_doe.h
+++ b/include/lib/pcie/pcie_doe.h
@@ -111,13 +111,13 @@
#define SKIP_TEST_IF_DOE_NOT_SUPPORTED(_bdf, _doe_cap_base) \
do { \
/* Test PCIe DOE only for RME */ \
- if (!get_armv9_2_feat_rme_support()) { \
+ if (get_armv9_2_feat_rme_support() == 0U) { \
tftf_testcase_printf("FEAT_RME not supported\n"); \
return TEST_RESULT_SKIPPED; \
} \
\
pcie_init(); \
- if (pcie_find_doe_device(&(_bdf), &(_doe_cap_base)) != 0) { \
+ if (pcie_find_doe_device(&(_bdf), &(_doe_cap_base)) != 0) { \
tftf_testcase_printf("PCIe DOE not supported\n"); \
return TEST_RESULT_SKIPPED; \
} \
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index 8103335..e5032fa 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -25,6 +25,13 @@
} while (0)
/*
+ * Represents whether a device memory location is within the system coherent
+ * memory space.
+ */
+#define DEV_MEM_NON_COHERENT 0
+#define DEV_MEM_COHERENT 1
+
+/*
* The platform structure to represent the valid local power state
* properties for a particular affinity level. The platform needs to
* export the array of valid local low power states for each affinity level
@@ -213,4 +220,10 @@
*/
uintptr_t plat_get_invalid_addr(void);
+/*
+ * Retrieve platform PCIe memory region
+ */
+int plat_get_dev_region(uint64_t *dev_base, size_t *dev_size,
+ uint32_t dev_type, uint32_t dev_idx);
+
#endif /* __PLATFORM_H__ */
diff --git a/include/runtime_services/host_realm_managment/host_realm_rmi.h b/include/runtime_services/host_realm_managment/host_realm_rmi.h
index 4a87ede..571f129 100644
--- a/include/runtime_services/host_realm_managment/host_realm_rmi.h
+++ b/include/runtime_services/host_realm_managment/host_realm_rmi.h
@@ -324,16 +324,6 @@
#define RMI_RTT_SET_RIPAS SMC64_RMI_FID(U(0x19))
/*
- * FID: 0xC4000170
- */
-#define SMC_RMI_GRANULE_DEV_DELEGATE SMC64_RMI_FID(U(0x20))
-
-/*
- * FID: 0xC4000171
- */
-#define SMC_RMI_GRANULE_DEV_UNDELEGATE SMC64_RMI_FID(U(0x21))
-
-/*
* FID: 0xC4000172
*/
#define SMC_RMI_DEV_MAP SMC64_RMI_FID(U(0x22))
diff --git a/plat/arm/fvp/fvp_def.h b/plat/arm/fvp/fvp_def.h
index 3609b86..4b5bd59 100644
--- a/plat/arm/fvp/fvp_def.h
+++ b/plat/arm/fvp/fvp_def.h
@@ -55,9 +55,12 @@
#define PCIE_MEM_1_BASE 0x50000000
#define PCIE_MEM_1_SIZE SZ_256M
-/* PCIe memory region #2 256GB */
+/*
+ * PCIe memory region #2 size is 256GB, but only 3GB
+ * are currently supported by GPT library
+ */
#define PCIE_MEM_2_BASE 0x4000000000
-#define PCIE_MEM_2_SIZE (SZ_1G * 256)
+#define PCIE_MEM_2_SIZE (SZ_1G * 3U)
/*******************************************************************************
* GIC-400 & interrupt handling related constants
diff --git a/plat/arm/fvp/fvp_pcie.c b/plat/arm/fvp/fvp_pcie.c
index c43e42d..38bdf39 100644
--- a/plat/arm/fvp/fvp_pcie.c
+++ b/plat/arm/fvp/fvp_pcie.c
@@ -1,9 +1,10 @@
/*
- * Copyright (c) 2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <assert.h>
#include <pcie.h>
#include <platform.h>
@@ -25,3 +26,32 @@
{
return &fvp_pcie_cfg;
}
+
+/*
+ * Retrieve platform PCIe memory region (Base Platform RevC only)
+ */
+int plat_get_dev_region(uint64_t *base, size_t *size,
+ uint32_t type, uint32_t idx)
+{
+#ifdef __aarch64__
+ assert((base != NULL) && (size != NULL));
+
+ if (type == DEV_MEM_NON_COHERENT) {
+ switch (idx) {
+ case 0U:
+ /* PCIe memory region 1 */
+ *base = PCIE_MEM_1_BASE;
+ *size = PCIE_MEM_1_SIZE;
+ return 0;
+ case 1U:
+ /* PCIe memory region 2 */
+ *base = PCIE_MEM_2_BASE;
+ *size = PCIE_MEM_2_SIZE;
+ return 0;
+ default:
+ break;
+ }
+ }
+#endif
+ return -1;
+}
diff --git a/plat/arm/fvp/plat_setup.c b/plat/arm/fvp/plat_setup.c
index 69cb0a1..f09bf59 100644
--- a/plat/arm/fvp/plat_setup.c
+++ b/plat/arm/fvp/plat_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -36,6 +36,10 @@
MAP_REGION_FLAT(FLASH_BASE, FLASH_SIZE, MT_DEVICE | MT_RW | MT_NS),
#endif
MAP_REGION_FLAT(PCIE_CONFIG_BASE, PCIE_CONFIG_SIZE, MT_DEVICE | MT_RW | MT_NS),
+#ifdef __aarch64__
+ MAP_REGION_FLAT(PCIE_MEM_1_BASE, PCIE_MEM_1_SIZE, MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(PCIE_MEM_2_BASE, PCIE_MEM_2_SIZE, MT_DEVICE | MT_RW | MT_NS),
+#endif
MAP_REGION_FLAT(DRAM_BASE, TFTF_BASE - DRAM_BASE, MT_MEMORY | MT_RW | MT_NS),
{0}
};
diff --git a/plat/arm/fvp/platform.mk b/plat/arm/fvp/platform.mk
index ee30721..42df3f7 100644
--- a/plat/arm/fvp/platform.mk
+++ b/plat/arm/fvp/platform.mk
@@ -81,7 +81,7 @@
$(eval $(call add_define,TFTF_DEFINES,FVP_MAX_PE_PER_CPU))
# Default PA size for FVP platform
-PA_SIZE := 34
+PA_SIZE := 39
$(eval $(call add_define,CACTUS_DEFINES,PA_SIZE))
$(eval $(call add_define,IVY_DEFINES,PA_SIZE))
diff --git a/plat/common/plat_common.c b/plat/common/plat_common.c
index da58579..c06ad13 100644
--- a/plat/common/plat_common.c
+++ b/plat/common/plat_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -26,6 +26,7 @@
#pragma weak plat_get_prot_regions
#pragma weak plat_pcie_get_info_table
#pragma weak plat_get_invalid_addr
+#pragma weak plat_get_dev_region
#if IMAGE_TFTF
@@ -160,3 +161,9 @@
{
return (uintptr_t)0x0;
}
+
+int plat_get_dev_region(uint64_t *dev_base, size_t *dev_size,
+ uint32_t dev_type, uint32_t dev_idx)
+{
+ return -1;
+}
diff --git a/tftf/tests/runtime_services/host_realm_managment/rmi_dev_delegate_tests.c b/tftf/tests/runtime_services/host_realm_managment/rmi_dev_delegate_tests.c
new file mode 100644
index 0000000..b4f7c51
--- /dev/null
+++ b/tftf/tests/runtime_services/host_realm_managment/rmi_dev_delegate_tests.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2024-2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdlib.h>
+
+#include <arch_features.h>
+#include <common_def.h>
+#include <host_realm_helper.h>
+#include <host_realm_mem_layout.h>
+#include <host_shared_data.h>
+#include <pcie_doe.h>
+#include <plat_topology.h>
+#include <platform.h>
+#include <power_management.h>
+#include "rmi_spm_tests.h"
+#include <test_helpers.h>
+
+static test_result_t host_multi_cpu_payload_dev_del_undel(void);
+
+/* Test 2MB of PCIe memory region 2 */
+#define PCIE_MEM_2_TEST_SIZE SZ_2M
+
+/* Number of dev granules to test */
+#define NUM_DEV_GRANULES ((PCIE_MEM_2_TEST_SIZE / GRANULE_SIZE) / \
+ PLATFORM_CORE_COUNT)
+
+/* Buffer to delegate and undelegate */
+const char *bufferdelegate;
+static char bufferstate[NUM_DEV_GRANULES * PLATFORM_CORE_COUNT];
+
+/*
+ * Overall test for Host in three sections:
+ * 1. Delegate and Undelegate Non-Secure dev granule via
+ * SMC call to realm payload.
+ * 2. Multi CPU delegation where random assignment of states
+ * (realm, non-secure) is assigned to a set of granules.
+ * Each CPU is given a number of dev granules to delegate in
+ * parallel with the other CPUs.
+ * 3. Fail testing of delegation parameters such as
+ * attempting to perform a delegation on the same dev granule
+ * twice and then testing a misaligned address.
+ */
+static test_result_t host_init_buffer_dev_del(void)
+{
+ __unused size_t dev_size;
+
+ host_rmi_init_cmp_result();
+
+ /* Retrieve platform PCIe memory region 2 */
+ if (plat_get_dev_region((uint64_t *)&bufferdelegate, &dev_size,
+ DEV_MEM_NON_COHERENT, 1U) != 0) {
+ tftf_testcase_printf("Cannot retrieve PCIe memory region 2\n");
+ return TEST_RESULT_SKIPPED;
+ }
+
+ assert(dev_size >= PCIE_MEM_2_TEST_SIZE);
+
+ for (uint32_t i = 0; i < (NUM_DEV_GRANULES * PLATFORM_CORE_COUNT) ; i++) {
+ if ((rand() & 1) == 0) {
+ u_register_t retrmm = host_rmi_granule_delegate(
+ (u_register_t)&bufferdelegate[i * GRANULE_SIZE]);
+
+ if (retrmm != RMI_SUCCESS) {
+ tftf_testcase_printf("Delegate operation returns 0x%lx\n",
+ retrmm);
+ return TEST_RESULT_FAIL;
+ }
+ bufferstate[i] = B_DELEGATED;
+ } else {
+ bufferstate[i] = B_UNDELEGATED;
+ }
+ }
+
+ return host_cmp_result();
+}
+
+/*
+ * Delegate and Undelegate Non-Secure Dev Granule
+ */
+test_result_t host_dev_mem_delegate_undelegate(void)
+{
+ __unused size_t dev_size;
+ u_register_t retrmm, rmi_feat_reg0;
+
+ CHECK_DA_SUPPORT_IN_RMI(rmi_feat_reg0);
+
+ host_rmi_init_cmp_result();
+
+ /* Retrieve platform PCIe memory region 2 */
+ if (plat_get_dev_region((uint64_t *)&bufferdelegate, &dev_size,
+ DEV_MEM_NON_COHERENT, 1U) != 0) {
+ tftf_testcase_printf("Cannot retrieve PCIe memory region 2\n");
+ return TEST_RESULT_SKIPPED;
+ }
+
+ assert(dev_size >= PCIE_MEM_2_TEST_SIZE);
+
+ retrmm = host_rmi_granule_delegate((u_register_t)bufferdelegate);
+ if (retrmm != RMI_SUCCESS) {
+ tftf_testcase_printf("Delegate operation returns 0x%lx\n",
+ retrmm);
+ return TEST_RESULT_FAIL;
+ }
+ retrmm = host_rmi_granule_undelegate((u_register_t)bufferdelegate);
+ if (retrmm != RMI_SUCCESS) {
+ tftf_testcase_printf("Undelegate operation returns 0x%lx\n",
+ retrmm);
+ return TEST_RESULT_FAIL;
+ }
+ tftf_testcase_printf("Delegate and undelegate of buffer 0x%lx succeeded\n",
+ (u_register_t)bufferdelegate);
+
+ return host_cmp_result();
+}
+
+/*
+ * Select all CPU's to randomly delegate/undelegate
+ * dev granule pages to stress the delegate mechanism
+ */
+test_result_t host_dev_mem_delundel_multi_cpu(void)
+{
+ u_register_t lead_mpid, target_mpid, retrmm, rmi_feat_reg0;
+ int32_t ret;
+ unsigned int cpu_node;
+
+ CHECK_DA_SUPPORT_IN_RMI(rmi_feat_reg0);
+
+ lead_mpid = read_mpidr_el1() & MPID_MASK;
+
+ host_rmi_init_cmp_result();
+
+ retrmm = host_init_buffer_dev_del();
+ if (retrmm != TEST_RESULT_SUCCESS) {
+ return retrmm;
+ }
+
+ for_each_cpu(cpu_node) {
+ target_mpid = (u_register_t)tftf_get_mpidr_from_node(cpu_node) & MPID_MASK;
+
+ if (lead_mpid == target_mpid) {
+ continue;
+ }
+
+ ret = tftf_cpu_on(target_mpid,
+ (uintptr_t)host_multi_cpu_payload_dev_del_undel, 0UL);
+
+ if (ret != PSCI_E_SUCCESS) {
+ ERROR("CPU ON failed for 0x%lx\n", target_mpid);
+ return TEST_RESULT_FAIL;
+ }
+
+ }
+
+ for_each_cpu(cpu_node) {
+ target_mpid = (u_register_t)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;
+ }
+ }
+
+ /*
+ * Cleanup to set all dev granules back to undelegated
+ */
+ for (unsigned int i = 0U; i < (NUM_DEV_GRANULES * PLATFORM_CORE_COUNT) ; i++) {
+ if (bufferstate[i] == B_DELEGATED) {
+ retrmm = host_rmi_granule_undelegate(
+ (u_register_t)&bufferdelegate[i * GRANULE_SIZE]);
+ if (retrmm != RMI_SUCCESS) {
+ tftf_testcase_printf("Undelegate operation returns 0x%lx\n",
+ retrmm);
+ return TEST_RESULT_FAIL;
+ }
+ bufferstate[i] = B_UNDELEGATED;
+ }
+ }
+
+ return host_cmp_result();
+}
+
+/*
+ * Multi CPU testing of delegate and undelegate of dev granules.
+ * The granules are first randomly initialized to either realm or
+ * non secure using the function init_buffer_dev_del() and then
+ * the function below assigns NUM_DEV_GRANULES to each CPU for delegation
+ * or undelgation depending upon the initial state.
+ */
+static test_result_t host_multi_cpu_payload_dev_del_undel(void)
+{
+ __unused size_t dev_size;
+ u_register_t retrmm;
+ unsigned int cpu_node;
+
+ /* Retrieve platform PCIe memory region 2 */
+ if (plat_get_dev_region((uint64_t *)&bufferdelegate, &dev_size,
+ DEV_MEM_NON_COHERENT, 1U) != 0) {
+ tftf_testcase_printf("Cannot retrieve PCIe memory region 2\n");
+ return TEST_RESULT_SKIPPED;
+ }
+
+ assert(dev_size >= PCIE_MEM_2_TEST_SIZE);
+
+ cpu_node = platform_get_core_pos(read_mpidr_el1() & MPID_MASK);
+
+ host_rmi_init_cmp_result();
+
+ for (unsigned int i = 0U; i < NUM_DEV_GRANULES; i++) {
+ if (bufferstate[((cpu_node * NUM_DEV_GRANULES) + i)] == B_UNDELEGATED) {
+ retrmm = host_rmi_granule_delegate((u_register_t)
+ &bufferdelegate[((cpu_node * NUM_DEV_GRANULES) + i) *
+ GRANULE_SIZE]);
+ if (retrmm != RMI_SUCCESS) {
+ tftf_testcase_printf("Delegate operation returns 0x%lx\n",
+ retrmm);
+ return TEST_RESULT_FAIL;
+ }
+ bufferstate[((cpu_node * NUM_DEV_GRANULES) + i)] = B_DELEGATED;
+ } else {
+ retrmm = host_rmi_granule_undelegate((u_register_t)
+ &bufferdelegate[((cpu_node * NUM_DEV_GRANULES) + i) *
+ GRANULE_SIZE]);
+ if (retrmm != RMI_SUCCESS) {
+ tftf_testcase_printf("Undelegate operation returns 0x%lx\n",
+ retrmm);
+ return TEST_RESULT_FAIL;
+ }
+ bufferstate[((cpu_node * NUM_DEV_GRANULES) + i)] = B_UNDELEGATED;
+ }
+ }
+
+ return host_cmp_result();
+}
+
+/*
+ * Fail testing of delegation process. The first is an error expected
+ * for processing the same granule twice and the second is submission of
+ * a misaligned address
+ */
+test_result_t host_fail_dev_mem_del(void)
+{
+ __unused size_t dev_size;
+ u_register_t retrmm, rmi_feat_reg0;
+
+ CHECK_DA_SUPPORT_IN_RMI(rmi_feat_reg0);
+
+ /* Retrieve platform PCIe memory region 2 */
+ if (plat_get_dev_region((uint64_t *)&bufferdelegate, &dev_size,
+ DEV_MEM_NON_COHERENT, 1U) != 0) {
+ tftf_testcase_printf("Cannot retrieve PCIe memory region 2\n");
+ return TEST_RESULT_SKIPPED;
+ }
+
+ assert(dev_size >= PCIE_MEM_2_TEST_SIZE);
+
+ host_rmi_init_cmp_result();
+
+ retrmm = host_rmi_granule_delegate((u_register_t)&bufferdelegate[0]);
+ if (retrmm != RMI_SUCCESS) {
+ tftf_testcase_printf
+ ("Delegate operation does not pass as expected for double delegation,"
+ " 0x%lx\n", retrmm);
+ return TEST_RESULT_FAIL;
+ }
+
+ retrmm = host_rmi_granule_delegate((u_register_t)&bufferdelegate[0]);
+ if (retrmm == RMI_SUCCESS) {
+ tftf_testcase_printf
+ ("Delegate operation does not fail as expected for double delegation,"
+ " 0x%lx\n", retrmm);
+ return TEST_RESULT_FAIL;
+ }
+
+ retrmm = host_rmi_granule_undelegate((u_register_t)&bufferdelegate[1]);
+ if (retrmm == RMI_SUCCESS) {
+ tftf_testcase_printf
+ ("Undelegate operation does not return fail for misaligned address,"
+ " 0x%lx\n", retrmm);
+ return TEST_RESULT_FAIL;
+ }
+
+ retrmm = host_rmi_granule_undelegate((u_register_t)&bufferdelegate[0]);
+ if (retrmm != RMI_SUCCESS) {
+ tftf_testcase_printf
+ ("Undelegate operation returns fail for cleanup, 0x%lx\n", retrmm);
+ return TEST_RESULT_FAIL;
+ }
+
+ return host_cmp_result();
+}
diff --git a/tftf/tests/tests-realm-payload.mk b/tftf/tests/tests-realm-payload.mk
index 8d9b8b1..9dff470 100644
--- a/tftf/tests/tests-realm-payload.mk
+++ b/tftf/tests/tests-realm-payload.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2021-2024, Arm Limited. All rights reserved.
+# Copyright (c) 2021-2025, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -22,13 +22,14 @@
TESTS_SOURCES += \
$(addprefix tftf/tests/runtime_services/host_realm_managment/, \
+ host_crypto_utils.c \
host_pmuv3.c \
- host_realm_rmi.c \
host_realm_helper.c \
+ host_realm_rmi.c \
+ host_rmi_pdev.c \
host_shared_data.c \
rmi_delegate_tests.c \
- host_rmi_pdev.c \
- host_crypto_utils.c \
+ rmi_dev_delegate_tests.c \
)
TESTS_SOURCES += \
diff --git a/tftf/tests/tests-realm-payload.xml b/tftf/tests/tests-realm-payload.xml
index b9e83fe..785e54f 100644
--- a/tftf/tests/tests-realm-payload.xml
+++ b/tftf/tests/tests-realm-payload.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (c) 2021-2024, Arm Limited. All rights reserved.
+ Copyright (c) 2021-2025, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
-->
@@ -68,6 +68,7 @@
function="host_realm_delundel_multi_cpu" />
<testcase name="Testing delegation fails"
function="host_realm_fail_del" />
+ <!-- Test cases related to PMUv3 support -->
<testcase name="PMUv3 cycle counter functional in Realm"
function="host_realm_pmuv3_cycle_works" />
<testcase name="PMUv3 event counter functional in Realm"
@@ -161,5 +162,12 @@
<!-- Test case for EL3-RMM IDE KM Interface -->
<testcase name="Test for Root Port Key management interface"
function="host_realm_test_root_port_key_management" />
+ <!-- Test cases related to Dev Mem Delegate and Undelegate -->
+ <testcase name="Host Dev Mem Delegate and Undelegate"
+ function="host_dev_mem_delegate_undelegate" />
+ <testcase name="Multi CPU Realm payload Dev Mem Delegate and Undelegate"
+ function="host_dev_mem_delundel_multi_cpu" />
+ <testcase name="Testing Dev Mem delegation fails"
+ function="host_fail_dev_mem_del" />
</testsuite>
</testsuites>