aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/runtime_services/host_realm_managment/host_realm_rmi.h1
-rw-r--r--tftf/tests/runtime_services/host_realm_managment/host_realm_helper.c41
-rw-r--r--tftf/tests/runtime_services/host_realm_managment/host_realm_rmi.c17
-rw-r--r--tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c551
-rw-r--r--tftf/tests/tests-realm-payload.xml6
5 files changed, 590 insertions, 26 deletions
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 3159ad4f3..55233a15d 100644
--- a/include/runtime_services/host_realm_managment/host_realm_rmi.h
+++ b/include/runtime_services/host_realm_managment/host_realm_rmi.h
@@ -350,6 +350,7 @@ typedef enum {
#define PAGE_SHIFT FOUR_KB_SHIFT
#define RTT_LEVEL_SHIFT(l) XLAT_ADDR_SHIFT(l)
#define RTT_L2_BLOCK_SIZE (1UL << RTT_LEVEL_SHIFT(2U))
+#define RTT_MAP_SIZE(level) (1UL << RTT_LEVEL_SHIFT(level))
#define REC_CREATE_NR_GPRS 8U
#define REC_HVC_NR_GPRS 7U
diff --git a/tftf/tests/runtime_services/host_realm_managment/host_realm_helper.c b/tftf/tests/runtime_services/host_realm_managment/host_realm_helper.c
index 682a699da..59a0012f6 100644
--- a/tftf/tests/runtime_services/host_realm_managment/host_realm_helper.c
+++ b/tftf/tests/runtime_services/host_realm_managment/host_realm_helper.c
@@ -149,6 +149,35 @@ bool host_create_realm_payload(struct realm *realm_ptr,
return false;
}
+ /* Fail if IPA bits > implemented size */
+ if (EXTRACT(RMI_FEATURE_REGISTER_0_S2SZ, feature_flag) >
+ EXTRACT(RMI_FEATURE_REGISTER_0_S2SZ, realm_ptr->rmm_feat_reg0)) {
+ ERROR("%s() failed\n", "Invalid s2sz");
+ return false;
+ }
+
+ /*
+ * Overwrite s2sz in feature flag if host passed a value
+ * if host passes default 0 use default RMI_FEATURES instead
+ */
+ if (EXTRACT(RMI_FEATURE_REGISTER_0_S2SZ, feature_flag) != 0U) {
+ realm_ptr->rmm_feat_reg0 &= ~MASK(RMI_FEATURE_REGISTER_0_S2SZ);
+ realm_ptr->rmm_feat_reg0 |= INPLACE(RMI_FEATURE_REGISTER_0_S2SZ,
+ EXTRACT(RMI_FEATURE_REGISTER_0_S2SZ, feature_flag));
+ }
+
+ /*
+ * At the moment, TFTF does not have support for FEAT_LPA2, so if
+ * S2SZ is larger than 48 bits, truncate it to ensure we don't surpass
+ * the maximum IPA size for a realm with no LPA2 support.
+ */
+ if (EXTRACT(RMI_FEATURE_REGISTER_0_S2SZ, realm_ptr->rmm_feat_reg0) > 48U) {
+ realm_ptr->rmm_feat_reg0 &=
+ ~MASK(RMI_FEATURE_REGISTER_0_S2SZ);
+ realm_ptr->rmm_feat_reg0 |=
+ INPLACE(RMI_FEATURE_REGISTER_0_S2SZ, 48U);
+ }
+
/* Disable PMU if not required */
if ((feature_flag & RMI_FEATURE_REGISTER_0_PMU_EN) == 0UL) {
realm_ptr->rmm_feat_reg0 &= ~RMI_FEATURE_REGISTER_0_PMU_EN;
@@ -215,18 +244,6 @@ bool host_create_realm_payload(struct realm *realm_ptr,
}
}
- /*
- * At the moment, TFTF does not have support for FEAT_LPA2, so if
- * S2SZ is larger than 48 bits, truncate it to ensure we don't surpass
- * the maximum IPA size for a realm with no LPA2 support.
- */
- if (EXTRACT(RMI_FEATURE_REGISTER_0_S2SZ, realm_ptr->rmm_feat_reg0) > 48U) {
- realm_ptr->rmm_feat_reg0 &=
- ~MASK(RMI_FEATURE_REGISTER_0_S2SZ);
- realm_ptr->rmm_feat_reg0 |=
- INPLACE(RMI_FEATURE_REGISTER_0_S2SZ, 48U);
- }
-
/* Create Realm */
if (host_realm_create(realm_ptr) != REALM_SUCCESS) {
ERROR("%s() failed\n", "host_realm_create");
diff --git a/tftf/tests/runtime_services/host_realm_managment/host_realm_rmi.c b/tftf/tests/runtime_services/host_realm_managment/host_realm_rmi.c
index 057dd0032..313009c29 100644
--- a/tftf/tests/runtime_services/host_realm_managment/host_realm_rmi.c
+++ b/tftf/tests/runtime_services/host_realm_managment/host_realm_rmi.c
@@ -292,15 +292,6 @@ u_register_t host_rmi_rtt_unmap_unprotected(u_register_t rd,
return rets.ret0;
}
-u_register_t host_rtt_level_mapsize(u_register_t level)
-{
- if (level > RTT_MAX_LEVEL) {
- return PAGE_SIZE;
- }
-
- return (1UL << RTT_LEVEL_SHIFT(level));
-}
-
static inline bool ipa_is_ns(u_register_t addr, u_register_t rmm_feat_reg0)
{
return (addr >> (EXTRACT(RMI_FEATURE_REGISTER_0_S2SZ, rmm_feat_reg0) - 1UL) == 1UL);
@@ -311,7 +302,7 @@ static inline u_register_t host_realm_rtt_create(struct realm *realm,
u_register_t level,
u_register_t phys)
{
- addr = ALIGN_DOWN(addr, host_rtt_level_mapsize(level - 1U));
+ addr = ALIGN_DOWN(addr, RTT_MAP_SIZE(level - 1U));
return host_rmi_rtt_create(realm->rd, phys, addr, level);
}
@@ -547,7 +538,7 @@ static u_register_t host_realm_rtt_destroy(struct realm *realm,
u_register_t *rtt,
u_register_t *top)
{
- addr = ALIGN_DOWN(addr, host_rtt_level_mapsize(level - 1U));
+ addr = ALIGN_DOWN(addr, RTT_MAP_SIZE(level - 1U));
return host_rmi_rtt_destroy(realm->rd, addr, level, rtt, top);
}
@@ -615,7 +606,7 @@ static u_register_t host_realm_tear_down_rtt_range(struct realm *realm,
u_register_t end)
{
u_register_t rd = realm->rd;
- u_register_t map_size = host_rtt_level_mapsize(level);
+ u_register_t map_size = RTT_MAP_SIZE(level);
u_register_t map_addr, next_addr, rtt_out_addr, end_addr, top;
struct rtt_entry rtt;
u_register_t ret;
@@ -863,7 +854,7 @@ u_register_t host_realm_map_payload_image(struct realm *realm,
src_pa + i * PAGE_SIZE);
if (ret != RMI_SUCCESS) {
ERROR("%s() failed, par_base=0x%lx ret=0x%lx\n",
- "host_realm_map_protected_data",
+ "host_realm_delegate_map_protected_data",
realm->par_base, ret);
return REALM_ERROR;
}
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c b/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c
index ff698692d..1ccf3175a 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_payload_tests.c
@@ -1048,7 +1048,7 @@ test_result_t host_realm_sea_empty(void)
/* DATA_CREATE_UNKNOWN */
ret = host_realm_delegate_map_protected_data(true, &realm, base, PAGE_SIZE, 0U);
if (ret != RMI_SUCCESS) {
- ERROR("host_realm_map_protected_data failed\n");
+ ERROR("host_realm_delegate_map_protected_data failed\n");
goto destroy_realm;
}
ret = host_rmi_rtt_readentry(realm.rd, base, 3U, &rtt);
@@ -1273,3 +1273,552 @@ test_result_t host_realm_enable_dit(void)
return TEST_RESULT_SUCCESS;
}
+
+/*
+ * Helper to test whether RTT_DESTROY will change state of
+ * Unassigned ram page to Unassigned Destroyed
+ * Realm is in new state, activate realm before RTT_DESTROY if requested
+ */
+static test_result_t test_rtt_destroy_ram(struct realm *realm, bool activate)
+{
+ u_register_t ret, top, out_rtt, base;
+ struct rtt_entry rtt;
+
+ /* Find an address not mapped in L3 */
+ base = ALIGN_DOWN(PAGE_POOL_BASE, RTT_MAP_SIZE(2U));
+ while (true) {
+ ret = host_rmi_rtt_readentry(realm->rd, base, 3U, &rtt);
+ if (ret != RMI_SUCCESS || rtt.walk_level != 2U || rtt.state != RMI_UNASSIGNED
+ || (rtt.ripas != RMI_EMPTY)) {
+ base += RTT_MAP_SIZE(2U);
+ continue;
+ }
+ break;
+ }
+
+ INFO("base = 0x%lx\n", base);
+
+ /* Create L3 RTT entries */
+ ret = host_rmi_create_rtt_levels(realm, base, rtt.walk_level, 3U);
+ if (ret != RMI_SUCCESS) {
+ ERROR("host_rmi_create_rtt_levels failed ret=0x%lx\n", ret);
+ return TEST_RESULT_FAIL;
+ }
+
+ /* L3 entry should be created */
+ ret = host_rmi_rtt_readentry(realm->rd, base, 3U, &rtt);
+ if (rtt.walk_level != 3U) {
+ ERROR("host_rmi_create_rtt_levels failed ret=0x%lx\n", ret);
+ return TEST_RESULT_FAIL;
+ }
+
+ ret = host_rmi_rtt_init_ripas(realm->rd, base, base + PAGE_SIZE, &top);
+ if (ret != RMI_SUCCESS) {
+ ERROR("%s() failed, ret=0x%lx line=%u\n",
+ "host_rmi_rtt_init_ripas", ret, __LINE__);
+ return TEST_RESULT_FAIL;
+ }
+
+ /* INIT_RIPAS should move state to unassigned ram */
+ ret = host_rmi_rtt_readentry(realm->rd, base, 3U, &rtt);
+ if (ret != RMI_SUCCESS || rtt.state != RMI_UNASSIGNED ||
+ (rtt.ripas != RMI_RAM)) {
+ ERROR("wrong state after INIT_RIPAS\n");
+ return TEST_RESULT_FAIL;
+ }
+
+ if (activate) {
+ /* Activate Realm */
+ if (host_realm_activate(realm) != REALM_SUCCESS) {
+ ERROR("%s() failed\n", "host_realm_activate");
+ return TEST_RESULT_FAIL;
+ }
+ }
+
+ /* Destroy newly created rtt, for protected IPA there should be no live L3 entry */
+ ret = host_rmi_rtt_destroy(realm->rd, base, 3U, &out_rtt, &top);
+ if (ret != RMI_SUCCESS) {
+ ERROR("host_rmi_rtt_destroy failed ret=0x%lx\n", ret);
+ return TEST_RESULT_FAIL;
+ }
+ ret = host_rmi_granule_undelegate(out_rtt);
+
+ /* Walk should terminate at L2 after RTT_DESTROY */
+ ret = host_rmi_rtt_readentry(realm->rd, base, 3U, &rtt);
+ if (ret != RMI_SUCCESS || rtt.state != RMI_UNASSIGNED ||
+ rtt.ripas != RMI_DESTROYED || rtt.walk_level != 2U) {
+ ERROR("Wrong state after host_rmi_rtt_destroy\n");
+ return TEST_RESULT_FAIL;
+ }
+ return TEST_RESULT_SUCCESS;
+}
+
+/*
+ * Helper to test whether RTT_DESTROY will change state of
+ * Unassigned empty page to Unassigned Destroyed
+ * Realm can be in new or active state
+ */
+static test_result_t test_rtt_destroy_empty(struct realm *realm)
+{
+ u_register_t base, ret, top, out_rtt;
+ struct rtt_entry rtt;
+
+ /* Find an address not mapped in L3 */
+ base = ALIGN_DOWN(PAGE_POOL_BASE, RTT_MAP_SIZE(2U));
+ while (true) {
+ ret = host_rmi_rtt_readentry(realm->rd, base, 3U, &rtt);
+ if (ret != RMI_SUCCESS || rtt.walk_level != 2U || rtt.state != RMI_UNASSIGNED
+ || (rtt.ripas != RMI_EMPTY)) {
+ base += RTT_MAP_SIZE(2U);
+ continue;
+ }
+ break;
+ }
+
+ INFO("base = 0x%lx\n", base);
+
+ /* Create L3 RTT entries */
+ ret = host_rmi_create_rtt_levels(realm, base, rtt.walk_level, 3U);
+ if (ret != RMI_SUCCESS) {
+ ERROR("host_rmi_create_rtt_levels failed ret=0x%lx\n", ret);
+ return TEST_RESULT_FAIL;
+ }
+
+ /* L3 entry should be created */
+ ret = host_rmi_rtt_readentry(realm->rd, base, 3U, &rtt);
+ if (rtt.walk_level != 3U) {
+ ERROR("host_rmi_create_rtt_levels failed ret=0x%lx\n", ret);
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Destroy newly created rtt, for protected IPA there should be no live L3 entry */
+ ret = host_rmi_rtt_destroy(realm->rd, base, 3U, &out_rtt, &top);
+ if (ret != RMI_SUCCESS) {
+ ERROR("host_rmi_rtt_destroy failed ret=0x%lx\n", ret);
+ return TEST_RESULT_FAIL;
+ }
+ ret = host_rmi_granule_undelegate(out_rtt);
+ if (ret != RMI_SUCCESS) {
+ ERROR("host_rmi_granule_undelegate RTT failed ret=0x%lx\n", ret);
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Walk should terminate at L2 after RTT_DESTROY */
+ ret = host_rmi_rtt_readentry(realm->rd, base, 3U, &rtt);
+ if (ret != RMI_SUCCESS || rtt.state != RMI_UNASSIGNED ||
+ rtt.ripas != RMI_DESTROYED || rtt.walk_level != 2U) {
+ ERROR("Wrong state after host_rmi_rtt_destroy\n");
+ return TEST_RESULT_FAIL;
+ }
+ return TEST_RESULT_SUCCESS;
+}
+
+/*
+ * Test aims to test PAS transitions
+ * when realm is in new state
+ * 1. Test initial state of PAGE is Unassigned Empty
+ * 2. Test DATA_CREATE moves initial state to Assigned Ram
+ * a. Test DATA_DESTROY moves state to Unassigned Destroyed
+ * b. Test DATA_CREATE_UNKNOWN moves state to Assigned Destroyed
+ * c. Test DATA_DESTROY moves state to Unassigned Destroyed
+ * 3. Test DATA_CREATE_UNKNOWN moves initial state (new page) to Assigned Empty
+ * Test DATA_DESTROY moves state to Unassigned Empty
+ * 4. Test INIT_RIPAS moves initial state (new page) to Unassigned RAM
+ * a. Test DATA_CREATE_UNKNOWN moves state to Assigned Ram
+ * 5. Test RTT_DESTROY moves initial state (new page) to Unassigned Destroyed
+ * 6. Test RTT_DESTROY moves state (new page) unassigned ram to Unassigned Destroyed
+ * Transition
+ *
+ * +------------------+ +-------------------+ +-------------------+
+ * | Assigned Empty | | Assigned Dest | | Assigned RAM |
+ * +------------------+ +--+---^------------+ +-------^---+-----^-+
+ * ^ | | ^ ^ | ^
+ * | | | | | | |
+ * | | | | 2a | | |
+ * | | | | +--------------------------+---+ |
+ * | | | | 2b | | |4a
+ * | |3a | +---------+ | |
+ * 3 | | 2c| | | | |
+ * | | | | | | |
+ * | +-----+--------2---------+----------+--+-----------------------+ |
+ * | | | | | | |
+ * | | V V V | |
+ * +----+----+-----v---+ |--V----------V--+---| |------------------+--|
+ * --->| Unassigned Empty |---------->|Unassigned Dest |<--------| Unassigned RAM |
+ * 1 +--------------+----+ 5 +--------------------+ 6 +---------^-----------+
+ * | ^
+ * | |
+ * +---------------------------------------------------------+
+ * 4
+ */
+test_result_t host_realm_pas_validation_new(void)
+{
+ bool ret1;
+ test_result_t test_result = TEST_RESULT_FAIL;
+ u_register_t ret, data, top;
+ struct realm realm;
+ struct rtt_entry rtt;
+ u_register_t rec_flag[2U] = {RMI_RUNNABLE, RMI_RUNNABLE}, base;
+
+ SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+
+ if (!host_create_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
+ (u_register_t)PAGE_POOL_BASE,
+ (u_register_t)PAGE_POOL_MAX_SIZE,
+ 0UL, rec_flag, 2U)) {
+ return TEST_RESULT_FAIL;
+ }
+ if (!host_create_shared_mem(&realm, NS_REALM_SHARED_MEM_BASE,
+ NS_REALM_SHARED_MEM_SIZE)) {
+ goto destroy_realm;
+ }
+
+ INFO("Test 1\n");
+ base = (u_register_t)page_alloc(PAGE_SIZE);
+
+ /* Create level 3 RTT */
+ ret = host_rmi_create_rtt_levels(&realm, base, 3U, 3U);
+ if (ret != RMI_SUCCESS) {
+ ERROR("host_rmi_create_rtt_levels failed\n");
+ goto destroy_realm;
+ }
+
+ ret = host_rmi_rtt_readentry(realm.rd, base, 3U, &rtt);
+ if (ret != RMI_SUCCESS || rtt.state != RMI_UNASSIGNED ||
+ (rtt.ripas != RMI_EMPTY) || rtt.walk_level != 3U) {
+ ERROR("wrong initial state\n");
+ goto destroy_realm;
+ }
+
+ /* 2. DATA_CREATE copy TFTF_BASE, chosen for convenience, can be any adr */
+ INFO("Test 2\n");
+ ret = host_realm_delegate_map_protected_data(false, &realm, base, PAGE_SIZE, TFTF_BASE);
+ if (ret != RMI_SUCCESS) {
+ ERROR("host_realm_delegate_map_protected_data failed\n");
+ goto destroy_realm;
+ }
+ ret = host_rmi_rtt_readentry(realm.rd, base, 3U, &rtt);
+ if (ret != RMI_SUCCESS || rtt.state != RMI_ASSIGNED ||
+ (rtt.ripas != RMI_RAM)) {
+ ERROR("wrong state after DATA_CRATE_UNKNOWN\n");
+ goto undelegate_destroy;
+ }
+
+ /* 2a DATA_DESTROY */
+ ret = host_rmi_data_destroy(realm.rd, base, &data, &top);
+ if (ret != RMI_SUCCESS || data != base) {
+ ERROR("host_rmi_data_destroy failed\n");
+ goto undelegate_destroy;
+ }
+ ret = host_rmi_rtt_readentry(realm.rd, base, 3U, &rtt);
+ if (ret != RMI_SUCCESS || rtt.state != RMI_UNASSIGNED ||
+ rtt.ripas != RMI_DESTROYED) {
+ ERROR("Wrong state after host_rmi_data_destroy\n");
+ goto undelegate_destroy;
+ }
+
+ /* Undelegated to use helper function host_realm_delegate_map_protected_data */
+ host_rmi_granule_undelegate(base);
+
+ /*2b DATA_CREATE_UNKNOWN */
+ ret = host_realm_delegate_map_protected_data(true, &realm, base, PAGE_SIZE, 0U);
+ if (ret != RMI_SUCCESS) {
+ ERROR("host_realm_delegate_map_protected_data failed\n");
+ goto undelegate_destroy;
+ }
+ ret = host_rmi_rtt_readentry(realm.rd, base, 3U, &rtt);
+ if (ret != RMI_SUCCESS || rtt.state != RMI_ASSIGNED ||
+ (rtt.ripas != RMI_DESTROYED)) {
+ ERROR("wrong state after DATA_CRATE_UNKNOWN\n");
+ goto undelegate_destroy;
+ }
+
+ /* 2c DATA_DESTROY */
+ ret = host_rmi_data_destroy(realm.rd, base, &data, &top);
+ if (ret != RMI_SUCCESS || data != base) {
+ ERROR("host_rmi_data_destroy failed\n");
+ goto undelegate_destroy;
+ }
+ ret = host_rmi_rtt_readentry(realm.rd, base, 3U, &rtt);
+ if (ret != RMI_SUCCESS || rtt.state != RMI_UNASSIGNED ||
+ rtt.ripas != RMI_DESTROYED) {
+ ERROR("Wrong state after host_rmi_data_destroy\n");
+ goto undelegate_destroy;
+ }
+
+ host_rmi_granule_undelegate(base);
+
+ /* 3. start with new page */
+ INFO("Test 3\n");
+ base = (u_register_t)page_alloc(PAGE_SIZE);
+ ret = host_realm_delegate_map_protected_data(true, &realm, base, PAGE_SIZE, 0U);
+ if (ret != RMI_SUCCESS) {
+ ERROR("host_realm_delegate_map_protected_data failed\n");
+ goto destroy_realm;
+ }
+ ret = host_rmi_rtt_readentry(realm.rd, base, 3U, &rtt);
+ if (ret != RMI_SUCCESS || rtt.state != RMI_ASSIGNED ||
+ (rtt.ripas != RMI_EMPTY)) {
+ ERROR("wrong state after DATA_CRATE_UNKNOWN\n");
+ goto undelegate_destroy;
+ }
+ ret = host_rmi_data_destroy(realm.rd, base, &data, &top);
+ if (ret != RMI_SUCCESS || data != base) {
+ ERROR("host_rmi_data_destroy failed\n");
+ goto undelegate_destroy;
+ }
+ ret = host_rmi_rtt_readentry(realm.rd, base, 3U, &rtt);
+ if (ret != RMI_SUCCESS || rtt.state != RMI_UNASSIGNED ||
+ rtt.ripas != RMI_EMPTY) {
+ ERROR("Wrong state after host_rmi_data_destroy\n");
+ goto undelegate_destroy;
+ }
+ host_rmi_granule_undelegate(base);
+
+ /* 4. start with new page */
+ INFO("Test 4\n");
+ base = (u_register_t)page_alloc(PAGE_SIZE);
+ ret = host_rmi_rtt_init_ripas(realm.rd, base, base + PAGE_SIZE, &top);
+ if (ret != RMI_SUCCESS) {
+ ERROR("%s() failed, ret=0x%lx line=%u\n",
+ "host_rmi_rtt_init_ripas", ret, __LINE__);
+ goto destroy_realm;
+ }
+ ret = host_rmi_rtt_readentry(realm.rd, base, 3U, &rtt);
+ if (ret != RMI_SUCCESS || rtt.state != RMI_UNASSIGNED ||
+ (rtt.ripas != RMI_RAM)) {
+ ERROR("wrong state after INIT_RIPAS\n");
+ goto undelegate_destroy;
+ }
+ /* 4a. DATA_CREATE_UNKNOWN */
+ ret = host_realm_delegate_map_protected_data(true, &realm, base, PAGE_SIZE, 0U);
+ if (ret != RMI_SUCCESS) {
+ ERROR("host_realm_delegate_map_protected_data failed\n");
+ goto destroy_realm;
+ }
+ ret = host_rmi_rtt_readentry(realm.rd, base, 3U, &rtt);
+ if (ret != RMI_SUCCESS || rtt.state != RMI_ASSIGNED ||
+ (rtt.ripas != RMI_RAM)) {
+ ERROR("wrong state after DATA_CRATE_UNKNOWN\n");
+ goto undelegate_destroy;
+ }
+ host_rmi_granule_undelegate(base);
+
+ /* 5. */
+ INFO("Test 5\n");
+ test_result = test_rtt_destroy_empty(&realm);
+ if (test_result != TEST_RESULT_SUCCESS) {
+ ERROR("Test 5 failed\n");
+ goto destroy_realm;
+ }
+
+ /* 6. */
+ INFO("Test 6\n");
+ test_result = test_rtt_destroy_ram(&realm, false);
+ goto destroy_realm;
+
+undelegate_destroy:
+ ret = host_rmi_granule_undelegate(base);
+ if (ret != RMI_SUCCESS) {
+ ERROR("host_rmi_granule_undelegate failed base=0x%lx ret=0x%lx\n", base, ret);
+ }
+destroy_realm:
+ ret1 = host_destroy_realm(&realm);
+ if (!ret1) {
+ ERROR("%s(): destroy=%d\n",
+ __func__, ret1);
+ return TEST_RESULT_FAIL;
+ }
+ return test_result;
+}
+
+/*
+ * Test aim is to test RTT_DESTROY for active realm
+ * Test initial state of page is unassigned empty
+ * After RTT_DESTROY verify state is unassigned destroyed
+ */
+test_result_t host_realm_pas_validation_active(void)
+{
+ bool ret;
+ test_result_t test_result = TEST_RESULT_FAIL;
+ u_register_t rec_flag[] = {RMI_RUNNABLE};
+ struct realm realm;
+
+ SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+
+ if (!host_create_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
+ (u_register_t)PAGE_POOL_BASE,
+ (u_register_t)PAGE_POOL_MAX_SIZE,
+ 0UL, rec_flag, 1U)) {
+ goto destroy_realm;
+ }
+ if (!host_create_shared_mem(&realm, NS_REALM_SHARED_MEM_BASE,
+ NS_REALM_SHARED_MEM_SIZE)) {
+ goto destroy_realm;
+ }
+
+ test_result = test_rtt_destroy_ram(&realm, true);
+ if (test_result != TEST_RESULT_SUCCESS) {
+ ERROR("test_rtt_destroy_ram failed\n");
+ goto destroy_realm;
+ }
+
+ test_result = test_rtt_destroy_empty(&realm);
+
+destroy_realm:
+ ret = host_destroy_realm(&realm);
+
+ if (!ret) {
+ ERROR("%s(): destroy=%d\n", __func__, ret);
+ return TEST_RESULT_FAIL;
+ }
+ return test_result;
+}
+
+/*
+ * Test aims to generate SEA in Realm by accessing
+ * PAGE with IPA outside realm IPA space and
+ * Generate Data abort by accessing
+ * PAGE with IPA outside max PA supported
+ * Rec0 and Rec2 tries to create Data Abort to realm
+ * Rec1 and Rec3 tries to create Instruction Abort to realm
+ * Realm exception handler runs and returns ESR
+ * Host validates ESR
+ */
+test_result_t host_realm_sea_adr_fault(void)
+{
+ bool ret1, ret2;
+ test_result_t res = TEST_RESULT_FAIL;
+ u_register_t base_ipa, esr, feature_flag, base;
+ struct realm realm;
+ u_register_t rec_flag[4U] = {RMI_RUNNABLE, RMI_RUNNABLE, RMI_RUNNABLE, RMI_RUNNABLE};
+ struct rmi_rec_run *run;
+
+ SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+
+ feature_flag = INPLACE(RMI_FEATURE_REGISTER_0_S2SZ, 0x2CU);
+ if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
+ (u_register_t)PAGE_POOL_BASE,
+ (u_register_t)PAGE_POOL_MAX_SIZE,
+ feature_flag, rec_flag, 4U)) {
+ return TEST_RESULT_FAIL;
+ }
+ if (!host_create_shared_mem(&realm, NS_REALM_SHARED_MEM_BASE,
+ NS_REALM_SHARED_MEM_SIZE)) {
+ goto destroy_realm;
+ }
+
+ /* Any Adr */
+ base = TFTF_BASE;
+ /* IPA outside Realm space */
+ base_ipa = base | (1UL << (EXTRACT(RMI_FEATURE_REGISTER_0_S2SZ,
+ realm.rmm_feat_reg0) + 1U));
+ host_shared_data_set_host_val(&realm, 0U, HOST_ARG1_INDEX, base_ipa);
+ host_shared_data_set_host_val(&realm, 1U, HOST_ARG1_INDEX, base_ipa);
+
+ INFO("base_ipa=0x%lx\n", base_ipa);
+
+ run = (struct rmi_rec_run *)realm.run[0];
+
+ /* Rec0 expect SEA in realm due to Data access to address outside Realm IPA size */
+ ret1 = host_enter_realm_execute(&realm, REALM_DATA_ACCESS_CMD,
+ RMI_EXIT_HOST_CALL, 0U);
+ if (!ret1) {
+ ERROR("Rec0 did not fault exit=0x%lx ret1=%d HPFAR=0x%lx esr=0x%lx\n",
+ run->exit.exit_reason, ret1, run->exit.hpfar, run->exit.esr);
+ goto destroy_realm;
+ }
+
+ /* get ESR set by Realm exception handler */
+ esr = host_shared_data_get_realm_val(&realm, 0U, HOST_ARG2_INDEX);
+ if (((esr & ISS_DFSC_MASK) != DFSC_NO_WALK_SEA)
+ || (EC_BITS(esr) != EC_DABORT_CUR_EL)
+ || ((esr & (1UL << ESR_ISS_EABORT_EA_BIT)) == 0U)) {
+ ERROR("Rec0 incorrect ESR=0x%lx\n", esr);
+ goto destroy_realm;
+ }
+ INFO("Rec0 ESR=0x%lx\n", esr);
+
+ run = (struct rmi_rec_run *)realm.run[1];
+
+ /* Rec1 expect SEA in realm due to Instruction access to address outside Realm IPA size */
+ ret1 = host_enter_realm_execute(&realm, REALM_INSTR_FETCH_CMD,
+ RMI_EXIT_HOST_CALL, 1U);
+ if (!ret1) {
+ ERROR("Rec1 did not fault\n");
+ goto destroy_realm;
+ }
+
+ /* get ESR set by Realm exception handler */
+ esr = host_shared_data_get_realm_val(&realm, 1U, HOST_ARG2_INDEX);
+ if (((esr & ISS_DFSC_MASK) != IFSC_NO_WALK_SEA)
+ || (EC_BITS(esr) != EC_IABORT_CUR_EL)
+ || ((esr & (1UL << ESR_ISS_EABORT_EA_BIT)) == 0U)) {
+ ERROR("Rec1 did not fault exit=0x%lx ret1=%d HPFAR=0x%lx esr=0x%lx\n",
+ run->exit.exit_reason, ret1, run->exit.hpfar, run->exit.esr);
+ goto destroy_realm;
+ }
+ INFO("Rec1 ESR=0x%lx\n", esr);
+
+ /* IPA outside max PA supported */
+ base_ipa |= (1UL << 53U);
+
+ INFO("base_ipa=0x%lx\n", base_ipa);
+
+ host_shared_data_set_host_val(&realm, 2U, HOST_ARG1_INDEX, base_ipa);
+ host_shared_data_set_host_val(&realm, 3U, HOST_ARG1_INDEX, base_ipa);
+
+ run = (struct rmi_rec_run *)realm.run[2];
+
+ /* Rec2 expect SEA in realm due to Data access to address outside Realm IPA size */
+ ret1 = host_enter_realm_execute(&realm, REALM_DATA_ACCESS_CMD,
+ RMI_EXIT_HOST_CALL, 2U);
+ if (!ret1) {
+ ERROR("Rec2 did not fault exit=0x%lx ret1=%d HPFAR=0x%lx esr=0x%lx\n",
+ run->exit.exit_reason, ret1, run->exit.hpfar, run->exit.esr);
+ goto destroy_realm;
+ }
+
+ /* get ESR set by Realm exception handler */
+ esr = host_shared_data_get_realm_val(&realm, 2U, HOST_ARG2_INDEX);
+ if (((esr & ISS_DFSC_MASK) != DFSC_L0_ADR_SIZE_FAULT)
+ || (EC_BITS(esr) != EC_DABORT_CUR_EL)
+ || ((esr & (1UL << ESR_ISS_EABORT_EA_BIT)) != 0U)) {
+ ERROR("Rec2 incorrect ESR=0x%lx\n", esr);
+ goto destroy_realm;
+ }
+ INFO("Rec2 ESR=0x%lx\n", esr);
+
+ run = (struct rmi_rec_run *)realm.run[3];
+
+ /* Rec3 expect SEA in realm due to Instruction access to address outside Realm IPA size */
+ ret1 = host_enter_realm_execute(&realm, REALM_INSTR_FETCH_CMD,
+ RMI_EXIT_HOST_CALL, 3U);
+ if (!ret1) {
+ ERROR("Rec3 did not fault\n");
+ goto destroy_realm;
+ }
+
+ /* get ESR set by Realm exception handler */
+ esr = host_shared_data_get_realm_val(&realm, 3U, HOST_ARG2_INDEX);
+ if (((esr & ISS_IFSC_MASK) != IFSC_L0_ADR_SIZE_FAULT)
+ || (EC_BITS(esr) != EC_IABORT_CUR_EL)
+ || ((esr & (1UL << ESR_ISS_EABORT_EA_BIT)) != 0U)) {
+ ERROR("Rec3 did not fault exit=0x%lx ret1=%d HPFAR=0x%lx esr=0x%lx\n",
+ run->exit.exit_reason, ret1, run->exit.hpfar, run->exit.esr);
+ goto destroy_realm;
+ }
+ INFO("Rec3 ESR=0x%lx\n", esr);
+ res = TEST_RESULT_SUCCESS;
+
+destroy_realm:
+ ret2 = host_destroy_realm(&realm);
+
+ if (!ret2) {
+ ERROR("%s(): destroy=%d\n",
+ __func__, ret2);
+ return TEST_RESULT_FAIL;
+ }
+
+ return res;
+}
diff --git a/tftf/tests/tests-realm-payload.xml b/tftf/tests/tests-realm-payload.xml
index 0ecefee14..9948ff1da 100644
--- a/tftf/tests/tests-realm-payload.xml
+++ b/tftf/tests/tests-realm-payload.xml
@@ -16,10 +16,16 @@
function="host_realm_multi_rec_multiple_cpu" />
<testcase name="Realm payload multi rec validations"
function="host_realm_multi_rec_multiple_cpu2" />
+ <testcase name="New Realm PAS Validation"
+ function="host_realm_pas_validation_new" />
+ <testcase name="Active Realm PAS validation"
+ function="host_realm_pas_validation_active" />
<testcase name="Realm SEA Empty"
function="host_realm_sea_empty" />
<testcase name="Realm SEA Unprotected"
function="host_realm_sea_unprotected" />
+ <testcase name="Realm SEA Adr Fault"
+ function="host_realm_sea_adr_fault" />
<testcase name="Realm Abort Unassigned RAM"
function="host_realm_abort_unassigned_ram" />
<testcase name="Realm Abort Unassigned Destroyed"