Merge "fix(xilinx): wire Xilinx platforms in docs"
diff --git a/docs/about/contact.rst b/docs/about/contact.rst
index 2b1778c..bb1e2a4 100644
--- a/docs/about/contact.rst
+++ b/docs/about/contact.rst
@@ -20,14 +20,14 @@
 Issue Tracker
 ^^^^^^^^^^^^^
 
-Specific issues may be raised using the `issue tracker`_ on the
-TrustedFirmware.org website. Using this tracker makes it easy for the
-maintainers to prioritise and respond to your ticket.
+Specific issues may be raised using the `issue tracker`_ on Github. Using this
+tracker makes it easy for the maintainers to prioritise and respond to your
+ticket.
 
 --------------
 
-*Copyright (c) 2019-2022, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2024, Arm Limited. All rights reserved.*
 
-.. _`issue tracker`: https://developer.trustedfirmware.org
+.. _`issue tracker`: https://github.com/TrustedFirmware-A/tf-a-tests/issues
 .. _`TF-A-Tests development`: https://lists.trustedfirmware.org/mailman3/lists/tf-a-tests.lists.trustedfirmware.org/
 .. _`summary of all the lists`: https://lists.trustedfirmware.org/mailman3/lists/
diff --git a/include/common/firmware_image_package.h b/include/common/firmware_image_package.h
index aba5b57..2a144ba 100644
--- a/include/common/firmware_image_package.h
+++ b/include/common/firmware_image_package.h
@@ -22,6 +22,8 @@
 	{{0x4f, 0x51, 0x1d, 0x11}, {0x2b, 0xe5}, {0x4e, 0x49}, 0xb4, 0xc5, {0x83, 0xc2, 0xf7, 0x15, 0x84, 0x0a} }
 #define UUID_FIRMWARE_UPDATE_FWU_CERT \
 	{{0x71, 0x40, 0x8a, 0xb2}, {0x18, 0xd6}, {0x87, 0x4c}, 0x8b, 0x2e, {0xc6, 0xdc, 0xcd, 0x50, 0xf0, 0x96} }
+#define UUID_TRUSTED_KEY_CERT \
+	{{0x82,  0x7e, 0xe8, 0x90}, {0xf8, 0x60}, {0xe4, 0x11}, 0xa1, 0xb4, {0x77, 0x7a, 0x21, 0xb4, 0xf9, 0x4c} }
 
 typedef struct fip_toc_header {
 	uint32_t	name;
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index 88c873c..6a0d286 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -828,8 +828,32 @@
 #define EC_SERROR			U(0x2f)
 /* Data Fault Status code, not all error codes listed */
 #define ISS_DFSC_MASK			U(0x3f)
+#define DFSC_L0_ADR_SIZE_FAULT		U(0)
+#define DFSC_L0_TRANS_FAULT		U(4)
+#define DFSC_L1_TRANS_FAULT		U(5)
+#define DFSC_L2_TRANS_FAULT		U(6)
+#define DFSC_L3_TRANS_FAULT		U(7)
+#define DFSC_NO_WALK_SEA		U(0x10)
+#define DFSC_L0_SEA			U(0x14)
+#define DFSC_L1_SEA			U(0x15)
+#define DFSC_L2_SEA			U(0x16)
+#define DFSC_L3_SEA			U(0x17)
 #define DFSC_EXT_DABORT			U(0x10)
 #define DFSC_GPF_DABORT			U(0x28)
+
+/* Instr Fault Status code, not all error codes listed */
+#define ISS_IFSC_MASK			U(0x3f)
+#define IFSC_L0_ADR_SIZE_FAULT		U(0)
+#define IFSC_L0_TRANS_FAULT		U(4)
+#define IFSC_L1_TRANS_FAULT		U(5)
+#define IFSC_L2_TRANS_FAULT		U(6)
+#define IFSC_L3_TRANS_FAULT		U(7)
+#define IFSC_NO_WALK_SEA		U(0x10)
+#define IFSC_L0_SEA			U(0x24)
+#define IFSC_L1_SEA			U(0x25)
+#define IFSC_L2_SEA			U(0x26)
+#define IFSC_L3_SEA			U(0x27)
+
 /* ISS encoding an exception from HVC or SVC instruction execution */
 #define ISS_HVC_SMC_IMM16_MASK		U(0xffff)
 
diff --git a/include/lib/extensions/pauth.h b/include/lib/extensions/pauth.h
index c8d577f..8816e18 100644
--- a/include/lib/extensions/pauth.h
+++ b/include/lib/extensions/pauth.h
@@ -11,6 +11,11 @@
 #include <stdint.h>
 
 #ifdef __aarch64__
+/* Number of ARMv8.3-PAuth keys */
+#define NUM_KEYS        5U
+
+static const char * const key_name[] = {"IA", "IB", "DA", "DB", "GA"};
+
 /* Initialize 128-bit ARMv8.3-PAuth key */
 uint128_t init_apkey(void);
 
@@ -24,13 +29,13 @@
  * Fill Pauth Keys and template with random values if keys werenot initialized earlier,
  * Else Copy PAuth key registers to template.
  */
-void pauth_test_lib_fill_regs_and_template(void);
+void pauth_test_lib_fill_regs_and_template(uint128_t *pauth_keys_arr);
 
 /* Read and Compare PAuth registers with provided template values. */
-bool pauth_test_lib_compare_template(void);
+bool pauth_test_lib_compare_template(uint128_t *pauth_keys_before, uint128_t *pauth_keys_after);
 
 /* Read and Store PAuth registers in template. */
-void pauth_test_lib_read_keys(void);
+void pauth_test_lib_read_keys(uint128_t *pauth_keys_arr);
 
 /* Test PAuth instructions. */
 void pauth_test_lib_test_intrs(void);
diff --git a/include/lib/tftf_lib.h b/include/lib/tftf_lib.h
index 8eff7fc..36e2e0f 100644
--- a/include/lib/tftf_lib.h
+++ b/include/lib/tftf_lib.h
@@ -38,6 +38,23 @@
 #define TEST_RESULT_IS_VALID(result) \
 	((result >= TEST_RESULT_MIN) && (result < TEST_RESULT_MAX))
 
+#define TEST_ASSERT(must_be_true) \
+	do { \
+		if (!(must_be_true)) { \
+			tftf_testcase_printf("Failed at %s:%d\n", __FILE__, __LINE__); \
+			return TEST_RESULT_FAIL;\
+		} \
+	} while (0)
+
+#define TEST_ASSERT_SKIP(must_be_true) \
+	do { \
+		if (!(must_be_true)) { \
+			tftf_testcase_printf("Failed at %s:%d\n", __FILE__, __LINE__); \
+			return TEST_RESULT_SKIPPED;\
+		} \
+	} while (0)
+
+
 /*
  * PSCI Function Wrappers
  *
diff --git a/include/runtime_services/cactus_test_cmds.h b/include/runtime_services/cactus_test_cmds.h
index af5d066..3938c2f 100644
--- a/include/runtime_services/cactus_test_cmds.h
+++ b/include/runtime_services/cactus_test_cmds.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -201,10 +201,13 @@
 static inline struct ffa_value cactus_mem_send_cmd(
 	ffa_id_t source, ffa_id_t dest, uint32_t mem_func,
 	ffa_memory_handle_t handle, ffa_memory_region_flags_t retrieve_flags,
-	uint16_t word_to_write)
+	uint16_t word_to_write, bool expect_exception)
 {
+	uint64_t _expect_exception = expect_exception ? (1ULL << 32) : 0;
+	uint64_t packed = (uint64_t)word_to_write | _expect_exception;
+
 	return cactus_send_cmd(source, dest, CACTUS_MEM_SEND_CMD, mem_func,
-			       handle, retrieve_flags, word_to_write);
+			       handle, retrieve_flags, packed);
 }
 
 static inline ffa_memory_handle_t cactus_mem_send_get_handle(
@@ -221,7 +224,12 @@
 
 static inline uint16_t cactus_mem_send_words_to_write(struct ffa_value ret)
 {
-	return (uint16_t)ret.arg7;
+	return (uint16_t)ret.arg7 & 0xFFFFU;
+}
+
+static inline bool cactus_mem_send_expect_exception(struct ffa_value ret)
+{
+	return (bool)(ret.arg7 >> 32);
 }
 
 /**
@@ -625,4 +633,25 @@
 	return (uint32_t)ret.arg4;
 }
 
+/*
+ * Request SP to mimic handling a RAS error delegated by an EL3 logical secure
+ * partition.
+ *
+ * The command ID is the hex representation of the string 'rase' which
+ * denotes RAS Error.
+ */
+#define CACTUS_RAS_DELEGATE_CMD U(0x72617365)
+
+static inline struct ffa_value cactus_ras_delegate_send_cmd(
+	ffa_id_t source, ffa_id_t dest, uint64_t event_id)
+{
+	return cactus_send_cmd(source, dest, CACTUS_RAS_DELEGATE_CMD, event_id, 0, 0,
+			       0);
+}
+
+static inline uint64_t cactus_ras_get_event_id(struct ffa_value ret)
+{
+	return (uint64_t)ret.arg4;
+}
+
 #endif
diff --git a/include/runtime_services/ffa_helpers.h b/include/runtime_services/ffa_helpers.h
index 3f760fa..0f19827 100644
--- a/include/runtime_services/ffa_helpers.h
+++ b/include/runtime_services/ffa_helpers.h
@@ -525,7 +525,11 @@
 #define FFA_MEMORY_REGION_TRANSACTION_TYPE_DONATE ((0x3U) << 3)
 
 /** The maximum number of recipients a memory region may be sent to. */
-#define MAX_MEM_SHARE_RECIPIENTS 1U
+#define MAX_MEM_SHARE_RECIPIENTS 2U
+
+struct ffa_memory_access_impdef {
+	uint64_t val[2];
+};
 
 /**
  * This corresponds to table "Endpoint memory access descriptor" of the FFA 1.0
@@ -538,6 +542,8 @@
 	 * an `ffa_composite_memory_region` struct.
 	 */
 	uint32_t composite_memory_region_offset;
+	/* Space for implementation defined information */
+	struct ffa_memory_access_impdef impdef;
 	uint64_t reserved_0;
 };
 
@@ -619,6 +625,43 @@
 }
 
 /**
+ * To maintain forwards compatability we can't make assumptions about the size
+ * of the endpoint memory access descriptor so provide a helper function
+ * to get a receiver from the receiver array using the memory access descriptor
+ * size field from the memory region descriptor struct.
+ * Returns NULL if we cannot return the receiver.
+ */
+static inline struct ffa_memory_access *ffa_memory_region_get_receiver(
+	struct ffa_memory_region *memory_region, uint32_t receiver_index)
+{
+	uint32_t memory_access_desc_size =
+		memory_region->memory_access_desc_size;
+
+	if (receiver_index >= memory_region->receiver_count) {
+		return NULL;
+	}
+
+	/*
+	 * Memory access descriptor size cannot be greater than the size of
+	 * the memory access descriptor defined by the current FF-A version.
+	 */
+	if (memory_access_desc_size > sizeof(struct ffa_memory_access)) {
+		return NULL;
+	}
+
+	/* Check we cannot use receivers offset to cause overflow. */
+	if (memory_region->receivers_offset !=
+	    sizeof(struct ffa_memory_region)) {
+		return NULL;
+	}
+
+	return (struct ffa_memory_access *)((uint8_t *)memory_region +
+					    memory_region->receivers_offset +
+					    (receiver_index *
+					     memory_access_desc_size));
+}
+
+/**
  * Gets the `ffa_composite_memory_region` for the given receiver from an
  * `ffa_memory_region`, or NULL if it is not valid.
  */
@@ -751,10 +794,11 @@
 					     const uint16_t start_index,
 					     const uint16_t tag);
 
-struct ffa_memory_access ffa_memory_access_init_permissions(
+struct ffa_memory_access ffa_memory_access_init(
 	ffa_id_t receiver_id, enum ffa_data_access data_access,
 	enum ffa_instruction_access instruction_access,
-	ffa_memory_receiver_flags_t flags);
+	ffa_memory_receiver_flags_t flags,
+	struct ffa_memory_access_impdef *impdef);
 
 #endif /* __ASSEMBLY__ */
 
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 4f81042..3159ad4 100644
--- a/include/runtime_services/host_realm_managment/host_realm_rmi.h
+++ b/include/runtime_services/host_realm_managment/host_realm_rmi.h
@@ -549,37 +549,64 @@
 u_register_t host_rmi_realm_create(u_register_t rd, u_register_t params_ptr);
 u_register_t host_rmi_realm_destroy(u_register_t rd);
 u_register_t host_rmi_features(u_register_t index, u_register_t *features);
+u_register_t host_rmi_data_destroy(u_register_t rd,
+				   u_register_t map_addr,
+				   u_register_t *data,
+				   u_register_t *top);
+u_register_t host_rmi_rtt_readentry(u_register_t rd,
+				    u_register_t map_addr,
+				    u_register_t level,
+				    struct rtt_entry *rtt);
+u_register_t host_rmi_rtt_destroy(u_register_t rd,
+				  u_register_t map_addr,
+				  u_register_t level,
+				  u_register_t *rtt,
+				  u_register_t *top);
+u_register_t host_rmi_rtt_init_ripas(u_register_t rd,
+				   u_register_t start,
+				   u_register_t end,
+				   u_register_t *top);
+u_register_t host_rmi_create_rtt_levels(struct realm *realm,
+					u_register_t map_addr,
+					u_register_t level,
+					u_register_t max_level);
+u_register_t host_rmi_rtt_unmap_unprotected(u_register_t rd,
+					    u_register_t map_addr,
+					    u_register_t level,
+					    u_register_t *top);
+u_register_t host_rmi_rtt_set_ripas(u_register_t rd,
+				    u_register_t rec,
+				    u_register_t start,
+				    u_register_t end,
+				    u_register_t *top);
+u_register_t host_rmi_psci_complete(u_register_t calling_rec, u_register_t target_rec,
+				    unsigned long status);
+void host_rmi_init_cmp_result(void);
+bool host_rmi_get_cmp_result(void);
 
 /* Realm management */
 u_register_t host_realm_create(struct realm *realm);
 u_register_t host_realm_map_payload_image(struct realm *realm,
 					  u_register_t realm_payload_adr);
 u_register_t host_realm_map_ns_shared(struct realm *realm,
-					u_register_t ns_shared_mem_adr,
-					u_register_t ns_shared_mem_size);
+				      u_register_t ns_shared_mem_adr,
+				      u_register_t ns_shared_mem_size);
 u_register_t host_realm_rec_create(struct realm *realm);
 unsigned int host_realm_find_rec_by_mpidr(unsigned int mpidr, struct realm *realm);
 u_register_t host_realm_activate(struct realm *realm);
 u_register_t host_realm_destroy(struct realm *realm);
 u_register_t host_realm_rec_enter(struct realm *realm,
-					u_register_t *exit_reason,
-					unsigned int *host_call_result,
-					unsigned int rec_num);
+				  u_register_t *exit_reason,
+				  unsigned int *host_call_result,
+				  unsigned int rec_num);
 u_register_t host_realm_init_ipa_state(struct realm *realm, u_register_t level,
-					u_register_t start, uint64_t end);
-u_register_t host_rmi_psci_complete(u_register_t calling_rec, u_register_t target_rec,
-		unsigned long status);
-void host_rmi_init_cmp_result(void);
-bool host_rmi_get_cmp_result(void);
-u_register_t host_realm_map_protected_data(bool unknown,
-			struct realm *realm,
-			u_register_t target_pa,
-			u_register_t map_size,
-			u_register_t src_pa);
-u_register_t host_rmi_rtt_set_ripas(u_register_t rd,
-				  u_register_t rec,
-				  u_register_t start,
-				  u_register_t end,
-				  u_register_t *top);
+				       u_register_t start, uint64_t end);
+u_register_t host_realm_delegate_map_protected_data(bool unknown,
+					   struct realm *realm,
+					   u_register_t target_pa,
+					   u_register_t map_size,
+					   u_register_t src_pa);
+u_register_t host_realm_map_unprotected(struct realm *realm, u_register_t ns_pa,
+					u_register_t map_size);
 
 #endif /* HOST_REALM_RMI_H */
diff --git a/include/runtime_services/host_realm_managment/host_shared_data.h b/include/runtime_services/host_realm_managment/host_shared_data.h
index 8549512..632fdaa 100644
--- a/include/runtime_services/host_realm_managment/host_shared_data.h
+++ b/include/runtime_services/host_realm_managment/host_shared_data.h
@@ -47,6 +47,8 @@
 	REALM_MULTIPLE_REC_PSCI_DENIED_CMD,
 	REALM_MULTIPLE_REC_MULTIPLE_CPU_CMD,
 	REALM_GET_RSI_VERSION,
+	REALM_INSTR_FETCH_CMD,
+	REALM_DATA_ACCESS_CMD,
 	REALM_PMU_CYCLE,
 	REALM_PMU_EVENT,
 	REALM_PMU_PRESERVE,
@@ -65,6 +67,7 @@
 	REALM_PAUTH_SET_CMD,
 	REALM_PAUTH_CHECK_CMD,
 	REALM_PAUTH_FAULT,
+	REALM_DIT_CHECK_CMD,
 	REALM_SME_ID_REGISTERS,
 	REALM_SME_UNDEF_ABORT
 };
@@ -101,6 +104,12 @@
 		unsigned int rec_num, uint8_t index, u_register_t val);
 
 /*
+ * Get data shared from realm to Host
+ */
+u_register_t host_shared_data_get_realm_val(struct realm *realm_ptr,
+		unsigned int rec_num, uint8_t index);
+
+/*
  * Set command to be send from Host to realm
  */
 void host_shared_data_set_realm_cmd(struct realm *realm_ptr, uint8_t cmd,
diff --git a/lib/extensions/pauth/aarch64/pauth.c b/lib/extensions/pauth/aarch64/pauth.c
index 90e16d5..9608b97 100644
--- a/lib/extensions/pauth/aarch64/pauth.c
+++ b/lib/extensions/pauth/aarch64/pauth.c
@@ -11,14 +11,6 @@
 #include <debug.h>
 #include <pauth.h>
 
-/* Number of ARMv8.3-PAuth keys */
-#define NUM_KEYS        5U
-
-static const char * const key_name[] = {"IA", "IB", "DA", "DB", "GA"};
-
-static uint128_t pauth_keys_before[NUM_KEYS];
-static uint128_t pauth_keys_after[NUM_KEYS];
-
 /*
  * This is only a toy implementation to generate a seemingly random
  * 128-bit key from sp, x30 and cntpct_el0 values.
@@ -49,11 +41,11 @@
 	return false;
 }
 
-bool pauth_test_lib_compare_template(void)
+bool pauth_test_lib_compare_template(uint128_t *pauth_keys_before, uint128_t *pauth_keys_after)
 {
 	bool result = true;
 
-	pauth_test_lib_read_keys();
+	pauth_test_lib_read_keys(pauth_keys_after);
 	for (unsigned int i = 0U; i < NUM_KEYS; ++i) {
 		if (pauth_keys_before[i] != pauth_keys_after[i]) {
 			ERROR("AP%sKey_EL1 read 0x%llx:%llx "
@@ -73,7 +65,7 @@
  * Program or read ARMv8.3-PAuth keys (if already enabled)
  * and store them in <pauth_keys_before> buffer
  */
-void pauth_test_lib_fill_regs_and_template(void)
+void pauth_test_lib_fill_regs_and_template(uint128_t *pauth_keys_before)
 {
 	uint128_t plat_key;
 
@@ -146,30 +138,30 @@
 
 /*
  * Read ARMv8.3-PAuth keys and store them in
- * <pauth_keys_after> buffer
+ * <pauth_keys_arr> buffer
  */
-void pauth_test_lib_read_keys(void)
+void pauth_test_lib_read_keys(uint128_t *pauth_keys_arr)
 {
-	(void)memset(pauth_keys_after, 0, NUM_KEYS * sizeof(uint128_t));
+	(void)memset(pauth_keys_arr, 0, NUM_KEYS * sizeof(uint128_t));
 
 	/* Read APIAKey_EL1 */
-	pauth_keys_after[0] = read_apiakeylo_el1() |
+	pauth_keys_arr[0] = read_apiakeylo_el1() |
 		((uint128_t)(read_apiakeyhi_el1()) << 64U);
 
 	/* Read APIBKey_EL1 */
-	pauth_keys_after[1] = read_apibkeylo_el1() |
+	pauth_keys_arr[1] = read_apibkeylo_el1() |
 		((uint128_t)(read_apibkeyhi_el1()) << 64U);
 
 	/* Read APDAKey_EL1 */
-	pauth_keys_after[2] = read_apdakeylo_el1() |
+	pauth_keys_arr[2] = read_apdakeylo_el1() |
 		((uint128_t)(read_apdakeyhi_el1()) << 64U);
 
 	/* Read APDBKey_EL1 */
-	pauth_keys_after[3] = read_apdbkeylo_el1() |
+	pauth_keys_arr[3] = read_apdbkeylo_el1() |
 		((uint128_t)(read_apdbkeyhi_el1()) << 64U);
 
 	/* Read APGAKey_EL1 */
-	pauth_keys_after[4] = read_apgakeylo_el1() |
+	pauth_keys_arr[4] = read_apgakeylo_el1() |
 		((uint128_t)(read_apgakeyhi_el1()) << 64U);
 }
 
diff --git a/plat/arm/fvp/include/platform_def.h b/plat/arm/fvp/include/platform_def.h
index b8871c4..60c33e9 100644
--- a/plat/arm/fvp/include/platform_def.h
+++ b/plat/arm/fvp/include/platform_def.h
@@ -89,6 +89,12 @@
 #define SECURE_MEMORY_ACCESS_ADDR		U(0xFD000000)
 
 /*******************************************************************************
+ * Base address and size for the FIP.
+ ******************************************************************************/
+#define PLAT_ARM_FIP_BASE		(FLASH_BASE)
+#define PLAT_ARM_FIP_SIZE		(0x100000)
+
+/*******************************************************************************
  * Base address and size for the FIP that contains FWU images.
  ******************************************************************************/
 #define PLAT_ARM_FWU_FIP_BASE		(FLASH_BASE + 0x400000)
@@ -253,11 +259,11 @@
 #define MAX_MMAP_REGIONS		50
 #else
 #if IMAGE_CACTUS
-#define MAX_XLAT_TABLES			9
+#define MAX_XLAT_TABLES			12
 #else
 #define MAX_XLAT_TABLES			5
 #endif
-#define MAX_MMAP_REGIONS		16
+#define MAX_MMAP_REGIONS		20
 #endif
 
 /*******************************************************************************
diff --git a/plat/arm/tc/include/platform_def.h b/plat/arm/tc/include/platform_def.h
index 1f0c28d..82fa6c2 100644
--- a/plat/arm/tc/include/platform_def.h
+++ b/plat/arm/tc/include/platform_def.h
@@ -80,7 +80,7 @@
 #define TC_GICC_BASE			0x2C000000
 
 /* SoC's PL011 UART0 related constants */
-#define PL011_UART0_BASE		0x7FF70000
+#define PL011_UART0_BASE		0x2A400000
 #define PL011_UART0_CLK_IN_HZ		7372800
 
 /* SoC's PL011 UART1 related constants */
diff --git a/plat/xilinx/versal/tests_to_skip.txt b/plat/xilinx/versal/tests_to_skip.txt
index fddf331..b430058 100644
--- a/plat/xilinx/versal/tests_to_skip.txt
+++ b/plat/xilinx/versal/tests_to_skip.txt
@@ -39,8 +39,14 @@
 PSCI CPU ON OFF Stress Tests/Repeated hotplug of all cores to stress test CPU_ON and CPU_OFF
 PSCI CPU ON OFF Stress Tests/Random hotplug cores in a large iteration to stress boot path code
 
- #TESTS: TSP
- IRQ support in TSP/Resume preempted STD SMC after PSCI CPU OFF/ON cycle
- IRQ support in TSP/Resume preempted STD SMC after PSCI SYSTEM SUSPEND
- IRQ support in TSP/Resume preempted STD SMC
- TSP PSTATE test
+#TESTS: TSP
+IRQ support in TSP/Resume preempted STD SMC after PSCI CPU OFF/ON cycle
+IRQ support in TSP/Resume preempted STD SMC after PSCI SYSTEM SUSPEND
+IRQ support in TSP/Resume preempted STD SMC
+TSP PSTATE test
+
+#TESTS: runtime-instrumentation
+Runtime Instrumentation Validation
+
+#TESTS: debugfs
+DebugFS
diff --git a/plat/xilinx/versal_net/aarch64/plat_helpers.S b/plat/xilinx/versal_net/aarch64/plat_helpers.S
index 77012ef..698a8bc 100644
--- a/plat/xilinx/versal_net/aarch64/plat_helpers.S
+++ b/plat/xilinx/versal_net/aarch64/plat_helpers.S
@@ -22,14 +22,36 @@
  * ---------------------------------------------------------------------
  */
 func platform_get_core_pos
+        /*
+         * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
+         * look as if in a multi-threaded implementation.
+         */
+        tst     x0, #MPIDR_MT_MASK
+        lsl     x3, x0, #MPIDR_AFFINITY_BITS
+        csel    x3, x3, x0, eq
+
 	/* x1 = core-id inside cluster */
-	ubfx	x1, x0, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx	x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx	x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
 	/* x2 = cluster-id */
-	ubfx	x2, x0, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx	x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+
+	/* check if cpu_id valid */
+	cmp x1, #PLATFORM_CORE_COUNT_PER_CLUSTER
+	b.hi    error
+
+	/* check if cluster valid */
+	cmp x2, #PLATFORM_CLUSTER_COUNT
+	b.hi    error
 
 	/* core-position = cluster-id * cores per cluster + core-id */
-	mov	x3, #PLATFORM_CORE_COUNT_PER_CLUSTER
-	madd	x0, x2, x3, x1
+	mov     x3, #PLATFORM_CORE_COUNT_PER_CLUSTER
+	madd	x1, x2, x3, x1
+	mov	x3, #PLATFORM_MAX_PE_PER_CPU
+	madd	x0, x1, x3, x0
+	ret
+error:
+	mov     x0, #-1
 	ret
 endfunc platform_get_core_pos
 
diff --git a/plat/xilinx/versal_net/include/platform_def.h b/plat/xilinx/versal_net/include/platform_def.h
index c357c96..8431ca6 100644
--- a/plat/xilinx/versal_net/include/platform_def.h
+++ b/plat/xilinx/versal_net/include/platform_def.h
@@ -18,6 +18,10 @@
 
 #define PLATFORM_CLUSTER_COUNT			U(4)
 #define PLATFORM_CORE_COUNT_PER_CLUSTER		U(4)
+#define PLATFORM_MAX_PE_PER_CPU	U(1)
+/* Because of make_mpid from include/lib/tftf_lib.h */
+#define PLAT_MAX_PE_PER_CPU	PLATFORM_MAX_PE_PER_CPU
+
 #define PLATFORM_CORE_COUNT			(PLATFORM_CLUSTER_COUNT * \
 						PLATFORM_CORE_COUNT_PER_CLUSTER)
 #define PLATFORM_NUM_AFFS			(PLATFORM_CORE_COUNT + \
diff --git a/plat/xilinx/versal_net/tests_to_skip.txt b/plat/xilinx/versal_net/tests_to_skip.txt
index a45426f..46bc1a3 100644
--- a/plat/xilinx/versal_net/tests_to_skip.txt
+++ b/plat/xilinx/versal_net/tests_to_skip.txt
@@ -62,8 +62,8 @@
 #TESTS: el3-power-state
 EL3 power state parser validation
 
-#TESTS: TSP
-IRQ support in TSP/Resume preempted STD SMC
-IRQ support in TSP/Resume preempted STD SMC from other CPUs
-IRQ support in TSP/Resume preempted STD SMC after PSCI CPU OFF/ON cycle
-IRQ support in TSP/Resume preempted STD SMC after PSCI SYSTEM SUSPEND
+#TESTS: runtime-instrumentation
+Runtime Instrumentation Validation
+
+#TESTS: debugfs
+DebugFS
diff --git a/realm/realm_pauth.c b/realm/realm_pauth.c
index cf3bec3..31b26e7 100644
--- a/realm/realm_pauth.c
+++ b/realm/realm_pauth.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -7,12 +7,15 @@
 
 #include <stdio.h>
 #include <arch_features.h>
+#include <assert.h>
 #include <debug.h>
 #include <pauth.h>
 #include <realm_rsi.h>
 #include <sync.h>
 
-static volatile bool set_cmd_done;
+static volatile bool set_cmd_done[MAX_REC_COUNT];
+static uint128_t pauth_keys_before[MAX_REC_COUNT][NUM_KEYS];
+static uint128_t pauth_keys_after[MAX_REC_COUNT][NUM_KEYS];
 
 static bool exception_handler(void)
 {
@@ -68,19 +71,28 @@
  */
 bool test_realm_pauth_set_cmd(void)
 {
+	unsigned int rec = read_mpidr_el1() & MPID_MASK;
+
 	if (!is_armv8_3_pauth_present()) {
 		return false;
 	}
+	assert(rec < MAX_REC_COUNT);
 	pauth_test_lib_test_intrs();
-	pauth_test_lib_fill_regs_and_template();
-	set_cmd_done = true;
+	pauth_test_lib_fill_regs_and_template(pauth_keys_before[rec]);
+	set_cmd_done[rec] = true;
 	return true;
 }
 
 bool test_realm_pauth_check_cmd(void)
 {
-	if (!is_armv8_3_pauth_present() || !set_cmd_done) {
+	unsigned int rec = read_mpidr_el1() & MPID_MASK;
+	bool ret;
+
+	assert(rec < MAX_REC_COUNT);
+	if (!is_armv8_3_pauth_present() || !set_cmd_done[rec]) {
 		return false;
 	}
-	return pauth_test_lib_compare_template();
+	ret = pauth_test_lib_compare_template(pauth_keys_before[rec], pauth_keys_after[rec]);
+	realm_printf("Pauth key comparison ret=%d\n", ret);
+	return ret;
 }
diff --git a/realm/realm_payload_main.c b/realm/realm_payload_main.c
index ddaa3cb..ce25f43 100644
--- a/realm/realm_payload_main.c
+++ b/realm/realm_payload_main.c
@@ -16,6 +16,7 @@
 #include "realm_def.h"
 #include <realm_rsi.h>
 #include <realm_tests.h>
+#include <sync.h>
 #include <tftf_lib.h>
 
 static fpu_state_t rl_fpu_state_write;
@@ -129,6 +130,72 @@
 	return false;
 }
 
+bool test_realm_dit_check_cmd(void)
+{
+	if (is_armv8_4_dit_present()) {
+		write_dit(DIT_BIT);
+		realm_printf("Testing DIT=0x%lx\n", read_dit());
+		/* Test if DIT is preserved after HOST_CALL */
+		if (read_dit() == DIT_BIT) {
+			return true;
+		}
+	}
+	return false;
+}
+
+
+static bool test_realm_instr_fetch_cmd(void)
+{
+	u_register_t base;
+	void (*func_ptr)(void);
+	rsi_ripas_type ripas;
+
+	base = realm_shared_data_get_my_host_val(HOST_ARG1_INDEX);
+	rsi_ipa_state_get(base, &ripas);
+	realm_printf("Initial ripas=0x%lx\n", ripas);
+	/* causes instruction abort */
+	realm_printf("Generate Instruction Abort\n");
+	func_ptr = (void (*)(void))base;
+	func_ptr();
+	/* should not return */
+	return false;
+}
+
+static bool test_realm_data_access_cmd(void)
+{
+	u_register_t base;
+	rsi_ripas_type ripas;
+
+	base = realm_shared_data_get_my_host_val(HOST_ARG1_INDEX);
+	rsi_ipa_state_get(base, &ripas);
+	realm_printf("Initial ripas=0x%lx\n", ripas);
+	/* causes data abort */
+	realm_printf("Generate Data Abort\n");
+	*((volatile uint64_t *)base);
+	/* should not return */
+	return false;
+}
+
+static bool realm_exception_handler(void)
+{
+	u_register_t base, far, esr;
+
+	base = realm_shared_data_get_my_host_val(HOST_ARG1_INDEX);
+	far = read_far_el1();
+	esr = read_esr_el1();
+
+	if (far == base) {
+		/* return ESR to Host */
+		realm_shared_data_set_my_realm_val(HOST_ARG2_INDEX, esr);
+		rsi_exit_to_host(HOST_CALL_EXIT_SUCCESS_CMD);
+	}
+	realm_printf("Realm Abort fail incorrect FAR=0x%lx ESR+0x%lx\n", far, esr);
+	rsi_exit_to_host(HOST_CALL_EXIT_FAILED_CMD);
+
+	/* Should not return. */
+	return false;
+}
+
 /*
  * This is the entry function for Realm payload, it first requests the shared buffer
  * IPA address from Host using HOST_CALL/RSI, it reads the command to be executed,
@@ -141,6 +208,7 @@
 {
 	bool test_succeed = false;
 
+	register_custom_sync_exception_handler(realm_exception_handler);
 	realm_set_shared_structure((host_shared_data_t *)rsi_get_ns_buffer());
 	if (realm_get_my_shared_structure() != NULL) {
 		uint8_t cmd = realm_shared_data_get_my_realm_cmd();
@@ -156,9 +224,16 @@
 			break;
 		case REALM_MULTIPLE_REC_PSCI_DENIED_CMD:
 			test_succeed = test_realm_multiple_rec_psci_denied_cmd();
+			break;
 		case REALM_MULTIPLE_REC_MULTIPLE_CPU_CMD:
 			test_succeed = test_realm_multiple_rec_multiple_cpu_cmd();
 			break;
+		case REALM_INSTR_FETCH_CMD:
+			test_succeed = test_realm_instr_fetch_cmd();
+			break;
+		case REALM_DATA_ACCESS_CMD:
+			test_succeed = test_realm_data_access_cmd();
+			break;
 		case REALM_PAUTH_SET_CMD:
 			test_succeed = test_realm_pauth_set_cmd();
 			break;
@@ -168,6 +243,9 @@
 		case REALM_PAUTH_FAULT:
 			test_succeed = test_realm_pauth_fault();
 			break;
+		case REALM_DIT_CHECK_CMD:
+			test_succeed = test_realm_dit_check_cmd();
+			break;
 		case REALM_GET_RSI_VERSION:
 			test_succeed = realm_get_rsi_version();
 			break;
diff --git a/smc_fuzz/dts/sdei.dts b/smc_fuzz/dts/sdei.dts
index 2418916..a8199e1 100644
--- a/smc_fuzz/dts/sdei.dts
+++ b/smc_fuzz/dts/sdei.dts
@@ -15,31 +15,31 @@
 		bias = <30>;
 		sdei_version {
 			bias = <30>;
-			functionname = "sdei_version";
+			functionname = "sdei_version_funcid";
 		};
 		sdei_pe_unmask {
 			bias = <30>;
-			functionname = "sdei_pe_unmask";
+			functionname = "sdei_pe_unmask_funcid";
 		};
 		sdei_pe_mask {
 			bias = <30>;
-			functionname = "sdei_pe_mask";
+			functionname = "sdei_pe_mask_funcid";
 		};
 		sdei_event_status {
 			bias = <30>;
-			functionname = "sdei_event_status";
+			functionname = "sdei_event_status_funcid";
 		};
 		sdei_event_signal {
 			bias = <30>;
-			functionname = "sdei_event_signal";
+			functionname = "sdei_event_signal_funcid";
 		};
 		sdei_private_reset {
 			bias = <30>;
-			functionname = "sdei_private_reset";
+			functionname = "sdei_private_reset_funcid";
 		};
 		sdei_shared_reset {
 			bias = <30>;
-			functionname = "sdei_shared_reset";
+			functionname = "sdei_shared_reset_funcid";
 		};
 	};
 
diff --git a/smc_fuzz/dts/top.dts b/smc_fuzz/dts/top.dts
index bda77d6..4d37c7e 100644
--- a/smc_fuzz/dts/top.dts
+++ b/smc_fuzz/dts/top.dts
@@ -20,50 +20,50 @@
 		bias = <30>;
 		sdei_version {
 			bias = <30>;
-			functionname = "sdei_version";
+			functionname = "sdei_version_funcid";
 		};
 		sdei_pe_unmask {
 			bias = <30>;
-			functionname = "sdei_pe_unmask";
+			functionname = "sdei_pe_unmask_funcid";
 		};
 		sdei_pe_mask {
 			bias = <30>;
-			functionname = "sdei_pe_mask";
+			functionname = "sdei_pe_mask_funcid";
 		};
 		sdei_event_status {
 			bias = <30>;
-			functionname = "sdei_event_status";
+			functionname = "sdei_event_status_funcid";
 		};
 		sdei_event_signal {
 			bias = <30>;
-			functionname = "sdei_event_signal";
+			functionname = "sdei_event_signal_funcid";
 		};
 		sdei_private_reset {
 			bias = <30>;
-			functionname = "sdei_private_reset";
+			functionname = "sdei_private_reset_funcid";
 		};
 		sdei_shared_reset {
 			bias = <30>;
-			functionname = "sdei_shared_reset";
+			functionname = "sdei_shared_reset_funcid";
 		};
 	};
 	tsp {
 		bias = <30>;
 		tsp_add_op {
 			bias = <30>;
-			functionname = "tsp_add_op";
+			functionname = "tsp_add_op_funcid";
 		};
 		tsp_sub_op {
 			bias = <30>;
-			functionname = "tsp_sub_op";
+			functionname = "tsp_sub_op_funcid";
 		};
 		tsp_mul_op {
 			bias = <30>;
-			functionname = "tsp_mul_op";
+			functionname = "tsp_mul_op_funcid";
 		};
 		tsp_div_op {
 			bias = <30>;
-			functionname = "tsp_div_op";
+			functionname = "tsp_div_op_funcid";
 		};
 	};
 };
diff --git a/smc_fuzz/include/fifo3d.h b/smc_fuzz/include/fifo3d.h
index c04567c..95ebb4a 100644
--- a/smc_fuzz/include/fifo3d.h
+++ b/smc_fuzz/include/fifo3d.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -18,22 +18,28 @@
 	char ***nnfifo;
 	char ***fnamefifo;
 	int **biasfifo;
+	int **fidfifo;
 	int col;
 	int curr_col;
 	int *row;
 };
 
 /*
- * Push function name string into raw data structure
+ * Push function name string into the raw data structure
  */
 void push_3dfifo_fname(struct fifo3d *f3d, char *fname);
 
 /*
- * Push bias value into raw data structure
+ * Push bias value into the raw data structure
  */
 void push_3dfifo_bias(struct fifo3d *f3d, int bias);
 
 /*
+ * Push id for function value into the raw data structure
+ */
+void push_3dfifo_fid(struct fifo3d *f3d, int id);
+
+/*
  * Create new column and/or row for raw data structure for newly
  * found node from device tree
  */
diff --git a/smc_fuzz/include/nfifo.h b/smc_fuzz/include/nfifo.h
new file mode 100644
index 0000000..cef07da
--- /dev/null
+++ b/smc_fuzz/include/nfifo.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+#ifndef NFIFO_H
+#define NFIFO_H
+
+#define CMP_SUCCESS 0
+#define NFIFO_Q_THRESHOLD 10
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "smcmalloc.h"
+
+struct nfifo {
+	char **lnme;
+	int nent;
+	int thent;
+};
+
+void nfifoinit(struct nfifo *nf, struct memmod *mmod);
+void pushnme(char *nme, struct nfifo *nf, struct memmod *mmod);
+char *readnme(int ent, struct nfifo *nf, struct memmod *mmod);
+int searchnme(char *nme, struct nfifo *nf, struct memmod *mmod);
+void printent(struct nfifo *nf);
+
+#endif /* NFIFO_H */
diff --git a/smc_fuzz/include/sdei_fuzz_helper.h b/smc_fuzz/include/sdei_fuzz_helper.h
index 71d462d..cf4ddd1 100644
--- a/smc_fuzz/include/sdei_fuzz_helper.h
+++ b/smc_fuzz/include/sdei_fuzz_helper.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,6 +11,29 @@
 #include <tftf_lib.h>
 #include <timer.h>
 
-void tftf_test_sdei_noarg(int64_t (*sdei_func)(void), char *);
+#ifndef sdei_version_funcid
+#define sdei_version_funcid 0
+#endif
+#ifndef sdei_pe_unmask_funcid
+#define sdei_pe_unmask_funcid 0
+#endif
+#ifndef sdei_pe_mask_funcid
+#define sdei_pe_mask_funcid 0
+#endif
+#ifndef sdei_event_status_funcid
+#define sdei_event_status_funcid 0
+#endif
+#ifndef sdei_event_signal_funcid
+#define sdei_event_signal_funcid 0
+#endif
+#ifndef sdei_private_reset_funcid
+#define sdei_private_reset_funcid 0
+#endif
+#ifndef sdei_shared_reset_funcid
+#define sdei_shared_reset_funcid 0
+#endif
+
+
+void tftf_test_sdei_noarg(int64_t (*sdei_func)(void), char *funcstr);
 void tftf_test_sdei_singlearg(int64_t (*sdei_func)(uint64_t), char *funcstr);
-void run_sdei_fuzz(char *);
+void run_sdei_fuzz(int funcid);
diff --git a/smc_fuzz/include/smcmalloc.h b/smc_fuzz/include/smcmalloc.h
index 129e07c..fe134bf 100644
--- a/smc_fuzz/include/smcmalloc.h
+++ b/smc_fuzz/include/smcmalloc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,7 +11,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include "fifo3d.h"
 
 #define TOTALMEMORYSIZE (0x10000)
 #define BLKSPACEDIV (4)
diff --git a/smc_fuzz/include/tsp_fuzz_helper.h b/smc_fuzz/include/tsp_fuzz_helper.h
index 444d54b..019ee68 100644
--- a/smc_fuzz/include/tsp_fuzz_helper.h
+++ b/smc_fuzz/include/tsp_fuzz_helper.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,5 +11,18 @@
 #include <tftf_lib.h>
 #include <timer.h>
 
-void tftf_test_tsp_smc(uint64_t tsp_id, char *);
-void run_tsp_fuzz(char *);
+#ifndef tsp_add_op_funcid
+#define tsp_add_op_funcid 0
+#endif
+#ifndef tsp_sub_op_funcid
+#define tsp_sub_op_funcid 0
+#endif
+#ifndef tsp_mul_op_funcid
+#define tsp_mul_op_funcid 0
+#endif
+#ifndef tsp_div_op_funcid
+#define tsp_div_op_funcid 0
+#endif
+
+void tftf_test_tsp_smc(uint64_t tsp_id, char *funcstr);
+void run_tsp_fuzz(int funcid);
diff --git a/smc_fuzz/src/fifo3d.c b/smc_fuzz/src/fifo3d.c
index 119b26c..0b99907 100644
--- a/smc_fuzz/src/fifo3d.c
+++ b/smc_fuzz/src/fifo3d.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -27,7 +27,7 @@
 #endif
 
 /*
- * Push function name string into raw data structure
+ * Push function name string into the data structure from device tree file
  */
 void push_3dfifo_fname(struct fifo3d *f3d, char *fname)
 {
@@ -36,7 +36,7 @@
 }
 
 /*
- * Push bias value into raw data structure
+ * Push bias value into data structure from device tree file
  */
 void push_3dfifo_bias(struct fifo3d *f3d, int bias)
 {
@@ -44,14 +44,36 @@
 }
 
 /*
+ * Push function id value into data structure from device tree file
+ */
+void push_3dfifo_fid(struct fifo3d *f3d, int id)
+{
+	f3d->fidfifo[f3d->col - 1][f3d->row[f3d->col - 1] - 1] = id;
+}
+
+
+/*
  * Create new column and/or row for raw data structure for newly
- * found node from device tree
+ * found node from device tree.  The fifo has four elements that reflect
+ * values obtained from the device tree for each node read.  This preserves
+ * the hierarchy found in that file so it can be utilized in construction of
+ * the smc nodes structure for final use in randomly calling the SMC functions.
+ * This is essentially a bias tree in final form.
  */
 void push_3dfifo_col(struct fifo3d *f3d, char *entry, struct memmod *mmod)
 {
+
+/*
+ * four elements required:
+ * 1. node name as a string
+ * 2. function name as a string
+ * 3. bias value as an integer
+ * 4. id value as an integer
+ */
 	char ***tnnfifo;
 	char ***tfnamefifo;
 	int **tbiasfifo;
+	int **tfidfifo;
 
 	if (f3d->col == f3d->curr_col) {
 		f3d->col++;
@@ -76,15 +98,17 @@
 		f3d->row[f3d->col - 1] = 1;
 
 		/*
-		 * Create new raw data memory
+		 * Start node creation for reading of device tree file
 		 */
 		tnnfifo = GENMALLOC(f3d->col * sizeof(char **));
 		tfnamefifo = GENMALLOC(f3d->col * sizeof(char **));
 		tbiasfifo = GENMALLOC((f3d->col) * sizeof(int *));
+		tfidfifo = GENMALLOC((f3d->col) * sizeof(int *));
 		for (unsigned int i = 0U; (int)i < f3d->col; i++) {
 			tnnfifo[i] = GENMALLOC(f3d->row[i] * sizeof(char *));
 			tfnamefifo[i] = GENMALLOC(f3d->row[i] * sizeof(char *));
 			tbiasfifo[i] = GENMALLOC((f3d->row[i]) * sizeof(int));
+			tfidfifo[i] = GENMALLOC((f3d->row[i]) * sizeof(int));
 			for (unsigned int j = 0U; (int)j < f3d->row[i]; j++) {
 				tnnfifo[i][j] = GENMALLOC(1 * sizeof(char[MAX_NAME_CHARS]));
 				tfnamefifo[i][j] =
@@ -95,6 +119,7 @@
 					strlcpy(tfnamefifo[i][j],
 						f3d->fnamefifo[i][j], MAX_NAME_CHARS);
 					tbiasfifo[i][j] = f3d->biasfifo[i][j];
+					tfidfifo[i][j] = f3d->fidfifo[i][j];
 				}
 			}
 		}
@@ -107,6 +132,7 @@
 		strlcpy(tfnamefifo[f3d->col - 1][f3d->row[f3d->col - 1] - 1],
 			"none", MAX_NAME_CHARS);
 		tbiasfifo[f3d->col - 1][f3d->row[f3d->col - 1] - 1] = 0;
+		tfidfifo[f3d->col - 1][f3d->row[f3d->col - 1] - 1] = 0;
 
 		/*
 		 * Free the old raw data structres
@@ -119,11 +145,13 @@
 			GENFREE(f3d->nnfifo[i]);
 			GENFREE(f3d->fnamefifo[i]);
 			GENFREE(f3d->biasfifo[i]);
+			GENFREE(f3d->fidfifo[i]);
 		}
 		if (f3d->col > 1) {
 			GENFREE(f3d->nnfifo);
 			GENFREE(f3d->fnamefifo);
 			GENFREE(f3d->biasfifo);
+			GENFREE(f3d->fidfifo);
 		}
 
 		/*
@@ -132,6 +160,7 @@
 		f3d->nnfifo = tnnfifo;
 		f3d->fnamefifo = tfnamefifo;
 		f3d->biasfifo = tbiasfifo;
+		f3d->fidfifo = tfidfifo;
 	}
 	if (f3d->col != f3d->curr_col) {
 		/*
@@ -141,15 +170,17 @@
 		f3d->row[f3d->col - 1]++;
 
 		/*
-		 * Create new raw data memory
+		 * Create new node form device tree file
 		 */
 		tnnfifo = GENMALLOC(f3d->col * sizeof(char **));
 		tfnamefifo = GENMALLOC(f3d->col * sizeof(char **));
 		tbiasfifo = GENMALLOC((f3d->col) * sizeof(int *));
+		tfidfifo = GENMALLOC((f3d->col) * sizeof(int *));
 		for (unsigned int i = 0U; (int)i < f3d->col; i++) {
 			tnnfifo[i] = GENMALLOC(f3d->row[i] * sizeof(char *));
 			tfnamefifo[i] = GENMALLOC(f3d->row[i] * sizeof(char *));
 			tbiasfifo[i] = GENMALLOC((f3d->row[i]) * sizeof(int));
+			tfidfifo[i] = GENMALLOC((f3d->row[i]) * sizeof(int));
 			for (unsigned int j = 0U; (int)j < f3d->row[i]; j++) {
 				tnnfifo[i][j] = GENMALLOC(1 * sizeof(char[MAX_NAME_CHARS]));
 				tfnamefifo[i][j] =
@@ -160,6 +191,7 @@
 					strlcpy(tfnamefifo[i][j],
 						f3d->fnamefifo[i][j], MAX_NAME_CHARS);
 					tbiasfifo[i][j] = f3d->biasfifo[i][j];
+					tfidfifo[i][j] = f3d->fidfifo[i][j];
 				}
 			}
 		}
@@ -172,6 +204,7 @@
 		strlcpy(tfnamefifo[f3d->col - 1][f3d->row[f3d->col - 1] - 1],
 			"none", MAX_NAME_CHARS);
 		tbiasfifo[f3d->col - 1][f3d->row[f3d->col - 1] - 1] = 0;
+		tfidfifo[f3d->col - 1][f3d->row[f3d->col - 1] - 1] = 0;
 
 		/*
 		 * Free the old raw data structres
@@ -187,10 +220,12 @@
 			GENFREE(f3d->nnfifo[i]);
 			GENFREE(f3d->fnamefifo[i]);
 			GENFREE(f3d->biasfifo[i]);
+			GENFREE(f3d->fidfifo[i]);
 		}
 		GENFREE(f3d->nnfifo);
 		GENFREE(f3d->fnamefifo);
 		GENFREE(f3d->biasfifo);
+		GENFREE(f3d->fidfifo);
 
 		/*
 		 * Point to new data
@@ -198,5 +233,6 @@
 		f3d->nnfifo = tnnfifo;
 		f3d->fnamefifo = tfnamefifo;
 		f3d->biasfifo = tbiasfifo;
+		f3d->fidfifo = tfidfifo;
 	}
 }
diff --git a/smc_fuzz/src/nfifo.c b/smc_fuzz/src/nfifo.c
new file mode 100644
index 0000000..b4a021c
--- /dev/null
+++ b/smc_fuzz/src/nfifo.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * FIFO for matching strings to integers
+ */
+
+#include "nfifo.h"
+
+#ifdef SMC_FUZZ_TMALLOC
+#define GENMALLOC(x)	malloc((x))
+#define GENFREE(x)	free((x))
+#else
+#define GENMALLOC(x)	smcmalloc((x), mmod)
+#define GENFREE(x)	smcfree((x), mmod)
+#endif
+
+/*
+ * Initialization of FIFO
+ */
+void nfifoinit(struct nfifo *nf, struct memmod *mmod)
+{
+	nf->nent = 0;
+	nf->thent = NFIFO_Q_THRESHOLD;
+	nf->lnme = GENMALLOC(nf->thent * sizeof(char *));
+}
+
+/*
+ * push string to FIFO for automatic numerical assignment
+ */
+void pushnme(char *nme, struct nfifo *nf, struct memmod *mmod)
+{
+	char **tnme;
+
+	if (searchnme(nme, nf, mmod) == -1) {
+		if (nf->nent >= nf->thent) {
+			nf->thent += NFIFO_Q_THRESHOLD;
+			tnme = GENMALLOC(nf->thent * sizeof(char *));
+			for (unsigned int x = 0; x < nf->nent; x++) {
+				tnme[x] = GENMALLOC(1 * sizeof(char[MAX_NAME_CHARS]));
+				strlcpy(tnme[x], nf->lnme[x], MAX_NAME_CHARS);
+			}
+			tnme[nf->nent] = GENMALLOC(1 * sizeof(char[MAX_NAME_CHARS]));
+			strlcpy(tnme[nf->nent], nme, MAX_NAME_CHARS);
+			for (unsigned int x = 0; x < nf->nent; x++) {
+				GENFREE(nf->lnme[x]);
+			}
+			GENFREE(nf->lnme);
+			nf->lnme = tnme;
+		} else {
+			nf->lnme[nf->nent] = GENMALLOC(1 * sizeof(char[MAX_NAME_CHARS]));
+			strlcpy(nf->lnme[nf->nent], nme, MAX_NAME_CHARS);
+		}
+		nf->nent++;
+	}
+}
+
+/*
+ * Find name associated with numercal designation
+ */
+char *readnme(int ent, struct nfifo *nf, struct memmod *mmod)
+{
+	return nf->lnme[ent];
+}
+
+/*
+ * Search FIFO for integer given an input string returns -1
+ * if not found
+ */
+int searchnme(char *nme, struct nfifo *nf, struct memmod *mmod)
+{
+	for (unsigned int x = 0; x < nf->nent; x++) {
+		if (strcmp(nf->lnme[x], nme) == CMP_SUCCESS) {
+			return (x + 1);
+		}
+	}
+	return -1;
+}
+
+/*
+ * Print of all elements of FIFO string and associated integer
+ */
+void printent(struct nfifo *nf)
+{
+	for (unsigned int x = 0; x < nf->nent; x++) {
+		printf("nfifo entry %s has value %d\n", nf->lnme[x], x);
+	}
+}
diff --git a/smc_fuzz/src/randsmcmod.c b/smc_fuzz/src/randsmcmod.c
index 7bedf81..a86feb6 100644
--- a/smc_fuzz/src/randsmcmod.c
+++ b/smc_fuzz/src/randsmcmod.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,6 +9,7 @@
 #include <drivers/arm/private_timer.h>
 #include <events.h>
 #include "fifo3d.h"
+#include "nfifo.h"
 #include <libfdt.h>
 
 #include <plat_topology.h>
@@ -16,7 +17,7 @@
 #include <tftf_lib.h>
 
 extern char _binary___dtb_start[];
-extern void runtestfunction(char *funcstr);
+extern void runtestfunction(int funcid);
 
 struct memmod tmod __aligned(65536) __section("smcfuzz");
 static int cntndarray;
@@ -119,13 +120,14 @@
 	int *biases;				 // Biases of the individual nodes
 	int *biasarray;				 // Array of biases across all nodes
 	char **snames;				 // String that is unique to the SMC call called in test
+	int *snameid;				 // ID that is unique to the SMC call called in test
 	struct rand_smc_node *treenodes;	 // Selection of nodes that are farther down in the tree
-						// that reference further rand_smc_node objects
+						 // that reference further rand_smc_node objects
 	int *norcall;				// Specifies whether a particular node is a leaf node or tree node
-	int entries;				// Number of nodes in object
-	int biasent;				// Number that gives the total number of entries in biasarray
-						// based on all biases of the nodes
-	char **nname;				// Array of node names
+	int entries;				 // Number of nodes in object
+	int biasent;				 // Number that gives the total number of entries in biasarray
+						 // based on all biases of the nodes
+	char **nname;				 // Array of node names
 };
 
 
@@ -156,6 +158,9 @@
 	int cntndarray;
 	struct rand_smc_node nrnode;
 	struct rand_smc_node *tndarray;
+	struct nfifo nf;
+
+	nfifoinit(&nf, mmod);
 
 	f3d.col = 0;
 	f3d.curr_col = 0;
@@ -166,9 +171,6 @@
 
 	fhdptr = (struct fdt_header *)_binary___dtb_start;
 
-	if (fdt_check_header((void *)fhdptr) != 0) {
-		printf("ERROR, not device tree compliant\n");
-	}
 	fhd = *fhdptr;
 	cntndarray = 0;
 	nrnode.entries = 0;
@@ -244,6 +246,8 @@
 			if (strcmp(cset, "functionname") == 0) {
 				pullstringdt(&dtb, dtb_beg, 0, cset);
 				push_3dfifo_fname(&f3d, cset);
+				pushnme(cset, &nf, mmod);
+				push_3dfifo_fid(&f3d, searchnme(cset, &nf, mmod));
 				leafnode = 1;
 				if (bias_count == 0U) {
 					bintnode = 1U;
@@ -279,6 +283,7 @@
 				for (unsigned int j = 0U; (int)j < cntndarray; j++) {
 					tndarray[j].biases = GENMALLOC(ndarray[j].entries * sizeof(int));
 					tndarray[j].snames = GENMALLOC(ndarray[j].entries * sizeof(char *));
+					tndarray[j].snameid = GENMALLOC(ndarray[j].entries * sizeof(int));
 					tndarray[j].norcall = GENMALLOC(ndarray[j].entries * sizeof(int));
 					tndarray[j].nname = GENMALLOC(ndarray[j].entries * sizeof(char *));
 					tndarray[j].treenodes = GENMALLOC(ndarray[j].entries * sizeof(struct rand_smc_node));
@@ -286,6 +291,7 @@
 					for (unsigned int i = 0U; (int)i < ndarray[j].entries; i++) {
 						tndarray[j].snames[i] = GENMALLOC(1 * sizeof(char[MAX_NAME_CHARS]));
 						strlcpy(tndarray[j].snames[i], ndarray[j].snames[i], MAX_NAME_CHARS);
+						tndarray[j].snameid[i] = ndarray[j].snameid[i];
 						tndarray[j].nname[i] = GENMALLOC(1 * sizeof(char[MAX_NAME_CHARS]));
 						strlcpy(tndarray[j].nname[i], ndarray[j].nname[i], MAX_NAME_CHARS);
 						tndarray[j].biases[i] = ndarray[j].biases[i];
@@ -303,6 +309,7 @@
 				}
 				tndarray[cntndarray].biases = GENMALLOC(f3d.row[f3d.col + 1] * sizeof(int));
 				tndarray[cntndarray].snames = GENMALLOC(f3d.row[f3d.col + 1] * sizeof(char *));
+				tndarray[cntndarray].snameid = GENMALLOC(f3d.row[f3d.col + 1] * sizeof(int));
 				tndarray[cntndarray].norcall = GENMALLOC(f3d.row[f3d.col + 1] * sizeof(int));
 				tndarray[cntndarray].nname = GENMALLOC(f3d.row[f3d.col + 1] * sizeof(char *));
 				tndarray[cntndarray].treenodes = GENMALLOC(f3d.row[f3d.col + 1] * sizeof(struct rand_smc_node));
@@ -313,9 +320,11 @@
 				 */
 				int cntbias = 0;
 				int bias_count = 0;
+
 				for (unsigned int j = 0U; (int)j < f3d.row[f3d.col + 1]; j++) {
 					tndarray[cntndarray].snames[j] = GENMALLOC(1 * sizeof(char[MAX_NAME_CHARS]));
 					strlcpy(tndarray[cntndarray].snames[j], f3d.fnamefifo[f3d.col + 1][j], MAX_NAME_CHARS);
+					tndarray[cntndarray].snameid[j] = f3d.fidfifo[f3d.col + 1][j];
 					tndarray[cntndarray].nname[j] = GENMALLOC(1 * sizeof(char[MAX_NAME_CHARS]));
 					strlcpy(tndarray[cntndarray].nname[j], f3d.nnfifo[f3d.col + 1][j], MAX_NAME_CHARS);
 					tndarray[cntndarray].biases[j] = f3d.biasfifo[f3d.col + 1][j];
@@ -355,6 +364,7 @@
 						GENFREE(ndarray[j].norcall);
 						GENFREE(ndarray[j].biasarray);
 						GENFREE(ndarray[j].snames);
+						GENFREE(ndarray[j].snameid);
 						GENFREE(ndarray[j].nname);
 						GENFREE(ndarray[j].treenodes);
 					}
@@ -377,6 +387,7 @@
 				GENFREE(f3d.nnfifo[f3d.col + 1]);
 				GENFREE(f3d.fnamefifo[f3d.col + 1]);
 				GENFREE(f3d.biasfifo[f3d.col + 1]);
+				GENFREE(f3d.fidfifo[f3d.col + 1]);
 				f3d.curr_col -= 1;
 			}
 		}
@@ -393,16 +404,17 @@
 				GENFREE(f3d.nnfifo[i]);
 				GENFREE(f3d.fnamefifo[i]);
 				GENFREE(f3d.biasfifo[i]);
+				GENFREE(f3d.fidfifo[i]);
 			}
 			GENFREE(f3d.nnfifo);
 			GENFREE(f3d.fnamefifo);
 			GENFREE(f3d.biasfifo);
+			GENFREE(f3d.fidfifo);
 			GENFREE(f3d.row);
 			dtdone = 1;
 		}
 	}
 
-
 	*casz = cntndarray;
 	return ndarray;
 }
@@ -445,9 +457,6 @@
 	return TEST_RESULT_SUCCESS;
 }
 
-/*
- * Declaration of single fuzzing instance(seed based)
- */
 test_result_t smc_fuzzing_instance(uint32_t seed)
 {
 	struct rand_smc_node *tlnode;
@@ -479,11 +488,13 @@
 	for (unsigned int i = 0U; i < SMC_FUZZ_CALLS_PER_INSTANCE; i++) {
 		tlnode = &ndarray[cntndarray - 1];
 		int nd = 0;
+
 		while (nd == 0) {
 			int nch = rand()%tlnode->biasent;
 			int selent = tlnode->biasarray[nch];
+
 			if (tlnode->norcall[selent] == 0) {
-				runtestfunction(tlnode->snames[selent]);
+				runtestfunction(tlnode->snameid[selent]);
 				nd = 1;
 			} else {
 				tlnode = &tlnode->treenodes[selent];
@@ -493,9 +504,6 @@
 	return TEST_RESULT_SUCCESS;
 }
 
-/*
- * free memory after fuzzing is complete
- */
 test_result_t smc_fuzzing_deinit(void)
 {
 	/*
@@ -511,6 +519,7 @@
 			GENFREE(ndarray[j].norcall);
 			GENFREE(ndarray[j].biasarray);
 			GENFREE(ndarray[j].snames);
+			GENFREE(ndarray[j].snameid);
 			GENFREE(ndarray[j].nname);
 			GENFREE(ndarray[j].treenodes);
 		}
@@ -521,7 +530,7 @@
 }
 
 /*
- * Execute fuzzing module
+ * Top of SMC fuzzing module
  */
 test_result_t smc_fuzzer_execute(void)
 {
@@ -576,14 +585,11 @@
 	return result;
 }
 
-/*
- * Top level of fuzzing module
- */
 test_result_t smc_fuzzing_top(void)
 {
 	test_result_t result = TEST_RESULT_SUCCESS;
-
 	init_smc_fuzzing();
+
 #ifdef MULTI_CPU_SMC_FUZZER
 	u_register_t lead_mpid, target_mpid;
 	int cpu_node;
diff --git a/smc_fuzz/src/runtestfunction_helpers.c b/smc_fuzz/src/runtestfunction_helpers.c
index b9fa794..c3b2cca 100644
--- a/smc_fuzz/src/runtestfunction_helpers.c
+++ b/smc_fuzz/src/runtestfunction_helpers.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,8 +11,8 @@
 /*
  * Invoke the SMC call based on the function name specified.
  */
-void runtestfunction(char *funcstr)
+void runtestfunction(int funcid)
 {
-	run_sdei_fuzz(funcstr);
-	run_tsp_fuzz(funcstr);
+	run_sdei_fuzz(funcid);
+	run_tsp_fuzz(funcid);
 }
diff --git a/smc_fuzz/src/sdei_fuzz_helper.c b/smc_fuzz/src/sdei_fuzz_helper.c
index cb634dc..1d22335 100644
--- a/smc_fuzz/src/sdei_fuzz_helper.c
+++ b/smc_fuzz/src/sdei_fuzz_helper.c
@@ -1,11 +1,15 @@
 /*
- * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <fuzz_names.h>
 #include <sdei_fuzz_helper.h>
 
+/*
+ * SDEI function that has no arguments
+ */
 void tftf_test_sdei_noarg(int64_t (*sdei_func)(void), char *funcstr)
 {
 		int64_t ret = (*sdei_func)();
@@ -15,6 +19,9 @@
 		}
 }
 
+/*
+ * SDEI function that has single argument
+ */
 void tftf_test_sdei_singlearg(int64_t (*sdei_func)(uint64_t), char *funcstr)
 {
 		int64_t ret = (*sdei_func)(0);
@@ -24,28 +31,30 @@
 		}
 }
 
-
-void run_sdei_fuzz(char *funcstr)
+/*
+ * SDEI function called from fuzzer
+ */
+void run_sdei_fuzz(int funcid)
 {
-	if (strcmp(funcstr, "sdei_version") == CMP_SUCCESS) {
+	if (funcid == sdei_version_funcid) {
 		long long ret = sdei_version();
 
 		if (ret != MAKE_SDEI_VERSION(1, 0, 0)) {
 			tftf_testcase_printf("Unexpected SDEI version: 0x%llx\n",
 					     ret);
 		}
-	} else if (strcmp(funcstr, "sdei_pe_unmask") == CMP_SUCCESS) {
-		tftf_test_sdei_noarg(sdei_pe_unmask, "sdei_pe_unmask");
-	} else if (strcmp(funcstr, "sdei_pe_mask") == CMP_SUCCESS) {
+	} else if (funcid == sdei_pe_unmask_funcid) {
+		tftf_test_sdei_noarg(sdei_pe_unmask, "sdei_pe_unmuask");
+	} else if (funcid == sdei_pe_mask_funcid) {
 		tftf_test_sdei_noarg(sdei_pe_mask, "sdei_pe_mask");
-	} else if (strcmp(funcstr, "sdei_event_status") == CMP_SUCCESS) {
+	} else if (funcid == sdei_event_status_funcid) {
 		tftf_test_sdei_singlearg((int64_t (*)(uint64_t))sdei_event_status,
 		"sdei_event_status");
-	} else if (strcmp(funcstr, "sdei_event_signal") == CMP_SUCCESS) {
+	} else if (funcid == sdei_event_signal_funcid) {
 		tftf_test_sdei_singlearg(sdei_event_signal, "sdei_event_signal");
-	} else if (strcmp(funcstr, "sdei_private_reset") == CMP_SUCCESS) {
+	} else if (funcid == sdei_private_reset_funcid) {
 		tftf_test_sdei_noarg(sdei_private_reset, "sdei_private_reset");
-	} else if (strcmp(funcstr, "sdei_shared_reset") == CMP_SUCCESS) {
+	} else if (funcid == sdei_shared_reset_funcid) {
 		tftf_test_sdei_noarg(sdei_shared_reset, "sdei_shared_reset");
 	}
 }
diff --git a/smc_fuzz/src/tsp_fuzz_helper.c b/smc_fuzz/src/tsp_fuzz_helper.c
index c6ed219..610fae0 100644
--- a/smc_fuzz/src/tsp_fuzz_helper.c
+++ b/smc_fuzz/src/tsp_fuzz_helper.c
@@ -1,10 +1,14 @@
 /*
- * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
+#include <fuzz_names.h>
 #include <tsp_fuzz_helper.h>
 
+/*
+ * Generic TSP based function call for math operations
+ */
 void tftf_test_tsp_smc(uint64_t tsp_id, char *funcstr)
 {
 		uint64_t fn_identifier = TSP_FAST_FID(tsp_id);
@@ -22,15 +26,18 @@
 		}
 }
 
-void run_tsp_fuzz(char *funcstr)
+/*
+ * TSP function called from fuzzer
+ */
+void run_tsp_fuzz(int funcid)
 {
-	if (strcmp(funcstr, "tsp_add_op") == CMP_SUCCESS) {
+	if (funcid == tsp_add_op_funcid) {
 		tftf_test_tsp_smc(TSP_ADD, "tsp_add_op");
-	} else if (strcmp(funcstr, "tsp_sub_op") == CMP_SUCCESS) {
+	} else if (funcid == tsp_sub_op_funcid) {
 		tftf_test_tsp_smc(TSP_SUB, "tsp_sub_op");
-	} else if (strcmp(funcstr, "tsp_mul_op") == CMP_SUCCESS) {
+	} else if (funcid == tsp_mul_op_funcid) {
 		tftf_test_tsp_smc(TSP_MUL, "tsp_mul_op");
-	} else if (strcmp(funcstr, "tsp_div_op") == CMP_SUCCESS) {
+	} else if (funcid == tsp_div_op_funcid) {
 		tftf_test_tsp_smc(TSP_DIV, "tsp_div_op");
 	}
 }
diff --git a/spm/cactus/cactus.mk b/spm/cactus/cactus.mk
index be8997e..4e86e3d 100644
--- a/spm/cactus/cactus.mk
+++ b/spm/cactus/cactus.mk
@@ -49,7 +49,7 @@
 	)						\
 	$(addprefix spm/cactus/cactus_tests/,		\
 		cactus_message_loop.c			\
-		cactus_test_cpu_features.c		\
+		cactus_test_simd.c		\
 		cactus_test_direct_messaging.c		\
 		cactus_test_interrupts.c		\
 		cactus_test_memory_sharing.c		\
diff --git a/spm/cactus/cactus_main.c b/spm/cactus/cactus_main.c
index 19a89f5..b3f7451 100644
--- a/spm/cactus/cactus_main.c
+++ b/spm/cactus/cactus_main.c
@@ -115,6 +115,10 @@
 	/* scratch memory allocated to be used for running SMMU tests */
 	MAP_REGION_FLAT(PLAT_CACTUS_MEMCPY_BASE, PLAT_CACTUS_MEMCPY_RANGE,
 			MT_MEMORY | MT_RW),
+#if PLAT_fvp
+	MAP_REGION_FLAT(PLAT_CACTUS_NS_MEMCPY_BASE, PLAT_CACTUS_MEMCPY_RANGE,
+			MT_MEMORY | MT_RW | MT_NS),
+#endif
 	{0}
 };
 
@@ -286,22 +290,16 @@
 		goto msg_loop;
 	}
 
-	if (ffa_id == SPM_VM_ID_FIRST) {
-		console_init(CACTUS_PL011_UART_BASE,
-			     CACTUS_PL011_UART_CLK_IN_HZ,
-			     PL011_BAUDRATE);
-
-		set_putc_impl(PL011_AS_STDOUT);
-
-		cactus_print_boot_info(boot_info_header);
-	} else {
-		set_putc_impl(FFA_SVC_SMC_CALL_AS_STDOUT);
-	}
+	set_putc_impl(FFA_SVC_SMC_CALL_AS_STDOUT);
 
 	/* Below string is monitored by CI expect script. */
 	NOTICE("Booting Secure Partition (ID: %x)\n%s\n%s\n",
 		ffa_id, build_message, version_string);
 
+	if (ffa_id == SP_ID(1)) {
+		cactus_print_boot_info(boot_info_header);
+	}
+
 	if (ffa_id == (SPM_VM_ID_FIRST + 2)) {
 		VERBOSE("Mapping RXTX Region\n");
 		CONFIGURE_AND_MAP_MAILBOX(mb, PAGE_SIZE, ret);
diff --git a/spm/cactus/cactus_tests/cactus_message_loop.c b/spm/cactus/cactus_tests/cactus_message_loop.c
index e56e51e..c0abf2b 100644
--- a/spm/cactus/cactus_tests/cactus_message_loop.c
+++ b/spm/cactus/cactus_tests/cactus_message_loop.c
@@ -11,6 +11,7 @@
 #include <ffa_helpers.h>
 #include <events.h>
 #include <platform.h>
+#include <spm_helpers.h>
 
 /**
  * Counter of the number of handled requests, for each CPU. The number of
@@ -43,9 +44,8 @@
 {
 	uint64_t in_cmd;
 
-	/* Get which core it is running from. */
-	unsigned int core_pos = platform_get_core_pos(
-						read_mpidr_el1() & MPID_MASK);
+	/* Get vCPU index for currently running vCPU. */
+	unsigned int core_pos = spm_get_my_core_pos();
 
 	if (cmd_args == NULL || ret == NULL) {
 		ERROR("Invalid arguments passed to %s!\n", __func__);
diff --git a/spm/cactus/cactus_tests/cactus_test_direct_messaging.c b/spm/cactus/cactus_tests/cactus_test_direct_messaging.c
index 540ef01..fd82f82 100644
--- a/spm/cactus/cactus_tests/cactus_test_direct_messaging.c
+++ b/spm/cactus/cactus_tests/cactus_test_direct_messaging.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -114,3 +114,15 @@
 
 	return base_deadlock_handler(vm_id, source, deadlock_dest, deadlock_next_dest);
 }
+
+CACTUS_CMD_HANDLER(ras_delegate_cmd, CACTUS_RAS_DELEGATE_CMD)
+{
+	uint64_t event_id = cactus_ras_get_event_id(*args);
+
+	INFO("Received RAS cmd at %x, value %llu.\n", ffa_dir_msg_dest(*args),
+						      event_id);
+
+	return cactus_success_resp(ffa_dir_msg_dest(*args),
+				   ffa_dir_msg_source(*args),
+				   event_id);
+}
diff --git a/spm/cactus/cactus_tests/cactus_test_interrupts.c b/spm/cactus/cactus_tests/cactus_test_interrupts.c
index 4250445..2e0249c 100644
--- a/spm/cactus/cactus_tests/cactus_test_interrupts.c
+++ b/spm/cactus/cactus_tests/cactus_test_interrupts.c
@@ -86,8 +86,9 @@
 			/* Received FFA_INTERRUPT in blocked state. */
 			VERBOSE("Processing FFA_INTERRUPT while"
 				" blocked on direct response\n");
-			unsigned int my_core_pos =
-				platform_get_core_pos(read_mpidr_el1());
+
+			/* Get vCPU index for currently running vCPU. */
+			unsigned int my_core_pos = spm_get_my_core_pos();
 
 			ffa_ret = ffa_run(fwd_dest, my_core_pos);
 		} else {
diff --git a/spm/cactus/cactus_tests/cactus_test_memory_sharing.c b/spm/cactus/cactus_tests/cactus_test_memory_sharing.c
index 2fbc63b..4d738b1 100644
--- a/spm/cactus/cactus_tests/cactus_test_memory_sharing.c
+++ b/spm/cactus/cactus_tests/cactus_test_memory_sharing.c
@@ -11,6 +11,8 @@
 #include <ffa_helpers.h>
 #include <sp_helpers.h>
 #include "sp_tests.h"
+#include "spm_common.h"
+#include "stdint.h"
 #include <xlat_tables_defs.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
 #include <sync.h>
@@ -66,11 +68,42 @@
 	return (void *)CACTUS_SP3_NS_MEM_SHARE_BASE;
 }
 
+static bool cactus_mem_unmap_and_relinquish(
+		struct ffa_composite_memory_region *composite,
+		void *send, ffa_memory_handle_t handle, ffa_id_t vm_id)
+{
+	int ret;
+
+	for (uint32_t i = 0; i < composite->constituent_count; i++) {
+		uint64_t base_address = (uint64_t)composite->constituents[i]
+								.address;
+		size_t size = composite->constituents[i].page_count * PAGE_SIZE;
+
+		ret = mmap_remove_dynamic_region(
+			(uint64_t)composite->constituents[i].address,
+			composite->constituents[i].page_count * PAGE_SIZE);
+
+		if (ret != 0) {
+			ERROR("Failed to unmap received memory region %llx "
+			      "size: %lu (error:%d)\n",
+			      base_address, size, ret);
+			return false;
+		}
+	}
+
+	if (!memory_relinquish((struct ffa_mem_relinquish *)send,
+				handle, vm_id)) {
+		return false;
+	}
+
+	return true;
+}
+
 CACTUS_CMD_HANDLER(mem_send_cmd, CACTUS_MEM_SEND_CMD)
 {
 	struct ffa_memory_region *m;
 	struct ffa_composite_memory_region *composite;
-	int ret;
+	int ret = -1;
 	unsigned int mem_attrs;
 	uint32_t *ptr;
 	ffa_id_t source = ffa_dir_msg_source(*args);
@@ -80,13 +113,14 @@
 	ffa_memory_region_flags_t retrv_flags =
 					 cactus_mem_send_get_retrv_flags(*args);
 	uint32_t words_to_write = cactus_mem_send_words_to_write(*args);
+	bool expect_exception = cactus_mem_send_expect_exception(*args);
 
-	struct ffa_memory_access receiver = ffa_memory_access_init_permissions(
+	struct ffa_memory_access receiver = ffa_memory_access_init(
 		vm_id, FFA_DATA_ACCESS_RW,
 		(mem_func == FFA_MEM_SHARE_SMC32)
 			? FFA_INSTRUCTION_ACCESS_NOT_SPECIFIED
 			: FFA_INSTRUCTION_ACCESS_NX,
-		0);
+		0, NULL);
 
 	expect(memory_retrieve(mb, &m, handle, source, &receiver, 1,
 			       retrv_flags),
@@ -94,10 +128,6 @@
 
 	composite = ffa_memory_region_get_composite(m, 0);
 
-	VERBOSE("Address: %p; page_count: %x %x\n",
-		composite->constituents[0].address,
-		composite->constituents[0].page_count, PAGE_SIZE);
-
 	/* This test is only concerned with RW permissions. */
 	if (m->receivers[0].receiver_permissions.permissions.data_access !=
 	    FFA_DATA_ACCESS_RW) {
@@ -111,32 +141,89 @@
 		mem_attrs |= MT_NS;
 	}
 
-	ret = mmap_add_dynamic_region(
-			(uint64_t)composite->constituents[0].address,
-			(uint64_t)composite->constituents[0].address,
-			composite->constituents[0].page_count * PAGE_SIZE,
-			mem_attrs);
+	for (uint32_t i = 0; i < composite->constituent_count; i++) {
+		uint64_t base_address = (uint64_t)composite->constituents[i]
+								.address;
+		size_t size = composite->constituents[i].page_count * PAGE_SIZE;
 
-	if (ret != 0) {
-		ERROR("Failed to map received memory region(%d)!\n", ret);
-		return cactus_error_resp(vm_id, source, CACTUS_ERROR_TEST);
+		ret = mmap_add_dynamic_region(
+			base_address, base_address, size, mem_attrs);
+
+		if (ret != 0) {
+			ERROR("Failed to map received memory region %llx "
+			      "size: %lu (error:%d)\n",
+			      base_address, size, ret);
+			return cactus_error_resp(vm_id,
+						 source,
+						 CACTUS_ERROR_TEST);
+		}
 	}
 
 	VERBOSE("Memory has been mapped\n");
 
-	ptr = (uint32_t *) composite->constituents[0].address;
+	for (uint32_t i = 0; i < composite->constituent_count; i++) {
+		ptr = (uint32_t *) composite->constituents[i].address;
 
-	/* Check that memory has been cleared by the SPMC before using it. */
-	if ((retrv_flags & FFA_MEMORY_REGION_FLAG_CLEAR) != 0U) {
-		VERBOSE("Check if memory has been cleared!\n");
-		for (uint32_t i = 0; i < words_to_write; i++) {
-			if (ptr[i] != 0) {
+		for (uint32_t j = 0; j < words_to_write; j++) {
+
+			/**
+			 * Check that memory has been cleared by the SPMC
+			 * before using it.
+			 */
+			if ((retrv_flags & FFA_MEMORY_REGION_FLAG_CLEAR) != 0U) {
+				VERBOSE("Check if memory has been cleared.\n");
+				if (ptr[j] != 0) {
+					/*
+					 * If it hasn't been cleared, shouldn't
+					 * be used.
+					 */
+					ERROR("Memory NOT cleared!\n");
+					cactus_mem_unmap_and_relinquish(composite,
+							      mb->send,
+							      handle, vm_id);
+					ffa_rx_release();
+					return cactus_error_resp(
+						vm_id, source,
+						CACTUS_ERROR_TEST);
+				}
+			} else {
 				/*
-				 * If it hasn't been cleared, shouldn't be used.
+				 * In RME enabled systems, the memory is expected
+				 * to be scrubbed on PAS updates from S to NS.
+				 * As well, it is likely that the memory
+				 * addresses are shadowed, and the contents are
+				 * not visible accross updates from the
+				 * different address spaces. As such, the SP
+				 * shall not rely on memory content to be
+				 * in any form. FFA_MEM_LEND/FFA_MEM_DONATE are
+				 * thus considered for memory allocation
+				 * purposes.
+				 *
+				 * Expect valid data if:
+				 * - Operation between SPs.
+				 * - Memory sharing from NWd to SP.
 				 */
-				ERROR("Memory should have been cleared!\n");
-				return cactus_error_resp(
-					vm_id, source, CACTUS_ERROR_TEST);
+				if ((mem_func != FFA_MEM_SHARE_SMC32 &&
+				    !IS_SP_ID(m->sender)) ||
+				    expect_exception) {
+					continue;
+				}
+
+				VERBOSE("Check memory contents. Expect %u "
+					"words of %x\n", words_to_write,
+					mem_func + 0xFFA);
+
+				/* SPs writing `mem_func` + 0xFFA. */
+				if (ptr[i] != mem_func + 0xFFA) {
+					ERROR("Memory content NOT as expected!\n");
+					cactus_mem_unmap_and_relinquish(
+						composite, mb->send, handle,
+						vm_id);
+					ffa_rx_release();
+					return cactus_error_resp(
+						vm_id, source,
+						CACTUS_ERROR_TEST);
+				}
 			}
 		}
 	}
@@ -145,9 +232,11 @@
 	register_custom_sync_exception_handler(data_abort_gpf_handler);
 
 	/* Write mem_func to retrieved memory region for validation purposes. */
-	VERBOSE("Writing: %x\n", mem_func);
-	for (unsigned int i = 0U; i < words_to_write; i++) {
-		ptr[i] = mem_func;
+	for (uint32_t i = 0; i < composite->constituent_count; i++) {
+		ptr = (uint32_t *) composite->constituents[i].address;
+		for (uint32_t j = 0; j < words_to_write; j++) {
+			ptr[j] = mem_func + 0xFFA;
+		}
 	}
 
 	unregister_custom_sync_exception_handler();
@@ -156,22 +245,11 @@
 	 * A FFA_MEM_DONATE changes the ownership of the page, as such no
 	 * relinquish is needed.
 	 */
-	if (mem_func != FFA_MEM_DONATE_SMC32) {
-		ret = mmap_remove_dynamic_region(
-			(uint64_t)composite->constituents[0].address,
-			composite->constituents[0].page_count * PAGE_SIZE);
-
-		if (ret != 0) {
-			ERROR("Failed to unmap received memory region(%d)!\n", ret);
-			return cactus_error_resp(vm_id, source,
-						 CACTUS_ERROR_TEST);
-		}
-
-		if (!memory_relinquish((struct ffa_mem_relinquish *)mb->send,
-					m->handle, vm_id)) {
-			return cactus_error_resp(vm_id, source,
-						 CACTUS_ERROR_TEST);
-		}
+	if (mem_func != FFA_MEM_DONATE_SMC32 &&
+	    !cactus_mem_unmap_and_relinquish(composite, mb->send, handle,
+					     vm_id)) {
+		return cactus_error_resp(vm_id, source,
+					 CACTUS_ERROR_TEST);
 	}
 
 	if (ffa_func_id(ffa_rx_release()) != FFA_SUCCESS_SMC32) {
@@ -192,18 +270,19 @@
 	ffa_memory_handle_t handle;
 	ffa_id_t vm_id = ffa_dir_msg_dest(*args);
 	ffa_id_t source = ffa_dir_msg_source(*args);
+	uint32_t *ptr;
 	bool non_secure = cactus_req_mem_send_get_non_secure(*args);
 	void *share_page_addr =
 		non_secure ? share_page_non_secure(vm_id) : share_page(vm_id);
 	unsigned int mem_attrs;
 	int ret;
-
+	const uint32_t words_to_write = 10;
 	struct ffa_memory_access receiver =
 		ffa_memory_access_init_permissions_from_mem_func(receiver_id,
 								 mem_func);
 
 	VERBOSE("%x requested to send memory to %x (func: %x), page: %llx\n",
-		source, receiver, mem_func, (uint64_t)share_page_addr);
+		source, receiver_id, mem_func, (uint64_t)share_page_addr);
 
 	const struct ffa_memory_region_constituent constituents[] = {
 		{share_page_addr, 1, 0}
@@ -232,6 +311,18 @@
 					 CACTUS_ERROR_TEST);
 	}
 
+	/* Write to memory before sharing to SP. */
+	if (IS_SP_ID(receiver_id)) {
+		for (size_t i = 0; i < constituents_count; i++) {
+			VERBOSE("Sharing Address: %p\n",
+					constituents[i].address);
+			ptr = (uint32_t *)constituents[i].address;
+			for (size_t j = 0; j < words_to_write; j++) {
+				ptr[j] = mem_func + 0xFFA;
+			}
+		}
+	}
+
 	handle = memory_init_and_send(mb->send, PAGE_SIZE, vm_id, &receiver, 1,
 				       constituents, constituents_count,
 				       mem_func, &ffa_ret);
@@ -245,8 +336,8 @@
 					 ffa_error_code(ffa_ret));
 	}
 
-	ffa_ret = cactus_mem_send_cmd(vm_id, receiver_id, mem_func, handle, 0,
-				      10);
+	ffa_ret = cactus_mem_send_cmd(vm_id, receiver_id, mem_func, handle,
+				      0, 10, false);
 
 	if (!is_ffa_direct_response(ffa_ret)) {
 		return cactus_error_resp(vm_id, source, CACTUS_ERROR_FFA_CALL);
diff --git a/spm/cactus/cactus_tests/cactus_test_notifications.c b/spm/cactus/cactus_tests/cactus_test_notifications.c
index d8b88ed..6d7b41b 100644
--- a/spm/cactus/cactus_tests/cactus_test_notifications.c
+++ b/spm/cactus/cactus_tests/cactus_test_notifications.c
@@ -9,6 +9,7 @@
 #include "sp_tests.h"
 
 #include <ffa_helpers.h>
+#include <spm_helpers.h>
 #include <debug.h>
 
 /* Booleans to keep track of which CPUs handled NPI. */
@@ -33,9 +34,8 @@
 
 void notification_pending_interrupt_handler(void)
 {
-	/* Get which core it is running from. */
-	unsigned int core_pos = platform_get_core_pos(
-						read_mpidr_el1() & MPID_MASK);
+	/* Get vCPU index for currently running vCPU. */
+	unsigned int core_pos = spm_get_my_core_pos();
 
 	VERBOSE("NPI handled in core %u\n", core_pos);
 
diff --git a/spm/cactus/cactus_tests/cactus_test_cpu_features.c b/spm/cactus/cactus_tests/cactus_test_simd.c
similarity index 85%
rename from spm/cactus/cactus_tests/cactus_test_cpu_features.c
rename to spm/cactus/cactus_tests/cactus_test_simd.c
index a1366d3..bcf1c38 100644
--- a/spm/cactus/cactus_tests/cactus_test_cpu_features.c
+++ b/spm/cactus/cactus_tests/cactus_test_simd.c
@@ -7,6 +7,7 @@
 #include "cactus_message_loop.h"
 #include "cactus_test_cmds.h"
 #include <fpu.h>
+#include <spm_helpers.h>
 #include "spm_common.h"
 
 /*
@@ -21,7 +22,8 @@
  */
 CACTUS_CMD_HANDLER(req_simd_fill, CACTUS_REQ_SIMD_FILL_CMD)
 {
-	core_pos = platform_get_core_pos(read_mpidr_el1());
+	/* Get vCPU index for currently running vCPU. */
+	core_pos = spm_get_my_core_pos();
 	fpu_state_write_rand(&sp_fpu_state_write);
 	return cactus_response(ffa_dir_msg_dest(*args),
 			       ffa_dir_msg_source(*args),
@@ -36,7 +38,8 @@
 {
 	bool test_succeed = false;
 
-	unsigned int core_pos1 = platform_get_core_pos(read_mpidr_el1());
+	/* Get vCPU index for currently running vCPU. */
+	unsigned int core_pos1 = spm_get_my_core_pos();
 	if (core_pos1 == core_pos) {
 		fpu_state_read(&sp_fpu_state_read);
 		if (fpu_state_compare(&sp_fpu_state_write,
diff --git a/spm/cactus/plat/arm/fvp/fdts/cactus.dts b/spm/cactus/plat/arm/fvp/fdts/cactus.dts
index 12d7b84..3effb39 100644
--- a/spm/cactus/plat/arm/fvp/fdts/cactus.dts
+++ b/spm/cactus/plat/arm/fvp/fdts/cactus.dts
@@ -80,6 +80,9 @@
 			pages-count = <4>;
 			base-address = <0x00000000 0x7400000>;
 			attributes = <0x3>; /* read-write */
+			smmu-id = <0>;
+			stream-ids = <0x0 0x1>;
+			stream-ids-access-permissions = <0x3 0x3>;
 		};
 
 		smmuv3-memcpy-dst {
@@ -87,25 +90,25 @@
 			pages-count = <4>;
 			base-address = <0x00000000 0x7404000>;
 			attributes = <0x3>; /* read-write */
+			smmu-id = <0>;
+			stream-ids = <0x0 0x1>;
+			stream-ids-access-permissions = <0x3 0x3>;
 		};
 
 		smmuv3-ns-region {
-			description = "smmuv3-ns-region";
+			description = "smmuv3-memcpy-ns-region";
 			pages-count = <8>;
 			base-address = <0x0 0x90000000>;
 			attributes = <0xb>; /* ns-read-write */
+			smmu-id = <0>;
+			stream-ids = <0x0 0x1>;
+			stream-ids-access-permissions = <0xb 0xb>;
 		};
 	};
 
 	device-regions {
 		compatible = "arm,ffa-manifest-device-regions";
 
-		uart2 {
-			base-address = <0x00000000 0x1c0b0000>;
-			pages-count = <1>;
-			attributes = <0x3>; /* read-write */
-		};
-
 		smmuv3-testengine {
 			/*
 			 * SMMUv3TestEngine is a DMA IP modeled in the
diff --git a/spm/cactus/plat/arm/fvp/include/sp_platform_def.h b/spm/cactus/plat/arm/fvp/include/sp_platform_def.h
index 0025dce..bb57ce8 100644
--- a/spm/cactus/plat/arm/fvp/include/sp_platform_def.h
+++ b/spm/cactus/plat/arm/fvp/include/sp_platform_def.h
@@ -21,9 +21,6 @@
 #define PLAT_ARM_DEVICE0_BASE		DEVICE0_BASE
 #define PLAT_ARM_DEVICE0_SIZE		DEVICE0_SIZE
 
-#define CACTUS_PL011_UART_BASE		PL011_UART2_BASE
-#define CACTUS_PL011_UART_CLK_IN_HZ	PL011_UART2_CLK_IN_HZ
-
 /* Scratch memory used for SMMUv3 driver testing purposes in Cactus SP */
 #define PLAT_CACTUS_MEMCPY_BASE			ULL(0x7400000)
 #define PLAT_CACTUS_NS_MEMCPY_BASE		ULL(0x90000000)
diff --git a/spm/cactus/plat/arm/tc/fdts/cactus.dts b/spm/cactus/plat/arm/tc/fdts/cactus.dts
index fe450e8..31b9e8e 100644
--- a/spm/cactus/plat/arm/tc/fdts/cactus.dts
+++ b/spm/cactus/plat/arm/tc/fdts/cactus.dts
@@ -70,13 +70,4 @@
 			attributes = <0x3>; /* read-write */
 		};
 	};
-
-	device-regions {
-		compatible = "arm,ffa-manifest-device-regions";
-		uart2 {
-			base-address = <0x00000000 0x7FF80000>;
-			pages-count = <1>;
-			attributes = <0x3>; /* read-write */
-		};
-	};
 };
diff --git a/spm/cactus/plat/arm/tc/include/sp_platform_def.h b/spm/cactus/plat/arm/tc/include/sp_platform_def.h
index c5b548d..b3a3514 100644
--- a/spm/cactus/plat/arm/tc/include/sp_platform_def.h
+++ b/spm/cactus/plat/arm/tc/include/sp_platform_def.h
@@ -21,9 +21,6 @@
 #define PLAT_ARM_DEVICE0_BASE		TC_DEVICE0_BASE
 #define PLAT_ARM_DEVICE0_SIZE		TC_DEVICE0_SIZE
 
-#define CACTUS_PL011_UART_BASE		PL011_UART1_BASE
-#define CACTUS_PL011_UART_CLK_IN_HZ	PL011_UART1_CLK_IN_HZ
-
 /* Scratch memory used for SMMUv3 driver testing purposes in Cactus SP */
 /* SMMUv3 tests are disabled for TC platform */
 #define PLAT_CACTUS_MEMCPY_BASE		ULL(0xfe400000)
diff --git a/spm/common/sp_tests/sp_test_ffa.c b/spm/common/sp_tests/sp_test_ffa.c
index 73db187..219b149 100644
--- a/spm/common/sp_tests/sp_test_ffa.c
+++ b/spm/common/sp_tests/sp_test_ffa.c
@@ -17,7 +17,7 @@
 
 /* FFA version test helpers */
 #define FFA_MAJOR 1U
-#define FFA_MINOR 1U
+#define FFA_MINOR 2U
 
 static uint32_t spm_version;
 
@@ -133,11 +133,11 @@
 	struct ffa_value ret = { 0 };
 
 	VERBOSE("FF-A Partition Info regs interface tests\n");
-	ret = ffa_version(MAKE_FFA_VERSION(1, 1));
+	ret = ffa_version(MAKE_FFA_VERSION(1, 2));
 	uint32_t version = ret.fid;
 
 	if (version == FFA_ERROR_NOT_SUPPORTED) {
-		ERROR("FFA_VERSION 1.1 not supported, skipping"
+		ERROR("FFA_VERSION 1.2 not supported, skipping"
 			" FFA_PARTITION_INFO_GET_REGS test.\n");
 		return;
 	}
diff --git a/spm/common/spm_helpers.c b/spm/common/spm_helpers.c
index 1cb5f4d..b2a4709 100644
--- a/spm/common/spm_helpers.c
+++ b/spm/common/spm_helpers.c
@@ -56,3 +56,16 @@
 
 	return (int64_t)ret.ret0;
 }
+
+/**
+ * Return vCPU index for the currently running vCPU.
+ * Virtual MPIDR holds the linear vCPU index information in lower bits.
+ * Keep only first 24 bits (mapping to Aff0/Aff1/Aff2).
+ * Omit Aff3, bit [31], U[30], MT[24].
+ */
+unsigned int spm_get_my_core_pos(void)
+{
+	uint64_t mpidr = read_mpidr_el1();
+
+	return (unsigned int)(mpidr & 0xffffff);
+}
diff --git a/spm/common/spm_helpers.h b/spm/common/spm_helpers.h
index 1d3ddc2..59cdaf1 100644
--- a/spm/common/spm_helpers.h
+++ b/spm/common/spm_helpers.h
@@ -23,4 +23,6 @@
 int64_t spm_interrupt_enable(uint32_t int_id, bool enable, enum interrupt_pin pin);
 int64_t spm_interrupt_deactivate(uint32_t vint_id);
 
+unsigned int spm_get_my_core_pos(void);
+
 #endif /* SPMC_H */
diff --git a/tftf/tests/extensions/pauth/test_pauth.c b/tftf/tests/extensions/pauth/test_pauth.c
index b29e5d0..ada2f1d 100644
--- a/tftf/tests/extensions/pauth/test_pauth.c
+++ b/tftf/tests/extensions/pauth/test_pauth.c
@@ -13,6 +13,11 @@
 #include <tsp.h>
 #include <string.h>
 
+#ifdef __aarch64__
+static uint128_t pauth_keys_before[NUM_KEYS];
+static uint128_t pauth_keys_after[NUM_KEYS];
+#endif
+
 /*
  * TF-A is expected to allow access to key registers from lower EL's,
  * reading the keys excercises this, on failure this will trap to
@@ -23,7 +28,7 @@
 	SKIP_TEST_IF_AARCH32();
 #ifdef __aarch64__
 	SKIP_TEST_IF_PAUTH_NOT_SUPPORTED();
-	pauth_test_lib_read_keys();
+	pauth_test_lib_read_keys(pauth_keys_before);
 	return TEST_RESULT_SUCCESS;
 #endif	/* __aarch64__ */
 }
@@ -37,11 +42,11 @@
 	SKIP_TEST_IF_AARCH32();
 #ifdef __aarch64__
 	SKIP_TEST_IF_PAUTH_NOT_SUPPORTED();
-	pauth_test_lib_read_keys();
+	pauth_test_lib_read_keys(pauth_keys_before);
 
 	tftf_get_psci_version();
 
-	return pauth_test_lib_compare_template();
+	return pauth_test_lib_compare_template(pauth_keys_before, pauth_keys_after);
 #endif	/* __aarch64__ */
 }
 
@@ -84,7 +89,7 @@
 	SKIP_TEST_IF_PAUTH_NOT_SUPPORTED();
 	SKIP_TEST_IF_TSP_NOT_PRESENT();
 
-	pauth_test_lib_fill_regs_and_template();
+	pauth_test_lib_fill_regs_and_template(pauth_keys_before);
 
 	/* Standard SMC to ADD two numbers */
 	tsp_svc_params.fid = TSP_STD_FID(TSP_ADD);
@@ -106,6 +111,6 @@
 		return TEST_RESULT_FAIL;
 	}
 
-	return pauth_test_lib_compare_template();
+	return pauth_test_lib_compare_template(pauth_keys_before, pauth_keys_after);
 #endif	/* __aarch64__ */
 }
diff --git a/tftf/tests/misc_tests/test_invalid_access.c b/tftf/tests/misc_tests/test_invalid_access.c
index b05d694..3baeed5 100644
--- a/tftf/tests/misc_tests/test_invalid_access.c
+++ b/tftf/tests/misc_tests/test_invalid_access.c
@@ -302,7 +302,7 @@
 		return TEST_RESULT_SKIPPED;
 	}
 
-	CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids);
+	CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
 
 	GET_TFTF_MAILBOX(mb);
 
diff --git a/tftf/tests/misc_tests/test_undef_injection.c b/tftf/tests/misc_tests/test_undef_injection.c
new file mode 100644
index 0000000..2d925a2
--- /dev/null
+++ b/tftf/tests/misc_tests/test_undef_injection.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <arm_arch_svc.h>
+#include <assert.h>
+#include <debug.h>
+#include <smccc.h>
+#include <sync.h>
+#include <tftf_lib.h>
+#include <platform_def.h>
+
+static volatile bool undef_injection_triggered;
+
+static bool undef_injection_handler(void)
+{
+	uint64_t esr_el2 = read_esr_el2();
+	if (EC_BITS(esr_el2) == EC_UNKNOWN) {
+		VERBOSE("UNDEF injection from EL3\n");
+		undef_injection_triggered = true;
+		return true;
+	}
+
+	return false;
+}
+
+/*
+ * Test to verify UNDEF injection support in TF-A
+ *
+ * This test tries to access FGT EL2 registers which traps to EL3 and then
+ * the error is injected back from EL3 to TFTF to ensure that injection
+ * logic in TF-A is working, it also ensures that EL3 is still functional
+ * after UNDEF injection.
+ *
+ * To trap FGT register access to EL3, we run this test on a model with
+ * FEAT_FGT present but the traps from EL3 are not disabled by setting
+ * ENABLE_FEAT_FGT = 0
+ */
+test_result_t test_undef_injection(void)
+{
+	undef_injection_triggered = false;
+
+	register_custom_sync_exception_handler(undef_injection_handler);
+
+	/* Try to access a register which traps to EL3 */
+	read_hfgitr_el2();
+
+	unregister_custom_sync_exception_handler();
+
+	/* Ensure that EL3 still functional */
+	smc_args args;
+	smc_ret_values smc_ret;
+	memset(&args, 0, sizeof(args));
+	args.fid = SMCCC_VERSION;
+	smc_ret = tftf_smc(&args);
+
+	tftf_testcase_printf("SMCCC Version = %d.%d\n",
+		(int)((smc_ret.ret0 >> SMCCC_VERSION_MAJOR_SHIFT) & SMCCC_VERSION_MAJOR_MASK),
+		(int)((smc_ret.ret0 >> SMCCC_VERSION_MINOR_SHIFT) & SMCCC_VERSION_MINOR_MASK));
+
+	if (undef_injection_triggered == false) {
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
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 a424b09..682a699 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
@@ -215,6 +215,18 @@
 		}
 	}
 
+	/*
+	 * 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 c678217..057dd00 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
@@ -142,10 +142,10 @@
 	return host_rmi_handler(&(smc_args) {RMI_REALM_DESTROY, rd}, 2U).ret0;
 }
 
-static inline u_register_t host_rmi_data_destroy(u_register_t rd,
-						 u_register_t map_addr,
-						 u_register_t *data,
-						 u_register_t *top)
+u_register_t host_rmi_data_destroy(u_register_t rd,
+				   u_register_t map_addr,
+				   u_register_t *data,
+				   u_register_t *top)
 {
 	smc_ret_values rets;
 
@@ -179,11 +179,11 @@
 				rd, rtt, map_addr, level}, 5U).ret0;
 }
 
-static inline u_register_t host_rmi_rtt_destroy(u_register_t rd,
-						u_register_t map_addr,
-						u_register_t level,
-						u_register_t *rtt,
-						u_register_t *top)
+u_register_t host_rmi_rtt_destroy(u_register_t rd,
+				  u_register_t map_addr,
+				  u_register_t level,
+				  u_register_t *rtt,
+				  u_register_t *top)
 {
 	smc_ret_values rets;
 
@@ -203,10 +203,10 @@
 	return rets.ret0;
 }
 
-static inline u_register_t host_rmi_rtt_init_ripas(u_register_t rd,
-						   u_register_t start,
-						   u_register_t end,
-						   u_register_t *top)
+u_register_t host_rmi_rtt_init_ripas(u_register_t rd,
+				   u_register_t start,
+				   u_register_t end,
+				   u_register_t *top)
 
 {
 	smc_ret_values rets;
@@ -263,10 +263,10 @@
 				rd, map_addr, level, ns_pa}, 5U).ret0;
 }
 
-static u_register_t host_rmi_rtt_readentry(u_register_t rd,
-					   u_register_t map_addr,
-					   u_register_t level,
-					   struct rtt_entry *rtt)
+u_register_t host_rmi_rtt_readentry(u_register_t rd,
+				   u_register_t map_addr,
+				   u_register_t level,
+				   struct rtt_entry *rtt)
 {
 	smc_ret_values rets;
 
@@ -279,10 +279,10 @@
 	return rets.ret0;
 }
 
-static inline u_register_t host_rmi_rtt_unmap_unprotected(u_register_t rd,
-							  u_register_t map_addr,
-							  u_register_t level,
-							  u_register_t *top)
+u_register_t host_rmi_rtt_unmap_unprotected(u_register_t rd,
+					  u_register_t map_addr,
+					  u_register_t level,
+					  u_register_t *top)
 {
 	smc_ret_values rets;
 
@@ -292,7 +292,7 @@
 	return rets.ret0;
 }
 
-static inline u_register_t host_rtt_level_mapsize(u_register_t level)
+u_register_t host_rtt_level_mapsize(u_register_t level)
 {
 	if (level > RTT_MAX_LEVEL) {
 		return PAGE_SIZE;
@@ -315,10 +315,10 @@
 	return host_rmi_rtt_create(realm->rd, phys, addr, level);
 }
 
-static u_register_t host_rmi_create_rtt_levels(struct realm *realm,
-						u_register_t map_addr,
-						u_register_t level,
-						u_register_t max_level)
+u_register_t host_rmi_create_rtt_levels(struct realm *realm,
+					u_register_t map_addr,
+					u_register_t level,
+					u_register_t max_level)
 {
 	u_register_t rtt, ret;
 
@@ -381,11 +381,11 @@
 
 }
 
-u_register_t host_realm_map_protected_data(bool unknown,
-					   struct realm *realm,
-					   u_register_t target_pa,
-					   u_register_t map_size,
-					   u_register_t src_pa)
+u_register_t host_realm_delegate_map_protected_data(bool unknown,
+						    struct realm *realm,
+						    u_register_t target_pa,
+						    u_register_t map_size,
+						    u_register_t src_pa)
 {
 	u_register_t rd = realm->rd;
 	u_register_t map_level, level;
@@ -393,8 +393,6 @@
 	u_register_t size = 0UL;
 	u_register_t phys = target_pa;
 	u_register_t map_addr = target_pa;
-	u_register_t end_addr = map_addr + map_size;
-	u_register_t top;
 
 	if (!IS_ALIGNED(map_addr, map_size)) {
 		return REALM_ERROR;
@@ -412,23 +410,6 @@
 		return REALM_ERROR;
 	}
 
-	ret = host_rmi_rtt_init_ripas(rd, map_addr, end_addr, &top);
-	if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT) {
-		ret = host_rmi_create_rtt_levels(realm, map_addr,
-						 RMI_RETURN_INDEX(ret),
-						 map_level);
-		if (ret != RMI_SUCCESS) {
-			ERROR("%s() failed, ret=0x%lx line=%u\n",
-				"host_rmi_create_rtt_levels", ret, __LINE__);
-			goto err;
-		}
-		ret = host_rmi_rtt_init_ripas(rd, map_addr, end_addr, &top);
-		if (ret != RMI_SUCCESS) {
-			ERROR("%s() failed, ret=0x%lx line=%u\n",
-				"host_rmi_rtt_init_ripas", ret, __LINE__);
-			goto err;
-		}
-	}
 	for (size = 0UL; size < map_size; size += PAGE_SIZE) {
 		ret = host_rmi_granule_delegate(phys);
 		if (ret != RMI_SUCCESS) {
@@ -533,7 +514,6 @@
 		ERROR("Unknown map_size=0x%lx\n", map_size);
 		return REALM_ERROR;
 	}
-
 	u_register_t desc = phys | S2TTE_ATTR_FWB_WB_RW;
 
 	ret = host_rmi_rtt_mapunprotected(rd, map_addr, map_level, desc);
@@ -877,7 +857,7 @@
 
 	/* MAP image regions */
 	while (i < (realm->par_size / PAGE_SIZE)) {
-		ret = host_realm_map_protected_data(false, realm,
+		ret = host_realm_delegate_map_protected_data(false, realm,
 						realm->par_base + i * PAGE_SIZE,
 						PAGE_SIZE,
 						src_pa + i * PAGE_SIZE);
@@ -1130,17 +1110,12 @@
 		return REALM_SUCCESS;
 	}
 
-	if (realm->state == REALM_STATE_NEW) {
-		goto undo_from_new_state;
-	}
-
-	if (realm->state != REALM_STATE_ACTIVE) {
-		ERROR("Invalid realm state found 0x%x\n", realm->state);
-		return REALM_ERROR;
-	}
-
+	/* For each REC - Destroy, undelegate and free */
 	for (unsigned int i = 0U; i < realm->rec_count; i++) {
-		/* For each REC - Destroy, undelegate and free */
+		if (realm->rec[i] == 0U) {
+			break;
+		}
+
 		ret = host_rmi_rec_destroy(realm->rec[i]);
 		if (ret != RMI_SUCCESS) {
 			ERROR("%s() failed, rec=0x%lx ret=0x%lx\n",
@@ -1176,13 +1151,14 @@
 		ERROR("host_realm_tear_down_rtt_range() line=%u\n", __LINE__);
 		return REALM_ERROR;
 	}
-	if (host_realm_tear_down_rtt_range(realm, 0UL, realm->ipa_ns_buffer,
-			(realm->ipa_ns_buffer + realm->ns_buffer_size)) !=
-			RMI_SUCCESS) {
-		ERROR("host_realm_tear_down_rtt_range() line=%u\n", __LINE__);
-		return REALM_ERROR;
+	if (realm->shared_mem_created == true) {
+		if (host_realm_tear_down_rtt_range(realm, 0UL, realm->ipa_ns_buffer,
+				(realm->ipa_ns_buffer + realm->ns_buffer_size)) !=
+				RMI_SUCCESS) {
+			ERROR("host_realm_tear_down_rtt_range() line=%u\n", __LINE__);
+			return REALM_ERROR;
+		}
 	}
-undo_from_new_state:
 
 	/*
 	 * RD Destroy, undelegate and free
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 1948c1f..ff69869 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -25,6 +25,11 @@
 
 extern const char *rmi_exit[];
 
+#if ENABLE_PAUTH
+static uint128_t pauth_keys_before[NUM_KEYS];
+static uint128_t pauth_keys_after[NUM_KEYS];
+#endif
+
 /*
  * @Test_Aim@ Test realm payload creation, execution and destruction  iteratively
  */
@@ -97,7 +102,8 @@
 }
 
 /*
- * @Test_Aim@ Test PAuth in realm
+ * @Test_Aim@ Create realm with multiple rec
+ * Test PAuth registers are preserved for each rec
  */
 test_result_t host_realm_enable_pauth(void)
 {
@@ -105,16 +111,17 @@
 	return TEST_RESULT_SKIPPED;
 #else
 	bool ret1, ret2;
-	u_register_t rec_flag[1] = {RMI_RUNNABLE};
+	u_register_t rec_flag[MAX_REC_COUNT] = {RMI_RUNNABLE, RMI_RUNNABLE, RMI_RUNNABLE,
+		RMI_RUNNABLE, RMI_RUNNABLE, RMI_RUNNABLE, RMI_RUNNABLE, RMI_RUNNABLE,};
 	struct realm realm;
 
 	SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
 
-	pauth_test_lib_fill_regs_and_template();
+	pauth_test_lib_fill_regs_and_template(pauth_keys_before);
 	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,
-				0UL, rec_flag, 1U)) {
+				0UL, rec_flag, MAX_REC_COUNT)) {
 		return TEST_RESULT_FAIL;
 	}
 
@@ -123,24 +130,33 @@
 		return TEST_RESULT_FAIL;
 	}
 
-	ret1 = host_enter_realm_execute(&realm, REALM_PAUTH_SET_CMD, RMI_EXIT_HOST_CALL, 0U);
+	for (unsigned int i = 0U; i < MAX_REC_COUNT; i++) {
+		ret1 = host_enter_realm_execute(&realm, REALM_PAUTH_SET_CMD,
+				RMI_EXIT_HOST_CALL, i);
 
-	if (ret1) {
+		if (!ret1) {
+			ERROR("Pauth set cmd failed\n");
+			break;
+		}
 		/* Re-enter Realm to compare PAuth registers. */
 		ret1 = host_enter_realm_execute(&realm, REALM_PAUTH_CHECK_CMD,
-				RMI_EXIT_HOST_CALL, 0U);
+			RMI_EXIT_HOST_CALL, i);
+		if (!ret1) {
+			ERROR("Pauth check cmd failed\n");
+			break;
+		}
 	}
 
 	ret2 = host_destroy_realm(&realm);
 
-	if (!ret1) {
+	if (!ret1 || !ret2) {
 		ERROR("%s(): enter=%d destroy=%d\n",
 				__func__, ret1, ret2);
 		return TEST_RESULT_FAIL;
 	}
 
 	/* Check if PAuth keys are preserved. */
-	if (!pauth_test_lib_compare_template()) {
+	if (!pauth_test_lib_compare_template(pauth_keys_before, pauth_keys_after)) {
 		ERROR("%s(): NS PAuth keys not preserved\n",
 				__func__);
 		return TEST_RESULT_FAIL;
@@ -456,11 +472,11 @@
 			base + (PAGE_SIZE * test_page_num));
 
 	for (unsigned int i = 0U; i < test_page_num; i++) {
-		ret = host_realm_map_protected_data(true, &realm,
+		ret = host_realm_delegate_map_protected_data(true, &realm,
 				base + (PAGE_SIZE * i), PAGE_SIZE,
 				base + (PAGE_SIZE * i));
 		if (ret != REALM_SUCCESS) {
-			ERROR("host_realm_map_protected_data failed\n");
+			ERROR("host_realm_delegate_map_protected_data failed\n");
 			goto destroy_realm;
 		}
 	}
@@ -548,9 +564,9 @@
 
 	base = (u_register_t)page_alloc(PAGE_SIZE);
 
-	ret = host_realm_map_protected_data(true, &realm, base, PAGE_SIZE, base);
+	ret = host_realm_delegate_map_protected_data(true, &realm, base, PAGE_SIZE, base);
 	if (ret != RMI_SUCCESS) {
-		ERROR("host_realm_map_protected_data failede\n");
+		ERROR("host_realm_delegate_map_protected_data failede\n");
 		goto destroy_realm;
 	}
 	host_shared_data_set_host_val(&realm, 0U, HOST_ARG1_INDEX, base);
@@ -584,3 +600,676 @@
 	return host_call_result;
 }
 
+/*
+ * Test aims to generate REALM Exit due to abort
+ * when access page with RIPAS=DESTOYED HIPAS=ASSIGNED
+ * Host maps a protected page (calls data_create) when realm is in new state
+ * Initial state of PAGE is RIPAS=RAM HIPAS=ASSIGNED
+ * Host calls data_destroy, new state HIPAS=UNASSIGNED RIPAS=DESTROYED
+ * Enter Realm, Rec0 executes from page, and Rec1 reads the page
+ * Realm should trigger an Instr/Data abort, and will exit to Host.
+ * The Host verifies exit reason is Instr/Data abort
+ */
+test_result_t host_realm_abort_unassigned_destroyed(void)
+{
+	bool ret1, ret2;
+	test_result_t res = TEST_RESULT_FAIL;
+	u_register_t ret, data, top;
+	struct realm realm;
+	struct rmi_rec_run *run;
+	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;
+	}
+
+	base = (u_register_t)page_alloc(PAGE_SIZE);
+
+	run = (struct rmi_rec_run *)realm.run[0];
+
+	/* DATA_CREATE
+	 * Copies content of TFTF_BASE in newly created page, any PA can be used for dummy copy
+	 * maps 1:1 IPA:PA
+	 */
+	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;
+	}
+	INFO("Initial state base = 0x%lx rtt.state=0x%lx rtt.ripas=0x%lx\n",
+			base, rtt.state, rtt.ripas);
+	host_shared_data_set_host_val(&realm, 0U, HOST_ARG1_INDEX, base);
+	host_shared_data_set_host_val(&realm, 1U, HOST_ARG1_INDEX, base);
+
+	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;
+	}
+
+	INFO("New state4 base = 0x%lx rtt.state=0x%lx rtt.ripas=0x%lx\n",
+			base, rtt.state, rtt.ripas);
+
+	if (host_realm_activate(&realm) != REALM_SUCCESS) {
+		ERROR("%s() failed\n", "host_realm_activate");
+		goto undelegate_destroy;
+	}
+
+	/* Realm0 expect rec exit due to Instr Abort unassigned destroyed page */
+	ret1 = host_enter_realm_execute(&realm, REALM_INSTR_FETCH_CMD,
+		RMI_EXIT_SYNC, 0U);
+
+	/* ESR.EC == 0b100000 Instruction Abort from a lower Exception level */
+	if (!ret1 || ((run->exit.hpfar >> 4U) != (base >> PAGE_SIZE_SHIFT)
+			|| (EC_BITS(run->exit.esr) != EC_IABORT_LOWER_EL)
+			|| ((run->exit.esr & ISS_IFSC_MASK) < IFSC_L0_TRANS_FAULT)
+			|| ((run->exit.esr & ISS_IFSC_MASK) > IFSC_L3_TRANS_FAULT)
+			|| ((run->exit.esr & (1UL << ESR_ISS_EABORT_EA_BIT)) != 0U))) {
+		ERROR("Rec did not fault ESR=0x%lx\n", run->exit.esr);
+		goto undelegate_destroy;
+	}
+	INFO("IA FAR=0x%lx, HPFAR=0x%lx ESR=0x%lx\n", run->exit.far, run->exit.hpfar,
+			run->exit.esr);
+
+	run = (struct rmi_rec_run *)realm.run[1];
+
+	/* Realm1 expect rec exit due to Data Abort unassigned destroyed page */
+	ret1 = host_enter_realm_execute(&realm, REALM_DATA_ACCESS_CMD,
+			RMI_EXIT_SYNC, 1U);
+
+	/* ESR.EC == 0b100100 Data Abort exception from a lower Exception level */
+	if (!ret1 || ((run->exit.hpfar >> 4U) != (base >> PAGE_SIZE_SHIFT)
+		|| (EC_BITS(run->exit.esr) != EC_DABORT_LOWER_EL)
+		|| ((run->exit.esr & ISS_DFSC_MASK) < DFSC_L0_TRANS_FAULT)
+		|| ((run->exit.esr & ISS_DFSC_MASK) > DFSC_L3_TRANS_FAULT)
+		|| ((run->exit.esr & (1UL << ESR_ISS_EABORT_EA_BIT)) != 0U))) {
+		ERROR("Rec did not fault\n");
+		goto undelegate_destroy;
+	}
+	INFO("DA FAR=0x%lx, HPFAR=0x%lx ESR= 0x%lx\n", run->exit.far, run->exit.hpfar,
+			run->exit.esr);
+	res = TEST_RESULT_SUCCESS;
+
+undelegate_destroy:
+	ret = host_rmi_granule_undelegate(base);
+destroy_realm:
+	ret2 = host_destroy_realm(&realm);
+
+	if (!ret2) {
+		ERROR("%s(): destroy=%d\n",
+		__func__, ret2);
+		return TEST_RESULT_FAIL;
+	}
+
+	return res;
+}
+
+/*
+ * Test aims to generate REALM Exit due to Abort
+ * when access page with RIPAS=RAM HIPAS=UNASSIGNED
+ * Host allocates a PAGE, calls init_ripas when realm is in new state
+ * Initial state of PAGE is RIPAS=RAM HIPAS=UNASSIGNED
+ * Enter Realm, REC0 executes from page, and REC1 reads the page
+ * Realm should trigger an Instr/Data abort, and will exit to Host.
+ * Host verifies exit reason is Instr/Data abort.
+ */
+test_result_t host_realm_abort_unassigned_ram(void)
+{
+	bool ret1, ret2;
+	u_register_t ret, top;
+	struct realm realm;
+	struct rmi_rec_run *run;
+	struct rtt_entry rtt;
+	test_result_t res = TEST_RESULT_FAIL;
+	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;
+	}
+
+	/* This is dummy allocation to get a base address */
+	base = (u_register_t)page_alloc(PAGE_SIZE);
+
+	run = (struct rmi_rec_run *)realm.run[0];
+
+	/* Set RIPAS of PAGE to RAM */
+	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;
+	}
+	if (host_realm_activate(&realm) != REALM_SUCCESS) {
+		ERROR("%s() failed\n", "host_realm_activate");
+		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 initial state\n");
+		goto destroy_realm;
+	}
+	INFO("Initial state base = 0x%lx rtt.state=0x%lx rtt.ripas=0x%lx\n",
+			base, rtt.state, rtt.ripas);
+	host_shared_data_set_host_val(&realm, 0U, HOST_ARG1_INDEX, base);
+	host_shared_data_set_host_val(&realm, 1U, HOST_ARG1_INDEX, base);
+
+	/* Rec0 expect rec exit due to Instr Abort unassigned ram page */
+	ret1 = host_enter_realm_execute(&realm, REALM_INSTR_FETCH_CMD,
+			RMI_EXIT_SYNC, 0U);
+
+	/* ESR.EC == 0b100000 Instruction Abort from a lower Exception level */
+	if (!ret1 || ((run->exit.hpfar >> 4U) != (base >> PAGE_SIZE_SHIFT)
+			|| (EC_BITS(run->exit.esr) != EC_IABORT_LOWER_EL)
+			|| ((run->exit.esr & ISS_IFSC_MASK) < IFSC_L0_TRANS_FAULT)
+			|| ((run->exit.esr & ISS_IFSC_MASK) > IFSC_L3_TRANS_FAULT)
+			|| ((run->exit.esr & (1UL << ESR_ISS_EABORT_EA_BIT)) != 0U))) {
+		ERROR("Rec did not fault ESR=0x%lx\n", run->exit.esr);
+		goto destroy_realm;
+	}
+	INFO("IA FAR=0x%lx, HPFAR=0x%lx ESR=0x%lx\n", run->exit.far, run->exit.hpfar,
+			run->exit.esr);
+	run = (struct rmi_rec_run *)realm.run[1];
+
+	/* Rec1 expect rec exit due to Data Abort unassigned ram page */
+	ret1 = host_enter_realm_execute(&realm, REALM_DATA_ACCESS_CMD,
+			RMI_EXIT_SYNC, 1U);
+
+	/* ESR.EC == 0b100100 Data Abort exception from a lower Exception level */
+	if (!ret1 || ((run->exit.hpfar >> 4U) != (base >> PAGE_SIZE_SHIFT)
+		|| (EC_BITS(run->exit.esr) != EC_DABORT_LOWER_EL)
+		|| ((run->exit.esr & ISS_DFSC_MASK) < DFSC_L0_TRANS_FAULT)
+		|| ((run->exit.esr & ISS_DFSC_MASK) > DFSC_L3_TRANS_FAULT)
+		|| ((run->exit.esr & (1UL << ESR_ISS_EABORT_EA_BIT)) != 0U))) {
+		ERROR("Rec did not fault ESR=0x%lx\n", run->exit.esr);
+		goto destroy_realm;
+	}
+	INFO("DA FAR=0x%lx, HPFAR=0x%lx ESR=0x%lx\n", run->exit.far, run->exit.hpfar,
+			run->exit.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;
+}
+
+/*
+ * Test aims to generate REALM Exit due to Abort
+ * when access page with RIPAS=DESTOYED HIPAS=Assigned
+ * Host maps a protected page (calls data_create) when realm is in new state
+ * initial state of PAGE is RIPAS=RAM HIPAS=ASSIGNED
+ * Host calls data_destroy, new state HIPAS=UNASSIGNED RIPAS=DESTROYED
+ * Host calls data_create_unknown, new state HIPAS=ASSIGNED RIPAS=DESTROYED
+ * Enter Realm, REC0 executes from page, and REC1 reads the page
+ * Realm should trigger an Instr/Data abort, and will exit to Host.
+ * The Host verifies exit reason is Instr/Data abort
+ */
+test_result_t host_realm_abort_assigned_destroyed(void)
+{
+	bool ret1, ret2;
+	test_result_t res = TEST_RESULT_FAIL;
+	u_register_t ret, top, data;
+	struct realm realm;
+	struct rmi_rec_run *run;
+	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;
+	}
+
+	base = (u_register_t)page_alloc(PAGE_SIZE);
+	run = (struct rmi_rec_run *)realm.run[0];
+
+	/* DATA_CREATE */
+	/* Copied content of TFTF_BASE to new page, can use any adr, maps 1:1 IPA:PA */
+	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 create\n");
+		goto destroy_realm;
+	}
+	INFO("Initial state base = 0x%lx rtt.state=0x%lx rtt.ripas=0x%lx\n",
+			base, rtt.state, rtt.ripas);
+	host_shared_data_set_host_val(&realm, 0U, HOST_ARG1_INDEX, base);
+	host_shared_data_set_host_val(&realm, 1U, HOST_ARG1_INDEX, base);
+
+	if (host_realm_activate(&realm) != REALM_SUCCESS) {
+		ERROR("%s() failed\n", "host_realm_activate");
+		goto destroy_realm;
+	}
+
+	ret = host_rmi_data_destroy(realm.rd, base, &data, &top);
+	if (ret != RMI_SUCCESS || data != base) {
+		ERROR("host_rmi_data_destroy 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_DESTROYED) {
+		ERROR("Wrong state after host_rmi_data_destroy\n");
+		goto destroy_realm;
+	}
+	ret = host_rmi_granule_undelegate(base);
+
+	/* 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 failede\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_DESTROYED)) {
+		ERROR("wrong state after data create unknown\n");
+		goto destroy_data;
+	}
+
+	/* Rec0, expect rec exit due to Instr Abort assigned destroyed page */
+	ret1 = host_enter_realm_execute(&realm, REALM_INSTR_FETCH_CMD,
+		RMI_EXIT_SYNC, 0U);
+
+	/* ESR.EC == 0b100000 Instruction Abort from a lower Exception level */
+	if (!ret1 || ((run->exit.hpfar >> 4U) != (base >> PAGE_SIZE_SHIFT)
+		|| (EC_BITS(run->exit.esr) != EC_IABORT_LOWER_EL)
+		|| ((run->exit.esr & ISS_IFSC_MASK) < IFSC_L0_TRANS_FAULT)
+		|| ((run->exit.esr & ISS_IFSC_MASK) > IFSC_L3_TRANS_FAULT)
+		|| ((run->exit.esr & (1UL << ESR_ISS_EABORT_EA_BIT)) != 0U))) {
+		ERROR("Rec did not fault ESR=0x%lx\n", run->exit.esr);
+		goto destroy_data;
+	}
+	INFO("IA FAR=0x%lx, HPFAR=0x%lx ESR=0x%lx\n", run->exit.far, run->exit.hpfar,
+				run->exit.esr);
+	run = (struct rmi_rec_run *)realm.run[1];
+
+	/* Rec1  expect rec exit due to Data Abort  assigned destroyed page */
+	ret1 = host_enter_realm_execute(&realm, REALM_DATA_ACCESS_CMD,
+			RMI_EXIT_SYNC, 1U);
+
+	/* ESR.EC == 0b100100 Data Abort exception from a lower Exception level */
+	if (!ret1 || ((run->exit.hpfar >> 4U) != (base >> PAGE_SIZE_SHIFT)
+		|| (EC_BITS(run->exit.esr) != EC_DABORT_LOWER_EL)
+		|| ((run->exit.esr & ISS_DFSC_MASK) < DFSC_L0_TRANS_FAULT)
+		|| ((run->exit.esr & ISS_DFSC_MASK) > DFSC_L3_TRANS_FAULT)
+		|| ((run->exit.esr & (1UL << ESR_ISS_EABORT_EA_BIT)) != 0U))) {
+		ERROR("Rec did not fault ESR=0x%lx\n", run->exit.esr);
+		goto destroy_data;
+	}
+	INFO("DA FAR=0x%lx, HPFAR=0x%lx ESR=0x%lx\n", run->exit.far, run->exit.hpfar,
+				run->exit.esr);
+	res = TEST_RESULT_SUCCESS;
+
+destroy_data:
+	ret = host_rmi_data_destroy(realm.rd, base, &data, &top);
+	ret = host_rmi_granule_undelegate(base);
+destroy_realm:
+	ret2 = host_destroy_realm(&realm);
+
+	if (!ret2) {
+		ERROR("%s(): destroy=%d\n",
+		__func__, ret2);
+		return TEST_RESULT_FAIL;
+	}
+
+	return res;
+}
+
+/*
+ * Test aims to generate SEA in Realm by accessing
+ * PAGE with HIPAS=assigned/unassigned and RIPAS=EMPTY
+ * Host creates and executes 4 recs to generate SEA
+ * Rec exception handler runs and returns back ESR to Host
+ * Host validates ESR
+ * Rec0 generated IA unassigned empty
+ * Rec1 generated DA unassigned empty
+ * Rec2 generated IA for assigned empty
+ * Rec3 generated DA for assigned empty
+ */
+test_result_t host_realm_sea_empty(void)
+{
+	bool ret1, ret2;
+	test_result_t res = TEST_RESULT_FAIL;
+	u_register_t ret, base, esr;
+	struct realm realm;
+	struct rtt_entry rtt;
+	u_register_t rec_flag[] = {RMI_RUNNABLE, RMI_RUNNABLE, RMI_RUNNABLE, RMI_RUNNABLE};
+
+	SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+
+	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,
+			0UL, 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;
+	}
+
+	base = (u_register_t)page_alloc(PAGE_SIZE);
+
+	ret = host_rmi_rtt_readentry(realm.rd, base, 3U, &rtt);
+	if (rtt.state != RMI_UNASSIGNED ||
+			(rtt.ripas != RMI_EMPTY)) {
+		ERROR("wrong initial state\n");
+		goto destroy_realm;
+	}
+	host_shared_data_set_host_val(&realm, 0U, HOST_ARG1_INDEX, base);
+	host_shared_data_set_host_val(&realm, 1U, HOST_ARG1_INDEX, base);
+	host_shared_data_set_host_val(&realm, 2U, HOST_ARG1_INDEX, base);
+	host_shared_data_set_host_val(&realm, 3U, HOST_ARG1_INDEX, base);
+
+	/* Rec0 expect IA due to SEA unassigned empty page */
+	ret1 = host_enter_realm_execute(&realm, REALM_INSTR_FETCH_CMD,
+			RMI_EXIT_HOST_CALL, 0U);
+	if (!ret1) {
+		ERROR("Rec0 did not fault\n");
+		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_IFSC_MASK) != IFSC_NO_WALK_SEA) || (EC_BITS(esr) != EC_IABORT_CUR_EL)) {
+		ERROR("Rec0 incorrect ESR=0x%lx\n", esr);
+		goto destroy_realm;
+	}
+	INFO("Rec0 ESR=0x%lx\n", esr);
+
+	/* Rec1 expect DA due to SEA unassigned empty page */
+	ret1 = host_enter_realm_execute(&realm, REALM_DATA_ACCESS_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) != DFSC_NO_WALK_SEA) || (EC_BITS(esr) != EC_DABORT_CUR_EL)) {
+		ERROR("Rec1 incorrect ESR=0x%lx\n", esr);
+		goto destroy_realm;
+	}
+	INFO("Rec1 ESR=0x%lx\n", esr);
+
+	/* 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");
+		goto destroy_realm;
+	}
+	ret = host_rmi_rtt_readentry(realm.rd, base, 3U, &rtt);
+	if (rtt.state != RMI_ASSIGNED ||
+			(rtt.ripas != RMI_EMPTY)) {
+		ERROR("wrong state after DATA_CRATE_UNKNOWN\n");
+		goto undelegate_destroy;
+	}
+	INFO("state base = 0x%lx rtt.state=0x%lx rtt.ripas=0x%lx\n",
+			base, rtt.state, rtt.ripas);
+
+	/* Rec2 expect IA due to SEA assigned empty page */
+	ret1 = host_enter_realm_execute(&realm, REALM_INSTR_FETCH_CMD,
+		RMI_EXIT_HOST_CALL, 2U);
+
+	if (!ret1) {
+		ERROR("Rec2 did not fault\n");
+		goto undelegate_destroy;
+	}
+
+	/* get ESR set by Realm exception handler */
+	esr = host_shared_data_get_realm_val(&realm, 2U, HOST_ARG2_INDEX);
+	if (((esr & ISS_IFSC_MASK) != IFSC_NO_WALK_SEA) || (EC_BITS(esr) != EC_IABORT_CUR_EL)) {
+		ERROR("Rec2 incorrect ESR=0x%lx\n", esr);
+		goto destroy_realm;
+	}
+	INFO("Rec2 ESR=0x%lx\n", esr);
+
+	/* Rec3 expect DA due to SEA unassigned empty page */
+	ret1 = host_enter_realm_execute(&realm, REALM_DATA_ACCESS_CMD,
+			RMI_EXIT_HOST_CALL, 3U);
+	if (!ret1) {
+		ERROR("Rec3 did not fault\n");
+		goto undelegate_destroy;
+	}
+
+	/* get ESR set by Realm exception handler */
+	esr = host_shared_data_get_realm_val(&realm, 3U, HOST_ARG2_INDEX);
+	if (((esr & ISS_DFSC_MASK) != DFSC_NO_WALK_SEA) || (EC_BITS(esr) != EC_DABORT_CUR_EL)) {
+		ERROR("Rec3 incorrect ESR=0x%lx\n", esr);
+	}
+	INFO("Rec3 ESR=0x%lx\n", esr);
+	res = TEST_RESULT_SUCCESS;
+
+undelegate_destroy:
+	ret = host_rmi_granule_undelegate(base);
+destroy_realm:
+	ret2 = host_destroy_realm(&realm);
+
+	if (!ret2) {
+		ERROR("%s(): destroy=%d\n",
+		__func__, ret2);
+		return TEST_RESULT_FAIL;
+	}
+
+	return res;
+}
+
+/*
+ * Test aims to generate SEA in Realm by
+ * executing instructions in unprotected IPA - Rec0
+ * In Rec 1 , when HIPAS=UNASSIGNED_NS, we expect to get a Data abort.
+ * Then Host will inject SEA to realm.
+ * Realm exception handler runs and returns ESR back to Host
+ * Host validates ESR
+ */
+test_result_t host_realm_sea_unprotected(void)
+{
+
+	bool ret1, ret2;
+	test_result_t res = TEST_RESULT_FAIL;
+	u_register_t ret, base, base_ipa, esr;
+	unsigned int host_call_result;
+	u_register_t exit_reason;
+	struct realm realm;
+	struct rtt_entry rtt;
+	struct rmi_rec_run *run;
+	u_register_t rec_flag[2U] = {RMI_RUNNABLE, RMI_RUNNABLE};
+
+	SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+
+	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,
+			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;
+	}
+
+	/* Can choose any unprotected IPA adr, TFTF_BASE chosen for convenience */
+	base = TFTF_BASE;
+	base_ipa = base | (1UL << (EXTRACT(RMI_FEATURE_REGISTER_0_S2SZ,
+					realm.rmm_feat_reg0) - 1U));
+
+
+	ret = host_rmi_rtt_readentry(realm.rd, base, 3U, &rtt);
+	if (rtt.state != RMI_UNASSIGNED) {
+		ERROR("wrong state\n");
+		goto destroy_realm;
+	}
+
+	run = (struct rmi_rec_run *)realm.run[0];
+	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);
+
+	/* Rec0 expect SEA in realm due to IA unprotected IPA page */
+	ret1 = host_enter_realm_execute(&realm, REALM_INSTR_FETCH_CMD,
+			RMI_EXIT_HOST_CALL, 0U);
+	if (!ret1) {
+		ERROR("Rec0 did not fault\n");
+		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_IFSC_MASK) != IFSC_NO_WALK_SEA) || (EC_BITS(esr) != EC_IABORT_CUR_EL)) {
+		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[1U];
+
+	/* Rec1 expect rec exit due to DA unprotected IPA page when HIPAS is UNASSIGNED_NS */
+	ret1 = host_enter_realm_execute(&realm, REALM_DATA_ACCESS_CMD,
+			RMI_EXIT_SYNC, 1U);
+
+	if (!ret1 || (run->exit.hpfar >> 4U) != (base_ipa >> PAGE_SIZE_SHIFT)
+		|| (EC_BITS(run->exit.esr) != EC_DABORT_LOWER_EL)
+		|| ((run->exit.esr & ISS_DFSC_MASK) < DFSC_L0_TRANS_FAULT)
+		|| ((run->exit.esr & ISS_DFSC_MASK) > DFSC_L3_TRANS_FAULT)
+		|| ((run->exit.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("Host DA FAR=0x%lx, HPFAR=0x%lx\n", run->exit.far, run->exit.hpfar);
+	INFO("Injecting SEA to Realm\n");
+
+	/* Inject SEA back to Realm */
+	run->entry.flags = REC_ENTRY_FLAG_INJECT_SEA;
+
+	/* Rec1 re-entry expect exception handler to run, return ESR */
+	ret = host_realm_rec_enter(&realm, &exit_reason, &host_call_result, 1U);
+	if (ret != RMI_SUCCESS || exit_reason != RMI_EXIT_HOST_CALL) {
+		ERROR("rec1 failed ret=0x%lx exit_reason=0x%lx", ret, run->exit.exit_reason);
+		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) != DFSC_NO_WALK_SEA) || (EC_BITS(esr) != EC_DABORT_CUR_EL)) {
+		ERROR("Rec1 incorrect ESR=0x%lx\n", esr);
+		goto destroy_realm;
+	}
+	INFO("Rec1 ESR=0x%lx\n", esr);
+	res = host_call_result;
+
+destroy_realm:
+	ret2 = host_destroy_realm(&realm);
+
+	if (!ret2) {
+		ERROR("%s(): destroy=%d\n",
+		__func__, ret2);
+		return TEST_RESULT_FAIL;
+	}
+
+	return res;
+}
+
+/*
+ * @Test_Aim@ Test to check if DIT bit is preserved across NS/RL switch
+ */
+test_result_t host_realm_enable_dit(void)
+{
+	bool ret1, ret2;
+	struct realm realm;
+	u_register_t rec_flag[] = {RMI_RUNNABLE, RMI_RUNNABLE, RMI_RUNNABLE,
+	RMI_RUNNABLE, RMI_RUNNABLE, RMI_RUNNABLE, RMI_RUNNABLE, RMI_RUNNABLE}, dit;
+
+	SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+
+	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,
+			0UL, rec_flag, MAX_REC_COUNT)) {
+		return TEST_RESULT_FAIL;
+	}
+	if (!host_create_shared_mem(&realm, NS_REALM_SHARED_MEM_BASE,
+			NS_REALM_SHARED_MEM_SIZE)) {
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Enable FEAT_DIT on Host */
+	write_dit(DIT_BIT);
+	for (unsigned int i = 0; i < MAX_REC_COUNT; i++) {
+		host_shared_data_set_host_val(&realm, i, HOST_ARG1_INDEX, 10U);
+		ret1 = host_enter_realm_execute(&realm, REALM_DIT_CHECK_CMD,
+				RMI_EXIT_HOST_CALL, i);
+		if (!ret1) {
+			break;
+		}
+	}
+
+	ret2 = host_destroy_realm(&realm);
+
+	dit = read_dit();
+	if (dit != DIT_BIT) {
+		ERROR("Host DIT bit not preserved\n");
+		return TEST_RESULT_FAIL;
+	}
+
+	write_dit(0U);
+	if (!ret1 || !ret2) {
+		ERROR("%s(): enter=%d destroy=%d\n",
+		__func__, ret1, ret2);
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/runtime_services/secure_service/ffa_helpers.c b/tftf/tests/runtime_services/secure_service/ffa_helpers.c
index ad63e68..8b53bb0 100644
--- a/tftf/tests/runtime_services/secure_service/ffa_helpers.c
+++ b/tftf/tests/runtime_services/secure_service/ffa_helpers.c
@@ -787,10 +787,11 @@
 /**
  * Initializes receiver permissions in a memory transaction descriptor.
  */
-struct ffa_memory_access ffa_memory_access_init_permissions(
+struct ffa_memory_access ffa_memory_access_init(
 	ffa_id_t receiver_id, enum ffa_data_access data_access,
 	enum ffa_instruction_access instruction_access,
-	ffa_memory_receiver_flags_t flags)
+	ffa_memory_receiver_flags_t flags,
+	struct ffa_memory_access_impdef *impdef)
 {
 	struct ffa_memory_access access;
 	access.reserved_0 = 0;
@@ -800,6 +801,8 @@
 	access.receiver_permissions.permissions.data_access = data_access;
 	access.receiver_permissions.permissions.instruction_access =
 		instruction_access;
+	access.impdef = impdef != NULL ? *impdef :
+		(struct ffa_memory_access_impdef){{0, 0}};
 
 	return access;
 }
diff --git a/tftf/tests/runtime_services/secure_service/spm_common.c b/tftf/tests/runtime_services/secure_service/spm_common.c
index dce4b7f..ee25c82 100644
--- a/tftf/tests/runtime_services/secure_service/spm_common.c
+++ b/tftf/tests/runtime_services/secure_service/spm_common.c
@@ -323,7 +323,7 @@
 	 * because `mb->recv` will be overwritten if sending a fragmented
 	 * message.
 	 */
-	memcpy(out, mb->recv, total_size);
+	memcpy(out, mb->recv, fragment_size);
 
 	if (region_out->receiver_count == 0) {
 		VERBOSE("copied region has no recivers\n");
@@ -370,7 +370,7 @@
 			return false;
 		}
 
-		fragment_size = ret.arg3;
+		fragment_size = ret.arg2;
 		if (fragment_size == 0) {
 			ERROR("%s: fragment size must not be 0\n", __func__);
 			return false;
@@ -537,13 +537,13 @@
 		*ret = ffa_mem_donate(total_length, fragment_length);
 		break;
 	default:
-		ERROR("%s: Invalid func id %d!\n", __func__, mem_func);
+		ERROR("%s: Invalid func id %x!\n", __func__, mem_func);
 		return FFA_MEMORY_HANDLE_INVALID;
 	}
 
 	if (is_ffa_call_error(*ret)) {
 		VERBOSE("%s: Failed to send memory: %d\n", __func__,
-			ffa_error_code(ret));
+			ffa_error_code(*ret));
 		return FFA_MEMORY_HANDLE_INVALID;
 	}
 
@@ -827,6 +827,6 @@
 			? FFA_DATA_ACCESS_NOT_SPECIFIED
 			: FFA_DATA_ACCESS_RW;
 
-	return ffa_memory_access_init_permissions(receiver_id, data_access,
-						  instruction_access, 0);
+	return ffa_memory_access_init(receiver_id, data_access,
+				      instruction_access, 0, NULL);
 }
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_exceptions.c b/tftf/tests/runtime_services/secure_service/test_ffa_exceptions.c
index 19f33a2..0a345d4 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_exceptions.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_exceptions.c
@@ -60,7 +60,7 @@
 		return TEST_RESULT_SKIPPED;
 	}
 
-	CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids);
+	CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
 
 	GET_TFTF_MAILBOX(mb);
 
@@ -84,9 +84,12 @@
 		return TEST_RESULT_FAIL;
 	}
 
-	/* Retrieve the shared page and attempt accessing it. */
+	/*
+	 * Retrieve the shared page and attempt accessing it.
+	 * Tell SP to expect an exception.
+	 */
 	ret = cactus_mem_send_cmd(SENDER, RECEIVER, FFA_MEM_SHARE_SMC32,
-				  handle, 0, 1);
+				  handle, 0, 1, true);
 
 	/* Undelegate the shared page. */
 	retmm = host_rmi_granule_undelegate((u_register_t)&share_page);
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c b/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c
index f678a6a..af5a077 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c
@@ -1,14 +1,22 @@
 /*
- * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include "arch_features.h"
+#include "arch_helpers.h"
+#include "ffa_helpers.h"
+#include "ffa_svc.h"
+#include "stdint.h"
+#include "utils_def.h"
 #include <debug.h>
 #include "ffa_helpers.h"
+#include <sync.h>
 
 #include <cactus_test_cmds.h>
 #include <ffa_endpoints.h>
+#include <host_realm_rmi.h>
 #include <spm_common.h>
 #include <spm_test_helpers.h>
 #include <test_helpers.h>
@@ -35,9 +43,12 @@
 /* Memory section to be used for memory share operations */
 static __aligned(PAGE_SIZE) uint8_t
 	share_page[PAGE_SIZE * FRAGMENTED_SHARE_PAGE_COUNT];
+static __aligned(PAGE_SIZE) uint8_t donate_page[PAGE_SIZE];
 static __aligned(PAGE_SIZE) uint8_t consecutive_donate_page[PAGE_SIZE];
 static __aligned(PAGE_SIZE) uint8_t four_share_pages[PAGE_SIZE * 4];
 
+static bool gpc_abort_triggered;
+
 static bool check_written_words(uint32_t *ptr, uint32_t word, uint32_t wcount)
 {
 	VERBOSE("TFTF - Memory contents after SP use:\n");
@@ -90,6 +101,34 @@
 	return true;
 }
 
+static bool data_abort_handler(void)
+{
+	uint64_t esr_elx = IS_IN_EL2() ? read_esr_el2() : read_esr_el1();
+
+	VERBOSE("%s esr_elx %llx\n", __func__, esr_elx);
+
+	if (EC_BITS(esr_elx) == EC_DABORT_CUR_EL) {
+		/* Synchronous data abort triggered by Granule protection */
+		if ((ISS_BITS(esr_elx) & ISS_DFSC_MASK) == DFSC_GPF_DABORT) {
+			VERBOSE("%s GPF Data Abort caught to address: %llx\n",
+				__func__, (uint64_t)read_far_el2());
+			gpc_abort_triggered = true;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static bool get_gpc_abort_triggered(void)
+{
+	bool ret = gpc_abort_triggered;
+
+	gpc_abort_triggered = false;
+
+	return ret;
+}
+
 /**
  * Test invocation to FF-A memory sharing interfaces that should return in an
  * error.
@@ -105,7 +144,7 @@
 		(uintptr_t)0x0000880080001000,
 	};
 
-	CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids);
+	CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
 
 	for (unsigned i = 0; i < 3; i++) {
 		if (!test_memory_send_expect_denied(
@@ -144,6 +183,10 @@
 	ffa_memory_handle_t handle;
 	uint32_t *ptr;
 	struct mailbox_buffers mb;
+	unsigned int rme_supported = get_armv9_2_feat_rme_support();
+	const bool check_gpc_fault =
+		mem_func != FFA_MEM_SHARE_SMC32 &&
+		rme_supported != 0U;
 
 	/* Arbitrarily write 5 words after using memory. */
 	const uint32_t nr_words_to_write = 5;
@@ -155,16 +198,24 @@
 	/***********************************************************************
 	 * Check if SPMC has ffa_version and expected FFA endpoints are deployed.
 	 **********************************************************************/
-	CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids);
+	CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
 
 	GET_TFTF_MAILBOX(mb);
 
-	if (constituents_count != 1) {
-		WARN("Test expects constituents_count to be 1\n");
+	/*
+	 * If the RME is enabled for the platform under test, check that the
+	 * GPCs are working as expected, as such setup the exception handler.
+	 */
+	if (check_gpc_fault) {
+		register_custom_sync_exception_handler(data_abort_handler);
 	}
 
 	for (size_t i = 0; i < constituents_count; i++) {
-		VERBOSE("TFTF - Address: %p\n", constituents[0].address);
+		VERBOSE("Sharing Address: %p\n", constituents[i].address);
+		ptr = (uint32_t *)constituents[i].address;
+		for (size_t j = 0; j < nr_words_to_write; j++) {
+			ptr[j] = mem_func + 0xFFA;
+		}
 	}
 
 	handle = memory_init_and_send((struct ffa_memory_region *)mb.send,
@@ -181,15 +232,21 @@
 	ptr = (uint32_t *)constituents[0].address;
 
 	ret = cactus_mem_send_cmd(SENDER, borrower, mem_func, handle, 0,
-				  nr_words_to_write);
+				  nr_words_to_write, false);
 
-	if (!is_ffa_direct_response(ret)) {
+	if (!is_ffa_direct_response(ret) ||
+	    cactus_get_response(ret) != CACTUS_SUCCESS) {
+		ffa_mem_reclaim(handle, 0);
+		ERROR("Failed memory send operation!\n");
 		return TEST_RESULT_FAIL;
 	}
 
-	if (cactus_get_response(ret) != CACTUS_SUCCESS) {
-		ERROR("Failed memory send operation!\n");
-		return TEST_RESULT_FAIL;
+	/*
+	 * If there is RME support, look to trigger an exception as soon as the
+	 * security state is update, due to GPC fault.
+	 */
+	if (check_gpc_fault) {
+		*ptr = 0xBEEF;
 	}
 
 	if (mem_func != FFA_MEM_DONATE_SMC32) {
@@ -200,12 +257,27 @@
 			return TEST_RESULT_FAIL;
 		}
 
-		/*
-		 * Check that borrower used the memory as expected for this
-		 * test.
-		 */
-		if (!check_written_words(ptr, mem_func, nr_words_to_write)) {
-			ERROR("Fail because of state of memory.\n");
+		for (uint32_t i = 0; i < constituents_count; i++) {
+			ptr = constituents[i].address;
+
+			/*
+			 * Check that borrower used the memory as expected
+			 * for FFA_MEM_SHARE test.
+			 */
+			if (mem_func == FFA_MEM_SHARE_SMC32 &&
+			    !check_written_words(ptr,
+						 mem_func + 0xFFAU,
+						 nr_words_to_write)) {
+				ERROR("Fail because of state of memory.\n");
+				return TEST_RESULT_FAIL;
+			}
+		}
+	}
+
+	if (check_gpc_fault) {
+		unregister_custom_sync_exception_handler();
+		if (!get_gpc_abort_triggered()) {
+			ERROR("No exception due to GPC for lend/donate with RME.\n");
 			return TEST_RESULT_FAIL;
 		}
 	}
@@ -229,6 +301,7 @@
 test_result_t test_mem_lend_sp(void)
 {
 	struct ffa_memory_region_constituent constituents[] = {
+		{(void *)four_share_pages, 4, 0},
 		{(void *)share_page, 1, 0}
 	};
 
@@ -242,7 +315,7 @@
 test_result_t test_mem_donate_sp(void)
 {
 	struct ffa_memory_region_constituent constituents[] = {
-		{(void *)share_page, 1, 0}
+		{(void *)donate_page, 1, 0}
 	};
 	const uint32_t constituents_count = sizeof(constituents) /
 				sizeof(struct ffa_memory_region_constituent);
@@ -258,7 +331,7 @@
 	const uint32_t constituents_count = sizeof(constituents) /
 				sizeof(struct ffa_memory_region_constituent);
 
-	CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids);
+	CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
 
 	test_result_t ret = test_memory_send_sp(FFA_MEM_DONATE_SMC32, SP_ID(1),
 						constituents,
@@ -302,7 +375,7 @@
 	/***********************************************************************
 	 * Check if SPMC's ffa_version and presence of expected FF-A endpoints.
 	 **********************************************************************/
-	CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids);
+	CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
 
 	ret = cactus_req_mem_send_send_cmd(HYP_ID, sender_sp, mem_func,
 					   receiver_sp, non_secure);
@@ -334,7 +407,7 @@
 	/**********************************************************************
 	 * Check if SPMC's ffa_version and presence of expected FF-A endpoints.
 	 *********************************************************************/
-	CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids);
+	CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
 
 	ret = cactus_req_mem_send_send_cmd(HYP_ID, sender_sp, mem_func,
 					   receiver_vm, false);
@@ -418,7 +491,6 @@
 	uint32_t fragment_length;
 	ffa_memory_handle_t handle;
 	struct ffa_value ret;
-	uint32_t *ptr;
 	/* Arbitrarily write 10 words after using shared memory. */
 	const uint32_t nr_words_to_write = 10U;
 
@@ -426,7 +498,7 @@
 		ffa_memory_access_init_permissions_from_mem_func(
 			RECEIVER, FFA_MEM_LEND_SMC32);
 
-	CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids);
+	CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
 
 	GET_TFTF_MAILBOX(mb);
 
@@ -454,7 +526,8 @@
 	VERBOSE("Memory has been shared!\n");
 
 	ret = cactus_mem_send_cmd(SENDER, RECEIVER, FFA_MEM_LEND_SMC32, handle,
-				  FFA_MEMORY_REGION_FLAG_CLEAR, nr_words_to_write);
+				  FFA_MEMORY_REGION_FLAG_CLEAR,
+				  nr_words_to_write, false);
 
 	if (!is_ffa_direct_response(ret)) {
 		return TEST_RESULT_FAIL;
@@ -472,14 +545,6 @@
 		return TEST_RESULT_FAIL;
 	}
 
-	ptr = (uint32_t *)constituents[0].address;
-
-	/* Check that borrower used the memory as expected for this test. */
-	if (!check_written_words(ptr, FFA_MEM_LEND_SMC32, nr_words_to_write)) {
-		ERROR("Words written to shared memory, not as expected.\n");
-		return TEST_RESULT_FAIL;
-	}
-
 	return TEST_RESULT_SUCCESS;
 }
 
@@ -636,6 +701,100 @@
 	return true;
 }
 
+static bool verify_receivers_impdef(struct ffa_memory_access_impdef impdef1,
+				    struct ffa_memory_access_impdef impdef2)
+{
+	if (impdef1.val[0] != impdef2.val[0] ||
+	    impdef1.val[1] != impdef2.val[1]) {
+		ERROR("ipmdef1.val[0]=%llu expected=%llu"
+		      " ipmdef1.val[1]=%llu expected=%llu\n",
+		      impdef1.val[0], impdef2.val[0],
+		      impdef1.val[1], impdef2.val[1]);
+		return false;
+	}
+
+	return true;
+}
+
+static bool verify_permissions(
+		ffa_memory_access_permissions_t permissions1,
+		ffa_memory_access_permissions_t permissions2)
+{
+	uint8_t access1;
+	uint8_t access2;
+
+	access1 = permissions1.data_access;
+	access2 = permissions2.data_access;
+
+	if (access1 != access2) {
+		ERROR("permissions1.data_access=%u expected=%u\n",
+		      access1, access2);
+		return false;
+	}
+
+	access1 = permissions1.instruction_access;
+	access2 = permissions2.instruction_access;
+
+	if (access1 != access2) {
+		ERROR("permissions1.instruction_access=%u expected=%u\n",
+		      access1, access2);
+		return false;
+	}
+
+	return true;
+}
+
+/**
+ * Used by hypervisor retrieve request test: validate descriptors provided by
+ * SPMC.
+ */
+static bool verify_receivers(struct ffa_memory_access *receivers1,
+			     struct ffa_memory_access *receivers2,
+			     uint32_t receivers_count)
+{
+	for (uint32_t i = 0; i < receivers_count; i++) {
+		if (receivers1[i].receiver_permissions.receiver !=
+		    receivers2[i].receiver_permissions.receiver) {
+			ERROR("receivers1[%u].receiver_permissions.receiver=%x"
+			      " expected=%x\n", i,
+			      receivers1[i].receiver_permissions.receiver,
+			      receivers2[i].receiver_permissions.receiver);
+			return false;
+		}
+
+		if (receivers1[i].receiver_permissions.flags !=
+		    receivers2[i].receiver_permissions.flags) {
+			ERROR("receivers1[%u].receiver_permissions.flags=%u"
+			      " expected=%u\n", i,
+			      receivers1[i].receiver_permissions.flags,
+			      receivers2[i].receiver_permissions.flags);
+			return false;
+		}
+
+		if (!verify_permissions(
+			receivers1[i].receiver_permissions.permissions,
+			receivers2[i].receiver_permissions.permissions)) {
+			return false;
+		}
+
+		if (receivers1[i].composite_memory_region_offset !=
+		    receivers2[i].composite_memory_region_offset) {
+			ERROR("receivers1[%u].composite_memory_region_offset=%u"
+			      " expected %u\n",
+			      i, receivers1[i].composite_memory_region_offset,
+			      receivers2[i].composite_memory_region_offset);
+			return false;
+		}
+
+		if (!verify_receivers_impdef(receivers1[i].impdef,
+					     receivers1[i].impdef)) {
+			return false;
+		}
+	}
+
+	return true;
+}
+
 /**
  * Helper for performing a hypervisor retrieve request test.
  */
@@ -644,7 +803,6 @@
 {
 	static struct ffa_memory_region_constituent
 		sent_constituents[FRAGMENTED_SHARE_PAGE_COUNT];
-
 	__aligned(PAGE_SIZE) static uint8_t page[PAGE_SIZE * 2] = {0};
 	struct ffa_memory_region *hypervisor_retrieve_response =
 		(struct ffa_memory_region *)page;
@@ -652,7 +810,8 @@
 	struct mailbox_buffers mb;
 	ffa_memory_handle_t handle;
 	struct ffa_value ret;
-
+	struct ffa_composite_memory_region *composite;
+	struct ffa_memory_access *retrvd_receivers;
 	uint32_t expected_flags = 0;
 
 	ffa_memory_attributes_t expected_attrs = {
@@ -679,10 +838,17 @@
 	uint32_t receiver_count =
 		multiple_receivers ? ARRAY_SIZE(receivers) : 1;
 
-
 	uint32_t sent_constituents_count =
 		fragmented ? ARRAY_SIZE(sent_constituents) : 1;
 
+	/* Prepare the composite offset for the comparison. */
+	for (uint32_t i = 0; i < receiver_count; i++) {
+		receivers[i].composite_memory_region_offset =
+			sizeof(struct ffa_memory_region) +
+			receiver_count *
+				sizeof(struct ffa_memory_access);
+	}
+
 	/* Add a page per constituent, so that we exhaust the size of a single
 	 * fragment (for testing). In a real world scenario, the whole region
 	 * could be described in a single constituent.
@@ -711,8 +877,8 @@
 		panic();
 	}
 
-	handle = memory_init_and_send(mb.send, MAILBOX_SIZE, SENDER, receivers, receiver_count,
-				      sent_constituents,
+	handle = memory_init_and_send(mb.send, MAILBOX_SIZE, SENDER, receivers,
+				      receiver_count, sent_constituents,
 				      sent_constituents_count, mem_func, &ret);
 	if (handle == FFA_MEMORY_HANDLE_INVALID) {
 		ERROR("Memory share failed: %d\n", ffa_error_code(ret));
@@ -733,34 +899,37 @@
 	 * Verify the received `FFA_MEM_RETRIEVE_RESP` aligns with
 	 * transaction description sent above.
 	 */
-	expected_response = (struct ffa_memory_region){
+	expected_response = (struct ffa_memory_region) {
 		.sender = SENDER,
 		.attributes = expected_attrs,
 		.flags = expected_flags,
 		.handle = handle,
 		.tag = 0,
 		.memory_access_desc_size = sizeof(struct ffa_memory_access),
-		.receiver_count = 1,
+		.receiver_count = receiver_count,
 		.receivers_offset =
 			offsetof(struct ffa_memory_region, receivers),
 	};
-	if (!verify_retrieve_response(hypervisor_retrieve_response, &expected_response)) {
+
+	if (!verify_retrieve_response(hypervisor_retrieve_response,
+				      &expected_response)) {
 		return TEST_RESULT_FAIL;
 	}
 
-	for (uint32_t i = 0; i < hypervisor_retrieve_response->receiver_count; i++) {
-		struct ffa_composite_memory_region *composite =
-			ffa_memory_region_get_composite(
-				hypervisor_retrieve_response, i);
-		if (composite == NULL) {
-			ERROR("composite %d is null\n", i);
-			return TEST_RESULT_FAIL;
-		}
+	retrvd_receivers =
+		ffa_memory_region_get_receiver(hypervisor_retrieve_response, 0);
 
-		if (!verify_composite(composite, &composite->constituents[i],
-				      sent_constituents_count, sent_constituents_count)) {
-			return TEST_RESULT_FAIL;
-		}
+	if (!verify_receivers(retrvd_receivers,
+			      receivers, receiver_count)) {
+		return TEST_RESULT_FAIL;
+	}
+
+	composite = ffa_memory_region_get_composite(
+				hypervisor_retrieve_response, 0);
+
+	if (!verify_composite(composite, composite->constituents,
+			      sent_constituents_count, sent_constituents_count)) {
+		return TEST_RESULT_FAIL;
 	}
 
 	/*
@@ -809,3 +978,186 @@
 {
 	return hypervisor_retrieve_request_test_helper(FFA_MEM_LEND_SMC32, false, true);
 }
+
+/**
+ * Test helper that performs memory sharing operation, and alters the PAS
+ * of the memory, to validate that SPM intersects the operation in case the PAS
+ * is not coherent with its use. Relevant for the functioning of FFA_MEM_LEND
+ * and FFA_MEM_DONATE from NWd to an SP.
+ *
+ * In cases the memory is not in NS state, the SPMC should intersect memory
+ * management call with an appropriate FFA_ERROR.
+ */
+static test_result_t test_ffa_mem_send_realm_expect_fail(
+		uint32_t mem_func, ffa_id_t borrower,
+		struct ffa_memory_region_constituent *constituents,
+		size_t constituents_count, uint64_t delegate_addr)
+{
+	struct ffa_value ret;
+	uint32_t remaining_constituent_count;
+	uint32_t total_length;
+	uint32_t fragment_length;
+	struct mailbox_buffers mb;
+	u_register_t ret_rmm;
+	test_result_t result = TEST_RESULT_FAIL;
+	struct ffa_memory_access receiver =
+		ffa_memory_access_init_permissions_from_mem_func(borrower,
+								 mem_func);
+
+	if (get_armv9_2_feat_rme_support() == 0U) {
+		return TEST_RESULT_SKIPPED;
+	}
+
+	/***********************************************************************
+	 * Check if SPMC has ffa_version and expected FFA endpoints are deployed.
+	 **********************************************************************/
+	CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
+
+	GET_TFTF_MAILBOX(mb);
+
+	register_custom_sync_exception_handler(data_abort_handler);
+
+	/*
+	 * Delegate page to a realm. This should make memory sharing operation
+	 * fail.
+	 */
+	ret_rmm = host_rmi_granule_delegate((u_register_t)delegate_addr);
+
+	if (ret_rmm != 0UL) {
+		INFO("Delegate operation returns 0x%lx for address %llx\n",
+		     ret_rmm, delegate_addr);
+		return TEST_RESULT_FAIL;
+	}
+
+	remaining_constituent_count = ffa_memory_region_init(
+		(struct ffa_memory_region *)mb.send, MAILBOX_SIZE, SENDER,
+		&receiver, 1, constituents, constituents_count, 0,
+		FFA_MEMORY_REGION_FLAG_CLEAR,
+		FFA_MEMORY_NOT_SPECIFIED_MEM, 0, 0,
+		&total_length, &fragment_length);
+
+	if (remaining_constituent_count != 0) {
+		goto out;
+	}
+
+	switch (mem_func) {
+	case FFA_MEM_LEND_SMC32:
+		ret = ffa_mem_lend(total_length, fragment_length);
+		break;
+	case FFA_MEM_DONATE_SMC32:
+		ret = ffa_mem_donate(total_length, fragment_length);
+		break;
+	default:
+		ERROR("Not expected for func name: %x\n", mem_func);
+		return TEST_RESULT_FAIL;
+	}
+
+	if (!is_expected_ffa_error(ret, FFA_ERROR_DENIED)) {
+		goto out;
+	}
+
+	/* Undelegate to reestablish the same security state for PAS. */
+	ret_rmm = host_rmi_granule_undelegate((u_register_t)delegate_addr);
+
+	for (uint32_t i = 0; i < constituents_count; i++) {
+		uint32_t *ptr = (uint32_t *)constituents[i].address;
+
+		*ptr = 0xFFA;
+	}
+
+	if (get_gpc_abort_triggered()) {
+		ERROR("Exception due to GPC for lend/donate with RME. Not"
+		      " expected for this case.\n");
+		result = TEST_RESULT_FAIL;
+	} else {
+		result = TEST_RESULT_SUCCESS;
+	}
+out:
+	unregister_custom_sync_exception_handler();
+
+	if (ret_rmm != 0UL) {
+		INFO("Undelegate operation returns 0x%lx for address %llx\n",
+		     ret_rmm, (uint64_t)delegate_addr);
+		return TEST_RESULT_FAIL;
+	}
+
+	return result;
+}
+
+/**
+ * Memory to be shared between partitions is described in a composite, with
+ * various constituents. In an RME system, the memory must be in NS PAS in
+ * operations from NWd to an SP. In case the PAS is not following this
+ * expectation memory lend/donate should fail, and all constituents must
+ * remain in the NS PAS.
+ *
+ * This test validates that if one page in the middle of one of the constituents
+ * is not in the NS PAS the operation fails.
+ */
+test_result_t test_ffa_mem_send_sp_realm_memory(void)
+{
+	test_result_t ret;
+	uint32_t mem_func[] = {FFA_MEM_LEND_SMC32, FFA_MEM_DONATE_SMC32};
+	struct ffa_memory_region_constituent constituents[] = {
+		{(void *)four_share_pages, 4, 0},
+		{(void *)share_page, 1, 0}
+	};
+
+	const uint32_t constituents_count = sizeof(constituents) /
+				sizeof(struct ffa_memory_region_constituent);
+
+	for (unsigned j = 0; j < ARRAY_SIZE(mem_func); j++) {
+		for (unsigned int i = 0; i < 4; i++) {
+			/* Address to be delegated to Realm PAS. */
+			uint64_t realm_addr =
+				(uint64_t)&four_share_pages[i * PAGE_SIZE];
+
+			INFO("%s memory with realm addr: %llx\n",
+			     mem_func[j] == FFA_MEM_LEND_SMC32
+				? "Lend"
+				: "Donate",
+			     realm_addr);
+
+			ret = test_ffa_mem_send_realm_expect_fail(
+				mem_func[j], SP_ID(1), constituents,
+				constituents_count, realm_addr);
+
+			if (ret != TEST_RESULT_SUCCESS) {
+				break;
+			}
+		}
+	}
+
+	return ret;
+}
+
+/**
+ * Memory to be shared between partitions is described in a composite, with
+ * various constituents. In an RME system, the memory must be in NS PAS in
+ * operations from NWd to an SP. In case the PAS is not following this
+ * expectation memory lend/donate should fail, and all constituents must
+ * remain in the NS PAS.
+ *
+ * This test validates the case in which the memory lend/donate fail in
+ * case one of the constituents in the composite is not in the NS PAS.
+ */
+test_result_t test_ffa_mem_lend_sp_realm_memory_separate_constituent(void)
+{
+	test_result_t ret;
+	struct ffa_memory_region_constituent constituents[] = {
+		{(void *)four_share_pages, 4, 0},
+		{(void *)share_page, 1, 0}
+	};
+	const uint32_t constituents_count = sizeof(constituents) /
+				sizeof(struct ffa_memory_region_constituent);
+	/* Address to be delegated to Realm PAS. */
+	uint64_t realm_addr = (uint64_t)&share_page[0];
+
+	INFO("Sharing memory with realm addr: %llx\n", realm_addr);
+
+	ret = test_ffa_mem_send_realm_expect_fail(
+		FFA_MEM_LEND_SMC32, SP_ID(1), constituents,
+		constituents_count, realm_addr);
+
+	return ret;
+}
diff --git a/tftf/tests/runtime_services/secure_service/test_spm_cpu_features.c b/tftf/tests/runtime_services/secure_service/test_spm_simd.c
similarity index 100%
rename from tftf/tests/runtime_services/secure_service/test_spm_cpu_features.c
rename to tftf/tests/runtime_services/secure_service/test_spm_simd.c
diff --git a/tftf/tests/runtime_services/secure_service/test_spm_smmu.c b/tftf/tests/runtime_services/secure_service/test_spm_smmu.c
index ae2068a..6237eb8 100644
--- a/tftf/tests/runtime_services/secure_service/test_spm_smmu.c
+++ b/tftf/tests/runtime_services/secure_service/test_spm_smmu.c
@@ -20,8 +20,20 @@
 #define TEST_DMA_ENGINE_MEMCPY	(2U)
 #define TEST_DMA_ENGINE_RAND48	(3U)
 
-#define TEST_DMA_ENGINE_ATTR_DEST_ACACHE_RAWAWB_S	(0xffU)
-#define TEST_DMA_ENGINE_ATTR_DEST_ACACHE_RAWAWB_NS	(0x2ffU)
+/*
+ * Attribute encoding for Inner and Outer:
+ * Read-Allocate Write-Allocate Write-Back Normal Memory
+ */
+#define ATTR_ACACHE_RAWAWB_S	(0xffU)
+#define ATTR_ACACHE_RAWAWB_NS	(0x2ffU)
+
+/* Source attributes occupy the bottom halfword */
+#define DMA_ENGINE_ATTR_SRC_ACACHE_RAWAWB_S	ATTR_ACACHE_RAWAWB_S
+#define DMA_ENGINE_ATTR_SRC_ACACHE_RAWAWB_NS	ATTR_ACACHE_RAWAWB_NS
+
+/* Destination attributes occupy the top halfword */
+#define DMA_ENGINE_ATTR_DEST_ACACHE_RAWAWB_S	(ATTR_ACACHE_RAWAWB_S << 16)
+#define DMA_ENGINE_ATTR_DEST_ACACHE_RAWAWB_NS	(ATTR_ACACHE_RAWAWB_NS << 16)
 
 /**************************************************************************
  * test_smmu_spm
@@ -54,7 +66,7 @@
 		TEST_DMA_ENGINE_RAND48,
 		PLAT_CACTUS_MEMCPY_BASE,
 		PLAT_CACTUS_MEMCPY_RANGE / 2,
-		TEST_DMA_ENGINE_ATTR_DEST_ACACHE_RAWAWB_S << 16);
+		DMA_ENGINE_ATTR_DEST_ACACHE_RAWAWB_S);
 
 	/* Expect the SMMU DMA operation to pass. */
 	if (cactus_get_response(ret) != CACTUS_SUCCESS) {
@@ -70,8 +82,27 @@
 		TEST_DMA_ENGINE_MEMCPY,
 		PLAT_CACTUS_MEMCPY_BASE,
 		PLAT_CACTUS_MEMCPY_RANGE,
-		(TEST_DMA_ENGINE_ATTR_DEST_ACACHE_RAWAWB_S << 16) |
-		TEST_DMA_ENGINE_ATTR_DEST_ACACHE_RAWAWB_S);
+		DMA_ENGINE_ATTR_DEST_ACACHE_RAWAWB_S |
+		DMA_ENGINE_ATTR_SRC_ACACHE_RAWAWB_S);
+
+	/* Expect the SMMU DMA operation to pass. */
+	if (cactus_get_response(ret) != CACTUS_SUCCESS) {
+		return TEST_RESULT_FAIL;
+	}
+
+	/*
+	 * Copy first half to second half of the non-secure buffer and
+	 * check both match.
+	 * Source and destination memory attributes are non-secure rawaWB.
+	 * This test helps to validate a scenario where a secure stream
+	 * belonging to Cactus SP accesses non-secure IPA space.
+	 */
+	ret = cactus_send_dma_cmd(HYP_ID, SP_ID(1),
+		TEST_DMA_ENGINE_MEMCPY,
+		PLAT_CACTUS_NS_MEMCPY_BASE,
+		PLAT_CACTUS_MEMCPY_RANGE,
+		DMA_ENGINE_ATTR_DEST_ACACHE_RAWAWB_NS |
+		DMA_ENGINE_ATTR_SRC_ACACHE_RAWAWB_NS);
 
 	/* Expect the SMMU DMA operation to pass. */
 	if (cactus_get_response(ret) != CACTUS_SUCCESS) {
@@ -127,7 +158,7 @@
 		TEST_DMA_ENGINE_RAND48,
 		PLAT_CACTUS_NS_MEMCPY_BASE,
 		PLAT_CACTUS_MEMCPY_RANGE,
-		TEST_DMA_ENGINE_ATTR_DEST_ACACHE_RAWAWB_NS << 16);
+		DMA_ENGINE_ATTR_DEST_ACACHE_RAWAWB_NS);
 
 	/* Update the buffer back to NS PAS. */
 	retmm = host_rmi_granule_undelegate((u_register_t)PLAT_CACTUS_NS_MEMCPY_BASE);
diff --git a/tftf/tests/tbb-tests/tbb_test_infra.c b/tftf/tests/tbb-tests/tbb_test_infra.c
new file mode 100644
index 0000000..dc8ae38
--- /dev/null
+++ b/tftf/tests/tbb-tests/tbb_test_infra.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "tbb_test_infra.h"
+
+#include <fwu_nvm.h>
+#include <io_storage.h>
+#include <platform.h>
+#include <status.h>
+#include <test_helpers.h>
+#include <tftf_lib.h>
+
+test_result_t test_corrupt_boot_fip(unsigned int offset)
+{
+	unsigned int flag = 0xDEADBEEF;
+	size_t written = 0;
+	uintptr_t dev_handle;
+	int result;
+
+	if (tftf_is_rebooted()) {
+		/* FIP successfully repaired */
+		return TEST_RESULT_SUCCESS;
+	}
+
+	/* Corrupt the FIP at the provided offset */
+	plat_get_nvm_handle(&dev_handle);
+	result = io_seek(dev_handle, IO_SEEK_SET, offset);
+	TEST_ASSERT(result == IO_SUCCESS);
+	result = io_write(dev_handle, (uintptr_t) &flag, sizeof(flag), &written);
+	TEST_ASSERT(result == IO_SUCCESS);
+	TEST_ASSERT(written == sizeof(flag));
+
+	/*
+	 * Now reboot the system.
+	 * On the next boot, EL3 firmware should notice and repair the corruption
+	 * before re-entering TFTF
+	 */
+
+	tftf_notify_reboot();
+	psci_system_reset();
+	return TEST_RESULT_FAIL;
+}
diff --git a/tftf/tests/tbb-tests/tbb_test_infra.h b/tftf/tests/tbb-tests/tbb_test_infra.h
new file mode 100644
index 0000000..e6bf0e5
--- /dev/null
+++ b/tftf/tests/tbb-tests/tbb_test_infra.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TBB_TEST_INFRA_H_INCLUDED
+#define TBB_TEST_INFRA_H_INCLUDED
+
+#include <tftf_lib.h>
+
+test_result_t test_corrupt_boot_fip(unsigned int offset);
+
+#endif /* TBB_TEST_INFRA_H_INCLUDED */
+
diff --git a/tftf/tests/tbb-tests/test_tbb_corrupt_fip.c b/tftf/tests/tbb-tests/test_tbb_corrupt_fip.c
new file mode 100644
index 0000000..135efee
--- /dev/null
+++ b/tftf/tests/tbb-tests/test_tbb_corrupt_fip.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <uuid.h>
+
+#include "tbb_test_infra.h"
+
+#include <firmware_image_package.h>
+#include <platform.h>
+#include <tftf_lib.h>
+#include <uuid_utils.h>
+
+/*
+ * Return the offset relative to the base of the FIP of
+ * the image described by the uuid. 0 is returned on failure.
+ * The first image will not have an offset of 0, as the header
+ * exists at offset 0.
+ */
+static unsigned int
+find_offset_in_fip(const uuid_t *uuid)
+{
+	fip_toc_entry_t *current_file =
+		(fip_toc_entry_t *) (PLAT_ARM_FIP_BASE + sizeof(fip_toc_header_t));
+
+	while (!is_uuid_null(&(current_file->uuid))) {
+		if (uuid_equal(&(current_file->uuid), uuid)) {
+			return current_file->offset_address;
+		}
+		current_file += 1;
+	};
+	return 0;
+}
+
+test_result_t test_tbb_tkey_cert_header(void)
+{
+	static const uuid_t tkey_cert_uuid = UUID_TRUSTED_KEY_CERT;
+	unsigned int image_offset = find_offset_in_fip(&tkey_cert_uuid);
+
+	TEST_ASSERT_SKIP(image_offset != 0);
+	return test_corrupt_boot_fip(image_offset);
+}
+
diff --git a/tftf/tests/tests-corrupt-fip.mk b/tftf/tests/tests-corrupt-fip.mk
new file mode 100644
index 0000000..22fa686
--- /dev/null
+++ b/tftf/tests/tests-corrupt-fip.mk
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2023, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+TESTS_SOURCES	+=	$(addprefix tftf/tests/tbb-tests/,	\
+	test_tbb_corrupt_fip.c						\
+	tbb_test_infra.c						\
+)
+
+TESTS_SOURCES	+=	plat/common/fwu_nvm_accessors.c \
+	plat/arm/common/arm_fwu_io_storage.c \
+	drivers/io/io_fip.c \
+	drivers/io/io_memmap.c
diff --git a/tftf/tests/tests-corrupt-fip.xml b/tftf/tests/tests-corrupt-fip.xml
new file mode 100644
index 0000000..6bfa4a4
--- /dev/null
+++ b/tftf/tests/tests-corrupt-fip.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright (c) 2023, Arm Limited. All rights reserved.
+
+  SPDX-License-Identifier: BSD-3-Clause
+-->
+
+<testsuites>
+
+  <testsuite name="tbb corrupt trusted key header" description="The FIP is corrupted before update">
+     <testcase name="tbb bad tkey cert header" function="test_tbb_tkey_cert_header" />
+  </testsuite>
+
+</testsuites>
diff --git a/tftf/tests/tests-invalid-access.xml b/tftf/tests/tests-invalid-access.xml
deleted file mode 100644
index 33b85c5..0000000
--- a/tftf/tests/tests-invalid-access.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
-  Copyright (c) 2023, Arm Limited. All rights reserved.
-
-  SPDX-License-Identifier: BSD-3-Clause
--->
-
-<testsuites>
-  <testsuite name="Invalid memory access" description="Invalid memory access">
-      <testcase name="Access EL3 memory from NS world"
-                function="el3_memory_cannot_be_accessed_in_ns" />
-      <testcase name="Access Secure memory from NS world"
-                function="s_memory_cannot_be_accessed_in_ns" />
-  </testsuite>
-
-  <testsuite name="Invalid memory access with RME extension"
-    description="Invalid memory access with RME extension">
-      <testcase name="Access Realm memory from NS world"
-                function="rl_memory_cannot_be_accessed_in_ns" />
-      <testcase name="Access Secure memory from Realm world"
-                function="s_memory_cannot_be_accessed_in_rl" />
-      <testcase name="Access Root memory from Realm world"
-                function="rt_memory_cannot_be_accessed_in_rl" />
-      <testcase name="Share memory to an SP from a Root region"
-                function="rt_memory_cannot_be_accessed_in_s" />
-  </testsuite>
-</testsuites>
diff --git a/tftf/tests/tests-invalid-access.mk b/tftf/tests/tests-memory-access.mk
similarity index 94%
rename from tftf/tests/tests-invalid-access.mk
rename to tftf/tests/tests-memory-access.mk
index 346ba9d..13b2241 100644
--- a/tftf/tests/tests-invalid-access.mk
+++ b/tftf/tests/tests-memory-access.mk
@@ -24,6 +24,7 @@
 		${ARCH}/ffa_arch_helpers.S				\
 		ffa_helpers.c						\
 		spm_common.c						\
+		test_ffa_memory_sharing.c				\
 		test_ffa_setup_and_discovery.c				\
 		spm_test_helpers.c					\
 )
diff --git a/tftf/tests/tests-memory-access.xml b/tftf/tests/tests-memory-access.xml
new file mode 100644
index 0000000..4318cc9
--- /dev/null
+++ b/tftf/tests/tests-memory-access.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright (c) 2024, Arm Limited. All rights reserved.
+
+  SPDX-License-Identifier: BSD-3-Clause
+-->
+
+<testsuites>
+
+  <testsuite name="FF-A Memory Sharing (RME)"
+             description="Test FF-A Memory Sharing ABIs" >
+     <testcase name="Lend Memory to Secure World"
+               function="test_mem_lend_sp" />
+     <testcase name="Lend memory, clear flag set"
+               function="test_mem_share_to_sp_clear_memory"/>
+     <testcase name="Share Memory with Secure World"
+               function="test_mem_share_sp" />
+     <testcase name="Donate Memory to Secure World"
+               function="test_mem_donate_sp"/>
+     <testcase name="Request Share Memory SP-to-SP"
+               function="test_req_mem_share_sp_to_sp" />
+     <testcase name="Request Lend Memory SP-to-SP"
+               function="test_req_mem_lend_sp_to_sp" />
+     <testcase name="Request Donate Memory SP-to-SP"
+               function="test_req_mem_donate_sp_to_sp" />
+     <testcase name="Request Share NS Memory (large PA) SP-to-SP"
+               function="test_req_ns_mem_share_sp_to_sp" />
+     <testcase name="Request Share Memory SP-to-VM"
+               function="test_req_mem_share_sp_to_vm" />
+     <testcase name="Request Lend Memory SP-to-VM"
+               function="test_req_mem_lend_sp_to_vm" />
+     <testcase name="Share forbidden memory with SP"
+               function="test_share_forbidden_ranges" />
+     <testcase name="Donate consecutively"
+               function="test_consecutive_donate" />
+  </testsuite>
+
+  <testsuite name="Invalid memory access" description="Invalid memory access">
+      <testcase name="Access EL3 memory from NS world"
+                function="el3_memory_cannot_be_accessed_in_ns" />
+      <testcase name="Access Secure memory from NS world"
+                function="s_memory_cannot_be_accessed_in_ns" />
+  </testsuite>
+
+  <testsuite name="Invalid memory access with RME extension"
+    description="Invalid memory access with RME extension">
+      <testcase name="Access Realm memory from NS world"
+                function="rl_memory_cannot_be_accessed_in_ns" />
+      <testcase name="Access Secure memory from Realm world"
+                function="s_memory_cannot_be_accessed_in_rl" />
+      <testcase name="Access Root memory from Realm world"
+                function="rt_memory_cannot_be_accessed_in_rl" />
+      <testcase name="Share memory to an SP from a Root region"
+                function="rt_memory_cannot_be_accessed_in_s" />
+      <testcase name="FF-A memory share fails if using realm memory"
+                function="test_ffa_mem_send_sp_realm_memory" />
+      <testcase name="FF-A memory share fail realm memory other constituent"
+                function="test_ffa_mem_lend_sp_realm_memory_separate_constituent" />
+  </testsuite>
+
+</testsuites>
diff --git a/tftf/tests/tests-realm-payload.xml b/tftf/tests/tests-realm-payload.xml
index 68d68dd..0ecefee 100644
--- a/tftf/tests/tests-realm-payload.xml
+++ b/tftf/tests/tests-realm-payload.xml
@@ -16,6 +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="Realm SEA Empty"
+	  function="host_realm_sea_empty" />
+	  <testcase name="Realm SEA Unprotected"
+	  function="host_realm_sea_unprotected" />
+	  <testcase name="Realm Abort Unassigned RAM"
+	  function="host_realm_abort_unassigned_ram" />
+	  <testcase name="Realm Abort Unassigned Destroyed"
+	  function="host_realm_abort_unassigned_destroyed" />
+	  <testcase name="Realm Abort Assigned destroyed"
+	  function="host_realm_abort_assigned_destroyed" />
 	  <testcase name="Realm payload multi rec single cpu"
 	  function="host_realm_multi_rec_single_cpu" />
 	  <testcase name="Realm payload multi rec psci denied"
@@ -87,5 +97,7 @@
 	  function="host_realm_enable_pauth" />
 	  <testcase name="Generate PAuth Fault by overwriting LR"
 	  function="host_realm_pauth_fault" />
+	  <testcase name="Check if DIT Bit is preserved in RL/NS"
+	  function="host_realm_enable_dit" />
   </testsuite>
 </testsuites>
diff --git a/tftf/tests/tests-rmi-spm.mk b/tftf/tests/tests-rmi-spm.mk
index 12ebb5a..735e191 100644
--- a/tftf/tests/tests-rmi-spm.mk
+++ b/tftf/tests/tests-rmi-spm.mk
@@ -21,6 +21,7 @@
 		${ARCH}/ffa_arch_helpers.S				\
 		ffa_helpers.c						\
 		spm_common.c						\
+		spm_test_helpers.c					\
 	)
 
 TESTS_SOURCES	+=							\
diff --git a/tftf/tests/tests-smcfuzzing.mk b/tftf/tests/tests-smcfuzzing.mk
index 738e1d6..2834e4e 100644
--- a/tftf/tests/tests-smcfuzzing.mk
+++ b/tftf/tests/tests-smcfuzzing.mk
@@ -46,4 +46,5 @@
 		runtestfunction_helpers.c				\
 		sdei_fuzz_helper.c					\
 		tsp_fuzz_helper.c					\
+		nfifo.c							\
 	)
diff --git a/tftf/tests/tests-spm.mk b/tftf/tests/tests-spm.mk
index 174e11d..97b3a49 100644
--- a/tftf/tests/tests-spm.mk
+++ b/tftf/tests/tests-spm.mk
@@ -27,7 +27,7 @@
 ifeq (${ARCH},aarch64)
 TESTS_SOURCES   +=                                                      \
         $(addprefix tftf/tests/runtime_services/secure_service/,        \
-	  test_spm_cpu_features.c					\
+	  test_spm_simd.c					\
 	 )
 
 TESTS_SOURCES	+=							\
diff --git a/tftf/tests/tests-spm.xml b/tftf/tests/tests-spm.xml
index b682837..09e0fd7 100644
--- a/tftf/tests/tests-spm.xml
+++ b/tftf/tests/tests-spm.xml
@@ -88,6 +88,20 @@
 
   <testsuite name="FF-A Memory Sharing"
              description="Test FF-A Memory Sharing ABIs" >
+     <testcase name="Hypervisor share + memory retrieve request"
+               function="test_hypervisor_share_retrieve" />
+     <testcase name="Hypervisor lend + memory retrieve request"
+               function="test_hypervisor_lend_retrieve" />
+     <testcase name="Hypervisor donate + memory retrieve request"
+               function="test_hypervisor_donate_retrieve" />
+     <testcase name="Hypervisor share + memory retrieve request (multiple receivers)"
+               function="test_hypervisor_share_retrieve_multiple_receivers" />
+     <testcase name="Hypervisor lend + memory retrieve request (multiple receivers)"
+               function="test_hypervisor_lend_retrieve_multiple_receivers" />
+     <testcase name="Hypervisor share + memory retrieve request (fragmented)"
+               function="test_hypervisor_share_retrieve_fragmented" />
+     <testcase name="Hypervisor lend + memory retrieve request (fragmented)"
+               function="test_hypervisor_lend_retrieve_fragmented" />
      <testcase name="Lend Memory to Secure World"
                function="test_mem_lend_sp" />
      <testcase name="Lend memory, clear flag set"
diff --git a/tftf/tests/tests-undef-injection.mk b/tftf/tests/tests-undef-injection.mk
new file mode 100644
index 0000000..e13df17
--- /dev/null
+++ b/tftf/tests/tests-undef-injection.mk
@@ -0,0 +1,7 @@
+#
+# Copyright (c) 2023, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+TESTS_SOURCES	+=	tftf/tests/misc_tests/test_undef_injection.c
diff --git a/tftf/tests/tests-undef-injection.xml b/tftf/tests/tests-undef-injection.xml
new file mode 100644
index 0000000..0d43cdf
--- /dev/null
+++ b/tftf/tests/tests-undef-injection.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright (c) 2023, Arm Limited. All rights reserved.
+
+  SPDX-License-Identifier: BSD-3-Clause
+-->
+
+<testsuites>
+  <testsuite name="UNDEF Injection" description="UNDEF injection from EL3 to lower EL">
+      <testcase name="UNDEF Injection to lower EL"
+                function="test_undef_injection" />
+  </testsuite>
+</testsuites>