Merge changes from topic "qemu_tests"

* changes:
  fix(test): compile error in test_irq_spurious_gicv2.c
  feat(timer): support PPI timer interrupts
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..1946491
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "ext/mbedtls"]
+	path = ext/mbedtls
+	url = https://github.com/Mbed-TLS/mbedtls.git
diff --git a/Makefile b/Makefile
index e7efa2e..4936ff7 100644
--- a/Makefile
+++ b/Makefile
@@ -1,12 +1,12 @@
 #
-# Copyright (c) 2018-2023, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2024, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
 # TFTF Version
 VERSION_MAJOR		:= 2
-VERSION_MINOR		:= 11
+VERSION_MINOR		:= 12
 
 MAKE_HELPERS_DIRECTORY := make_helpers/
 include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
@@ -134,8 +134,8 @@
 # List of secure partitions present.
 SECURE_PARTITIONS	:=
 
-# Only platform fvp supports cactus_mm
-ifeq (${ARCH}-${PLAT},aarch64-fvp)
+# Only platform fvp and rdv3 supports cactus_mm
+ifeq (${ARCH}-${PLAT},$(filter ${ARCH}-${PLAT},aarch64-fvp aarch64-rdv3))
 include spm/cactus_mm/cactus_mm.mk
 include realm/realm.mk
 endif
@@ -432,7 +432,7 @@
 	@exit 1
 endif
 
-ifneq (${ARCH}-${PLAT},aarch64-fvp)
+ifneq (${ARCH}-${PLAT},$(filter ${ARCH}-${PLAT},aarch64-fvp aarch64-rdv3))
 .PHONY: cactus_mm
 cactus_mm:
 	@echo "ERROR: $@ is supported only on AArch64 FVP."
@@ -440,7 +440,7 @@
 
 .PHONY: realm
 realm:
-	@echo "ERROR: $@ is supported only on AArch64 FVP."
+	@echo "ERROR: $@ is supported only on AArch64 FVP and RD-V3."
 	@exit 1
 
 endif
diff --git a/docs/change-log.rst b/docs/change-log.rst
index 89d9c10..0f22ded 100644
--- a/docs/change-log.rst
+++ b/docs/change-log.rst
@@ -7,6 +7,139 @@
 Tests are not guaranteed to be compatible. This also means that a version
 upgrade on the TF-A-Tests side might not necessarily introduce any new feature.
 
+Version 2.12
+------------
+
+New features
+^^^^^^^^^^^^
+
+-  More tests are made available in this release to help validate the
+   functionalities in the following areas:
+
+   - FF-A
+   - Realm Management Extension
+   - EL3 Runtime
+   - New Platform ports
+
+TFTF
+^^^^
+
+- SPM/FF-A Testing:
+
+    - Added tests to attest SPMC handles GPF in memory sharing ABIs:
+
+        - FFA_MEM_RETRIEVE_REQ
+        - FFA_MEM_FRAG_RX/TX
+        - FFA_MEM_RELINQUISH
+
+    - Added tests using the SMC64 ABI version for the FF-A memory management
+      interfaces.
+    - Tests to attest the SPMC is doing the necessary context management
+      of SME registers.
+    - Check that SRI delay flag use from normal world results in an error.
+    - FF-A Setup and discovery interfaces:
+
+        - FFA_VERSION called restricted to be used until first FF-A call,
+          from a given endpoint is handled.
+        - FFA_FEATURES tests changed to cater for feature return based on
+          EL of the FF-A endpoint, and the security state it relates to.
+        - FFA_PARTITION_INFO_GET changed to report support of indirect
+          messaging.
+
+  - New tests
+
+    - Added AMU counter restriction (RAZ) test.
+    - Added test to validate EL1 and EL2 registers during context switch.
+    - Added PCIe DOE library and tests.
+    - Added tests for newly supported features FEAT_FGT2, LS64_ACCDATA,
+      FEAT_Debugv8p9.
+    - Added test for 64-byte load/store instructions introduced by LS64.
+    - Added asymmetric feature testing for FEAT_SPE, FEAT_TRBE, and FEAT_TCR2.
+    - Added a new test suite supported by EL3 SPMC.
+    - Added SDEI tests for attempting to bind too many events.
+    - Added test suite to exercise SIMD context management with Cactus SP
+      (supported by EL3 SPMC).
+
+- Platforms
+
+    - Corstone-1000:
+
+        - Updated test skip list.
+
+    - FVP:
+
+        - Added PCIe support.
+
+    - Neoverse-RD:
+
+        - Defined naming convention for CSS macros.
+        - Introduced flash and ROS macros.
+        - Introduced timer and watchdog macros.
+        - Refactored header files for first gen platforms.
+        - refactored header files for second gen platforms.
+        - Removed deprecated header files.
+
+    - Versal-2:
+
+        - Added support for AMD Versal Gen 2 platform.
+        - Added AMD Versal Gen 2 documentation.
+
+- Miscellaneous:
+
+    - Added skeleton for asymmetric feature testing capability.
+    - Added asymmetric tests to skip when features are not present on a core.
+    - Added test to ensure arch timer in NWd is honored across world switch.
+    - Added test to confirm errata 2938996/2726228 workaround by checking
+      trbe_el1 access.
+    - Fixed GICD_ITARGETSR assertion to relax check on unicore systems.
+    - Fixed expect to print file and line number on failure for easier debugging.
+    - Fixed TRBE extension test to skip on Cortex-A520 and Cortex-X4 due to errata.
+    - Refactored to register undef_injection_handler only during register accesses
+      for better control over exceptions.
+    - Fixed firmware handoff register convention value to match updated spec.
+    - Updated toolchain requirements.
+
+Realm Management Extension
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+    - Set number of num_bps and num_wps.
+    - Updated rsi_ipa_state_get() function.
+    - Increased maximum number of RECs.
+    - Use random start REC.
+    - Added specific tests for FEAT_LPA2 on RMI tests.
+    - Added support for FEAT_LPA2 to the Realm Extension tests.
+    - Added test for rtt_fold unassigned.
+    - Added test for rtt_fold assigned.
+    - Unified SIMD test cases.
+    - Fixed pauth exception test.
+    - Fix(realm): cater for removal of SH from rtte.
+    - Fixed RMI and RSI definitions to match RMM Specification 1.0-rel0-rc1.
+    - Fixed RMI commands arguments descriptions.
+    - Fixed calculation of Realm's REC index.
+    - Fixed host_realm_init_ipa_state()'s retry path.
+    - Fixed realm initialisation code.
+    - Separated pool creation from Realm creation helpers.
+    - Fixed tests passing with TRP but not with RMM.
+
+Cactus (Secure-EL1 FF-A test partition)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    - Added support for Cactus SP to boot on EL3 SPMC.
+    - Added fix to skip computing linear core id.
+    - Fixed cactus_mm verbosity on some tests.
+
+Issues resolved since last release
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+    - Added "build" directory dependency to ensure correct ordering
+      on slow systems.
+    - Fixed race condition in tests_list generation by using grouped target.
+    - Fixed virtual timer enablement by moving it to command handler.
+    - Fixed test case test_smccc_callee_preserved.
+    - Updated definitions for sysregs on older toolchains.
+    - Fixed undef_injection_handler to clarify it catches both undef injections
+  and EL2 register traps.
+
 Version 2.11
 ------------
 
diff --git a/docs/getting_started/obtain.rst b/docs/getting_started/obtain.rst
index cffab2d..68b4072 100644
--- a/docs/getting_started/obtain.rst
+++ b/docs/getting_started/obtain.rst
@@ -5,7 +5,9 @@
 
 ::
 
-    git clone https://git.trustedfirmware.org/TF-A/tf-a-tests.git
+    git clone --recursive https://git.trustedfirmware.org/TF-A/tf-a-tests.git
+
+Note that TF-A-Tests will also fetch the MbedTLS repo as a git submodule.
 
 --------------
 
diff --git a/docs/getting_started/requirements.rst b/docs/getting_started/requirements.rst
index 553975f..14e4458 100644
--- a/docs/getting_started/requirements.rst
+++ b/docs/getting_started/requirements.rst
@@ -16,6 +16,18 @@
 distributions should also work fine, provided that the tools and libraries
 can be installed.
 
+Dependencies
+------------
+
+This section lists the dependencies for TF-A-Tests which are added as
+as a git submodule.
+
+======================== =====================
+        Name             Version
+======================== =====================
+Mbed TLS                 3.6.2
+======================== =====================
+
 Toolchain
 ---------
 
diff --git a/docs/porting/optional-mods.rst b/docs/porting/optional-mods.rst
index a88d682..7fc3813 100644
--- a/docs/porting/optional-mods.rst
+++ b/docs/porting/optional-mods.rst
@@ -50,6 +50,18 @@
 generate a watchdog timeout interrupt. This interrupt remains deliberately
 unserviced, which eventually asserts the reset signal.
 
+Function : plat_pcie_get_info_table()
+----------------------------
+
+::
+
+    Argument : void
+    Return   : struct pcie_info_table *
+
+This function returns the pointer to `pcie_info_table` structure
+correponding to the platform. This needs to be implemented
+only if the platform want to run PCIe related tests.
+
 --------------
 
 *Copyright (c) 2019, Arm Limited. All rights reserved.*
diff --git a/ext/mbedtls b/ext/mbedtls
new file mode 160000
index 0000000..107ea89
--- /dev/null
+++ b/ext/mbedtls
@@ -0,0 +1 @@
+Subproject commit 107ea89daaefb9867ea9121002fbbdf926780e98
diff --git a/include/common/test_helpers.h b/include/common/test_helpers.h
index 28b1d4e..124cc4e 100644
--- a/include/common/test_helpers.h
+++ b/include/common/test_helpers.h
@@ -88,6 +88,34 @@
 		}								\
 	} while (0)
 
+#define SKIP_TEST_IF_SMCCC_VERSION_LT(major, minor)				\
+	do {									\
+		smc_args args = {0};						\
+		smc_ret_values ret;						\
+		args.fid = SMCCC_VERSION;					\
+		ret = tftf_smc(&args);						\
+		if ((int32_t)ret.ret0 < MAKE_SMCCC_VERSION(major, minor)) {	\
+			tftf_testcase_printf(					\
+				"Unexpected SMCCC version: 0x%x\n",		\
+			       (int)ret.ret0);					\
+			return TEST_RESULT_SKIPPED;				\
+		}								\
+	} while (0)
+
+#define SKIP_TEST_IF_SMCCC_FUNC_NOT_SUPPORTED(func)				\
+	do {									\
+		smc_ret_values ret;						\
+		smc_args args = {0};						\
+		args.fid = SMCCC_ARCH_FEATURES;					\
+		args.arg1 = func;						\
+		ret = tftf_smc(&args);						\
+		if ((int)ret.ret0 == SMC_ARCH_CALL_NOT_SUPPORTED) {		\
+			tftf_testcase_printf(					\
+				#func " is not implemented\n");			\
+			return TEST_RESULT_SKIPPED;				\
+		}								\
+	} while (0)
+
 #define SKIP_TEST_IF_DIT_NOT_SUPPORTED()					\
 	do {									\
 		if (!is_armv8_4_dit_present()) {				\
@@ -212,7 +240,7 @@
 
 #define SKIP_TEST_IF_TRBE_NOT_SUPPORTED()					\
 	do {									\
-		if (!get_armv9_0_trbe_support()) {				\
+		if (!is_feat_trbe_present()) {					\
 			tftf_testcase_printf("ARMv9-TRBE not supported\n");	\
 			return TEST_RESULT_SKIPPED;				\
 		}								\
@@ -319,6 +347,38 @@
 		}								\
 	} while (false)
 
+#define SKIP_TEST_IF_FPMR_NOT_SUPPORTED()					\
+	do {									\
+		if(!is_feat_fpmr_present()) {					\
+			tftf_testcase_printf("FEAT_FPMR not supported\n");	\
+			return TEST_RESULT_SKIPPED;				\
+		}								\
+	} while (false)
+
+#define SKIP_TEST_IF_SCTLR2_NOT_SUPPORTED()					\
+	do {									\
+		if (!is_feat_sctlr2_supported()) {				\
+			tftf_testcase_printf("FEAT_SCTLR2 not supported\n");	\
+			return TEST_RESULT_SKIPPED;				\
+		}								\
+	} while (false)
+
+#define SKIP_TEST_IF_THE_NOT_SUPPORTED()					\
+	do {									\
+		if (!is_feat_the_supported()) {					\
+			tftf_testcase_printf("FEAT_THE not supported\n");	\
+			return TEST_RESULT_SKIPPED;				\
+		}								\
+	} while (false)
+
+#define SKIP_TEST_IF_D128_NOT_SUPPORTED()					\
+	do {									\
+		if (!is_feat_d128_supported()) {				\
+			tftf_testcase_printf("FEAT_D128 not supported\n");	\
+			return TEST_RESULT_SKIPPED;				\
+		}								\
+	} while (false)
+
 #define SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP()				\
 	do {									\
 		u_register_t retrmm = 0U;					\
@@ -364,6 +424,13 @@
 		}							\
 	} while (false)
 
+#define SKIP_TEST_IF_DOUBLE_FAULT2_NOT_SUPPORTED()				\
+	do {									\
+		if (is_feat_double_fault2_present() == false) {			\
+			return TEST_RESULT_SKIPPED;				\
+		}								\
+	} while (false)
+
 /* Helper macro to verify if system suspend API is supported */
 #define is_psci_sys_susp_supported()	\
 		(tftf_get_psci_feature_info(SMC_PSCI_SYSTEM_SUSPEND)		\
diff --git a/include/configs/tftf_mbedtls_config.h b/include/configs/tftf_mbedtls_config.h
new file mode 100644
index 0000000..77e7ba9
--- /dev/null
+++ b/include/configs/tftf_mbedtls_config.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Based on migration guide[1]:
+ *
+ * config.h was split into build_info.h and mbedtls_config.h. In code, use
+ * #include <mbedtls/build_info.h>. Don't include mbedtls/config.h and don't
+ * refer to MBEDTLS_CONFIG_FILE. And also the guide recommends, if you have a
+ * custom configuration file don't define MBEDTLS_CONFIG_H anymore.
+ *
+ * [1] https://github.com/Mbed-TLS/mbedtls/blob/v3.6.0/docs/3.0-migration-guide.md
+ */
+
+#include <limits.h>
+/* This is needed for size_t */
+#include <stddef.h>
+/* For snprintf function declaration */
+#include <stdio.h>
+
+/* This file is compatible with release 3.6.2 */
+#define MBEDTLS_CONFIG_VERSION         0x03060200
+
+/* Configuration file to build mbed TLS with the required features for TFTF */
+#define MBEDTLS_PLATFORM_MEMORY
+
+#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+
+#define MBEDTLS_CIPHER_C
+
+#define MBEDTLS_ECP_C
+#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
+#define MBEDTLS_ECP_RESTARTABLE
+#define MBEDTLS_ECDSA_C
+#define MBEDTLS_ECDSA_DETERMINISTIC
+#define MBEDTLS_ECP_WINDOW_SIZE		(2U)	/* Valid range = [2,7] */
+
+/*
+ * This is enabled in TFTF as PSA calls are made within the trust boundary.
+ * Disabling this option causes mbedtls to create a local copy of input buffer
+ * using buffer_alloc_calloc().
+ */
+#define MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS
+
+#define MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_ASN1_WRITE_C
+
+#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf
+
+#define MBEDTLS_BASE64_C
+#define MBEDTLS_BIGNUM_C
+
+#define MBEDTLS_ERROR_C
+
+#define MBEDTLS_HKDF_C
+#define MBEDTLS_HMAC_DRBG_C
+
+#define MBEDTLS_MD_C
+
+#define MBEDTLS_PLATFORM_C
+
+#define MBEDTLS_SHA256_C
+#define MBEDTLS_SHA224_C
+#define MBEDTLS_SHA384_C
+#define MBEDTLS_SHA512_C
+
+#define MBEDTLS_VERSION_C
+
+/*
+ * Prevent the use of 128-bit division which
+ * creates dependency on external libraries.
+ */
+#define MBEDTLS_NO_UDBL_DIVISION
+
+/* Memory buffer allocator option */
+#define MBEDTLS_MEMORY_ALIGN_MULTIPLE	8
+
+#define MBEDTLS_GENPRIME
+
+#define MBEDTLS_X509_CRL_PARSE_C
+#define MBEDTLS_X509_CSR_PARSE_C
+#define MBEDTLS_X509_CREATE_C
+#define MBEDTLS_X509_CSR_WRITE_C
+
+#define MBEDTLS_AES_C
+#define MBEDTLS_GCM_C
+
+#define MBEDTLS_CHACHA20_C
+#define MBEDTLS_POLY1305_C
+#define MBEDTLS_CHACHAPOLY_C
+
+#define MBEDTLS_ECDH_C
+#define MBEDTLS_DHM_C
+
+#define MBEDTLS_PK_WRITE_C
+
+#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
+
+#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
+
+#define MBEDTLS_OID_C
+#define MBEDTLS_RSA_C
+#define MBEDTLS_PKCS1_V21
+
+#define MBEDTLS_X509_USE_C
+#define MBEDTLS_X509_CRT_PARSE_C
+
+#define MBEDTLS_PK_C
+#define MBEDTLS_PK_PARSE_C
diff --git a/include/lib/aarch32/arch_features.h b/include/lib/aarch32/arch_features.h
index 3c6a338..999f7ec 100644
--- a/include/lib/aarch32/arch_features.h
+++ b/include/lib/aarch32/arch_features.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -59,4 +59,11 @@
 {
 	return 0;
 }
+
+static inline unsigned int amu_get_version(void)
+{
+	return (unsigned int)(read_id_pfr0() >> ID_PFR0_AMU_SHIFT) &
+		ID_PFR0_AMU_MASK;
+}
+
 #endif /* ARCH_FEATURES_H */
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index 50cb5f9..f0d1398 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -218,6 +218,12 @@
 #define ID_AA64PFR0_CSV2_SUPPORTED		ULL(0x1)
 #define ID_AA64PFR0_CSV2_2_SUPPORTED		ULL(0x2)
 
+/* ID_AA64DFR0_EL1.DoubleLock definitions */
+#define ID_AA64DFR0_DOUBLELOCK_SHIFT		U(36)
+#define ID_AA64DFR0_DOUBLELOCK_MASK		ULL(0xf)
+#define ID_AA64DFR0_DOUBLELOCK_WIDTH		U(4)
+#define DOUBLELOCK_IMPLEMENTED			ULL(0)
+
 /* ID_AA64DFR0_EL1.PMS definitions (for ARMv8.2+) */
 #define ID_AA64DFR0_PMS_SHIFT		U(32)
 #define ID_AA64DFR0_PMS_LENGTH		U(4)
@@ -260,6 +266,7 @@
 /* ID_DFR0_EL1.Tracefilt definitions */
 #define ID_AA64DFR0_TRACEFILT_SHIFT		U(40)
 #define ID_AA64DFR0_TRACEFILT_MASK		U(0xf)
+#define ID_AA64DFR0_TRACEFILT_WIDTH		U(4)
 #define ID_AA64DFR0_TRACEFILT_SUPPORTED		U(1)
 
 /* ID_AA64DFR0_EL1.PMUVer definitions */
@@ -432,6 +439,11 @@
 /* ID_AA64MMFR3_EL1 definitions */
 #define ID_AA64MMFR3_EL1			S3_0_C0_C7_3
 
+#define ID_AA64MMFR3_EL1_D128_SHIFT		U(32)
+#define ID_AA64MMFR3_EL1_D128_MASK		ULL(0xf)
+#define ID_AA64MMFR3_EL1_D128_WIDTH		U(4)
+#define ID_AA64MMFR3_EL1_D128_SUPPORTED		ULL(0x1)
+
 #define ID_AA64MMFR3_EL1_S2POE_SHIFT		U(20)
 #define ID_AA64MMFR3_EL1_S2POE_MASK		ULL(0xf)
 #define ID_AA64MMFR3_EL1_S2POE_WIDTH		U(4)
@@ -452,12 +464,26 @@
 #define ID_AA64MMFR3_EL1_S1PIE_WIDTH		U(4)
 #define ID_AA64MMFR3_EL1_S1PIE_SUPPORTED	ULL(0x1)
 
+#define ID_AA64MMFR3_EL1_SCTLRX_SHIFT		U(4)
+#define ID_AA64MMFR3_EL1_SCTLRX_MASK		ULL(0xf)
+#define ID_AA64MMFR3_EL1_SCTLRX_WIDTH		ULL(0x4)
+#define ID_AA64MMFR3_EL1_SCTLR2_SUPPORTED	ULL(0x1)
+
 #define ID_AA64MMFR3_EL1_TCRX_SHIFT		U(0)
 #define ID_AA64MMFR3_EL1_TCRX_MASK		ULL(0xf)
 #define ID_AA64MMFR3_EL1_TCRX_WIDTH		U(4)
 #define ID_AA64MMFR3_EL1_TCR2_SUPPORTED		ULL(0x1)
 
 /* ID_AA64PFR1_EL1 definitions */
+#define ID_AA64PFR1_EL1_DF2_SHIFT		U(56)
+#define ID_AA64PFR1_EL1_DF2_WIDTH		U(4)
+#define ID_AA64PFR1_EL1_DF2_MASK		(0xf << ID_AA64PFR1_EL1_DF2_SHIFT)
+
+#define ID_AA64PFR1_EL1_THE_SHIFT		U(48)
+#define ID_AA64PFR1_EL1_THE_MASK		ULL(0xf)
+#define ID_AA64PFR1_EL1_THE_WIDTH		U(4)
+#define ID_AA64PFR1_EL1_THE_SUPPORTED		ULL(1)
+
 #define ID_AA64PFR1_EL1_GCS_SHIFT		U(44)
 #define ID_AA64PFR1_EL1_GCS_MASK		ULL(0xf)
 #define ID_AA64PFR1_EL1_GCS_WIDTH		U(4)
@@ -484,6 +510,7 @@
 #define ID_AA64PFR1_MPAM_FRAC_SHIFT		U(16)
 #define ID_AA64PFR1_MPAM_FRAC_MASK		ULL(0xf)
 
+#define ID_AA64PFR1_RAS_FRAC_MASK		ULL(0xf)
 #define ID_AA64PFR1_RAS_FRAC_SHIFT		U(12)
 #define ID_AA64PFR1_RAS_FRAC_MASK		ULL(0xf)
 #define ID_AA64PFR1_RAS_FRAC_WIDTH		U(4)
@@ -504,6 +531,16 @@
 #define ID_AA64PFR1_EL1_BT_MASK			ULL(0xf)
 #define BTI_IMPLEMENTED				ULL(1)	/* The BTI mechanism is implemented */
 
+#define ID_AA64PFR1_DF2_SHIFT			U(56)
+#define ID_AA64PFR1_DF2_WIDTH			ULL(0x4)
+
+/* ID_AA64PFR2_EL1 definitions */
+#define ID_AA64PFR2_EL1				S3_0_C0_C4_2
+#define ID_AA64PFR2_EL1_FPMR_SHIFT		U(32)
+#define ID_AA64PFR2_EL1_FPMR_MASK		ULL(0xf)
+#define ID_AA64PFR2_EL1_FPMR_WIDTH		U(4)
+#define ID_AA64PFR2_EL1_FPMR_SUPPORTED		ULL(0x1)
+
 /* ID_PFR1_EL1 definitions */
 #define ID_PFR1_VIRTEXT_SHIFT	U(12)
 #define ID_PFR1_VIRTEXT_MASK	U(0xf)
@@ -553,6 +590,16 @@
 #define SCTLR_DSSBS_BIT		(ULL(1) << 44)
 #define SCTLR_RESET_VAL		SCTLR_EL3_RES1
 
+/* SCTLR2 register definitions */
+#define SCTLR2_EL2		S3_4_C1_C0_3
+#define SCTLR2_EL1		S3_0_C1_C0_3
+
+#define SCTLR2_NMEA_BIT		(UL(1) << 2)
+#define SCTLR2_EnADERR_BIT	(UL(1) << 3)
+#define SCTLR2_EnANERR_BIT	(UL(1) << 4)
+#define SCTLR2_EASE_BIT		(UL(1) << 5)
+#define SCTLR2_EnIDCP128_BIT	(UL(1) << 6)
+
 /* CPACR_El1 definitions */
 #define CPACR_EL1_FPEN(x)	((x) << 20)
 #define CPACR_EL1_FP_TRAP_EL0	U(0x1)
@@ -571,37 +618,110 @@
 
 /* SCR definitions */
 #define SCR_RES1_BITS		((U(1) << 4) | (U(1) << 5))
-#define SCR_AMVOFFEN_BIT	(UL(1) << 35)
-#define SCR_ATA_BIT		(U(1) << 26)
-#define SCR_FIEN_BIT		(U(1) << 21)
-#define SCR_API_BIT		(U(1) << 17)
-#define SCR_APK_BIT		(U(1) << 16)
-#define SCR_TWE_BIT		(U(1) << 13)
-#define SCR_TWI_BIT		(U(1) << 12)
-#define SCR_ST_BIT		(U(1) << 11)
-#define SCR_RW_BIT		(U(1) << 10)
-#define SCR_SIF_BIT		(U(1) << 9)
-#define SCR_HCE_BIT		(U(1) << 8)
-#define SCR_SMD_BIT		(U(1) << 7)
-#define SCR_EA_BIT		(U(1) << 3)
-#define SCR_FIQ_BIT		(U(1) << 2)
-#define SCR_IRQ_BIT		(U(1) << 1)
-#define SCR_NS_BIT		(U(1) << 0)
+#define SCR_NSE_SHIFT		U(62)
+#define SCR_FGTEN2_BIT		(UL(1) << 59)
+#define SCR_NSE_BIT		(ULL(1) << SCR_NSE_SHIFT)
+#define SCR_EnIDCP128_BIT	(UL(1) << 55)
+#define SCR_PFAREn_BIT		(UL(1) << 53)
+#define SCR_TWERR_BIT		(UL(1) << 52)
+#define SCR_TMEA_BIT		(UL(1) << 51)
+#define SCR_EnFPM_BIT		(UL(1) << 50)
+#define SCR_MECEn_BIT		(UL(1) << 49)
+#define SCR_GPF_BIT		(UL(1) << 48)
+#define SCR_D128En_BIT		(UL(1) << 47)
+#define SCR_AIEn_BIT		(UL(1) << 46)
+#define SCR_TWEDEL_SHIFT	U(30)
+#define SCR_TWEDEL_MASK		ULL(0xf)
+#define SCR_PIEN_BIT		(UL(1) << 45)
+#define SCR_SCTLR2En_BIT	(UL(1) << 44)
+#define SCR_TCR2EN_BIT		(UL(1) << 43)
+#define SCR_RCWMASKEn_BIT	(UL(1) << 42)
+#define SCR_ENTP2_SHIFT		U(41)
+#define SCR_TRNDR_BIT		(UL(1) << 40)
+#define SCR_GCSEn_BIT		(UL(1) << 39)
+#define SCR_HXEn_BIT		(UL(1) << 38)
+#define SCR_ADEn_BIT		(UL(1) << 37)
+#define SCR_EnAS0_BIT		(UL(1) << 36)
+#define SCR_ENTP2_BIT		(UL(1) << SCR_ENTP2_SHIFT)
+#define SCR_AMVOFFEN_SHIFT	U(35)
+#define SCR_AMVOFFEN_BIT	(UL(1) << SCR_AMVOFFEN_SHIFT)
+#define SCR_TME_BIT		(UL(1) << 34)
+#define SCR_TWEDEn_BIT		(UL(1) << 29)
+#define SCR_ECVEN_BIT		(UL(1) << 28)
+#define SCR_FGTEN_BIT		(UL(1) << 27)
+#define SCR_ATA_BIT		(UL(1) << 26)
+#define SCR_EnSCXT_BIT		(UL(1) << 25)
+#define SCR_FIEN_BIT		(UL(1) << 21)
+#define SCR_NMEA_BIT		(UL(1) << 20)
+#define SCR_EASE_BIT		(UL(1) << 19)
+#define SCR_EEL2_BIT		(UL(1) << 18)
+#define SCR_API_BIT		(UL(1) << 17)
+#define SCR_APK_BIT		(UL(1) << 16)
+#define SCR_TERR_BIT		(UL(1) << 15)
+#define SCR_TLOR_BIT		(UL(1) << 14)
+#define SCR_TWE_BIT		(UL(1) << 13)
+#define SCR_TWI_BIT		(UL(1) << 12)
+#define SCR_ST_BIT		(UL(1) << 11)
+#define SCR_RW_BIT		(UL(1) << 10)
+#define SCR_SIF_BIT		(UL(1) << 9)
+#define SCR_HCE_BIT		(UL(1) << 8)
+#define SCR_SMD_BIT		(UL(1) << 7)
+#define SCR_EA_BIT		(UL(1) << 3)
+#define SCR_FIQ_BIT		(UL(1) << 2)
+#define SCR_IRQ_BIT		(UL(1) << 1)
+#define SCR_NS_BIT		(UL(1) << 0)
+#define SCR_RES1_BITS		((U(1) << 4) | (U(1) << 5))
 #define SCR_VALID_BIT_MASK	U(0x2f8f)
 #define SCR_RESET_VAL		SCR_RES1_BITS
 
 /* MDCR_EL3 definitions */
+#define MDCR_EnSTEPOP_BIT	(ULL(1) << 50)
+#define MDCR_ETBAD(x)		((x) << 48)
+#define MDCR_EnITE_BIT		(ULL(1) << 47)
+#define MDCR_EPMSSAD(x)		(ULL(x) << 45)
+#define MDCR_EnPMSS_BIT		(ULL(1) << 44)
+#define MDCR_EBWE_BIT		(ULL(1) << 43)
+#define MDCR_EnPMS3_BIT		(ULL(1) << 42)
+#define MDCR_PMEE(x)		((x) << 40)
+#define MDCR_EnTB2_BIT		(ULL(1) << 39)
+#define MDCR_E3BREC_BIT		(ULL(1) << 38)
+#define MDCR_E3BREW_BIT		(ULL(1) << 37)
+#define MDCR_EnPMSN_BIT		(ULL(1) << 36)
+#define MDCR_MPMX_BIT		(ULL(1) << 35)
+#define MDCR_MCCD_BIT		(ULL(1) << 34)
+#define MDCR_SBRBE_SHIFT	U(32)
+#define MDCR_SBRBE_MASK		ULL(0x3)
+#define MDCR_SBRBE(x)		(ULL(x) << MDCR_SBRBE_SHIFT)
+#define MDCR_PMSSE(x)		((x) << 30)
+#define MDCR_NSTBE_BIT		(ULL(1) << 26)
+#define MDCR_NSTB(x)		((x) << 24)
+#define MDCR_NSTB_EL1		ULL(0x3)
+#define MDCR_NSTBE_BIT		(ULL(1) << 26)
+#define MDCR_MTPME_BIT		(ULL(1) << 28)
+#define MDCR_TDCC_BIT		(ULL(1) << 27)
+#define MDCR_SCCD_BIT		(ULL(1) << 23)
+#define MDCR_ETAD_BIT		(ULL(1) << 22)
+#define MDCR_EPMAD_BIT		(ULL(1) << 21)
+#define MDCR_EDAD_BIT		(ULL(1) << 20)
+#define MDCR_TTRF_BIT		(ULL(1) << 19)
+#define MDCR_STE_BIT		(ULL(1) << 18)
+#define MDCR_SPME_BIT		(ULL(1) << 17)
+#define MDCR_SDD_BIT		(ULL(1) << 16)
 #define MDCR_SPD32(x)		((x) << 14)
 #define MDCR_SPD32_LEGACY	ULL(0x0)
 #define MDCR_SPD32_DISABLE	ULL(0x2)
 #define MDCR_SPD32_ENABLE	ULL(0x3)
-#define MDCR_SDD_BIT		(ULL(1) << 16)
 #define MDCR_NSPB(x)		((x) << 12)
 #define MDCR_NSPB_EL1		ULL(0x3)
+#define MDCR_NSPBE_BIT		(ULL(1) << 11)
 #define MDCR_TDOSA_BIT		(ULL(1) << 10)
 #define MDCR_TDA_BIT		(ULL(1) << 9)
+#define MDCR_EnPM2_BIT		(ULL(1) << 7)
 #define MDCR_TPM_BIT		(ULL(1) << 6)
-#define MDCR_SCCD_BIT		(ULL(1) << 23)
+#define MDCR_EDADE_BIT		(ULL(1) << 4)
+#define MDCR_ETADE_BIT		(ULL(1) << 3)
+#define MDCR_EPMADE_BIT		(ULL(1) << 2)
+#define MDCR_RLTE_BIT		(ULL(1) << 0)
 #define MDCR_EL3_RESET_VAL	ULL(0x0)
 
 /* MDCR_EL2 definitions */
@@ -667,6 +787,14 @@
 #define EVNTI_SHIFT		U(4)
 #define EVNTI_MASK		U(0xf)
 
+/* CPTR_EL3 definitions */
+#define CPTR_EL3_TCPAC_BIT	(ULL(1) << 31)
+#define CPTR_EL3_TAM_BIT	(ULL(1) << 30)
+#define CPTR_EL3_TTA_BIT	(ULL(1) << 20)
+#define CPTR_EL3_ESM_BIT	(ULL(1) << 12)
+#define CPTR_EL3_TFP_BIT	(ULL(1) << 10)
+#define CPTR_EL3_EZ_BIT		(ULL(1) << 8)
+
 /* CPTR_EL2 definitions */
 #define CPTR_EL2_RES1		((ULL(1) << 13) | (ULL(1) << 9) | (ULL(0xff)))
 #define CPTR_EL2_TCPAC_BIT	(ULL(1) << 31)
@@ -1245,6 +1373,7 @@
 
 /* MPAM register definitions */
 #define MPAM3_EL3_MPAMEN_BIT		(ULL(1) << 63)
+#define MPAM3_EL3_TRAPLOWER_BIT		(ULL(1) << 62)
 #define MPAMHCR_EL2_TRAP_MPAMIDR_EL1	(ULL(1) << 31)
 
 #define MPAM2_EL2_TRAPMPAM0EL1		(ULL(1) << 49)
@@ -1391,6 +1520,12 @@
  ******************************************************************************/
 #define MDSELR_EL1		S2_0_C0_C4_2
 
+/******************************************************************************
+ * Armv8.9 - Translation Hardening Extension Registers
+ ******************************************************************************/
+#define RCWMASK_EL1		S3_0_C13_C0_6
+#define RCWSMASK_EL1		S3_0_C13_C0_3
+
 /*******************************************************************************
  * Armv9.0 - Trace Buffer Extension System Registers
  ******************************************************************************/
@@ -1526,6 +1661,24 @@
 #define POR_EL1			S3_0_C10_C2_4
 #define S2POR_EL1		S3_0_C10_C2_5
 
+/* Perm value encoding for S2POR_EL1 */
+#define PERM_LABEL_NO_ACCESS		U(0)
+#define PERM_LABEL_RESERVED_1		U(1)
+#define PERM_LABEL_MRO			U(2)
+#define PERM_LABEL_MRO_TL1		U(3)
+#define PERM_LABEL_WO			U(4)
+#define PERM_LABEL_RESERVED_5		U(5)
+#define PERM_LABEL_MRO_TL0		U(6)
+#define PERM_LABEL_MRO_TL01		U(7)
+#define PERM_LABEL_RO			U(8)
+#define PERM_LABEL_RO_uX		U(9)
+#define PERM_LABEL_RO_pX		U(10)
+#define PERM_LABEL_RO_upX		U(11)
+#define PERM_LABEL_RW			U(12)
+#define PERM_LABEL_RW_uX		U(13)
+#define PERM_LABEL_RW_pX		U(14)
+#define PERM_LABEL_RW_upX		U(15)
+
 /*******************************************************************************
  * FEAT_GCS - Guarded Control Stack Registers
  ******************************************************************************/
@@ -1543,4 +1696,9 @@
 #define SCXTNUM_EL1		S3_0_C13_C0_7
 #define SCXTNUM_EL0		S3_3_C13_C0_7
 
+/*******************************************************************************
+ * Floating Point Mode Register definitions
+ ******************************************************************************/
+#define FPMR			S3_3_C4_C4_2
+
 #endif /* ARCH_H */
diff --git a/include/lib/aarch64/arch_features.h b/include/lib/aarch64/arch_features.h
index c7d824a..cee8dd2 100644
--- a/include/lib/aarch64/arch_features.h
+++ b/include/lib/aarch64/arch_features.h
@@ -120,12 +120,6 @@
 		(read_id_aa64isar2_el1() & mask_id_aa64isar2)) != 0U;
 }
 
-static inline bool is_armv8_4_amuv1_present(void)
-{
-	return ((read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT) &
-		ID_AA64PFR0_AMU_MASK) == 1U;
-}
-
 static inline bool is_armv8_4_dit_present(void)
 {
 	return ((read_id_aa64pfr0_el1() >> ID_AA64PFR0_DIT_SHIFT) &
@@ -186,13 +180,6 @@
 		ID_AA64DFR0_DEBUG_SHIFT);
 }
 
-static inline bool get_armv9_0_trbe_support(void)
-{
-	return ((read_id_aa64dfr0_el1() >> ID_AA64DFR0_TRACEBUFFER_SHIFT) &
-		ID_AA64DFR0_TRACEBUFFER_MASK) ==
-		ID_AA64DFR0_TRACEBUFFER_SUPPORTED;
-}
-
 static inline bool get_armv8_4_trf_support(void)
 {
 	return ((read_id_aa64dfr0_el1() >> ID_AA64DFR0_TRACEFILT_SHIFT) &
@@ -233,7 +220,7 @@
 static inline bool get_feat_brbe_support(void)
 {
 	return ((read_id_aa64dfr0_el1() >> ID_AA64DFR0_BRBE_SHIFT) &
-		ID_AA64DFR0_BRBE_MASK) ==
+		ID_AA64DFR0_BRBE_MASK) >=
 		ID_AA64DFR0_BRBE_SUPPORTED;
 }
 
@@ -474,6 +461,22 @@
 		ID_AA64ISAR1_LS64_MASK);
 }
 
+static inline unsigned int amu_get_version(void)
+{
+	return (unsigned int)(read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT) &
+		ID_AA64PFR0_AMU_MASK;
+}
+
+static inline bool is_feat_amuv1_present(void)
+{
+	return amu_get_version() >= ID_AA64PFR0_AMU_V1;
+}
+
+static inline bool is_feat_amuv1p1_present(void)
+{
+	return amu_get_version() >= ID_AA64PFR0_AMU_V1P1;
+}
+
 static inline bool is_feat_trbe_present(void)
 {
 	return EXTRACT(ID_AA64DFR0_TRACEBUFFER, read_id_aa64dfr0_el1())
@@ -525,4 +528,40 @@
 	return EXTRACT(ID_AA64PFR1_EL1_MTE, read_id_aa64pfr1_el1())
 		>= MTE_IMPLEMENTED_ELX;
 }
+
+static inline bool is_feat_double_fault2_present(void)
+{
+	return (EXTRACT(ID_AA64PFR1_EL1_DF2,
+		read_id_aa64pfr1_el1()) == 1UL);
+}
+
+static inline bool is_feat_fpmr_present(void)
+{
+	return EXTRACT(ID_AA64PFR2_EL1_FPMR, read_id_aa64pfr2_el1())
+		== ID_AA64PFR2_EL1_FPMR_SUPPORTED;
+}
+
+static inline bool is_feat_sctlr2_supported(void)
+{
+	return (((read_id_aa64mmfr3_el1() >> ID_AA64MMFR3_EL1_SCTLRX_SHIFT) &
+		ID_AA64MMFR3_EL1_SCTLRX_MASK) == ID_AA64MMFR3_EL1_SCTLR2_SUPPORTED);
+}
+
+static inline bool is_feat_the_supported(void)
+{
+	return (((read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_THE_SHIFT) &
+		ID_AA64PFR1_EL1_THE_MASK) == ID_AA64PFR1_EL1_THE_SUPPORTED);
+}
+
+static inline bool is_feat_d128_supported(void)
+{
+	return (((read_id_aa64mmfr3_el1() >> ID_AA64MMFR3_EL1_D128_SHIFT) &
+		ID_AA64MMFR3_EL1_D128_MASK) == ID_AA64MMFR3_EL1_D128_SUPPORTED);
+}
+
+static inline bool is_feat_doublelock_present(void)
+{
+	return EXTRACT(ID_AA64DFR0_DOUBLELOCK, read_id_aa64dfr0_el1())
+			>= DOUBLELOCK_IMPLEMENTED;
+}
 #endif /* ARCH_FEATURES_H */
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index c906181..35d2454 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -190,6 +190,7 @@
 DEFINE_SYSREG_READ_FUNC(id_aa64isar1_el1)
 DEFINE_SYSREG_READ_FUNC(id_aa64pfr0_el1)
 DEFINE_SYSREG_READ_FUNC(id_aa64pfr1_el1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(id_aa64pfr2_el1, ID_AA64PFR2_EL1)
 DEFINE_SYSREG_READ_FUNC(id_aa64dfr0_el1)
 DEFINE_SYSREG_READ_FUNC(id_afr0_el1)
 DEFINE_SYSREG_READ_FUNC(id_pfr0_el1)
@@ -322,6 +323,9 @@
 DEFINE_SYSREG_RW_FUNCS(sctlr_el2)
 DEFINE_SYSREG_RW_FUNCS(sctlr_el3)
 
+DEFINE_RENAME_SYSREG_RW_FUNCS(sctlr2_el1, SCTLR2_EL1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(sctlr2_el2, SCTLR2_EL2)
+
 DEFINE_SYSREG_RW_FUNCS(actlr_el1)
 DEFINE_SYSREG_RW_FUNCS(actlr_el2)
 DEFINE_SYSREG_RW_FUNCS(actlr_el3)
@@ -645,6 +649,10 @@
 DEFINE_RENAME_SYSREG_RW_FUNCS(pir_el2, PIR_EL2)
 DEFINE_RENAME_SYSREG_RW_FUNCS(s2pir_el2, S2PIR_EL2)
 
+/* Armv8.9 Translation Hardening Extension */
+DEFINE_RENAME_SYSREG_RW_FUNCS(rcwmask_el1, RCWMASK_EL1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(rcwsmask_el1, RCWSMASK_EL1)
+
 /* Armv9.4 Guarded Control Stack Extension */
 DEFINE_RENAME_SYSREG_RW_FUNCS(gcscr_el2, GCSCR_EL2)
 DEFINE_RENAME_SYSREG_RW_FUNCS(gcspr_el2, GCSPR_EL2)
@@ -675,6 +683,9 @@
 DEFINE_RENAME_SYSREG_RW_FUNCS(fpcr, FPCR)
 DEFINE_RENAME_SYSREG_RW_FUNCS(fpsr, FPSR)
 
+/* Floating point Mode Register */
+DEFINE_RENAME_SYSREG_RW_FUNCS(fpmr, FPMR)
+
 /* ID_AA64ISAR2_EL1 */
 DEFINE_RENAME_SYSREG_READ_FUNC(id_aa64isar2_el1, ID_AA64ISAR2_EL1)
 
diff --git a/include/lib/aarch64/serror.h b/include/lib/aarch64/serror.h
index ac25f87..e6aa64f 100644
--- a/include/lib/aarch64/serror.h
+++ b/include/lib/aarch64/serror.h
@@ -7,8 +7,8 @@
 #ifndef __SERROR_H__
 #define  __SERROR_H__
 
-typedef bool (*exception_handler_t)(void);
-void register_custom_serror_handler(exception_handler_t handler);
+typedef bool (*serr_exception_handler_t)(bool *incr_elr_elx);
+void register_custom_serror_handler(serr_exception_handler_t handler);
 void unregister_custom_serror_handler(void);
 
 #endif /* __SERROR_H__ */
diff --git a/include/lib/extensions/amu.h b/include/lib/extensions/amu.h
index 3ce053d..838e4b9 100644
--- a/include/lib/extensions/amu.h
+++ b/include/lib/extensions/amu.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -61,8 +61,6 @@
 
 CASSERT(AMU_GROUP1_COUNTERS_MASK <= 0xffff, invalid_amu_group1_counters_mask);
 
-unsigned int amu_get_version(void);
-
 uint64_t amu_group0_cnt_read(unsigned int idx);
 #if __aarch64__
 uint64_t amu_group0_voffset_read(unsigned int idx);
diff --git a/include/lib/extensions/sysreg128.h b/include/lib/extensions/sysreg128.h
new file mode 100644
index 0000000..5be2ffc
--- /dev/null
+++ b/include/lib/extensions/sysreg128.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SYSREG128_H
+#define SYSREG128_H
+
+#include <stdint.h>
+
+#ifdef __aarch64__
+
+/* Assembly function prototypes. */
+uint128_t read128_par_el1(void);
+uint128_t read128_ttbr0_el1(void);
+uint128_t read128_ttbr1_el1(void);
+uint128_t read128_ttbr0_el2(void);
+uint128_t read128_ttbr1_el2(void);
+uint128_t read128_vttbr_el2(void);
+uint128_t read128_rcwmask_el1(void);
+uint128_t read128_rcwsmask_el1(void);
+
+void write128_par_el1(uint128_t v);
+void write128_ttbr0_el1(uint128_t v);
+void write128_ttbr1_el1(uint128_t v);
+void write128_ttbr0_el2(uint128_t v);
+void write128_ttbr1_el2(uint128_t v);
+void write128_vttbr_el2(uint128_t v);
+void write128_rcwmask_el1(uint128_t v);
+void write128_rcwsmask_el1(uint128_t v);
+
+#endif /* __aarch64__ */
+
+#endif /* SYSREG128_H */
diff --git a/include/lib/pcie/pcie.h b/include/lib/pcie/pcie.h
index aa3911f..65e0202 100644
--- a/include/lib/pcie/pcie.h
+++ b/include/lib/pcie/pcie.h
@@ -11,6 +11,9 @@
 #include <stdint.h>
 #include <utils_def.h>
 
+/* platforms need to ensure that number of entries is less that this value */
+#define MAX_PCIE_INFO_ENTRIES 5
+
 typedef struct {
 	unsigned long ecam_base;	/* ECAM base address */
 	unsigned int segment_num;	/* Segment number of this ECAM */
@@ -18,10 +21,10 @@
 	unsigned int end_bus_num;	/* Last bus number */
 } pcie_info_block_t;
 
-typedef struct {
+struct pcie_info_table{
 	unsigned int num_entries;	/* Number of entries */
-	pcie_info_block_t block[];
-} pcie_info_table_t;
+	pcie_info_block_t block[MAX_PCIE_INFO_ENTRIES];
+};
 
 typedef struct {
 	uint32_t bdf;
@@ -96,6 +99,7 @@
 #define CC_SUB_SHIFT	16
 #define CC_BASE_SHIFT	24
 
+void pcie_init(void);
 void pcie_create_info_table(void);
 pcie_device_bdf_table_t *pcie_get_bdf_table(void);
 uint32_t pcie_find_capability(uint32_t bdf, uint32_t cid_type, uint32_t cid,
diff --git a/include/lib/pcie/pcie_doe.h b/include/lib/pcie/pcie_doe.h
index 4e12afd..bac0dbf 100644
--- a/include/lib/pcie/pcie_doe.h
+++ b/include/lib/pcie/pcie_doe.h
@@ -8,6 +8,11 @@
 #ifndef PCIE_DOE_H
 #define PCIE_DOE_H
 
+#include <stdbool.h>
+#include <stddef.h>
+#include <pcie.h>
+#include <test_helpers.h>
+
 /* DOE Extended Capability */
 #define DOE_CAP_ID			0x002E
 
@@ -86,10 +91,45 @@
 	uint8_t next_index;
 } pcie_doe_disc_resp_t;
 
+/* Skip test if DA is not supported in RMI features */
+#define CHECK_DA_SUPPORT_IN_RMI(_reg0)						\
+	do {									\
+		SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();			\
+		/* Get feature register0 */					\
+		if (host_rmi_features(0UL, &_reg0) != REALM_SUCCESS) {		\
+			ERROR("Failed to get RMI feat_reg0\n");			\
+			return TEST_RESULT_FAIL;				\
+		}								\
+										\
+		/* DA not supported in RMI features? */				\
+		if ((_reg0 & RMI_FEATURE_REGISTER_0_DA_EN) == 0UL) {		\
+			WARN("DA not in RMI features, skipping\n");		\
+			return TEST_RESULT_SKIPPED;				\
+		}								\
+	} while (false)
+
+#define SKIP_TEST_IF_DOE_NOT_SUPPORTED(_bdf, _doe_cap_base)			\
+	do {									\
+		/* Test PCIe DOE only for RME */				\
+		if (!get_armv9_2_feat_rme_support()) {				\
+			tftf_testcase_printf("FEAT_RME not supported\n");	\
+			return TEST_RESULT_SKIPPED;				\
+		}								\
+										\
+		pcie_init();							\
+		if (pcie_find_doe_device(&(_bdf), &(_doe_cap_base)) != 0) {		\
+			tftf_testcase_printf("PCIe DOE not supported\n");	\
+			return TEST_RESULT_SKIPPED;				\
+		}								\
+	} while (false)
+
 void print_doe_disc(pcie_doe_disc_resp_t *data);
 int pcie_doe_send_req(uint32_t header, uint32_t bdf, uint32_t doe_cap_base,
 			uint32_t *req_addr, uint32_t req_len);
 int pcie_doe_recv_resp(uint32_t bdf, uint32_t doe_cap_base,
 			uint32_t *resp_addr, uint32_t *resp_len);
+int pcie_doe_communicate(uint32_t header, uint32_t bdf, uint32_t doe_cap_base, void *req_buf,
+			 size_t req_sz, void *rsp_buf, size_t *rsp_sz);
+int pcie_find_doe_device(uint32_t *bdf_ptr, uint32_t *cap_base_ptr);
 
 #endif /* PCIE_DOE_H */
diff --git a/include/lib/tftf_lib.h b/include/lib/tftf_lib.h
index 36e2e0f..c65b061 100644
--- a/include/lib/tftf_lib.h
+++ b/include/lib/tftf_lib.h
@@ -140,48 +140,109 @@
 void waitms(uint64_t ms);
 void waitus(uint64_t us);
 
+/* Define fields in common for smc_args and smc_args_ext */
+#define FID_COMMON_ARGS()						\
+	/*								\
+	 * Function identifier. Identifies which function is being	\
+	 * invoked.							\
+	 */								\
+	uint32_t	fid;						\
+									\
+	u_register_t	arg1;						\
+	u_register_t	arg2;						\
+	u_register_t	arg3;						\
+	u_register_t	arg4;						\
+	u_register_t	arg5;						\
+	u_register_t	arg6;						\
+	u_register_t	arg7;
+
+/* Define fields in common for smc_ret_values and smc_ret_values_ext */
+#define COMMON_RETVALS()						\
+	u_register_t	ret0;						\
+	u_register_t	ret1;						\
+	u_register_t	ret2;						\
+	u_register_t	ret3;						\
+	u_register_t	ret4;						\
+	u_register_t	ret5;						\
+	u_register_t	ret6;						\
+	u_register_t	ret7;
+
+
 /*
- * SMC calls take a function identifier and up to 7 arguments.
+ * SMC calls take a function identifier and up to 7 arguments if using x8
+ * as an address pointing to a structure where return values are stored.
  * Additionally, few SMC calls that originate from EL2 leverage the seventh
  * argument explicitly. Given that TFTF runs in EL2, we need to be able to
  * specify it.
  */
 typedef struct {
-	/* Function identifier. Identifies which function is being invoked. */
-	uint32_t	fid;
-
-	u_register_t	arg1;
-	u_register_t	arg2;
-	u_register_t	arg3;
-	u_register_t	arg4;
-	u_register_t	arg5;
-	u_register_t	arg6;
-	u_register_t	arg7;
+	FID_COMMON_ARGS()
 } smc_args;
 
-/* SMC calls can return up to 8 register values */
+/*
+ * If x8 is not used as an address pointing to a structure where the return
+ * values are stored, SMC calls take up to 17 arguments.
+ */
 typedef struct {
-	u_register_t	ret0;
-	u_register_t	ret1;
-	u_register_t	ret2;
-	u_register_t	ret3;
-	u_register_t	ret4;
-	u_register_t	ret5;
-	u_register_t	ret6;
-	u_register_t	ret7;
+	FID_COMMON_ARGS()
+	u_register_t	arg8;
+	u_register_t	arg9;
+	u_register_t	arg10;
+	u_register_t	arg11;
+	u_register_t	arg12;
+	u_register_t	arg13;
+	u_register_t	arg14;
+	u_register_t	arg15;
+	u_register_t	arg16;
+	u_register_t	arg17;
+} smc_args_ext;
+
+/*
+ * SMC calls can return up to 8 register values if x8 is used as an address
+ * pointing to a structure where the return values are stored.
+ */
+typedef struct {
+	COMMON_RETVALS()
 } smc_ret_values;
 
 /*
- * Trigger an SMC call.
+ * If x8 is not used as an address pointing to a structure where the return
+ * values are stored, SMC calls return up to 18 register values.
+ */
+typedef struct {
+	COMMON_RETVALS()
+	u_register_t	ret8;
+	u_register_t	ret9;
+	u_register_t	ret10;
+	u_register_t	ret11;
+	u_register_t	ret12;
+	u_register_t	ret13;
+	u_register_t	ret14;
+	u_register_t	ret15;
+	u_register_t	ret16;
+	u_register_t	ret17;
+} smc_ret_values_ext;
+
+/*
+ * Trigger an SMC call. Return values are stored in structure pointed by address
+ * stored in x8.
  */
 smc_ret_values tftf_smc(const smc_args *args);
 
+/*
+ * Trigger an SMC call. Return values are stored in structure pointed by 'ret'
+ */
+void tftf_smc_no_retval_x8(const smc_args_ext *args, smc_ret_values_ext *ret);
+
 /* Assembler routine to trigger a SMC call. */
 smc_ret_values asm_tftf_smc64(uint32_t fid, u_register_t arg1, u_register_t arg2,
 			      u_register_t arg3, u_register_t arg4,
 			      u_register_t arg5, u_register_t arg6,
 			      u_register_t arg7);
 
+/* Assembler routine to trigger a SMC call without smc_ret_values in x8. */
+u_register_t asm_tftf_smc64_no_retval_x8(const smc_args_ext *args,
+					  smc_ret_values_ext *ret);
 /*
  * Update the SVE hint for the current CPU. Any SMC call made through tftf_smc
  * will update the SVE hint bit in the SMC Function ID.
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index c8b785c..1a51823 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -193,4 +193,12 @@
 	return platform_get_core_pos(read_mpidr_el1() & MPID_MASK);
 }
 
+/* Forward declaration */
+struct pcie_info_table;
+
+/*
+ * Retrieve platform PCIe information.
+ */
+const struct pcie_info_table *plat_pcie_get_info_table(void);
+
 #endif /* __PLATFORM_H__ */
diff --git a/include/runtime_services/arm_arch_svc.h b/include/runtime_services/arm_arch_svc.h
index 0d2eb38..0b4e2ad 100644
--- a/include/runtime_services/arm_arch_svc.h
+++ b/include/runtime_services/arm_arch_svc.h
@@ -13,5 +13,6 @@
 #define SMCCC_ARCH_WORKAROUND_1	0x80008000
 #define SMCCC_ARCH_WORKAROUND_2	0x80007FFF
 #define SMCCC_ARCH_WORKAROUND_3	0x80003FFF
+#define SMCCC_ARCH_FEATURE_AVAILABILITY		U(0x80000003)
 
 #endif /* __ARM_ARCH_SVC_H__ */
diff --git a/include/runtime_services/ffa_helpers.h b/include/runtime_services/ffa_helpers.h
index 4dc3f53..0a63e96 100644
--- a/include/runtime_services/ffa_helpers.h
+++ b/include/runtime_services/ffa_helpers.h
@@ -357,8 +357,8 @@
  */
 struct ffa_partition_rxtx_header {
 	uint32_t flags;
-	/* MBZ */
-	uint32_t reserved;
+	/* Reserved (SBZ). */
+	uint32_t reserved_1;
 	/* Offset from the beginning of the buffer to the message payload. */
 	uint32_t offset;
 	/* Sender(Bits[31:16]) and Receiver(Bits[15:0]) endpoint IDs. */
@@ -366,6 +366,10 @@
 	ffa_id_t sender;
 	/* Size of message in buffer. */
 	uint32_t size;
+	/* Reserved (SBZ). Added in v1.2 */
+	uint32_t reserved_2;
+	/* UUID identifying the communication protocol. Added in v1.2. */
+	struct ffa_uuid uuid;
 };
 
 #define FFA_RXTX_HEADER_SIZE sizeof(struct ffa_partition_rxtx_header)
@@ -375,11 +379,13 @@
 	struct ffa_partition_rxtx_header *header)
 {
 	header->flags = 0;
-	header->reserved = 0;
+	header->reserved_1 = 0;
 	header->offset = FFA_RXTX_HEADER_SIZE;
 	header->sender = sender;
 	header->receiver = receiver;
 	header->size = size;
+	header->reserved_2 = 0;
+	header->uuid = (struct ffa_uuid){0};
 }
 
 /* The maximum length possible for a single message. */
diff --git a/include/runtime_services/host_realm_managment/host_crypto_utils.h b/include/runtime_services/host_realm_managment/host_crypto_utils.h
new file mode 100644
index 0000000..2f865c0
--- /dev/null
+++ b/include/runtime_services/host_realm_managment/host_crypto_utils.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef HOST_CRYPTO_UTILS_H
+#define HOST_CRYPTO_UTILS_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define PUBLIC_KEY_ALGO_ECDSA_ECC_NIST_P256	0x10
+#define PUBLIC_KEY_ALGO_ECDSA_ECC_NIST_P384	0x20
+#define PUBLIC_KEY_ALGO_RSASSA_3072		0x30
+
+int host_get_public_key_from_cert_chain(uint8_t *cert_chain,
+					size_t cert_chain_len,
+					void *public_key,
+					size_t *public_key_len,
+					void *public_key_metadata,
+					size_t *public_key_metadata_len,
+					uint8_t *public_key_algo);
+
+#endif /* HOST_CRYPTO_UTILS_H */
diff --git a/include/runtime_services/host_realm_managment/host_realm_helper.h b/include/runtime_services/host_realm_managment/host_realm_helper.h
index 168bb0a..6909a4e 100644
--- a/include/runtime_services/host_realm_managment/host_realm_helper.h
+++ b/include/runtime_services/host_realm_managment/host_realm_helper.h
@@ -18,7 +18,8 @@
 		u_register_t feature_flag,
 		long sl,
 		const u_register_t *rec_flag,
-		unsigned int rec_count);
+		unsigned int rec_count,
+		unsigned int num_aux_planes);
 
 /*
  * Creates realm, initializes heap, creates RTTs and also
@@ -29,7 +30,8 @@
 		u_register_t feature_flag,
 		long sl,
 		const u_register_t *rec_flag,
-		unsigned int rec_count);
+		unsigned int rec_count,
+		unsigned int num_aux_planes);
 
 /*
  * Creates realm, initializes heap, creates RTTs,
@@ -40,7 +42,8 @@
 		u_register_t feature_flag,
 		long sl,
 		const u_register_t *rec_flag,
-		unsigned int rec_count);
+		unsigned int rec_count,
+		unsigned int num_aux_planes);
 bool host_destroy_realm(struct realm *realm_ptr);
 void host_rec_send_sgi(struct realm *realm_ptr,
 		unsigned int sgi, unsigned int rec_num);
diff --git a/include/runtime_services/host_realm_managment/host_realm_mem_layout.h b/include/runtime_services/host_realm_managment/host_realm_mem_layout.h
index 7458146..1bef986 100644
--- a/include/runtime_services/host_realm_managment/host_realm_mem_layout.h
+++ b/include/runtime_services/host_realm_managment/host_realm_mem_layout.h
@@ -41,8 +41,8 @@
 #ifdef ENABLE_REALM_PAYLOAD_TESTS
  /* 1MB for shared buffer between Realm and Host */
  #define NS_REALM_SHARED_MEM_SIZE	U(0x100000)
- /* 8MB of memory used as a pool for realm's objects creation */
- #define PAGE_POOL_MAX_SIZE		U(0x800000)
+ /* 10MB of memory used as a pool for realm's objects creation */
+ #define PAGE_POOL_MAX_SIZE		U(0xA00000)
 #else
  #define NS_REALM_SHARED_MEM_SIZE       U(0x0)
  #define PAGE_POOL_MAX_SIZE             U(0x0)
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 484deeb..00435b0 100644
--- a/include/runtime_services/host_realm_managment/host_realm_rmi.h
+++ b/include/runtime_services/host_realm_managment/host_realm_rmi.h
@@ -18,6 +18,12 @@
 #define RMI_FNUM_MIN_VALUE	U(0x150)
 #define RMI_FNUM_MAX_VALUE	U(0x18F)
 
+/*
+ * Defines member of structure and reserves space
+ * for the next member with specified offset.
+ */
+#define SET_MEMBER_RMI	SET_MEMBER
+
 /* Get RMI fastcall std FID from offset */
 #define SMC64_RMI_FID(_offset)					\
 	((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) |			\
@@ -92,6 +98,11 @@
 #define RMI_DATA_DESTROY		SMC64_RMI_FID(U(0x5))
 
 /*
+ * FID: 0xC4000156
+ */
+#define SMC_RMI_PDEV_AUX_COUNT		SMC64_RMI_FID(U(0x6))
+
+/*
  * arg0 == RD address
  */
 #define RMI_REALM_ACTIVATE		SMC64_RMI_FID(U(0x7))
@@ -135,6 +146,30 @@
 
 /*
  * arg0 == RD address
+ * arg1 == RTT address
+ * arg2 == map address
+ * arg3 == level
+ * arg4 == RTT tree index
+ *
+ * ret0 == status/index
+ */
+#define RMI_RTT_AUX_CREATE		SMC64_RMI_FID(U(0x2D))
+
+/*
+ * arg0 == RD address
+ * arg1 == map address
+ * arg2 == level
+ * arg3 == RTT tree index
+ *
+ * ret1 == Address (PA) of the RTT, if ret0 == RMI_SUCCESS
+ *         Otherwise, undefined.
+ * ret2 == Top of the non-live address region. Only valid
+ *         if ret0 == RMI_SUCCESS or ret0 == (RMI_ERROR_RTT_WALK, x)
+ */
+#define RMI_RTT_AUX_DESTROY		SMC64_RMI_FID(U(0x2E))
+
+/*
+ * arg0 == RD address
  * arg1 == map address
  * arg2 == level
  *
@@ -156,6 +191,31 @@
 /*
  * arg0 == RD address
  * arg1 == map address
+ * arg2 == RTT tree index
+ *
+ * ret0 == status/index
+ * ret1 == fail_index
+ * ret2 == primary level
+ * ret3 == state
+ * ret4 == ripas
+ */
+#define RMI_RTT_AUX_MAP_PROTECTED	SMC64_RMI_FID(U(0x30))
+
+/*
+ * arg0 == RD address
+ * arg1 == map address
+ * arg2 == RTT tree index
+ *
+ * ret0 == status/index
+ * ret1 == fail_index
+ * ret2 == primary level
+ * ret3 == state
+ */
+#define RMI_RTT_AUX_MAP_UNPROTECTED	SMC64_RMI_FID(U(0x31))
+
+/*
+ * arg0 == RD address
+ * arg1 == map address
  * arg2 == level
  *
  * ret1 == level
@@ -174,6 +234,40 @@
 #define RMI_RTT_UNMAP_UNPROTECTED	SMC64_RMI_FID(U(0x12))
 
 /*
+ * arg0 == RD address
+ * arg1 == map address
+ * arg2 == RTT tree index
+ *
+ * ret0 == status/index
+ * ret1 == top
+ * ret2 == level
+ */
+#define RMI_RTT_AUX_UNMAP_PROTECTED	SMC64_RMI_FID(U(0x33))
+
+/*
+ * arg0 == RD address
+ * arg1 == map address
+ * arg2 == RTT tree index
+ *
+ * ret0 == status/index
+ * ret1 == top
+ * ret2 == level
+ */
+#define RMI_RTT_AUX_UNMAP_UNPROTECTED	SMC64_RMI_FID(U(0x34))
+
+/*
+ * arg0 == RD address
+ * arg1 == target rec
+ * arg2 == base adr
+ * arg3 == top adr
+ *
+ * ret0 == return code
+ * ret1 == Top IPA of range whose S2AP was modified
+ * ret2 == Index of RTT tree in which base alignment check failed
+ */
+#define RMI_RTT_SET_S2AP		SMC64_RMI_FID(U(0x3B))
+
+/*
  * arg0 == calling rec address
  * arg1 == target rec address
  */
@@ -195,6 +289,16 @@
 
 /*
  * arg0 == RD address
+ * arg1 == map address
+ * arg2 == level
+ * arg3 == RTT tree index
+ *
+ * ret1 == Address(PA) of the RTT folded, if ret0 == RMI_SUCCESS
+ */
+#define RMI_RTT_AUX_FOLD		SMC64_RMI_FID(U(0x2F))
+
+/*
+ * arg0 == RD address
  */
 #define RMI_REC_AUX_COUNT		SMC64_RMI_FID(U(0x17))
 
@@ -219,6 +323,156 @@
  */
 #define RMI_RTT_SET_RIPAS		SMC64_RMI_FID(U(0x19))
 
+/*
+ * FID: 0xC4000170
+ */
+#define SMC_RMI_GRANULE_DEV_DELEGATE		SMC64_RMI_FID(U(0x20))
+
+/*
+ * FID: 0xC4000171
+ */
+#define SMC_RMI_GRANULE_DEV_UNDELEGATE		SMC64_RMI_FID(U(0x21))
+
+/*
+ * FID: 0xC4000172
+ */
+#define SMC_RMI_DEV_MAP				SMC64_RMI_FID(U(0x22))
+
+/*
+ * FID: 0xC4000173
+ */
+#define SMC_RMI_DEV_UNMAP			SMC64_RMI_FID(U(0x23))
+
+/*
+ * FID: 0xC4000174
+ */
+#define SMC_RMI_PDEV_ABORT			SMC64_RMI_FID(U(0x24))
+
+/*
+ * FID: 0xC4000175
+ */
+#define SMC_RMI_PDEV_COMMUNICATE		SMC64_RMI_FID(U(0x25))
+
+/*
+ * FID: 0xC4000176
+ */
+#define SMC_RMI_PDEV_CREATE			SMC64_RMI_FID(U(0x26))
+
+/*
+ * FID: 0xC4000177
+ */
+#define SMC_RMI_PDEV_DESTROY			SMC64_RMI_FID(U(0x27))
+
+/*
+ * FID: 0xC4000178
+ */
+#define SMC_RMI_PDEV_GET_STATE			SMC64_RMI_FID(U(0x28))
+
+/*
+ * FID: 0xC4000179
+ */
+#define SMC_RMI_PDEV_IDE_RESET			SMC64_RMI_FID(U(0x29))
+
+/*
+ * FID: 0xC400017A
+ */
+#define SMC_RMI_PDEV_NOTIFY			SMC64_RMI_FID(U(0x2A))
+
+/*
+ * FID: 0xC400017B
+ */
+#define SMC_RMI_PDEV_SET_PUBKEY			SMC64_RMI_FID(U(0x2B))
+
+/*
+ * FID: 0xC400017C
+ */
+#define SMC_RMI_PDEV_STOP			SMC64_RMI_FID(U(0x2C))
+
+/*
+ * FID: 0xC400017D
+ */
+#define SMC_RMI_RTT_AUX_CREATE			SMC64_RMI_FID(U(0x2D))
+
+/*
+ * FID: 0xC400017E
+ */
+#define SMC_RMI_RTT_AUX_DESTROY			SMC64_RMI_FID(U(0x2E))
+
+/*
+ * FID: 0xC400017F
+ */
+#define SMC_RMI_RTT_AUX_FOLD			SMC64_RMI_FID(U(0x2F))
+
+/*
+ * FID: 0xC4000180
+ */
+#define SMC_RMI_RTT_AUX_MAP_PROTECTED		SMC64_RMI_FID(U(0x30))
+
+/*
+ * FID: 0xC4000181
+ */
+#define SMC_RMI_RTT_AUX_MAP_UNPROTECTED		SMC64_RMI_FID(U(0x31))
+
+/*
+ * FID: 0xC4000183
+ */
+#define SMC_RMI_RTT_AUX_UNMAP_PROTECTED		SMC64_RMI_FID(U(0x33))
+
+/*
+ * FID: 0xC4000184
+ */
+#define SMC_RMI_RTT_AUX_UNMAP_UNPROTECTED	SMC64_RMI_FID(U(0x34))
+
+/*
+ * FID: 0xC4000185
+ */
+#define SMC_RMI_VDEV_ABORT			SMC64_RMI_FID(U(0x35))
+
+/*
+ * FID: 0xC4000186
+ */
+#define SMC_RMI_VDEV_COMMUNICATE		SMC64_RMI_FID(U(0x36))
+
+/*
+ * FID: 0xC4000187
+ */
+#define SMC_RMI_VDEV_CREATE			SMC64_RMI_FID(U(0x37))
+
+/*
+ * FID: 0xC4000188
+ */
+#define SMC_RMI_VDEV_DESTROY			SMC64_RMI_FID(U(0x38))
+
+/*
+ * FID: 0xC4000189
+ */
+#define SMC_RMI_VDEV_GET_STATE			SMC64_RMI_FID(U(0x39))
+
+/*
+ * FID: 0xC400018A
+ */
+#define SMC_RMI_VDEV_STOP			SMC64_RMI_FID(U(0x3A))
+
+/*
+ * FID: 0xC400018B
+ */
+#define SMC_RMI_RTT_SET_S2AP			SMC64_RMI_FID(U(0x3B))
+
+/*
+ * FID: 0xC400018C
+ */
+#define SMC_RMI_MEC_SET_SHARED			SMC64_RMI_FID(U(0x3C))
+
+/*
+ * FID: 0xC400018D
+ */
+#define SMC_RMI_MEC_SET_PRIVATE			SMC64_RMI_FID(U(0x3D))
+
+/*
+ * FID: 0xC400018E
+ */
+#define SMC_RMI_VDEV_COMPLETE			SMC64_RMI_FID(U(0x3E))
+
 #define GRANULE_SIZE			PAGE_SIZE_4KB
 
 /* Maximum number of auxiliary granules required for a REC */
@@ -237,10 +491,14 @@
 #define RMI_FEATURE_FALSE		0U
 #define RMI_FEATURE_TRUE		1U
 
-/* RmiRealmFlags format */
-#define RMI_REALM_FLAGS_LPA2		BIT(0)
-#define RMI_REALM_FLAGS_SVE		BIT(1)
-#define RMI_REALM_FLAGS_PMU		BIT(2)
+/* RmiRealmFlags0 format */
+#define RMI_REALM_FLAGS0_LPA2		BIT(0)
+#define RMI_REALM_FLAGS0_SVE		BIT(1)
+#define RMI_REALM_FLAGS0_PMU		BIT(2)
+#define RMI_REALM_FLAGS0_DA		BIT(3)
+
+/* RmiRealmFlags1 format */
+#define RMI_REALM_FLAGS1_RTT_TREE_PP	BIT(0)
 
 /* RmiInterfaceVersion type */
 #define RMI_MAJOR_VERSION		0U
@@ -265,7 +523,11 @@
 #define RMI_EXIT_RIPAS_CHANGE		4U
 #define RMI_EXIT_HOST_CALL		5U
 #define RMI_EXIT_SERROR			6U
-#define RMI_EXIT_INVALID		(RMI_EXIT_SERROR + 1U)
+#define RMI_EXIT_IO			7U
+#define RMI_EXIT_RTT_REQUEST		8U
+#define RMI_EXIT_S2AP_CHANGE		9U
+#define RMI_EXIT_VDEV_REQUEST		10U
+#define RMI_EXIT_INVALID		(RMI_EXIT_VDEV_REQUEST + 1U)
 
 /* RmiRecRunnable types */
 #define RMI_NOT_RUNNABLE		0U
@@ -305,20 +567,34 @@
 #define RMI_FEATURE_REGISTER_0_GICV3_NUM_LRS_WIDTH	4UL
 #define RMI_FEATURE_REGISTER_0_MAX_RECS_ORDER_SHIFT	38UL
 #define RMI_FEATURE_REGISTER_0_MAX_RECS_ORDER_WIDTH	4UL
+#define RMI_FEATURE_REGISTER_0_DA_EN			BIT(42)
 
 /*
  * Format of feature_flag[63:32].
  * Value -1 (0 in case of NUM_BPS and NUM_WPS) indicates not set field,
  * and parameter will be set from the corresponding field of feature register 0.
  */
-#define FEATURE_SVE_VL_SHIFT				32UL
-#define FEATURE_SVE_VL_WIDTH				8UL
-#define FEATURE_NUM_BPS_SHIFT				40UL
-#define FEATURE_NUM_BPS_WIDTH				8UL
-#define FEATURE_NUM_WPS_SHIFT				48UL
-#define FEATURE_NUM_WPS_WIDTH				8UL
-#define FEATURE_PMU_NUM_CTRS_SHIFT			56UL
-#define FEATURE_PMU_NUM_CTRS_WIDTH			8UL
+#define RMI_FEATURE_REGISTER_0_DA			BIT(42)
+
+#define RMI_FEATURE_REGISTER_0_PLANE_RTT_SHIFT		43UL
+#define RMI_FEATURE_REGISTER_0_PLANE_RTT_WIDTH		2UL
+
+#define RMI_FEATURE_REGISTER_0_MAX_NUM_AUX_PLANES_SHIFT	45UL
+#define RMI_FEATURE_REGISTER_0_MAX_NUM_AUX_PLANES_WIDTH	4UL
+
+#define FEATURE_SVE_VL_SHIFT				56UL
+#define FEATURE_SVE_VL_WIDTH				4UL
+#define FEATURE_NUM_BPS_SHIFT				14UL
+#define FEATURE_NUM_BPS_WIDTH				6UL
+#define FEATURE_NUM_WPS_SHIFT				20UL
+#define FEATURE_NUM_WPS_WIDTH				6UL
+#define FEATURE_PMU_NUM_CTRS_SHIFT			35UL
+#define FEATURE_PMU_NUM_CTRS_WIDTH			4UL
+
+/* Possible values for RmiPlaneRttFeature */
+#define RMI_PLANE_RTT_AUX				0UL
+#define RMI_PLANE_RTT_AUX_SINGLE			1UL
+#define RMI_PLANE_RTT_SINGLE				2UL
 
 /* RmiStatusCode types */
 /*
@@ -358,6 +634,18 @@
 	 * index: RTT level at which the walk terminated
 	 */
 	RMI_ERROR_RTT = 4,
+	/*
+	 * An attribute of a device does not match the expected value
+	 */
+	RMI_ERROR_DEVICE = 5,
+	/*
+	 * The command is not supported
+	 */
+	RMI_ERROR_NOT_SUPPORTED = 6,
+	/*
+	 * RTTE in an auxiliary RTT contained an unexpected value
+	 */
+	RMI_ERROR_RTT_AUX = 7,
 	RMI_ERROR_COUNT
 } status_t;
 
@@ -398,31 +686,41 @@
  */
 struct rmi_realm_params {
 	/* Flags */
-	SET_MEMBER(unsigned long flags, 0, 0x8);		/* Offset 0 */
+	SET_MEMBER(unsigned long flags0, 0, 0x8);			/* Offset 0 */
 	/* Requested IPA width */
-	SET_MEMBER(unsigned int s2sz, 0x8, 0x10);		/* 0x8 */
+	SET_MEMBER(unsigned int s2sz, 0x8, 0x10);			/* 0x8 */
 	/* Requested SVE vector length */
-	SET_MEMBER(unsigned int sve_vl, 0x10, 0x18);		/* 0x10 */
+	SET_MEMBER(unsigned int sve_vl, 0x10, 0x18);			/* 0x10 */
 	/* Requested number of breakpoints */
-	SET_MEMBER(unsigned int num_bps, 0x18, 0x20);		/* 0x18 */
+	SET_MEMBER(unsigned int num_bps, 0x18, 0x20);			/* 0x18 */
 	/* Requested number of watchpoints */
-	SET_MEMBER(unsigned int num_wps, 0x20, 0x28);		/* 0x20 */
+	SET_MEMBER(unsigned int num_wps, 0x20, 0x28);			/* 0x20 */
 	/* Requested number of PMU counters */
-	SET_MEMBER(unsigned int pmu_num_ctrs, 0x28, 0x30);	/* 0x28 */
+	SET_MEMBER(unsigned int pmu_num_ctrs, 0x28, 0x30);		/* 0x28 */
 	/* Measurement algorithm */
-	SET_MEMBER(unsigned char hash_algo, 0x30, 0x400);	/* 0x30 */
+	SET_MEMBER(unsigned char algorithm, 0x30, 0x38);		/* 0x30 */
+	/* Number of auxiliary Planes */
+	SET_MEMBER(unsigned int num_aux_planes, 0x38, 0x400);		/* 0x38 */
 	/* Realm Personalization Value */
-	SET_MEMBER(unsigned char rpv[RPV_SIZE], 0x400, 0x800);	/* 0x400 */
+	SET_MEMBER(unsigned char rpv[RPV_SIZE], 0x400, 0x800);		/* 0x400 */
 	SET_MEMBER(struct {
-		/* Virtual Machine Identifier */
-		unsigned short vmid;				/* 0x800 */
-		/* Realm Translation Table base */
-		u_register_t rtt_base;				/* 0x808 */
-		/* RTT starting level */
-		long rtt_level_start;				/* 0x810 */
-		/* Number of starting level RTTs */
-		unsigned int rtt_num_start;			/* 0x818 */
-	}, 0x800, 0x1000);
+			/* Virtual Machine Identifier */
+			unsigned short vmid;				/* 0x800 */
+			/* Realm Translation Table base */
+			unsigned long rtt_base;				/* 0x808 */
+			/* RTT starting level */
+			long rtt_level_start;				/* 0x810 */
+			/* Number of starting level RTTs */
+			unsigned int rtt_num_start;			/* 0x818 */
+		   }, 0x800, 0x820);
+	/* Flags */
+	SET_MEMBER(unsigned long flags1, 0x820, 0x828);			/* 0x820 */
+	/* MECID */
+	SET_MEMBER(long mecid, 0x828, 0xF00);				/* 0x828 */
+	/* Auxiliary Virtual Machine Identifiers */
+	SET_MEMBER(unsigned short aux_vmid[3], 0xF00, 0xF80);		/* 0xF00 */
+	/* Base address of auxiliary RTTs */
+	SET_MEMBER(unsigned long aux_rtt_base[3], 0xF80, 0x1000);	/* 0xF80 */
 };
 
 /*
@@ -537,6 +835,249 @@
 	SET_MEMBER(struct rmi_rec_exit exit, 0x800, 0x1000);	/* 0x800 */
 };
 
+/*
+ * RmiPdevProtConfig
+ * Represents the protection between system and device.
+ * Width: 2 bits
+ */
+#define RMI_PDEV_IOCOH_E2E_IDE			U(0)
+#define RMI_PDEV_IOCOH_E2E_SYS			U(1)
+#define RMI_PDEV_FCOH_E2E_IDE			U(2)
+#define RMI_PDEV_FCOH_E2E_SYS			U(3)
+
+/*
+ * RmiPdevFlags
+ * Fieldset contains flags provided by the Host during PDEV creation
+ * Width: 64 bits
+ */
+/* RmiPdevProtConfig Bits 1:0 */
+#define RMI_PDEV_FLAGS_PROT_CONFIG_SHIFT	UL(0)
+#define RMI_PDEV_FLAGS_PROT_CONFIG_WIDTH	UL(2)
+
+/*
+ * RmiPdevEvent
+ * Represents physical device event.
+ * Width: 8 bits
+ */
+#define RMI_PDEV_EVENT_IDE_KEY_REFRESH		U(0)
+
+/*
+ * RmiPdevState
+ * Represents the state of a PDEV
+ * Width: 8 bits
+ */
+#define RMI_PDEV_STATE_NEW			U(0)
+#define RMI_PDEV_STATE_NEEDS_KEY		U(1)
+#define RMI_PDEV_STATE_HAS_KEY			U(2)
+#define RMI_PDEV_STATE_READY			U(3)
+#define RMI_PDEV_STATE_COMMUNICATING		U(4)
+#define RMI_PDEV_STATE_STOPPING			U(5)
+#define RMI_PDEV_STATE_STOPPED			U(6)
+#define RMI_PDEV_STATE_ERROR			U(7)
+
+/*
+ * RmiSignatureAlgorithm
+ * Represents signature algorithm used in PDEV set key RMI call.
+ * Width: 8 bits
+ */
+#define RMI_SIGNATURE_ALGORITHM_RSASSA_3072	U(0)
+#define RMI_SIGNATURE_ALGORITHM_ECDSA_P256	U(1)
+#define RMI_SIGNATURE_ALGORITHM_ECDSA_P384	U(2)
+
+/*
+ * RmiDevMemShared
+ * Represents whether device memory Granule should be shared
+ * Width: 1 bit
+ */
+#define RMI_DEV_MEM_PRIVATE			U(0)
+#define RMI_DEV_MEM_SHARED			U(1)
+
+/*
+ * RmiDevDelegateFlags
+ * Fieldset contains flags provided by the Host during device memory granule
+ * delegation.
+ * Width: 64 bits
+ */
+/* RmiDevMemShared: Bit 0 */
+#define RMI_DEV_DELEGATE_FLAGS_SHARE_SHIFT	U(0)
+#define RMI_DEV_DELEGATE_FLAGS_SHARE_WIDTH	U(1)
+
+/*
+ * RmiDevCommEnterStatus (Name in Spec RmiDevCommStatus)
+ * Represents status passed from the Host to the RMM during device communication.
+ * Width: 8 bits
+ */
+#define RMI_DEV_COMM_ENTER_STATUS_SUCCESS	U(0)
+#define RMI_DEV_COMM_ENTER_STATUS_ERROR		U(1)
+#define RMI_DEV_COMM_ENTER_STATUS_NONE		U(2)
+
+/*
+ * RmiDevCommEnter
+ * This structure contains data passed from the Host to the RMM during device
+ * communication.
+ * Width: 256 (0x100) bytes
+ */
+struct rmi_dev_comm_enter {
+	/* RmiDevCommEnterStatus: Status of device transaction */
+	SET_MEMBER_RMI(unsigned char status, 0, 0x8);
+	/* Address: Address of request buffer */
+	SET_MEMBER_RMI(unsigned long req_addr, 0x8, 0x10);
+	/* Address: Address of response buffer */
+	SET_MEMBER_RMI(unsigned long resp_addr, 0x10, 0x18);
+	/* UInt64: Amount of valid data in response buffer in bytes */
+	SET_MEMBER_RMI(unsigned long resp_len, 0x18, 0x100);
+};
+
+/*
+ * RmiDevCommExitFlags
+ * Fieldset contains flags provided by the RMM during a device transaction.
+ * Width: 64 bits
+ */
+#define RMI_DEV_COMM_EXIT_FLAGS_CACHE_SHIFT		UL(0)
+#define RMI_DEV_COMM_EXIT_FLAGS_CACHE_WIDTH		UL(1)
+#define RMI_DEV_COMM_EXIT_FLAGS_SEND_SHIFT		UL(1)
+#define RMI_DEV_COMM_EXIT_FLAGS_SEND_WIDTH		UL(1)
+#define RMI_DEV_COMM_EXIT_FLAGS_WAIT_SHIFT		UL(2)
+#define RMI_DEV_COMM_EXIT_FLAGS_WAIT_WIDTH		UL(1)
+#define RMI_DEV_COMM_EXIT_FLAGS_MULTI_SHIFT		UL(3)
+#define RMI_DEV_COMM_EXIT_FLAGS_MULTI_WIDTH		UL(1)
+
+/*
+ * RmiDevCommProtocol
+ * Represents the protocol used for device communication.
+ * Width: 8 bits
+ */
+#define RMI_DEV_COMM_PROTOCOL_SPDM		U(0)
+#define RMI_DEV_COMM_PROTOCOL_SECURE_SPDM	U(1)
+
+/*
+ * RmiDevCommExit
+ * This structure contains data passed from the RMM to the Host during device
+ * communication.
+ * Width: 256 (0x100) bytes.
+ */
+struct rmi_dev_comm_exit {
+	/*
+	 * RmiDevCommExitFlags: Flags indicating the actions the host is
+	 * requested to perform
+	 */
+	SET_MEMBER_RMI(unsigned long flags, 0, 0x8);
+	/*
+	 * UInt64: If flags.cache is true, offset in the device response buffer
+	 * to the start of data to be cached in bytes.
+	 */
+	SET_MEMBER_RMI(unsigned long cache_offset, 0x8, 0x10);
+	/*
+	 * UInt64: If flags.cache is true, amount of data to be cached in
+	 * bytes.
+	 */
+	SET_MEMBER_RMI(unsigned long cache_len, 0x10, 0x18);
+	/* RmiDevCommProtocol: If flags.send is true, type of request */
+	SET_MEMBER_RMI(unsigned char protocol, 0x18, 0x20);
+	/*
+	 * UInt64: If flags.send is true, amount of valid data in request buffer
+	 * in bytes
+	 */
+	SET_MEMBER_RMI(unsigned long req_len, 0x20, 0x28);
+	/*
+	 * UInt64: If flags.wait is true, amount of time to wait for device
+	 * response in milliseconds
+	 */
+	SET_MEMBER_RMI(unsigned long timeout, 0x28, 0x100);
+};
+
+/*
+ * RmiDevCommData
+ * This structure contains data structure shared between Host and RMM for
+ * device communication.
+ * Width: 4096 (0x1000) bytes.
+ */
+#define RMI_DEV_COMM_ENTER_OFFSET		0x0
+#define RMI_DEV_COMM_EXIT_OFFSET		0x800
+#define RMI_DEV_COMM_DATA_SIZE			0x1000
+struct rmi_dev_comm_data {
+	/* RmiDevCommEnter: Entry information */
+	SET_MEMBER_RMI(struct rmi_dev_comm_enter enter,
+		       RMI_DEV_COMM_ENTER_OFFSET, RMI_DEV_COMM_EXIT_OFFSET);
+	/* RmiDevCommExit: Exit information */
+	SET_MEMBER_RMI(struct rmi_dev_comm_exit exit,
+		       RMI_DEV_COMM_EXIT_OFFSET, RMI_DEV_COMM_DATA_SIZE);
+};
+
+/*
+ * RmiAddressRange
+ * This structure contains base and top value of an address range.
+ * Width: 16 (0x10) bytes.
+ */
+struct rmi_address_range {
+	/* Address: Base of the address range (inclusive) */
+	SET_MEMBER_RMI(unsigned long base, 0, 0x8);
+	/* Address: Top of the address range (exclusive) */
+	SET_MEMBER_RMI(unsigned long top, 0x8, 0x10);
+};
+
+/*
+ * Maximum number of aux granules paramenter passed in rmi_pdev_params during
+ * PDEV createto PDEV create
+ */
+#define PDEV_PARAM_AUX_GRANULES_MAX		U(32)
+
+/*
+ * Maximum number of IO coherent RmiAddressRange parameter passed in
+ * rmi_pdev_params during PDEV create
+ */
+#define PDEV_PARAM_IOCOH_ADDR_RANGE_MAX		U(16)
+
+/*
+ * Maximum number of fully coherent RmiAddressRange parameter passed in
+ * rmi_pdev_params during PDEV create
+ */
+#define PDEV_PARAM_FCOH_ADDR_RANGE_MAX		U(4)
+
+/*
+ * RmiPdevParams
+ * This structure contains parameters provided by Host during PDEV creation.
+ * Width: 4096 (0x1000) bytes.
+ */
+struct rmi_pdev_params {
+	/* RmiPdevFlags: Flags */
+	SET_MEMBER_RMI(unsigned long flags, 0, 0x8);
+	/* Bits64: Physical device identifier */
+	SET_MEMBER_RMI(unsigned long pdev_id, 0x8, 0x10);
+	/* Bits16: Segment ID */
+	SET_MEMBER_RMI(unsigned short segment_id, 0x10, 0x18);
+	/* Bits16: Root Port identifier */
+	SET_MEMBER_RMI(unsigned short root_id, 0x18, 0x20);
+	/* UInt64: Certificate identifier */
+	SET_MEMBER_RMI(unsigned long cert_id, 0x20, 0x28);
+	/* UInt64: Base requester ID range (inclusive) */
+	SET_MEMBER_RMI(unsigned long rid_base, 0x28, 0x30);
+	/* UInt64: Top of requester ID range (exclusive) */
+	SET_MEMBER_RMI(unsigned long rid_top, 0x30, 0x38);
+	/* RmiHashAlgorithm: Algorithm used to generate device digests */
+	SET_MEMBER_RMI(unsigned char hash_algo, 0x38, 0x40);
+	/* UInt64: Number of auxiliary granules */
+	SET_MEMBER_RMI(unsigned long num_aux, 0x40, 0x48);
+	/* UInt64: IDE stream identifier */
+	SET_MEMBER_RMI(unsigned long ide_sid, 0x48, 0x50);
+	/* UInt64: Number of IO-coherent address ranges */
+	SET_MEMBER_RMI(unsigned long iocoh_num_addr_range, 0x50, 0x58);
+	/* UInt64: Number of fully-coherent address ranges */
+	SET_MEMBER_RMI(unsigned long fcoh_num_addr_range, 0x58, 0x100);
+
+	/* Address: Addresses of auxiliary granules */
+	SET_MEMBER_RMI(unsigned long aux[PDEV_PARAM_AUX_GRANULES_MAX], 0x100,
+		       0x200);
+	/* RmiAddressRange: IO-coherent address range */
+	SET_MEMBER_RMI(struct rmi_address_range
+		       iocoh_addr_range[PDEV_PARAM_IOCOH_ADDR_RANGE_MAX],
+		       0x200, 0x300);
+	/* RmiAddressRange: Fully coherent address range */
+	SET_MEMBER_RMI(struct rmi_address_range
+		       fcoh_addr_range[PDEV_PARAM_FCOH_ADDR_RANGE_MAX],
+		       0x300, 0x1000);
+};
+
 struct rtt_entry {
 	long walk_level;
 	uint64_t out_addr;
@@ -554,6 +1095,7 @@
 struct realm {
 	u_register_t     host_shared_data;
 	unsigned int     rec_count;
+	unsigned int     num_aux_planes;
 	u_register_t     par_base;
 	u_register_t     par_size;
 	u_register_t     rd;
@@ -574,9 +1116,12 @@
 	uint8_t          pmu_num_ctrs;
 	bool             payload_created;
 	bool             shared_mem_created;
+	bool             rtt_tree_single;
 	unsigned short   vmid;
 	enum realm_state state;
 	long start_level;
+	u_register_t     aux_rtt_addr[MAX_AUX_PLANE_COUNT];
+	unsigned short   aux_vmid[MAX_AUX_PLANE_COUNT];
 };
 
 /* RMI/SMC */
@@ -615,6 +1160,12 @@
 				    u_register_t start,
 				    u_register_t end,
 				    u_register_t *top);
+u_register_t host_rmi_rtt_set_s2ap(u_register_t rd,
+				   u_register_t rec,
+				   u_register_t start,
+				   u_register_t end,
+				   u_register_t *top,
+				   u_register_t *rtt_tree);
 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);
@@ -646,4 +1197,15 @@
 					u_register_t map_size);
 u_register_t host_realm_fold_rtt(u_register_t rd, u_register_t addr, long level);
 
+u_register_t host_rmi_pdev_aux_count(u_register_t pdev_ptr, u_register_t *count);
+u_register_t host_rmi_pdev_create(u_register_t pdev_ptr,
+				  u_register_t params_ptr);
+u_register_t host_rmi_pdev_get_state(u_register_t pdev_ptr, u_register_t *state);
+u_register_t host_rmi_pdev_communicate(u_register_t pdev_ptr,
+				       u_register_t data_ptr);
+u_register_t host_rmi_pdev_set_pubkey(u_register_t pdev_ptr, u_register_t key,
+				      u_register_t len, uint8_t algo);
+u_register_t host_rmi_pdev_stop(u_register_t pdev_ptr);
+u_register_t host_rmi_pdev_destroy(u_register_t pdev_ptr);
+
 #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 7cfffe6..7005c0d 100644
--- a/include/runtime_services/host_realm_managment/host_shared_data.h
+++ b/include/runtime_services/host_realm_managment/host_shared_data.h
@@ -70,7 +70,10 @@
 	REALM_PAUTH_FAULT,
 	REALM_DIT_CHECK_CMD,
 	REALM_SME_ID_REGISTERS,
-	REALM_SME_UNDEF_ABORT
+	REALM_SME_UNDEF_ABORT,
+	REALM_FEAT_DOUBLEFAULT2_TEST,
+	REALM_ATTESTATION,
+	REALM_ATTESTATION_FAULT
 };
 
 /*
diff --git a/include/runtime_services/host_realm_managment/realm_def.h b/include/runtime_services/host_realm_managment/realm_def.h
index 5258b87..5d3a196 100644
--- a/include/runtime_services/host_realm_managment/realm_def.h
+++ b/include/runtime_services/host_realm_managment/realm_def.h
@@ -10,7 +10,7 @@
 
 #include <xlat_tables_defs.h>
 
-/* 1MB for Realm payload as a default value */
+/* 1 MB for Realm payload as a default value */
 #define REALM_MAX_LOAD_IMG_SIZE		U(0x100000)
 #define REALM_STACK_SIZE		0x1000U
 #define DATA_PATTERN_1			0x12345678U
@@ -19,6 +19,10 @@
 #define REALM_ERROR			1U
 #define MAX_REC_COUNT			17U
 #define MAX_REALM_COUNT			U(2)
+#define MAX_AUX_PLANE_COUNT		U(3)
+#define MAX_PLANE_COUNT			MAX_AUX_PLANE_COUNT + U(1)
+#define PRIMARY_RTT_INDEX		0U
+#define PRIMARY_PLANE_ID		0U
 
 /* Only support 4KB at the moment */
 
@@ -101,4 +105,6 @@
 		(((idx) & ~MASK(RMI_MPIDR_AFF0)) << 	\
 		(RMI_MPIDR_AFF1_SHIFT - RMI_MPIDR_AFF0_WIDTH)));
 
+#define REALM_TOKEN_BUF_SIZE		GRANULE_SIZE
+
 #endif /* REALM_DEF_H */
diff --git a/include/runtime_services/smccc.h b/include/runtime_services/smccc.h
index b898138..513ec8f 100644
--- a/include/runtime_services/smccc.h
+++ b/include/runtime_services/smccc.h
@@ -80,4 +80,9 @@
 #define SMC_GET_SOC_VERSION		0
 #define SMC_GET_SOC_REVISION		1
 
+#define SCR_EL3_OPCODE			U(0x1E1100)
+#define CPTR_EL3_OPCODE			U(0x1E1140)
+#define MDCR_EL3_OPCODE			U(0x1E1320)
+#define MPAM3_EL3_OPCODE		U(0x1EA500)
+
 #endif /* __SMCCC_H__ */
diff --git a/include/runtime_services/spm_test_helpers.h b/include/runtime_services/spm_test_helpers.h
index 93027d6..14b2fb5 100644
--- a/include/runtime_services/spm_test_helpers.h
+++ b/include/runtime_services/spm_test_helpers.h
@@ -104,12 +104,6 @@
                                       event_t *cpu_booted);
 
 /**
- * Call FFA_RUN in the designated SP to make it reach the message loop.
- * Used within CPU_ON handlers, to bring up the SP in the current core.
- */
-bool spm_core_sp_init(ffa_id_t sp_id);
-
-/**
  * Initializes the Mailbox for other SPM related tests that need to use
  * RXTX buffers.
  */
diff --git a/lib/context_mgmt/aarch64/context_el2.c b/lib/context_mgmt/aarch64/context_el2.c
index 3049274..2bea84b 100644
--- a/lib/context_mgmt/aarch64/context_el2.c
+++ b/lib/context_mgmt/aarch64/context_el2.c
@@ -57,7 +57,7 @@
 {
 	if (is_armv8_6_fgt_present()) {
 		EL2_SAVE_CTX_REG(ctx, hdfgrtr_el2);
-		if (is_armv8_4_amuv1_present())
+		if (is_feat_amuv1_present())
 			EL2_SAVE_CTX_REG(ctx, hafgrtr_el2);
 		EL2_SAVE_CTX_REG(ctx, hdfgwtr_el2);
 		EL2_SAVE_CTX_REG(ctx, hfgitr_el2);
@@ -231,7 +231,7 @@
 {
 	if (is_armv8_6_fgt_present()) {
 		EL2_WRITE_MASK_CTX_REG(ctx, hdfgrtr_el2, or_mask);
-		if (is_armv8_4_amuv1_present())
+		if (is_feat_amuv1_present())
 			EL2_WRITE_MASK_CTX_REG(ctx, hafgrtr_el2, or_mask);
 		EL2_WRITE_MASK_CTX_REG(ctx, hdfgwtr_el2, or_mask);
 		EL2_WRITE_MASK_CTX_REG(ctx, hfgitr_el2, or_mask);
diff --git a/lib/exceptions/aarch64/serror.c b/lib/exceptions/aarch64/serror.c
index 9c35712..a57514b 100644
--- a/lib/exceptions/aarch64/serror.c
+++ b/lib/exceptions/aarch64/serror.c
@@ -9,9 +9,9 @@
 #include <debug.h>
 #include <serror.h>
 
-static exception_handler_t custom_serror_handler;
+static serr_exception_handler_t custom_serror_handler;
 
-void register_custom_serror_handler(exception_handler_t handler)
+void register_custom_serror_handler(serr_exception_handler_t handler)
 {
 	custom_serror_handler = handler;
 }
@@ -23,9 +23,24 @@
 
 bool tftf_serror_handler(void)
 {
+	uint64_t elr_elx = IS_IN_EL2() ? read_elr_el2() : read_elr_el1();
+	bool resume = false;
+	bool incr_elr_elx = false;
+
 	if (custom_serror_handler == NULL) {
 		return false;
 	}
 
-	return custom_serror_handler();
+	resume = custom_serror_handler(&incr_elr_elx);
+
+	if (resume && incr_elr_elx) {
+		/* Move ELR to next instruction to allow tftf to continue */
+		if (IS_IN_EL2()) {
+			write_elr_el2(elr_elx + 4U);
+		} else {
+			write_elr_el1(elr_elx + 4U);
+		}
+	}
+
+	return resume;
 }
diff --git a/lib/ext_mbedtls/mbedtls.mk b/lib/ext_mbedtls/mbedtls.mk
new file mode 100644
index 0000000..74ab284
--- /dev/null
+++ b/lib/ext_mbedtls/mbedtls.mk
@@ -0,0 +1,55 @@
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+MBEDTLS_DIR ?= ext/mbedtls
+ifeq (${MBEDTLS_DIR},)
+$(error Error: MBEDTLS_DIR not set)
+endif
+
+MBEDTLS_PRESENT := $(wildcard ${MBEDTLS_DIR}/include/mbedtls)
+
+ifneq (${MBEDTLS_PRESENT},)
+$(info Found mbedTLS at ${MBEDTLS_DIR})
+
+TFTF_INCLUDES += -I${MBEDTLS_DIR}/include
+MBEDTLS_CONFIG_FILE ?= "<configs/tftf_mbedtls_config.h>"
+$(eval $(call add_define,TFTF_DEFINES,MBEDTLS_CONFIG_FILE))
+
+#
+# Include mbedtls source required to parse x509 certificate and its helper
+# routines. This can be later extended to include other crypto/PSA crypto
+# library sources.
+#
+TESTS_SOURCES	+=				\
+	$(addprefix ${MBEDTLS_DIR}/library/,	\
+		asn1parse.c			\
+		asn1write.c			\
+		constant_time.c			\
+		bignum.c			\
+		oid.c				\
+		hmac_drbg.c			\
+		memory_buffer_alloc.c		\
+		platform.c 			\
+		platform_util.c			\
+		bignum_core.c			\
+		md.c				\
+		pk.c 				\
+		pk_ecc.c 			\
+		pk_wrap.c 			\
+		pkparse.c 			\
+		sha256.c            		\
+		sha512.c            		\
+		ecdsa.c				\
+		ecp_curves.c			\
+		ecp.c				\
+		rsa.c				\
+		rsa_alt_helpers.c		\
+		x509.c 				\
+		x509_crt.c 			\
+		)
+else
+$(info MbedTLS not found, some dependent tests will be skipped or fail.)
+endif
diff --git a/lib/extensions/amu/aarch32/amu.c b/lib/extensions/amu/aarch32/amu.c
index f730568..56abf7a 100644
--- a/lib/extensions/amu/aarch32/amu.c
+++ b/lib/extensions/amu/aarch32/amu.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,22 +7,10 @@
 #include <amu.h>
 #include <amu_private.h>
 #include <arch.h>
+#include <arch_features.h>
 #include <arch_helpers.h>
 #include <assert.h>
 
-/*
- * Get AMU version value from pfr0.
- * Return values
- *   ID_PFR0_AMU_V1: FEAT_AMUv1 supported (introduced in ARM v8.4)
- *   ID_PFR0_AMU_V1P1: FEAT_AMUv1p1 supported (introduced in ARM v8.6)
- *   ID_PFR0_AMU_NOT_SUPPORTED: not supported
- */
-unsigned int amu_get_version(void)
-{
-	return (unsigned int)(read_id_pfr0() >> ID_PFR0_AMU_SHIFT) &
-		ID_PFR0_AMU_MASK;
-}
-
 /* Read the group 0 counter identified by the given `idx`. */
 uint64_t amu_group0_cnt_read(unsigned int idx)
 {
diff --git a/lib/extensions/amu/aarch64/amu.c b/lib/extensions/amu/aarch64/amu.c
index 491edde..c089746 100644
--- a/lib/extensions/amu/aarch64/amu.c
+++ b/lib/extensions/amu/aarch64/amu.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,21 +7,10 @@
 #include <amu.h>
 #include <amu_private.h>
 #include <arch.h>
+#include <arch_features.h>
 #include <arch_helpers.h>
 #include <assert.h>
 
-/*
- * Get AMU version value from aa64pfr0.
- * Return values
- *   ID_AA64PFR0_AMU_V1: FEAT_AMUv1 supported (introduced in ARM v8.4)
- *   ID_AA64PFR0_AMU_V1P1: FEAT_AMUv1p1 supported (introduced in ARM v8.6)
- *   ID_AA64PFR0_AMU_NOT_SUPPORTED: not supported
- */
-unsigned int amu_get_version(void)
-{
-	return (unsigned int)(read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT) &
-		ID_AA64PFR0_AMU_MASK;
-}
 
 /* Check if group 1 counters is implemented */
 int amu_group1_supported(void)
diff --git a/lib/extensions/sysreg128/aarch64/sysreg128_helpers.S b/lib/extensions/sysreg128/aarch64/sysreg128_helpers.S
new file mode 100644
index 0000000..27db8b1
--- /dev/null
+++ b/lib/extensions/sysreg128/aarch64/sysreg128_helpers.S
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+
+#if __aarch64__
+
+    .globl read128_par_el1
+    .globl read128_ttbr0_el1
+    .globl read128_ttbr1_el1
+    .globl read128_ttbr0_el2
+    .globl read128_ttbr1_el2
+    .globl read128_vttbr_el2
+    .globl read128_rcwmask_el1
+    .globl read128_rcwsmask_el1
+    .globl write128_par_el1
+    .globl write128_ttbr0_el1
+    .globl write128_ttbr1_el1
+    .globl write128_ttbr0_el2
+    .globl write128_ttbr1_el2
+    .globl write128_vttbr_el2
+    .globl write128_rcwmask_el1
+    .globl write128_rcwsmask_el1
+
+func read128_par_el1 /* MRRS x0, x1, S3_0_C7_C4_0 */
+    .inst 0xD5787400
+    ret
+endfunc read128_par_el1
+
+func read128_ttbr0_el1 /* MRRS x0, x1, S3_0_C2_C0_0 */
+    .inst 0xD5782000
+    ret
+endfunc read128_ttbr0_el1
+
+func read128_ttbr1_el1 /* MRRS x0, x1, S3_0_C2_C0_1 */
+    .inst 0xD5782020
+    ret
+endfunc read128_ttbr1_el1
+
+func read128_ttbr0_el2 /* MRRS x0, x1, S3_4_C2_C0_0 */
+    .inst 0xD57C2000
+    ret
+endfunc read128_ttbr0_el2
+
+func read128_ttbr1_el2 /* MRRS x0, x1, S3_4_C2_C0_1 */
+    .inst 0xD57C2020
+    ret
+endfunc read128_ttbr1_el2
+
+func read128_vttbr_el2 /* MRRS x0, x1, S3_4_C2_C1_0 */
+    .inst 0xD57C2100
+    ret
+endfunc read128_vttbr_el2
+
+func read128_rcwmask_el1 /* MRRS x0, x1, S3_0_C13_C0_6 */
+    .inst 0xD578D0C0
+    ret
+endfunc read128_rcwmask_el1
+
+func read128_rcwsmask_el1 /* MRRS x0, x1, S3_0_C13_C0_3 */
+    .inst 0xD578D060
+    ret
+endfunc read128_rcwsmask_el1
+
+func write128_par_el1 /* MSRR S3_0_C7_C4_0, x0, x1 */
+    .inst 0xD5587400
+    ret
+endfunc write128_par_el1
+
+func write128_ttbr0_el1 /* MSRR S3_0_C2_C0_0, x0, x1 */
+    .inst 0xD5582000
+    ret
+endfunc write128_ttbr0_el1
+
+func write128_ttbr1_el1 /* MSRR S3_0_C2_C0_1, x0, x1 */
+    .inst 0xD5582020
+    ret
+endfunc write128_ttbr1_el1
+
+func write128_ttbr0_el2 /* MSRR S3_4_C2_C0_0, x0, x1 */
+    .inst 0xD55C2000
+    ret
+endfunc write128_ttbr0_el2
+
+func write128_ttbr1_el2 /* MSRR S3_4_C2_C0_1, x0, x1 */
+    .inst 0xD55C2020
+    ret
+endfunc write128_ttbr1_el2
+
+func write128_vttbr_el2 /* MSRR S3_4_C2_C1_0, x0, x1 */
+    .inst 0xD55C2100
+    ret
+endfunc write128_vttbr_el2
+
+func write128_rcwmask_el1 /* MSRR S3_0_C13_C0_6, x0, x1 */
+    .inst 0xD558D0C0
+    ret
+endfunc write128_rcwmask_el1
+
+func write128_rcwsmask_el1 /* MSRR S3_0_C13_C0_3, x0, x1 */
+    .inst 0xD558D060
+    ret
+endfunc write128_rcwsmask_el1
+
+#endif /* __aarch64__ */
diff --git a/lib/pcie/pcie.c b/lib/pcie/pcie.c
index c3906d5..8de2825 100644
--- a/lib/pcie/pcie.c
+++ b/lib/pcie/pcie.c
@@ -5,19 +5,20 @@
  */
 
 #include <assert.h>
+#include <errno.h>
 #include <stddef.h>
 
 #include <debug.h>
 #include <mmio.h>
 #include <pcie.h>
+#include <pcie_doe.h>
 #include <pcie_spec.h>
+#include <platform.h>
 #include <tftf_lib.h>
 
-#include <platform_pcie.h>
-
 #define PCIE_DEBUG	VERBOSE
 
-const pcie_info_table_t *g_pcie_info_table;
+const struct pcie_info_table *g_pcie_info_table;
 pcie_device_bdf_table_t *g_pcie_bdf_table;
 
 pcie_device_bdf_table_t pcie_bdf_table[PCIE_DEVICE_BDF_TABLE_SZ];
@@ -256,6 +257,8 @@
 		return 1;
 	}
 
+	assert(g_pcie_bdf_table != NULL);
+
 	while (index < g_pcie_bdf_table->num_entries) {
 		*rp_bdf = g_pcie_bdf_table->device[index++].bdf;
 
@@ -294,6 +297,8 @@
 	uint32_t bdf, rp_bdf;
 	pcie_device_bdf_table_t *bdf_tbl_ptr = g_pcie_bdf_table;
 
+	assert(bdf_tbl_ptr != NULL);
+
 	for (unsigned int tbl_index = 0; tbl_index < bdf_tbl_ptr->num_entries;
 								tbl_index++) {
 		bdf = bdf_tbl_ptr->device[tbl_index].bdf;
@@ -317,6 +322,8 @@
  */
 pcie_device_bdf_table_t *pcie_get_bdf_table(void)
 {
+	assert(g_pcie_bdf_table != NULL);
+
 	return g_pcie_bdf_table;
 }
 
@@ -336,6 +343,8 @@
 	assert(g_pcie_bdf_table != NULL);
 
 	g_pcie_bdf_table->num_entries = 0;
+
+	assert(g_pcie_info_table != NULL);
 	assert(g_pcie_info_table->num_entries != 0);
 
 	for (ecam_index = 0; ecam_index < g_pcie_info_table->num_entries; ecam_index++) {
@@ -420,6 +429,8 @@
 	uint32_t reg_value;
 	uintptr_t ecam_base = 0;
 
+	assert(g_pcie_info_table != NULL);
+
 	while (ecam_index < g_pcie_info_table->num_entries) {
 		/* Derive ECAM specific information */
 		const pcie_info_block_t *block = &g_pcie_info_table->block[ecam_index];
@@ -462,13 +473,15 @@
 	uint32_t ecam_index = 0;
 	uint32_t ecam_base, ecam_start_bus, ecam_end_bus;
 	pcie_device_bdf_table_t *bdf_tbl_ptr = g_pcie_bdf_table;
-	uint32_t num_rciep = 0, num_rcec = 0;
-	uint32_t num_iep = 0, num_irp = 0;
-	uint32_t num_ep = 0, num_rp = 0;
-	uint32_t num_dp = 0, num_up = 0;
-	uint32_t num_pcie_pci = 0, num_pci_pcie = 0;
+	uint32_t num_rciep __unused = 0, num_rcec __unused = 0;
+	uint32_t num_iep __unused = 0, num_irp __unused = 0;
+	uint32_t num_ep __unused = 0, num_rp __unused = 0;
+	uint32_t num_dp __unused = 0, num_up __unused = 0;
+	uint32_t num_pcie_pci __unused = 0, num_pci_pcie __unused = 0;
 	uint32_t bdf_counter;
 
+	assert(bdf_tbl_ptr != NULL);
+
 	if (bdf_tbl_ptr->num_entries == 0) {
 		INFO("BDF Table: No RCiEP or iEP found\n");
 		return;
@@ -525,6 +538,8 @@
 	INFO("Number of PCI/PCIe Bridge: %u\n", num_pci_pcie);
 	INFO("Number of PCIe/PCI Bridge: %u\n", num_pcie_pci);
 
+	assert(g_pcie_info_table != NULL);
+
 	while (ecam_index < g_pcie_info_table->num_entries) {
 
 		/* Derive ECAM specific information */
@@ -540,7 +555,7 @@
 
 		while (tbl_index < bdf_tbl_ptr->num_entries) {
 			uint32_t seg_num, bus_num, dev_num, func_num;
-			uint32_t device_id, vendor_id, reg_value;
+			uint32_t device_id __unused, vendor_id __unused, reg_value;
 			uint32_t bdf, dev_ecam_base;
 
 			bdf = bdf_tbl_ptr->device[tbl_index++].bdf;
@@ -588,13 +603,30 @@
 	INFO("Creating PCIe info table\n");
 
 	g_pcie_info_table = plat_pcie_get_info_table();
+	if (g_pcie_info_table == NULL) {
+		ERROR("PCIe info not returned by platform\n");
+		panic();
+	}
+
 	g_pcie_bdf_table = pcie_bdf_table;
 
 	num_ecam = g_pcie_info_table->num_entries;
 	INFO("Number of ECAM regions   : %u\n", num_ecam);
-	if (num_ecam == 0) {
-		return;
+	if ((num_ecam == 0) || (num_ecam > MAX_PCIE_INFO_ENTRIES)) {
+		ERROR("PCIe info entries invalid\n");
+		panic();
 	}
 	pcie_create_device_bdf_table();
 	pcie_print_device_info();
 }
+
+void pcie_init(void)
+{
+	static bool is_init;
+
+	/* Create PCIe table and enumeration */
+	if (!is_init) {
+		pcie_create_info_table();
+		is_init = true;
+	}
+}
diff --git a/lib/pcie/pcie_doe.c b/lib/pcie/pcie_doe.c
index 3c6819c..bd8e53a 100644
--- a/lib/pcie/pcie_doe.c
+++ b/lib/pcie/pcie_doe.c
@@ -5,7 +5,9 @@
  *
  */
 
+#include <assert.h>
 #include <errno.h>
+#include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -14,12 +16,6 @@
 #include <pcie_doe.h>
 #include <tftf_lib.h>
 
-#if LOG_LEVEL >= LOG_LEVEL_INFO
-#define DOE_INFO(...)	mp_printf(__VA_ARGS__)
-#else
-#define DOE_INFO(...)
-#endif
-
 static int pcie_doe_wait_ready(uint32_t bdf, uint32_t doe_cap_base)
 {
 	uint32_t value;
@@ -65,9 +61,9 @@
 	INFO("Vendor ID: 0x%x, ", data->vendor_id);
 
 	if (type >= ARRAY_SIZE(doe_object_type)) {
-		DOE_INFO("Unknown type: 0x%x\n", type);
+		INFO("Unknown type: 0x%x\n", type);
 	} else {
-		DOE_INFO("%s\n", doe_object_type[type]);
+		INFO("%s\n", doe_object_type[type]);
 	}
 }
 
@@ -77,16 +73,16 @@
 
 	if (last) {
 		if ((j & 7) == 0) {
-			INFO(" %08x\n", data);
+			VERBOSE(" %08x\n", data);
 		} else {
-			DOE_INFO(" %08x\n", data);
+			VERBOSE(" %08x\n", data);
 		}
 	} else if ((j & 7) == 0) {
-		INFO(" %08x", data);
+		VERBOSE(" %08x", data);
 	} else if ((j & 7) == 7) {
-		DOE_INFO(" %08x\n", data);
+		VERBOSE(" %08x\n", data);
 	} else {
-		DOE_INFO(" %08x", data);
+		VERBOSE(" %08x", data);
 	}
 }
 
@@ -121,11 +117,11 @@
 	/* Calculated adjusted data length in DW */
 	doe_length = (rem_length == 0) ? send_length : (send_length + 1);
 
-	INFO(">%08x", header);
+	VERBOSE(">%08x", header);
 
 	pcie_write_cfg(bdf, doe_cap_base + DOE_WRITE_DATA_MAILBOX_REG,
 								header);
-	DOE_INFO(" %08x", doe_length + DOE_HEADER_LENGTH);
+	VERBOSE(" %08x", doe_length + DOE_HEADER_LENGTH);
 
 	pcie_write_cfg(bdf, doe_cap_base + DOE_WRITE_DATA_MAILBOX_REG,
 				doe_length + DOE_HEADER_LENGTH);
@@ -144,7 +140,7 @@
 		pcie_write_cfg(bdf, doe_cap_base + DOE_WRITE_DATA_MAILBOX_REG, value);
 
 	} else if (((i + DOE_HEADER_LENGTH) & 7) != 0) {
-		DOE_INFO("\n");
+		VERBOSE("\n");
 	}
 
 	/* Set Go bit */
@@ -178,7 +174,7 @@
 	 * Vendor ID and Data Object Type
 	 */
 	value = pcie_read_cfg(bdf, doe_cap_base + DOE_READ_DATA_MAILBOX_REG);
-	INFO("<%08x", value);
+	VERBOSE("<%08x", value);
 
 	/* Indicate a successful transfer of the current data object DW */
 	pcie_write_cfg(bdf, doe_cap_base + DOE_READ_DATA_MAILBOX_REG, 0);
@@ -188,13 +184,13 @@
 	 * Length in DW
 	 */
 	value = pcie_read_cfg(bdf, doe_cap_base + DOE_READ_DATA_MAILBOX_REG);
-	DOE_INFO(" %08x", value);
+	VERBOSE(" %08x", value);
 
 	pcie_write_cfg(bdf, doe_cap_base + DOE_READ_DATA_MAILBOX_REG, 0);
 
 	/* Check value */
 	if ((value & PCI_DOE_RESERVED_MASK) != 0) {
-		DOE_INFO("\n");
+		VERBOSE("\n");
 		ERROR("DOE Data Object Header 2 error\n");
 		return -EIO;
 	}
@@ -214,7 +210,7 @@
 	}
 
 	if (((i + DOE_HEADER_LENGTH) & 7) != 0) {
-		DOE_INFO("\n");
+		VERBOSE("\n");
 	}
 
 	value = pcie_read_cfg(bdf, doe_cap_base + DOE_STATUS_REG);
@@ -225,3 +221,55 @@
 
 	return 0;
 }
+
+int pcie_doe_communicate(uint32_t header, uint32_t bdf, uint32_t doe_cap_base,
+			 void *req_buf, size_t req_sz, void *rsp_buf, size_t *rsp_sz)
+{
+	int rc;
+
+	assert(header == DOE_HEADER_0 || header == DOE_HEADER_1 || header == DOE_HEADER_2);
+
+	rc = pcie_doe_send_req(header, bdf, doe_cap_base,
+			       (uint32_t *)req_buf, (uint32_t)req_sz);
+	if (rc != 0) {
+		ERROR("PCIe DOE %s failed %d\n", "Request", rc);
+		return rc;
+	}
+
+	rc = pcie_doe_recv_resp(bdf, doe_cap_base, (uint32_t *)rsp_buf,
+				(uint32_t *)rsp_sz);
+	return rc;
+}
+
+int pcie_find_doe_device(uint32_t *bdf_ptr, uint32_t *cap_base_ptr)
+{
+	pcie_device_bdf_table_t *bdf_table_ptr = pcie_get_bdf_table();
+	uint32_t num_bdf = bdf_table_ptr->num_entries;
+
+	INFO("PCI BDF table entries: %u\n", num_bdf);
+
+	/* If no entries in BDF table return error */
+	if (num_bdf == 0) {
+		ERROR("No BDFs entries found\n");
+		return -ENODEV;
+	}
+
+	INFO("PCI BDF table 0x%lx\n", (uintptr_t)bdf_table_ptr);
+
+	while (num_bdf-- != 0) {
+		uint32_t bdf = bdf_table_ptr->device[num_bdf].bdf;
+		uint32_t status, doe_cap_base;
+
+		/* Check for DOE capability */
+		status = pcie_find_capability(bdf, PCIE_ECAP, DOE_CAP_ID, &doe_cap_base);
+		if (status == PCIE_SUCCESS) {
+			INFO("PCIe DOE capability: bdf 0x%x cap_base 0x%x\n", bdf, doe_cap_base);
+			*bdf_ptr = bdf;
+			*cap_base_ptr = doe_cap_base;
+			return 0;
+		}
+	}
+
+	ERROR("No PCIe DOE capability found\n");
+	return -ENODEV;
+}
diff --git a/lib/power_management/hotplug/hotplug.c b/lib/power_management/hotplug/hotplug.c
index 5c68642..3981aa9 100644
--- a/lib/power_management/hotplug/hotplug.c
+++ b/lib/power_management/hotplug/hotplug.c
@@ -254,7 +254,7 @@
 	tftf_prepare_cpu_off();
 	tftf_set_cpu_offline();
 
-	INFO("Powering off\n");
+	INFO("Powering off CPU:%lx\n", read_mpidr_el1());
 
 	/* Flush console before the last CPU is powered off. */
 	if (tftf_get_ref_cnt() == 0)
@@ -307,7 +307,7 @@
 
 	enable_irq();
 
-	INFO("Booting\n");
+	INFO("Booting CPU:%lx\n", read_mpidr_el1());
 
 	tftf_set_cpu_online();
 
diff --git a/lib/smc/aarch64/asm_smc.S b/lib/smc/aarch64/asm_smc.S
index b11baa8..d4cede9 100644
--- a/lib/smc/aarch64/asm_smc.S
+++ b/lib/smc/aarch64/asm_smc.S
@@ -38,6 +38,59 @@
 
 	.endm
 
+	.macro smccc_conduit_nox8 _conduit
+
+	/*
+	 * Store address pointing at the smc_ret_values structure in the stack
+	 */
+	str	x1, [sp, #-16]!
+
+	/*
+	 * Store arguments in x0..x17. Start from highest registers so address
+	 * pointed by x0 is preserved until it is no longer needed.
+	 */
+	ldp	x16, x17, [x0, #128]
+	ldp	x14, x15, [x0, #112]
+	ldp	x12, x13, [x0, #96]
+	ldp	x10, x11, [x0, #80]
+	ldp	x8, x9, [x0, #64]
+	ldp	x6, x7, [x0, #48]
+	ldp	x4, x5, [x0, #32]
+	ldp	x2, x3, [x0, #16]
+	ldp	x0, x1, [x0, #0]
+
+	/* "Conduit" arguments are already stored in x0..x17 */
+	\_conduit	#0
+
+	/*
+	 * Store value received in x0 as x0 will be used to compute addresses
+	 * to store the results.
+	 */
+	str	x0, [sp, #-16]!
+
+	/* Load address of smc_ret_values structure into x0 */
+	ldr	x0, [sp, #16]
+
+	/* Store values x1..x17 in the smc_ret_values structure */
+	stp	x16, x17, [x0, #128]
+	stp	x14, x15, [x0, #112]
+	stp	x12, x13, [x0, #96]
+	stp	x10, x11, [x0, #80]
+	stp	x8, x9, [x0, #64]
+	stp	x6, x7, [x0, #48]
+	stp	x4, x5, [x0, #32]
+	stp	x2, x3, [x0, #16]
+	str	x1, [x0, #8]
+
+	/*
+	 * Load previously stored value of x0 into x1 and store it in the
+	 * smc_ret_values structure. Return sp to its original position.
+	 */
+	ldr	x1, [sp], #32
+	str	x1, [x0, #0]
+
+	.endm
+
 /* ---------------------------------------------------------------------------
  * smc_ret_values asm_tftf_smc64(uint32_t fid,
  *				 u_register_t arg1,
@@ -56,6 +109,17 @@
 	ret
 endfunc asm_tftf_smc64
 
+	.globl asm_tftf_smc64_no_retval_x8
+
+/* ---------------------------------------------------------------------------
+ * void asm_tftf_smc64_no_retval_x8(smc_args *args, smc_ret_values *ret);
+ * ---------------------------------------------------------------------------
+ */
+func asm_tftf_smc64_no_retval_x8
+	smccc_conduit_nox8 smc
+	ret
+endfunc asm_tftf_smc64_no_retval_x8
+
 /* ---------------------------------------------------------------------------
  * hvc_ret_values asm_tftf_hvcc64(uint32_t fid,
  *				 u_register_t arg1,
diff --git a/lib/smc/aarch64/smc.c b/lib/smc/aarch64/smc.c
index 9912e72..b0fea4b 100644
--- a/lib/smc/aarch64/smc.c
+++ b/lib/smc/aarch64/smc.c
@@ -102,3 +102,19 @@
 			      args->arg6,
 			      args->arg7);
 }
+
+void tftf_smc_no_retval_x8(const smc_args_ext *args, smc_ret_values_ext *ret)
+{
+	uint32_t fid = args->fid;
+	/* Copy args into new structure so the fid field can be modified */
+	smc_args_ext args_copy = *args;
+
+	if (tftf_smc_get_sve_hint()) {
+		fid |= MASK(FUNCID_SVE_HINT);
+	} else {
+		fid &= ~MASK(FUNCID_SVE_HINT);
+	}
+	args_copy.fid = fid;
+
+	asm_tftf_smc64_no_retval_x8(&args_copy, ret);
+}
diff --git a/plat/arm/fvp/fvp_pcie.c b/plat/arm/fvp/fvp_pcie.c
index 0569832..c43e42d 100644
--- a/plat/arm/fvp/fvp_pcie.c
+++ b/plat/arm/fvp/fvp_pcie.c
@@ -11,7 +11,7 @@
 
 CASSERT(PLATFORM_NUM_ECAM != 0, PLATFORM_NUM_ECAM_is_zero);
 
-const pcie_info_table_t fvp_pcie_cfg = {
+const struct pcie_info_table fvp_pcie_cfg = {
 	.num_entries = PLATFORM_NUM_ECAM,
 	.block[0] = {
 		PLATFORM_PCIE_ECAM_BASE_ADDR_0,
@@ -21,7 +21,7 @@
 	}
 };
 
-const pcie_info_table_t *plat_pcie_get_info_table(void)
+const struct pcie_info_table *plat_pcie_get_info_table(void)
 {
 	return &fvp_pcie_cfg;
 }
diff --git a/plat/arm/fvp/include/platform_pcie.h b/plat/arm/fvp/include/platform_pcie.h
index c76c7d9..4b3a0e9 100644
--- a/plat/arm/fvp/include/platform_pcie.h
+++ b/plat/arm/fvp/include/platform_pcie.h
@@ -19,6 +19,4 @@
 #define PLATFORM_PCIE_START_BUS_NUM_0	0x0
 #define PLATFORM_PCIE_END_BUS_NUM_0	0xFF
 
-const pcie_info_table_t *plat_pcie_get_info_table(void);
-
 #endif	/* PLATFORM_PCIE_H */
diff --git a/plat/arm/fvp/plat_setup.c b/plat/arm/fvp/plat_setup.c
index e6e4244..69cb0a1 100644
--- a/plat/arm/fvp/plat_setup.c
+++ b/plat/arm/fvp/plat_setup.c
@@ -35,9 +35,7 @@
 #if USE_NVM
 	MAP_REGION_FLAT(FLASH_BASE, FLASH_SIZE, MT_DEVICE | MT_RW | MT_NS),
 #endif
-#if USE_PCIE
 	MAP_REGION_FLAT(PCIE_CONFIG_BASE, PCIE_CONFIG_SIZE, MT_DEVICE | MT_RW | MT_NS),
-#endif
 	MAP_REGION_FLAT(DRAM_BASE, TFTF_BASE - DRAM_BASE, MT_MEMORY | MT_RW | MT_NS),
 	{0}
 };
diff --git a/plat/arm/fvp/platform.mk b/plat/arm/fvp/platform.mk
index 7a2850f..ee30721 100644
--- a/plat/arm/fvp/platform.mk
+++ b/plat/arm/fvp/platform.mk
@@ -90,12 +90,8 @@
 $(eval $(call add_define,TFTF_DEFINES,PA_SIZE))
 $(eval $(call add_define,REALM_DEFINES,PA_SIZE))
 
-ifeq ($(TESTS),pcie-doe)
-USE_PCIE=1
-$(eval $(call add_define,TFTF_DEFINES,USE_PCIE))
-endif
-
-PLAT_INCLUDES	+=	-Iplat/arm/fvp/include/
+PLAT_INCLUDES	+=	-Iplat/arm/fvp/include/				\
+			-Iinclude/lib/pcie/
 
 PLAT_SOURCES	:=	drivers/arm/gic/arm_gic_v2v3.c			\
 			drivers/arm/gic/gic_v2.c			\
@@ -104,6 +100,7 @@
 			drivers/arm/timer/private_timer.c		\
 			drivers/arm/timer/system_timer.c		\
 			plat/arm/fvp/${ARCH}/plat_helpers.S		\
+			plat/arm/fvp/fvp_pcie.c				\
 			plat/arm/fvp/fvp_pwr_state.c			\
 			plat/arm/fvp/fvp_topology.c			\
 			plat/arm/fvp/fvp_mem_prot.c			\
diff --git a/plat/arm/neoverse_rd/common/include/nrd3/nrd_css_def3.h b/plat/arm/neoverse_rd/common/include/nrd3/nrd_css_def3.h
new file mode 100644
index 0000000..b9e3654
--- /dev/null
+++ b/plat/arm/neoverse_rd/common/include/nrd3/nrd_css_def3.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file contains the CSS specific definitions for the third generation of
+ * platforms.
+ */
+
+#ifndef NRD_CSS_DEF3_H
+#define NRD_CSS_DEF3_H
+
+/*******************************************************************************
+ * CSS memory map related defines
+ ******************************************************************************/
+
+/* Sub-system Peripherals */
+#define NRD_CSS_PERIPH0_BASE		UL(0x2A400000)
+#define NRD_CSS_PERIPH0_SIZE		UL(0x0DC00000)
+
+/* Peripherals and PCIe expansion area */
+#define NRD_CSS_PERIPH1_BASE		UL(0x60000000)
+#define NRD_CSS_PERIPH1_SIZE		UL(0x20000000)
+
+/* DRAM base address and size */
+#define NRD_CSS_DRAM1_BASE		UL(0x80000000)
+#define NRD_CSS_DRAM1_SIZE		UL(0x80000000)
+
+/* AP Non-Secure UART related constants */
+#define NRD_CSS_NSEC_UART_BASE		UL(0x2A400000)
+
+/* Base address of trusted watchdog (SP805) */
+#define NRD_CSS_TWDOG_BASE		UL(0x2A480000)
+
+/* Base address of non-trusted watchdog (SP805) */
+#define NRD_CSS_WDOG_BASE		UL(0x2A440000)
+
+/* Memory mapped Generic timer interfaces */
+#define NRD_CSS_NSEC_CNT_BASE1		UL(0x2A830000)
+
+#endif /* NRD_CSS_DEF3_H */
\ No newline at end of file
diff --git a/plat/arm/neoverse_rd/common/include/nrd3/nrd_css_fw_def3.h b/plat/arm/neoverse_rd/common/include/nrd3/nrd_css_fw_def3.h
new file mode 100644
index 0000000..245b3d7
--- /dev/null
+++ b/plat/arm/neoverse_rd/common/include/nrd3/nrd_css_fw_def3.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file contains the CSS-firmware specific definitions for the third
+ * generation of platforms.
+ */
+
+#ifndef NRD_CSS_FW_DEF3_H
+#define NRD_CSS_FW_DEF3_H
+
+#include "nrd_css_def3.h"
+
+/*******************************************************************************
+ * Console config
+ ******************************************************************************/
+
+#define NRD_CSS_NSEC_CLK_IN_HZ		UL(7372800)
+
+#endif /* NRD_CSS_FW_DEF3_H */
\ No newline at end of file
diff --git a/plat/arm/neoverse_rd/common/include/nrd3/nrd_plat_arm_def3.h b/plat/arm/neoverse_rd/common/include/nrd3/nrd_plat_arm_def3.h
new file mode 100644
index 0000000..20c748e
--- /dev/null
+++ b/plat/arm/neoverse_rd/common/include/nrd3/nrd_plat_arm_def3.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file is limited to include the platform port definitions for the
+ * third generation of platforms.
+ */
+
+#ifndef NRD_PLAT_ARM_DEF3_H
+#define NRD_PLAT_ARM_DEF3_H
+
+#ifndef __ASSEMBLER__
+#include <lib/mmio.h>
+#endif /* __ASSEMBLER__ */
+
+#include <lib/utils_def.h>
+#include "nrd_css_fw_def3.h"
+#include "nrd_ros_def3.h"
+
+/* Platform binary types for linking */
+#define PLATFORM_LINKER_FORMAT		"elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH		aarch64
+
+/*******************************************************************************
+ * Stack size
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#define PLATFORM_STACK_SIZE		U(0x1400) /* 5120 bytes */
+
+/* Size of coherent stacks */
+#define PCPU_DV_MEM_STACK_SIZE		U(0x600) /* 1536 bytes */
+
+/*******************************************************************************
+ * Core count
+ ******************************************************************************/
+
+#define PLATFORM_CORE_COUNT		(PLAT_ARM_CLUSTER_COUNT * \
+						NRD_MAX_CPUS_PER_CLUSTER)
+#define PLATFORM_NUM_AFFS		(PLAT_ARM_CLUSTER_COUNT + PLATFORM_CORE_COUNT)
+
+/*******************************************************************************
+ * Power related definitions
+ ******************************************************************************/
+
+#define PLATFORM_MAX_AFFLVL		MPIDR_AFFLVL1
+
+#define PLAT_MAX_PWR_LEVEL		PLATFORM_MAX_AFFLVL
+#define PLAT_MAX_PWR_STATES_PER_LVL	U(2)
+
+/* Local state bit width for each level in the state-ID field of power state */
+#define PLAT_LOCAL_PSTATE_WIDTH		U(4)
+
+/*******************************************************************************
+ * XLAT definitions
+ ******************************************************************************/
+
+/* Platform specific page table and MMU setup constants */
+#define MAX_XLAT_TABLES			U(7)
+#define MAX_MMAP_REGIONS		U(16)
+
+/*******************************************************************************
+ * I/O definitions
+ ******************************************************************************/
+
+/* I/O Storage NOR flash device */
+#define MAX_IO_DEVICES			U(1)
+#define MAX_IO_HANDLES			U(1)
+
+/*******************************************************************************
+ * Non-Secure Software Generated Interupts IDs
+ ******************************************************************************/
+
+#define IRQ_NS_SGI_0			U(0)
+#define IRQ_NS_SGI_7			U(7)
+
+/* Maximum SPI */
+#define PLAT_MAX_SPI_OFFSET_ID		U(256)
+
+/*******************************************************************************
+ * Timer config
+ ******************************************************************************/
+
+/* Per-CPU Hypervisor Timer Interrupt ID */
+#define IRQ_PCPU_HP_TIMER		U(26)
+
+/* Memory mapped Generic timer interfaces */
+#define SYS_CNT_BASE1			NRD_CSS_NSEC_CNT_BASE1
+
+/* AP_REFCLK Generic Timer, Non-secure. */
+#define IRQ_CNTPSIRQ1			U(109)
+
+/* Times(in ms) used by test code for completion of different events */
+#define PLAT_SUSPEND_ENTRY_TIME		U(15)
+#define PLAT_SUSPEND_ENTRY_EXIT_TIME	U(30)
+
+/*******************************************************************************
+ * Console config
+ ******************************************************************************/
+
+#define PLAT_ARM_UART_BASE		NRD_CSS_NSEC_UART_BASE
+#define PLAT_ARM_UART_CLK_IN_HZ		NRD_CSS_NSEC_CLK_IN_HZ
+
+/*******************************************************************************
+ * DRAM config
+ ******************************************************************************/
+
+/* TF-A reserves DRAM space 0xFF000000- 0xFFFFFFFF for TZC */
+#define DRAM_BASE			NRD_CSS_DRAM1_BASE
+#define DRAM_SIZE			(NRD_CSS_DRAM1_SIZE - 0x1000000)
+
+/*******************************************************************************
+ * Cache related config
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT		U(6)
+#define CACHE_WRITEBACK_GRANULE		(1U << CACHE_WRITEBACK_SHIFT)
+
+/*******************************************************************************
+ * Run-time address of the TFTF image.
+ * It has to match the location where the Trusted Firmware-A loads the BL33
+ * image.
+ ******************************************************************************/
+#define TFTF_BASE			UL(0xE0000000)
+
+/*******************************************************************************
+ * TFTF NVM configs
+ ******************************************************************************/
+
+#define TFTF_NVM_OFFSET			U(0x0)
+#define TFTF_NVM_SIZE			UL(0x08000000)	/* 128 MB */
+
+/*******************************************************************************
+ * Watchdog related config
+ ******************************************************************************/
+
+/* Base address of trusted watchdog (SP805) */
+#define SP805_TWDOG_BASE		NRD_CSS_TWDOG_BASE
+
+/* Base address of non-trusted watchdog (SP805) */
+#define SP805_WDOG_BASE			NRD_CSS_WDOG_BASE
+
+/* Trusted watchdog (SP805) Interrupt ID */
+#define IRQ_TWDOG_INTID			U(107)
+
+/*******************************************************************************
+ * Flash related config
+ ******************************************************************************/
+
+/* Base address and size of external NVM flash */
+#define FLASH_BASE			NRD_ROS_FLASH_BASE
+#define FLASH_SIZE			NRD_ROS_FLASH_SIZE
+#define NOR_FLASH_BLOCK_SIZE		UL(0x40000)     /* 256KB */
+
+#endif /* NRD_PLAT_ARM_DEF3_H */
\ No newline at end of file
diff --git a/plat/arm/neoverse_rd/common/include/nrd3/nrd_ros_def3.h b/plat/arm/neoverse_rd/common/include/nrd3/nrd_ros_def3.h
new file mode 100644
index 0000000..2822ed9
--- /dev/null
+++ b/plat/arm/neoverse_rd/common/include/nrd3/nrd_ros_def3.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file contains the RoS specific definitions for the third generation of
+ * platforms.
+ */
+
+#ifndef NRD_ROS_DEF3_H
+#define NRD_ROS_DEF3_H
+
+/*******************************************************************************
+ * ROS configs
+ ******************************************************************************/
+
+/* Base address and size of external NVM flash */
+#define NRD_ROS_FLASH_BASE			UL(0x08000000)  /* 128MB */
+#define NRD_ROS_FLASH_SIZE			UL(0x04000000)  /* 64MB */
+
+#endif /* NRD_ROS_DEF3_H */
\ No newline at end of file
diff --git a/plat/arm/neoverse_rd/platform/rdv3/include/platform_def.h b/plat/arm/neoverse_rd/platform/rdv3/include/platform_def.h
new file mode 100644
index 0000000..f3ae5ef
--- /dev/null
+++ b/plat/arm/neoverse_rd/platform/rdv3/include/platform_def.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <nrd3/nrd_plat_arm_def3.h>
+
+#define PLAT_ARM_CLUSTER_COUNT		U(16)
+#define NRD_MAX_CPUS_PER_CLUSTER	U(1)
+#define NRD_MAX_PE_PER_CPU		U(1)
+
+/* GIC-600 & interrupt handling related constants */
+#define PLAT_ARM_GICD_BASE		UL(0x30000000)
+#define PLAT_ARM_GICR_BASE		UL(0x301C0000)
+#define PLAT_ARM_GICC_BASE		UL(0x2C000000)
+
+/* Platform specific page table and MMU setup constants */
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 46)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 46)
+
+#endif /* PLATFORM_DEF_H */
\ No newline at end of file
diff --git a/plat/arm/neoverse_rd/platform/rdv3/platform.mk b/plat/arm/neoverse_rd/platform/rdv3/platform.mk
new file mode 100644
index 0000000..3fd2cd2
--- /dev/null
+++ b/plat/arm/neoverse_rd/platform/rdv3/platform.mk
@@ -0,0 +1,21 @@
+#
+# Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include plat/arm/neoverse_rd/common/nrd_common.mk
+
+PLAT_INCLUDES		+=	-Iplat/arm/neoverse_rd/platform/rdv3/include/
+
+PLAT_SOURCES		+=	plat/arm/neoverse_rd/platform/rdv3/topology.c
+
+PLAT_TESTS_SKIP_LIST	:=	plat/arm/neoverse_rd/platform/rdv3/tests_to_skip.txt
+
+RD_V3_VARIANTS		:=	0
+
+ifneq ($(NRD_PLATFORM_VARIANT), \
+  $(filter $(NRD_PLATFORM_VARIANT),$(RD_V3_VARIANTS)))
+  $(error "NRD_PLATFORM_VARIANT for RD-V3 should be 0, currently \
+    set to ${NRD_PLATFORM_VARIANT}.")
+endif
\ No newline at end of file
diff --git a/plat/arm/neoverse_rd/platform/rdv3/tests_to_skip.txt b/plat/arm/neoverse_rd/platform/rdv3/tests_to_skip.txt
new file mode 100644
index 0000000..d5904e8
--- /dev/null
+++ b/plat/arm/neoverse_rd/platform/rdv3/tests_to_skip.txt
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# OS-initiated mode is not supported on RD-V3
+PSCI CPU Suspend in OSI mode
+
+# System suspend is not supported as there are no wakeup sources in RD-V3 FVP
+PSCI STAT/Stats test cases after system suspend
+PSCI System Suspend Validation
+
+# The following test cases result in unhandled exception at EL3
+CPU extensions/Use trace buffer control Registers
+CPU extensions/Use trace filter control Registers
+CPU extensions/Use branch record buffer control registers
+
+Framework Validation
\ No newline at end of file
diff --git a/plat/arm/neoverse_rd/platform/rdv3/topology.c b/plat/arm/neoverse_rd/platform/rdv3/topology.c
new file mode 100644
index 0000000..07e2a57
--- /dev/null
+++ b/plat/arm/neoverse_rd/platform/rdv3/topology.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <plat_topology.h>
+#include <tftf_lib.h>
+
+static const struct {
+	unsigned int cluster_id;
+	unsigned int cpu_id;
+} plat_cores[] = {
+	/* Cluster0: 1 core */
+	{ 0, 0 },
+	/* Cluster1: 1 core */
+	{ 1, 0 },
+	/* Cluster2: 1 core */
+	{ 2, 0 },
+	/* Cluster3: 1 core */
+	{ 3, 0 },
+	/* Cluster4: 1 core */
+	{ 4, 0 },
+	/* Cluster5: 1 core */
+	{ 5, 0 },
+	/* Cluster6: 1 core */
+	{ 6, 0 },
+	/* Cluster7: 1 core */
+	{ 7, 0 },
+	/* Cluster8: 1 core */
+	{ 8, 0 },
+	/* Cluster9: 1 core */
+	{ 9, 0 },
+	/* Cluster10: 1 core */
+	{ 10, 0 },
+	/* Cluster11: 1 core */
+	{ 11, 0 },
+	/* Cluster12: 1 core */
+	{ 12, 0 },
+	/* Cluster13: 1 core */
+	{ 13, 0 },
+	/* Cluster14: 1 core */
+	{ 14, 0 },
+	/* Cluster15: 1 core */
+	{ 15, 0 },
+};
+
+/*
+ * The power domain tree descriptor. The cluster power domains are
+ * arranged so that when the PSCI generic code creates the power domain tree,
+ * the indices of the CPU power domain nodes it allocates match the linear
+ * indices returned by plat_core_pos_by_mpidr().
+ */
+const unsigned char plat_pd_tree_desc[] = {
+	/* Number of root nodes */
+	PLAT_ARM_CLUSTER_COUNT,
+	/* Number of children for the 1st node */
+	NRD_MAX_CPUS_PER_CLUSTER,
+	/* Number of children for the 2nd node */
+	NRD_MAX_CPUS_PER_CLUSTER,
+	/* Number of children for the 3rd node */
+	NRD_MAX_CPUS_PER_CLUSTER,
+	/* Number of children for the 4th node */
+	NRD_MAX_CPUS_PER_CLUSTER,
+	/* Number of children for the 5th node */
+	NRD_MAX_CPUS_PER_CLUSTER,
+	/* Number of children for the 6th node */
+	NRD_MAX_CPUS_PER_CLUSTER,
+	/* Number of children for the 7th node */
+	NRD_MAX_CPUS_PER_CLUSTER,
+	/* Number of children for the 8th node */
+	NRD_MAX_CPUS_PER_CLUSTER,
+	/* Number of children for the 9th node */
+	NRD_MAX_CPUS_PER_CLUSTER,
+	/* Number of children for the 10th node */
+	NRD_MAX_CPUS_PER_CLUSTER,
+	/* Number of children for the 11th node */
+	NRD_MAX_CPUS_PER_CLUSTER,
+	/* Number of children for the 12th node */
+	NRD_MAX_CPUS_PER_CLUSTER,
+	/* Number of children for the 13th node */
+	NRD_MAX_CPUS_PER_CLUSTER,
+	/* Number of children for the 14th node */
+	NRD_MAX_CPUS_PER_CLUSTER,
+	/* Number of children for the 15th node */
+	NRD_MAX_CPUS_PER_CLUSTER,
+	/* Number of children for the 16th node */
+	NRD_MAX_CPUS_PER_CLUSTER
+};
+
+const unsigned char *tftf_plat_get_pwr_domain_tree_desc(void)
+{
+	return plat_pd_tree_desc;
+}
+
+uint64_t tftf_plat_get_mpidr(unsigned int core_pos)
+{
+	unsigned int mpid;
+
+	assert(core_pos < PLATFORM_CORE_COUNT);
+
+	mpid = make_mpid(plat_cores[core_pos].cluster_id,
+				plat_cores[core_pos].cpu_id);
+
+	return (uint64_t)mpid;
+}
\ No newline at end of file
diff --git a/plat/common/plat_common.c b/plat/common/plat_common.c
index c43ae12..a4195c3 100644
--- a/plat/common/plat_common.c
+++ b/plat/common/plat_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -24,6 +24,7 @@
 #pragma weak tftf_plat_enable_mmu
 #pragma weak tftf_plat_reset
 #pragma weak plat_get_prot_regions
+#pragma weak plat_pcie_get_info_table
 
 #if IMAGE_TFTF
 
@@ -148,3 +149,8 @@
 	*nelem = 0;
 	return NULL;
 }
+
+const struct pcie_info_table *plat_pcie_get_info_table(void)
+{
+	return NULL;
+}
diff --git a/plat/xilinx/versal/tests_to_skip.txt b/plat/xilinx/versal/tests_to_skip.txt
index 87b9e41..997bc61 100644
--- a/plat/xilinx/versal/tests_to_skip.txt
+++ b/plat/xilinx/versal/tests_to_skip.txt
@@ -30,6 +30,10 @@
 PSCI System Suspend Validation/system suspend from all cores
 PSCI System Suspend Validation/Validate suspend to RAM functionality
 
+#Query runtime services
+Query runtime services/Query Vendor-Specific Service
+Query runtime services/Probe PMF Version
+
 #TESTS: el3-power-state
 EL3 power state parser validation/Create all power states and validate EL3 power state parsing
 EL3 power state parser validation/Create invalid local power state at all levels and validate EL3 power state parsing
diff --git a/plat/xilinx/versal_net/tests_to_skip.txt b/plat/xilinx/versal_net/tests_to_skip.txt
index 80e7cb2..f9668ee 100644
--- a/plat/xilinx/versal_net/tests_to_skip.txt
+++ b/plat/xilinx/versal_net/tests_to_skip.txt
@@ -58,6 +58,10 @@
 PSCI System Suspend Validation/system suspend from all cores
 PSCI System Suspend Validation/Validate suspend to RAM functionality
 
+#Query runtime services
+Query runtime services/Query Vendor-Specific Service
+Query runtime services/Probe PMF Version
+
 #TESTS: el3-power-state
 EL3 power state parser validation
 
diff --git a/plat/xilinx/zynqmp/tests_to_skip.txt b/plat/xilinx/zynqmp/tests_to_skip.txt
index 271fdc8..f72de18 100644
--- a/plat/xilinx/zynqmp/tests_to_skip.txt
+++ b/plat/xilinx/zynqmp/tests_to_skip.txt
@@ -49,6 +49,10 @@
 PSCI STAT/Stats test cases for CPU OFF
 PSCI STAT/Stats test cases after system suspend
 
+#Query runtime services
+Query runtime services/Query Vendor-Specific Service
+Query runtime services/Probe PMF Version
+
 #TESTS: el3-power-state
 EL3 power state parser validation
 
diff --git a/realm/aarch64/realm_exceptions.S b/realm/aarch64/realm_exceptions.S
index 210dd3e..c1d1c0c 100644
--- a/realm/aarch64/realm_exceptions.S
+++ b/realm/aarch64/realm_exceptions.S
@@ -43,8 +43,9 @@
 	b	interrupt_vector_entry
 end_vector_entry fiq_spx
 
-unhandled_exception serr_spx
-
+vector_entry serr_spx
+	b	serr_exception_vector_entry
+end_vector_entry serr_spx
 	/*
 	 * Lower EL using AArch64 : 0x400 - 0x600.
 	 */
@@ -116,6 +117,22 @@
 	eret
 endfunc sync_exception_vector_entry
 
+func serr_exception_vector_entry
+	sub	sp, sp, #0x100
+	save_gp_regs
+	mov	x19, sp
+	bl	tftf_serror_handler
+	cbnz	x0, 0f
+	mov	x0, x19
+	/* Save original stack pointer value on the stack */
+	add	x1, x0, #0x100
+	str	x1, [x0, #0xf8]
+	b	realm_print_exception
+0:	restore_gp_regs
+	add	sp, sp, #0x100
+	eret
+endfunc serr_exception_vector_entry
+
 func interrupt_vector_entry
 	sub	sp, sp, #0x100
 	save_gp_regs
diff --git a/realm/include/realm_helpers.h b/realm/include/realm_helpers.h
new file mode 100644
index 0000000..a9b2f7c
--- /dev/null
+++ b/realm/include/realm_helpers.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef REALM_HELPERS_H
+#define REALM_HELPERS_H
+
+/* Generate 64-bit random number */
+unsigned long long realm_rand64(void);
+/*
+ * Function to enter Aux Plane from Primary Plane
+ * arg1 == plane index
+ * arg2 == permission index to be used by plane
+ * arg3 == base entrypoint
+ * arg4 == entry flags
+ * aarg5 == run object, needs to be PAGE aligned
+ */
+bool realm_plane_enter(u_register_t plane_index, u_register_t perm_index,
+		u_register_t base, u_register_t flags, rsi_plane_run *run);
+
+/* Function for initializing planes, called at Boot */
+void realm_plane_init(void);
+
+#endif /* REALM_HELPERS_H */
+
diff --git a/realm/include/realm_rsi.h b/realm/include/realm_rsi.h
index 92a078b..33e8fcf 100644
--- a/realm/include/realm_rsi.h
+++ b/realm/include/realm_rsi.h
@@ -8,6 +8,7 @@
 #ifndef REALM_RSI_H
 #define REALM_RSI_H
 
+#include <arch.h>
 #include <stdint.h>
 #include <host_shared_data.h>
 #include <tftf_lib.h>
@@ -71,7 +72,9 @@
 	/* IPA width in bits */
 	SET_MEMBER(unsigned long ipa_width, 0, 8);	/* Offset 0 */
 	/* Hash algorithm */
-	SET_MEMBER(unsigned long algorithm, 8, 0x200);	/* Offset 8 */
+	SET_MEMBER(unsigned long algorithm, 8, 0x10);	/* Offset 8 */
+	/* Number of auxiliary Planes */
+	SET_MEMBER(unsigned long num_aux_planes, 0x10, 0x200); /* Offset 0x10 */
 	/* Realm Personalization Value */
 	SET_MEMBER(unsigned char rpv[RSI_RPV_SIZE], 0x200, 0x1000); /* Offset 0x200 */
 };
@@ -127,6 +130,21 @@
  */
 #define RSI_IPA_STATE_GET	SMC_RSI_FID(8U)
 
+/*
+ * ret0 == Status / error
+ * ret1 == Token maximum length
+ */
+#define RSI_ATTEST_TOKEN_INIT	SMC_RSI_FID(4U)
+
+/*
+ * arg0 == Base of buffer to write the token to
+ * arg1 == Offset within the buffer
+ * arg2 == Size of the buffer
+ * ret0 == Status / error
+ * ret1 == Size of received token hunk
+ */
+#define RSI_ATTEST_TOKEN_CONTINUE	SMC_RSI_FID(5U)
+
 typedef enum {
 	RSI_EMPTY = 0U,
 	RSI_RAM,
@@ -142,7 +160,151 @@
 #define RSI_NO_CHANGE_DESTROYED	0UL
 #define RSI_CHANGE_DESTROYED	1UL
 
-/* Request RIPAS of a target IPA range to be changed to a specified value */
+/*
+ * arg1 == plane index
+ * arg2 == perm index
+ *
+ * ret0 == status
+ * ret1 == perm value
+ */
+#define RSI_MEM_GET_PERM_VALUE	SMC_RSI_FID(0x10U)
+
+/*
+ * arg1 == base adr
+ * arg2 == top adr
+ * arg3 == perm index
+ * arg4 == cookie
+ *
+ * ret0 == status
+ * ret1 == new_base
+ * ret2 == response
+ * ret3 == new_cookie
+ */
+#define RSI_MEM_SET_PERM_INDEX	SMC_RSI_FID(0x11U)
+
+/*
+ * arg1 == plane index
+ * arg2 == perm index
+ *
+ * ret0 == status
+ */
+#define RSI_MEM_SET_PERM_VALUE	SMC_RSI_FID(0x12U)
+
+#define RSI_PLANE_NR_GPRS	31U
+#define RSI_PLANE_GIC_NUM_LRS	16U
+
+/*
+ * Flags provided by the Primary Plane to the secondary ones upon
+ * plane entry.
+ */
+#define RSI_PLANE_ENTRY_FLAG_TRAP_WFI	U(1UL << 0)
+#define RSI_PLANE_ENTRY_FLAG_TRAP_WFE	U(1UL << 1)
+#define RSI_PLANE_ENTRY_FLAG_TRAP_HC	U(1UL << 2)
+
+/* Data structure used to pass values from P0 to the RMM on Plane entry */
+struct rsi_plane_entry {
+	/* Flags */
+	SET_MEMBER(u_register_t flags, 0, 0x8);	/* Offset 0 */
+	/* PC */
+	SET_MEMBER(u_register_t pc, 0x8, 0x100);	/* Offset 0x8 */
+	/* General-purpose registers */
+	SET_MEMBER(u_register_t gprs[RSI_PLANE_NR_GPRS], 0x100, 0x200);	/* 0x100 */
+	/* EL1 system registers */
+	SET_MEMBER(struct {
+		/* GICv3 Hypervisor Control Register */
+		u_register_t gicv3_hcr;                         /* 0x200 */
+		/* GICv3 List Registers */
+		u_register_t gicv3_lrs[RSI_PLANE_GIC_NUM_LRS];        /* 0x208 */
+	}, 0x200, 0x800);
+};
+
+/* Data structure used to pass values from the RMM to P0 on Plane exit */
+struct rsi_plane_exit {
+	/* Exit reason */
+	SET_MEMBER(u_register_t exit_reason, 0, 0x100);/* Offset 0 */
+	SET_MEMBER(struct {
+		/* Exception Link Register */
+		u_register_t elr;				/* 0x100 */
+		/* Exception Syndrome Register */
+		u_register_t esr;				/* 0x108 */
+		/* Fault Address Register */
+		u_register_t far;				/* 0x108 */
+		/* Hypervisor IPA Fault Address register */
+		u_register_t hpfar;				/* 0x110 */
+	}, 0x100, 0x200);
+	/* General-purpose registers */
+	SET_MEMBER(u_register_t gprs[RSI_PLANE_NR_GPRS], 0x200, 0x300); /* 0x200 */
+	SET_MEMBER(struct {
+		/* GICv3 Hypervisor Control Register */
+		u_register_t gicv3_hcr;				/* 0x300 */
+		/* GICv3 List Registers */
+		u_register_t gicv3_lrs[RSI_PLANE_GIC_NUM_LRS];	/* 0x308 */
+		/* GICv3 Maintenance Interrupt State Register */
+		u_register_t gicv3_misr;			/* 0x388 */
+		/* GICv3 Virtual Machine Control Register */
+		u_register_t gicv3_vmcr;			/* 0x390 */
+	}, 0x300, 0x600);
+};
+
+typedef struct {
+	/* Entry information */
+	SET_MEMBER(struct rsi_plane_entry enter, 0, 0x800); /* Offset 0 */
+	/* Exit information */
+	SET_MEMBER(struct rsi_plane_exit exit, 0x800, 0x1000);/* 0x800 */
+} rsi_plane_run;
+
+/*
+ * arg1 == plane index
+ * arg2 == run pointer
+ *
+ * ret0 == status
+ */
+#define RSI_PLANE_ENTER		SMC_RSI_FID(0x13U)
+
+/*
+ * arg1 == plane index
+ * arg2 == register encoding
+ *
+ * ret0 == status
+ * ret1 = register value
+ */
+#define RSI_PLANE_REG_READ	SMC_RSI_FID(0x1EU)
+
+/*
+ * arg1 == plane index
+ * arg2 == register encoding
+ * arg3 == register value
+ *
+ * ret0 == status
+ */
+#define RSI_PLANE_REG_WRITE	SMC_RSI_FID(0x1FU)
+
+/*
+ * Function to set overlay permission value for a specified
+ * (plane index, overlay permission index) tuple
+ */
+u_register_t rsi_mem_set_perm_value(u_register_t plane_index,
+	u_register_t perm_index,
+	u_register_t perm);
+
+/*
+ * Function to Get overlay permission value for a specified
+ * (plane index, overlay permission index) tuple
+ */
+u_register_t rsi_mem_get_perm_value(u_register_t plane_index,
+	u_register_t perm_index,
+	u_register_t *perm);
+
+/* Function to Set overlay permission index for a specified IPA range See RSI_MEM_SET_PERM_INDEX */
+u_register_t rsi_mem_set_perm_index(u_register_t base,
+	u_register_t top,
+	u_register_t perm_index,
+	u_register_t cookie,
+	u_register_t *new_base,
+	u_register_t *response,
+	u_register_t *new_cookie);
+
+/* Request RIPAS of a target IPA range to be changed to a specified value. */
 u_register_t rsi_ipa_state_set(u_register_t base,
 				u_register_t top,
 				rsi_ripas_type ripas,
@@ -162,7 +324,30 @@
 /* This function will call the Host to request IPA of the NS shared buffer */
 u_register_t rsi_get_ns_buffer(void);
 
+/* This function will initialize the attestation context */
+u_register_t rsi_attest_token_init(u_register_t challenge_0,
+				   u_register_t challenge_1,
+				   u_register_t challenge_2,
+				   u_register_t challenge_3,
+				   u_register_t challenge_4,
+				   u_register_t challenge_5,
+				   u_register_t challenge_6,
+				   u_register_t challenge_7,
+				   u_register_t *out_token_upper_bound);
+
+/* This function will retrieve the (or part of) attestation token */
+u_register_t rsi_attest_token_continue(u_register_t buffer_addr,
+					u_register_t offset,
+					u_register_t buffer_size,
+					u_register_t *bytes_copied);
+
 /* This function call Host and request to exit Realm with proper exit code */
 void rsi_exit_to_host(enum host_call_cmd exit_code);
 
+/* Function to get Realm configuration. See RSI_REALM_CONFIG */
+u_register_t rsi_realm_config(struct rsi_realm_config *s);
+
+/* Function to enter aux plane. See RSI_PLANE_ENTER */
+u_register_t rsi_plane_enter(u_register_t plane_index, u_register_t run);
+
 #endif /* REALM_RSI_H */
diff --git a/realm/include/realm_tests.h b/realm/include/realm_tests.h
index b58949b..2c1d3a1 100644
--- a/realm/include/realm_tests.h
+++ b/realm/include/realm_tests.h
@@ -27,6 +27,9 @@
 bool test_realm_multiple_rec_multiple_cpu_cmd(void);
 bool test_realm_sme_read_id_registers(void);
 bool test_realm_sme_undef_abort(void);
+bool test_realm_sctlr2_ease(void);
+bool test_realm_attestation(void);
+bool test_realm_attestation_fault(void);
 
 #endif /* REALM_TESTS_H */
 
diff --git a/realm/realm.mk b/realm/realm.mk
index 305c007..f59387c 100644
--- a/realm/realm.mk
+++ b/realm/realm.mk
@@ -26,12 +26,15 @@
 	$(addprefix realm/,						\
 	aarch64/realm_entrypoint.S					\
 	aarch64/realm_exceptions.S					\
+	realm_attestation.c						\
 	realm_exception_report.c					\
 	realm_debug.c							\
+	realm_helpers.c							\
 	realm_interrupt.c						\
 	realm_multiple_rec.c						\
 	realm_pauth.c							\
 	realm_payload_main.c						\
+	realm_plane.c							\
 	realm_pmuv3.c							\
 	realm_psci.c							\
 	realm_rsi.c							\
@@ -43,6 +46,7 @@
 	lib/${ARCH}/misc_helpers.S					\
 	lib/smc/${ARCH}/asm_smc.S					\
 	lib/smc/${ARCH}/smc.c						\
+	lib/exceptions/${ARCH}/serror.c					\
 	lib/exceptions/${ARCH}/sync.c					\
 	lib/locks/${ARCH}/spinlock.S					\
 	lib/delay/delay.c						\
diff --git a/realm/realm_attestation.c b/realm/realm_attestation.c
new file mode 100644
index 0000000..e42484e
--- /dev/null
+++ b/realm/realm_attestation.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <assert.h>
+#include <stdio.h>
+
+#include <realm_rsi.h>
+
+#include <arch_features.h>
+#include <debug.h>
+#include <realm_def.h>
+#include <sync.h>
+#include <realm_helpers.h>
+
+#define CHALLENGE_SIZE	8
+
+static unsigned char attest_token_buffer[REALM_TOKEN_BUF_SIZE]
+	__aligned(GRANULE_SIZE);
+static uint64_t attest_token_offset;
+
+bool test_realm_attestation(void)
+{
+	u_register_t rsi_ret;
+	u_register_t bytes_copied;
+	u_register_t token_upper_bound;
+	u_register_t challenge[CHALLENGE_SIZE];
+
+	for (unsigned int i = 0U; i < CHALLENGE_SIZE; i++) {
+		challenge[i] = realm_rand64();
+	}
+
+	rsi_ret = rsi_attest_token_init(challenge[0],
+					challenge[1],
+					challenge[2],
+					challenge[3],
+					challenge[4],
+					challenge[5],
+					challenge[6],
+					challenge[7],
+					&token_upper_bound);
+
+	if (rsi_ret != RSI_SUCCESS) {
+		realm_printf("RSI_ATTEST_TOKEN_INIT"
+			     " returned with code %lu\n", rsi_ret);
+		return false;
+	}
+
+	if (token_upper_bound > REALM_TOKEN_BUF_SIZE) {
+		realm_printf("Attestation token buffer is not large enough"
+				" to hold the token.\n");
+		return false;
+	}
+
+	do {
+		rsi_ret = rsi_attest_token_continue(
+					(u_register_t)attest_token_buffer,
+					attest_token_offset,
+					REALM_TOKEN_BUF_SIZE,
+					&bytes_copied);
+
+		if ((rsi_ret != RSI_SUCCESS) && (rsi_ret != RSI_INCOMPLETE)) {
+			realm_printf("RSI_ATTEST_TOKEN_CONTINUE"
+				     " returned with code %lu\n", rsi_ret);
+			return false;
+		}
+
+		attest_token_offset += bytes_copied;
+
+	} while (rsi_ret != RSI_SUCCESS);
+
+	return true;
+}
+
+bool test_realm_attestation_fault(void)
+{
+	u_register_t rsi_ret;
+	u_register_t bytes_copied;
+
+	/*
+	 * This RSI call will fail as RSI_ATTEST_TOKEN_INIT has to be invoked
+	 * before calling RSI_ATTEST_TOKEN_CONTINUE.
+	 */
+	rsi_ret = rsi_attest_token_continue(
+				(u_register_t)attest_token_buffer,
+				attest_token_offset,
+				REALM_TOKEN_BUF_SIZE,
+				&bytes_copied);
+
+	if ((rsi_ret == RSI_SUCCESS) || (rsi_ret == RSI_INCOMPLETE)) {
+		return false;
+	}
+
+	return true;
+}
diff --git a/realm/realm_helpers.c b/realm/realm_helpers.c
new file mode 100644
index 0000000..6a3c57d
--- /dev/null
+++ b/realm/realm_helpers.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdlib.h>
+
+/* Generate 64-bit random number */
+unsigned long long realm_rand64(void)
+{
+	return ((unsigned long long)rand() << 32) | rand();
+}
+
diff --git a/realm/realm_payload_main.c b/realm/realm_payload_main.c
index 47f9b9f..3339b9a 100644
--- a/realm/realm_payload_main.c
+++ b/realm/realm_payload_main.c
@@ -16,11 +16,13 @@
 #include "realm_def.h"
 #include <realm_rsi.h>
 #include <realm_tests.h>
+#include <serror.h>
 #include <sync.h>
 #include <tftf_lib.h>
 
 static fpu_state_t rl_fpu_state_write;
 static fpu_state_t rl_fpu_state_read;
+
 /*
  * This function reads sleep time in ms from shared buffer and spins PE
  * in a loop for that time period.
@@ -176,7 +178,7 @@
 	/* Causes data abort */
 	realm_printf("Generate Data Abort\n");
 	*((volatile uint64_t *)base);
-	/* Should not return */
+
 	return false;
 }
 
@@ -200,6 +202,53 @@
 	return false;
 }
 
+static bool realm_serror_handler_doublefault(bool *incr_elr_elx)
+{
+	*incr_elr_elx = false;
+
+	if ((read_sctlr2_el1() & SCTLR2_EASE_BIT) != 0UL) {
+		/* The serror exception should have been routed here */
+		*incr_elr_elx = true;
+
+		return true;
+	}
+
+	rsi_exit_to_host(HOST_CALL_EXIT_FAILED_CMD);
+
+	/* Should have never get here */
+	return false;
+}
+
+static bool realm_sync_handler_doublefault(void)
+{
+	if ((read_sctlr2_el1() & SCTLR2_EASE_BIT) == 0UL) {
+		/* The sync exception should have been routed here */
+		return true;
+	}
+
+	rsi_exit_to_host(HOST_CALL_EXIT_FAILED_CMD);
+
+	/* Should have never get here */
+	return false;
+}
+
+static void test_realm_feat_doublefault2(void)
+{
+	u_register_t ease_bit = realm_shared_data_get_my_host_val(HOST_ARG2_INDEX);
+
+	unregister_custom_sync_exception_handler();
+	register_custom_sync_exception_handler(realm_sync_handler_doublefault);
+	register_custom_serror_handler(realm_serror_handler_doublefault);
+
+	if (ease_bit != 0UL) {
+		write_sctlr2_el1(read_sctlr2_el1() | SCTLR2_EASE_BIT);
+	} else {
+		write_sctlr2_el1(read_sctlr2_el1() & ~SCTLR2_EASE_BIT);
+	}
+
+	(void)test_realm_data_access_cmd();
+}
+
 /*
  * 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,
@@ -213,7 +262,12 @@
 	bool test_succeed = false;
 
 	register_custom_sync_exception_handler(realm_exception_handler);
+
+	/* No serror handler registered by default */
+	unregister_custom_serror_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();
 
@@ -232,6 +286,10 @@
 		case REALM_MULTIPLE_REC_MULTIPLE_CPU_CMD:
 			test_succeed = test_realm_multiple_rec_multiple_cpu_cmd();
 			break;
+		case REALM_FEAT_DOUBLEFAULT2_TEST:
+			test_realm_feat_doublefault2();
+			test_succeed = true;
+			break;
 		case REALM_INSTR_FETCH_CMD:
 			test_succeed = test_realm_instr_fetch_cmd();
 			break;
@@ -310,6 +368,12 @@
 		case REALM_SME_UNDEF_ABORT:
 			test_succeed = test_realm_sme_undef_abort();
 			break;
+		case REALM_ATTESTATION:
+			test_succeed = test_realm_attestation();
+			break;
+		case REALM_ATTESTATION_FAULT:
+			test_succeed = test_realm_attestation_fault();
+			break;
 		default:
 			realm_printf("%s() invalid cmd %u\n", __func__, cmd);
 			break;
diff --git a/realm/realm_plane.c b/realm/realm_plane.c
new file mode 100644
index 0000000..ef1e0ab
--- /dev/null
+++ b/realm/realm_plane.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2022-2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <stdio.h>
+#include <arch.h>
+#include <arch_features.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <host_realm_helper.h>
+#include <realm_rsi.h>
+#include <sync.h>
+
+bool is_plane0;
+
+void realm_plane_init(void)
+{
+	u_register_t ret;
+
+	ret = rsi_get_version(RSI_ABI_VERSION_VAL);
+	if (ret == RSI_ERROR_STATE) {
+		is_plane0 = false;
+	} else {
+		is_plane0 = true;
+	}
+}
+
+static void restore_plane_context(rsi_plane_run *run)
+{
+	for (unsigned int i = 0U; i < RSI_PLANE_NR_GPRS; i++) {
+		run->enter.gprs[i] = run->exit.gprs[i];
+	}
+
+	run->enter.pc = run->exit.elr;
+}
+
+/* return true to re-enter PlaneN, false to exit to P0 */
+static bool handle_plane_exit(u_register_t plane_index,
+		u_register_t perm_index,
+		rsi_plane_run *run)
+{
+	u_register_t ec = EC_BITS(run->exit.esr);
+
+	/* Disallow SMC from Plane N */
+	if (ec == EC_AARCH64_SMC) {
+		restore_plane_context(run);
+		run->enter.gprs[0] = RSI_ERROR_STATE;
+		return true;
+	}
+	return false;
+}
+
+static bool plane_common_init(u_register_t plane_index,
+		u_register_t perm_index,
+		u_register_t base,
+		rsi_plane_run *run)
+{
+	u_register_t ret;
+
+	memset(run, 0, sizeof(rsi_plane_run));
+	run->enter.pc = base;
+
+	/* Perm init */
+	ret = rsi_mem_set_perm_value(plane_index, perm_index, PERM_LABEL_RW_upX);
+	if (ret != RSI_SUCCESS) {
+		ERROR("rsi_mem_set_perm_value failed %u\n", plane_index);
+		return false;
+	}
+	return true;
+}
+
+bool realm_plane_enter(u_register_t plane_index,
+		u_register_t perm_index,
+		u_register_t base,
+		u_register_t flags,
+		rsi_plane_run *run)
+{
+	u_register_t ret;
+	bool ret1;
+
+	ret1 = plane_common_init(plane_index, perm_index, base, run);
+	if (!ret1) {
+		return ret1;
+	}
+
+	run->enter.flags = flags;
+
+	while (ret1) {
+		ret = rsi_plane_enter(plane_index, (u_register_t)run);
+		if (ret != RSI_SUCCESS) {
+			ERROR("Plane %u enter failed ret= 0x%lx\n", plane_index, ret);
+			return false;
+		}
+
+		VERBOSE("plane exit_reason=0x%lx esr=0x%lx hpfar=0x%lx far=0x%lx\n",
+				run->exit.exit_reason,
+				run->exit.esr,
+				run->exit.hpfar,
+				run->exit.far);
+
+		ret1 = handle_plane_exit(plane_index, perm_index, run);
+	}
+	return true;
+}
+
diff --git a/realm/realm_rsi.c b/realm/realm_rsi.c
index b2a49d4..1c6fc8e 100644
--- a/realm/realm_rsi.c
+++ b/realm/realm_rsi.c
@@ -22,6 +22,11 @@
 	if (res.ret0 == SMC_UNKNOWN) {
 		return SMC_UNKNOWN;
 	}
+
+	if (res.ret0 == RSI_ERROR_STATE) {
+		return RSI_ERROR_STATE;
+	}
+
 	/* Return lower version */
 	return res.ret1;
 }
@@ -87,3 +92,121 @@
 	}
 	return res.ret0;
 }
+
+/* This function will initialize the attestation context */
+u_register_t rsi_attest_token_init(u_register_t challenge_0,
+				   u_register_t challenge_1,
+				   u_register_t challenge_2,
+				   u_register_t challenge_3,
+				   u_register_t challenge_4,
+				   u_register_t challenge_5,
+				   u_register_t challenge_6,
+				   u_register_t challenge_7,
+				   u_register_t *out_token_upper_bound)
+{
+	smc_ret_values_ext res = {};
+
+	tftf_smc_no_retval_x8(&(smc_args_ext) {
+		RSI_ATTEST_TOKEN_INIT,
+		challenge_0,
+		challenge_1,
+		challenge_2,
+		challenge_3,
+		challenge_4,
+		challenge_5,
+		challenge_6,
+		challenge_7
+	},
+	&res);
+
+	if (res.ret0 == RSI_SUCCESS) {
+		*out_token_upper_bound = res.ret1;
+	}
+
+	return res.ret0;
+}
+
+/* This function will retrieve the (or part of) attestation token */
+u_register_t rsi_attest_token_continue(u_register_t buffer_addr,
+					u_register_t offset,
+					u_register_t buffer_size,
+					u_register_t *bytes_copied)
+{
+	smc_ret_values res = {};
+
+	res = tftf_smc(&(smc_args) {
+		RSI_ATTEST_TOKEN_CONTINUE,
+		buffer_addr,
+		offset,
+		buffer_size
+	});
+
+	if ((res.ret0 == RSI_SUCCESS) || (res.ret0 == RSI_INCOMPLETE)) {
+		*bytes_copied = res.ret1;
+	}
+	return res.ret0;
+}
+
+u_register_t rsi_realm_config(struct rsi_realm_config *s)
+{
+	smc_ret_values res = {};
+
+	res = tftf_smc(&(smc_args)
+			{RSI_REALM_CONFIG, (u_register_t)s});
+	return res.ret0;
+}
+
+u_register_t rsi_mem_get_perm_value(u_register_t plane_index,
+				    u_register_t perm_index,
+				    u_register_t *perm)
+{
+	smc_ret_values res = {};
+
+	res = tftf_smc(&(smc_args)
+			{RSI_MEM_GET_PERM_VALUE, plane_index, perm_index});
+	if (res.ret0 == RSI_SUCCESS) {
+		*perm = res.ret1;
+	}
+	return res.ret0;
+}
+
+u_register_t rsi_mem_set_perm_value(u_register_t plane_index,
+				    u_register_t perm_index,
+				    u_register_t perm)
+{
+	smc_ret_values res = {};
+
+	res = tftf_smc(&(smc_args)
+			{RSI_MEM_SET_PERM_VALUE, plane_index, perm_index, perm});
+	return res.ret0;
+}
+
+u_register_t rsi_mem_set_perm_index(u_register_t base,
+				    u_register_t top,
+				    u_register_t perm_index,
+				    u_register_t cookie,
+				    u_register_t *new_base,
+				    u_register_t *response,
+				    u_register_t *new_cookie)
+{
+	smc_ret_values res = {};
+
+	res = tftf_smc(&(smc_args)
+			{RSI_MEM_SET_PERM_INDEX, base, top, perm_index, cookie});
+	if (res.ret0 == RSI_SUCCESS) {
+		*new_base = res.ret1;
+		*response = res.ret2;
+		*new_cookie = res.ret3;
+	}
+	return res.ret0;
+}
+
+u_register_t rsi_plane_enter(u_register_t plane_index,
+			     u_register_t plane_run)
+{
+	smc_ret_values res = {};
+
+	res = tftf_smc(&(smc_args)
+			{RSI_PLANE_ENTER, plane_index, plane_run});
+	return res.ret0;
+}
diff --git a/spm/cactus/cactus_main.c b/spm/cactus/cactus_main.c
index b608d7b..c15ee4e 100644
--- a/spm/cactus/cactus_main.c
+++ b/spm/cactus/cactus_main.c
@@ -61,8 +61,9 @@
 	ffa_ret = ffa_msg_wait();
 
 	for (;;) {
-		VERBOSE("Woke up with func id: %s\n",
-			ffa_func_name(ffa_func_id(ffa_ret)));
+		VERBOSE("Woke up with func:%s  id: %x\n",
+			ffa_func_name(ffa_func_id(ffa_ret)),
+			ffa_func_id(ffa_ret));
 
 		if (ffa_func_id(ffa_ret) == FFA_ERROR) {
 			ERROR("Error: %s\n",
@@ -74,7 +75,7 @@
 		    ffa_func_id(ffa_ret) != FFA_MSG_SEND_DIRECT_REQ_SMC64 &&
 		    ffa_func_id(ffa_ret) != FFA_INTERRUPT &&
 		    ffa_func_id(ffa_ret) != FFA_RUN) {
-			ERROR("%s(%u) unknown func id %s\n", __func__, vm_id,
+			ERROR("%s(%x) unknown func id %s\n", __func__, vm_id,
 			      ffa_func_name(ffa_func_id(ffa_ret)));
 			break;
 		}
@@ -87,10 +88,15 @@
 			 * informational as we're running with virtual
 			 * interrupts unmasked and the interrupt is processed
 			 * by the interrupt handler.
-			 *
-			 * Received FFA_RUN in waiting state, the endpoint
-			 * simply returns by FFA_MSG_WAIT.
 			 */
+			if (ffa_func_id(ffa_ret) == FFA_RUN) {
+				/*
+				 * Received FFA_RUN in waiting state, the
+				 * endpoint simply returns by FFA_MSG_WAIT.
+				 */
+				VERBOSE("Nothing to do. Exit to NWd\n");
+			}
+
 			ffa_ret = ffa_msg_wait();
 			continue;
 		}
diff --git a/tftf/framework/framework.mk b/tftf/framework/framework.mk
index fc0ccbd..4e27995 100644
--- a/tftf/framework/framework.mk
+++ b/tftf/framework/framework.mk
@@ -92,7 +92,8 @@
 	lib/extensions/sme/aarch64/sme_helpers.S			\
 	lib/extensions/sme/aarch64/sme2_helpers.S			\
 	lib/extensions/sve/aarch64/sve.c				\
-	lib/extensions/sve/aarch64/sve_helpers.S
+	lib/extensions/sve/aarch64/sve_helpers.S			\
+	lib/extensions/sysreg128/aarch64/sysreg128_helpers.S
 endif
 
 ifeq (${ARCH},aarch64)
diff --git a/tftf/tests/doe_tests/doe_helpers.c b/tftf/tests/doe_tests/doe_helpers.c
index 28b6a86..75f63b6 100644
--- a/tftf/tests/doe_tests/doe_helpers.c
+++ b/tftf/tests/doe_tests/doe_helpers.c
@@ -13,14 +13,6 @@
 #include <pcie_doe.h>
 #include <spdm.h>
 
-#include <platform_pcie.h>
-
-void pcie_init(void)
-{
-	/* Create PCIe table and enumeration */
-	pcie_create_info_table();
-}
-
 /*
  * @brief  Returns the BDF Table pointer
  *
@@ -33,39 +25,6 @@
 	return pcie_get_bdf_table();
 }
 
-int find_doe_device(uint32_t *bdf_ptr, uint32_t *cap_base_ptr)
-{
-	pcie_device_bdf_table_t	*bdf_table_ptr = pcie_get_bdf_table();
-	uint32_t num_bdf = bdf_table_ptr->num_entries;
-
-	INFO("PCI BDF table entries: %u\n", num_bdf);
-
-	/* If no entries in BDF table return error */
-	if (num_bdf == 0) {
-		ERROR("No BDFs entries found\n");
-		return -ENODEV;
-	}
-
-	INFO("PCI BDF table 0x%lx\n", (uintptr_t)bdf_table_ptr);
-
-	while (num_bdf-- != 0) {
-		uint32_t bdf = bdf_table_ptr->device[num_bdf].bdf;
-		uint32_t status, doe_cap_base;
-
-		/* Check for DOE capability */
-		status = pcie_find_capability(bdf, PCIE_ECAP, DOE_CAP_ID, &doe_cap_base);
-		if (status == PCIE_SUCCESS) {
-			INFO("PCIe DOE capability: bdf 0x%x cap_base 0x%x\n", bdf, doe_cap_base);
-			*bdf_ptr = bdf;
-			*cap_base_ptr = doe_cap_base;
-			return 0;
-		}
-	}
-
-	ERROR("No PCIe DOE capability found\n");
-	return -ENODEV;
-}
-
 int get_spdm_version(uint32_t bdf, uint32_t doe_cap_base)
 {
 	uint32_t response[SPDM_GET_VERS_RESP_LEN], resp_len;
@@ -113,7 +72,7 @@
 			sizeof(ver_resp->version_number_entry_count));
 
 	while (entry_count-- != 0) {
-		spdm_version_number_t ver = *ver_ptr++;
+		spdm_version_number_t ver __unused = *ver_ptr++;
 
 		INFO("SPDM v%llu.%llu.%llu.%llu\n",
 			EXTRACT(SPDM_VER_MAJOR, ver),
@@ -128,19 +87,14 @@
 {
 	pcie_doe_disc_req_t request = { 0, };
 	pcie_doe_disc_resp_t response;
-	uint32_t resp_len;
+	size_t resp_len;
 	int ret;
 
 	do {
-		ret = pcie_doe_send_req(DOE_HEADER_0, bdf, doe_cap_base,
-					(uint32_t *)&request,
-					sizeof(pcie_doe_disc_req_t));
-		if (ret != 0) {
-			return ret;
-		}
+		ret = pcie_doe_communicate(DOE_HEADER_0, bdf, doe_cap_base,
+				(void *)&request, sizeof(pcie_doe_disc_req_t),
+				(void *)&response, &resp_len);
 
-		ret = pcie_doe_recv_resp(bdf, doe_cap_base,
-					(uint32_t *)&response, &resp_len);
 		if (ret != 0) {
 			return ret;
 		}
diff --git a/tftf/tests/doe_tests/doe_helpers.h b/tftf/tests/doe_tests/doe_helpers.h
index 08137e3..8d48278 100644
--- a/tftf/tests/doe_tests/doe_helpers.h
+++ b/tftf/tests/doe_tests/doe_helpers.h
@@ -8,7 +8,8 @@
 #ifndef DOE_HELPERS_H
 #define DOE_HELPERS_H
 
-void pcie_init(void);
+#include <stdint.h>
+
 int find_doe_device(uint32_t *bdf_ptr, uint32_t *cap_base_ptr);
 int doe_discovery(uint32_t bdf, uint32_t doe_cap_base);
 int get_spdm_version(uint32_t bdf, uint32_t doe_cap_base);
diff --git a/tftf/tests/doe_tests/test_doe.c b/tftf/tests/doe_tests/test_doe.c
index 6eb5079..84b30d5 100644
--- a/tftf/tests/doe_tests/test_doe.c
+++ b/tftf/tests/doe_tests/test_doe.c
@@ -5,25 +5,15 @@
  */
 
 #include "doe_helpers.h"
-
+#include <pcie_doe.h>
 #include <test_helpers.h>
 
-#define SKIP_TEST_IF_DOE_NOT_SUPPORTED()					\
-	do {									\
-		if (find_doe_device(&bdf, &doe_cap_base) != 0) {		\
-			tftf_testcase_printf("PCIe DOE not supported\n");	\
-			return TEST_RESULT_SKIPPED;				\
-		}								\
-	} while (false)
-
 test_result_t doe_discovery_test(void)
 {
 	uint32_t bdf, doe_cap_base;
 	int ret;
 
-	pcie_init();
-
-	SKIP_TEST_IF_DOE_NOT_SUPPORTED();
+	SKIP_TEST_IF_DOE_NOT_SUPPORTED(bdf, doe_cap_base);
 
 	ret = doe_discovery(bdf, doe_cap_base);
 	if (ret != 0) {
@@ -38,7 +28,7 @@
 	uint32_t bdf, doe_cap_base;
 	int ret;
 
-	SKIP_TEST_IF_DOE_NOT_SUPPORTED();
+	SKIP_TEST_IF_DOE_NOT_SUPPORTED(bdf, doe_cap_base);
 
 	ret = get_spdm_version(bdf, doe_cap_base);
 	if (ret != 0) {
diff --git a/tftf/tests/extensions/amu/test_amu.c b/tftf/tests/extensions/amu/test_amu.c
index 21305a7..0cc4395 100644
--- a/tftf/tests/extensions/amu/test_amu.c
+++ b/tftf/tests/extensions/amu/test_amu.c
@@ -1,11 +1,12 @@
 /*
- * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <amu.h>
 #include <arch.h>
+#include <arch_features.h>
 #include <arch_helpers.h>
 #include <assert.h>
 #include <debug.h>
diff --git a/tftf/tests/extensions/d128/test_d128.c b/tftf/tests/extensions/d128/test_d128.c
new file mode 100644
index 0000000..1e8df0c
--- /dev/null
+++ b/tftf/tests/extensions/d128/test_d128.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/extensions/sysreg128.h>
+#include <test_helpers.h>
+
+#include "./test_d128.h"
+
+/*
+ * @brief Test FEAT_D128 feature support when the extension is enabled.
+ *
+ * The test ensures that access to common system registers PAR_EL1, TTBR0_EL1, TTBR1_EL1,
+ * TTBR0_EL2, VTTBR_EL2 and the VHE register TTBR1_EL2 do not trap to EL3.
+ *
+ * Additonally this test verifies that EL1 registers are properly context switched by
+ * making dummy SMC call to TSPD (running at S-EL1).
+ *
+ * TODO: EL2 registers context switching.
+ *
+ * @return test_result_t
+ */
+test_result_t test_d128_support(void)
+{
+#ifdef __aarch64__
+	SKIP_TEST_IF_D128_NOT_SUPPORTED();
+	SKIP_TEST_IF_TSP_NOT_PRESENT();
+
+	smc_args tsp_svc_params;
+
+	/* Access 128 bit variant of system registers */
+	read128_par_el1();
+	read128_ttbr0_el1();
+	read128_ttbr1_el1();
+	read128_ttbr0_el2();
+	read128_ttbr1_el2();
+	if (is_armv8_1_vhe_present()) {
+		read128_vttbr_el2();
+	}
+
+	/*
+	 * Check that EL1 registers are properly contexted by EL3. Write to the registers
+	 * make dummy SMC call TSP and ensure that values are prorperly contexted.
+	 * NOTE: Ideal way would be to modify these registers in TSP in SMC handler
+	 */
+	write128_par_el1(PAR_EL1_MASK_FULL);
+	write128_ttbr0_el1(TTBR_REG_MASK_FULL);
+	write128_ttbr1_el1(TTBR_REG_MASK_FULL);
+
+	tsp_svc_params.fid = TSP_STD_FID(TSP_ADD);
+	tsp_svc_params.arg1 = 4;
+	tsp_svc_params.arg2 = 6;
+	tftf_smc(&tsp_svc_params);
+
+	if ((read128_par_el1() != PAR_EL1_MASK_FULL) ||
+	    (read128_ttbr0_el1() != TTBR_REG_MASK_FULL) ||
+	    (read128_ttbr1_el1() != TTBR_REG_MASK_FULL)) {
+		NOTICE("Unexpected value of registers after context switch\n");
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+#else
+	SKIP_TEST_IF_AARCH32();
+#endif /* __aarch64_ */
+}
diff --git a/tftf/tests/extensions/d128/test_d128.h b/tftf/tests/extensions/d128/test_d128.h
new file mode 100644
index 0000000..2e40753
--- /dev/null
+++ b/tftf/tests/extensions/d128/test_d128.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TEST_D128_H
+#define TEST_D128_H
+
+/* Create Mask setting all used bits except PA */
+#define PAR_EL1_MASK_HIGH		0x0000000000000001
+#define PAR_EL1_MASK_LOW		0xFF00000000000F81
+#define PAR_EL1_MASK_FULL		(((uint128_t)PAR_EL1_MASK_HIGH) << 64U | PAR_EL1_MASK_LOW)
+
+/* Masks created by setting all used bits */
+#define TTBR_REG_MASK_HIGH		0x0000000000FF0000
+#define TTBR_REG_MASK_LOW		0xFFFFFFFFFFFFFFE7
+#define TTBR_REG_MASK_FULL		(((uint128_t)TTBR_REG_MASK_HIGH) << 64U | TTBR_REG_MASK_LOW)
+
+#endif /* TEST_D128_H */
diff --git a/tftf/tests/extensions/fpmr/test_fpmr.c b/tftf/tests/extensions/fpmr/test_fpmr.c
new file mode 100644
index 0000000..1e02780
--- /dev/null
+++ b/tftf/tests/extensions/fpmr/test_fpmr.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <test_helpers.h>
+#include <tftf_lib.h>
+#include <debug.h>
+#include <arch_helpers.h>
+
+test_result_t test_fpmr_enabled(void)
+{
+	SKIP_TEST_IF_AARCH32();
+
+#if __aarch64__
+	SKIP_TEST_IF_FPMR_NOT_SUPPORTED();
+
+	read_fpmr();
+#endif
+	return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/extensions/sctlr2/test_sctlr2.c b/tftf/tests/extensions/sctlr2/test_sctlr2.c
new file mode 100644
index 0000000..704d19d
--- /dev/null
+++ b/tftf/tests/extensions/sctlr2/test_sctlr2.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <test_helpers.h>
+
+/*
+ * @brief Test FEAT_SCTLR2 support when the extension is enabled.
+ *
+ * Ensure that reading of SCTLR2_EL1 and SCTLR2_EL2 system registers does not
+ * trap to EL3. Also, verify that SCTLR2_EL1 register value is preserved
+ * correctly during world switch to TSP.
+ *
+ * TODO: Test context switching of SCTLR2_EL2
+ *
+ * @return test_result_t
+ */
+test_result_t test_sctlr2_support(void)
+{
+#ifdef __aarch64__
+	SKIP_TEST_IF_SCTLR2_NOT_SUPPORTED();
+	SKIP_TEST_IF_TSP_NOT_PRESENT();
+
+	smc_args tsp_svc_params;
+
+	/* Access the registers */
+	read_sctlr2_el1();
+	read_sctlr2_el2();
+
+	/* Check that SCTLR2_EL1 is properly contexted by EL3. Write to the registers
+	 * make dummy SMC call TSP and ensure that values are prorperly contexted.
+	 * Set EnIDCP128_BIT which is guaranteed to be present if SCTLR2 is present.
+	 */
+	write_sctlr2_el1(read_sctlr2_el1() | SCTLR2_EnIDCP128_BIT);
+
+	tsp_svc_params.fid = TSP_STD_FID(TSP_ADD);
+	tsp_svc_params.arg1 = 4;
+	tsp_svc_params.arg2 = 6;
+	tftf_smc(&tsp_svc_params);
+
+	if ((read_sctlr2_el1() & SCTLR2_EnIDCP128_BIT) == 0) {
+		ERROR("SCTLR2_EL1 unexpected value after context switch\n");
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+#else
+	SKIP_TEST_IF_AARCH32();
+#endif /* __aarch64_ */
+}
diff --git a/tftf/tests/extensions/the/test_the.c b/tftf/tests/extensions/the/test_the.c
new file mode 100644
index 0000000..b56be93
--- /dev/null
+++ b/tftf/tests/extensions/the/test_the.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/extensions/sysreg128.h>
+#include <test_helpers.h>
+
+#include "./test_the.h"
+
+/*
+ * @brief Test FEAT_THE support when the extension is enabled.
+ *
+ * Write to the RCWMASK_EL1 and RCWSMASK_EL1 system registers with
+ * a mask of allowed bits in 128-bit mode, if FEAT_D128 is supported,
+ * otherwise in 64-bit mode, perform a dummy SMC call, then read the
+ * registers back.
+ *
+ * The test ensures that accesses to these registers do not trap
+ * to EL3 as well as that their values are preserved correctly.
+ *
+ * @return test_result_t
+ */
+test_result_t test_the_support(void)
+{
+#ifdef __aarch64__
+	SKIP_TEST_IF_THE_NOT_SUPPORTED();
+	SKIP_TEST_IF_TSP_NOT_PRESENT();
+
+	smc_args tsp_svc_params;
+	/* Standard SMC to ADD two numbers */
+	tsp_svc_params.fid = TSP_STD_FID(TSP_ADD);
+	tsp_svc_params.arg1 = 4;
+	tsp_svc_params.arg2 = 6;
+
+	if (is_feat_d128_supported()) {
+		uint128_t reg_read;
+
+		write128_rcwmask_el1(RCWMASK_EL1_MASK_FULL);
+		write128_rcwsmask_el1(RCWSMASK_EL1_MASK_FULL);
+		tftf_smc(&tsp_svc_params);
+
+		reg_read = read128_rcwmask_el1();
+		if (reg_read != RCWMASK_EL1_MASK_FULL) {
+			NOTICE("RCWMASK_EL1 unexpected value after context switch: 0x%llx:0x%llx\n",
+				(uint64_t)(reg_read >> 64U), (uint64_t)reg_read);
+			return TEST_RESULT_FAIL;
+		}
+
+		reg_read = read128_rcwsmask_el1();
+		if (reg_read != RCWSMASK_EL1_MASK_FULL) {
+			NOTICE("RCWSMASK_EL1 unexpected value after context switch: 0x%llx:0x%llx\n",
+				(uint64_t)(reg_read >> 64U), (uint64_t)reg_read);
+			return TEST_RESULT_FAIL;
+		}
+
+		return TEST_RESULT_SUCCESS;
+	}
+
+	uint64_t reg_read;
+
+	write_rcwmask_el1(RCWMASK_EL1_MASK_LOW);
+	write_rcwsmask_el1(RCWSMASK_EL1_MASK_LOW);
+	tftf_smc(&tsp_svc_params);
+
+	reg_read = read_rcwmask_el1();
+	if (reg_read != RCWMASK_EL1_MASK_LOW) {
+		NOTICE("RCWMASK_EL1 unexpected value after context switch: 0x%llx\n", reg_read);
+		return TEST_RESULT_FAIL;
+	}
+
+	reg_read = read_rcwsmask_el1();
+	if (reg_read != RCWSMASK_EL1_MASK_LOW) {
+		NOTICE("RCWSMASK_EL1 unexpected value after context switch: 0x%llx\n", reg_read);
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+#else
+	SKIP_TEST_IF_AARCH32();
+#endif /* __aarch64_ */
+}
diff --git a/tftf/tests/extensions/the/test_the.h b/tftf/tests/extensions/the/test_the.h
new file mode 100644
index 0000000..92a3768
--- /dev/null
+++ b/tftf/tests/extensions/the/test_the.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TEST_THE_H
+#define TEST_THE_H
+
+#define RCWMASK_EL1_MASK_HIGH	0x807BE01FF8000000
+#define RCWMASK_EL1_MASK_LOW	0xFFEC00000003FFFE
+#define RCWMASK_EL1_MASK_FULL	\
+    (((uint128_t)RCWMASK_EL1_MASK_HIGH) << 64U | RCWMASK_EL1_MASK_LOW)
+
+#define RCWSMASK_EL1_MASK_HIGH	0x807BE01FF8000000
+#define RCWSMASK_EL1_MASK_LOW	0xFFFC00000003FFFE
+#define RCWSMASK_EL1_MASK_FULL	\
+    (((uint128_t)RCWSMASK_EL1_MASK_HIGH) << 64U | RCWSMASK_EL1_MASK_LOW)
+
+#endif /* TEST_THE_H */
diff --git a/tftf/tests/misc_tests/test_ras_kfh.c b/tftf/tests/misc_tests/test_ras_kfh.c
index b38d6c4..f92e048 100644
--- a/tftf/tests/misc_tests/test_ras_kfh.c
+++ b/tftf/tests/misc_tests/test_ras_kfh.c
@@ -13,9 +13,10 @@
 static volatile uint64_t serror_triggered;
 extern void inject_unrecoverable_ras_error(void);
 
-static bool serror_handler(void)
+static bool serror_handler(bool *incr_elr_elx)
 {
 	serror_triggered = 1;
+	*incr_elr_elx = false;
 	return true;
 }
 
diff --git a/tftf/tests/misc_tests/test_ras_kfh_reflect.c b/tftf/tests/misc_tests/test_ras_kfh_reflect.c
index d24fc47..eb93d72 100644
--- a/tftf/tests/misc_tests/test_ras_kfh_reflect.c
+++ b/tftf/tests/misc_tests/test_ras_kfh_reflect.c
@@ -33,9 +33,10 @@
  * One test each to verify reflection in sync and async exception.
  *
  */
-static bool serror_handler(void)
+static bool serror_handler(bool *incr_elr_elx)
 {
 	serror_triggered = 1;
+	*incr_elr_elx = false;
 	tftf_testcase_printf("SError event received.\n");
 	return true;
 }
diff --git a/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_1.c b/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_1.c
index 93abf15..7babcd1 100644
--- a/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_1.c
+++ b/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_1.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
  * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -13,6 +13,7 @@
 #include <psci.h>
 #include <smccc.h>
 #include <string.h>
+#include <test_helpers.h>
 #include <tftf_lib.h>
 
 #ifdef __aarch64__
@@ -69,21 +70,11 @@
 {
 	smc_args args;
 	smc_ret_values ret;
-	int32_t expected_ver;
 	unsigned int my_midr, midr_mask;
 	int wa_required;
 	size_t i;
 
-	/* Check if SMCCC version is at least v1.1 */
-	expected_ver = MAKE_SMCCC_VERSION(1, 1);
-	memset(&args, 0, sizeof(args));
-	args.fid = SMCCC_VERSION;
-	ret = tftf_smc(&args);
-	if ((int32_t)ret.ret0 < expected_ver) {
-		tftf_testcase_printf("Unexpected SMCCC version: 0x%x\n",
-		       (int)ret.ret0);
-		return TEST_RESULT_SKIPPED;
-	}
+	SKIP_TEST_IF_SMCCC_VERSION_LT(1, 1);
 
 	/* Check if SMCCC_ARCH_WORKAROUND_1 is required or not */
 	memset(&args, 0, sizeof(args));
diff --git a/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_2.c b/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_2.c
index 1557e4f..b5aa636 100644
--- a/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_2.c
+++ b/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_2.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,6 +12,7 @@
 #include <psci.h>
 #include <smccc.h>
 #include <string.h>
+#include <test_helpers.h>
 #include <tftf_lib.h>
 
 #ifdef __aarch64__
@@ -40,20 +41,10 @@
 {
 	smc_args args;
 	smc_ret_values ret;
-	int32_t expected_ver;
 	unsigned int my_midr, midr_mask;
 	size_t i;
 
-	/* Check if SMCCC version is at least v1.1 */
-	expected_ver = MAKE_SMCCC_VERSION(1, 1);
-	memset(&args, 0, sizeof(args));
-	args.fid = SMCCC_VERSION;
-	ret = tftf_smc(&args);
-	if ((int32_t)ret.ret0 < expected_ver) {
-		tftf_testcase_printf("Unexpected SMCCC version: 0x%x\n",
-		       (int)ret.ret0);
-		return TEST_RESULT_SKIPPED;
-	}
+	SKIP_TEST_IF_SMCCC_VERSION_LT(1, 1);
 
 	/* Check if SMCCC_ARCH_WORKAROUND_2 is required or not */
 	memset(&args, 0, sizeof(args));
diff --git a/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_3.c b/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_3.c
index ebf40a5..77c50cc 100644
--- a/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_3.c
+++ b/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_3.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,6 +12,7 @@
 #include <psci.h>
 #include <smccc.h>
 #include <string.h>
+#include <test_helpers.h>
 #include <tftf_lib.h>
 
 #ifdef __aarch64__
@@ -65,21 +66,11 @@
 {
 	smc_args args;
 	smc_ret_values ret;
-	int32_t expected_ver;
 	unsigned int my_midr, midr_mask;
 	int wa_required;
 	size_t i;
 
-	/* Check if SMCCC version is at least v1.1 */
-	expected_ver = MAKE_SMCCC_VERSION(1, 1);
-	memset(&args, 0, sizeof(args));
-	args.fid = SMCCC_VERSION;
-	ret = tftf_smc(&args);
-	if ((int32_t)ret.ret0 < expected_ver) {
-		tftf_testcase_printf("Unexpected SMCCC version: 0x%x\n",
-		       (int)ret.ret0);
-		return TEST_RESULT_SKIPPED;
-	}
+	SKIP_TEST_IF_SMCCC_VERSION_LT(1, 1);
 
 	/* Check if SMCCC_ARCH_WORKAROUND_3 is required or not */
 	memset(&args, 0, sizeof(args));
diff --git a/tftf/tests/runtime_services/arm_arch_svc/smccc_feature_availability.c b/tftf/tests/runtime_services/arm_arch_svc/smccc_feature_availability.c
new file mode 100644
index 0000000..1418ca1
--- /dev/null
+++ b/tftf/tests/runtime_services/arm_arch_svc/smccc_feature_availability.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <tftf.h>
+
+#include <arm_arch_svc.h>
+#include <smccc.h>
+#include <test_helpers.h>
+#include <tftf_lib.h>
+
+static inline u_register_t get_feature_for_reg(u_register_t reg)
+{
+	smc_args args = {0};
+	smc_ret_values ret;
+
+	args.fid = SMCCC_ARCH_FEATURE_AVAILABILITY | (SMC_64 << FUNCID_CC_SHIFT);
+	args.arg1 = reg;
+	ret = tftf_smc(&args);
+
+	/* APi is pretty simple, support was already checked. This is simpler */
+	assert((int)ret.ret0 == SMC_ARCH_CALL_SUCCESS);
+	return ret.ret1;
+}
+
+static inline bool always_present(void)
+{
+	return true;
+}
+
+/*
+ * Checks that the bit's matches the feature's presence
+ * feat_func should be is_feat_xyz_present(), but get_feat_xyz_support() will
+ * also work.
+ */
+#define CHECK_BIT_SET(feat_func, bit)						\
+	do {									\
+		if (!!feat_func() != !!(reg & bit)) {				\
+			tftf_testcase_printf(					\
+				#feat_func " says feature is %ssupported but "	\
+				#bit " was %sset!\n", feat_func() ? "" : "not ",\
+				(reg & bit) ? "" : "not ");			\
+			bad = true;						\
+		}								\
+		reg &= ~bit;							\
+	} while (0)
+
+/* when support for a new feature is added, we want this test to be
+ * updated. Fail the test so it's noticed. */
+#define CHECK_NO_BITS_SET(reg_name)						\
+	do {									\
+		if (reg != 0) {							\
+			tftf_testcase_printf(					\
+			#reg_name " still has values set: 0x%lx. "		\
+				"Test needs to be updated\n", reg);		\
+			bad = true;						\
+		}								\
+	} while (0)
+
+test_result_t test_smccc_arch_feature_availability(void)
+{
+	SKIP_TEST_IF_AARCH32();
+#ifdef __aarch64__
+
+	SKIP_TEST_IF_SMCCC_VERSION_LT(1, 1);
+	SKIP_TEST_IF_SMCCC_FUNC_NOT_SUPPORTED(SMCCC_ARCH_FEATURE_AVAILABILITY);
+
+	u_register_t reg;
+	bool bad = false;
+
+	reg = get_feature_for_reg(SCR_EL3_OPCODE);
+	CHECK_BIT_SET(is_armv8_9_fgt2_present,			SCR_FGTEN2_BIT);
+	CHECK_BIT_SET(is_feat_fpmr_present,			SCR_EnFPM_BIT);
+	CHECK_BIT_SET(is_feat_d128_supported,			SCR_D128En_BIT);
+	CHECK_BIT_SET(is_feat_s1pie_present,			SCR_PIEN_BIT);
+	CHECK_BIT_SET(is_feat_sctlr2_supported,			SCR_SCTLR2En_BIT);
+	CHECK_BIT_SET(is_feat_tcr2_supported,			SCR_TCR2EN_BIT);
+	CHECK_BIT_SET(is_feat_the_supported,			SCR_RCWMASKEn_BIT);
+	CHECK_BIT_SET(is_feat_sme_supported,			SCR_ENTP2_BIT);
+	CHECK_BIT_SET(is_feat_rng_trap_present,			SCR_TRNDR_BIT);
+	CHECK_BIT_SET(is_feat_gcs_present,			SCR_GCSEn_BIT);
+	CHECK_BIT_SET(get_feat_hcx_support,			SCR_HXEn_BIT);
+	CHECK_BIT_SET(is_feat_ls64_accdata_present,		SCR_ADEn_BIT);
+	CHECK_BIT_SET(is_feat_ls64_accdata_present,		SCR_EnAS0_BIT);
+	CHECK_BIT_SET(is_feat_amuv1p1_present,			SCR_AMVOFFEN_BIT);
+	CHECK_BIT_SET(get_armv8_6_ecv_support,			SCR_ECVEN_BIT);
+	CHECK_BIT_SET(is_armv8_6_fgt_present,			SCR_FGTEN_BIT);
+	CHECK_BIT_SET(is_feat_mte2_present,			SCR_ATA_BIT);
+	CHECK_BIT_SET(is_feat_csv2_2_present,			SCR_EnSCXT_BIT);
+	CHECK_BIT_SET(is_armv8_3_pauth_present,			SCR_APK_BIT);
+	CHECK_BIT_SET(is_feat_ras_present,			SCR_TERR_BIT);
+	CHECK_NO_BITS_SET(SCR_EL3);
+
+	reg = get_feature_for_reg(CPTR_EL3_OPCODE);
+	CHECK_BIT_SET(always_present,				CPTR_EL3_TCPAC_BIT);
+	CHECK_BIT_SET(is_feat_amuv1_present,			CPTR_EL3_TAM_BIT);
+	CHECK_BIT_SET(get_armv8_0_sys_reg_trace_support,	CPTR_EL3_TTA_BIT);
+	CHECK_BIT_SET(is_feat_sme_supported,			CPTR_EL3_ESM_BIT);
+	CHECK_BIT_SET(always_present,				CPTR_EL3_TFP_BIT);
+	CHECK_BIT_SET(is_armv8_2_sve_present,			CPTR_EL3_EZ_BIT);
+	CHECK_NO_BITS_SET(CPTR_EL3);
+
+	reg = get_feature_for_reg(MDCR_EL3_OPCODE);
+	CHECK_BIT_SET(get_feat_brbe_support,			MDCR_SBRBE(1));
+	CHECK_BIT_SET(is_armv8_6_fgt_present,			MDCR_TDCC_BIT);
+	CHECK_BIT_SET(is_feat_trbe_present,			MDCR_NSTB(1));
+	CHECK_BIT_SET(get_armv8_4_trf_support,			MDCR_TTRF_BIT);
+	CHECK_BIT_SET(is_feat_spe_supported,			MDCR_NSPB(1));
+	CHECK_BIT_SET(is_feat_doublelock_present,		MDCR_TDOSA_BIT);
+	CHECK_BIT_SET(always_present,				MDCR_TDA_BIT);
+	CHECK_BIT_SET(get_feat_pmuv3_supported,			MDCR_TPM_BIT);
+	CHECK_NO_BITS_SET(MDCR_EL3);
+
+	reg = get_feature_for_reg(MPAM3_EL3_OPCODE);
+	CHECK_BIT_SET(is_feat_mpam_supported,			MPAM3_EL3_TRAPLOWER_BIT);
+	CHECK_NO_BITS_SET(MPAM3_EL3);
+
+	if (bad)
+		return TEST_RESULT_FAIL;
+
+	return TEST_RESULT_SUCCESS;
+#endif /* __aarch64__ */
+}
diff --git a/tftf/tests/runtime_services/host_realm_managment/host_crypto_utils.c b/tftf/tests/runtime_services/host_realm_managment/host_crypto_utils.c
new file mode 100644
index 0000000..80834fa
--- /dev/null
+++ b/tftf/tests/runtime_services/host_realm_managment/host_crypto_utils.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+#include <stdbool.h>
+
+#ifdef MBEDTLS_CONFIG_FILE
+#include <mbedtls/asn1.h>
+#include <mbedtls/bignum.h>
+#include <mbedtls/ecdh.h>
+#include <mbedtls/memory_buffer_alloc.h>
+#include <mbedtls/x509.h>
+#include <mbedtls/x509_crt.h>
+#endif
+
+#include <host_crypto_utils.h>
+#include <test_helpers.h>
+
+#ifdef MBEDTLS_CONFIG_FILE
+#define HOST_MBEDTLS_HEAP_SIZE	(2U * SZ_4K)
+static unsigned char host_mbedtls_heap[HOST_MBEDTLS_HEAP_SIZE];
+
+static int host_get_leaf_cert_from_cert_chain(uint8_t *cert_chain,
+					      size_t cert_chain_len,
+					      uint8_t **leaf_cert,
+					      size_t *leaf_cert_len)
+{
+	size_t asn1_len;
+	unsigned char *tag_ptr;
+	uint8_t *cert_chain_end;
+	uint8_t *cur_cert;
+	size_t cur_cert_len;
+	int cur_cert_idx;
+	int rc;
+
+	cur_cert = cert_chain;
+	cur_cert_idx = -1;
+	cert_chain_end = cert_chain + cert_chain_len;
+
+	/* Get leaf certificate from cert_chain */
+	while (true) {
+		tag_ptr = cur_cert;
+		rc = mbedtls_asn1_get_tag(&tag_ptr, cert_chain_end, &asn1_len,
+					  MBEDTLS_ASN1_CONSTRUCTED |
+					  MBEDTLS_ASN1_SEQUENCE);
+		if (rc != 0) {
+			break;
+		}
+
+		cur_cert_len = asn1_len + (tag_ptr - cur_cert);
+		if (cur_cert + cur_cert_len > cert_chain_end) {
+			cur_cert_idx = -1;
+			break;
+		}
+
+		cur_cert = cur_cert + cur_cert_len;
+		cur_cert_idx++;
+	}
+
+	if (cur_cert_idx == -1) {
+		return -1;
+	}
+
+	*leaf_cert = cur_cert - cur_cert_len;
+	*leaf_cert_len = cur_cert_len;
+	INFO("leaf_cert_len: 0x%lx\n", *leaf_cert_len);
+
+	return 0;
+}
+
+/*
+ * @In:
+ * cert_chain		- Certificate chain
+ * cert_chain_len	- Length of certificate
+ * public_key_len	- Max length of 'public_key' buffer
+ * metadata_len		- Max length of 'metadata' buffer
+ *
+ * On success below variables are set:
+ * @Out:
+ * public_key		- Public key content
+ * public_key_len	- length of 'public_key'
+ * metadata		- Public key metadata content
+ * metadata_len		- length of 'metadata' if metadata exists, else set to 0
+ * public_key_algo	- Public key algorithm
+ */
+static int _host_get_public_key_from_cert_chain(uint8_t *cert_chain,
+						size_t cert_chain_len,
+						void *public_key,
+						size_t *public_key_len,
+						void *public_key_metadata,
+						size_t *public_key_metadata_len,
+						uint8_t *public_key_algo)
+{
+	uint8_t *leaf_cert;
+	size_t leaf_cert_len;
+	mbedtls_x509_crt crt;
+	mbedtls_pk_type_t pk_type;
+	int rc;
+
+	/* Get leaf cert and its length */
+	rc = host_get_leaf_cert_from_cert_chain(cert_chain, cert_chain_len,
+						&leaf_cert, &leaf_cert_len);
+	if (rc != 0) {
+		return -1;
+	}
+
+	/* Get public key from leaf certificate */
+	mbedtls_x509_crt_init(&crt);
+
+	if (mbedtls_x509_crt_parse_der(&crt, leaf_cert, leaf_cert_len) != 0) {
+		return -1;
+	}
+
+	pk_type = mbedtls_pk_get_type(&crt.pk);
+	if (pk_type != MBEDTLS_PK_ECKEY && pk_type != MBEDTLS_PK_RSA) {
+		rc = -1;
+		goto out_crt_free;
+	}
+
+	if (pk_type == MBEDTLS_PK_ECKEY) {
+		mbedtls_ecp_keypair *ecp;
+		mbedtls_ecp_group grp;
+		mbedtls_ecp_point pt;
+
+		ecp = mbedtls_pk_ec(crt.pk);
+		mbedtls_ecp_group_init(&grp);
+		mbedtls_ecp_point_init(&pt);
+		rc = mbedtls_ecp_export(ecp, &grp, NULL, &pt);
+
+		if (rc != 0 || (grp.id != MBEDTLS_ECP_DP_SECP256R1 &&
+				grp.id != MBEDTLS_ECP_DP_SECP384R1)) {
+			mbedtls_ecp_point_free(&pt);
+			mbedtls_ecp_group_free(&grp);
+			rc = -1;
+			goto out_crt_free;
+		}
+
+		rc = mbedtls_ecp_point_write_binary(&grp, &pt,
+						    MBEDTLS_ECP_PF_UNCOMPRESSED,
+						    public_key_len, public_key,
+						    MBEDTLS_ECP_MAX_PT_LEN);
+
+		if (rc == 0) {
+			if (grp.id == MBEDTLS_ECP_DP_SECP256R1) {
+				*public_key_algo =
+					PUBLIC_KEY_ALGO_ECDSA_ECC_NIST_P256;
+			} else {
+				*public_key_algo =
+					PUBLIC_KEY_ALGO_ECDSA_ECC_NIST_P384;
+			}
+
+			/* No metadata for PK_ECKEY type */
+			*public_key_metadata_len = 0;
+		}
+
+		mbedtls_ecp_point_free(&pt);
+		mbedtls_ecp_group_free(&grp);
+	} else {
+		mbedtls_rsa_context *rsa;
+		mbedtls_mpi N;
+		mbedtls_mpi E;
+		size_t N_sz, E_sz;
+
+		rsa = mbedtls_pk_rsa(crt.pk);
+		mbedtls_mpi_init(&N);
+		mbedtls_mpi_init(&E);
+
+		rc = mbedtls_rsa_export(rsa, &N, NULL, NULL, NULL, &E);
+		N_sz = mbedtls_mpi_size(&N);
+		E_sz = mbedtls_mpi_size(&E);
+		INFO("RSA public key len: %ld, metadata len:%ld\n", N_sz, E_sz);
+
+		/* Supported ALGO type RSASSA_3072 (384 bytes) */
+		if (rc == 0 && N_sz == 384) {
+			rc = mbedtls_mpi_write_binary(&N, public_key, N_sz);
+			rc |= mbedtls_mpi_write_binary(&E, public_key_metadata,
+						       E_sz);
+			if (rc == 0) {
+				*public_key_algo = PUBLIC_KEY_ALGO_RSASSA_3072;
+				*public_key_len = N_sz;
+				*public_key_metadata_len = E_sz;
+			}
+		} else {
+			rc = -1;
+		}
+
+		mbedtls_mpi_free(&N);
+		mbedtls_mpi_free(&E);
+	}
+
+out_crt_free:
+	mbedtls_x509_crt_free(&crt);
+
+	return rc;
+}
+#endif
+
+int host_get_public_key_from_cert_chain(uint8_t *cert_chain,
+					size_t cert_chain_len,
+					void *public_key,
+					size_t *public_key_len,
+					void *public_key_metadata,
+					size_t *public_key_metadata_len,
+					uint8_t *public_key_algo)
+{
+	int rc;
+
+#ifdef MBEDTLS_CONFIG_FILE
+	mbedtls_memory_buffer_alloc_init(host_mbedtls_heap,
+					 sizeof(host_mbedtls_heap));
+
+	rc = _host_get_public_key_from_cert_chain(cert_chain, cert_chain_len,
+						  public_key, public_key_len,
+						  public_key_metadata,
+						  public_key_metadata_len,
+						  public_key_algo);
+#else
+	ERROR("MbedTLS not found.\n");
+	rc = -1;
+#endif
+	return rc;
+}
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 9c7ceba..3a4121b 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
@@ -34,7 +34,11 @@
 	RMI_EXIT(PSCI),
 	RMI_EXIT(RIPAS_CHANGE),
 	RMI_EXIT(HOST_CALL),
-	RMI_EXIT(SERROR)
+	RMI_EXIT(SERROR),
+	RMI_EXIT(IO),
+	RMI_EXIT(RTT_REQUEST),
+	RMI_EXIT(S2AP_CHANGE),
+	RMI_EXIT(VDEV_REQUEST)
 };
 
 /*
@@ -135,7 +139,8 @@
 			       u_register_t feature_flag,
 			       long sl,
 			       const u_register_t *rec_flag,
-			       unsigned int rec_count)
+			       unsigned int rec_count,
+			       unsigned int num_aux_planes)
 {
 	int8_t value;
 
@@ -169,6 +174,21 @@
 				EXTRACT(RMI_FEATURE_REGISTER_0_S2SZ, feature_flag));
 	}
 
+	realm_ptr->rtt_tree_single = false;
+	if (num_aux_planes > 0U) {
+		if (EXTRACT(RMI_FEATURE_REGISTER_0_PLANE_RTT, feature_flag) >=
+							RMI_PLANE_RTT_SINGLE) {
+			ERROR("S2POE not suported on TFTF\n");
+			return false;
+		}
+
+		/*
+		 * @TODO: once S2POE is supported, this should be a parameter
+		 * so it can be tested with and without support for auxiliary
+		 * tables.
+		 */
+	}
+
 	/* Disable PMU if not required */
 	if ((feature_flag & RMI_FEATURE_REGISTER_0_PMU_EN) == 0UL) {
 		realm_ptr->rmm_feat_reg0 &= ~RMI_FEATURE_REGISTER_0_PMU_EN;
@@ -246,6 +266,12 @@
 
 	realm_ptr->start_level = sl;
 
+	if (num_aux_planes > MAX_AUX_PLANE_COUNT) {
+		ERROR("Invalid aux plane count\n");
+		return false;
+	}
+	realm_ptr->num_aux_planes = num_aux_planes;
+
 	/* Create Realm */
 	if (host_realm_create(realm_ptr) != REALM_SUCCESS) {
 		ERROR("%s() failed\n", "host_realm_create");
@@ -283,7 +309,8 @@
 			       u_register_t feature_flag,
 			       long sl,
 			       const u_register_t *rec_flag,
-			       unsigned int rec_count)
+			       unsigned int rec_count,
+			       unsigned int num_aux_planes)
 {
 	bool ret;
 
@@ -292,7 +319,8 @@
 			feature_flag,
 			sl,
 			rec_flag,
-			rec_count);
+			rec_count,
+			num_aux_planes);
 	if (!ret) {
 		goto destroy_realm;
 	} else {
@@ -323,7 +351,8 @@
 			u_register_t feature_flag,
 			long sl,
 			const u_register_t *rec_flag,
-			unsigned int rec_count)
+			unsigned int rec_count,
+			unsigned int num_aux_planes)
 
 {
 	bool ret;
@@ -333,7 +362,8 @@
 			feature_flag,
 			sl,
 			rec_flag,
-			rec_count);
+			rec_count,
+			num_aux_planes);
 	if (!ret) {
 		goto destroy_realm;
 	} else {
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 fdb1d4a..5c851a7 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
@@ -76,7 +76,7 @@
 	 * must be preserved unless they contain result,
 	 * as specified in the function definition.
 	 */
-	if (regs[0] != RMI_RTT_READ_ENTRY) {
+	if ((regs[0] != RMI_RTT_READ_ENTRY) && (regs[0] != RMI_RTT_AUX_MAP_PROTECTED)) {
 		CHECK_RET(4);
 	}
 
@@ -184,6 +184,16 @@
 				rd, rtt, map_addr, (u_register_t)level}, 5U).ret0;
 }
 
+static inline u_register_t host_rmi_rtt_aux_create(u_register_t rd,
+						u_register_t rtt,
+						u_register_t map_addr,
+						long  level,
+						u_register_t tree_index)
+{
+	return host_rmi_handler(&(smc_args) {RMI_RTT_AUX_CREATE,
+				rd, rtt, map_addr, (u_register_t)level, tree_index}, 6U).ret0;
+}
+
 u_register_t host_rmi_rtt_destroy(u_register_t rd,
 				  u_register_t map_addr,
 				  long level,
@@ -200,6 +210,24 @@
 	return rets.ret0;
 }
 
+u_register_t host_rmi_rtt_aux_destroy(u_register_t rd,
+				  u_register_t map_addr,
+				  long level,
+				  u_register_t tree_index,
+				  u_register_t *rtt,
+				  u_register_t *top)
+{
+	smc_ret_values rets;
+
+	rets = host_rmi_handler(&(smc_args) {RMI_RTT_AUX_DESTROY,
+				rd, map_addr, (u_register_t)level,
+				tree_index,
+				(u_register_t)&rets}, 6U);
+	*rtt = rets.ret1;
+	*top = rets.ret2;
+	return rets.ret0;
+}
+
 u_register_t host_rmi_features(u_register_t index, u_register_t *features)
 {
 	smc_ret_values rets;
@@ -243,6 +271,22 @@
 	return rets.ret0;
 }
 
+static inline u_register_t host_rmi_rtt_aux_fold(u_register_t rd,
+						 u_register_t map_addr,
+						 long level,
+						 u_register_t tree_index,
+						 u_register_t *pa)
+{
+	smc_ret_values rets;
+
+	rets = host_rmi_handler(&(smc_args) {RMI_RTT_AUX_FOLD,
+				rd, map_addr, (u_register_t)level,
+				tree_index,
+				(u_register_t)&rets}, 6U);
+	*pa = rets.ret1;
+	return rets.ret0;
+}
+
 static inline u_register_t host_rmi_rec_aux_count(u_register_t rd,
 						  u_register_t *aux_count)
 {
@@ -276,6 +320,42 @@
 				rd, map_addr, (u_register_t)level, ns_pa}, 5U).ret0;
 }
 
+u_register_t host_rmi_rtt_aux_map_unprotected(u_register_t rd,
+					      u_register_t map_addr,
+					      u_register_t tree_index,
+					      u_register_t *fail_index,
+					      u_register_t *level_pri,
+					      u_register_t *state)
+{
+	smc_ret_values rets;
+
+	rets = host_rmi_handler(&(smc_args) {RMI_RTT_AUX_MAP_UNPROTECTED,
+				rd, map_addr, tree_index}, 4U);
+	*fail_index = rets.ret1;
+	*level_pri = rets.ret2;
+	*state = rets.ret3;
+	return rets.ret0;
+}
+
+u_register_t host_rmi_rtt_aux_map_protected(u_register_t rd,
+					 u_register_t map_addr,
+					 u_register_t tree_index,
+					 u_register_t *fail_index,
+					 u_register_t *level_pri,
+					 u_register_t *state,
+					 u_register_t *ripas)
+{
+	smc_ret_values rets;
+
+	rets = host_rmi_handler(&(smc_args) {RMI_RTT_AUX_MAP_PROTECTED,
+				rd, map_addr, tree_index}, 4U);
+	*fail_index = rets.ret1;
+	*level_pri = rets.ret2;
+	*state = rets.ret3;
+	*ripas = rets.ret4;
+	return rets.ret0;
+}
+
 u_register_t host_rmi_rtt_readentry(u_register_t rd,
 				   u_register_t map_addr,
 				   long level,
@@ -305,6 +385,36 @@
 	return rets.ret0;
 }
 
+u_register_t host_rmi_rtt_aux_unmap_unprotected(u_register_t rd,
+					  u_register_t map_addr,
+					  u_register_t tree_index,
+					  u_register_t *top,
+					  u_register_t *level)
+{
+	smc_ret_values rets;
+
+	rets = host_rmi_handler(&(smc_args) {RMI_RTT_AUX_UNMAP_UNPROTECTED,
+					rd, map_addr, tree_index}, 4U);
+	*top = rets.ret1;
+	*level = rets.ret2;
+	return rets.ret0;
+}
+
+u_register_t host_rmi_rtt_aux_unmap_protected(u_register_t rd,
+					  u_register_t map_addr,
+					  u_register_t tree_index,
+					  u_register_t *top,
+					  u_register_t *level)
+{
+	smc_ret_values rets;
+
+	rets = host_rmi_handler(&(smc_args) {RMI_RTT_AUX_UNMAP_PROTECTED,
+					rd, map_addr, tree_index}, 4U);
+	*top = rets.ret1;
+	*level = rets.ret2;
+	return rets.ret0;
+}
+
 bool host_ipa_is_ns(u_register_t addr, u_register_t rmm_feat_reg0)
 {
 	return (addr >> (EXTRACT(RMI_FEATURE_REGISTER_0_S2SZ, rmm_feat_reg0) - 1UL) == 1UL);
@@ -351,6 +461,42 @@
 	return REALM_SUCCESS;
 }
 
+static u_register_t host_realm_create_rtt_aux_levels(struct realm *realm,
+					    u_register_t map_addr,
+					    long level, long max_level,
+					    u_register_t tree_index)
+{
+	u_register_t rtt, ret, ipa_align;
+
+	assert(tree_index != PRIMARY_RTT_INDEX);
+	while (level++ < max_level) {
+		rtt = (u_register_t)page_alloc(PAGE_SIZE);
+		if (rtt == HEAP_NULL_PTR) {
+			ERROR("Failed to allocate memory for rtt\n");
+			return REALM_ERROR;
+		} else {
+			ret = host_rmi_granule_delegate(rtt);
+			if (ret != RMI_SUCCESS) {
+				ERROR("%s() failed, rtt=0x%lx ret=0x%lx\n",
+					"host_rmi_granule_delegate", rtt, ret);
+				return REALM_ERROR;
+			}
+		}
+		ipa_align = ALIGN_DOWN(map_addr, RTT_MAP_SIZE(level - 1));
+		ret = host_rmi_rtt_aux_create(realm->rd, rtt, ipa_align, (u_register_t)level,
+				tree_index);
+		if (ret != RMI_SUCCESS) {
+			ERROR("%s() failed, rtt=0x%lx ret=0x%lx\n",
+				"host_realm_rtt_aux_create", rtt, ret);
+			host_rmi_granule_undelegate(rtt);
+			page_free(rtt);
+			return REALM_ERROR;
+		}
+	}
+
+	return REALM_SUCCESS;
+}
+
 u_register_t host_realm_fold_rtt(u_register_t rd, u_register_t addr,
 				 long level)
 {
@@ -379,6 +525,93 @@
 
 }
 
+u_register_t host_realm_aux_map_protected_data(struct realm *realm,
+						u_register_t target_pa,
+						u_register_t map_size,
+						u_register_t tree_index,
+						u_register_t *fail_index,
+						u_register_t *level_pri,
+						u_register_t *state,
+						u_register_t *ripas)
+{
+	u_register_t ret, top;
+	long level;
+	int8_t ulevel;
+	u_register_t size = 0UL;
+	u_register_t map_addr = target_pa;
+
+	assert(tree_index != PRIMARY_RTT_INDEX);
+	for (size = 0UL; size < map_size; size += PAGE_SIZE) {
+		ret =  host_rmi_rtt_aux_map_protected(realm->rd, map_addr, tree_index,
+			fail_index, level_pri, state, ripas);
+
+		if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT_AUX) {
+			/* Create missing RTTs till L3 and retry */
+			ulevel = RMI_RETURN_INDEX(ret);
+			level = (long)ulevel;
+
+			ret = host_realm_create_rtt_aux_levels(realm, map_addr,
+							 (u_register_t)level,
+							 3U, tree_index);
+			if (ret != RMI_SUCCESS) {
+				ERROR("%s() failed, ret=0x%lx line=%u\n",
+					"host_realm_create_rtt_aux_levels",
+					ret, __LINE__);
+				goto err;
+			}
+			ret =  host_rmi_rtt_aux_map_protected(realm->rd, target_pa, tree_index,
+				fail_index, level_pri, state, ripas);
+			if (ret != RMI_SUCCESS) {
+				ERROR("%s() failed, ret=0x%lx\n",
+				"host_rmi_data_create", ret);
+				goto err;
+			}
+		} else if (ret != RMI_SUCCESS) {
+			ERROR("host_rmi_rtt_aux_map_protected failed ret = 0x%lx", ret);
+			goto err;
+		}
+		map_addr += PAGE_SIZE;
+	}
+	return REALM_SUCCESS;
+
+err:
+	while (size >= PAGE_SIZE) {
+		ret = host_rmi_rtt_aux_unmap_protected(realm->rd, target_pa, tree_index,
+				&top, (u_register_t *)&level);
+		if (ret != RMI_SUCCESS) {
+			ERROR("%s() failed, addr=0x%lx ret=0x%lx\n",
+				"host_rmi_rtt_aux_unmap_protected", map_addr, ret);
+		}
+		size -= PAGE_SIZE;
+		map_addr -= PAGE_SIZE;
+	}
+	return REALM_ERROR;
+}
+
+u_register_t host_realm_aux_unmap_protected_data(struct realm *realm,
+						u_register_t target_ipa,
+						u_register_t map_size,
+						u_register_t tree_index,
+						u_register_t *top,
+						u_register_t *level)
+{
+	u_register_t ret, size = 0UL, map_addr = target_ipa;
+
+	assert(tree_index != PRIMARY_RTT_INDEX);
+	for (size = 0UL; size < map_size; size += PAGE_SIZE) {
+		ret = host_rmi_rtt_aux_unmap_protected(realm->rd, map_addr, tree_index,
+				top, level);
+		if (ret != RMI_SUCCESS) {
+			WARN("%s() failed, ret=0x%lx line=%u\n",
+					"host_rmi_rtt_aux_unmap_protected",
+					ret, __LINE__);
+			return REALM_ERROR;
+		}
+		map_addr += PAGE_SIZE;
+	}
+	return REALM_SUCCESS;
+}
+
 u_register_t host_realm_delegate_map_protected_data(bool unknown,
 						    struct realm *realm,
 						    u_register_t target_pa,
@@ -392,7 +625,7 @@
 	u_register_t phys = target_pa;
 	u_register_t map_addr = target_pa;
 
-	if (!IS_ALIGNED(map_addr, map_size)) {
+	if (!IS_ALIGNED(map_addr, PAGE_SIZE)) {
 		return REALM_ERROR;
 	}
 
@@ -562,6 +795,50 @@
 	return REALM_SUCCESS;
 }
 
+static u_register_t host_realm_destroy_free_aux_rtt(struct realm *realm,
+						    u_register_t addr,
+						    long level)
+{
+	u_register_t rtt2, top, ret;
+
+	/* Destroy and undelegate RTT entry for all trees */
+	for (unsigned int tree_index = 1U;
+			tree_index <= realm->num_aux_planes;
+			tree_index++) {
+
+		ret = host_rmi_rtt_aux_destroy(realm->rd, ALIGN_DOWN(addr,
+					RTT_MAP_SIZE(level)),
+					level + 1L,
+					tree_index, &rtt2, &top);
+
+		if (ret != RMI_SUCCESS) {
+			/*
+			 * IPA might not be mapped on all AUX RTTs
+			 * ignore error
+			 */
+			VERBOSE("%s() failed, map_addr=0x%lx ret=0x%lx \
+					rtt2=0x%lx \
+					top=0x%lx level=0x%lx\n",
+					"host_rmi_rtt_aux_destroy",
+					addr, ret, rtt2,
+					top, level + 1L);
+		}
+
+		if (rtt2 != 0UL) {
+			ret = host_rmi_granule_undelegate(rtt2);
+			if (ret != RMI_SUCCESS) {
+				ERROR("%s() failed, rtt=0x%lx ret=0x%lx\n",
+					"host_rmi_granule_undelegate",
+					rtt2, ret);
+				return REALM_ERROR;
+			}
+
+			page_free(rtt2);
+		}
+	}
+	return REALM_SUCCESS;
+}
+
 static u_register_t host_realm_destroy_undelegate_range(struct realm *realm,
 							u_register_t ipa,
 							u_register_t addr,
@@ -573,6 +850,29 @@
 
 	while (size >= PAGE_SIZE) {
 		ret = host_rmi_data_destroy(rd, ipa, &data, &top);
+
+		if (ret == RMI_ERROR_RTT_AUX) {
+			/* Unmap from all Aux RTTs */
+			for (unsigned int tree_index = 1U; tree_index <= realm->num_aux_planes;
+					tree_index++) {
+				u_register_t top1, level1;
+
+				/* IPA might not be mapped in all Aux RTTs ignore error */
+				ret = host_rmi_rtt_aux_unmap_protected(
+								rd,
+								ipa,
+								tree_index,
+								&top1, &level1);
+				if (ret != RMI_SUCCESS) {
+					VERBOSE("%s() failed, addr=0x%lx ret=0x%lx tree=0x%x\n",
+					"host_rmi_rtt_aux_unmap_protected",
+					ipa, ret, tree_index);
+				}
+			}
+			/* Retry DATA_DESTROY */
+			continue;
+		}
+
 		if (ret != RMI_SUCCESS) {
 			ERROR("%s() failed, addr=0x%lx ret=0x%lx\n",
 				"host_rmi_data_destroy", ipa, ret);
@@ -622,6 +922,28 @@
 		case RMI_ASSIGNED:
 			if (host_ipa_is_ns(map_addr, realm->rmm_feat_reg0)) {
 
+				u_register_t level1;
+
+				/* Unmap from all Aux RTT */
+				if (!realm->rtt_tree_single) {
+					for (unsigned int tree_index = 1U;
+						tree_index <= realm->num_aux_planes;
+						tree_index++) {
+
+						ret = host_rmi_rtt_aux_unmap_unprotected(
+								rd,
+								map_addr,
+								tree_index,
+								&top, &level1);
+
+						if (ret != RMI_SUCCESS) {
+							ERROR("%s() failed, addr=0x%lx ret=0x%lx\n",
+							"host_rmi_rtt_unmap_unprotected",
+							map_addr, ret);
+						}
+					}
+				}
+
 				ret = host_rmi_rtt_unmap_unprotected(
 								rd,
 								map_addr,
@@ -669,6 +991,19 @@
 					map_addr, ret);
 				return REALM_ERROR;
 			}
+
+			/* RTT_AUX_DESTROY */
+			if (!realm->rtt_tree_single) {
+				ret = host_realm_destroy_free_aux_rtt(realm, map_addr,
+						level);
+
+				if (ret != RMI_SUCCESS) {
+					ERROR("%s() failed, map_addr=0x%lx ret=0x%lx\n",
+						"host_realm_destroy_free_aux_rtt",
+						map_addr, ret);
+					return REALM_ERROR;
+				}
+			}
 			break;
 		default:
 			return REALM_ERROR;
@@ -700,11 +1035,28 @@
 	return ret.ret1;
 }
 
+u_register_t host_rmi_rtt_set_s2ap(u_register_t rd,
+				u_register_t rec,
+				u_register_t base,
+				u_register_t top,
+				u_register_t *out_top,
+				u_register_t *rtt_tree)
+{
+	smc_ret_values rets;
+
+	rets = host_rmi_handler(&(smc_args) {RMI_RTT_SET_S2AP,
+				rd, rec, base, top,
+				(u_register_t)&rets}, 6U);
+	*out_top = rets.ret1;
+	*rtt_tree = rets.ret2;
+	return rets.ret0;
+}
+
 u_register_t host_realm_create(struct realm *realm)
 {
 	struct rmi_realm_params *params;
 	u_register_t ret;
-	unsigned int count;
+	unsigned int count, rtt_page_count = 0U;
 
 	realm->par_size = REALM_MAX_LOAD_IMG_SIZE;
 
@@ -724,11 +1076,16 @@
 		}
 	}
 
+	assert(realm->num_aux_planes <= MAX_AUX_PLANE_COUNT);
+
 	/*
-	 * Allocate memory for PAR - Realm image. Granule delegation
+	 * Allocate memory for PAR - Realm image for each Plane.
+	 * Granule delegation
 	 * of PAR will be performed during rtt creation.
 	 */
-	realm->par_base = (u_register_t)page_alloc(realm->par_size);
+	realm->par_base = (u_register_t)page_alloc((realm->par_size) *
+			(realm->num_aux_planes + 1U));
+
 	if (realm->par_base == HEAP_NULL_PTR) {
 		ERROR("page_alloc failed, base=0x%lx, size=0x%lx\n",
 			  realm->par_base, realm->par_size);
@@ -737,6 +1094,15 @@
 
 	INFO("Realm start adr=0x%lx\n", realm->par_base);
 
+	/* Allocate memory for params */
+	params = (struct rmi_realm_params *)page_alloc(PAGE_SIZE);
+	if (params == NULL) {
+		ERROR("Failed to allocate memory for params\n");
+		goto pool_reset;
+	}
+
+	memset(params, 0, PAGE_SIZE);
+
 	/* Allocate and delegate RD */
 	realm->rd = (u_register_t)page_alloc(PAGE_SIZE);
 	if (realm->rd == HEAP_NULL_PTR) {
@@ -752,24 +1118,39 @@
 	}
 
 	/* Allocate and delegate RTT */
-	realm->rtt_addr = (u_register_t)page_alloc(PAGE_SIZE);
+	if (realm->rtt_tree_single) {
+		rtt_page_count = 1U;
+	} else {
+		/* Primary + AUX RTT Tree */
+		rtt_page_count = (realm->num_aux_planes + 1U);
+	}
+
+	realm->rtt_addr = (u_register_t)page_alloc(rtt_page_count * PAGE_SIZE);
+
 	if (realm->rtt_addr == HEAP_NULL_PTR) {
 		ERROR("Failed to allocate memory for rtt_addr\n");
 		goto err_undelegate_rd;
 	} else {
-		ret = host_rmi_granule_delegate(realm->rtt_addr);
-		if (ret != RMI_SUCCESS) {
-			ERROR("%s() failed, rtt_addr=0x%lx ret=0x%lx\n",
-				"host_rmi_granule_delegate", realm->rtt_addr, ret);
-			goto err_free_rtt;
-		}
-	}
+		for (unsigned int i = 0U; i < rtt_page_count; i++) {
+			ret = host_rmi_granule_delegate(realm->rtt_addr + (i * PAGE_SIZE));
 
-	/* Allocate memory for params */
-	params = (struct rmi_realm_params *)page_alloc(PAGE_SIZE);
-	if (params == NULL) {
-		ERROR("Failed to allocate memory for params\n");
-		goto err_undelegate_rtt;
+			if (ret != RMI_SUCCESS) {
+				ERROR("%s() failed, rtt_addr=0x%lx ret=0x%lx\n",
+				"host_rmi_granule_delegate", realm->rtt_addr, ret);
+
+				for (unsigned int j = 0U; j < i; j++) {
+					host_rmi_granule_undelegate(realm->rtt_addr
+							+ (i * PAGE_SIZE));
+				}
+
+				goto err_free_rtt;
+			}
+
+			if (i > 0U && !realm->rtt_tree_single) {
+				realm->aux_rtt_addr[i - 1] = realm->rtt_addr + (i * PAGE_SIZE);
+				params->aux_rtt_base[i - 1] = realm->rtt_addr + (i * PAGE_SIZE);
+			}
+		}
 	}
 
 	/* Populate params */
@@ -780,16 +1161,16 @@
 
 	/* SVE enable and vector length */
 	if ((realm->rmm_feat_reg0 & RMI_FEATURE_REGISTER_0_SVE_EN) != 0UL) {
-		params->flags = RMI_REALM_FLAGS_SVE;
+		params->flags0 = RMI_REALM_FLAGS0_SVE;
 		params->sve_vl = realm->sve_vl;
 	} else {
-		params->flags = 0UL;
+		params->flags0 = 0UL;
 		params->sve_vl = 0U;
 	}
 
 	/* PMU enable and number of event counters */
 	if ((realm->rmm_feat_reg0 & RMI_FEATURE_REGISTER_0_PMU_EN) != 0UL) {
-		params->flags |= RMI_REALM_FLAGS_PMU;
+		params->flags0 |= RMI_REALM_FLAGS0_PMU;
 		params->pmu_num_ctrs = realm->pmu_num_ctrs;
 	} else {
 		params->pmu_num_ctrs = 0U;
@@ -797,21 +1178,32 @@
 
 	/* LPA2 enable */
 	if ((realm->rmm_feat_reg0 & RMI_FEATURE_REGISTER_0_LPA2) != 0UL) {
-		params->flags |= RMI_REALM_FLAGS_LPA2;
+		params->flags0 |= RMI_REALM_FLAGS0_LPA2;
 	}
 
 	params->rtt_level_start = realm->start_level;
-	params->hash_algo = RMI_HASH_SHA_256;
+	params->algorithm = RMI_HASH_SHA_256;
 	params->vmid = vmid++;
 	params->rtt_base = realm->rtt_addr;
 	params->rtt_num_start = 1U;
 
+	if (!realm->rtt_tree_single) {
+		params->flags1 = RMI_REALM_FLAGS1_RTT_TREE_PP;
+	}
+	params->num_aux_planes = realm->num_aux_planes;
+
+	/* Allocate VMID for all planes */
+	for (unsigned int i = 0U; i < realm->num_aux_planes; i++) {
+		params->aux_vmid[i] = (unsigned short)(vmid++);
+		realm->aux_vmid[i] = params->aux_vmid[i];
+	}
+
 	/* Create Realm */
 	ret = host_rmi_realm_create(realm->rd, (u_register_t)params);
 	if (ret != RMI_SUCCESS) {
 		ERROR("%s() failed, rd=0x%lx ret=0x%lx\n",
 			"host_rmi_realm_create", realm->rd, ret);
-		goto err_free_params;
+		goto err_free_vmid;
 	}
 
 	realm->vmid = params->vmid;
@@ -820,7 +1212,7 @@
 		ERROR("%s() failed, rd=0x%lx ret=0x%lx\n",
 			"host_rmi_rec_aux_count", realm->rd, ret);
 		host_rmi_realm_destroy(realm->rd);
-		goto err_free_params;
+		goto err_free_vmid;
 	}
 
 	realm->state = REALM_STATE_NEW;
@@ -829,14 +1221,10 @@
 	page_free((u_register_t)params);
 	return REALM_SUCCESS;
 
-err_free_params:
-	page_free((u_register_t)params);
-
-err_undelegate_rtt:
-	ret = host_rmi_granule_undelegate(realm->rtt_addr);
-	if (ret != RMI_SUCCESS) {
-		WARN("%s() failed, rtt_addr=0x%lx ret=0x%lx\n",
-			"host_rmi_granule_undelegate", realm->rtt_addr, ret);
+err_free_vmid:
+	/* Free VMID */
+	for (unsigned int i = 0U; i <= realm->num_aux_planes; i++) {
+		vmid--;
 	}
 
 err_free_rtt:
@@ -848,9 +1236,20 @@
 		WARN("%s() failed, rd=0x%lx ret=0x%lx\n",
 			"host_rmi_granule_undelegate", realm->rd, ret);
 	}
+
 err_free_rd:
 	page_free(realm->rd);
 
+	page_free((u_register_t)params);
+
+	for (unsigned int i = 0U; i < rtt_page_count; i++) {
+		ret = host_rmi_granule_undelegate(realm->rtt_addr + (i * PAGE_SIZE));
+		if (ret != RMI_SUCCESS) {
+			WARN("%s() failed, rtt_addr=0x%lx ret=0x%lx\n",
+			"host_rmi_granule_undelegate", realm->rtt_addr + (i * PAGE_SIZE), ret);
+		}
+	}
+
 err_free_par:
 	page_free(realm->par_base);
 
@@ -873,22 +1272,23 @@
 					  u_register_t realm_payload_adr)
 {
 	u_register_t src_pa = realm_payload_adr;
-	u_register_t i = 0UL;
 	u_register_t ret;
 
 	/* MAP image regions */
-	while (i < (realm->par_size / PAGE_SIZE)) {
+	/* Copy Plane 0-N Images */
+
+	for (unsigned int j = 0U; j <= realm->num_aux_planes; j++) {
 		ret = host_realm_delegate_map_protected_data(false, realm,
-						realm->par_base + i * PAGE_SIZE,
-						PAGE_SIZE,
-						src_pa + i * PAGE_SIZE);
+					realm->par_base + (j * realm->par_size),
+					realm->par_size,
+					src_pa);
+
 		if (ret != RMI_SUCCESS) {
-			ERROR("%s() failed, par_base=0x%lx ret=0x%lx\n",
-				"host_realm_delegate_map_protected_data",
-				realm->par_base, ret);
+			ERROR("%s() failed par_base=0x%lx size=0x%lx j=%u ret=0x%lx\n",
+			"host_realm_delegate_map_protected_data",
+			realm->par_base, realm->par_size, j, ret);
 			return REALM_ERROR;
 		}
-		i++;
 	}
 
 	return REALM_SUCCESS;
@@ -1129,6 +1529,7 @@
 u_register_t host_realm_destroy(struct realm *realm)
 {
 	u_register_t ret;
+	unsigned int rtt_page_count;
 	long rtt_start_level = realm->start_level;
 
 	if (realm->state == REALM_STATE_NULL) {
@@ -1207,11 +1608,24 @@
 		return REALM_ERROR;
 	}
 
-	ret = host_rmi_granule_undelegate(realm->rtt_addr);
-	if (ret != RMI_SUCCESS) {
-		ERROR("%s() failed, rtt_addr=0x%lx ret=0x%lx\n",
-			"host_rmi_granule_undelegate", realm->rtt_addr, ret);
-		return REALM_ERROR;
+	if (realm->rtt_tree_single) {
+		rtt_page_count = 1U;
+	} else {
+		rtt_page_count = realm->num_aux_planes + 1U;
+	}
+
+	for (unsigned int i = 0U; i < rtt_page_count; i++) {
+		ret = host_rmi_granule_undelegate(realm->rtt_addr + (i * PAGE_SIZE));
+		if (ret != RMI_SUCCESS) {
+			ERROR("%s() failed, rtt_addr=0x%lx ret=0x%lx\n",
+			"host_rmi_granule_undelegate", realm->rtt_addr + (i * PAGE_SIZE), ret);
+			return REALM_ERROR;
+		}
+	}
+
+	/* Free VMID */
+	for (unsigned int i = 0U; i <= realm->num_aux_planes; i++) {
+		vmid--;
 	}
 
 	page_free(realm->rd);
@@ -1299,3 +1713,55 @@
 	*exit_reason = run->exit.exit_reason;
 	return ret;
 }
+
+u_register_t host_rmi_pdev_aux_count(u_register_t pdev_ptr, u_register_t *count)
+{
+	smc_ret_values rets;
+
+	rets = host_rmi_handler(&(smc_args) {SMC_RMI_PDEV_AUX_COUNT, pdev_ptr},
+				2U);
+	*count = rets.ret1;
+	return rets.ret0;
+}
+
+u_register_t host_rmi_pdev_create(u_register_t pdev_ptr, u_register_t params_ptr)
+{
+	return host_rmi_handler(&(smc_args) {SMC_RMI_PDEV_CREATE, pdev_ptr,
+					     params_ptr}, 3U).ret0;
+}
+
+u_register_t host_rmi_pdev_get_state(u_register_t pdev_ptr, u_register_t *state)
+{
+	smc_ret_values rets;
+
+	rets = host_rmi_handler(&(smc_args) {SMC_RMI_PDEV_GET_STATE, pdev_ptr},
+				2U);
+	*state = rets.ret1;
+	return rets.ret0;
+}
+
+u_register_t host_rmi_pdev_communicate(u_register_t pdev_ptr,
+				       u_register_t data_ptr)
+{
+	return host_rmi_handler(&(smc_args) {SMC_RMI_PDEV_COMMUNICATE, pdev_ptr,
+						data_ptr}, 3U).ret0;
+}
+
+u_register_t host_rmi_pdev_set_pubkey(u_register_t pdev_ptr, u_register_t key,
+				      u_register_t len, uint8_t algo)
+{
+	return host_rmi_handler(&(smc_args) {SMC_RMI_PDEV_SET_PUBKEY, pdev_ptr,
+						key, len, algo}, 5U).ret0;
+}
+
+u_register_t host_rmi_pdev_stop(u_register_t pdev_ptr)
+{
+	return host_rmi_handler(&(smc_args) {SMC_RMI_PDEV_STOP, pdev_ptr},
+				2U).ret0;
+}
+
+u_register_t host_rmi_pdev_destroy(u_register_t pdev_ptr)
+{
+	return host_rmi_handler(&(smc_args) {SMC_RMI_PDEV_DESTROY, pdev_ptr},
+				2U).ret0;
+}
diff --git a/tftf/tests/runtime_services/host_realm_managment/host_rmi_pdev.c b/tftf/tests/runtime_services/host_realm_managment/host_rmi_pdev.c
new file mode 100644
index 0000000..c43c374
--- /dev/null
+++ b/tftf/tests/runtime_services/host_realm_managment/host_rmi_pdev.c
@@ -0,0 +1,580 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <heap/page_alloc.h>
+#include <host_crypto_utils.h>
+#include <host_realm_helper.h>
+#include <host_realm_mem_layout.h>
+#include <host_shared_data.h>
+#include <mmio.h>
+#include <pcie.h>
+#include <pcie_doe.h>
+#include <pcie_spec.h>
+#include <platform.h>
+#include <spdm.h>
+#include <test_helpers.h>
+
+/* SPDM_MAX_CERTIFICATE_CHAIN_SIZE is 64KB */
+#define HOST_PDEV_CERT_LEN_MAX		(64 * 1024)
+
+/*
+ * Measurement max supported is 4KB.
+ * todo: This will be increased if device supports returning more measurements
+ */
+#define HOST_PDEV_MEAS_LEN_MAX		(4 * 1024)
+
+#define DEV_OBJ_CERT			0U
+#define DEV_OBJ_MEASUREMENTS		2U
+#define DEV_OBJ_INTERFACE_REPORT	3U
+
+struct host_tdi {
+	/* PDEV related fields */
+	void *pdev;
+	unsigned long pdev_flags;
+	void *pdev_aux[PDEV_PARAM_AUX_GRANULES_MAX];
+	uint32_t pdev_aux_num;
+	struct rmi_dev_comm_data *dev_comm_data;
+
+	/* Algorithm used to generate device digests */
+	uint8_t pdev_hash_algo;
+
+	/* Certificate, public key fields */
+	uint8_t cert_slot_id;
+	uint8_t *cert_chain;
+	size_t cert_chain_len;
+	void *public_key;
+	size_t public_key_len;
+	void *public_key_metadata;
+	size_t public_key_metadata_len;
+	unsigned char public_key_sig_algo;
+
+	/*
+	 * Fields related to cached device measurements.
+	 * todo: This will be moved to vdev scope
+	 */
+	uint8_t *meas;
+	size_t meas_len;
+
+	/* PCIe details: bdf, DOE, Stream id, IO range */
+	uint32_t bdf;
+	uint32_t doe_cap_base;
+};
+
+static struct host_tdi g_tdi;
+
+static const char * const pdev_state_str[] = {
+	"PDEV_STATE_NEW",
+	"PDEV_STATE_NEEDS_KEY",
+	"PDEV_STATE_HAS_KEY",
+	"PDEV_STATE_READY",
+	"PDEV_STATE_COMMUNICATING",
+	"PDEV_STATE_STOPPED",
+	"RMI_PDEV_STATE_ERROR"
+};
+
+static int host_tdi_pdev_get_state(struct host_tdi *tdi, u_register_t *state)
+{
+	u_register_t ret;
+
+	ret = host_rmi_pdev_get_state((u_register_t)tdi->pdev, state);
+	if (ret != RMI_SUCCESS) {
+		return -1;
+	}
+	return 0;
+}
+
+static bool is_host_tdi_pdev_state(struct host_tdi *tdi, u_register_t exp_state)
+{
+	u_register_t cur_state;
+
+	if (host_tdi_pdev_get_state(tdi, &cur_state) != 0) {
+		return false;
+	}
+
+	if (cur_state != exp_state) {
+		return false;
+	}
+
+	return true;
+}
+
+static int host_tdi_pdev_create(struct host_tdi *tdi)
+{
+	struct rmi_pdev_params *pdev_params;
+	u_register_t ret;
+	uint32_t i;
+
+	pdev_params = (struct rmi_pdev_params *)page_alloc(PAGE_SIZE);
+	memset(pdev_params, 0, GRANULE_SIZE);
+
+	pdev_params->flags = tdi->pdev_flags;
+	pdev_params->cert_id = tdi->cert_slot_id;
+	pdev_params->pdev_id = tdi->bdf;
+	pdev_params->num_aux = tdi->pdev_aux_num;
+	pdev_params->hash_algo = tdi->pdev_hash_algo;
+	for (i = 0; i < tdi->pdev_aux_num; i++) {
+		pdev_params->aux[i] = (uintptr_t)tdi->pdev_aux[i];
+	}
+
+	ret = host_rmi_pdev_create((u_register_t)tdi->pdev,
+				   (u_register_t)pdev_params);
+	if (ret != RMI_SUCCESS) {
+		return -1;
+	}
+
+	return 0;
+}
+
+static int host_tdi_pdev_set_pubkey(struct host_tdi *tdi)
+{
+	u_register_t ret;
+
+	ret = host_rmi_pdev_set_pubkey((u_register_t)tdi->pdev,
+				       (u_register_t)tdi->public_key,
+				       (u_register_t)tdi->public_key_len,
+				       (u_register_t)tdi->public_key_sig_algo);
+	if (ret != RMI_SUCCESS) {
+		return -1;
+	}
+
+	return 0;
+}
+
+static int host_tdi_pdev_stop(struct host_tdi *tdi)
+{
+	u_register_t ret;
+
+	ret = host_rmi_pdev_stop((u_register_t)tdi->pdev);
+	if (ret != RMI_SUCCESS) {
+		return -1;
+	}
+
+	return 0;
+}
+
+static int host_tdi_pdev_destroy(struct host_tdi *tdi)
+{
+	u_register_t ret;
+
+	ret = host_rmi_pdev_destroy((u_register_t)tdi->pdev);
+	if (ret != RMI_SUCCESS) {
+		return -1;
+	}
+
+	return 0;
+}
+
+static int host_tdi_pdev_cache_device_object(struct host_tdi *tdi,
+					     uint8_t obj_type,
+					     const uint8_t *obj_buf,
+					     size_t obj_len)
+{
+	int rc = -1;
+
+	if (obj_type == DEV_OBJ_CERT) {
+		if ((tdi->cert_chain_len + obj_len) > HOST_PDEV_CERT_LEN_MAX) {
+			return -1;
+		}
+
+		INFO("%s: cache_cert: offset: 0x%lx, len: 0x%lx\n",
+		     __func__, tdi->cert_chain_len, obj_len);
+
+		memcpy((void *)(tdi->cert_chain + tdi->cert_chain_len),
+		       obj_buf, obj_len);
+		tdi->cert_chain_len += obj_len;
+		rc = 0;
+	} else if (obj_type == DEV_OBJ_MEASUREMENTS) {
+		if ((tdi->meas_len + obj_len) > HOST_PDEV_MEAS_LEN_MAX) {
+			return -1;
+		}
+
+		INFO("%s: cache_meas: offset: 0x%lx, len: 0x%lx\n",
+		     __func__, tdi->meas_len, obj_len);
+
+		memcpy((void *)(tdi->meas + tdi->meas_len), obj_buf, obj_len);
+		tdi->meas_len += obj_len;
+		rc = 0;
+	}
+
+	return rc;
+}
+
+/* Call RMI PDEV communicate until the target state is reached */
+static int host_tdi_pdev_communicate(struct host_tdi *tdi,
+				     unsigned char target_state)
+{
+	int rc;
+	u_register_t state;
+	u_register_t ret;
+	struct rmi_dev_comm_enter *dev_comm_enter;
+	struct rmi_dev_comm_exit *dev_comm_exit;
+	size_t resp_len;
+
+	dev_comm_enter = &tdi->dev_comm_data->enter;
+	dev_comm_exit = &tdi->dev_comm_data->exit;
+
+	dev_comm_enter->status = RMI_DEV_COMM_ENTER_STATUS_NONE;
+	dev_comm_enter->resp_len = 0;
+
+	if (host_tdi_pdev_get_state(tdi, &state) != 0) {
+		return -1;
+	}
+
+	do {
+		ret = host_rmi_pdev_communicate((u_register_t)tdi->pdev,
+					(u_register_t)tdi->dev_comm_data);
+		if (ret != RMI_SUCCESS) {
+			INFO("rmi_pdev_communicate failed\n");
+			rc = -1;
+			break;
+		}
+
+		/*
+		 * If cache is set, then response buffer has the device object
+		 * to be cached.
+		 */
+		if (EXTRACT(RMI_DEV_COMM_EXIT_FLAGS_CACHE,
+			    dev_comm_exit->flags)) {
+			uint8_t *obj_buf;
+			uint8_t obj_type;
+
+			if (dev_comm_exit->cache_len == 0 ||
+			    (dev_comm_exit->cache_offset +
+			     dev_comm_exit->cache_len) >
+			    GRANULE_SIZE) {
+				INFO("Invalid cache offset/length\n");
+				rc = -1;
+				break;
+			}
+
+			if (state == RMI_PDEV_STATE_NEW) {
+				obj_type = DEV_OBJ_CERT;
+			} else if (state == RMI_PDEV_STATE_HAS_KEY) {
+				/* todo: replace with RMI_PDEV_STATE_READY */
+				obj_type = DEV_OBJ_MEASUREMENTS;
+			} else {
+				rc = -1;
+				break;
+			}
+
+			obj_buf = (uint8_t *)dev_comm_enter->resp_addr +
+				dev_comm_exit->cache_offset;
+			rc = host_tdi_pdev_cache_device_object(tdi, obj_type,
+							       obj_buf,
+						       dev_comm_exit->cache_len);
+			if (rc != 0) {
+				INFO("host_pdev_cache_device_object failed\n");
+				rc = -1;
+				break;
+			}
+		}
+
+		/* Send request to spdm responder */
+		if (EXTRACT(RMI_DEV_COMM_EXIT_FLAGS_SEND,
+			    dev_comm_exit->flags)) {
+			uint32_t doe_header;
+
+			/* todo: validate DevCommExit flags */
+			if (dev_comm_exit->protocol ==
+			    RMI_DEV_COMM_PROTOCOL_SPDM) {
+				doe_header = DOE_HEADER_1;
+			} else if (dev_comm_exit->protocol ==
+				   RMI_DEV_COMM_PROTOCOL_SECURE_SPDM) {
+				doe_header = DOE_HEADER_2;
+			} else {
+				INFO("Invalid dev_comm_exit.protocol\n");
+				rc = -1;
+				break;
+			}
+
+			rc = pcie_doe_communicate(doe_header, tdi->bdf, tdi->doe_cap_base,
+					  (void *)dev_comm_enter->req_addr,
+						  dev_comm_exit->req_len,
+					(void *)dev_comm_enter->resp_addr,
+						  &resp_len);
+
+			/*
+			 * Set IoEnter args for next pdev_communicate. Upon
+			 * success or error call pdev_communicate
+			 */
+			if (rc == 0) {
+				dev_comm_enter->status =
+					RMI_DEV_COMM_ENTER_STATUS_SUCCESS;
+				dev_comm_enter->resp_len = resp_len;
+			} else {
+				dev_comm_enter->status =
+					RMI_DEV_COMM_ENTER_STATUS_ERROR;
+				dev_comm_enter->resp_len = 0;
+			}
+		}
+
+		rc = host_tdi_pdev_get_state(tdi, &state);
+		if (rc != 0) {
+			break;
+		}
+	} while ((state != target_state) && (state != RMI_PDEV_STATE_ERROR));
+
+	return rc;
+}
+
+/*
+ * Invoke RMI handler to transition PDEV state to 'to_state'
+ */
+static int host_tdi_pdev_transition(struct host_tdi *tdi, unsigned char to_state)
+{
+	int rc;
+
+	switch (to_state) {
+	case RMI_PDEV_STATE_NEW:
+		rc = host_tdi_pdev_create(tdi);
+		break;
+	case RMI_PDEV_STATE_NEEDS_KEY:
+		rc = host_tdi_pdev_communicate(tdi, RMI_PDEV_STATE_NEEDS_KEY);
+		break;
+	case RMI_PDEV_STATE_HAS_KEY:
+		rc = host_tdi_pdev_set_pubkey(tdi);
+		break;
+	case RMI_PDEV_STATE_READY:
+		rc = host_tdi_pdev_communicate(tdi, RMI_PDEV_STATE_READY);
+		break;
+	case RMI_PDEV_STATE_STOPPING:
+		rc = host_tdi_pdev_stop(tdi);
+		break;
+	case RMI_PDEV_STATE_STOPPED:
+		rc = host_tdi_pdev_communicate(tdi, RMI_PDEV_STATE_STOPPED);
+		break;
+	default:
+		rc = -1;
+	}
+
+	if (rc != 0) {
+		INFO("RMI command failed\n");
+		return -1;
+	}
+
+	if (!is_host_tdi_pdev_state(tdi, to_state)) {
+		ERROR("PDEV state not [%s]\n", pdev_state_str[to_state]);
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * Allocate granules needed for a PDEV object like device communication data,
+ * response buffer, PDEV AUX granules and memory required to store cert_chain
+ */
+static int host_tdi_pdev_setup(struct host_tdi *tdi)
+{
+	u_register_t ret, count;
+	int i;
+
+	memset(tdi, 0, sizeof(struct host_tdi));
+
+	/* Allocate granule for PDEV and delegate */
+	tdi->pdev = page_alloc(PAGE_SIZE);
+	memset(tdi->pdev, 0, GRANULE_SIZE);
+	ret = host_rmi_granule_delegate((u_register_t)tdi->pdev);
+	if (ret != RMI_SUCCESS) {
+		ERROR("PDEV delegate failed 0x%lx\n", ret);
+		return -1;
+	}
+
+	/* Set flags as IO coherent device protected by end to end IDE. */
+	tdi->pdev_flags = INPLACE(RMI_PDEV_FLAGS_PROT_CONFIG,
+				  RMI_PDEV_IOCOH_E2E_IDE);
+
+	/* Get num of aux granules required for this PDEV */
+	ret = host_rmi_pdev_aux_count(tdi->pdev_flags, &count);
+	if (ret != RMI_SUCCESS) {
+		ERROR("host_rmi_pdev_aux_count() failed 0x%lx\n", ret);
+		return -1;
+	}
+	tdi->pdev_aux_num = count;
+
+	/* Allocate aux granules for PDEV and delegate */
+	INFO("PDEV create requires %u aux pages\n", tdi->pdev_aux_num);
+	for (i = 0; i < tdi->pdev_aux_num; i++) {
+		tdi->pdev_aux[i] = page_alloc(PAGE_SIZE);
+		ret = host_rmi_granule_delegate((u_register_t)tdi->pdev_aux[i]);
+		if (ret != RMI_SUCCESS) {
+			ERROR("Aux granule delegate failed 0x%lx\n", ret);
+			return -1;
+		}
+	}
+
+	/* Allocate dev_comm_data and send/recv buffer for Dev communication */
+	tdi->dev_comm_data = (struct rmi_dev_comm_data *)page_alloc(PAGE_SIZE);
+	memset(tdi->dev_comm_data, 0, sizeof(struct rmi_dev_comm_data));
+	tdi->dev_comm_data->enter.req_addr = (unsigned long)
+		page_alloc(PAGE_SIZE);
+	tdi->dev_comm_data->enter.resp_addr = (unsigned long)
+		page_alloc(PAGE_SIZE);
+
+	/* Allocate buffer to cache device certificate */
+	tdi->cert_slot_id = 0;
+	tdi->cert_chain = (uint8_t *)page_alloc(HOST_PDEV_CERT_LEN_MAX);
+	tdi->cert_chain_len = 0;
+	if (tdi->cert_chain == NULL) {
+		return -1;
+	}
+
+	/* Allocate buffer to store extracted public key */
+	tdi->public_key = (void *)page_alloc(PAGE_SIZE);
+	if (tdi->public_key == NULL) {
+		return -1;
+	}
+	tdi->public_key_len = PAGE_SIZE;
+
+	/* Allocate buffer to store public key metadata */
+	tdi->public_key_metadata = (void *)page_alloc(PAGE_SIZE);
+	if (tdi->public_key_metadata == NULL) {
+		return -1;
+	}
+	tdi->public_key_metadata_len = PAGE_SIZE;
+
+	/* Allocate buffer to cache device measurements */
+	tdi->meas = (uint8_t *)page_alloc(HOST_PDEV_MEAS_LEN_MAX);
+	tdi->meas_len = 0;
+	if (tdi->meas == NULL) {
+		return -1;
+	}
+
+	/* Set algorithm to use for device digests */
+	tdi->pdev_hash_algo = RMI_HASH_SHA_512;
+
+	return 0;
+}
+
+/*
+ * Stop PDEV and ternimate secure session and call PDEV destroy
+ */
+static int host_tdi_pdev_reclaim(struct host_tdi *tdi)
+{
+	int rc;
+
+	/* Move the device to STOPPING state */
+	rc = host_tdi_pdev_transition(tdi, RMI_PDEV_STATE_STOPPING);
+	if (rc != 0) {
+		INFO("PDEV transition: to PDEV_STATE_STOPPING failed\n");
+		return -1;
+	}
+
+	/* Do pdev_communicate to terminate secure session */
+	rc = host_tdi_pdev_transition(tdi, RMI_PDEV_STATE_STOPPED);
+	if (rc != 0) {
+		INFO("PDEV transition: to PDEV_STATE_STOPPED failed\n");
+		return -1;
+	}
+
+	rc = host_tdi_pdev_destroy(tdi);
+	if (rc != 0) {
+		INFO("PDEV transition: to STATE_NULL failed\n");
+		return -1;
+	}
+
+	/* Undelegate all the delegated pages */
+	for (int i = 0; i < tdi->pdev_aux_num; i++) {
+		host_rmi_granule_undelegate((u_register_t)tdi->pdev_aux[i]);
+	}
+	host_rmi_granule_undelegate((u_register_t)tdi->pdev);
+
+	return rc;
+}
+
+/*
+ * This invokes various RMI calls related to PDEV management that does
+ * PDEV create/communicate/set_key/abort/stop/destroy on a device.
+ */
+test_result_t host_test_rmi_pdev_calls(void)
+{
+	u_register_t rmi_feat_reg0;
+	uint32_t pdev_bdf, doe_cap_base;
+	struct host_tdi *tdi;
+	uint8_t public_key_algo;
+	int ret, rc;
+
+	CHECK_DA_SUPPORT_IN_RMI(rmi_feat_reg0);
+	SKIP_TEST_IF_DOE_NOT_SUPPORTED(pdev_bdf, doe_cap_base);
+
+	/* Initialize Host NS heap memory */
+	ret = page_pool_init((u_register_t)PAGE_POOL_BASE,
+				(u_register_t)PAGE_POOL_MAX_SIZE);
+	if (ret != HEAP_INIT_SUCCESS) {
+		ERROR("Failed to init heap pool %d\n", ret);
+		return TEST_RESULT_FAIL;
+	}
+
+	tdi = &g_tdi;
+
+	/* Allocate granules. Skip DA ABIs if host_pdev_setup fails */
+	rc = host_tdi_pdev_setup(tdi);
+	if (rc == -1) {
+		INFO("host_pdev_setup failed. skipping DA ABIs...\n");
+		return TEST_RESULT_SKIPPED;
+	}
+
+	/* todo: move to tdi_pdev_setup */
+	tdi->bdf = pdev_bdf;
+	tdi->doe_cap_base = doe_cap_base;
+
+	/* Call rmi_pdev_create to transition PDEV to STATE_NEW */
+	rc = host_tdi_pdev_transition(tdi, RMI_PDEV_STATE_NEW);
+	if (rc != 0) {
+		ERROR("PDEV transition: NULL -> STATE_NEW failed\n");
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Call rmi_pdev_communicate to transition PDEV to NEEDS_KEY */
+	rc = host_tdi_pdev_transition(tdi, RMI_PDEV_STATE_NEEDS_KEY);
+	if (rc != 0) {
+		ERROR("PDEV transition: PDEV_NEW -> PDEV_NEEDS_KEY failed\n");
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Get public key. Verifying cert_chain not done by host but by Realm? */
+	rc = host_get_public_key_from_cert_chain(tdi->cert_chain,
+						 tdi->cert_chain_len,
+						 tdi->public_key,
+						 &tdi->public_key_len,
+						 tdi->public_key_metadata,
+						 &tdi->public_key_metadata_len,
+						 &public_key_algo);
+	if (rc != 0) {
+		ERROR("Get public key failed\n");
+		return TEST_RESULT_FAIL;
+	}
+
+	if (public_key_algo == PUBLIC_KEY_ALGO_ECDSA_ECC_NIST_P256) {
+		tdi->public_key_sig_algo = RMI_SIGNATURE_ALGORITHM_ECDSA_P256;
+	} else if (public_key_algo == PUBLIC_KEY_ALGO_ECDSA_ECC_NIST_P384) {
+		tdi->public_key_sig_algo = RMI_SIGNATURE_ALGORITHM_ECDSA_P384;
+	} else {
+		tdi->public_key_sig_algo = RMI_SIGNATURE_ALGORITHM_RSASSA_3072;
+	}
+	INFO("DEV public key len/sig_algo: %ld/%d\n", tdi->public_key_len,
+	     tdi->public_key_sig_algo);
+
+	/* Call rmi_pdev_set_key transition PDEV to HAS_KEY */
+	rc = host_tdi_pdev_transition(tdi, RMI_PDEV_STATE_HAS_KEY);
+	if (rc != 0) {
+		INFO("PDEV transition: PDEV_NEEDS_KEY -> PDEV_HAS_KEY failed\n");
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Call rmi_pdev_comminucate to transition PDEV to READY state */
+	rc = host_tdi_pdev_transition(tdi, RMI_PDEV_STATE_READY);
+	if (rc != 0) {
+		INFO("PDEV transition: PDEV_HAS_KEY -> PDEV_READY failed\n");
+		return TEST_RESULT_FAIL;
+	}
+
+	host_tdi_pdev_reclaim(tdi);
+
+	return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_lpa2_tests.c b/tftf/tests/runtime_services/realm_payload/host_realm_lpa2_tests.c
index 34c684c..43d9f01 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_lpa2_tests.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_lpa2_tests.c
@@ -22,7 +22,7 @@
 	SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
 
 	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			0UL, RTT_MIN_LEVEL_LPA2, rec_flag, 1U)) {
+			0UL, RTT_MIN_LEVEL_LPA2, rec_flag, 1U, 0U)) {
 		return TEST_RESULT_SUCCESS;
 	}
 
@@ -41,7 +41,7 @@
 
 	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
 			INPLACE(RMI_FEATURE_REGISTER_0_S2SZ, 50UL),
-			RTT_MIN_LEVEL, rec_flag, 1U)) {
+			RTT_MIN_LEVEL, rec_flag, 1U, 0U)) {
 		return TEST_RESULT_SUCCESS;
 	}
 
@@ -67,7 +67,7 @@
 
 	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
 			INPLACE(RMI_FEATURE_REGISTER_0_S2SZ, 48UL),
-			RTT_MIN_LEVEL, rec_flag, 1U)) {
+			RTT_MIN_LEVEL, rec_flag, 1U, 0U)) {
 		return TEST_RESULT_FAIL;
 	}
 
@@ -80,6 +80,62 @@
 }
 
 /*
+ * @Test_Aim@ Create a Realm with LPA2 disabled but FEAT_LPA2 present
+ * on the platform.
+ * Test that RMI_RTT_MAP_UNPROTECTED and RMI_RTT_CREATE commands fails if PA >= 48 bits
+ */
+test_result_t host_test_data_bound_non_lpa2_realm_on_lpa2plat(void)
+{
+	u_register_t rec_flag[1] = {RMI_RUNNABLE};
+	struct realm realm;
+	u_register_t ret, base, base_ipa;
+	test_result_t result = TEST_RESULT_FAIL;
+
+	SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+
+	if (is_feat_52b_on_4k_2_supported() == false) {
+		return TEST_RESULT_SKIPPED;
+	}
+
+	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
+			INPLACE(RMI_FEATURE_REGISTER_0_S2SZ, 48UL),
+			RTT_MIN_LEVEL, rec_flag, 1U, 0U)) {
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Can choose any unprotected IPA adr, TFTF_BASE chosen for convenience */
+	base = TFTF_BASE;
+	base = base | (1UL << 48UL);
+
+	ret = host_realm_map_unprotected(&realm, base, PAGE_SIZE);
+
+	if (ret == REALM_SUCCESS) {
+		ERROR("host_realm_map_unprotected should have failed\n");
+		goto destroy_realm;
+	}
+
+	base_ipa = base | (1UL <<
+			(EXTRACT(RMI_FEATURE_REGISTER_0_S2SZ, realm.rmm_feat_reg0) - 1UL));
+
+	ret = host_rmi_create_rtt_levels(&realm, base_ipa, RTT_MIN_LEVEL, 3);
+
+	if (ret == REALM_SUCCESS) {
+		ERROR("host_rmi_create_rtt_levels should have failed\n");
+		goto destroy_realm;
+	}
+
+	result = TEST_RESULT_SUCCESS;
+
+destroy_realm:
+	if (!host_destroy_realm(&realm)) {
+		ERROR("%s(): failed to destroy realm\n", __func__);
+		return TEST_RESULT_FAIL;
+	}
+
+	return result;
+}
+
+/*
  * @Test_Aim@ Test creating a Realm payload with LPA2 enabled on a platform
  * which does not implement FEAT_LPA2.
  * Realm creation must fail.
@@ -99,7 +155,7 @@
 	}
 
 	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, RTT_MIN_LEVEL, rec_flag, 1U)) {
+			feature_flag, RTT_MIN_LEVEL, rec_flag, 1U, 0U)) {
 		return TEST_RESULT_SUCCESS;
 	}
 
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_payload_multiple_rec_tests.c b/tftf/tests/runtime_services/realm_payload/host_realm_payload_multiple_rec_tests.c
index e3ee23b..151e871 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_payload_multiple_rec_tests.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_payload_multiple_rec_tests.c
@@ -47,7 +47,7 @@
 	}
 
 	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, MAX_REC_COUNT)) {
+			feature_flag, sl, rec_flag, MAX_REC_COUNT, 0U)) {
 		return TEST_RESULT_FAIL;
 	}
 
@@ -112,7 +112,7 @@
 	}
 
 	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, 3U)) {
+			feature_flag, sl, rec_flag, 3U, 0U)) {
 		return TEST_RESULT_FAIL;
 	}
 
@@ -257,7 +257,7 @@
 	}
 
 	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, rec_count)) {
+			feature_flag, sl, rec_flag, rec_count, 0U)) {
 		return TEST_RESULT_FAIL;
 	}
 
@@ -361,7 +361,7 @@
 	}
 
 	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, rec_count)) {
+			feature_flag, sl, rec_flag, rec_count, 0U)) {
 		return TEST_RESULT_FAIL;
 	}
 
@@ -499,12 +499,12 @@
 	}
 
 	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, MAX_REC_COUNT)) {
+			feature_flag, sl, rec_flag, MAX_REC_COUNT, 0U)) {
 		return TEST_RESULT_FAIL;
 	}
 
 	if (!host_create_activate_realm_payload(&realm2, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, 1U)) {
+			feature_flag, sl, rec_flag, 1U, 0U)) {
 		ret2 = host_destroy_realm(&realm);
 		return TEST_RESULT_FAIL;
 	}
@@ -661,7 +661,7 @@
 
 	/* Request more PMU counter than total, expect failure */
 	if (host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, 1U)) {
+			feature_flag, sl, rec_flag, 1U, 0U)) {
 		ERROR("Realm create should have failed\n");
 		host_destroy_realm(&realm);
 		return TEST_RESULT_FAIL;
@@ -676,7 +676,7 @@
 	}
 
 	ret1 = host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-				feature_flag, sl, rec_flag, 1U);
+				feature_flag, sl, rec_flag, 1U, 0U);
 
 	if (!get_feat_hpmn0_supported()) {
 		if (ret1) {
@@ -702,7 +702,7 @@
 
 	/* Prepare realm0, create recs for realm0 later */
 	if (!host_prepare_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, rec_count)) {
+			feature_flag, sl, rec_flag, rec_count, 0U)) {
 		goto test_exit;
 		return TEST_RESULT_FAIL;
 	}
@@ -716,7 +716,7 @@
 	}
 
 	if (!host_create_activate_realm_payload(&realm1, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, rec_count)) {
+			feature_flag, sl, rec_flag, rec_count, 0U)) {
 		goto test_exit2;
 	}
 
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 e22a9f1..c25c58d 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
@@ -59,7 +59,7 @@
 		unsigned int run_num = (unsigned int)rand() % MAX_REC_COUNT;
 
 		if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-				feature_flag, sl, rec_flag, MAX_REC_COUNT)) {
+				feature_flag, sl, rec_flag, MAX_REC_COUNT, 0U)) {
 			return TEST_RESULT_FAIL;
 		}
 
@@ -97,7 +97,7 @@
 	}
 
 	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, 1U)) {
+			feature_flag, sl, rec_flag, 1U, 0U)) {
 		return TEST_RESULT_FAIL;
 	}
 
@@ -141,7 +141,7 @@
 
 	pauth_test_lib_fill_regs_and_template(pauth_keys_before);
 	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-				feature_flag, sl, rec_flag, MAX_REC_COUNT)) {
+				feature_flag, sl, rec_flag, MAX_REC_COUNT, 0U)) {
 		return TEST_RESULT_FAIL;
 	}
 
@@ -203,7 +203,7 @@
 	SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
 
 	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-				feature_flag, sl, rec_flag, 1U)) {
+				feature_flag, sl, rec_flag, 1U, 0U)) {
 		return TEST_RESULT_FAIL;
 	}
 
@@ -281,17 +281,25 @@
 static test_result_t host_test_realm_pmuv3(uint8_t cmd)
 {
 	struct realm realm;
-	u_register_t feature_flag;
+	u_register_t feature_flag, rmm_feat_reg0;
+	unsigned int num_cnts;
 	long sl = RTT_MIN_LEVEL;
 	u_register_t rec_flag[1] = {RMI_RUNNABLE};
 	bool ret1, ret2;
 
 	SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
 
+	/* Get Max PMU counter implemented through RMI_FEATURES */
+	if (host_rmi_features(0UL, &rmm_feat_reg0) != REALM_SUCCESS) {
+		ERROR("%s() failed\n", "host_rmi_features");
+		return TEST_RESULT_FAIL;
+	}
+
+	num_cnts = EXTRACT(RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS, rmm_feat_reg0);
 	host_set_pmu_state();
 
 	feature_flag = RMI_FEATURE_REGISTER_0_PMU_EN |
-			INPLACE(FEATURE_PMU_NUM_CTRS, (unsigned long long)(-1));
+			INPLACE(FEATURE_PMU_NUM_CTRS, num_cnts);
 
 	if (is_feat_52b_on_4k_2_supported() == true) {
 		feature_flag |= RMI_FEATURE_REGISTER_0_LPA2;
@@ -299,7 +307,7 @@
 	}
 
 	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, 1U)) {
+			feature_flag, sl, rec_flag, 1U, 0U)) {
 		return TEST_RESULT_FAIL;
 	}
 
@@ -412,7 +420,8 @@
 
 		ret = host_create_activate_realm_payload(&realm[num],
 							(u_register_t)REALM_IMAGE_BASE,
-							feature_flag, sl, rec_flag, MAX_REC_COUNT);
+							feature_flag, sl, rec_flag,
+							MAX_REC_COUNT, 0U);
 		if (!ret) {
 			goto destroy_realms;
 		}
@@ -476,7 +485,7 @@
 	}
 
 	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, 1U)) {
+			feature_flag, sl, rec_flag, 1U, 0U)) {
 		return TEST_RESULT_FAIL;
 	}
 
@@ -575,7 +584,7 @@
 	}
 
 	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, 1U)) {
+			feature_flag, sl, rec_flag, 1U, 0U)) {
 		return TEST_RESULT_FAIL;
 	}
 
@@ -647,7 +656,7 @@
 	}
 
 	if (!host_create_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, 2U)) {
+			feature_flag, sl, rec_flag, 2U, 0U)) {
 		return TEST_RESULT_FAIL;
 	}
 
@@ -773,7 +782,7 @@
 	}
 
 	if (!host_create_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, 2U)) {
+			feature_flag, sl, rec_flag, 2U, 0U)) {
 		return TEST_RESULT_FAIL;
 	}
 
@@ -882,7 +891,7 @@
 	}
 
 	if (!host_create_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, 2U)) {
+			feature_flag, sl, rec_flag, 2U, 0U)) {
 		return TEST_RESULT_FAIL;
 	}
 
@@ -1017,7 +1026,7 @@
 	}
 
 	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, 4U)) {
+			feature_flag, sl, rec_flag, 4U, 0U)) {
 		return TEST_RESULT_FAIL;
 	}
 
@@ -1159,7 +1168,7 @@
 	}
 
 	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, 2U)) {
+			feature_flag, sl, rec_flag, 2U, 0U)) {
 		return TEST_RESULT_FAIL;
 	}
 
@@ -1267,7 +1276,7 @@
 	}
 
 	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, MAX_REC_COUNT)) {
+			feature_flag, sl, rec_flag, MAX_REC_COUNT, 0U)) {
 		return TEST_RESULT_FAIL;
 	}
 
@@ -1497,7 +1506,7 @@
 	}
 
 	if (!host_create_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, 2U)) {
+			feature_flag, sl, rec_flag, 2U, 0U)) {
 		return TEST_RESULT_FAIL;
 	}
 
@@ -1683,7 +1692,7 @@
 	}
 
 	if (!host_create_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, 1U)) {
+			feature_flag, sl, rec_flag, 1U, 0U)) {
 		goto destroy_realm;
 	}
 
@@ -1729,7 +1738,7 @@
 	feature_flag = INPLACE(RMI_FEATURE_REGISTER_0_S2SZ, 0x2CU);
 
 	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, RTT_MIN_LEVEL, rec_flag, 4U)) {
+			feature_flag, RTT_MIN_LEVEL, rec_flag, 4U, 0U)) {
 		return TEST_RESULT_FAIL;
 	}
 
@@ -1876,7 +1885,7 @@
 	}
 
 	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, 1U)) {
+			feature_flag, sl, rec_flag, 1U, 0U)) {
 		ERROR("Realm creation failed\n");
 		goto destroy_realm;
 	}
@@ -2033,7 +2042,7 @@
 	}
 
 	if (!host_create_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, 1U)) {
+			feature_flag, sl, rec_flag, 1U, 0U)) {
 		ERROR("Realm creation failed\n");
 		goto destroy_realm;
 	}
@@ -2208,7 +2217,7 @@
 	}
 
 	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, 1U)) {
+			feature_flag, sl, rec_flag, 1U, 0U)) {
 		ERROR("Realm creation failed\n");
 		goto destroy_realm;
 	}
@@ -2323,7 +2332,7 @@
 	}
 
 	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, 1U)) {
+			feature_flag, sl, rec_flag, 1U, 0U)) {
 		ERROR("Realm creation failed\n");
 		goto destroy_realm;
 	}
@@ -2436,7 +2445,7 @@
 	}
 
 	if (!host_create_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
-			feature_flag, sl, rec_flag, 1U)) {
+			feature_flag, sl, rec_flag, 1U, 0U)) {
 		ERROR("Realm creation failed\n");
 		goto destroy_realm;
 	}
@@ -2525,3 +2534,151 @@
 	}
 	return res;
 }
+
+/*
+ * Test aims to test that TF-RMM takes SCTLR2_EL1.EASE bit into account
+ * when injecting a SEA (Feat_DoubleFault2).
+ */
+test_result_t host_test_feat_doublefault2(void)
+{
+	bool ret;
+	u_register_t rec_flag;
+	u_register_t base;
+	struct realm realm;
+	struct rtt_entry rtt;
+	u_register_t feature_flag = 0UL;
+	long sl = RTT_MIN_LEVEL;
+
+	SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+	SKIP_TEST_IF_DOUBLE_FAULT2_NOT_SUPPORTED();
+
+	if (is_feat_52b_on_4k_2_supported() == true) {
+		feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
+		sl = RTT_MIN_LEVEL_LPA2;
+	}
+
+	rec_flag = RMI_RUNNABLE;
+
+	if (!host_create_activate_realm_payload(&realm,
+					(u_register_t)REALM_IMAGE_BASE,
+				feature_flag, sl, &rec_flag, 1U, 0U)) {
+		return TEST_RESULT_FAIL;
+	}
+
+	/*
+	 * Allocate a page so we pass its address as first argument of
+	 * the test command. The test will attempt an instruction fetch
+	 * from that address, which will fail as the address will not
+	 * be mapped into the Realm.
+	 */
+	base = (u_register_t)page_alloc(PAGE_SIZE);
+
+	(void)host_rmi_rtt_readentry(realm.rd, base, 3L, &rtt);
+	if (rtt.state != RMI_UNASSIGNED ||
+			(rtt.ripas != RMI_EMPTY)) {
+		ERROR("wrong initial state\n");
+		host_destroy_realm(&realm);
+		return TEST_RESULT_FAIL;
+	}
+
+	host_shared_data_set_host_val(&realm, 0U, HOST_ARG1_INDEX, base);
+
+	for (unsigned int i = 0U; i < 2U; i++) {
+		host_shared_data_set_host_val(&realm, 0U, HOST_ARG2_INDEX,
+					      (unsigned long)i);
+
+		/* Rec0 expect IA due to SEA unassigned empty page */
+		ret = host_enter_realm_execute(&realm, REALM_FEAT_DOUBLEFAULT2_TEST,
+							RMI_EXIT_HOST_CALL, 0U);
+
+		if (!ret) {
+			host_destroy_realm(&realm);
+			return TEST_RESULT_FAIL;
+		}
+	}
+
+	host_destroy_realm(&realm);
+	return TEST_RESULT_SUCCESS;
+}
+
+/*
+ * @Test_Aim@ Create realm with a single REC
+ * Test attestation process for REC
+ */
+test_result_t host_realm_test_attestation(void)
+{
+	bool ret1, ret2;
+	u_register_t rec_flag[] = {RMI_RUNNABLE};
+	struct realm realm;
+	u_register_t feature_flag = 0UL;
+	long sl = RTT_MIN_LEVEL;
+
+	SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+
+	if (is_feat_52b_on_4k_2_supported() == true) {
+		feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
+		sl = RTT_MIN_LEVEL_LPA2;
+	}
+
+	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
+				feature_flag, sl, rec_flag, 1U, 0U)) {
+		return TEST_RESULT_FAIL;
+	}
+
+	ret1 = host_enter_realm_execute(&realm, REALM_ATTESTATION,
+				RMI_EXIT_HOST_CALL, 0U);
+	if (!ret1) {
+		ERROR("Realm attestation test failed\n");
+	}
+
+	ret2 = host_destroy_realm(&realm);
+
+	if (!ret1 || !ret2) {
+		ERROR("%s(): enter=%d destroy=%d\n",
+				__func__, ret1, ret2);
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
+
+/*
+ * @Test_Aim@ Create realm with a single REC
+ * Test attestation fault for REC
+ */
+test_result_t host_realm_test_attestation_fault(void)
+{
+	bool ret1, ret2;
+	u_register_t rec_flag[] = {RMI_RUNNABLE};
+	struct realm realm;
+	u_register_t feature_flag = 0UL;
+	long sl = RTT_MIN_LEVEL;
+
+	SKIP_TEST_IF_RME_NOT_SUPPORTED_OR_RMM_IS_TRP();
+
+	if (is_feat_52b_on_4k_2_supported() == true) {
+		feature_flag = RMI_FEATURE_REGISTER_0_LPA2;
+		sl = RTT_MIN_LEVEL_LPA2;
+	}
+
+	if (!host_create_activate_realm_payload(&realm, (u_register_t)REALM_IMAGE_BASE,
+				feature_flag, sl, rec_flag, 1U, 0U)) {
+		return TEST_RESULT_FAIL;
+	}
+
+	ret1 = host_enter_realm_execute(&realm, REALM_ATTESTATION_FAULT,
+				RMI_EXIT_HOST_CALL, 0U);
+	if (!ret1) {
+		ERROR("Realm attestation fault test failed\n");
+	}
+
+	ret2 = host_destroy_realm(&realm);
+
+	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/realm_payload/host_realm_simd_common.c b/tftf/tests/runtime_services/realm_payload/host_realm_simd_common.c
index 02c5d0f..235e093 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_simd_common.c
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_simd_common.c
@@ -39,7 +39,7 @@
 	/* Initialise Realm payload */
 	if (!host_create_activate_realm_payload(realm,
 				       (u_register_t)REALM_IMAGE_BASE,
-				       feature_flag, sl, rec_flag, 1U)) {
+				       feature_flag, sl, rec_flag, 1U, 0U)) {
 		return TEST_RESULT_FAIL;
 	}
 
diff --git a/tftf/tests/runtime_services/realm_payload/host_realm_simd_common.h b/tftf/tests/runtime_services/realm_payload/host_realm_simd_common.h
index 377c85b..6ab45c3 100644
--- a/tftf/tests/runtime_services/realm_payload/host_realm_simd_common.h
+++ b/tftf/tests/runtime_services/realm_payload/host_realm_simd_common.h
@@ -4,7 +4,7 @@
  */
 
 #ifndef HOST_REALM_COMMON_H
-#define HOST_REALM_COMMON_h
+#define HOST_REALM_COMMON_H
 
 #define NS_NORMAL_SVE		0x1U
 #define NS_STREAMING_SVE	0x2U
diff --git a/tftf/tests/runtime_services/secure_service/spm_test_helpers.c b/tftf/tests/runtime_services/secure_service/spm_test_helpers.c
index 054e774..09482f2 100644
--- a/tftf/tests/runtime_services/secure_service/spm_test_helpers.c
+++ b/tftf/tests/runtime_services/secure_service/spm_test_helpers.c
@@ -106,23 +106,3 @@
 
 	return TEST_RESULT_SUCCESS;
 }
-
-bool spm_core_sp_init(ffa_id_t sp_id)
-{
-	/*
-	 * Secure Partitions secondary ECs need one round of ffa_run to reach
-	 * the message loop.
-	 */
-	if (sp_id != SP_ID(1)) {
-		uint32_t core_pos = get_current_core_id();
-		struct ffa_value ret = ffa_run(sp_id, core_pos);
-
-		if (ffa_func_id(ret) != FFA_MSG_WAIT) {
-			ERROR("Failed to run SP%x on core %u\n",
-			      sp_id, core_pos);
-			return false;
-		}
-	}
-
-	return true;
-}
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c b/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c
index 1f8e81c..4686e4c 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c
@@ -185,19 +185,6 @@
 	}
 
 	/*
-	 * Secure Partitions beyond the first SP only have their first
-	 * EC (or vCPU0) woken up at boot time by the SPMC.
-	 * Other ECs need one round of ffa_run to reach the message loop.
-	 */
-	ffa_ret = ffa_run(SP_ID(2), core_pos);
-	if (ffa_func_id(ffa_ret) != FFA_MSG_WAIT) {
-		ERROR("Failed to run SP%x on core %u\n", SP_ID(2),
-				core_pos);
-		ret = TEST_RESULT_FAIL;
-		goto out;
-	}
-
-	/*
 	 * Send a direct message request to SP2 (MP SP) from current physical
 	 * CPU. The SPMC uses the MP pinned context corresponding to the
 	 * physical CPU emitting the request.
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_indirect_messaging.c b/tftf/tests/runtime_services/secure_service/test_ffa_indirect_messaging.c
index 5a60a21..47b4ad9 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_indirect_messaging.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_indirect_messaging.c
@@ -32,12 +32,17 @@
 static __aligned(PAGE_SIZE) uint8_t vm1_rx_buffer[PAGE_SIZE];
 static __aligned(PAGE_SIZE) uint8_t vm1_tx_buffer[PAGE_SIZE];
 
+static int schedule_receiver_interrupt_handler(void *data)
+{
+	return 0;
+}
+
 test_result_t test_ffa_indirect_message_sp_to_vm(void)
 {
 	struct ffa_value ret;
 	struct mailbox_buffers mb;
 	ffa_id_t header_sender;
-	const ffa_id_t vm_id = 1;
+	const ffa_id_t vm_id = VM_ID(1);
 	const ffa_id_t sender = SP_ID(1);
 	char msg[300];
 
@@ -48,6 +53,9 @@
 
 	GET_TFTF_MAILBOX(mb);
 
+	tftf_irq_register_handler(FFA_SCHEDULE_RECEIVER_INTERRUPT_ID,
+				  schedule_receiver_interrupt_handler);
+
 	ret = ffa_rxtx_map_forward(mb.send, vm_id, vm1_rx_buffer,
 				   vm1_tx_buffer);
 
@@ -89,6 +97,15 @@
 		return TEST_RESULT_FAIL;
 	}
 
+	/*
+	 * Managed exit occured while SP was running and it is left in its
+	 * fiq handler, resume the SP to reach the FF-A message loop again.
+	 */
+	ret = cactus_resume_after_managed_exit(HYP_ID, SPM_VM_ID_FIRST);
+	if (!is_ffa_direct_response(ret)) {
+		return TEST_RESULT_FAIL;
+	}
+
 	ret = ffa_notification_bitmap_destroy(vm_id);
 	if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
 		return TEST_RESULT_FAIL;
@@ -99,6 +116,8 @@
 		return TEST_RESULT_FAIL;
 	}
 
+	tftf_irq_unregister_handler(FFA_SCHEDULE_RECEIVER_INTERRUPT_ID);
+
 	return TEST_RESULT_SUCCESS;
 }
 
@@ -110,7 +129,7 @@
 {
 	struct ffa_value ret;
 	struct mailbox_buffers mb;
-	const ffa_id_t vm_id = 1;
+	const ffa_id_t vm_id = VM_ID(1);
 	const ffa_id_t sender = SP_ID(1);
 	ffa_id_t header_sender;
 	u_register_t ret_rmm;
@@ -148,6 +167,9 @@
 		return TEST_RESULT_FAIL;
 	}
 
+	tftf_irq_register_handler(FFA_SCHEDULE_RECEIVER_INTERRUPT_ID,
+				  schedule_receiver_interrupt_handler);
+
 	/*
 	 * Delegate RX buffer of VM to realm.
 	 */
@@ -201,6 +223,15 @@
 		return TEST_RESULT_FAIL;
 	}
 
+	/*
+	 * Managed exit occured while SP was running and it is left in its
+	 * fiq handler, resume the SP to reach the FF-A message loop again.
+	 */
+	ret = cactus_resume_after_managed_exit(HYP_ID, SPM_VM_ID_FIRST);
+	if (!is_ffa_direct_response(ret)) {
+		return TEST_RESULT_FAIL;
+	}
+
 	if (strncmp(msg, expected_msg, ARRAY_SIZE(expected_msg)) != 0) {
 		ERROR("Unexpected message: %s, expected: %s\n", msg, expected_msg);
 		return TEST_RESULT_FAIL;
@@ -213,6 +244,7 @@
 	}
 
 	/* Cleaning up after the test: */
+	tftf_irq_unregister_handler(FFA_SCHEDULE_RECEIVER_INTERRUPT_ID);
 
 	/* Destroy bitmap of VM. */
 	ret = ffa_notification_bitmap_destroy(vm_id);
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 b402c58..d80a052 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
@@ -1713,7 +1713,11 @@
 		goto exit;
 	}
 
-	/* This time test should pass. */
+	/* Undelegate operation scrubbed the TX buffer, re-init the fragment. */
+	remaining_constituent_count = ffa_memory_fragment_init(
+		mb.send, PAGE_SIZE, &constituents[1], 1, &fragment_length);
+
+	/* This time the test is expected to pass. */
 	ffa_ret = ffa_mem_frag_tx(handle, fragment_length);
 
 	if (is_ffa_call_error(ffa_ret)) {
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c b/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c
index af338fb..fe04751 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c
@@ -679,8 +679,6 @@
 {
 	tftf_irq_register_handler(FFA_SCHEDULE_RECEIVER_INTERRUPT_ID,
 				  schedule_receiver_interrupt_handler);
-
-	tftf_irq_enable(FFA_SCHEDULE_RECEIVER_INTERRUPT_ID, 0xA);
 }
 
 /**
@@ -689,7 +687,6 @@
  */
 static void schedule_receiver_interrupt_deinit(void)
 {
-	tftf_irq_disable(FFA_SCHEDULE_RECEIVER_INTERRUPT_ID);
 	tftf_irq_unregister_handler(FFA_SCHEDULE_RECEIVER_INTERRUPT_ID);
 	schedule_receiver_interrupt_received = 0;
 }
@@ -984,14 +981,6 @@
 		 per_vcpu_receiver, core_pos);
 
 	/*
-	 * Secure Partitions secondary ECs need one round of ffa_run to reach
-	 * the message loop.
-	 */
-	if (!spm_core_sp_init(per_vcpu_receiver)) {
-		goto out;
-	}
-
-	/*
 	 * Request to get notifications sent to the respective vCPU.
 	 * Check also if NPI was handled by the receiver. It should have been
 	 * pended at notifications set, in the respective vCPU.
@@ -1005,6 +994,8 @@
 	result = TEST_RESULT_SUCCESS;
 
 out:
+	INFO("Request get per-vCPU notification to %x, core: %u.\n",
+		 per_vcpu_receiver, core_pos);
 	/* Tell the lead CPU that the calling CPU has completed the test. */
 	tftf_send_event(&per_vcpu_finished[core_pos]);
 
@@ -1019,17 +1010,8 @@
 	VERBOSE("Request SP %x to enable NPI in core %u\n",
 		 per_vcpu_receiver, core_pos);
 
-	/*
-	 * Secure Partitions secondary ECs need one round of ffa_run to reach
-	 * the message loop.
-	 */
-	if (!spm_core_sp_init(per_vcpu_receiver)) {
-		goto out;
-	}
-
 	result = TEST_RESULT_SUCCESS;
 
-out:
 	/* Tell the lead CPU that the calling CPU has completed the test. */
 	tftf_send_event(&per_vcpu_finished[core_pos]);
 
@@ -1086,6 +1068,7 @@
 	per_vcpu_receiver = receiver;
 	per_vcpu_sender = sender;
 
+	INFO("Execute npi_enable_per_vcpu_on_handler\n");
 	/* Boot all cores and enable the NPI in all of them. */
 	if (spm_run_multi_core_test(
 		(uintptr_t)npi_enable_per_vcpu_on_handler,
@@ -1137,6 +1120,7 @@
 		result = TEST_RESULT_FAIL;
 	}
 
+	INFO("Execute request_notification_get_per_vcpu_on_handler\n");
 	/*
 	 * Bring up all the cores, and request the receiver to get notifications
 	 * in each one of them.
@@ -1148,6 +1132,7 @@
 	}
 
 out:
+	INFO("UNbind message on CPU:%lx\n", read_mpidr_el1());
 	/* As a clean-up, unbind notifications. */
 	if (!request_notification_unbind(receiver, receiver,
 					 sender,
@@ -1156,6 +1141,7 @@
 		result = TEST_RESULT_FAIL;
 	}
 
+	INFO("Execute npi_disable_per_vcpu_on_handler\n");
 	/* Boot all cores and DISABLE the NPI in all of them. */
 	if (spm_run_multi_core_test(
 		(uintptr_t)npi_disable_per_vcpu_on_handler,
@@ -1190,10 +1176,6 @@
 	VERBOSE("Getting per-vCPU notifications from %x, core: %u.\n",
 		 per_vcpu_receiver, core_pos);
 
-	if (!spm_core_sp_init(per_vcpu_sender)) {
-		goto out;
-	}
-
 	if (!notification_get_and_validate(per_vcpu_receiver,
 					   FFA_NOTIFICATION(core_pos), 0,
 					   core_pos,
@@ -1202,7 +1184,6 @@
 		result = TEST_RESULT_FAIL;
 	}
 
-out:
 	/* Tell the lead CPU that the calling CPU has completed the test. */
 	tftf_send_event(&per_vcpu_finished[core_pos]);
 
@@ -1501,10 +1482,6 @@
 	unsigned int core_pos = get_current_core_id();
 	test_result_t result = TEST_RESULT_FAIL;
 
-	if (!spm_core_sp_init(per_vcpu_sender)) {
-		goto out;
-	}
-
 	if (!notification_set(per_vcpu_receiver, per_vcpu_sender,
 			      FFA_NOTIFICATIONS_FLAG_DELAY_SRI |
 			      FFA_NOTIFICATIONS_FLAG_PER_VCPU  |
diff --git a/tftf/tests/tests-cpu-extensions.mk b/tftf/tests/tests-cpu-extensions.mk
index 144694e..7375633 100644
--- a/tftf/tests/tests-cpu-extensions.mk
+++ b/tftf/tests/tests-cpu-extensions.mk
@@ -8,20 +8,24 @@
 	extensions/afp/test_afp.c					\
 	extensions/amu/test_amu.c					\
 	extensions/brbe/test_brbe.c					\
+	extensions/d128/test_d128.c					\
 	extensions/debugv8p9/test_debugv8p9.c				\
 	extensions/ecv/test_ecv.c					\
 	extensions/fgt/test_fgt.c					\
+	extensions/fpmr/test_fpmr.c					\
 	extensions/ls64/test_ls64.c 					\
 	extensions/ls64/ls64_operations.S				\
 	extensions/mpam/test_mpam.c					\
 	extensions/mte/test_mte.c					\
 	extensions/pauth/test_pauth.c					\
 	extensions/pmuv3/test_pmuv3.c					\
+	extensions/sctlr2/test_sctlr2.c					\
 	extensions/sme/test_sme.c					\
 	extensions/sme/test_sme2.c					\
 	extensions/spe/test_spe.c					\
 	extensions/sve/test_sve.c					\
 	extensions/sys_reg_trace/test_sys_reg_trace.c			\
+	extensions/the/test_the.c					\
 	extensions/trbe/test_trbe.c					\
 	extensions/trf/test_trf.c					\
 	extensions/wfxt/test_wfxt.c					\
@@ -29,4 +33,5 @@
 	runtime_services/arm_arch_svc/smccc_arch_workaround_1.c		\
 	runtime_services/arm_arch_svc/smccc_arch_workaround_2.c		\
 	runtime_services/arm_arch_svc/smccc_arch_workaround_3.c		\
+	runtime_services/arm_arch_svc/smccc_feature_availability.c	\
 )
diff --git a/tftf/tests/tests-cpu-extensions.xml b/tftf/tests/tests-cpu-extensions.xml
index 34ac0b6..51aa27c 100644
--- a/tftf/tests/tests-cpu-extensions.xml
+++ b/tftf/tests/tests-cpu-extensions.xml
@@ -23,6 +23,7 @@
     <testcase name="Check for MTE register leakage" function="test_mte_leakage" />
     <testcase name="Use FGT Registers" function="test_fgt_enabled" />
     <testcase name="Use FGT2 Registers" function="test_fgt2_enabled" />
+    <testcase name="Use FPMR Register" function="test_fpmr_enabled" />
     <testcase name="Use ECV Registers" function="test_ecv_enabled" />
     <testcase name="Use trace buffer control Registers" function="test_trbe_enabled" />
     <testcase name="Use branch record buffer control registers" function="test_brbe_enabled" />
@@ -39,6 +40,9 @@
     <testcase name="PMUv3 SMC counter preservation" function="test_pmuv3_el3_preserves" />
     <testcase name="LS64 support" function="test_ls64_instructions" />
     <testcase name="LS64-ACCDATA support" function="test_ls64_accdata_sysreg" />
+    <testcase name="SCTLR2 support" function="test_sctlr2_support" />
+    <testcase name="THE support" function="test_the_support" />
+    <testcase name="D128 support" function="test_d128_support" />
   </testsuite>
 
   <testsuite name="ARM_ARCH_SVC" description="Arm Architecture Service tests">
@@ -46,6 +50,7 @@
      <testcase name="SMCCC_ARCH_WORKAROUND_2 test" function="test_smccc_arch_workaround_2" />
      <testcase name="SMCCC_ARCH_WORKAROUND_3 test" function="test_smccc_arch_workaround_3" />
      <testcase name="SMCCC_ARCH_SOC_ID test" function="test_smccc_arch_soc_id" />
+     <testcase name="SMCCC_ARCH_FEATURE_AVAILABILITY test" function="test_smccc_arch_feature_availability" />
   </testsuite>
 
 </testsuites>
diff --git a/tftf/tests/tests-pcie-doe.mk b/tftf/tests/tests-pcie-doe.mk
deleted file mode 100644
index 14bc9cf..0000000
--- a/tftf/tests/tests-pcie-doe.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Copyright (c) 2024, Arm Limited. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-TESTS_SOURCES	+=			\
-	$(addprefix plat/arm/fvp/,	\
-		fvp_pcie.c		\
-	)
-
-TESTS_SOURCES	+=				\
-	$(addprefix tftf/tests/doe_tests/,	\
-		doe_helpers.c			\
-		test_doe.c			\
-	)
-
-TESTS_SOURCES	+=		\
-	$(addprefix lib/pcie/,	\
-		pcie.c		\
-		pcie_doe.c	\
-	)
diff --git a/tftf/tests/tests-pcie-doe.xml b/tftf/tests/tests-pcie-doe.xml
deleted file mode 100644
index ed8b7cb..0000000
--- a/tftf/tests/tests-pcie-doe.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
-  Copyright (c) 2024, Arm Limited. All rights reserved.
-
-  SPDX-License-Identifier: BSD-3-Clause
--->
-
-<testsuites>
-  <testsuite name="PCI Data Object Exchange" description="Check PCI DOE support">
-     <testcase name="PCI DOE Discovery" function="doe_discovery_test" />
-     <testcase name="SPDM Get Version" function="spdm_version_test" />
-  </testsuite>
-</testsuites>
diff --git a/tftf/tests/tests-realm-payload.mk b/tftf/tests/tests-realm-payload.mk
index ae4b20a..b6833e1 100644
--- a/tftf/tests/tests-realm-payload.mk
+++ b/tftf/tests/tests-realm-payload.mk
@@ -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,8 @@
 		host_realm_helper.c					\
 		host_shared_data.c					\
 		rmi_delegate_tests.c					\
+		host_rmi_pdev.c						\
+		host_crypto_utils.c					\
 	)
 
 TESTS_SOURCES	+=							\
@@ -44,4 +46,19 @@
 	$(addprefix lib/extensions/fpu/,				\
 		fpu.c							\
 	)
+
+TESTS_SOURCES	+=				\
+	$(addprefix tftf/tests/doe_tests/,	\
+		doe_helpers.c			\
+		test_doe.c			\
+	)
+
+TESTS_SOURCES	+=		\
+	$(addprefix lib/pcie/,	\
+		pcie.c		\
+		pcie_doe.c	\
+	)
+
+include lib/ext_mbedtls/mbedtls.mk
+
 endif
diff --git a/tftf/tests/tests-realm-payload.xml b/tftf/tests/tests-realm-payload.xml
index f359e72..da88701 100644
--- a/tftf/tests/tests-realm-payload.xml
+++ b/tftf/tests/tests-realm-payload.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-  Copyright (c) 2021-2023, Arm Limited. All rights reserved.
+  Copyright (c) 2021-2024, Arm Limited. All rights reserved.
 
   SPDX-License-Identifier: BSD-3-Clause
 -->
@@ -76,6 +76,8 @@
 	  function="host_realm_set_ripas" />
 	  <testcase name="Realm reject set_ripas"
 	  function="host_realm_reject_set_ripas" />
+	  <testcase name="Realm FEAT_DoubleFault2"
+	  function="host_test_feat_doublefault2" />
 	  <!-- Test case related to SVE support and SIMD state -->
 	  <testcase name="Check RMI reports proper SVE VL"
 	  function="host_check_rmi_reports_proper_sve_vl" />
@@ -122,7 +124,21 @@
 	  function="host_test_realm_no_lpa2_invalid_s2sz" />
 	  <testcase name="Test Realm creation with LPA2 disabled but FEAT_LPA2 present on platform"
 	  function="host_test_non_lpa2_realm_on_lpa2plat" />
+	  <testcase name="Test Data bound with LPA2 disabled but FEAT_LPA2 present on platform"
+	  function="host_test_data_bound_non_lpa2_realm_on_lpa2plat" />
 	  <testcase name="Test Realm creation with LPA2 enabled but FEAT_LPA2 absent on platform"
 	  function="host_test_lpa2_realm_on_non_lpa2plat" />
+	  <!-- Test cases related to Attestation -->
+	  <testcase name="Test realm attestation" function="host_realm_test_attestation" />
+	  <testcase name="Test realm attestation fault"
+	  function="host_realm_test_attestation_fault" />
+	  <!-- Test case related to PCIE-DOE -->
+	  <testcase name="PCI DOE Discovery"
+	  function="doe_discovery_test" />
+	  <testcase name="SPDM Get Version"
+	  function="spdm_version_test" />
+	  <!-- Invoke RMI calls related to PDEV management -->
+	  <testcase name="Invoke RMI PDEV calls "
+	  function="host_test_rmi_pdev_calls" />
   </testsuite>
 </testsuites>