Merge changes from topic "handoff_tpm_event_log" into integration

* changes:
  feat(qemu): hand off TPM event log via TL
  feat(handoff): common API for TPM event log handoff
  feat(handoff): transfer entry ID for TPM event log
  fix(qemu): fix register convention in BL31 for qemu
  fix(handoff): fix register convention in opteed
diff --git a/Makefile b/Makefile
index 6f080b4..a286a4a 100644
--- a/Makefile
+++ b/Makefile
@@ -514,6 +514,12 @@
 endif
 
 ################################################################################
+# Include the platform specific Makefile after the SPD Makefile (the platform
+# makefile may use all previous definitions in this file)
+################################################################################
+include ${PLAT_MAKEFILE_FULL}
+
+################################################################################
 # Process BRANCH_PROTECTION value and set
 # Pointer Authentication and Branch Target Identification flags
 ################################################################################
@@ -558,12 +564,6 @@
 endif
 
 ################################################################################
-# Include the platform specific Makefile after the SPD Makefile (the platform
-# makefile may use all previous definitions in this file)
-################################################################################
-include ${PLAT_MAKEFILE_FULL}
-
-################################################################################
 # Setup arch_features based on ARM_ARCH_MAJOR, ARM_ARCH_MINOR provided from
 # platform.
 ################################################################################
@@ -599,11 +599,6 @@
 ################################################################################
 # FEAT_RME
 ifeq (${ENABLE_RME},1)
-	# RME doesn't support PIE
-	ifneq (${ENABLE_PIE},0)
-                $(error ENABLE_RME does not support PIE)
-	endif
-
 	# RME requires AARCH64
 	ifneq (${ARCH},aarch64)
                 $(error ENABLE_RME requires AArch64)
@@ -959,6 +954,10 @@
 	ifneq (${ENABLE_FEAT_FPMR},0)
                 $(error "ENABLE_FEAT_FPMR cannot be used with ARCH=aarch32")
 	endif
+
+	ifeq (${ARCH_FEATURE_AVAILABILITY},1)
+                $(error "ARCH_FEATURE_AVAILABILITY cannot be used with ARCH=aarch32")
+	endif
 endif #(ARCH=aarch32)
 
 ifneq (${ENABLE_FEAT_FPMR},0)
@@ -1207,6 +1206,7 @@
 	PROGRAMMABLE_RESET_ADDRESS \
 	PSCI_EXTENDED_STATE_ID \
 	PSCI_OS_INIT_MODE \
+	ARCH_FEATURE_AVAILABILITY \
 	RESET_TO_BL31 \
 	SAVE_KEYS \
 	SEPARATE_CODE_AND_RODATA \
@@ -1388,6 +1388,7 @@
 	PROGRAMMABLE_RESET_ADDRESS \
 	PSCI_EXTENDED_STATE_ID \
 	PSCI_OS_INIT_MODE \
+	ARCH_FEATURE_AVAILABILITY \
 	RESET_TO_BL31 \
 	RME_GPT_BITLOCK_BLOCK \
 	RME_GPT_MAX_BLOCK \
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index d2d2eb5..a8184e6 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -858,6 +858,11 @@
 -  ``PSCI_OS_INIT_MODE``: Boolean flag to enable support for optional PSCI
    OS-initiated mode. This option defaults to 0.
 
+-  ``ARCH_FEATURE_AVAILABILITY``: Boolean flag to enable support for the
+   optional SMCCC_ARCH_FEATURE_AVAILABILITY call. This option implicitly
+   interacts with IMPDEF_SYSREG_TRAP and software emulation. This option
+   defaults to 0.
+
 -  ``ENABLE_FEAT_RAS``: Boolean flag to enable Armv8.2 RAS features. RAS features
    are an optional extension for pre-Armv8.2 CPUs, but are mandatory for Armv8.2
    or later CPUs. This flag can take the values 0 or 1. The default value is 0.
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index 5cb20fd..6d03f44 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -2454,7 +2454,7 @@
 The value should be obtained from a reliable source of randomness.
 
 This function is only needed if ARMv8.3 pointer authentication is used in the
-Trusted Firmware by building with ``BRANCH_PROTECTION`` option set to non-zero.
+Trusted Firmware by building with ``BRANCH_PROTECTION`` option set to 1, 2 or 3.
 
 Function : plat_get_syscnt_freq2() [mandatory]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -3553,7 +3553,10 @@
 This function is invoked by BL31's exception handler when there is a synchronous
 system register trap caused by access to the implementation defined registers.
 It allows platforms enabling ``IMPDEF_SYSREG_TRAP`` to emulate those system
-registers choosing to program bits of their choice.
+registers choosing to program bits of their choice. If using in combination with
+``ARCH_FEATURE_AVAILABILITY``, the macros
+{SCR,MDCR,CPTR}_PLAT_{BITS,IGNORED,FLIPPED} should be defined to report correct
+results.
 
 The first parameter (``uint64_t esr_el3``) contains the content of the ESR_EL3
 syndrome register, which encodes the instruction that was trapped.
diff --git a/fdts/tc-base.dtsi b/fdts/tc-base.dtsi
index e898399..691a3b8 100644
--- a/fdts/tc-base.dtsi
+++ b/fdts/tc-base.dtsi
@@ -387,7 +387,7 @@
 	soc_uartclk: uartclk {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
-		clock-frequency = <UARTCLK_FREQ>;
+		clock-frequency = <TC_UARTCLK>;
 		clock-output-names = "uartclk";
 	};
 
diff --git a/fdts/tc2.dts b/fdts/tc2.dts
index c492274..003efdc 100644
--- a/fdts/tc2.dts
+++ b/fdts/tc2.dts
@@ -36,7 +36,6 @@
 #define BIG_CPU_PMU_COMPATIBLE		"arm,cortex-x4-pmu"
 
 #define MPAM_ADDR			0x1 0x00010000 /* 0x1_0001_0000 */
-#define UARTCLK_FREQ			5000000
 
 #define DPU_ADDR			2cc00000
 #define DPU_IRQ				69
diff --git a/fdts/tc3-4-base.dtsi b/fdts/tc3-4-base.dtsi
index c7f3084..84aa8e8 100644
--- a/fdts/tc3-4-base.dtsi
+++ b/fdts/tc3-4-base.dtsi
@@ -18,7 +18,6 @@
 #define MHU_RX_INT_NAME			"combined"
 
 #define MPAM_ADDR			0x0 0x5f010000 /* 0x5f01_0000 */
-#define UARTCLK_FREQ			3750000
 
 #if TARGET_FLAVOUR_FVP
 #define DPU_ADDR			4000000000
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index 3a7e2eb..fefee4a 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -654,15 +654,18 @@
 
 /* MDCR_EL3 definitions */
 #define MDCR_EBWE_BIT		(ULL(1) << 43)
-#define MDCR_E3BREC		(ULL(1) << 38)
-#define MDCR_E3BREW		(ULL(1) << 37)
+#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)		((x) << MDCR_SBRBE_SHIFT)
+#define MDCR_SBRBE_ALL		ULL(0x3)
+#define MDCR_SBRBE_NS		ULL(0x1)
 #define MDCR_NSTB(x)		((x) << 24)
 #define MDCR_NSTB_EL1		ULL(0x3)
+#define MDCR_NSTB_EL3		ULL(0x2)
 #define MDCR_NSTBE_BIT		(ULL(1) << 26)
 #define MDCR_MTPME_BIT		(ULL(1) << 28)
 #define MDCR_TDCC_BIT		(ULL(1) << 27)
@@ -679,6 +682,7 @@
 #define MDCR_SPD32_ENABLE	ULL(0x3)
 #define MDCR_NSPB(x)		((x) << 12)
 #define MDCR_NSPB_EL1		ULL(0x3)
+#define MDCR_NSPB_EL3		ULL(0x2)
 #define MDCR_NSPBE_BIT		(ULL(1) << 11)
 #define MDCR_TDOSA_BIT		(ULL(1) << 10)
 #define MDCR_TDA_BIT		(ULL(1) << 9)
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index 8bdc13c..99c2cdf 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -353,8 +353,8 @@
 		     ID_AA64MMFR1_EL1_HCX_MASK, 1U, ENABLE_FEAT_HCX)
 
 /* FEAT_RNG_TRAP: Trapping support */
-CREATE_FEATURE_PRESENT(feat_rng_trap, id_aa64pfr1_el1, ID_AA64PFR1_EL1_RNDR_TRAP_SHIFT,
-		      ID_AA64PFR1_EL1_RNDR_TRAP_MASK, RNG_TRAP_IMPLEMENTED)
+CREATE_FEATURE_FUNCS(feat_rng_trap, id_aa64pfr1_el1, ID_AA64PFR1_EL1_RNDR_TRAP_SHIFT,
+		      ID_AA64PFR1_EL1_RNDR_TRAP_MASK, RNG_TRAP_IMPLEMENTED, ENABLE_FEAT_RNG_TRAP)
 
 /* Return the RME version, zero if not supported. */
 CREATE_FEATURE_FUNCS(feat_rme, id_aa64pfr0_el1, ID_AA64PFR0_FEAT_RME_SHIFT,
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index 3f3f14d..8b92f19 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -295,6 +295,7 @@
 DEFINE_SYSREG_RW_FUNCS(dbgdtrtx_el0)
 DEFINE_SYSREG_RW_FUNCS(sp_el1)
 DEFINE_SYSREG_RW_FUNCS(sp_el2)
+DEFINE_SYSREG_RW_FUNCS(dbgprcr_el1)
 
 DEFINE_SYSOP_FUNC(wfi)
 DEFINE_SYSOP_FUNC(wfe)
diff --git a/include/services/arm_arch_svc.h b/include/services/arm_arch_svc.h
index 645b388..c2b1f41 100644
--- a/include/services/arm_arch_svc.h
+++ b/include/services/arm_arch_svc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,8 +13,310 @@
 #define SMCCC_ARCH_WORKAROUND_1		U(0x80008000)
 #define SMCCC_ARCH_WORKAROUND_2		U(0x80007FFF)
 #define SMCCC_ARCH_WORKAROUND_3		U(0x80003FFF)
+#define SMCCC_ARCH_FEATURE_AVAILABILITY		U(0x80000003)
 
 #define SMCCC_GET_SOC_VERSION		U(0)
 #define SMCCC_GET_SOC_REVISION		U(1)
 
+#ifndef __ASSEMBLER__
+#if ARCH_FEATURE_AVAILABILITY
+#include <lib/cassert.h>
+
+#if ENABLE_FEAT_FGT2
+#define SCR_FEAT_FGT2 SCR_FGTEN2_BIT
+#else
+#define SCR_FEAT_FGT2 (0)
+#endif
+
+#if ENABLE_FEAT_FPMR
+#define SCR_FEAT_FPMR SCR_EnFPM_BIT
+#else
+#define SCR_FEAT_FPMR
+#endif
+
+#if ENABLE_FEAT_D128
+#define SCR_FEAT_D128 SCR_D128En_BIT
+#else
+#define SCR_FEAT_D128 (0)
+#endif
+
+#if ENABLE_FEAT_S1PIE
+#define SCR_FEAT_S1PIE SCR_PIEN_BIT
+#else
+#define SCR_FEAT_S1PIE (0)
+#endif
+
+#if ENABLE_FEAT_SCTLR2
+#define SCR_FEAT_SCTLR2 SCR_SCTLR2En_BIT
+#else
+#define SCR_FEAT_SCTLR2 (0)
+#endif
+
+#if ENABLE_FEAT_TCR2
+#define SCR_FEAT_TCR2 SCR_TCR2EN_BIT
+#else
+#define SCR_FEAT_TCR2 (0)
+#endif
+
+#if ENABLE_FEAT_THE
+#define SCR_FEAT_THE SCR_RCWMASKEn_BIT
+#else
+#define SCR_FEAT_THE (0)
+#endif
+
+#if ENABLE_SME_FOR_NS
+#define SCR_FEAT_SME SCR_ENTP2_BIT
+#else
+#define SCR_FEAT_SME (0)
+#endif
+
+#if ENABLE_FEAT_GCS
+#define SCR_FEAT_GCS SCR_GCSEn_BIT
+#else
+#define SCR_FEAT_GCS (0)
+#endif
+
+#if ENABLE_FEAT_HCX
+#define SCR_FEAT_HCX SCR_HXEn_BIT
+#else
+#define SCR_FEAT_HCX (0)
+#endif
+
+#if ENABLE_FEAT_LS64_ACCDATA
+#define SCR_FEAT_LS64_ACCDATA (SCR_ADEn_BIT | SCR_EnAS0_BIT)
+#else
+#define SCR_FEAT_LS64_ACCDATA (0)
+#endif
+
+#if ENABLE_FEAT_AMUv1p1
+#define SCR_FEAT_AMUv1p1 SCR_AMVOFFEN_BIT
+#else
+#define SCR_FEAT_AMUv1p1 (0)
+#endif
+
+#if ENABLE_FEAT_ECV
+#define SCR_FEAT_ECV SCR_ECVEN_BIT
+#else
+#define SCR_FEAT_ECV (0)
+#endif
+
+#if ENABLE_FEAT_FGT
+#define SCR_FEAT_FGT SCR_FGTEN_BIT
+#else
+#define SCR_FEAT_FGT (0)
+#endif
+
+#if ENABLE_FEAT_MTE2
+#define SCR_FEAT_MTE2 SCR_ATA_BIT
+#else
+#define SCR_FEAT_MTE2 (0)
+#endif
+
+#if ENABLE_FEAT_CSV2_2
+#define SCR_FEAT_CSV2_2 SCR_EnSCXT_BIT
+#else
+#define SCR_FEAT_CSV2_2 (0)
+#endif
+
+#if ENABLE_FEAT_RAS
+#define SCR_FEAT_RAS SCR_TERR_BIT
+#else
+#define SCR_FEAT_RAS (0)
+#endif
+
+#ifndef SCR_PLAT_FEATS
+#define SCR_PLAT_FEATS (0)
+#endif
+#ifndef SCR_PLAT_FLIPPED
+#define SCR_PLAT_FLIPPED (0)
+#endif
+#ifndef SCR_PLAT_IGNORED
+#define SCR_PLAT_IGNORED (0)
+#endif
+
+#ifndef CPTR_PLAT_FEATS
+#define CPTR_PLAT_FEATS (0)
+#endif
+#ifndef CPTR_PLAT_FLIPPED
+#define CPTR_PLAT_FLIPPED (0)
+#endif
+
+#ifndef MDCR_PLAT_FEATS
+#define MDCR_PLAT_FEATS (0)
+#endif
+#ifndef MDCR_PLAT_FLIPPED
+#define MDCR_PLAT_FLIPPED (0)
+#endif
+#ifndef MDCR_PLAT_IGNORED
+#define MDCR_PLAT_IGNORED (0)
+#endif
+/*
+ * XYZ_EL3_FEATS - list all bits that are relevant for feature enablement. It's
+ * a constant list based on what features are expected. This relies on the fact
+ * that if the feature is in any way disabled, then the relevant bit will not be
+ * written by context management.
+ *
+ * XYZ_EL3_FLIPPED - bits with an active 0, rather than the usual active 1. The
+ * spec always uses active 1 to mean that the feature will not trap.
+ *
+ * XYZ_EL3_IGNORED - list of all bits that are not relevant for feature
+ * enablement and should not be reported to lower ELs
+ */
+#define SCR_EL3_FEATS (								\
+	SCR_FEAT_FGT2		|						\
+	SCR_FEAT_FPMR		|						\
+	SCR_FEAT_D128		|						\
+	SCR_FEAT_S1PIE		|						\
+	SCR_FEAT_SCTLR2		|						\
+	SCR_FEAT_TCR2		|						\
+	SCR_FEAT_THE		|						\
+	SCR_FEAT_SME		|						\
+	SCR_FEAT_GCS		|						\
+	SCR_FEAT_HCX		|						\
+	SCR_FEAT_LS64_ACCDATA	|						\
+	SCR_FEAT_AMUv1p1	|						\
+	SCR_FEAT_ECV		|						\
+	SCR_FEAT_FGT		|						\
+	SCR_FEAT_MTE2		|						\
+	SCR_FEAT_CSV2_2		|						\
+	SCR_APK_BIT		| /* FEAT_Pauth */				\
+	SCR_FEAT_RAS		|						\
+	SCR_PLAT_FEATS)
+#define SCR_EL3_FLIPPED (							\
+	SCR_FEAT_RAS		|						\
+	SCR_PLAT_FLIPPED)
+#define SCR_EL3_IGNORED (							\
+	SCR_API_BIT		|						\
+	SCR_RW_BIT		|						\
+	SCR_SIF_BIT		|						\
+	SCR_HCE_BIT		|						\
+	SCR_FIQ_BIT		|						\
+	SCR_IRQ_BIT		|						\
+	SCR_NS_BIT		|						\
+	SCR_RES1_BITS		|						\
+	SCR_PLAT_IGNORED)
+CASSERT((SCR_EL3_FEATS & SCR_EL3_IGNORED) == 0, scr_feat_is_ignored);
+CASSERT((SCR_EL3_FLIPPED & SCR_EL3_FEATS) == SCR_EL3_FLIPPED, scr_flipped_not_a_feat);
+
+#if ENABLE_SYS_REG_TRACE_FOR_NS
+#define CPTR_SYS_REG_TRACE (TCPAC_BIT | TTA_BIT)
+#else
+#define CPTR_SYS_REG_TRACE (0)
+#endif
+
+#if ENABLE_FEAT_AMU
+#define CPTR_FEAT_AMU TAM_BIT
+#else
+#define CPTR_FEAT_AMU (0)
+#endif
+
+#if ENABLE_SME_FOR_NS
+#define CPTR_FEAT_SME ESM_BIT
+#else
+#define CPTR_FEAT_SME (0)
+#endif
+
+#if ENABLE_SVE_FOR_NS
+#define CPTR_FEAT_SVE CPTR_EZ_BIT
+#else
+#define CPTR_FEAT_SVE (0)
+#endif
+
+#define CPTR_EL3_FEATS (							\
+	CPTR_SYS_REG_TRACE	|						\
+	CPTR_FEAT_AMU		|						\
+	CPTR_FEAT_SME		|						\
+	TFP_BIT			|						\
+	CPTR_FEAT_SVE		|						\
+	CPTR_PLAT_FEATS)
+#define CPTR_EL3_FLIPPED (							\
+	CPTR_SYS_REG_TRACE	|						\
+	CPTR_FEAT_AMU		|						\
+	TFP_BIT			|						\
+	CPTR_PLAT_FLIPPED)
+CASSERT((CPTR_EL3_FLIPPED & CPTR_EL3_FEATS) == CPTR_EL3_FLIPPED, cptr_flipped_not_a_feat);
+
+/*
+ * Some features enables are expressed with more than 1 bit in order to cater
+ * for multi world enablement. In those cases (BRB, TRB, SPE) only the last bit
+ * is used and reported. This (ab)uses the convenient fact that the last bit
+ * always means "enabled for this world" when context switched correctly.
+ * The per-world values have been adjusted such that this is always true.
+ */
+#if ENABLE_BRBE_FOR_NS
+#define MDCR_FEAT_BRBE MDCR_SBRBE(1UL)
+#else
+#define MDCR_FEAT_BRBE (0)
+#endif
+
+#if ENABLE_FEAT_FGT
+#define MDCR_FEAT_FGT MDCR_TDCC_BIT
+#else
+#define MDCR_FEAT_FGT (0)
+#endif
+
+#if ENABLE_TRBE_FOR_NS
+#define MDCR_FEAT_TRBE MDCR_NSTB(1UL)
+#else
+#define MDCR_FEAT_TRBE (0)
+#endif
+
+#if ENABLE_TRF_FOR_NS
+#define MDCR_FEAT_TRF MDCR_TTRF_BIT
+#else
+#define MDCR_FEAT_TRF (0)
+#endif
+
+#if ENABLE_SPE_FOR_NS
+#define MDCR_FEAT_SPE MDCR_NSPB(1UL)
+#else
+#define MDCR_FEAT_SPE (0)
+#endif
+
+#define MDCR_EL3_FEATS (							\
+	MDCR_FEAT_BRBE		|						\
+	MDCR_FEAT_FGT		|						\
+	MDCR_FEAT_TRBE		|						\
+	MDCR_FEAT_TRF		|						\
+	MDCR_FEAT_SPE		|						\
+	MDCR_TDOSA_BIT		|						\
+	MDCR_TDA_BIT		|						\
+	MDCR_TPM_BIT		| /* FEAT_PMUv3 */				\
+	MDCR_PLAT_FEATS)
+#define MDCR_EL3_FLIPPED (							\
+	MDCR_FEAT_FGT		|						\
+	MDCR_FEAT_TRF		|						\
+	MDCR_TDOSA_BIT		|						\
+	MDCR_TDA_BIT		|						\
+	MDCR_TPM_BIT		|						\
+	MDCR_PLAT_FLIPPED)
+#define MDCR_EL3_IGNORED (							\
+	MDCR_EBWE_BIT		|						\
+	MDCR_EnPMSN_BIT		|						\
+	MDCR_SBRBE(2UL)		|						\
+	MDCR_MTPME_BIT		|						\
+	MDCR_NSTBE_BIT		|						\
+	MDCR_NSTB(2UL)		|						\
+	MDCR_SDD_BIT		|						\
+	MDCR_SPD32(3UL)		|						\
+	MDCR_NSPB(2UL)		|						\
+	MDCR_NSPBE_BIT		|						\
+	MDCR_PLAT_IGNORED)
+CASSERT((MDCR_EL3_FEATS & MDCR_EL3_IGNORED) == 0, mdcr_feat_is_ignored);
+CASSERT((MDCR_EL3_FLIPPED & MDCR_EL3_FEATS) == MDCR_EL3_FLIPPED, mdcr_flipped_not_a_feat);
+
+#define MPAM3_EL3_FEATS		(MPAM3_EL3_TRAPLOWER_BIT)
+#define MPAM3_EL3_FLIPPED	(MPAM3_EL3_TRAPLOWER_BIT)
+#define MPAM3_EL3_IGNORED	(MPAM3_EL3_MPAMEN_BIT)
+CASSERT((MPAM3_EL3_FEATS & MPAM3_EL3_IGNORED) == 0, mpam3_feat_is_ignored);
+CASSERT((MPAM3_EL3_FLIPPED & MPAM3_EL3_FEATS) == MPAM3_EL3_FLIPPED, mpam3_flipped_not_a_feat);
+
+/* The hex representations of these registers' S3 encoding */
+#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 /* ARCH_FEATURE_AVAILABILITY */
+#endif /* __ASSEMBLER__ */
 #endif /* ARM_ARCH_SVC_H */
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index ca5e047..f220d8a 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -49,7 +49,6 @@
 per_world_context_t per_world_context[CPU_DATA_CONTEXT_NUM];
 static bool has_secure_perworld_init;
 
-static void manage_extensions_common(cpu_context_t *ctx);
 static void manage_extensions_nonsecure(cpu_context_t *ctx);
 static void manage_extensions_secure(cpu_context_t *ctx);
 static void manage_extensions_secure_per_world(void);
@@ -236,8 +235,9 @@
 	 * SCR_EL3.APK: Set to one to not trap any PAuth key values at ELs other
 	 *  than EL3
 	 */
-	scr_el3 |= SCR_API_BIT | SCR_APK_BIT;
-
+	if (is_armv8_3_pauth_present()) {
+		scr_el3 |= SCR_API_BIT | SCR_APK_BIT;
+	}
 #endif /* CTX_INCLUDE_PAUTH_REGS */
 
 #if HANDLE_EA_EL3_FIRST_NS
@@ -251,7 +251,6 @@
 	 * and RAS ERX registers from EL1 and EL2(from any security state)
 	 * are trapped to EL3.
 	 * Set here to trap only for NS EL1/EL2
-	 *
 	 */
 	scr_el3 |= SCR_TERR_BIT;
 #endif
@@ -447,9 +446,9 @@
 	 * If FEAT_RNG_TRAP is enabled, all reads of the RNDR and RNDRRS
 	 * registers are trapped to EL3.
 	 */
-#if ENABLE_FEAT_RNG_TRAP
-	scr_el3 |= SCR_TRNDR_BIT;
-#endif
+	if (is_feat_rng_trap_supported()) {
+		scr_el3 |= SCR_TRNDR_BIT;
+	}
 
 #if FAULT_INJECTION_SUPPORT
 	/* Enable fault injection from lower ELs */
@@ -466,7 +465,9 @@
 	 * SCR_EL3.APK: Set to one to not trap any PAuth key values at ELs other
 	 *  than EL3
 	 */
-	scr_el3 |= SCR_API_BIT | SCR_APK_BIT;
+	if (is_armv8_3_pauth_present()) {
+		scr_el3 |= SCR_API_BIT | SCR_APK_BIT;
+	}
 #endif /* CTX_INCLUDE_PAUTH_REGS */
 
 	/*
@@ -567,11 +568,12 @@
 			& ~(MDCR_TDA_BIT | MDCR_TDOSA_BIT)) ;
 	write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3);
 
-	/*
-	 * Configure MDCR_EL3 register as applicable for each world
-	 * (NS/Secure/Realm) context.
-	 */
-	manage_extensions_common(ctx);
+#if IMAGE_BL31
+	/* Enable FEAT_TRF for Non-Secure and prohibit for Secure state. */
+	if (is_feat_trf_supported()) {
+		trf_enable(ctx);
+	}
+#endif /* IMAGE_BL31 */
 
 	/*
 	 * Store the X0-X7 value from the entrypoint into the context
@@ -781,41 +783,6 @@
 }
 
 /*******************************************************************************
- * Enable architecture extensions on first entry to Non-secure world only
- * and disable for secure world.
- *
- * NOTE: Arch features which have been provided with the capability of getting
- * enabled only for non-secure world and being disabled for secure world are
- * grouped here, as the MDCR_EL3 context value remains same across the worlds.
- ******************************************************************************/
-static void manage_extensions_common(cpu_context_t *ctx)
-{
-#if IMAGE_BL31
-	if (is_feat_spe_supported()) {
-		/*
-		 * Enable FEAT_SPE for Non-Secure and prohibit for Secure state.
-		 */
-		spe_enable(ctx);
-	}
-
-	if (is_feat_trbe_supported()) {
-		/*
-		 * Enable FEAT_TRBE for Non-Secure and prohibit for Secure and
-		 * Realm state.
-		 */
-		trbe_enable(ctx);
-	}
-
-	if (is_feat_trf_supported()) {
-		/*
-		 * Enable FEAT_TRF for Non-Secure and prohibit for Secure state.
-		 */
-		trf_enable(ctx);
-	}
-#endif /* IMAGE_BL31 */
-}
-
-/*******************************************************************************
  * Enable architecture extensions on first entry to Non-secure world.
  ******************************************************************************/
 static void manage_extensions_nonsecure(cpu_context_t *ctx)
@@ -837,6 +804,21 @@
 		debugv8p9_extended_bp_wp_enable(ctx);
 	}
 
+	/*
+	 * SPE, TRBE, and BRBE have multi-field enables that affect which world
+	 * they apply to. Despite this, it is useful to ignore these for
+	 * simplicity in determining the feature's per world enablement status.
+	 * This is only possible when context is written per-world. Relied on
+	 * by SMCCC_ARCH_FEATURE_AVAILABILITY
+	 */
+	if (is_feat_spe_supported()) {
+		spe_enable(ctx);
+	}
+
+	if (is_feat_trbe_supported()) {
+		trbe_enable(ctx);
+	}
+
 	if (is_feat_brbe_supported()) {
 		brbe_enable(ctx);
 	}
@@ -930,6 +912,20 @@
 			sme_disable(ctx);
 		}
 	}
+
+	/*
+	 * SPE and TRBE cannot be fully disabled from EL3 registers alone, only
+	 * sysreg access can. In case the EL1 controls leave them active on
+	 * context switch, we want the owning security state to be NS so Secure
+	 * can't be DOSed.
+	 */
+	if (is_feat_spe_supported()) {
+		spe_disable(ctx);
+	}
+
+	if (is_feat_trbe_supported()) {
+		trbe_disable(ctx);
+	}
 #endif /* IMAGE_BL31 */
 }
 
diff --git a/lib/extensions/brbe/brbe.c b/lib/extensions/brbe/brbe.c
index fef6647..f951654 100644
--- a/lib/extensions/brbe/brbe.c
+++ b/lib/extensions/brbe/brbe.c
@@ -22,7 +22,7 @@
 	 * MDCR_EL3.{E3BREW, E3BREC} = 0b00
 	 * Branch recording at EL3 is disabled
 	 */
-	mdcr_el3_val &= ~((MDCR_SBRBE_MASK << MDCR_SBRBE_SHIFT) | MDCR_E3BREW | MDCR_E3BREC);
-	mdcr_el3_val |= (0x1UL << MDCR_SBRBE_SHIFT);
+	mdcr_el3_val &= ~((MDCR_SBRBE(MDCR_SBRBE_ALL)) | MDCR_E3BREW_BIT | MDCR_E3BREC_BIT);
+	mdcr_el3_val |= (MDCR_SBRBE(MDCR_SBRBE_NS));
 	write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
 }
diff --git a/lib/extensions/spe/spe.c b/lib/extensions/spe/spe.c
index a8d42ab..8edba00 100644
--- a/lib/extensions/spe/spe.c
+++ b/lib/extensions/spe/spe.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -42,10 +42,10 @@
 	u_register_t mdcr_el3_val = read_ctx_reg(state, CTX_MDCR_EL3);
 
 	/*
-	 * MDCR_EL3.NSPB: Clear these bits to disable SPE feature, as it was enabled
-	 * for Non-secure state only. After clearing these bits Secure state owns
+	 * MDCR_EL3.NSPB: set to 0x2. After, Non-Secure state owns
 	 * the Profiling Buffer and accesses to Statistical Profiling and Profiling
-	 * Buffer control registers at EL2 and EL1 generate Trap exceptions to EL3
+	 * Buffer control registers at EL2 and EL1 generate Trap exceptions to EL3.
+	 * Profiling is disabled in Secure and Realm states.
 	 *
 	 * MDCR_EL3.NSPBE: Don't care as it was cleared during spe_enable and setting
 	 * this to 1 does not make sense as NSPBE{1} and NSPB{0b0x} is RESERVED.
@@ -54,6 +54,7 @@
 	 * from EL2/EL1 to EL3.
 	 */
 	mdcr_el3_val &= ~(MDCR_NSPB(MDCR_NSPB_EL1) | MDCR_EnPMSN_BIT);
+	mdcr_el3_val |= MDCR_NSPB(MDCR_NSPB_EL3);
 	write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
 }
 
diff --git a/lib/extensions/trbe/trbe.c b/lib/extensions/trbe/trbe.c
index 8775e40..d8eb4c2 100644
--- a/lib/extensions/trbe/trbe.c
+++ b/lib/extensions/trbe/trbe.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -35,16 +35,13 @@
 	u_register_t mdcr_el3_val = read_ctx_reg(state, CTX_MDCR_EL3);
 
 	/*
-	 * MDCR_EL3.NSTBE = 0b0
-	 *  Trace Buffer owning Security state is secure state. If FEAT_RME
-	 *  is not implemented, this field is RES0.
-	 *
-	 * MDCR_EL3.NSTB = 0b00
-	 *  Clear these bits to disable access of trace buffer control registers
-	 *  from lower ELs in any security state.
+	 * MDCR_EL3.{NSTBE,NSTB} = 0b0, 0b10
+	 *  Disable access of trace buffer control registers from lower ELs in
+	 *  any security state. Non-secure owns the buffer.
 	 */
 	mdcr_el3_val &= ~(MDCR_NSTB(MDCR_NSTB_EL1));
 	mdcr_el3_val &= ~(MDCR_NSTBE_BIT);
+	mdcr_el3_val |= MDCR_NSTB(MDCR_NSTB_EL3);
 	write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
 }
 
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 8a0975b..4985c0c 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -210,6 +210,9 @@
 # Enable PSCI OS-initiated mode support
 PSCI_OS_INIT_MODE		:= 0
 
+# SMCCC_ARCH_FEATURE_AVAILABILITY support
+ARCH_FEATURE_AVAILABILITY	:= 0
+
 # By default, BL1 acts as the reset handler, not BL31
 RESET_TO_BL31			:= 0
 
diff --git a/package-lock.json b/package-lock.json
index a039bc5..61d05bd 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1963,9 +1963,9 @@
       }
     },
     "node_modules/cross-spawn": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
-      "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+      "version": "7.0.6",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+      "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
       "dev": true,
       "dependencies": {
         "path-key": "^3.1.0",
diff --git a/plat/arm/board/tc/include/platform_def.h b/plat/arm/board/tc/include/platform_def.h
index 5a22628..ff79402 100644
--- a/plat/arm/board/tc/include/platform_def.h
+++ b/plat/arm/board/tc/include/platform_def.h
@@ -443,18 +443,19 @@
 #undef PLAT_ARM_BOOT_UART_CLK_IN_HZ
 #undef PLAT_ARM_RUN_UART_CLK_IN_HZ
 
-#if TARGET_FLAVOUR_FVP
-#define PLAT_ARM_BOOT_UART_BASE		TC_UART1
-#define TC_UARTCLK			7372800
-#else /* TARGET_FLAVOUR_FPGA */
-#define PLAT_ARM_BOOT_UART_BASE		TC_UART0
+#undef  ARM_CONSOLE_BAUDRATE
+#define ARM_CONSOLE_BAUDRATE		38400
+
 #if TARGET_PLATFORM <= 2
 #define TC_UARTCLK			5000000
 #elif TARGET_PLATFORM >= 3
 #define TC_UARTCLK			3750000
 #endif /* TARGET_PLATFORM >= 3 */
-#undef  ARM_CONSOLE_BAUDRATE
-#define ARM_CONSOLE_BAUDRATE		38400
+
+#if TARGET_FLAVOUR_FVP
+#define PLAT_ARM_BOOT_UART_BASE		TC_UART1
+#else /* TARGET_FLAVOUR_FPGA */
+#define PLAT_ARM_BOOT_UART_BASE		TC_UART0
 #endif /* TARGET_FLAVOUR_FPGA */
 
 #define PLAT_ARM_RUN_UART_BASE		TC_UART0
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index 07b3b62..17dc0ed 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -52,17 +52,10 @@
 #pragma weak bl2_plat_arch_setup
 #pragma weak bl2_plat_sec_mem_layout
 
-#if ENABLE_RME
 #define MAP_BL2_TOTAL		MAP_REGION_FLAT(			\
 					bl2_tzram_layout.total_base,	\
 					bl2_tzram_layout.total_size,	\
-					MT_MEMORY | MT_RW | MT_ROOT)
-#else
-#define MAP_BL2_TOTAL		MAP_REGION_FLAT(			\
-					bl2_tzram_layout.total_base,	\
-					bl2_tzram_layout.total_size,	\
-					MT_MEMORY | MT_RW | MT_SECURE)
-#endif /* ENABLE_RME */
+					MT_MEMORY | MT_RW | EL3_PAS)
 
 #pragma weak arm_bl2_plat_handle_post_image_load
 
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 73d96c5..580ef5f 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -363,7 +363,7 @@
 endif
 
 # Pointer Authentication sources
-ifeq (${ENABLE_PAUTH}, 1)
+ifeq ($(BRANCH_PROTECTION),$(filter $(BRANCH_PROTECTION),1 2 3))
 PLAT_BL_COMMON_SOURCES	+=	plat/arm/common/aarch64/arm_pauth.c
 endif
 
diff --git a/plat/arm/common/arm_ni.c b/plat/arm/common/arm_ni.c
index b3ad8b3..9c105f7 100644
--- a/plat/arm/common/arm_ni.c
+++ b/plat/arm/common/arm_ni.c
@@ -144,19 +144,33 @@
 
 	for (uint32_t i = 0U; i < vd_count; i++) {
 		vd_addr = global_cfg + mmio_read_32(global_cfg + NI_CHILD_POINTER(i));
+
+		VERBOSE("Voltage domain %u at 0x%lx node info: 0x%x\n",
+			i, vd_addr, mmio_read_32(vd_addr));
+
 		pd_count = mmio_read_32(vd_addr + NI_CHILD_NODE_COUNT);
 
 		for (uint32_t j = 0U; j < pd_count; j++) {
 			pd_addr = global_cfg + mmio_read_32(vd_addr + NI_CHILD_POINTER(j));
 			cd_count = mmio_read_32(pd_addr + NI_CHILD_NODE_COUNT);
 
+			VERBOSE("Power domain %u at 0x%lx node info: 0x%x\n",
+				j, pd_addr, mmio_read_32(pd_addr));
+
 			for (uint32_t k = 0U; k < cd_count; k++) {
 				cd_addr = global_cfg + mmio_read_32(pd_addr + NI_CHILD_POINTER(k));
 				comp_count = mmio_read_32(cd_addr + NI_CHILD_NODE_COUNT);
 
+				VERBOSE("Clock domain %u at 0x%lx node info: 0x%x\n",
+					k, cd_addr, mmio_read_32(cd_addr));
+
 				for (uint32_t l = 0U; l < comp_count; l++) {
 					comp_addr = global_cfg +
 						mmio_read_32(cd_addr + NI_CHILD_POINTER(l));
+
+					VERBOSE("Component %u at 0x%lx node info: 0x%x\n",
+						l, comp_addr, mmio_read_32(comp_addr));
+
 					ni_setup_component(comp_addr);
 				}
 			}
diff --git a/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.c b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.c
index 8c012e7..9eb348e 100644
--- a/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.c
+++ b/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.c
@@ -18,8 +18,6 @@
 #include <plat_mtk_lpm.h>
 #include <plat_pm.h>
 
-DEFINE_SYSREG_RW_FUNCS(dbgprcr_el1);
-
 static int plat_mt_lp_cpu_rc;
 
 static int pwr_state_prompt(unsigned int cpu, const psci_power_state_t *state)
diff --git a/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c b/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c
index b483c36..1df75f7 100644
--- a/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c
+++ b/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c
@@ -18,8 +18,6 @@
 #include <plat_mtk_lpm.h>
 #include <plat_pm.h>
 
-DEFINE_SYSREG_RW_FUNCS(dbgprcr_el1);
-
 static int plat_mt_lp_cpu_rc;
 
 static int pwr_state_prompt(unsigned int cpu, const psci_power_state_t *state)
diff --git a/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c b/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c
index 5a80d95..d32a7df 100644
--- a/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c
+++ b/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c
@@ -18,8 +18,6 @@
 #include <plat_mtk_lpm.h>
 #include <plat_pm.h>
 
-DEFINE_SYSREG_RW_FUNCS(dbgprcr_el1);
-
 static int plat_mt_lp_cpu_rc;
 
 static int pwr_state_prompt(unsigned int cpu, const psci_power_state_t *state)
diff --git a/plat/nuvoton/npcm845x/platform.mk b/plat/nuvoton/npcm845x/platform.mk
index 1959aac..d73756c 100644
--- a/plat/nuvoton/npcm845x/platform.mk
+++ b/plat/nuvoton/npcm845x/platform.mk
@@ -318,9 +318,8 @@
 endif
 
 # Pointer Authentication sources
-ifeq (${ENABLE_PAUTH}, 1)
-PLAT_BL_COMMON_SOURCES	+=	plat/arm/common/aarch64/arm_pauth.c \
-		lib/extensions/pauth/pauth_helpers.S
+ifeq ($(BRANCH_PROTECTION),$(filter $(BRANCH_PROTECTION),1 2 3))
+PLAT_BL_COMMON_SOURCES	+=	plat/arm/common/aarch64/arm_pauth.c
 endif
 
 ifeq (${SPD},spmd)
diff --git a/plat/qemu/common/common.mk b/plat/qemu/common/common.mk
index 51497bd..5e3a61a 100644
--- a/plat/qemu/common/common.mk
+++ b/plat/qemu/common/common.mk
@@ -149,9 +149,8 @@
 endif
 
 # Pointer Authentication sources
-ifeq (${ENABLE_PAUTH}, 1)
+ifeq ($(BRANCH_PROTECTION),$(filter $(BRANCH_PROTECTION),1 2 3))
 PLAT_BL_COMMON_SOURCES	+=	plat/arm/common/aarch64/arm_pauth.c
-CTX_INCLUDE_PAUTH_REGS	:=	1
 endif
 
 endif
diff --git a/plat/qemu/common/qemu_common.c b/plat/qemu/common/qemu_common.c
index 0bfb126..5dc39a1 100644
--- a/plat/qemu/common/qemu_common.c
+++ b/plat/qemu/common/qemu_common.c
@@ -258,6 +258,23 @@
 }
 #endif /* PLAT_qemu */
 
+/*
+ * Calculate checksum of 64-bit words @buffer, of @size bytes
+ */
+static uint64_t checksum_calc(uint64_t *buffer, size_t size)
+{
+	uint64_t sum = 0UL;
+
+	assert(((uintptr_t)buffer & (sizeof(uint64_t) - 1UL)) == 0UL);
+	assert((size & (sizeof(uint64_t) - 1UL)) == 0UL);
+
+	for (unsigned long i = 0UL; i < (size / sizeof(uint64_t)); i++) {
+		sum += buffer[i];
+	}
+
+	return sum;
+}
+
 int plat_rmmd_load_manifest(struct rmm_manifest *manifest)
 {
 	int i, last;
@@ -352,10 +369,12 @@
 	last = num_banks - 1;
 	for (i = 0; i < num_banks; i++) {
 		plat_get_memory_node(i, &bank_ptr[last]);
-		checksum += bank_ptr[last].base + bank_ptr[last].size;
 		last--;
 	}
 
+	checksum += checksum_calc((uint64_t *)bank_ptr,
+				  num_banks * sizeof(*bank_ptr));
+
 	/* Checksum must be 0 */
 	manifest->plat_dram.checksum = ~checksum + 1UL;
 
@@ -373,8 +392,8 @@
 	strlcpy(console_ptr[0].name, "pl011", sizeof(console_ptr[0].name));
 
 	/* Update checksum */
-	checksum += console_ptr[0].base + console_ptr[0].map_pages +
-		console_ptr[0].clk_in_hz + console_ptr[0].baud_rate;
+	checksum += checksum_calc((uint64_t *)console_ptr,
+				  num_consoles * sizeof(*console_ptr));
 
 	/* Checksum must be 0 */
 	manifest->plat_console.checksum = ~checksum + 1UL;
diff --git a/poetry.lock b/poetry.lock
index 91203d2..0349943 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,4 +1,4 @@
-# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
+# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand.
 
 [[package]]
 name = "alabaster"
@@ -399,13 +399,13 @@
 
 [[package]]
 name = "jinja2"
-version = "3.1.4"
+version = "3.1.5"
 description = "A very fast and expressive template engine."
 optional = false
 python-versions = ">=3.7"
 files = [
-    {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"},
-    {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"},
+    {file = "jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb"},
+    {file = "jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb"},
 ]
 
 [package.dependencies]
diff --git a/services/arm_arch_svc/arm_arch_svc_setup.c b/services/arm_arch_svc/arm_arch_svc_setup.c
index 5456164..6acd1b6 100644
--- a/services/arm_arch_svc/arm_arch_svc_setup.c
+++ b/services/arm_arch_svc/arm_arch_svc_setup.c
@@ -14,6 +14,9 @@
 #include <services/arm_arch_svc.h>
 #include <smccc_helpers.h>
 #include <plat/common/platform.h>
+#include <arch_features.h>
+#include <arch_helpers.h>
+#include <lib/el3_runtime/context_mgmt.h>
 
 static int32_t smccc_version(void)
 {
@@ -90,6 +93,12 @@
 		}
 		return 0; /* ERRATA_APPLIES || ERRATA_MISSING */
 #endif
+
+#if ARCH_FEATURE_AVAILABILITY
+	case SMCCC_ARCH_FEATURE_AVAILABILITY:
+		return SMC_ARCH_CALL_SUCCESS;
+#endif /* ARCH_FEATURE_AVAILABILITY */
+
 #endif /* __aarch64__ */
 
 	/* Fallthrough */
@@ -111,6 +120,91 @@
 	}
 	return SMC_ARCH_CALL_INVAL_PARAM;
 }
+
+/*
+ * Reads a system register, sanitises its value, and returns a bitmask
+ * representing which feature in that sysreg has been enabled by firmware. The
+ * bitmask is a 1:1 mapping to the register's fields.
+ */
+#if ARCH_FEATURE_AVAILABILITY
+static uintptr_t smccc_arch_feature_availability(u_register_t reg,
+						 void *handle,
+						 u_register_t flags)
+{
+	cpu_context_t *caller_context;
+	per_world_context_t *caller_per_world_context;
+	el3_state_t *state;
+	u_register_t bitmask, check;
+
+	/* check the caller security state */
+	if (is_caller_secure(flags)) {
+		caller_context = cm_get_context(SECURE);
+		caller_per_world_context = &per_world_context[CPU_CONTEXT_SECURE];
+	} else if (is_caller_non_secure(flags)) {
+		caller_context = cm_get_context(NON_SECURE);
+		caller_per_world_context = &per_world_context[CPU_CONTEXT_NS];
+	} else {
+#if ENABLE_RME
+		caller_context = cm_get_context(REALM);
+		caller_per_world_context = &per_world_context[CPU_CONTEXT_REALM];
+#else /* !ENABLE_RME */
+		assert(0); /* shouldn't be possible */
+#endif /* ENABLE_RME */
+	}
+
+	state = get_el3state_ctx(caller_context);
+
+	switch (reg) {
+	case SCR_EL3_OPCODE:
+		bitmask  = read_ctx_reg(state, CTX_SCR_EL3);
+		bitmask &= ~SCR_EL3_IGNORED;
+		check    = bitmask & ~SCR_EL3_FEATS;
+		bitmask &= SCR_EL3_FEATS;
+		bitmask ^= SCR_EL3_FLIPPED;
+		/* will only report 0 if neither is implemented */
+		if (is_feat_rng_trap_supported() || is_feat_rng_present())
+			bitmask |= SCR_TRNDR_BIT;
+		break;
+	case CPTR_EL3_OPCODE:
+		bitmask  = caller_per_world_context->ctx_cptr_el3;
+		check    = bitmask & ~CPTR_EL3_FEATS;
+		bitmask &= CPTR_EL3_FEATS;
+		bitmask ^= CPTR_EL3_FLIPPED;
+		break;
+	case MDCR_EL3_OPCODE:
+		bitmask  = read_ctx_reg(state, CTX_MDCR_EL3);
+		bitmask &= ~MDCR_EL3_IGNORED;
+		check    = bitmask & ~MDCR_EL3_FEATS;
+		bitmask &= MDCR_EL3_FEATS;
+		bitmask ^= MDCR_EL3_FLIPPED;
+		break;
+#if ENABLE_FEAT_MPAM
+	case MPAM3_EL3_OPCODE:
+		bitmask  = caller_per_world_context->ctx_mpam3_el3;
+		bitmask &= ~MPAM3_EL3_IGNORED;
+		check    = bitmask & ~MPAM3_EL3_FEATS;
+		bitmask &= MPAM3_EL3_FEATS;
+		bitmask ^= MPAM3_EL3_FLIPPED;
+		break;
+#endif /* ENABLE_FEAT_MPAM */
+	default:
+		SMC_RET2(handle, SMC_INVALID_PARAM, ULL(0));
+	}
+
+	/*
+	 * failing this means that the requested register has a bit set that
+	 * hasn't been declared as a known feature bit or an ignore bit. This is
+	 * likely to happen when support for a new feature is added but the
+	 * bitmask macros are not updated.
+	 */
+	if (ENABLE_ASSERTIONS && check != 0) {
+		ERROR("Unexpected bits 0x%lx were set in register %lx!\n", check, reg);
+		assert(0);
+	}
+
+	SMC_RET2(handle, SMC_ARCH_CALL_SUCCESS, bitmask);
+}
+#endif /* ARCH_FEATURE_AVAILABILITY */
 
 /*
  * Top-level Arm Architectural Service SMC handler.
@@ -161,6 +255,11 @@
 		SMC_RET0(handle);
 #endif
 #endif /* __aarch64__ */
+#if ARCH_FEATURE_AVAILABILITY
+	/* return is 64 bit so only reply on SMC64 requests */
+	case SMCCC_ARCH_FEATURE_AVAILABILITY | (SMC_64 << FUNCID_CC_SHIFT):
+		return smccc_arch_feature_availability(x1, handle, flags);
+#endif /* ARCH_FEATURE_AVAILABILITY */
 	default:
 		WARN("Unimplemented Arm Architecture Service Call: 0x%x \n",
 			smc_fid);
diff --git a/services/std_svc/rmmd/rmmd_main.c b/services/std_svc/rmmd/rmmd_main.c
index d063ea3..13ea5db 100644
--- a/services/std_svc/rmmd/rmmd_main.c
+++ b/services/std_svc/rmmd/rmmd_main.c
@@ -33,6 +33,8 @@
 #include <smccc_helpers.h>
 #include <lib/extensions/sme.h>
 #include <lib/extensions/sve.h>
+#include <lib/extensions/spe.h>
+#include <lib/extensions/trbe.h>
 #include "rmmd_initial_context.h"
 #include "rmmd_private.h"
 
@@ -127,6 +129,20 @@
 	if (is_feat_sme_supported()) {
 		sme_enable(ctx);
 	}
+
+	/*
+	 * SPE and TRBE cannot be fully disabled from EL3 registers alone, only
+	 * sysreg access can. In case the EL1 controls leave them active on
+	 * context switch, we want the owning security state to be NS so Realm
+	 * can't be DOSed.
+	 */
+	if (is_feat_spe_supported()) {
+		spe_disable(ctx);
+	}
+
+	if (is_feat_trbe_supported()) {
+		trbe_disable(ctx);
+	}
 }
 
 static void manage_extensions_realm_per_world(void)
diff --git a/tools/cot_dt2c/poetry.lock b/tools/cot_dt2c/poetry.lock
index df58d54..eea96cd 100644
--- a/tools/cot_dt2c/poetry.lock
+++ b/tools/cot_dt2c/poetry.lock
@@ -1,35 +1,6 @@
 # This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
 
 [[package]]
-name = "atomicwrites"
-version = "1.4.1"
-description = "Atomic file writes."
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-files = [
-    {file = "atomicwrites-1.4.1.tar.gz", hash = "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11"},
-]
-
-[[package]]
-name = "attrs"
-version = "24.2.0"
-description = "Classes Without Boilerplate"
-optional = false
-python-versions = ">=3.7"
-files = [
-    {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"},
-    {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"},
-]
-
-[package.extras]
-benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
-cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
-dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
-docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"]
-tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
-tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"]
-
-[[package]]
 name = "click"
 version = "8.1.7"
 description = "Composable command line interface toolkit"
@@ -54,6 +25,20 @@
     {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
 ]
 
+[[package]]
+name = "exceptiongroup"
+version = "1.2.2"
+description = "Backport of PEP 654 (exception groups)"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"},
+    {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"},
+]
+
+[package.extras]
+test = ["pytest (>=6)"]
+
 [[package]]
 name = "igraph"
 version = "0.11.6"
@@ -218,17 +203,6 @@
 testing = ["pytest", "pytest-benchmark"]
 
 [[package]]
-name = "py"
-version = "1.11.0"
-description = "library with cross-python path, ini-parsing, io, code, log facilities"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-files = [
-    {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
-    {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
-]
-
-[[package]]
 name = "pydevicetree"
 version = "0.0.13"
 description = "A library for parsing Devicetree Source v1"
@@ -258,27 +232,25 @@
 
 [[package]]
 name = "pytest"
-version = "6.2.5"
+version = "8.3.4"
 description = "pytest: simple powerful testing with Python"
 optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.8"
 files = [
-    {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"},
-    {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"},
+    {file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"},
+    {file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"},
 ]
 
 [package.dependencies]
-atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
-attrs = ">=19.2.0"
 colorama = {version = "*", markers = "sys_platform == \"win32\""}
+exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
 iniconfig = "*"
 packaging = "*"
-pluggy = ">=0.12,<2.0"
-py = ">=1.8.2"
-toml = "*"
+pluggy = ">=1.5,<2"
+tomli = {version = ">=1", markers = "python_version < \"3.11\""}
 
 [package.extras]
-testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
+dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
 
 [[package]]
 name = "tenacity"
@@ -318,6 +290,47 @@
 ]
 
 [[package]]
+name = "tomli"
+version = "2.2.1"
+description = "A lil' TOML parser"
+optional = false
+python-versions = ">=3.8"
+files = [
+    {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"},
+    {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"},
+    {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"},
+    {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"},
+    {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"},
+    {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"},
+    {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"},
+    {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"},
+    {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"},
+    {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"},
+    {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"},
+    {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"},
+    {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"},
+    {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"},
+    {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"},
+    {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"},
+    {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"},
+    {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"},
+    {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"},
+    {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"},
+    {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"},
+    {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"},
+    {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"},
+    {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"},
+    {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"},
+    {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"},
+    {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"},
+    {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"},
+    {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"},
+    {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"},
+    {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"},
+    {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"},
+]
+
+[[package]]
 name = "typing-extensions"
 version = "4.12.2"
 description = "Backported and Experimental Type Hints for Python 3.8+"
@@ -331,4 +344,4 @@
 [metadata]
 lock-version = "2.0"
 python-versions = "^3.8"
-content-hash = "afa5cb49be96467a848bab753a630c6f5ec42d6750d67d29920c3e3971774e36"
+content-hash = "0f5b2b008bb5de8545881eaeacfdd1a6fe50e5271feea4635d622ffce9e550dc"
diff --git a/tools/cot_dt2c/pyproject.toml b/tools/cot_dt2c/pyproject.toml
index 73251d7..fc31d54 100644
--- a/tools/cot_dt2c/pyproject.toml
+++ b/tools/cot_dt2c/pyproject.toml
@@ -38,7 +38,7 @@
 
 [tool.poetry.group.dev.dependencies]
 mypy = "^0.910"
-pytest = "^6.2.5"
+pytest = "^8.3.4"
 
 [tool.mypy]
 # https://mypy.readthedocs.io/en/latest/config_file.html#using-a-pyproject-toml-file
diff --git a/tools/tlc/poetry.lock b/tools/tlc/poetry.lock
index decec59..3c0cdf8 100644
--- a/tools/tlc/poetry.lock
+++ b/tools/tlc/poetry.lock
@@ -1,4 +1,4 @@
-# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
+# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand.
 
 [[package]]
 name = "astroid"
@@ -495,13 +495,13 @@
 
 [[package]]
 name = "jinja2"
-version = "3.1.4"
+version = "3.1.5"
 description = "A very fast and expressive template engine."
 optional = false
 python-versions = ">=3.7"
 files = [
-    {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"},
-    {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"},
+    {file = "jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb"},
+    {file = "jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb"},
 ]
 
 [package.dependencies]
@@ -1431,4 +1431,4 @@
 [metadata]
 lock-version = "2.0"
 python-versions = "^3.8"
-content-hash = "aac9123f3fa544b8c3e9b085f41f5a1c6c4ed2d59ce3236dcda6ea2aef5a694c"
+content-hash = "a4b9c3bababadba14f49a8de0ccee1f5a141b6cea23d02a19ab8bf4f8c45533f"
diff --git a/tools/tlc/pyproject.toml b/tools/tlc/pyproject.toml
index b606238..e9ff26f 100644
--- a/tools/tlc/pyproject.toml
+++ b/tools/tlc/pyproject.toml
@@ -39,7 +39,7 @@
 click = "^8.1.7"
 pyyaml = "^6.0.1"
 tox = "^4.18.0"
-jinja2 = "^3.1.4"
+jinja2 = "^3.1.5"
 
 [tool.poetry.group.dev]
 optional = true