Merge "feat(rk3576): support rk3576" into integration
diff --git a/Makefile b/Makefile
index 5682f93..a3aad12 100644
--- a/Makefile
+++ b/Makefile
@@ -1185,7 +1185,6 @@
 	DYN_DISABLE_AUTH \
 	EL3_EXCEPTION_HANDLING \
 	ENABLE_AMU_AUXILIARY_COUNTERS \
-	ENABLE_AMU_FCONF \
 	AMU_RESTRICT_COUNTERS \
 	ENABLE_ASSERTIONS \
 	ENABLE_PIE \
@@ -1252,7 +1251,6 @@
 	PSA_FWU_METADATA_FW_STORE_DESC \
 	ENABLE_MPMM \
 	FEAT_PABANDON \
-	ENABLE_MPMM_FCONF \
 	FEATURE_DETECTION \
 	TRNG_SUPPORT \
 	ENABLE_ERRATA_ALL \
@@ -1361,7 +1359,6 @@
 	DISABLE_MTPMU \
 	ENABLE_FEAT_AMU \
 	ENABLE_AMU_AUXILIARY_COUNTERS \
-	ENABLE_AMU_FCONF \
 	AMU_RESTRICT_COUNTERS \
 	ENABLE_ASSERTIONS \
 	ENABLE_BTI \
@@ -1454,7 +1451,6 @@
 	ENABLE_FEAT_HCX \
 	ENABLE_MPMM \
 	FEAT_PABANDON \
-	ENABLE_MPMM_FCONF \
 	ENABLE_FEAT_FGT \
 	ENABLE_FEAT_FGT2 \
 	ENABLE_FEAT_FPMR \
diff --git a/bl1/bl1.mk b/bl1/bl1.mk
index a8a0061..c068ea5 100644
--- a/bl1/bl1.mk
+++ b/bl1/bl1.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -18,8 +18,7 @@
 				${MBEDTLS_SOURCES}
 
 ifeq (${ARCH},aarch64)
-BL1_SOURCES		+=	lib/cpus/aarch64/dsu_helpers.S		\
-				lib/el3_runtime/aarch64/context.S	\
+BL1_SOURCES		+=	lib/el3_runtime/aarch64/context.S	\
 				lib/cpus/errata_common.c
 endif
 
diff --git a/bl2/bl2.mk b/bl2/bl2.mk
index 850d826..2a212e1 100644
--- a/bl2/bl2.mk
+++ b/bl2/bl2.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -43,10 +43,6 @@
 				bl2/${ARCH}/bl2_run_next_image.S        \
 				lib/cpus/${ARCH}/cpu_helpers.S
 
-ifeq (${ARCH},aarch64)
-BL2_SOURCES		+=	lib/cpus/aarch64/dsu_helpers.S
-endif
-
 BL2_DEFAULT_LINKER_SCRIPT_SOURCE := bl2/bl2_el3.ld.S
 endif
 
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index 2f9dc65..e390915 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -24,7 +24,6 @@
 endif
 
 include lib/extensions/amu/amu.mk
-include lib/mpmm/mpmm.mk
 
 ifeq (${SPMC_AT_EL3},1)
   $(info Including EL3 SPMC makefile)
@@ -43,7 +42,6 @@
 				bl31/bl31_traps.c				\
 				common/runtime_svc.c				\
 				lib/cpus/errata_common.c			\
-				lib/cpus/aarch64/dsu_helpers.S			\
 				plat/common/aarch64/platform_mp_stack.S		\
 				services/arm_arch_svc/arm_arch_svc_setup.c	\
 				services/std_svc/std_svc_setup.c		\
@@ -115,10 +113,6 @@
 BL31_SOURCES		+=	lib/extensions/tcr/tcr2.c
 endif
 
-ifeq (${ENABLE_MPMM},1)
-BL31_SOURCES		+=	${MPMM_SOURCES}
-endif
-
 ifneq (${ENABLE_SME_FOR_NS},0)
 BL31_SOURCES		+=	lib/extensions/sme/sme.c
 endif
diff --git a/bl31/bl31_main.c b/bl31/bl31_main.c
index 83be0f6..db0ea6c 100644
--- a/bl31/bl31_main.c
+++ b/bl31/bl31_main.c
@@ -127,7 +127,7 @@
 void bl31_main(void)
 {
 	/* Init registers that never change for the lifetime of TF-A */
-	cm_manage_extensions_el3();
+	cm_manage_extensions_el3(plat_my_core_pos());
 
 	/* Init per-world context registers for non-secure world */
 	manage_extensions_nonsecure_per_world();
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index 210ae7e..7914f6d 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -447,8 +447,7 @@
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 :|M|: Chris Kay <chris.kay@arm.com>
 :|G|: `CJKay`_
-:|F|: include/lib/mpmm/
-:|F|: lib/mpmm/
+:|F|: include/lib/cpus/aarch64/cpu_macros.S
 
 Granule Protection Tables Library (GPT-RME)
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/docs/components/activity-monitors.rst b/docs/components/activity-monitors.rst
index 5c1c2c2..4c33d42 100644
--- a/docs/components/activity-monitors.rst
+++ b/docs/components/activity-monitors.rst
@@ -20,15 +20,9 @@
 build option.
 
 As a security precaution, Trusted Firmware-A does not enable these by default.
-Instead, platforms may configure their auxiliary counters through one of two
-possible mechanisms:
-
-- |FCONF|, controlled by the ``ENABLE_AMU_FCONF`` build option.
-- A platform implementation of the ``plat_amu_topology`` function (the default).
-
-See :ref:`Activity Monitor Unit (AMU) Bindings` for documentation on the |FCONF|
-device tree bindings.
+Instead, platforms must configure their auxiliary counters through the
+``plat_amu_aux_enables`` platform hook.
 
 --------------
 
-*Copyright (c) 2021, Arm Limited. All rights reserved.*
+*Copyright (c) 2021-2025, Arm Limited. All rights reserved.*
diff --git a/docs/components/context-management-library.rst b/docs/components/context-management-library.rst
index 6a76ada..8cb1ace 100644
--- a/docs/components/context-management-library.rst
+++ b/docs/components/context-management-library.rst
@@ -498,7 +498,6 @@
 
 	typedef struct per_world_context {
 		uint64_t ctx_cptr_el3;
-		uint64_t ctx_zcr_el3;
 		uint64_t ctx_mpam3_el3;
 	} per_world_context_t;
 
@@ -555,7 +554,7 @@
 EL3 execution context needs to setup at both boot time (cold and warm boot)
 entrypaths and at all the possible exception handlers routing to EL3 at runtime.
 
-*Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.*
 
 .. |Context Memory Allocation| image:: ../resources/diagrams/context_memory_allocation.png
 .. |CPU Context Memory Configuration| image:: ../resources/diagrams/cpu_data_config_context_memory.png
diff --git a/docs/components/fconf/amu-bindings.rst b/docs/components/fconf/amu-bindings.rst
deleted file mode 100644
index 047f75e..0000000
--- a/docs/components/fconf/amu-bindings.rst
+++ /dev/null
@@ -1,142 +0,0 @@
-Activity Monitor Unit (AMU) Bindings
-====================================
-
-To support platform-defined Activity Monitor Unit (|AMU|) auxiliary counters
-through FCONF, the ``HW_CONFIG`` device tree accepts several |AMU|-specific
-nodes and properties.
-
-Bindings
-^^^^^^^^
-
-.. contents::
-    :local:
-
-``/cpus/cpus/cpu*`` node properties
-"""""""""""""""""""""""""""""""""""
-
-The ``cpu`` node has been augmented to support a handle to an associated |AMU|
-view, which should describe the counters offered by the core.
-
-+---------------+-------+---------------+-------------------------------------+
-| Property name | Usage | Value type    | Description                         |
-+===============+=======+===============+=====================================+
-| ``amu``       | O     | ``<phandle>`` | If present, indicates that an |AMU| |
-|               |       |               | is available and its counters are   |
-|               |       |               | described by the node provided.     |
-+---------------+-------+---------------+-------------------------------------+
-
-``/cpus/amus`` node properties
-""""""""""""""""""""""""""""""
-
-The ``amus`` node describes the |AMUs| implemented by the cores in the system.
-This node does not have any properties.
-
-``/cpus/amus/amu*`` node properties
-"""""""""""""""""""""""""""""""""""
-
-An ``amu`` node describes the layout and meaning of the auxiliary counter
-registers of one or more |AMUs|, and may be shared by multiple cores.
-
-+--------------------+-------+------------+------------------------------------+
-| Property name      | Usage | Value type | Description                        |
-+====================+=======+============+====================================+
-| ``#address-cells`` | R     | ``<u32>``  | Value shall be 1. Specifies that   |
-|                    |       |            | the ``reg`` property array of      |
-|                    |       |            | children of this node uses a       |
-|                    |       |            | single cell.                       |
-+--------------------+-------+------------+------------------------------------+
-| ``#size-cells``    | R     | ``<u32>``  | Value shall be 0. Specifies that   |
-|                    |       |            | no size is required in the ``reg`` |
-|                    |       |            | property in children of this node. |
-+--------------------+-------+------------+------------------------------------+
-
-``/cpus/amus/amu*/counter*`` node properties
-""""""""""""""""""""""""""""""""""""""""""""
-
-A ``counter`` node describes an auxiliary counter belonging to the parent |AMU|
-view.
-
-+-------------------+-------+-------------+------------------------------------+
-| Property name     | Usage | Value type  | Description                        |
-+===================+=======+=============+====================================+
-| ``reg``           | R     | array       | Represents the counter register    |
-|                   |       |             | index, and must be a single cell.  |
-+-------------------+-------+-------------+------------------------------------+
-| ``enable-at-el3`` | O     | ``<empty>`` | The presence of this property      |
-|                   |       |             | indicates that this counter should |
-|                   |       |             | be enabled prior to EL3 exit.      |
-+-------------------+-------+-------------+------------------------------------+
-
-Example
-^^^^^^^
-
-An example system offering four cores made up of two clusters, where the cores
-of each cluster share different |AMUs|, may use something like the following:
-
-.. code-block::
-
-    cpus {
-        #address-cells = <2>;
-        #size-cells = <0>;
-
-        amus {
-            amu0: amu-0 {
-                #address-cells = <1>;
-                #size-cells = <0>;
-
-                counterX: counter@0 {
-                    reg = <0>;
-
-                    enable-at-el3;
-                };
-
-                counterY: counter@1 {
-                    reg = <1>;
-
-                    enable-at-el3;
-                };
-            };
-
-            amu1: amu-1 {
-                #address-cells = <1>;
-                #size-cells = <0>;
-
-                counterZ: counter@0 {
-                    reg = <0>;
-
-                    enable-at-el3;
-                };
-            };
-        };
-
-        cpu0@00000 {
-            ...
-
-            amu = <&amu0>;
-        };
-
-        cpu1@00100 {
-            ...
-
-            amu = <&amu0>;
-        };
-
-        cpu2@10000 {
-            ...
-
-            amu = <&amu1>;
-        };
-
-        cpu3@10100 {
-            ...
-
-            amu = <&amu1>;
-        };
-    }
-
-In this situation, ``cpu0`` and ``cpu1`` (the two cores in the first cluster),
-share the view of their AMUs defined by ``amu0``. Likewise, ``cpu2`` and
-``cpu3`` (the two cores in the second cluster), share the view of their |AMUs|
-defined by ``amu1``. This will cause ``counterX`` and ``counterY`` to be enabled
-for both ``cpu0`` and ``cpu1``, and ``counterZ`` to be enabled for both ``cpu2``
-and ``cpu3``.
diff --git a/docs/components/fconf/index.rst b/docs/components/fconf/index.rst
index b8b4519..6cb6774 100644
--- a/docs/components/fconf/index.rst
+++ b/docs/components/fconf/index.rst
@@ -145,6 +145,4 @@
   :maxdepth: 1
 
   fconf_properties
-  amu-bindings
-  mpmm-bindings
   tb_fw_bindings
diff --git a/docs/components/fconf/mpmm-bindings.rst b/docs/components/fconf/mpmm-bindings.rst
deleted file mode 100644
index d3cc857..0000000
--- a/docs/components/fconf/mpmm-bindings.rst
+++ /dev/null
@@ -1,48 +0,0 @@
-Maximum Power Mitigation Mechanism (MPMM) Bindings
-==================================================
-
-|MPMM| support cannot be determined at runtime by the firmware. Instead, these
-DTB bindings allow the platform to communicate per-core support for |MPMM| via
-the ``HW_CONFIG`` device tree blob.
-
-Bindings
-^^^^^^^^
-
-.. contents::
-    :local:
-
-``/cpus/cpus/cpu*`` node properties
-"""""""""""""""""""""""""""""""""""
-
-The ``cpu`` node has been augmented to allow the platform to indicate support
-for |MPMM| on a given core.
-
-+-------------------+-------+-------------+------------------------------------+
-| Property name     | Usage | Value type  | Description                        |
-+===================+=======+=============+====================================+
-| ``supports-mpmm`` | O     | ``<empty>`` | If present, indicates that |MPMM|  |
-|                   |       |             | is available on this core.         |
-+-------------------+-------+-------------+------------------------------------+
-
-Example
-^^^^^^^
-
-An example system offering two cores, one with support for |MPMM| and one
-without, can be described as follows:
-
-.. code-block::
-
-    cpus {
-        #address-cells = <2>;
-        #size-cells = <0>;
-
-        cpu0@00000 {
-            ...
-
-            supports-mpmm;
-        };
-
-        cpu1@00100 {
-            ...
-        };
-    }
diff --git a/docs/components/mpmm.rst b/docs/components/mpmm.rst
index 1b1c6d8..aaa9481 100644
--- a/docs/components/mpmm.rst
+++ b/docs/components/mpmm.rst
@@ -8,16 +8,7 @@
 triggering of whole-rail (i.e. clock chopping) responses to overcurrent
 conditions.
 
-|MPMM| is enabled on a per-core basis by the EL3 runtime firmware. The presence
-of |MPMM| cannot be determined at runtime by the firmware, and therefore the
-platform must expose this information through one of two possible mechanisms:
-
-- |FCONF|, controlled by the ``ENABLE_MPMM_FCONF`` build option.
-- A platform implementation of the ``plat_mpmm_topology`` function (the
-  default).
-
-See :ref:`Maximum Power Mitigation Mechanism (MPMM) Bindings` for documentation
-on the |FCONF| device tree bindings.
+|MPMM| is enabled on a per-core basis by the EL3 runtime firmware.
 
 .. warning::
 
diff --git a/docs/design/firmware-design.rst b/docs/design/firmware-design.rst
index cda80ca..cf8cbc7 100644
--- a/docs/design/firmware-design.rst
+++ b/docs/design/firmware-design.rst
@@ -247,7 +247,7 @@
 
 -  CPU initialization
 
-   BL1 calls the ``reset_handler()`` function which in turn calls the CPU
+   BL1 calls the ``reset_handler`` macro/function which in turn calls the CPU
    specific reset handler function (see the section: "CPU specific operations
    framework").
 
@@ -1337,7 +1337,7 @@
 
 TF-A implements a framework that allows CPU and platform ports to perform
 actions very early after a CPU is released from reset in both the cold and warm
-boot paths. This is done by calling the ``reset_handler()`` function in both
+boot paths. This is done by calling the ``reset_handler`` macro/function in both
 the BL1 and BL31 images. It in turn calls the platform and CPU specific reset
 handling functions.
 
@@ -1481,7 +1481,9 @@
 handling for that CPU and also any errata workarounds enabled by the platform.
 
 It should be defined using the ``cpu_reset_func_{start,end}`` macros and its
-body may only clobber x0 to x14 with x14 being the cpu_rev parameter.
+body may only clobber x0 to x14 with x14 being the cpu_rev parameter. The cpu
+file should also include a call to ``cpu_reset_prologue`` at the start of the
+file for errata to work correctly.
 
 CPU specific power down sequence
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2904,7 +2906,7 @@
 
 --------------
 
-*Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.*
 
 .. _SMCCC: https://developer.arm.com/docs/den0028/latest
 .. _PSCI: https://developer.arm.com/documentation/den0022/latest/
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 8840e7f..2b36fda 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -258,10 +258,6 @@
    (also known as group 1 counters). These are implementation-defined counters,
    and as such require additional platform configuration. Default is 0.
 
--  ``ENABLE_AMU_FCONF``: Enables configuration of the AMU through FCONF, which
-   allows platforms with auxiliary counters to describe them via the
-   ``HW_CONFIG`` device tree blob. Default is 0.
-
 -  ``ENABLE_ASSERTIONS``: This option controls whether or not calls to ``assert()``
    are compiled out. For debug builds, this option defaults to 1, and calls to
    ``assert()`` are left in place. For release builds, this option defaults to 0
@@ -532,10 +528,6 @@
    introduces a performance penalty. Once this is removed, this option will be
    removed and the feature will be enabled by default. Defaults to ``0``.
 
--  ``ENABLE_MPMM_FCONF``: Enables configuration of MPMM through FCONF, which
-   allows platforms with cores supporting MPMM to describe them via the
-   ``HW_CONFIG`` device tree blob. Default is 0.
-
 -  ``ENABLE_PIE``: Boolean option to enable Position Independent Executable(PIE)
    support within generic code in TF-A. This option is currently only supported
    in BL2, BL31, and BL32 (TSP) for AARCH64 binaries, and
diff --git a/fdts/tc-base.dtsi b/fdts/tc-base.dtsi
index fc0b3b6..ac08e0b 100644
--- a/fdts/tc-base.dtsi
+++ b/fdts/tc-base.dtsi
@@ -104,28 +104,6 @@
 			};
 		};
 
-		amus {
-			amu: amu-0 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-
-				mpmm_gear0: counter@0 {
-					reg = <0>;
-					enable-at-el3;
-				};
-
-				mpmm_gear1: counter@1 {
-					reg = <1>;
-					enable-at-el3;
-				};
-
-				mpmm_gear2: counter@2 {
-					reg = <2>;
-					enable-at-el3;
-				};
-			};
-		};
-
 		CPU0:cpu@0 {
 			device_type = "cpu";
 			compatible = "arm,armv8";
@@ -134,8 +112,6 @@
 			clocks = <&scmi_dvfs 0>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 			capacity-dmips-mhz = <LIT_CAPACITY>;
-			amu = <&amu>;
-			supports-mpmm;
 		};
 
 		CPU1:cpu@100 {
@@ -146,8 +122,6 @@
 			clocks = <&scmi_dvfs 0>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 			capacity-dmips-mhz = <LIT_CAPACITY>;
-			amu = <&amu>;
-			supports-mpmm;
 		};
 
 		CPU2:cpu@200 {
@@ -156,8 +130,6 @@
 			reg = <0x200>;
 			enable-method = "psci";
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			amu = <&amu>;
-			supports-mpmm;
 		};
 
 		CPU3:cpu@300 {
@@ -166,8 +138,6 @@
 			reg = <0x300>;
 			enable-method = "psci";
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			amu = <&amu>;
-			supports-mpmm;
 		};
 
 		CPU4:cpu@400 {
@@ -178,8 +148,6 @@
 			clocks = <&scmi_dvfs 1>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 			capacity-dmips-mhz = <MID_CAPACITY>;
-			amu = <&amu>;
-			supports-mpmm;
 		};
 
 		CPU5:cpu@500 {
@@ -190,8 +158,6 @@
 			clocks = <&scmi_dvfs 1>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 			capacity-dmips-mhz = <MID_CAPACITY>;
-			amu = <&amu>;
-			supports-mpmm;
 		};
 
 		CPU6:cpu@600 {
@@ -200,8 +166,6 @@
 			reg = <0x600>;
 			enable-method = "psci";
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			amu = <&amu>;
-			supports-mpmm;
 		};
 
 		CPU7:cpu@700 {
@@ -210,8 +174,6 @@
 			reg = <0x700>;
 			enable-method = "psci";
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			amu = <&amu>;
-			supports-mpmm;
 		};
 	};
 
diff --git a/fdts/tc2.dts b/fdts/tc2.dts
index 8aa77ce..fa16dcd 100644
--- a/fdts/tc2.dts
+++ b/fdts/tc2.dts
@@ -123,8 +123,6 @@
 			enable-method = "psci";
 			clocks = <&scmi_dvfs 1>;
 			capacity-dmips-mhz = <MID_CAPACITY>;
-			amu = <&amu>;
-			supports-mpmm;
 		};
 
 		CPU9:cpu@900 {
@@ -134,8 +132,6 @@
 			enable-method = "psci";
 			clocks = <&scmi_dvfs 2>;
 			capacity-dmips-mhz = <BIG2_CAPACITY>;
-			amu = <&amu>;
-			supports-mpmm;
 		};
 
 		CPU10:cpu@A00 {
@@ -145,8 +141,6 @@
 			enable-method = "psci";
 			clocks = <&scmi_dvfs 2>;
 			capacity-dmips-mhz = <BIG2_CAPACITY>;
-			amu = <&amu>;
-			supports-mpmm;
 		};
 
 		CPU11:cpu@B00 {
@@ -156,8 +150,6 @@
 			enable-method = "psci";
 			clocks = <&scmi_dvfs 2>;
 			capacity-dmips-mhz = <BIG2_CAPACITY>;
-			amu = <&amu>;
-			supports-mpmm;
 		};
 
 		CPU12:cpu@C00 {
@@ -167,8 +159,6 @@
 			enable-method = "psci";
 			clocks = <&scmi_dvfs 3>;
 			capacity-dmips-mhz = <BIG_CAPACITY>;
-			amu = <&amu>;
-			supports-mpmm;
 		};
 
 		CPU13:cpu@D00 {
@@ -178,8 +168,6 @@
 			enable-method = "psci";
 			clocks = <&scmi_dvfs 3>;
 			capacity-dmips-mhz = <BIG_CAPACITY>;
-			amu = <&amu>;
-			supports-mpmm;
 		};
 #endif
 	};
diff --git a/include/arch/aarch32/arch.h b/include/arch/aarch32/arch.h
index d2591dd..41be1a1 100644
--- a/include/arch/aarch32/arch.h
+++ b/include/arch/aarch32/arch.h
@@ -761,7 +761,7 @@
 
 /* AMCNTENSET0 definitions */
 #define AMCNTENSET0_Pn_SHIFT	U(0)
-#define AMCNTENSET0_Pn_MASK	U(0xffff)
+#define AMCNTENSET0_Pn_MASK	U(0xf)
 
 /* AMCNTENSET1 definitions */
 #define AMCNTENSET1_Pn_SHIFT	U(0)
@@ -769,7 +769,7 @@
 
 /* AMCNTENCLR0 definitions */
 #define AMCNTENCLR0_Pn_SHIFT	U(0)
-#define AMCNTENCLR0_Pn_MASK	U(0xffff)
+#define AMCNTENCLR0_Pn_MASK	U(0xf)
 
 /* AMCNTENCLR1 definitions */
 #define AMCNTENCLR1_Pn_SHIFT	U(0)
diff --git a/include/arch/aarch32/arch_features.h b/include/arch/aarch32/arch_features.h
index e347240..e80faf2 100644
--- a/include/arch/aarch32/arch_features.h
+++ b/include/arch/aarch32/arch_features.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -85,6 +85,10 @@
 CREATE_FEATURE_FUNCS(feat_amu, id_pfr0, ID_PFR0_AMU_SHIFT,
 		    ID_PFR0_AMU_MASK, ID_PFR0_AMU_V1, ENABLE_FEAT_AMU)
 
+/* Auxiliary counters for FEAT_AMU */
+CREATE_FEATURE_FUNCS(feat_amu_aux, amcfgr, AMCFGR_NCG_SHIFT,
+		    AMCFGR_NCG_MASK, 1U, ENABLE_AMU_AUXILIARY_COUNTERS)
+
 /* FEAT_AMUV1P1: AMU Extension v1.1 */
 CREATE_FEATURE_FUNCS(feat_amuv1p1, id_pfr0, ID_PFR0_AMU_SHIFT,
 		    ID_PFR0_AMU_MASK, ID_PFR0_AMU_V1P1, ENABLE_FEAT_AMUv1p1)
diff --git a/include/arch/aarch32/arch_helpers.h b/include/arch/aarch32/arch_helpers.h
index adc96ae..4f80e3a 100644
--- a/include/arch/aarch32/arch_helpers.h
+++ b/include/arch/aarch32/arch_helpers.h
@@ -324,6 +324,23 @@
 DEFINE_COPROCR_RW_FUNCS_64(amevcntr02, AMEVCNTR02)
 DEFINE_COPROCR_RW_FUNCS_64(amevcntr03, AMEVCNTR03)
 
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr10, AMEVCNTR10);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr11, AMEVCNTR11);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr12, AMEVCNTR12);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr13, AMEVCNTR13);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr14, AMEVCNTR14);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr15, AMEVCNTR15);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr16, AMEVCNTR16);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr17, AMEVCNTR17);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr18, AMEVCNTR18);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr19, AMEVCNTR19);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr1a, AMEVCNTR1A);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr1b, AMEVCNTR1B);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr1c, AMEVCNTR1C);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr1d, AMEVCNTR1D);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr1e, AMEVCNTR1E);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr1f, AMEVCNTR1F);
+
 /*
  * TLBI operation prototypes
  */
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index fdf5a21..85b33aa 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -1530,6 +1530,11 @@
 #define SCTLR2_EL1		S3_0_C1_C0_3
 
 /*******************************************************************************
+ * FEAT_BRBE - Branch Record Buffer Extension Registers
+ ******************************************************************************/
+#define BRBCR_EL2		S2_4_C9_C0_0
+
+/*******************************************************************************
  * FEAT_LS64_ACCDATA - LoadStore64B with status data
  ******************************************************************************/
 #define ACCDATA_EL1		S3_0_C13_C0_5
@@ -1555,12 +1560,10 @@
  ******************************************************************************/
 
 #define CPUPPMCR_EL3			S3_6_C15_C2_0
-#define CPUPPMCR_EL3_MPMMPINCTL_SHIFT	UINT64_C(0)
-#define CPUPPMCR_EL3_MPMMPINCTL_MASK	UINT64_C(0x1)
+#define CPUPPMCR_EL3_MPMMPINCTL_BIT	BIT(0)
 
 #define CPUMPMMCR_EL3			S3_6_C15_C2_1
-#define CPUMPMMCR_EL3_MPMM_EN_SHIFT	UINT64_C(0)
-#define CPUMPMMCR_EL3_MPMM_EN_MASK	UINT64_C(0x1)
+#define CPUMPMMCR_EL3_MPMM_EN_BIT	BIT(0)
 
 /* alternative system register encoding for the "sb" speculation barrier */
 #define SYSREG_SB			S0_3_C3_C0_7
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index 1d0a2e0..a580213 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -311,6 +311,10 @@
 CREATE_FEATURE_FUNCS(feat_amu, id_aa64pfr0_el1, ID_AA64PFR0_AMU_SHIFT,
 		     ID_AA64PFR0_AMU_MASK, 1U, ENABLE_FEAT_AMU)
 
+/* Auxiliary counters for FEAT_AMU */
+CREATE_FEATURE_FUNCS(feat_amu_aux, amcfgr_el0, AMCFGR_EL0_NCG_SHIFT,
+		     AMCFGR_EL0_NCG_MASK, 1U, ENABLE_AMU_AUXILIARY_COUNTERS)
+
 /* FEAT_AMUV1P1: AMU Extension v1.1 */
 CREATE_FEATURE_FUNCS(feat_amuv1p1, id_aa64pfr0_el1, ID_AA64PFR0_AMU_SHIFT,
 		     ID_AA64PFR0_AMU_MASK, ID_AA64PFR0_AMU_V1P1, ENABLE_FEAT_AMUv1p1)
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index 4b08337..f85da97 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -564,6 +564,27 @@
 DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset0_el0, AMCNTENSET0_EL0)
 DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr1_el0, AMCNTENCLR1_EL0)
 DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset1_el0, AMCNTENSET1_EL0)
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr00_el0, AMEVCNTR00_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr01_el0, AMEVCNTR01_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr02_el0, AMEVCNTR02_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr03_el0, AMEVCNTR03_EL0);
+
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr10_el0, AMEVCNTR10_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr11_el0, AMEVCNTR11_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr12_el0, AMEVCNTR12_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr13_el0, AMEVCNTR13_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr14_el0, AMEVCNTR14_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr15_el0, AMEVCNTR15_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr16_el0, AMEVCNTR16_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr17_el0, AMEVCNTR17_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr18_el0, AMEVCNTR18_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr19_el0, AMEVCNTR19_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr1a_el0, AMEVCNTR1A_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr1b_el0, AMEVCNTR1B_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr1c_el0, AMEVCNTR1C_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr1d_el0, AMEVCNTR1D_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr1e_el0, AMEVCNTR1E_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr1f_el0, AMEVCNTR1F_EL0);
 
 DEFINE_RENAME_SYSREG_RW_FUNCS(pmblimitr_el1, PMBLIMITR_EL1)
 
@@ -716,6 +737,9 @@
 DEFINE_RENAME_SYSREG_RW_FUNCS(cpuppmcr_el3, CPUPPMCR_EL3)
 DEFINE_RENAME_SYSREG_RW_FUNCS(cpumpmmcr_el3, CPUMPMMCR_EL3)
 
+/* Armv9.1 FEAT_BRBE Registers */
+DEFINE_RENAME_SYSREG_RW_FUNCS(brbcr_el2, BRBCR_EL2)
+
 /* Armv9.2 RME Registers */
 DEFINE_RENAME_SYSREG_RW_FUNCS(gptbr_el3, GPTBR_EL3)
 DEFINE_RENAME_SYSREG_RW_FUNCS(gpccr_el3, GPCCR_EL3)
diff --git a/include/arch/aarch64/asm_macros.S b/include/arch/aarch64/asm_macros.S
index ff01278..dce07d9 100644
--- a/include/arch/aarch64/asm_macros.S
+++ b/include/arch/aarch64/asm_macros.S
@@ -8,6 +8,7 @@
 
 #include <arch.h>
 #include <common/asm_macros_common.S>
+#include <lib/cpus/cpu_ops.h>
 #include <lib/spinlock.h>
 
 /*
@@ -340,4 +341,26 @@
 	mrs	\reg, ID_AA64ISAR2_EL1
 	ands	\reg, \reg, #(ID_AA64ISAR2_SYSREG128_MASK << ID_AA64ISAR2_SYSREG128_SHIFT)
 	.endm
+
+.macro call_reset_handler
+#if !(defined(IMAGE_BL2) && ENABLE_RME)
+	/* ---------------------------------------------------------------------
+	 * It is a cold boot.
+	 * Perform any processor specific actions upon reset e.g. cache, TLB
+	 * invalidations etc.
+	 * ---------------------------------------------------------------------
+	 */
+	/* The plat_reset_handler can clobber x0 - x18, x30 */
+	bl	plat_reset_handler
+
+	/* Get the matching cpu_ops pointer */
+	bl	get_cpu_ops_ptr
+
+	/* Get the cpu_ops reset handler */
+	ldr	x2, [x0, #CPU_RESET_FUNC]
+
+	/* The cpu_ops reset handler can clobber x0 - x19, x30 */
+	blr	x2
+#endif
+.endm
 #endif /* ASM_MACROS_S */
diff --git a/include/arch/aarch64/el2_common_macros.S b/include/arch/aarch64/el2_common_macros.S
index b9b0e3d..5db6831 100644
--- a/include/arch/aarch64/el2_common_macros.S
+++ b/include/arch/aarch64/el2_common_macros.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2024, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -293,7 +293,7 @@
 	 * invalidations etc.
 	 * ---------------------------------------------------------------------
 	 */
-	bl	reset_handler
+	call_reset_handler
 
 	el2_arch_init_common
 
diff --git a/include/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S
index 204625c..2f2aeaf 100644
--- a/include/arch/aarch64/el3_common_macros.S
+++ b/include/arch/aarch64/el3_common_macros.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -49,7 +49,9 @@
 	 * due to a NULL TPIDR_EL3.
 	 * ---------------------------------------------------------------------
 	 */
-	bl	init_cpu_data_ptr
+	bl	plat_my_core_pos
+	bl	_cpu_data_by_index
+	msr	tpidr_el3, x0
 #endif /* IMAGE_BL31 */
 
 	/* ---------------------------------------------------------------------
@@ -219,15 +221,7 @@
 	msr	vbar_el3, x0
 	isb
 
-#if !(defined(IMAGE_BL2) && ENABLE_RME)
-	/* ---------------------------------------------------------------------
-	 * It is a cold boot.
-	 * Perform any processor specific actions upon reset e.g. cache, TLB
-	 * invalidations etc.
-	 * ---------------------------------------------------------------------
-	 */
-	bl	reset_handler
-#endif
+	call_reset_handler
 
 	el3_arch_init_common
 
@@ -460,6 +454,10 @@
 	 *  Necessary on PMUv3 <= p7 where MDCR_EL3.{SCCD,MCCD} are not
 	 *  available.
 	 *
+	 * CPTR_EL3.EZ: Set to one so that accesses to ZCR_EL3 do not trap
+	 * CPTR_EL3.TFP: Set to zero so that advanced SIMD operations don't trap
+	 * CPTR_EL3.ESM: Set to one so that SME related registers don't trap
+	 *
 	 * PSTATE.DIT: Set to one to enable the Data Independent Timing (DIT)
 	 *  functionality, if implemented in EL3.
 	 * ---------------------------------------------------------------------
@@ -479,6 +477,12 @@
 		orr	x15, x15, #PMCR_EL0_DP_BIT
 		msr	pmcr_el0, x15
 
+		mrs	x15, cptr_el3
+		orr	x15, x15, #CPTR_EZ_BIT
+		orr	x15, x15, #ESM_BIT
+		bic	x15, x15, #TFP_BIT
+		msr	cptr_el3, x15
+
 #if ENABLE_FEAT_DIT
 #if ENABLE_FEAT_DIT > 1
 		mrs	x15, id_aa64pfr0_el1
diff --git a/include/lib/cpus/aarch32/cpu_macros.S b/include/lib/cpus/aarch32/cpu_macros.S
index cfa5831..31f8811 100644
--- a/include/lib/cpus/aarch32/cpu_macros.S
+++ b/include/lib/cpus/aarch32/cpu_macros.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -48,8 +48,7 @@
 	 * _midr:
 	 *	Numeric value expected to read from CPU's MIDR
 	 * _resetfunc:
-	 *	Reset function for the CPU. If there's no CPU reset function,
-	 *	specify CPU_NO_RESET_FUNC
+	 *	Reset function for the CPU
 	 * _power_down_ops:
 	 *	Comma-separated list of functions to perform power-down
 	 *	operatios on the CPU. At least one, and up to
@@ -173,11 +172,6 @@
 		\_cpu\()_errata_list_start:
 		.endif
 
-		/* unused on AArch32, maintain for portability */
-		.word	0
-		/* TODO(errata ABI): this prevents all checker functions from
-		 * being optimised away. Can be done away with unless the ABI
-		 * needs them */
 		.ifnb \_special
 			.word	check_errata_\_special
 		.elseif \_cve
@@ -189,9 +183,7 @@
 		.word	\_id
 		.hword	\_cve
 		.byte	\_chosen
-		/* TODO(errata ABI): mitigated field for known but unmitigated
-		 * errata*/
-		.byte	0x1
+		.byte	0x0 /* alignment */
 	.popsection
 .endm
 
diff --git a/include/lib/cpus/aarch64/cpu_macros.S b/include/lib/cpus/aarch64/cpu_macros.S
index ac26fd7..a43746f 100644
--- a/include/lib/cpus/aarch64/cpu_macros.S
+++ b/include/lib/cpus/aarch64/cpu_macros.S
@@ -49,8 +49,7 @@
 	 * _midr:
 	 *	Numeric value expected to read from CPU's MIDR
 	 * _resetfunc:
-	 *	Reset function for the CPU. If there's no CPU reset function,
-	 *	specify CPU_NO_RESET_FUNC
+	 *	Reset function for the CPU.
 	 * _extra1:
 	 *	This is a placeholder for future per CPU operations.  Currently,
 	 *	some CPUs use this entry to set a test function to determine if
@@ -239,50 +238,22 @@
  * _apply_at_reset:
  *	Whether the erratum should be automatically applied at reset
  */
-.macro add_erratum_entry _cpu:req, _cve:req, _id:req, _chosen:req, _apply_at_reset:req
+.macro add_erratum_entry _cpu:req, _cve:req, _id:req, _chosen:req
+#if REPORT_ERRATA || ERRATA_ABI_SUPPORT
 	.pushsection .rodata.errata_entries
 		.align	3
 		.ifndef \_cpu\()_errata_list_start
 		\_cpu\()_errata_list_start:
 		.endif
 
-		/* check if unused and compile out if no references */
-		.if \_apply_at_reset && \_chosen
-			.quad	erratum_\_cpu\()_\_id\()_wa
-		.else
-			.quad	0
-		.endif
-		/* TODO(errata ABI): this prevents all checker functions from
-		 * being optimised away. Can be done away with unless the ABI
-		 * needs them */
 		.quad	check_erratum_\_cpu\()_\_id
 		/* Will fit CVEs with up to 10 character in the ID field */
 		.word	\_id
 		.hword	\_cve
 		.byte	\_chosen
-		/* TODO(errata ABI): mitigated field for known but unmitigated
-		 * errata */
-		.byte	0x1
+		.byte	0x0 /* alignment */
 	.popsection
-.endm
-
-.macro _workaround_start _cpu:req, _cve:req, _id:req, _chosen:req, _apply_at_reset:req
-	add_erratum_entry \_cpu, \_cve, \_id, \_chosen, \_apply_at_reset
-
-	func erratum_\_cpu\()_\_id\()_wa
-		mov	x8, x30
-
-		/* save rev_var for workarounds that might need it but don't
-		 * restore to x0 because few will care */
-		mov	x7, x0
-		bl	check_erratum_\_cpu\()_\_id
-		cbz	x0, erratum_\_cpu\()_\_id\()_skip
-.endm
-
-.macro _workaround_end _cpu:req, _id:req
-	erratum_\_cpu\()_\_id\()_skip:
-		ret	x8
-	endfunc erratum_\_cpu\()_\_id\()_wa
+#endif
 .endm
 
 /*******************************************************************************
@@ -312,7 +283,22 @@
  * _wa clobbers: x0-x8 (PCS compliant)
  */
 .macro workaround_reset_start _cpu:req, _cve:req, _id:req, _chosen:req
-	_workaround_start \_cpu, \_cve, \_id, \_chosen, 1
+	add_erratum_entry \_cpu, \_cve, \_id, \_chosen
+
+	.if \_chosen
+		/* put errata directly into the reset function */
+		.pushsection .text.asm.\_cpu\()_reset_func, "ax"
+	.else
+		/* or something else that will get garbage collected by the
+		 * linker */
+		.pushsection .text.asm.erratum_\_cpu\()_\_id\()_wa, "ax"
+	.endif
+		/* revision is stored in x14, get it */
+		mov	x0, x14
+		bl	check_erratum_\_cpu\()_\_id
+		/* save rev_var for workarounds that might need it */
+		mov	x7, x14
+		cbz	x0, erratum_\_cpu\()_\_id\()_skip_reset
 .endm
 
 /*
@@ -323,6 +309,10 @@
  *	for errata applied in generic code
  */
 .macro workaround_runtime_start _cpu:req, _cve:req, _id:req, _chosen:req, _midr
+	add_erratum_entry \_cpu, \_cve, \_id, \_chosen
+
+	func erratum_\_cpu\()_\_id\()_wa
+		mov	x8, x30
 	/*
 	 * Let errata specify if they need MIDR checking. Sadly, storing the
 	 * MIDR in an .equ to retrieve automatically blows up as it stores some
@@ -330,11 +320,15 @@
 	 */
 	.ifnb \_midr
 		jump_if_cpu_midr \_midr, 1f
-		b	erratum_\_cpu\()_\_id\()_skip
+		b	erratum_\_cpu\()_\_id\()_skip_runtime
 
 		1:
 	.endif
-	_workaround_start \_cpu, \_cve, \_id, \_chosen, 0
+		/* save rev_var for workarounds that might need it but don't
+		 * restore to x0 because few will care */
+		mov	x7, x0
+		bl	check_erratum_\_cpu\()_\_id
+		cbz	x0, erratum_\_cpu\()_\_id\()_skip_runtime
 .endm
 
 /*
@@ -342,7 +336,8 @@
  * is kept here so the same #define can be used as that macro
  */
 .macro workaround_reset_end _cpu:req, _cve:req, _id:req
-	_workaround_end \_cpu, \_id
+	erratum_\_cpu\()_\_id\()_skip_reset:
+	.popsection
 .endm
 
 /*
@@ -362,7 +357,9 @@
 	.ifb \_no_isb
 		isb
 	.endif
-	_workaround_end \_cpu, \_id
+	erratum_\_cpu\()_\_id\()_skip_runtime:
+		ret	x8
+	endfunc erratum_\_cpu\()_\_id\()_wa
 .endm
 
 /*******************************************************************************
@@ -441,6 +438,29 @@
 .endm
 
 /*
+ * Extract CPU revision and variant, and combine them into a single numeric for
+ * easier comparison.
+ *
+ * _res:
+ *	register where the result will be placed
+ * _tmp:
+ *	register to clobber for temporaries
+ */
+.macro get_rev_var _res:req, _tmp:req
+	mrs	\_tmp, midr_el1
+
+	/*
+	 * Extract the variant[23:20] and revision[3:0] from MIDR, and pack them
+	 * as variant[7:4] and revision[3:0] of x0.
+	 *
+	 * First extract x1[23:16] to x0[7:0] and zero fill the rest. Then
+	 * extract x1[3:0] into x0[3:0] retaining other bits.
+	 */
+	ubfx	\_res, \_tmp, #(MIDR_VAR_SHIFT - MIDR_REV_BITS), #(MIDR_REV_BITS + MIDR_VAR_BITS)
+	bfxil	\_res, \_tmp, #MIDR_REV_SHIFT, #MIDR_REV_BITS
+.endm
+
+/*
  * Apply erratum
  *
  * _cpu:
@@ -479,8 +499,35 @@
 .endm
 
 /*
- * Helpers to select which revisions errata apply to. Don't leave a link
- * register as the cpu_rev_var_*** will call the ret and we can save on one.
+ * Helpers to report if an erratum applies. Compares the given revision variant
+ * to the given value. Return ERRATA_APPLIES or ERRATA_NOT_APPLIES accordingly.
+ *
+ * _rev_num: the given revision variant. Or
+ * _rev_num_lo,_rev_num_hi: the lower and upper bounds of the revision variant
+ *
+ * in body:
+ *	clobber: x0
+ *	argument: x0 - cpu_rev_var
+ */
+.macro cpu_rev_var_ls _rev_num:req
+	cmp	x0, #\_rev_num
+	cset	x0, ls
+.endm
+
+.macro cpu_rev_var_hs _rev_num:req
+	cmp	x0, #\_rev_num
+	cset	x0, hs
+.endm
+
+.macro cpu_rev_var_range _rev_num_lo:req, _rev_num_hi:req
+	cmp	x0, #\_rev_num_lo
+	mov	x1, #\_rev_num_hi
+	ccmp	x0, x1, #2, hs
+	cset	x0, ls
+.endm
+
+/*
+ * Helpers to select which revisions errata apply to.
  *
  * _cpu:
  *	Name of cpu as given to declare_cpu_ops
@@ -496,28 +543,27 @@
  *	Revision to apply to
  *
  * in body:
- *	clobber: x0 to x4
+ *	clobber: x0 to x1
  *	argument: x0 - cpu_rev_var
  */
 .macro check_erratum_ls _cpu:req, _cve:req, _id:req, _rev_num:req
 	func check_erratum_\_cpu\()_\_id
-		mov	x1, #\_rev_num
-		b	cpu_rev_var_ls
+		cpu_rev_var_ls \_rev_num
+		ret
 	endfunc check_erratum_\_cpu\()_\_id
 .endm
 
 .macro check_erratum_hs _cpu:req, _cve:req, _id:req, _rev_num:req
 	func check_erratum_\_cpu\()_\_id
-		mov	x1, #\_rev_num
-		b	cpu_rev_var_hs
+		cpu_rev_var_hs \_rev_num
+		ret
 	endfunc check_erratum_\_cpu\()_\_id
 .endm
 
 .macro check_erratum_range _cpu:req, _cve:req, _id:req, _rev_num_lo:req, _rev_num_hi:req
 	func check_erratum_\_cpu\()_\_id
-		mov	x1, #\_rev_num_lo
-		mov	x2, #\_rev_num_hi
-		b	cpu_rev_var_range
+		cpu_rev_var_range \_rev_num_lo, \_rev_num_hi
+		ret
 	endfunc check_erratum_\_cpu\()_\_id
 .endm
 
@@ -532,7 +578,10 @@
 	endfunc check_erratum_\_cpu\()_\_id
 .endm
 
-/* provide a shorthand for the name format for annoying errata */
+/*
+ * provide a shorthand for the name format for annoying errata
+ * body: clobber x0 to x4
+ */
 .macro check_erratum_custom_start _cpu:req, _cve:req, _id:req
 	func check_erratum_\_cpu\()_\_id
 .endm
@@ -547,7 +596,21 @@
  ******************************************************************************/
 
 /*
- * Wrapper to automatically apply all reset-time errata. Will end with an isb.
+ * Helper to register a cpu with the errata framework. Begins the definition of
+ * the reset function.
+ *
+ * _cpu:
+ *	Name of cpu as given to declare_cpu_ops
+ */
+.macro cpu_reset_prologue _cpu:req
+	func \_cpu\()_reset_func
+		mov	x15, x30
+		get_rev_var x14, x0
+.endm
+
+/*
+ * Wrapper of the reset function to automatically apply all reset-time errata.
+ * Will end with an isb.
  *
  * _cpu:
  *	Name of cpu as given to declare_cpu_ops
@@ -557,39 +620,9 @@
  *	argument x14 - cpu_rev_var
  */
 .macro cpu_reset_func_start _cpu:req
-	func \_cpu\()_reset_func
-		mov	x15, x30
-		bl	cpu_get_rev_var
-		mov	x14, x0
-
-		/* short circuit the location to avoid searching the list */
-		adrp	x12, \_cpu\()_errata_list_start
-		add	x12, x12, :lo12:\_cpu\()_errata_list_start
-		adrp	x13, \_cpu\()_errata_list_end
-		add	x13, x13, :lo12:\_cpu\()_errata_list_end
-
-	errata_begin:
-		/* if head catches up with end of list, exit */
-		cmp	x12, x13
-		b.eq	errata_end
-
-		ldr	x10, [x12, #ERRATUM_WA_FUNC]
-		/* TODO(errata ABI): check mitigated and checker function fields
-		 * for 0 */
-		ldrb	w11, [x12, #ERRATUM_CHOSEN]
-
-		/* skip if not chosen */
-		cbz	x11, 1f
-		/* skip if runtime erratum */
-		cbz	x10, 1f
-
-		/* put cpu revision in x0 and call workaround */
-		mov	x0, x14
-		blr	x10
-	1:
-		add	x12, x12, #ERRATUM_ENTRY_SIZE
-		b	errata_begin
-	errata_end:
+	/* the func/endfunc macros will change sections. So change the section
+	 * back to the reset function's */
+	.section .text.asm.\_cpu\()_reset_func, "ax"
 .endm
 
 .macro cpu_reset_func_end _cpu:req
@@ -598,4 +631,21 @@
 	endfunc \_cpu\()_reset_func
 .endm
 
+/*
+ * Helper macro that enables Maximum Power Mitigation Mechanism (MPMM) on
+ * compatible Arm cores.
+ *
+ * Clobbers x0.
+ */
+.macro enable_mpmm
+#if ENABLE_MPMM
+	mrs	x0, CPUPPMCR_EL3
+	/* if CPUPPMCR_EL3.MPMMPINCTL != 0, skip enabling MPMM */
+	ands	x0, x0, CPUPPMCR_EL3_MPMMPINCTL_BIT
+	b.ne	1f
+	sysreg_bit_set CPUPPMCR_EL3, CPUMPMMCR_EL3_MPMM_EN_BIT
+	1:
+#endif
+.endm
+
 #endif /* CPU_MACROS_S */
diff --git a/include/lib/cpus/aarch64/dsu_def.h b/include/lib/cpus/aarch64/dsu_def.h
index 51fbfd1..78b3e7f 100644
--- a/include/lib/cpus/aarch64/dsu_def.h
+++ b/include/lib/cpus/aarch64/dsu_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -40,7 +40,23 @@
  ********************************************************************/
 #define DSU_ERRATA_936184_MASK	(U(0x3) << 15)
 
+#define CPUCFR_EL1		S3_0_C15_C0_0
+/* SCU bit of CPU Configuration Register, EL1 */
+#define SCU_SHIFT		U(2)
+
 #ifndef __ASSEMBLER__
-void dsu_pwr_dwn(void);
+DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpwrctlr_el1, CLUSTERPWRCTLR_EL1);
+
+/* ---------------------------------------------
+ * controls power features of the cluster
+ * 1. Cache portion power not request
+ * 2. Disable the retention circuit
+ * ---------------------------------------------
+ */
+static inline void dsu_pwr_dwn(void)
+{
+	write_clusterpwrctlr_el1(0);
+	isb();
+}
 #endif
 #endif /* DSU_DEF_H */
diff --git a/include/lib/cpus/aarch64/dsu_macros.S b/include/lib/cpus/aarch64/dsu_macros.S
new file mode 100644
index 0000000..6c8cb69
--- /dev/null
+++ b/include/lib/cpus/aarch64/dsu_macros.S
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2019-2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DSU_MACROS_S
+#define DSU_MACROS_S
+
+#include <asm_macros.S>
+#include <dsu_def.h>
+#include <lib/cpus/errata.h>
+
+.macro check_errata_dsu_798953_impl
+	mov	x2, #ERRATA_APPLIES
+	mov	x3, #ERRATA_NOT_APPLIES
+
+	/* Check if DSU is equal to r0p0 */
+	mrs	x1, CLUSTERIDR_EL1
+
+	/* DSU variant and revision bitfields in CLUSTERIDR are adjacent */
+	ubfx	x0, x1, #CLUSTERIDR_REV_SHIFT,\
+			#(CLUSTERIDR_REV_BITS + CLUSTERIDR_VAR_BITS)
+	mov	x1, #(0x0 << CLUSTERIDR_REV_SHIFT)
+	cmp	x0, x1
+	csel	x0, x2, x3, EQ
+.endm
+
+.macro errata_dsu_798953_wa_impl
+	/* If erratum applies, disable high-level clock gating */
+	mrs	x0, CLUSTERACTLR_EL1
+	orr	x0, x0, #CLUSTERACTLR_EL1_DISABLE_CLOCK_GATING
+	msr	CLUSTERACTLR_EL1, x0
+.endm
+
+.macro branch_if_scu_not_present _target:req
+	/* Check if the SCU L3 Unit is present on the DSU */
+	mrs	x0, CPUCFR_EL1
+	ubfx	x0, x0, #SCU_SHIFT, #1
+	eor	x0, x0, #1
+	/* If SCU is not present, return without applying patch */
+	cmp	x0, xzr
+	mov	x0, #ERRATA_NOT_APPLIES
+	b.eq	\_target
+.endm
+
+.macro check_errata_dsu_936184_impl
+	mov	x0, #ERRATA_NOT_APPLIES
+	/* Erratum applies only if DSU has the ACP interface */
+	mrs	x1, CLUSTERCFR_EL1
+	ubfx	x1, x1, #CLUSTERCFR_ACP_SHIFT, #1
+	cbz	x1, 1f
+
+	/* If ACP is present, check if DSU is older than r2p0 */
+	mrs	x1, CLUSTERIDR_EL1
+
+	/* DSU variant and revision bitfields in CLUSTERIDR are adjacent */
+	ubfx	x2, x1, #CLUSTERIDR_REV_SHIFT,\
+			#(CLUSTERIDR_REV_BITS + CLUSTERIDR_VAR_BITS)
+	cmp x2, #(0x2 << CLUSTERIDR_VAR_SHIFT)
+	b.hs	1f
+	mov	x0, #ERRATA_APPLIES
+1:
+.endm
+
+.macro errata_dsu_936184_wa_impl
+	/* If erratum applies, we set a mask to a DSU control register */
+	mrs	x0, CLUSTERACTLR_EL1
+	ldr	x1, =DSU_ERRATA_936184_MASK
+	orr	x0, x0, x1
+	msr	CLUSTERACTLR_EL1, x0
+.endm
+
+.macro check_errata_dsu_2313941_impl
+	mov	x2, #ERRATA_APPLIES
+	mov	x3, #ERRATA_NOT_APPLIES
+
+	/* Check if DSU version is less than or equal to r3p1 */
+	mrs	x1, CLUSTERIDR_EL1
+
+	mov	x0, #ERRATA_NOT_APPLIES
+	/* DSU variant and revision bitfields in CLUSTERIDR are adjacent */
+	ubfx	x0, x1, #CLUSTERIDR_REV_SHIFT,\
+			#(CLUSTERIDR_REV_BITS + CLUSTERIDR_VAR_BITS)
+	mov	x1, #(0x31 << CLUSTERIDR_REV_SHIFT)
+	cmp	x0, x1
+	csel	x0, x2, x3, LS
+1:
+.endm
+
+.macro errata_dsu_2313941_wa_impl
+	/* If erratum applies, disable high-level clock gating */
+	mrs	x0, CLUSTERACTLR_EL1
+	orr	x0, x0, #CLUSTERACTLR_EL1_DISABLE_SCLK_GATING
+	msr	CLUSTERACTLR_EL1, x0
+.endm
+#endif /* DSU_MACROS_S */
diff --git a/include/lib/cpus/aarch64/neoverse_n_common.h b/include/lib/cpus/aarch64/neoverse_n_common.h
deleted file mode 100644
index 7cb91cd..0000000
--- a/include/lib/cpus/aarch64/neoverse_n_common.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef NEOVERSE_N_COMMON_H
-#define NEOVERSE_N_COMMON_H
-
-/******************************************************************************
- * Neoverse Nx CPU Configuration register definitions
- *****************************************************************************/
-#define CPUCFR_EL1		S3_0_C15_C0_0
-
-/* SCU bit of CPU Configuration Register, EL1 */
-#define SCU_SHIFT		U(2)
-
-#endif /* NEOVERSE_N_COMMON_H */
diff --git a/include/lib/cpus/cpu_ops.h b/include/lib/cpus/cpu_ops.h
index c1bdf8d..0b08919 100644
--- a/include/lib/cpus/cpu_ops.h
+++ b/include/lib/cpus/cpu_ops.h
@@ -21,8 +21,6 @@
 
 /* The number of CPU operations allowed */
 #define CPU_MAX_PWR_DWN_OPS		2
-/* Special constant to specify that CPU has no reset function */
-#define CPU_NO_RESET_FUNC		0
 
 #if __aarch64__
 #define CPU_NO_EXTRA1_FUNC		0
diff --git a/include/lib/cpus/errata.h b/include/lib/cpus/errata.h
index b9166f7..10b949f 100644
--- a/include/lib/cpus/errata.h
+++ b/include/lib/cpus/errata.h
@@ -9,20 +9,18 @@
 
 #include <lib/cpus/cpu_ops.h>
 
-#define ERRATUM_WA_FUNC_SIZE	CPU_WORD_SIZE
 #define ERRATUM_CHECK_FUNC_SIZE	CPU_WORD_SIZE
 #define ERRATUM_ID_SIZE		4
 #define ERRATUM_CVE_SIZE	2
 #define ERRATUM_CHOSEN_SIZE	1
-#define ERRATUM_MITIGATED_SIZE	1
+#define ERRATUM_ALIGNMENT_SIZE	1
 
-#define ERRATUM_WA_FUNC		0
-#define ERRATUM_CHECK_FUNC	ERRATUM_WA_FUNC + ERRATUM_WA_FUNC_SIZE
+#define ERRATUM_CHECK_FUNC	0
 #define ERRATUM_ID		ERRATUM_CHECK_FUNC + ERRATUM_CHECK_FUNC_SIZE
 #define ERRATUM_CVE		ERRATUM_ID + ERRATUM_ID_SIZE
 #define ERRATUM_CHOSEN		ERRATUM_CVE + ERRATUM_CVE_SIZE
-#define ERRATUM_MITIGATED	ERRATUM_CHOSEN + ERRATUM_CHOSEN_SIZE
-#define ERRATUM_ENTRY_SIZE	ERRATUM_MITIGATED + ERRATUM_MITIGATED_SIZE
+#define ERRATUM_ALIGNMENT	ERRATUM_CHOSEN + ERRATUM_CHOSEN_SIZE
+#define ERRATUM_ENTRY_SIZE	ERRATUM_ALIGNMENT + ERRATUM_ALIGNMENT_SIZE
 
 /* Errata status */
 #define ERRATA_NOT_APPLIES	0
@@ -39,15 +37,13 @@
  * uintptr_t will reflect the change and the alignment will be correct in both.
  */
 struct erratum_entry {
-	uintptr_t (*wa_func)(uint64_t cpu_rev);
 	uintptr_t (*check_func)(uint64_t cpu_rev);
 	/* Will fit CVEs with up to 10 character in the ID field */
 	uint32_t id;
 	/* Denote CVEs with their year or errata with 0 */
 	uint16_t cve;
 	uint8_t chosen;
-	/* TODO(errata ABI): placeholder for the mitigated field */
-	uint8_t _mitigated;
+	uint8_t _alignment;
 } __packed;
 
 CASSERT(sizeof(struct erratum_entry) == ERRATUM_ENTRY_SIZE,
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index 87f1541..15d5204 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -167,9 +167,8 @@
  * Registers initialised in a per-world context.
  ******************************************************************************/
 #define CTX_CPTR_EL3			U(0x0)
-#define CTX_ZCR_EL3			U(0x8)
-#define CTX_MPAM3_EL3			U(0x10)
-#define CTX_PERWORLD_EL3STATE_END	U(0x18)
+#define CTX_MPAM3_EL3			U(0x8)
+#define CTX_PERWORLD_EL3STATE_END	U(0x10)
 
 #ifndef __ASSEMBLER__
 
@@ -278,7 +277,6 @@
  */
 typedef struct per_world_context {
 	uint64_t ctx_cptr_el3;
-	uint64_t ctx_zcr_el3;
 	uint64_t ctx_mpam3_el3;
 } per_world_context_t;
 
diff --git a/include/lib/el3_runtime/context_el2.h b/include/lib/el3_runtime/context_el2.h
index f35a091..672f533 100644
--- a/include/lib/el3_runtime/context_el2.h
+++ b/include/lib/el3_runtime/context_el2.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -142,6 +142,10 @@
 	uint64_t sctlr2_el2;
 } el2_sctlr2_regs_t;
 
+typedef struct el2_brbe_regs {
+	uint64_t brbcr_el2;
+} el2_brbe_regs_t;
+
 typedef struct el2_sysregs {
 
 	el2_common_regs_t common;
@@ -214,6 +218,10 @@
 	el2_sctlr2_regs_t sctlr2;
 #endif
 
+#if ENABLE_BRBE_FOR_NS
+	el2_brbe_regs_t brbe;
+#endif
+
 } el2_sysregs_t;
 
 /*
@@ -384,6 +392,15 @@
 #define write_el2_ctx_sctlr2(ctx, reg, val)
 #endif /* ENABLE_FEAT_SCTLR2 */
 
+#if ENABLE_BRBE_FOR_NS
+#define read_el2_ctx_brbe(ctx, reg)		(((ctx)->brbe).reg)
+#define write_el2_ctx_brbe(ctx, reg, val)	((((ctx)->brbe).reg)	\
+							= (uint64_t) (val))
+#else
+#define read_el2_ctx_brbe(ctx, reg)		ULL(0)
+#define write_el2_ctx_brbe(ctx, reg, val)
+#endif /* ENABLE_BRBE_FOR_NS */
+
 /******************************************************************************/
 
 #endif /* __ASSEMBLER__ */
diff --git a/include/lib/el3_runtime/context_mgmt.h b/include/lib/el3_runtime/context_mgmt.h
index 70dbd46..a48ed96 100644
--- a/include/lib/el3_runtime/context_mgmt.h
+++ b/include/lib/el3_runtime/context_mgmt.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -41,7 +41,7 @@
 
 #ifdef __aarch64__
 #if IMAGE_BL31
-void cm_manage_extensions_el3(void);
+void cm_manage_extensions_el3(unsigned int my_idx);
 void manage_extensions_nonsecure_per_world(void);
 void cm_el3_arch_init_per_world(per_world_context_t *per_world_ctx);
 void cm_handle_asymmetric_features(void);
@@ -95,7 +95,7 @@
 #else
 void *cm_get_next_context(void);
 void cm_set_next_context(void *context);
-static inline void cm_manage_extensions_el3(void) {}
+static inline void cm_manage_extensions_el3(unsigned int cpu_idx) {}
 static inline void manage_extensions_nonsecure_per_world(void) {}
 static inline void cm_handle_asymmetric_features(void) {}
 #endif /* __aarch64__ */
diff --git a/include/lib/el3_runtime/cpu_data.h b/include/lib/el3_runtime/cpu_data.h
index 8b54806..e417f45 100644
--- a/include/lib/el3_runtime/cpu_data.h
+++ b/include/lib/el3_runtime/cpu_data.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -230,7 +230,6 @@
  * APIs for initialising and accessing per-cpu data
  *************************************************************************/
 
-void init_cpu_data_ptr(void);
 void init_cpu_ops(void);
 
 #define get_cpu_data(_m)		   _cpu_data()->_m
diff --git a/include/lib/extensions/amu.h b/include/lib/extensions/amu.h
index a396b99..4020331 100644
--- a/include/lib/extensions/amu.h
+++ b/include/lib/extensions/amu.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -17,7 +17,7 @@
 #if ENABLE_FEAT_AMU
 #if __aarch64__
 void amu_enable(cpu_context_t *ctx);
-void amu_init_el3(void);
+void amu_init_el3(unsigned int core_pos);
 void amu_init_el2_unused(void);
 void amu_enable_per_world(per_world_context_t *per_world_ctx);
 #else
@@ -29,7 +29,7 @@
 void amu_enable(cpu_context_t *ctx)
 {
 }
-void amu_init_el3(void)
+void amu_init_el3(unsigned int core_pos)
 {
 }
 void amu_init_el2_unused(void)
@@ -45,28 +45,57 @@
 #endif /*__aarch64__ */
 #endif /* ENABLE_FEAT_AMU */
 
+/*
+ * Per-core list of the counters to be enabled. Value will be written into
+ * AMCNTENSET1_EL0 verbatim.
+ */
 #if ENABLE_AMU_AUXILIARY_COUNTERS
-/*
- * AMU data for a single core.
- */
-struct amu_core {
-	uint16_t enable; /* Mask of auxiliary counters to enable */
-};
+extern uint16_t plat_amu_aux_enables[PLATFORM_CORE_COUNT];
+#endif
 
-/*
- * Topological platform data specific to the AMU.
- */
-struct amu_topology {
-	struct amu_core cores[PLATFORM_CORE_COUNT]; /* Per-core data */
-};
+#define CTX_AMU_GRP0_ALL		U(4)
+#define CTX_AMU_GRP1_ALL		U(16)
 
-#if !ENABLE_AMU_FCONF
-/*
- * Retrieve the platform's AMU topology. A `NULL` return value is treated as a
- * non-fatal error, in which case no auxiliary counters will be enabled.
- */
-const struct amu_topology *plat_amu_topology(void);
-#endif /* ENABLE_AMU_FCONF */
-#endif /* ENABLE_AMU_AUXILIARY_COUNTERS */
+typedef struct amu_regs {
+	u_register_t grp0[CTX_AMU_GRP0_ALL];
+#if ENABLE_AMU_AUXILIARY_COUNTERS
+	u_register_t grp1[CTX_AMU_GRP1_ALL];
+#endif
+} amu_regs_t;
+
+static inline u_register_t read_amu_grp0_ctx_reg(amu_regs_t *ctx, size_t index)
+{
+	return ctx->grp0[index];
+}
+
+static inline void write_amu_grp0_ctx_reg(amu_regs_t *ctx, size_t index, u_register_t val)
+{
+	ctx->grp0[index] = val;
+}
+
+static inline uint16_t get_amu_aux_enables(size_t index)
+{
+#if ENABLE_AMU_AUXILIARY_COUNTERS
+	return plat_amu_aux_enables[index];
+#else
+	return 0;
+#endif
+}
+
+static inline u_register_t read_amu_grp1_ctx_reg(amu_regs_t *ctx, size_t index)
+{
+#if ENABLE_AMU_AUXILIARY_COUNTERS
+	return ctx->grp1[index];
+#else
+	return 0;
+#endif
+}
+
+static inline void write_amu_grp1_ctx_reg(amu_regs_t *ctx, size_t index, u_register_t val)
+{
+#if ENABLE_AMU_AUXILIARY_COUNTERS
+	ctx->grp1[index] = val;
+#endif
+}
 
 #endif /* AMU_H */
diff --git a/include/lib/extensions/sve.h b/include/lib/extensions/sve.h
index 2979efb..a471efb 100644
--- a/include/lib/extensions/sve.h
+++ b/include/lib/extensions/sve.h
@@ -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
  */
@@ -11,10 +11,14 @@
 
 #if (ENABLE_SME_FOR_NS || ENABLE_SVE_FOR_NS)
 
+void sve_init_el3(void);
 void sve_init_el2_unused(void);
 void sve_enable_per_world(per_world_context_t *per_world_ctx);
 void sve_disable_per_world(per_world_context_t *per_world_ctx);
 #else
+static inline void sve_init_el3(void)
+{
+}
 static inline void sve_init_el2_unused(void)
 {
 }
diff --git a/include/lib/fconf/fconf_amu_getter.h b/include/lib/fconf/fconf_amu_getter.h
deleted file mode 100644
index 2faee73..0000000
--- a/include/lib/fconf/fconf_amu_getter.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef FCONF_AMU_GETTER_H
-#define FCONF_AMU_GETTER_H
-
-#include <lib/extensions/amu.h>
-
-#define amu__config_getter(id)	fconf_amu_config.id
-
-struct fconf_amu_config {
-	const struct amu_topology *topology;
-};
-
-extern struct fconf_amu_config fconf_amu_config;
-
-#endif /* FCONF_AMU_GETTER_H */
diff --git a/include/lib/fconf/fconf_mpmm_getter.h b/include/lib/fconf/fconf_mpmm_getter.h
deleted file mode 100644
index 50d991a..0000000
--- a/include/lib/fconf/fconf_mpmm_getter.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef FCONF_MPMM_GETTER_H
-#define FCONF_MPMM_GETTER_H
-
-#include <lib/mpmm/mpmm.h>
-
-#define mpmm__config_getter(id)	fconf_mpmm_config.id
-
-struct fconf_mpmm_config {
-	const struct mpmm_topology *topology;
-};
-
-extern struct fconf_mpmm_config fconf_mpmm_config;
-
-#endif /* FCONF_MPMM_GETTER_H */
diff --git a/include/lib/mpmm/mpmm.h b/include/lib/mpmm/mpmm.h
deleted file mode 100644
index 955c530..0000000
--- a/include/lib/mpmm/mpmm.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef MPMM_H
-#define MPMM_H
-
-#include <stdbool.h>
-
-#include <platform_def.h>
-
-/*
- * Enable the Maximum Power Mitigation Mechanism.
- *
- * This function will enable MPMM for the current core. The AMU counters
- * representing the MPMM gears must have been configured and enabled prior to
- * calling this function.
- */
-void mpmm_enable(void);
-
-/*
- * MPMM core data.
- *
- * This structure represents per-core data retrieved from the hardware
- * configuration device tree.
- */
-struct mpmm_core {
-	/*
-	 * Whether MPMM is supported.
-	 *
-	 * Cores with support for MPMM offer one or more auxiliary AMU counters
-	 * representing MPMM gears.
-	 */
-	bool supported;
-};
-
-/*
- * MPMM topology.
- *
- * This topology structure describes the system-wide representation of the
- * information retrieved from the hardware configuration device tree.
- */
-struct mpmm_topology {
-	struct mpmm_core cores[PLATFORM_CORE_COUNT]; /* Per-core data */
-};
-
-#if !ENABLE_MPMM_FCONF
-/*
- * Retrieve the platform's MPMM topology. A `NULL` return value is treated as a
- * non-fatal error, in which case MPMM will not be enabled for any core.
- */
-const struct mpmm_topology *plat_mpmm_topology(void);
-#endif /* ENABLE_MPMM_FCONF */
-
-#endif /* MPMM_H */
diff --git a/lib/cpus/aarch32/aem_generic.S b/lib/cpus/aarch32/aem_generic.S
index f4dc0d1..a424575 100644
--- a/lib/cpus/aarch32/aem_generic.S
+++ b/lib/cpus/aarch32/aem_generic.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -40,8 +40,11 @@
 	b	dcsw_op_all
 endfunc aem_generic_cluster_pwr_dwn
 
+func aem_generic_reset_func
+	bx	lr
+endfunc aem_generic_reset_func
 
 /* cpu_ops for Base AEM FVP */
-declare_cpu_ops aem_generic, BASE_AEM_MIDR, CPU_NO_RESET_FUNC, \
+declare_cpu_ops aem_generic, BASE_AEM_MIDR, aem_generic_reset_func, \
 	aem_generic_core_pwr_dwn, \
 	aem_generic_cluster_pwr_dwn
diff --git a/lib/cpus/aarch64/a64fx.S b/lib/cpus/aarch64/a64fx.S
index 4893a44..a53467a 100644
--- a/lib/cpus/aarch64/a64fx.S
+++ b/lib/cpus/aarch64/a64fx.S
@@ -29,12 +29,15 @@
 a64fx_regs:  /* The ascii list of register names to be reported */
         .asciz  ""
 
+cpu_reset_func_start a64fx
+cpu_reset_func_end a64fx
+
 func a64fx_cpu_reg_dump
         adr     x6, a64fx_regs
         ret
 endfunc a64fx_cpu_reg_dump
 
-declare_cpu_ops a64fx, A64FX_MIDR, CPU_NO_RESET_FUNC \
+declare_cpu_ops a64fx, A64FX_MIDR, a64fx_reset_func \
                 a64fx_core_pwr_dwn, \
                 a64fx_cluster_pwr_dwn
 
diff --git a/lib/cpus/aarch64/aem_generic.S b/lib/cpus/aarch64/aem_generic.S
index d5634cf..9843943 100644
--- a/lib/cpus/aarch64/aem_generic.S
+++ b/lib/cpus/aarch64/aem_generic.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,6 +8,8 @@
 #include <asm_macros.S>
 #include <cpu_macros.S>
 
+cpu_reset_prologue aem_generic
+
 func aem_generic_core_pwr_dwn
 	/* ---------------------------------------------
 	 * Disable the Data Cache.
@@ -74,6 +76,9 @@
 	b	dcsw_op_all
 endfunc aem_generic_cluster_pwr_dwn
 
+cpu_reset_func_start aem_generic
+cpu_reset_func_end aem_generic
+
 	/* ---------------------------------------------
 	 * This function provides cpu specific
 	 * register information for crash reporting.
@@ -94,11 +99,11 @@
 
 
 /* cpu_ops for Base AEM FVP */
-declare_cpu_ops aem_generic, BASE_AEM_MIDR, CPU_NO_RESET_FUNC, \
+declare_cpu_ops aem_generic, BASE_AEM_MIDR, aem_generic_reset_func, \
 	aem_generic_core_pwr_dwn, \
 	aem_generic_cluster_pwr_dwn
 
 /* cpu_ops for Foundation FVP */
-declare_cpu_ops aem_generic, FOUNDATION_AEM_MIDR, CPU_NO_RESET_FUNC, \
+declare_cpu_ops aem_generic, FOUNDATION_AEM_MIDR, aem_generic_reset_func, \
 	aem_generic_core_pwr_dwn, \
 	aem_generic_cluster_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_a35.S b/lib/cpus/aarch64/cortex_a35.S
index c3d8c8d..40e6200 100644
--- a/lib/cpus/aarch64/cortex_a35.S
+++ b/lib/cpus/aarch64/cortex_a35.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,6 +11,7 @@
 #include <cpu_macros.S>
 #include <plat_macros.S>
 
+cpu_reset_prologue cortex_a35
 	/* ---------------------------------------------
 	 * Disable L1 data cache and unified L2 cache
 	 * ---------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a510.S b/lib/cpus/aarch64/cortex_a510.S
index b49d45a..81a227b 100644
--- a/lib/cpus/aarch64/cortex_a510.S
+++ b/lib/cpus/aarch64/cortex_a510.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,6 +9,7 @@
 #include <common/bl_common.h>
 #include <cortex_a510.h>
 #include <cpu_macros.S>
+#include <dsu_macros.S>
 #include <plat_macros.S>
 
 /* Hardware handled coherency */
@@ -21,6 +22,8 @@
 #error "Cortex-A510 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+cpu_reset_prologue cortex_a510
+
 workaround_reset_start cortex_a510, ERRATUM(1922240), ERRATA_A510_1922240
 	/* Apply the workaround by setting IMP_CMPXACTLR_EL1[11:10] = 0b11. */
 	sysreg_bitfield_insert CORTEX_A510_CMPXACTLR_EL1, CORTEX_A510_CMPXACTLR_EL1_SNPPREFERUNIQUE_DISABLE, \
@@ -108,25 +111,11 @@
 
 check_erratum_ls cortex_a510, ERRATUM(2218950), CPU_REV(1, 0)
 
-	/* --------------------------------------------------
-	 * This workaround is not a typical errata fix. MPMM
-	 * is disabled here, but this conflicts with the BL31
-	 * MPMM support. So in addition to simply disabling
-	 * the feature, a flag is set in the MPMM library
-	 * indicating that it should not be enabled even if
-	 * ENABLE_MPMM=1.
-	 * --------------------------------------------------
-	 */
 workaround_reset_start cortex_a510, ERRATUM(2250311), ERRATA_A510_2250311
 	/* Disable MPMM */
 	mrs	x0, CPUMPMMCR_EL3
 	bfm	x0, xzr, #0, #0 /* bfc instruction does not work in GCC */
 	msr	CPUMPMMCR_EL3, x0
-
-#if ENABLE_MPMM && IMAGE_BL31
-	/* If ENABLE_MPMM is set, tell the runtime lib to skip enabling it. */
-	bl mpmm_errata_disable
-#endif
 workaround_reset_end cortex_a510, ERRATUM(2250311)
 
 check_erratum_ls cortex_a510, ERRATUM(2250311), CPU_REV(1, 0)
@@ -180,15 +169,14 @@
 
 check_erratum_ls cortex_a510, ERRATUM(2684597), CPU_REV(1, 2)
 
-/*
- * ERRATA_DSU_2313941 :
- * The errata is defined in dsu_helpers.S but applies to cortex_a510
- * as well. Henceforth creating symbolic names to the already existing errata
- * workaround functions to get them registered under the Errata Framework.
- */
-.equ check_erratum_cortex_a510_2313941, check_errata_dsu_2313941
-.equ erratum_cortex_a510_2313941_wa, errata_dsu_2313941_wa
-add_erratum_entry cortex_a510, ERRATUM(2313941), ERRATA_DSU_2313941, APPLY_AT_RESET
+workaround_reset_start cortex_a510, ERRATUM(2313941), ERRATA_DSU_2313941
+	errata_dsu_2313941_wa_impl
+workaround_reset_end cortex_a510, ERRATUM(2313941)
+
+check_erratum_custom_start cortex_a510, ERRATUM(2313941)
+	check_errata_dsu_2313941_impl
+	ret
+check_erratum_custom_end cortex_a510, ERRATUM(2313941)
 
 	/* ----------------------------------------------------
 	 * HW will do the cache maintenance while powering down
@@ -207,6 +195,15 @@
 cpu_reset_func_start cortex_a510
 	/* Disable speculative loads */
 	msr	SSBS, xzr
+	/* skip enabling MPMM if this erratum is present */
+#if ERRATA_A510_2250311
+	/* the cpu_rev_var is kept in x14 */
+	mov	x14, x0
+	bl	check_erratum_cortex_a510_2250311
+	cbz	x0, skip_mpmm
+#endif
+	enable_mpmm
+skip_mpmm:
 cpu_reset_func_end cortex_a510
 
 	/* ---------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a520.S b/lib/cpus/aarch64/cortex_a520.S
index 811c836..ac8019e 100644
--- a/lib/cpus/aarch64/cortex_a520.S
+++ b/lib/cpus/aarch64/cortex_a520.S
@@ -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
  */
@@ -11,7 +11,6 @@
 #include <cpu_macros.S>
 #include <plat_macros.S>
 
-/* .global erratum_cortex_a520_2938996_wa */
 .global check_erratum_cortex_a520_2938996
 
 /* Hardware handled coherency */
@@ -24,6 +23,8 @@
 #error "Cortex A520 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+cpu_reset_prologue cortex_a520
+
 workaround_reset_start cortex_a520, ERRATUM(2630792), ERRATA_A520_2630792
 	sysreg_bit_set CORTEX_A520_CPUACTLR_EL1, BIT(38)
 workaround_reset_end cortex_a520, ERRATUM(2630792)
@@ -36,23 +37,9 @@
 
 check_erratum_ls cortex_a520, ERRATUM(2858100), CPU_REV(0, 1)
 
-workaround_runtime_start cortex_a520, ERRATUM(2938996), ERRATA_A520_2938996, CORTEX_A520_MIDR
-workaround_runtime_end cortex_a520, ERRATUM(2938996)
+add_erratum_entry cortex_a520, ERRATUM(2938996), ERRATA_A520_2938996
 
-check_erratum_custom_start cortex_a520, ERRATUM(2938996)
-
-       /* This erratum needs to be enabled for r0p0 and r0p1.
-        * Check if revision is less than or equal to r0p1.
-        */
-
-#if ERRATA_A520_2938996
-       mov     x1, #1
-       b       cpu_rev_var_ls
-#else
-       mov     x0, #ERRATA_MISSING
-#endif
-       ret
-check_erratum_custom_end cortex_a520, ERRATUM(2938996)
+check_erratum_ls cortex_a520, ERRATUM(2938996), CPU_REV(0, 1)
 
 	/* ----------------------------------------------------
 	 * HW will do the cache maintenance while powering down
@@ -71,6 +58,7 @@
 cpu_reset_func_start cortex_a520
 	/* Disable speculative loads */
 	msr	SSBS, xzr
+	enable_mpmm
 cpu_reset_func_end cortex_a520
 
 	/* ---------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a53.S b/lib/cpus/aarch64/cortex_a53.S
index 4a5b318..dbfff87 100644
--- a/lib/cpus/aarch64/cortex_a53.S
+++ b/lib/cpus/aarch64/cortex_a53.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,6 +12,8 @@
 #include <plat_macros.S>
 #include <lib/cpus/errata.h>
 
+cpu_reset_prologue cortex_a53
+
 	/* ---------------------------------------------
 	 * Disable L1 data cache and unified L2 cache
 	 * ---------------------------------------------
@@ -36,12 +38,12 @@
 /* Due to the nature of the errata it is applied unconditionally when chosen */
 check_erratum_ls cortex_a53, ERRATUM(819472), CPU_REV(0, 1)
 /* erratum workaround is interleaved with generic code */
-add_erratum_entry cortex_a53, ERRATUM(819472), ERRATUM_ALWAYS_CHOSEN, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a53, ERRATUM(819472), ERRATUM_ALWAYS_CHOSEN
 
 /* Due to the nature of the errata it is applied unconditionally when chosen */
 check_erratum_ls cortex_a53, ERRATUM(824069), CPU_REV(0, 2)
 /* erratum workaround is interleaved with generic code */
-add_erratum_entry cortex_a53, ERRATUM(824069), ERRATUM_ALWAYS_CHOSEN, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a53, ERRATUM(824069), ERRATUM_ALWAYS_CHOSEN
 
 workaround_reset_start cortex_a53, ERRATUM(826319), ERRATA_A53_826319
 	mrs	x1, CORTEX_A53_L2ACTLR_EL1
@@ -55,7 +57,7 @@
 /* Due to the nature of the errata it is applied unconditionally when chosen */
 check_erratum_ls cortex_a53, ERRATUM(827319), CPU_REV(0, 2)
 /* erratum workaround is interleaved with generic code */
-add_erratum_entry cortex_a53, ERRATUM(827319), ERRATUM_ALWAYS_CHOSEN, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a53, ERRATUM(827319), ERRATUM_ALWAYS_CHOSEN
 
 check_erratum_custom_start cortex_a53, ERRATUM(835769)
 	cmp	x0, CPU_REV(0, 4)
@@ -78,7 +80,7 @@
 check_erratum_custom_end cortex_a53, ERRATUM(835769)
 
 /* workaround at build time */
-add_erratum_entry cortex_a53, ERRATUM(835769), ERRATA_A53_835769, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a53, ERRATUM(835769), ERRATA_A53_835769
 
 	/*
 	 * Disable the cache non-temporal hint.
@@ -114,7 +116,7 @@
 check_erratum_custom_end cortex_a53, ERRATUM(843419)
 
 /* workaround at build time */
-add_erratum_entry cortex_a53, ERRATUM(843419), ERRATA_A53_843419, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a53, ERRATUM(843419), ERRATA_A53_843419
 
 	/*
 	 * Earlier revisions of the core are affected as well, but don't
@@ -131,7 +133,7 @@
 check_erratum_chosen cortex_a53, ERRATUM(1530924), ERRATA_A53_1530924
 
 /* erratum has no workaround in the cpu. Generic code must take care */
-add_erratum_entry cortex_a53, ERRATUM(1530924), ERRATA_A53_1530924, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a53, ERRATUM(1530924), ERRATA_A53_1530924
 
 cpu_reset_func_start cortex_a53
 	/* Enable the SMP bit. */
diff --git a/lib/cpus/aarch64/cortex_a55.S b/lib/cpus/aarch64/cortex_a55.S
index d5a74e9..cf91431 100644
--- a/lib/cpus/aarch64/cortex_a55.S
+++ b/lib/cpus/aarch64/cortex_a55.S
@@ -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
  */
@@ -9,6 +9,7 @@
 #include <common/bl_common.h>
 #include <cortex_a55.h>
 #include <cpu_macros.S>
+#include <dsu_macros.S>
 #include <plat_macros.S>
 
 /* Hardware handled coherency */
@@ -19,23 +20,25 @@
 	.globl cortex_a55_reset_func
 	.globl cortex_a55_core_pwr_dwn
 
-/* ERRATA_DSU_798953:
- * The errata is defined in dsu_helpers.S but applies to cortex_a55
- * as well. Henceforth creating symbolic names to the already existing errata
- * workaround functions to get them registered under the Errata Framework.
- */
-.equ check_erratum_cortex_a55_798953, check_errata_dsu_798953
-.equ erratum_cortex_a55_798953_wa, errata_dsu_798953_wa
-add_erratum_entry cortex_a55, ERRATUM(798953), ERRATA_DSU_798953, APPLY_AT_RESET
+cpu_reset_prologue cortex_a55
 
-/* ERRATA_DSU_936184:
- * The errata is defined in dsu_helpers.S but applies to cortex_a55
- * as well. Henceforth creating symbolic names to the already existing errata
- * workaround functions to get them registered under the Errata Framework.
- */
-.equ check_erratum_cortex_a55_936184, check_errata_dsu_936184
-.equ erratum_cortex_a55_936184_wa, errata_dsu_936184_wa
-add_erratum_entry cortex_a55, ERRATUM(936184), ERRATA_DSU_936184, APPLY_AT_RESET
+workaround_reset_start cortex_a55, ERRATUM(798953), ERRATA_DSU_798953
+	errata_dsu_798953_wa_impl
+workaround_reset_end cortex_a55, ERRATUM(798953)
+
+check_erratum_custom_start cortex_a55, ERRATUM(798953)
+	check_errata_dsu_798953_impl
+	ret
+check_erratum_custom_end cortex_a55, ERRATUM(798953)
+
+workaround_reset_start cortex_a55, ERRATUM(936184), ERRATA_DSU_936184
+	errata_dsu_936184_wa_impl
+workaround_reset_end cortex_a55, ERRATUM(936184)
+
+check_erratum_custom_start cortex_a55, ERRATUM(936184)
+	check_errata_dsu_936184_impl
+	ret
+check_erratum_custom_end cortex_a55, ERRATUM(936184)
 
 workaround_reset_start cortex_a55, ERRATUM(768277), ERRATA_A55_768277
 	sysreg_bit_set CORTEX_A55_CPUACTLR_EL1, CORTEX_A55_CPUACTLR_EL1_DISABLE_DUAL_ISSUE
@@ -50,8 +53,7 @@
 
 check_erratum_custom_start cortex_a55, ERRATUM(778703)
 	mov	x16, x30
-	mov	x1, #0x00
-	bl	cpu_rev_var_ls
+	cpu_rev_var_ls	CPU_REV(0, 0)
 	/*
 	 * Check that no private L2 cache is configured
 	 */
@@ -111,7 +113,7 @@
 check_erratum_chosen cortex_a55, ERRATUM(1530923), ERRATA_A55_1530923
 
 /* erratum has no workaround in the cpu. Generic code must take care */
-add_erratum_entry cortex_a55, ERRATUM(1530923), ERRATA_A55_1530923, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a55, ERRATUM(1530923), ERRATA_A55_1530923
 
 cpu_reset_func_start cortex_a55
 cpu_reset_func_end cortex_a55
diff --git a/lib/cpus/aarch64/cortex_a57.S b/lib/cpus/aarch64/cortex_a57.S
index fecb56f..adacc5c 100644
--- a/lib/cpus/aarch64/cortex_a57.S
+++ b/lib/cpus/aarch64/cortex_a57.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
  * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -13,6 +13,8 @@
 #include <cpu_macros.S>
 #include <plat_macros.S>
 
+cpu_reset_prologue cortex_a57
+
 	/* ---------------------------------------------
 	 * Disable L1 data cache and unified L2 cache
 	 * ---------------------------------------------
@@ -81,7 +83,7 @@
 
 /* erratum always worked around, but report it correctly */
 check_erratum_ls cortex_a57, ERRATUM(813419), CPU_REV(0, 0)
-add_erratum_entry cortex_a57, ERRATUM(813419), ERRATUM_ALWAYS_CHOSEN, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a57, ERRATUM(813419), ERRATUM_ALWAYS_CHOSEN
 
 workaround_reset_start cortex_a57, ERRATUM(813420), ERRATA_A57_813420
 	sysreg_bit_set CORTEX_A57_CPUACTLR_EL1, CORTEX_A57_CPUACTLR_EL1_DCC_AS_DCCI
@@ -95,7 +97,7 @@
 
 check_erratum_ls cortex_a57, ERRATUM(814670), CPU_REV(0, 0)
 
-workaround_runtime_start cortex_a57, ERRATUM(817169), ERRATA_A57_817169, CORTEX_A57_MIDR
+workaround_runtime_start cortex_a57, ERRATUM(817169), ERRATA_A57_817169
 	/* Invalidate any TLB address */
 	mov	x0, #0
 	tlbi	vae3, x0
@@ -150,7 +152,7 @@
 
 check_erratum_chosen cortex_a57, ERRATUM(1319537), ERRATA_A57_1319537
 /* erratum has no workaround in the cpu. Generic code must take care */
-add_erratum_entry cortex_a57, ERRATUM(1319537), ERRATA_A57_1319537, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a57, ERRATUM(1319537), ERRATA_A57_1319537
 
 workaround_reset_start cortex_a57, CVE(2017, 5715), WORKAROUND_CVE_2017_5715
 #if IMAGE_BL31
diff --git a/lib/cpus/aarch64/cortex_a65.S b/lib/cpus/aarch64/cortex_a65.S
index 3023ecb..3c32adb 100644
--- a/lib/cpus/aarch64/cortex_a65.S
+++ b/lib/cpus/aarch64/cortex_a65.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,6 +10,7 @@
 #include <common/debug.h>
 #include <cortex_a65.h>
 #include <cpu_macros.S>
+#include <dsu_macros.S>
 #include <plat_macros.S>
 
 /* Hardware handled coherency */
@@ -22,20 +23,19 @@
 #error "Cortex-A65 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
-/* -------------------------------------------------
- * The CPU Ops reset function for Cortex-A65.
- * Shall clobber: x0-x19
- * -------------------------------------------------
- */
-func cortex_a65_reset_func
-	mov	x19, x30
+cpu_reset_prologue cortex_a65
 
-#if ERRATA_DSU_936184
-	bl	errata_dsu_936184_wa
-#endif
+workaround_reset_start cortex_a65, ERRATUM(936184), ERRATA_DSU_936184
+	errata_dsu_936184_wa_impl
+workaround_reset_end cortex_a65, ERRATUM(936184)
 
-	ret	x19
-endfunc cortex_a65_reset_func
+check_erratum_custom_start cortex_a65, ERRATUM(936184)
+	check_errata_dsu_936184_impl
+	ret
+check_erratum_custom_end cortex_a65, ERRATUM(936184)
+
+cpu_reset_func_start cortex_a65
+cpu_reset_func_end cortex_a65
 
 func cortex_a65_cpu_pwr_dwn
 	mrs	x0, CORTEX_A65_CPUPWRCTLR_EL1
@@ -45,7 +45,6 @@
 	ret
 endfunc cortex_a65_cpu_pwr_dwn
 
-
 .section .rodata.cortex_a65_regs, "aS"
 cortex_a65_regs:  /* The ascii list of register names to be reported */
 	.asciz	"cpuectlr_el1", ""
diff --git a/lib/cpus/aarch64/cortex_a65ae.S b/lib/cpus/aarch64/cortex_a65ae.S
index 1cbb06a..f1a63b0 100644
--- a/lib/cpus/aarch64/cortex_a65ae.S
+++ b/lib/cpus/aarch64/cortex_a65ae.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,6 +11,7 @@
 #include <cortex_a65ae.h>
 #include <cpu_macros.S>
 #include <plat_macros.S>
+#include <dsu_macros.S>
 
 /* Hardware handled coherency */
 #if !HW_ASSISTED_COHERENCY
@@ -22,15 +23,16 @@
 #error "Cortex-A65AE supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
- /*
-  * ERRATA_DSU_936184 :
-  * The errata is defined in dsu_helpers.S but applies to cortex_a65ae
-  * as well. Henceforth creating symbolic names to the already existing errata
-  * workaround functions to get them registered under the Errata Framework.
-  */
-.equ check_erratum_cortex_a65ae_936184, check_errata_dsu_936184
-.equ erratum_cortex_a65ae_936184_wa, errata_dsu_936184_wa
-add_erratum_entry cortex_a65ae, ERRATUM(936184), ERRATA_DSU_936184, APPLY_AT_RESET
+cpu_reset_prologue cortex_a65ae
+
+workaround_reset_start cortex_a65ae, ERRATUM(936184), ERRATA_DSU_936184
+	errata_dsu_936184_wa_impl
+workaround_reset_end cortex_a65ae, ERRATUM(936184)
+
+check_erratum_custom_start cortex_a65ae, ERRATUM(936184)
+	check_errata_dsu_936184_impl
+	ret
+check_erratum_custom_end cortex_a65ae, ERRATUM(936184)
 
 cpu_reset_func_start cortex_a65ae
 cpu_reset_func_end cortex_a65ae
diff --git a/lib/cpus/aarch64/cortex_a710.S b/lib/cpus/aarch64/cortex_a710.S
index c50a7d3..e8f5a80 100644
--- a/lib/cpus/aarch64/cortex_a710.S
+++ b/lib/cpus/aarch64/cortex_a710.S
@@ -9,6 +9,7 @@
 #include <common/bl_common.h>
 #include <cortex_a710.h>
 #include <cpu_macros.S>
+#include <dsu_macros.S>
 #include <plat_macros.S>
 #include "wa_cve_2022_23960_bhb_vector.S"
 
@@ -28,6 +29,8 @@
 	wa_cve_2022_23960_bhb_vector_table CORTEX_A710_BHB_LOOP_COUNT, cortex_a710
 #endif /* WORKAROUND_CVE_2022_23960 */
 
+cpu_reset_prologue cortex_a710
+
 /* Disable hardware page aggregation. Enables mitigation for `CVE-2024-5660` */
 workaround_reset_start cortex_a710, CVE(2024, 5660), WORKAROUND_CVE_2024_5660
 	sysreg_bit_set CORTEX_A710_CPUECTLR_EL1, BIT(46)
@@ -173,14 +176,14 @@
 
 check_erratum_ls cortex_a710, ERRATUM(2291219), CPU_REV(2, 0)
 
-/*
- * ERRATA_DSU_2313941 is defined in dsu_helpers.S but applies to Cortex-A710 as
- * well. Create a symbollic link to existing errata workaround to get them
- * registered under the Errata Framework.
- */
-.equ check_erratum_cortex_a710_2313941, check_errata_dsu_2313941
-.equ erratum_cortex_a710_2313941_wa, errata_dsu_2313941_wa
-add_erratum_entry cortex_a710, ERRATUM(2313941), ERRATA_DSU_2313941, APPLY_AT_RESET
+workaround_reset_start cortex_a710, ERRATUM(2313941), ERRATA_DSU_2313941
+	errata_dsu_2313941_wa_impl
+workaround_reset_end cortex_a710, ERRATUM(2313941)
+
+check_erratum_custom_start cortex_a710, ERRATUM(2313941)
+	check_errata_dsu_2313941_impl
+	ret
+check_erratum_custom_end cortex_a710, ERRATUM(2313941)
 
 workaround_reset_start cortex_a710, ERRATUM(2371105), ERRATA_A710_2371105
 	/* Set bit 40 in CPUACTLR2_EL1 */
@@ -222,7 +225,7 @@
 
 check_erratum_chosen cortex_a710, CVE(2022, 23960), WORKAROUND_CVE_2022_23960
 
-add_erratum_entry cortex_a710, ERRATUM(3701772), ERRATA_A710_3701772, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a710, ERRATUM(3701772), ERRATA_A710_3701772
 
 check_erratum_ls cortex_a710, ERRATUM(3701772), CPU_REV(2, 1)
 
@@ -247,6 +250,7 @@
 cpu_reset_func_start cortex_a710
 	/* Disable speculative loads */
 	msr	SSBS, xzr
+	enable_mpmm
 cpu_reset_func_end cortex_a710
 
 	/* ---------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a715.S b/lib/cpus/aarch64/cortex_a715.S
index fbc73ed..d9c0df2 100644
--- a/lib/cpus/aarch64/cortex_a715.S
+++ b/lib/cpus/aarch64/cortex_a715.S
@@ -28,6 +28,8 @@
 	wa_cve_2022_23960_bhb_vector_table CORTEX_A715_BHB_LOOP_COUNT, cortex_a715
 #endif /* WORKAROUND_CVE_2022_23960 */
 
+cpu_reset_prologue cortex_a715
+
 workaround_reset_start cortex_a715, ERRATUM(2331818), ERRATA_A715_2331818
         sysreg_bit_set CORTEX_A715_CPUACTLR2_EL1, BIT(20)
 workaround_reset_end cortex_a715, ERRATUM(2331818)
@@ -129,13 +131,14 @@
 
 check_erratum_chosen cortex_a715, CVE(2022, 23960), WORKAROUND_CVE_2022_23960
 
-add_erratum_entry cortex_a715, ERRATUM(3699560), ERRATA_A715_3699560, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a715, ERRATUM(3699560), ERRATA_A715_3699560
 
 check_erratum_ls cortex_a715, ERRATUM(3699560), CPU_REV(1, 3)
 
 cpu_reset_func_start cortex_a715
 	/* Disable speculative loads */
 	msr	SSBS, xzr
+	enable_mpmm
 cpu_reset_func_end cortex_a715
 
 	/* ----------------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a72.S b/lib/cpus/aarch64/cortex_a72.S
index c300ea7..fee28ee 100644
--- a/lib/cpus/aarch64/cortex_a72.S
+++ b/lib/cpus/aarch64/cortex_a72.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,6 +15,8 @@
 	wa_cve_2022_23960_bhb_vector_table CORTEX_A72_BHB_LOOP_COUNT, cortex_a72
 #endif /* WORKAROUND_CVE_2022_23960 */
 
+cpu_reset_prologue cortex_a72
+
 	/* ---------------------------------------------
 	 * Disable L1 data cache and unified L2 cache
 	 * ---------------------------------------------
@@ -92,7 +94,7 @@
 /* Due to the nature of the errata it is applied unconditionally when chosen */
 check_erratum_chosen cortex_a72, ERRATUM(1319367), ERRATA_A72_1319367
 /* erratum workaround is interleaved with generic code */
-add_erratum_entry cortex_a72, ERRATUM(1319367), ERRATA_A72_1319367, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a72, ERRATUM(1319367), ERRATA_A72_1319367
 
 workaround_reset_start cortex_a72, CVE(2017, 5715), WORKAROUND_CVE_2017_5715
 #if IMAGE_BL31
diff --git a/lib/cpus/aarch64/cortex_a720.S b/lib/cpus/aarch64/cortex_a720.S
index ab2c12f..e639996 100644
--- a/lib/cpus/aarch64/cortex_a720.S
+++ b/lib/cpus/aarch64/cortex_a720.S
@@ -22,6 +22,8 @@
 #error "Cortex A720 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+cpu_reset_prologue cortex_a720
+
 .global check_erratum_cortex_a720_3699561
 
 #if WORKAROUND_CVE_2022_23960
@@ -74,13 +76,14 @@
 
 check_erratum_chosen cortex_a720, CVE(2022, 23960), WORKAROUND_CVE_2022_23960
 
-add_erratum_entry cortex_a720, ERRATUM(3699561), ERRATA_A720_3699561, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a720, ERRATUM(3699561), ERRATA_A720_3699561
 
 check_erratum_ls cortex_a720, ERRATUM(3699561), CPU_REV(0, 2)
 
 cpu_reset_func_start cortex_a720
 	/* Disable speculative loads */
 	msr	SSBS, xzr
+	enable_mpmm
 cpu_reset_func_end cortex_a720
 
 	/* ----------------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a720_ae.S b/lib/cpus/aarch64/cortex_a720_ae.S
index 57a5030..1d51c44 100644
--- a/lib/cpus/aarch64/cortex_a720_ae.S
+++ b/lib/cpus/aarch64/cortex_a720_ae.S
@@ -21,15 +21,18 @@
 #error "Cortex-A720AE supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+cpu_reset_prologue cortex_a720_ae
+
 .global check_erratum_cortex_a720_ae_3699562
 
-add_erratum_entry cortex_a720_ae, ERRATUM(3699562), ERRATA_A720_AE_3699562, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a720_ae, ERRATUM(3699562), ERRATA_A720_AE_3699562
 
 check_erratum_ls cortex_a720_ae, ERRATUM(3699562), CPU_REV(0, 0)
 
 cpu_reset_func_start cortex_a720_ae
 	/* Disable speculative loads */
 	msr	SSBS, xzr
+	enable_mpmm
 cpu_reset_func_end cortex_a720_ae
 
 	/* ----------------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a725.S b/lib/cpus/aarch64/cortex_a725.S
index c4d6034..682ca45 100644
--- a/lib/cpus/aarch64/cortex_a725.S
+++ b/lib/cpus/aarch64/cortex_a725.S
@@ -21,15 +21,18 @@
 #error "Cortex-A725 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+cpu_reset_prologue cortex_a725
+
 .global check_erratum_cortex_a725_3699564
 
-add_erratum_entry cortex_a725, ERRATUM(3699564), ERRATA_A725_3699564, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a725, ERRATUM(3699564), ERRATA_A725_3699564
 
 check_erratum_ls cortex_a725, ERRATUM(3699564), CPU_REV(0, 1)
 
 cpu_reset_func_start cortex_a725
 	/* Disable speculative loads */
 	msr	SSBS, xzr
+	enable_mpmm
 cpu_reset_func_end cortex_a725
 
 	/* ----------------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a73.S b/lib/cpus/aarch64/cortex_a73.S
index 2130ceb..d1fc6d4 100644
--- a/lib/cpus/aarch64/cortex_a73.S
+++ b/lib/cpus/aarch64/cortex_a73.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,6 +10,8 @@
 #include <cpu_macros.S>
 #include <plat_macros.S>
 
+cpu_reset_prologue cortex_a73
+
 	/* ---------------------------------------------
 	 * Disable L1 data cache
 	 * ---------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a75.S b/lib/cpus/aarch64/cortex_a75.S
index 152c81f..13599ca 100644
--- a/lib/cpus/aarch64/cortex_a75.S
+++ b/lib/cpus/aarch64/cortex_a75.S
@@ -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
  */
@@ -9,6 +9,7 @@
 #include <cortex_a75.h>
 #include <cpuamu.h>
 #include <cpu_macros.S>
+#include <dsu_macros.S>
 
 .global check_erratum_cortex_a75_764081
 
@@ -17,6 +18,8 @@
 #error "Cortex-A75 must be compiled with HW_ASSISTED_COHERENCY enabled"
 #endif
 
+cpu_reset_prologue cortex_a75
+
 workaround_reset_start cortex_a75, ERRATUM(764081), ERRATA_A75_764081
 	sysreg_bit_set sctlr_el3, SCTLR_IESB_BIT
 workaround_reset_end cortex_a75, ERRATUM(764081)
@@ -29,23 +32,23 @@
 
 check_erratum_ls cortex_a75, ERRATUM(790748), CPU_REV(0, 0)
 
-/* ERRATA_DSU_798953 :
- * The errata is defined in dsu_helpers.S but applies to cortex_a75
- * as well. Henceforth creating symbolic names to the already existing errata
- * workaround functions to get them registered under the Errata Framework.
- */
-.equ check_erratum_cortex_a75_798953, check_errata_dsu_798953
-.equ erratum_cortex_a75_798953_wa, errata_dsu_798953_wa
-add_erratum_entry cortex_a75, ERRATUM(798953), ERRATA_DSU_798953, APPLY_AT_RESET
+workaround_reset_start cortex_a75, ERRATUM(798953), ERRATA_DSU_798953
+	errata_dsu_798953_wa_impl
+workaround_reset_end cortex_a75, ERRATUM(798953)
 
-/* ERRATA_DSU_936184 :
- * The errata is defined in dsu_helpers.S but applies to cortex_a75
- * as well. Henceforth creating symbolic names to the already existing errata
- * workaround functions to get them registered under the Errata Framework.
- */
-.equ check_erratum_cortex_a75_936184, check_errata_dsu_936184
-.equ erratum_cortex_a75_936184_wa, errata_dsu_936184_wa
-add_erratum_entry cortex_a75, ERRATUM(936184), ERRATA_DSU_936184, APPLY_AT_RESET
+check_erratum_custom_start cortex_a75, ERRATUM(798953)
+	check_errata_dsu_798953_impl
+	ret
+check_erratum_custom_end cortex_a75, ERRATUM(798953)
+
+workaround_reset_start cortex_a75, ERRATUM(936184), ERRATA_DSU_936184
+	errata_dsu_936184_wa_impl
+workaround_reset_end cortex_a75, ERRATUM(936184)
+
+check_erratum_custom_start cortex_a75, ERRATUM(936184)
+	check_errata_dsu_936184_impl
+	ret
+check_erratum_custom_end cortex_a75, ERRATUM(936184)
 
 workaround_reset_start cortex_a75, CVE(2017, 5715), WORKAROUND_CVE_2017_5715
 #if IMAGE_BL31
diff --git a/lib/cpus/aarch64/cortex_a76.S b/lib/cpus/aarch64/cortex_a76.S
index 017086a..822ef05 100644
--- a/lib/cpus/aarch64/cortex_a76.S
+++ b/lib/cpus/aarch64/cortex_a76.S
@@ -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
  */
@@ -9,6 +9,7 @@
 #include <common/bl_common.h>
 #include <cortex_a76.h>
 #include <cpu_macros.S>
+#include <dsu_macros.S>
 #include <plat_macros.S>
 #include <services/arm_arch_svc.h>
 #include "wa_cve_2022_23960_bhb.S"
@@ -29,6 +30,8 @@
 #define ESR_EL3_A64_SMC0	0x5e000000
 #define ESR_EL3_A32_SMC0	0x4e000000
 
+cpu_reset_prologue cortex_a76
+
 #if DYNAMIC_WORKAROUND_CVE_2018_3639
 	/*
 	 * This macro applies the mitigation for CVE-2018-3639.
@@ -344,11 +347,10 @@
 check_erratum_custom_start cortex_a76, ERRATUM(1286807)
 #if ERRATA_A76_1286807
 	mov x0, #ERRATA_APPLIES
-	ret
 #else
-	mov	x1, #0x30
-	b	cpu_rev_var_ls
+	cpu_rev_var_ls	CPU_REV(3, 0)
 #endif
+	ret
 check_erratum_custom_end cortex_a76, ERRATUM(1286807)
 
 workaround_reset_start cortex_a76, ERRATUM(1791580), ERRATA_A76_1791580
@@ -419,35 +421,34 @@
 check_erratum_custom_start cortex_a76, ERRATUM(1165522)
 #if ERRATA_A76_1165522
 	mov	x0, #ERRATA_APPLIES
-	ret
 #else
-	mov	x1, #0x30
-	b	cpu_rev_var_ls
+	cpu_rev_var_ls	CPU_REV(3, 0)
 #endif
+	ret
 check_erratum_custom_end cortex_a76, ERRATUM(1165522)
 
 check_erratum_chosen cortex_a76, CVE(2022, 23960), WORKAROUND_CVE_2022_23960
 
 /* erratum has no workaround in the cpu. Generic code must take care */
-add_erratum_entry cortex_a76, CVE(2022, 23960), WORKAROUND_CVE_2022_23960, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a76, CVE(2022, 23960), WORKAROUND_CVE_2022_23960
 
-/* ERRATA_DSU_798953 :
- * The errata is defined in dsu_helpers.S but applies to cortex_a76
- * as well. Henceforth creating symbolic names to the already existing errata
- * workaround functions to get them registered under the Errata Framework.
- */
-.equ check_erratum_cortex_a76_798953, check_errata_dsu_798953
-.equ erratum_cortex_a76_798953_wa, errata_dsu_798953_wa
-add_erratum_entry cortex_a76, ERRATUM(798953), ERRATA_DSU_798953, APPLY_AT_RESET
+workaround_reset_start cortex_a76, ERRATUM(798953), ERRATA_DSU_798953
+	errata_dsu_798953_wa_impl
+workaround_reset_end cortex_a76, ERRATUM(798953)
 
-/* ERRATA_DSU_936184 :
- * The errata is defined in dsu_helpers.S but applies to cortex_a76
- * as well. Henceforth creating symbolic names to the already existing errata
- * workaround functions to get them registered under the Errata Framework.
- */
-.equ check_erratum_cortex_a76_936184, check_errata_dsu_936184
-.equ erratum_cortex_a76_936184_wa, errata_dsu_936184_wa
-add_erratum_entry cortex_a76, ERRATUM(936184), ERRATA_DSU_936184, APPLY_AT_RESET
+check_erratum_custom_start cortex_a76, ERRATUM(798953)
+	check_errata_dsu_798953_impl
+	ret
+check_erratum_custom_end cortex_a76, ERRATUM(798953)
+
+workaround_reset_start cortex_a76, ERRATUM(936184), ERRATA_DSU_936184
+	errata_dsu_936184_wa_impl
+workaround_reset_end cortex_a76, ERRATUM(936184)
+
+check_erratum_custom_start cortex_a76, ERRATUM(936184)
+	check_errata_dsu_936184_impl
+	ret
+check_erratum_custom_end cortex_a76, ERRATUM(936184)
 
 cpu_reset_func_start cortex_a76
 
diff --git a/lib/cpus/aarch64/cortex_a76ae.S b/lib/cpus/aarch64/cortex_a76ae.S
index 2fe3dbc..54af9a0 100644
--- a/lib/cpus/aarch64/cortex_a76ae.S
+++ b/lib/cpus/aarch64/cortex_a76ae.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -21,6 +21,8 @@
 #error "Cortex-A76AE supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+cpu_reset_prologue cortex_a76ae
+
 #if WORKAROUND_CVE_2022_23960
 	wa_cve_2022_23960_bhb_vector_table CORTEX_A76AE_BHB_LOOP_COUNT, cortex_a76ae
 #endif /* WORKAROUND_CVE_2022_23960 */
diff --git a/lib/cpus/aarch64/cortex_a77.S b/lib/cpus/aarch64/cortex_a77.S
index 766bdc0..7fb964d 100644
--- a/lib/cpus/aarch64/cortex_a77.S
+++ b/lib/cpus/aarch64/cortex_a77.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -17,6 +17,8 @@
 #error "Cortex-A77 must be compiled with HW_ASSISTED_COHERENCY enabled"
 #endif
 
+cpu_reset_prologue cortex_a77
+
 /* 64-bit only core */
 #if CTX_INCLUDE_AARCH32_REGS == 1
 #error "Cortex-A77 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
@@ -36,8 +38,7 @@
 workaround_reset_start cortex_a77, ERRATUM(1508412), ERRATA_A77_1508412
 	/* move cpu revision in again and compare against r0p0 */
 	mov	x0, x7
-	mov	x1, #CPU_REV(0, 0)
-	bl	cpu_rev_var_ls
+	cpu_rev_var_ls	CPU_REV(0, 0)
 	cbz	x0, 1f
 
 	ldr	x0, =0x0
diff --git a/lib/cpus/aarch64/cortex_a78.S b/lib/cpus/aarch64/cortex_a78.S
index 9f2ffdf..a66214b 100644
--- a/lib/cpus/aarch64/cortex_a78.S
+++ b/lib/cpus/aarch64/cortex_a78.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -24,6 +24,8 @@
 	wa_cve_2022_23960_bhb_vector_table CORTEX_A78_BHB_LOOP_COUNT, cortex_a78
 #endif /* WORKAROUND_CVE_2022_23960 */
 
+cpu_reset_prologue cortex_a78
+
 /* Disable hardware page aggregation.Enables mitigation for `CVE-2024-5660` */
 workaround_reset_start cortex_a78, CVE(2024, 5660), WORKAROUND_CVE_2024_5660
 	sysreg_bit_set CORTEX_A78_CPUECTLR_EL1, BIT(46)
diff --git a/lib/cpus/aarch64/cortex_a78_ae.S b/lib/cpus/aarch64/cortex_a78_ae.S
index 7fa1f9b..c537967 100644
--- a/lib/cpus/aarch64/cortex_a78_ae.S
+++ b/lib/cpus/aarch64/cortex_a78_ae.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2025, Arm Limited. All rights reserved.
  * Copyright (c) 2021-2023, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -22,6 +22,8 @@
 	wa_cve_2022_23960_bhb_vector_table CORTEX_A78_AE_BHB_LOOP_COUNT, cortex_a78_ae
 #endif /* WORKAROUND_CVE_2022_23960 */
 
+cpu_reset_prologue cortex_a78_ae
+
 /* Disable hardware page aggregation. Enables mitigation for `CVE-2024-5660` */
 workaround_reset_start cortex_a78_ae, CVE(2024, 5660), WORKAROUND_CVE_2024_5660
 	sysreg_bit_set CORTEX_A78_AE_CPUECTLR_EL1, BIT(46)
diff --git a/lib/cpus/aarch64/cortex_a78c.S b/lib/cpus/aarch64/cortex_a78c.S
index 3f6944a..aba7d25 100644
--- a/lib/cpus/aarch64/cortex_a78c.S
+++ b/lib/cpus/aarch64/cortex_a78c.S
@@ -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
  */
@@ -21,6 +21,8 @@
 	wa_cve_2022_23960_bhb_vector_table CORTEX_A78C_BHB_LOOP_COUNT, cortex_a78c
 #endif /* WORKAROUND_CVE_2022_23960 */
 
+cpu_reset_prologue cortex_a78c
+
 /* Disable hardware page aggregation. Enables mitigation for `CVE-2024-5660` */
 workaround_reset_start cortex_a78c, CVE(2024, 5660), WORKAROUND_CVE_2024_5660
 	sysreg_bit_set CORTEX_A78C_CPUECTLR_EL1, BIT(46)
diff --git a/lib/cpus/aarch64/cortex_alto.S b/lib/cpus/aarch64/cortex_alto.S
index 1422563..69a630d 100644
--- a/lib/cpus/aarch64/cortex_alto.S
+++ b/lib/cpus/aarch64/cortex_alto.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -25,9 +25,12 @@
 #error "Travis needs ERRATA_SME_POWER_DOWN=1 to powerdown correctly"
 #endif
 
+cpu_reset_prologue cortex_alto
+
 cpu_reset_func_start cortex_alto
 	/* Disable speculative loads */
 	msr	SSBS, xzr
+	enable_mpmm
 cpu_reset_func_end cortex_alto
 
 func cortex_alto_core_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_arcadia.S b/lib/cpus/aarch64/cortex_arcadia.S
index c97d87d..84749b6 100644
--- a/lib/cpus/aarch64/cortex_arcadia.S
+++ b/lib/cpus/aarch64/cortex_arcadia.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -21,9 +21,12 @@
 #error "Cortex-ARCADIA supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+cpu_reset_prologue cortex_arcadia
+
 cpu_reset_func_start cortex_arcadia
 	/* Disable speculative loads */
 	msr	SSBS, xzr
+	enable_mpmm
 cpu_reset_func_end cortex_arcadia
 
 	/* ----------------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_gelas.S b/lib/cpus/aarch64/cortex_gelas.S
index 709bb12..4cdec32 100644
--- a/lib/cpus/aarch64/cortex_gelas.S
+++ b/lib/cpus/aarch64/cortex_gelas.S
@@ -29,6 +29,8 @@
 #error "Gelas needs ERRATA_SME_POWER_DOWN=1 to powerdown correctly"
 #endif
 
+cpu_reset_prologue cortex_gelas
+
 cpu_reset_func_start cortex_gelas
 	/* ----------------------------------------------------
 	 * Disable speculative loads
@@ -38,6 +40,7 @@
 	/* model bug: not cleared on reset */
 	sysreg_bit_clear 	CORTEX_GELAS_CPUPWRCTLR_EL1, \
 		CORTEX_GELAS_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
+	enable_mpmm
 cpu_reset_func_end cortex_gelas
 
 	/* ----------------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_x1.S b/lib/cpus/aarch64/cortex_x1.S
index 5bd020c..27d181a 100644
--- a/lib/cpus/aarch64/cortex_x1.S
+++ b/lib/cpus/aarch64/cortex_x1.S
@@ -23,6 +23,8 @@
 	wa_cve_2022_23960_bhb_vector_table CORTEX_X1_BHB_LOOP_COUNT, cortex_x1
 #endif /* WORKAROUND_CVE_2022_23960 */
 
+cpu_reset_prologue cortex_x1
+
 /* Disable hardware page aggregation. Enables mitigation for `CVE-2024-5660` */
 workaround_reset_start cortex_x1, CVE(2024, 5660), WORKAROUND_CVE_2024_5660
 	sysreg_bit_set CORTEX_X1_CPUECTLR_EL1, BIT(46)
diff --git a/lib/cpus/aarch64/cortex_x2.S b/lib/cpus/aarch64/cortex_x2.S
index c18ce3c..b11c37d 100644
--- a/lib/cpus/aarch64/cortex_x2.S
+++ b/lib/cpus/aarch64/cortex_x2.S
@@ -9,6 +9,7 @@
 #include <common/bl_common.h>
 #include <cortex_x2.h>
 #include <cpu_macros.S>
+#include <dsu_macros.S>
 #include <plat_macros.S>
 #include "wa_cve_2022_23960_bhb_vector.S"
 
@@ -24,7 +25,7 @@
 
 .global check_erratum_cortex_x2_3701772
 
-add_erratum_entry cortex_x2, ERRATUM(3701772), ERRATA_X2_3701772, NO_APPLY_AT_RESET
+add_erratum_entry cortex_x2, ERRATUM(3701772), ERRATA_X2_3701772
 
 check_erratum_ls cortex_x2, ERRATUM(3701772), CPU_REV(2, 1)
 
@@ -32,6 +33,8 @@
 	wa_cve_2022_23960_bhb_vector_table CORTEX_X2_BHB_LOOP_COUNT, cortex_x2
 #endif /* WORKAROUND_CVE_2022_23960 */
 
+cpu_reset_prologue cortex_x2
+
 /* Disable hardware page aggregation. Enables mitigation for `CVE-2024-5660` */
 workaround_reset_start cortex_x2, CVE(2024, 5660), WORKAROUND_CVE_2024_5660
 	sysreg_bit_set CORTEX_X2_CPUECTLR_EL1, BIT(46)
@@ -164,15 +167,14 @@
 
 check_erratum_chosen cortex_x2, CVE(2022, 23960), WORKAROUND_CVE_2022_23960
 
-/*
- * ERRATA_DSU_2313941 :
- * The errata is defined in dsu_helpers.S but applies to cortex_x2
- * as well. Henceforth creating symbolic names to the already existing errata
- * workaround functions to get them registered under the Errata Framework.
- */
-.equ check_erratum_cortex_x2_2313941, check_errata_dsu_2313941
-.equ erratum_cortex_x2_2313941_wa, errata_dsu_2313941_wa
-add_erratum_entry cortex_x2, ERRATUM(2313941), ERRATA_DSU_2313941, APPLY_AT_RESET
+workaround_reset_start cortex_x2, ERRATUM(2313941), ERRATA_DSU_2313941
+	errata_dsu_2313941_wa_impl
+workaround_reset_end cortex_x2, ERRATUM(2313941)
+
+check_erratum_custom_start cortex_x2, ERRATUM(2313941)
+	check_errata_dsu_2313941_impl
+	ret
+check_erratum_custom_end cortex_x2, ERRATUM(2313941)
 
 	/* ----------------------------------------------------
 	 * HW will do the cache maintenance while powering down
@@ -193,6 +195,7 @@
 cpu_reset_func_start cortex_x2
 	/* Disable speculative loads */
 	msr	SSBS, xzr
+	enable_mpmm
 cpu_reset_func_end cortex_x2
 
 	/* ---------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_x3.S b/lib/cpus/aarch64/cortex_x3.S
index 503a4e5..3d52dae 100644
--- a/lib/cpus/aarch64/cortex_x3.S
+++ b/lib/cpus/aarch64/cortex_x3.S
@@ -24,7 +24,7 @@
 
 .global check_erratum_cortex_x3_3701769
 
-add_erratum_entry cortex_x3, ERRATUM(3701769), ERRATA_X3_3701769, NO_APPLY_AT_RESET
+add_erratum_entry cortex_x3, ERRATUM(3701769), ERRATA_X3_3701769
 
 check_erratum_ls cortex_x3, ERRATUM(3701769), CPU_REV(1, 2)
 
@@ -32,6 +32,8 @@
 	wa_cve_2022_23960_bhb_vector_table CORTEX_X3_BHB_LOOP_COUNT, cortex_x3
 #endif /* WORKAROUND_CVE_2022_23960 */
 
+cpu_reset_prologue cortex_x3
+
 /* Disable hardware page aggregation. Enables mitigation for `CVE-2024-5660` */
 workaround_reset_start cortex_x3, CVE(2024, 5660), WORKAROUND_CVE_2024_5660
 	sysreg_bit_set CORTEX_X3_CPUECTLR_EL1, BIT(46)
@@ -52,9 +54,9 @@
 
 check_erratum_ls cortex_x3, ERRATUM(2266875), CPU_REV(1, 0)
 
-workaround_runtime_start cortex_x3, ERRATUM(2302506), ERRATA_X3_2302506
+workaround_reset_start cortex_x3, ERRATUM(2302506), ERRATA_X3_2302506
 	sysreg_bit_set	CORTEX_X3_CPUACTLR2_EL1, BIT(0)
-workaround_runtime_end cortex_x3, ERRATUM(2302506), NO_ISB
+workaround_reset_end cortex_x3, ERRATUM(2302506)
 
 check_erratum_ls cortex_x3, ERRATUM(2302506), CPU_REV(1, 1)
 
@@ -84,9 +86,9 @@
 
 check_erratum_ls cortex_x3, ERRATUM(2615812), CPU_REV(1, 1)
 
-workaround_runtime_start cortex_x3, ERRATUM(2641945), ERRATA_X3_2641945
+workaround_reset_start cortex_x3, ERRATUM(2641945), ERRATA_X3_2641945
 	sysreg_bit_set	CORTEX_X3_CPUACTLR6_EL1, BIT(41)
-workaround_runtime_end cortex_x3, ERRATUM(2641945), NO_ISB
+workaround_reset_end cortex_x3, ERRATUM(2641945)
 
 check_erratum_ls cortex_x3, ERRATUM(2641945), CPU_REV(1, 0)
 
@@ -134,6 +136,7 @@
 cpu_reset_func_start cortex_x3
 	/* Disable speculative loads */
 	msr	SSBS, xzr
+	enable_mpmm
 cpu_reset_func_end cortex_x3
 
 	/* ----------------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_x4.S b/lib/cpus/aarch64/cortex_x4.S
index 1e81892..c067981 100644
--- a/lib/cpus/aarch64/cortex_x4.S
+++ b/lib/cpus/aarch64/cortex_x4.S
@@ -22,6 +22,8 @@
 #error "Cortex X4 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+cpu_reset_prologue cortex_x4
+
 .global check_erratum_cortex_x4_2726228
 .global check_erratum_cortex_x4_3701758
 
@@ -29,23 +31,9 @@
         wa_cve_2022_23960_bhb_vector_table CORTEX_X4_BHB_LOOP_COUNT, cortex_x4
 #endif /* WORKAROUND_CVE_2022_23960 */
 
-workaround_runtime_start cortex_x4, ERRATUM(2726228), ERRATA_X4_2726228, CORTEX_X4_MIDR
-workaround_runtime_end cortex_x4, ERRATUM(2726228)
+add_erratum_entry cortex_x4, ERRATUM(2726228), ERRATA_X4_2726228
 
-check_erratum_custom_start cortex_x4, ERRATUM(2726228)
-
-	/* This erratum needs to be enabled for r0p0 and r0p1.
-	 * Check if revision is less than or equal to r0p1.
-	 */
-
-#if ERRATA_X4_2726228
-	mov	x1, #1
-	b	cpu_rev_var_ls
-#else
-	mov	x0, #ERRATA_MISSING
-#endif
-	ret
-check_erratum_custom_end cortex_x4, ERRATUM(2726228)
+check_erratum_ls cortex_x4, ERRATUM(2726228), CPU_REV(0, 1)
 
 /* Disable hardware page aggregation. Enables mitigation for `CVE-2024-5660` */
 workaround_reset_start cortex_x4, CVE(2024, 5660), WORKAROUND_CVE_2024_5660
@@ -135,13 +123,14 @@
 
 check_erratum_chosen cortex_x4, CVE(2024, 7881), WORKAROUND_CVE_2024_7881
 
-add_erratum_entry cortex_x4, ERRATUM(3701758), ERRATA_X4_3701758, NO_APPLY_AT_RESET
+add_erratum_entry cortex_x4, ERRATUM(3701758), ERRATA_X4_3701758
 
 check_erratum_ls cortex_x4, ERRATUM(3701758), CPU_REV(0, 3)
 
 cpu_reset_func_start cortex_x4
 	/* Disable speculative loads */
 	msr	SSBS, xzr
+	enable_mpmm
 cpu_reset_func_end cortex_x4
 
 	/* ----------------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_x925.S b/lib/cpus/aarch64/cortex_x925.S
index 5974c18..093d91d 100644
--- a/lib/cpus/aarch64/cortex_x925.S
+++ b/lib/cpus/aarch64/cortex_x925.S
@@ -21,9 +21,9 @@
 #error "Cortex-X925 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
-.global check_erratum_cortex_x925_3701747
+cpu_reset_prologue cortex_x925
 
-add_erratum_entry cortex_x925, ERRATUM(3701747), ERRATA_X925_3701747, NO_APPLY_AT_RESET
+add_erratum_entry cortex_x925, ERRATUM(3701747), ERRATA_X925_3701747
 
 check_erratum_ls cortex_x925, ERRATUM(3701747), CPU_REV(0, 1)
 
@@ -63,6 +63,7 @@
 cpu_reset_func_start cortex_x925
 	/* Disable speculative loads */
 	msr	SSBS, xzr
+	enable_mpmm
 cpu_reset_func_end cortex_x925
 
 	/* ----------------------------------------------------
diff --git a/lib/cpus/aarch64/cpu_helpers.S b/lib/cpus/aarch64/cpu_helpers.S
index 0f9a3b8..e608422 100644
--- a/lib/cpus/aarch64/cpu_helpers.S
+++ b/lib/cpus/aarch64/cpu_helpers.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,47 +14,6 @@
 #include <lib/cpus/errata.h>
 #include <lib/el3_runtime/cpu_data.h>
 
- /* Reset fn is needed in BL at reset vector */
-#if defined(IMAGE_BL1) || defined(IMAGE_BL31) ||	\
-	(defined(IMAGE_BL2) && RESET_TO_BL2)
-	/*
-	 * The reset handler common to all platforms.  After a matching
-	 * cpu_ops structure entry is found, the correponding reset_handler
-	 * in the cpu_ops is invoked.
-	 * Clobbers: x0 - x19, x30
-	 */
-	.globl	reset_handler
-func reset_handler
-	mov	x19, x30
-
-	/* The plat_reset_handler can clobber x0 - x18, x30 */
-	bl	plat_reset_handler
-
-	/* Get the matching cpu_ops pointer */
-	bl	get_cpu_ops_ptr
-
-#if ENABLE_ASSERTIONS
-	/*
-	 * Assert if invalid cpu_ops obtained. If this is not valid, it may
-	 * suggest that the proper CPU file hasn't been included.
-	 */
-	cmp	x0, #0
-	ASM_ASSERT(ne)
-#endif
-
-	/* Get the cpu_ops reset handler */
-	ldr	x2, [x0, #CPU_RESET_FUNC]
-	mov	x30, x19
-	cbz	x2, 1f
-
-	/* The cpu_ops reset handler can clobber x0 - x19, x30 */
-	br	x2
-1:
-	ret
-endfunc reset_handler
-
-#endif
-
 #ifdef IMAGE_BL31 /* The power down core and cluster is needed only in  BL31 */
 	/*
 	 * void prepare_cpu_pwr_dwn(unsigned int power_level)
@@ -213,83 +172,24 @@
 	b	1b
 error_exit:
 #endif
+#if ENABLE_ASSERTIONS
+	/*
+	 * Assert if invalid cpu_ops obtained. If this is not valid, it may
+	 * suggest that the proper CPU file hasn't been included.
+	 */
+	cmp	x0, #0
+	ASM_ASSERT(ne)
+#endif
 	ret
 endfunc get_cpu_ops_ptr
 
-/*
- * Extract CPU revision and variant, and combine them into a single numeric for
- * easier comparison.
- */
 	.globl	cpu_get_rev_var
 func cpu_get_rev_var
-	mrs	x1, midr_el1
-
-	/*
-	 * Extract the variant[23:20] and revision[3:0] from MIDR, and pack them
-	 * as variant[7:4] and revision[3:0] of x0.
-	 *
-	 * First extract x1[23:16] to x0[7:0] and zero fill the rest. Then
-	 * extract x1[3:0] into x0[3:0] retaining other bits.
-	 */
-	ubfx	x0, x1, #(MIDR_VAR_SHIFT - MIDR_REV_BITS), #(MIDR_REV_BITS + MIDR_VAR_BITS)
-	bfxil	x0, x1, #MIDR_REV_SHIFT, #MIDR_REV_BITS
+	get_rev_var x0, x1
 	ret
 endfunc cpu_get_rev_var
 
 /*
- * Compare the CPU's revision-variant (x0) with a given value (x1), for errata
- * application purposes. If the revision-variant is less than or same as a given
- * value, indicates that errata applies; otherwise not.
- *
- * Shall clobber: x0-x3
- */
-	.globl	cpu_rev_var_ls
-func cpu_rev_var_ls
-	mov	x2, #ERRATA_APPLIES
-	mov	x3, #ERRATA_NOT_APPLIES
-	cmp	x0, x1
-	csel	x0, x2, x3, ls
-	ret
-endfunc cpu_rev_var_ls
-
-/*
- * Compare the CPU's revision-variant (x0) with a given value (x1), for errata
- * application purposes. If the revision-variant is higher than or same as a
- * given value, indicates that errata applies; otherwise not.
- *
- * Shall clobber: x0-x3
- */
-	.globl	cpu_rev_var_hs
-func cpu_rev_var_hs
-	mov	x2, #ERRATA_APPLIES
-	mov	x3, #ERRATA_NOT_APPLIES
-	cmp	x0, x1
-	csel	x0, x2, x3, hs
-	ret
-endfunc cpu_rev_var_hs
-
-/*
- * Compare the CPU's revision-variant (x0) with a given range (x1 - x2), for errata
- * application purposes. If the revision-variant is between or includes the given
- * values, this indicates that errata applies; otherwise not.
- *
- * Shall clobber: x0-x4
- */
-	.globl	cpu_rev_var_range
-func cpu_rev_var_range
-	mov	x3, #ERRATA_APPLIES
-	mov	x4, #ERRATA_NOT_APPLIES
-	cmp	x0, x1
-	csel	x1, x3, x4, hs
-	cbz	x1, 1f
-	cmp	x0, x2
-	csel	x1, x3, x4, ls
-1:
-	mov	x0, x1
-	ret
-endfunc cpu_rev_var_range
-
-/*
  * int check_wa_cve_2017_5715(void);
  *
  * This function returns:
diff --git a/lib/cpus/aarch64/denver.S b/lib/cpus/aarch64/denver.S
index ca250d3..64158e7 100644
--- a/lib/cpus/aarch64/denver.S
+++ b/lib/cpus/aarch64/denver.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2025, Arm Limited and Contributors. All rights reserved.
  * Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -13,6 +13,8 @@
 #include <cpu_macros.S>
 #include <plat_macros.S>
 
+cpu_reset_prologue denver
+
 	/* -------------------------------------------------
 	 * CVE-2017-5715 mitigation
 	 *
diff --git a/lib/cpus/aarch64/dsu_helpers.S b/lib/cpus/aarch64/dsu_helpers.S
deleted file mode 100644
index 3c5bf2e..0000000
--- a/lib/cpus/aarch64/dsu_helpers.S
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (c) 2019-2023, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <asm_macros.S>
-#include <dsu_def.h>
-#include <lib/cpus/errata.h>
-
-	/* -----------------------------------------------------------------------
-	 * DSU erratum 798953 check function
-	 * Checks the DSU variant, revision and configuration to determine if
-	 * the erratum applies. Erratum applies on all configurations of the
-	 * DSU and if revision-variant is r0p0.
-	 *
-	 * The erratum was fixed in r0p1.
-	 *
-	 * This function is called from both assembly and C environment. So it
-	 * follows AAPCS.
-	 *
-	 * Clobbers: x0-x3
-	 * -----------------------------------------------------------------------
-	 */
-	.globl	check_errata_dsu_798953
-	.globl	errata_dsu_798953_wa
-	.globl	dsu_pwr_dwn
-
-func check_errata_dsu_798953
-	mov	x2, #ERRATA_APPLIES
-	mov	x3, #ERRATA_NOT_APPLIES
-
-	/* Check if DSU is equal to r0p0 */
-	mrs	x1, CLUSTERIDR_EL1
-
-	/* DSU variant and revision bitfields in CLUSTERIDR are adjacent */
-	ubfx	x0, x1, #CLUSTERIDR_REV_SHIFT,\
-			#(CLUSTERIDR_REV_BITS + CLUSTERIDR_VAR_BITS)
-	mov	x1, #(0x0 << CLUSTERIDR_REV_SHIFT)
-	cmp	x0, x1
-	csel	x0, x2, x3, EQ
-	ret
-endfunc check_errata_dsu_798953
-
-	/* --------------------------------------------------
-	 * Errata Workaround for DSU erratum #798953.
-	 *
-	 * Can clobber only: x0-x8
-	 * --------------------------------------------------
-	 */
-func errata_dsu_798953_wa
-	mov	x8, x30
-	bl	check_errata_dsu_798953
-	cbz	x0, 1f
-
-	/* If erratum applies, disable high-level clock gating */
-	mrs	x0, CLUSTERACTLR_EL1
-	orr	x0, x0, #CLUSTERACTLR_EL1_DISABLE_CLOCK_GATING
-	msr	CLUSTERACTLR_EL1, x0
-	isb
-1:
-	ret	x8
-endfunc errata_dsu_798953_wa
-
-	/* -----------------------------------------------------------------------
-	 * DSU erratum 936184 check function
-	 * Checks the DSU variant, revision and configuration to determine if
-	 * the erratum applies. Erratum applies if ACP interface is present
-	 * in the DSU and revision-variant < r2p0.
-	 *
-	 * The erratum was fixed in r2p0.
-	 *
-	 * This function is called from both assembly and C environment. So it
-	 * follows AAPCS.
-	 *
-	 * Clobbers: x0-x4
-	 * -----------------------------------------------------------------------
-	 */
-	.globl	check_errata_dsu_936184
-	.globl	errata_dsu_936184_wa
-	.weak	is_scu_present_in_dsu
-
-	/* --------------------------------------------------------------------
-	 * Default behaviour respresents SCU is always present with DSU.
-	 * CPUs can override this definition if required.
-	 *
-	 * Can clobber only: x0-x3
-	 * --------------------------------------------------------------------
-	 */
-func is_scu_present_in_dsu
-	mov	x0, #1
-	ret
-endfunc is_scu_present_in_dsu
-
-func check_errata_dsu_936184
-	mov	x4, x30
-	bl	is_scu_present_in_dsu
-	cmp	x0, xzr
-	/* Default error status */
-	mov	x0, #ERRATA_NOT_APPLIES
-
-	/* If SCU is not present, return without applying patch */
-	b.eq	1f
-
-	/* Erratum applies only if DSU has the ACP interface */
-	mrs	x1, CLUSTERCFR_EL1
-	ubfx	x1, x1, #CLUSTERCFR_ACP_SHIFT, #1
-	cbz	x1, 1f
-
-	/* If ACP is present, check if DSU is older than r2p0 */
-	mrs	x1, CLUSTERIDR_EL1
-
-	/* DSU variant and revision bitfields in CLUSTERIDR are adjacent */
-	ubfx	x2, x1, #CLUSTERIDR_REV_SHIFT,\
-			#(CLUSTERIDR_REV_BITS + CLUSTERIDR_VAR_BITS)
-	cmp x2, #(0x2 << CLUSTERIDR_VAR_SHIFT)
-	b.hs	1f
-	mov	x0, #ERRATA_APPLIES
-1:
-	ret	x4
-endfunc check_errata_dsu_936184
-
-	/* --------------------------------------------------
-	 * Errata Workaround for DSU erratum #936184.
-	 *
-	 * Can clobber only: x0-x8
-	 * --------------------------------------------------
-	 */
-func errata_dsu_936184_wa
-	mov	x8, x30
-	bl	check_errata_dsu_936184
-	cbz	x0, 1f
-
-	/* If erratum applies, we set a mask to a DSU control register */
-	mrs	x0, CLUSTERACTLR_EL1
-	ldr	x1, =DSU_ERRATA_936184_MASK
-	orr	x0, x0, x1
-	msr	CLUSTERACTLR_EL1, x0
-	isb
-1:
-	ret	x8
-endfunc errata_dsu_936184_wa
-
-	/* -----------------------------------------------------------------------
-	 * DSU erratum 2313941 check function
-	 * Checks the DSU variant, revision and configuration to determine if
-	 * the erratum applies. Erratum applies on all configurations of the
-	 * DSU and if revision-variant is r0p0, r1p0, r2p0, r2p1, r3p0, r3p1.
-	 *
-	 * The erratum is still open.
-	 *
-	 * This function is called from both assembly and C environment. So it
-	 * follows AAPCS.
-	 *
-	 * Clobbers: x0-x4
-	 * -----------------------------------------------------------------------
-	 */
-	.globl	check_errata_dsu_2313941
-	.globl	errata_dsu_2313941_wa
-
-func check_errata_dsu_2313941
-	mov	x4, x30
-	bl	is_scu_present_in_dsu
-	cmp	x0, xzr
-	/* Default error status */
-	mov	x0, #ERRATA_NOT_APPLIES
-
-	/* If SCU is not present, return without applying patch */
-	b.eq	1f
-
-	mov	x2, #ERRATA_APPLIES
-	mov	x3, #ERRATA_NOT_APPLIES
-
-	/* Check if DSU version is less than or equal to r3p1 */
-	mrs	x1, CLUSTERIDR_EL1
-
-	/* DSU variant and revision bitfields in CLUSTERIDR are adjacent */
-	ubfx	x0, x1, #CLUSTERIDR_REV_SHIFT,\
-			#(CLUSTERIDR_REV_BITS + CLUSTERIDR_VAR_BITS)
-	mov	x1, #(0x31 << CLUSTERIDR_REV_SHIFT)
-	cmp	x0, x1
-	csel	x0, x2, x3, LS
-1:
-	ret	x4
-endfunc check_errata_dsu_2313941
-
-	/* --------------------------------------------------
-	 * Errata Workaround for DSU erratum #2313941.
-	 *
-	 * Can clobber only: x0-x8
-	 * --------------------------------------------------
-	 */
-func errata_dsu_2313941_wa
-	mov	x8, x30
-	bl	check_errata_dsu_2313941
-	cbz	x0, 1f
-
-	/* If erratum applies, disable high-level clock gating */
-	mrs	x0, CLUSTERACTLR_EL1
-	orr	x0, x0, #CLUSTERACTLR_EL1_DISABLE_SCLK_GATING
-	msr	CLUSTERACTLR_EL1, x0
-	isb
-1:
-	ret	x8
-endfunc errata_dsu_2313941_wa
-
-	/* ---------------------------------------------
-	 * controls power features of the cluster
-	 * 1. Cache portion power not request
-	 * 2. Disable the retention circuit
-	 * ---------------------------------------------
-	 */
-func dsu_pwr_dwn
-	msr	CLUSTERPWRCTLR_EL1, xzr
-	isb
-	ret
-endfunc dsu_pwr_dwn
diff --git a/lib/cpus/aarch64/generic.S b/lib/cpus/aarch64/generic.S
index 5d7a857..0a10eed 100644
--- a/lib/cpus/aarch64/generic.S
+++ b/lib/cpus/aarch64/generic.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,6 +11,8 @@
 #include <cpu_macros.S>
 #include <plat_macros.S>
 
+cpu_reset_prologue generic
+
 	/* ---------------------------------------------
 	 * Disable L1 data cache and unified L2 cache
 	 * ---------------------------------------------
@@ -80,7 +82,9 @@
  * ---------------------------------------------
  */
 .equ	generic_cpu_reg_dump,		0
-.equ	generic_reset_func,		0
+
+cpu_reset_func_start generic
+cpu_reset_func_end generic
 
 declare_cpu_ops generic, AARCH64_GENERIC_MIDR, \
 	generic_reset_func, \
diff --git a/lib/cpus/aarch64/neoverse_e1.S b/lib/cpus/aarch64/neoverse_e1.S
index 4bc95d0..f37bb28 100644
--- a/lib/cpus/aarch64/neoverse_e1.S
+++ b/lib/cpus/aarch64/neoverse_e1.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,6 +7,7 @@
 #include <asm_macros.S>
 #include <common/bl_common.h>
 #include <common/debug.h>
+#include <dsu_macros.S>
 #include <neoverse_e1.h>
 #include <cpu_macros.S>
 #include <plat_macros.S>
@@ -21,15 +22,18 @@
 #error "Neoverse-E1 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
-/*
- * ERRATA_DSU_936184:
- * The errata is defined in dsu_helpers.S and applies to neoverse_e1.
- * Henceforth creating symbolic names to the already existing errata
- * workaround functions to get them registered under the Errata Framework.
- */
-.equ check_erratum_neoverse_e1_936184, check_errata_dsu_936184
-.equ erratum_neoverse_e1_936184_wa, errata_dsu_936184_wa
-add_erratum_entry neoverse_e1, ERRATUM(936184), ERRATA_DSU_936184, APPLY_AT_RESET
+cpu_reset_prologue neoverse_e1
+
+workaround_reset_start neoverse_e1, ERRATUM(936184), ERRATA_DSU_936184
+	errata_dsu_936184_wa_impl
+workaround_reset_end neoverse_e1, ERRATUM(936184)
+
+check_erratum_custom_start neoverse_e1, ERRATUM(936184)
+	branch_if_scu_not_present 2f /* label 1 is used in the macro */
+	check_errata_dsu_936184_impl
+	2:
+	ret
+check_erratum_custom_end neoverse_e1, ERRATUM(936184)
 
 cpu_reset_func_start neoverse_e1
 cpu_reset_func_end neoverse_e1
diff --git a/lib/cpus/aarch64/neoverse_n1.S b/lib/cpus/aarch64/neoverse_n1.S
index f727226..1ad9557 100644
--- a/lib/cpus/aarch64/neoverse_n1.S
+++ b/lib/cpus/aarch64/neoverse_n1.S
@@ -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
  */
@@ -8,6 +8,7 @@
 #include <asm_macros.S>
 #include <cpuamu.h>
 #include <cpu_macros.S>
+#include <dsu_macros.S>
 #include <neoverse_n1.h>
 #include "wa_cve_2022_23960_bhb_vector.S"
 
@@ -27,15 +28,18 @@
 	wa_cve_2022_23960_bhb_vector_table NEOVERSE_N1_BHB_LOOP_COUNT, neoverse_n1
 #endif /* WORKAROUND_CVE_2022_23960 */
 
-/*
- * ERRATA_DSU_936184:
- * The errata is defined in dsu_helpers.S and applies to Neoverse N1.
- * Henceforth creating symbolic names to the already existing errata
- * workaround functions to get them registered under the Errata Framework.
- */
-.equ check_erratum_neoverse_n1_936184, check_errata_dsu_936184
-.equ erratum_neoverse_n1_936184_wa, errata_dsu_936184_wa
-add_erratum_entry neoverse_n1, ERRATUM(936184), ERRATA_DSU_936184, APPLY_AT_RESET
+cpu_reset_prologue neoverse_n1
+
+workaround_reset_start neoverse_n1, ERRATUM(936184), ERRATA_DSU_936184
+	errata_dsu_936184_wa_impl
+workaround_reset_end neoverse_n1, ERRATUM(936184)
+
+check_erratum_custom_start neoverse_n1, ERRATUM(936184)
+	branch_if_scu_not_present 2f /* label 1 is used in the macro */
+	check_errata_dsu_936184_impl
+	2:
+	ret
+check_erratum_custom_end neoverse_n1, ERRATUM(936184)
 
 workaround_reset_start neoverse_n1, ERRATUM(1043202), ERRATA_N1_1043202
 	/* Apply instruction patching sequence */
diff --git a/lib/cpus/aarch64/neoverse_n2.S b/lib/cpus/aarch64/neoverse_n2.S
index ce7e834..9c6f01a 100644
--- a/lib/cpus/aarch64/neoverse_n2.S
+++ b/lib/cpus/aarch64/neoverse_n2.S
@@ -7,6 +7,7 @@
 #include <arch.h>
 #include <asm_macros.S>
 #include <cpu_macros.S>
+#include <dsu_macros.S>
 #include <neoverse_n2.h>
 #include "wa_cve_2022_23960_bhb_vector.S"
 
@@ -22,7 +23,7 @@
 
 .global check_erratum_neoverse_n2_3701773
 
-add_erratum_entry neoverse_n2, ERRATUM(3701773), ERRATA_N2_3701773, NO_APPLY_AT_RESET
+add_erratum_entry neoverse_n2, ERRATUM(3701773), ERRATA_N2_3701773
 
 check_erratum_ls neoverse_n2, ERRATUM(3701773), CPU_REV(0, 3)
 
@@ -30,15 +31,18 @@
 	wa_cve_2022_23960_bhb_vector_table NEOVERSE_N2_BHB_LOOP_COUNT, neoverse_n2
 #endif /* WORKAROUND_CVE_2022_23960 */
 
-/*
- * ERRATA_DSU_2313941:
- * The errata is defined in dsu_helpers.S and applies to Neoverse N2.
- * Henceforth creating symbolic names to the already existing errata
- * workaround functions to get them registered under the Errata Framework.
- */
-.equ check_erratum_neoverse_n2_2313941, check_errata_dsu_2313941
-.equ erratum_neoverse_n2_2313941_wa, errata_dsu_2313941_wa
-add_erratum_entry neoverse_n2, ERRATUM(2313941), ERRATA_DSU_2313941, APPLY_AT_RESET
+cpu_reset_prologue neoverse_n2
+
+workaround_reset_start neoverse_n2, ERRATUM(2313941), ERRATA_DSU_2313941
+	errata_dsu_2313941_wa_impl
+workaround_reset_end neoverse_n2, ERRATUM(2313941)
+
+check_erratum_custom_start neoverse_n2, ERRATUM(2313941)
+	branch_if_scu_not_present 2f /* label 1 is used in the macro */
+	check_errata_dsu_2313941_impl
+	2:
+	ret
+check_erratum_custom_end neoverse_n2, ERRATUM(2313941)
 
 /* Disable hardware page aggregation. Enables mitigation for `CVE-2024-5660` */
 workaround_reset_start neoverse_n2, CVE(2024, 5660), WORKAROUND_CVE_2024_5660
@@ -180,20 +184,20 @@
 
 check_erratum_ls neoverse_n2, ERRATUM(2326639), CPU_REV(0, 0)
 
-workaround_runtime_start neoverse_n2, ERRATUM(2340933), ERRATA_N2_2340933
+workaround_reset_start neoverse_n2, ERRATUM(2340933), ERRATA_N2_2340933
 	/* Set bit 61 in CPUACTLR5_EL1 */
 	sysreg_bit_set NEOVERSE_N2_CPUACTLR5_EL1, BIT(61)
-workaround_runtime_end neoverse_n2, ERRATUM(2340933)
+workaround_reset_end neoverse_n2, ERRATUM(2340933)
 
 check_erratum_ls neoverse_n2, ERRATUM(2340933), CPU_REV(0, 0)
 
-workaround_runtime_start neoverse_n2, ERRATUM(2346952), ERRATA_N2_2346952
+workaround_reset_start neoverse_n2, ERRATUM(2346952), ERRATA_N2_2346952
 	/* Set TXREQ to STATIC and full L2 TQ size */
 	mrs	x1, NEOVERSE_N2_CPUECTLR2_EL1
 	mov	x0, #CPUECTLR2_EL1_TXREQ_STATIC_FULL
 	bfi	x1, x0, #CPUECTLR2_EL1_TXREQ_LSB, #CPUECTLR2_EL1_TXREQ_WIDTH
 	msr	NEOVERSE_N2_CPUECTLR2_EL1, x1
-workaround_runtime_end neoverse_n2, ERRATUM(2346952)
+workaround_reset_end neoverse_n2, ERRATUM(2346952)
 
 check_erratum_ls neoverse_n2, ERRATUM(2346952), CPU_REV(0, 2)
 
diff --git a/lib/cpus/aarch64/neoverse_n3.S b/lib/cpus/aarch64/neoverse_n3.S
index 8abcafe..1b7a3e1 100644
--- a/lib/cpus/aarch64/neoverse_n3.S
+++ b/lib/cpus/aarch64/neoverse_n3.S
@@ -21,9 +21,11 @@
 #error "Neoverse-N3 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+cpu_reset_prologue neoverse_n3
+
 .global check_erratum_neoverse_n3_3699563
 
-add_erratum_entry neoverse_n3, ERRATUM(3699563), ERRATA_N3_3699563, NO_APPLY_AT_RESET
+add_erratum_entry neoverse_n3, ERRATUM(3699563), ERRATA_N3_3699563
 
 check_erratum_ls neoverse_n3, ERRATUM(3699563), CPU_REV(0, 0)
 
diff --git a/lib/cpus/aarch64/neoverse_n_common.S b/lib/cpus/aarch64/neoverse_n_common.S
deleted file mode 100644
index b816342..0000000
--- a/lib/cpus/aarch64/neoverse_n_common.S
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <asm_macros.S>
-#include <neoverse_n_common.h>
-
-	.global is_scu_present_in_dsu
-
-/*
- * Check if the SCU L3 Unit is present on the DSU
- * 1-> SCU present
- * 0-> SCU not present
- *
- * This function is implemented as weak on dsu_helpers.S and must be
- * overwritten for Neoverse Nx cores.
- */
-
-func is_scu_present_in_dsu
-	mrs	x0, CPUCFR_EL1
-	ubfx	x0, x0, #SCU_SHIFT, #1
-	eor	x0, x0, #1
-	ret
-endfunc is_scu_present_in_dsu
diff --git a/lib/cpus/aarch64/neoverse_v1.S b/lib/cpus/aarch64/neoverse_v1.S
index d1a2c24..e1e8214 100644
--- a/lib/cpus/aarch64/neoverse_v1.S
+++ b/lib/cpus/aarch64/neoverse_v1.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -22,6 +22,8 @@
 #error "Neoverse-V1 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+cpu_reset_prologue neoverse_v1
+
 #if WORKAROUND_CVE_2022_23960
 	wa_cve_2022_23960_bhb_vector_table NEOVERSE_V1_BHB_LOOP_COUNT, neoverse_v1
 #endif /* WORKAROUND_CVE_2022_23960 */
@@ -203,10 +205,10 @@
 
 check_erratum_ls neoverse_v1, ERRATUM(2294912), CPU_REV(1, 2)
 
-workaround_runtime_start neoverse_v1, ERRATUM(2348377), ERRATA_V1_2348377
+workaround_reset_start neoverse_v1, ERRATUM(2348377), ERRATA_V1_2348377
 	/* Set bit 61 in CPUACTLR5_EL1 */
 	sysreg_bit_set NEOVERSE_V1_ACTLR5_EL1, NEOVERSE_V1_ACTLR5_EL1_BIT_61
-workaround_runtime_end neoverse_v1, ERRATUM(2348377)
+workaround_reset_end neoverse_v1, ERRATUM(2348377)
 
 check_erratum_ls neoverse_v1, ERRATUM(2348377), CPU_REV(1, 1)
 
diff --git a/lib/cpus/aarch64/neoverse_v2.S b/lib/cpus/aarch64/neoverse_v2.S
index b43f6dd..06521ec 100644
--- a/lib/cpus/aarch64/neoverse_v2.S
+++ b/lib/cpus/aarch64/neoverse_v2.S
@@ -22,6 +22,8 @@
 #error "Neoverse V2 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+cpu_reset_prologue neoverse_v2
+
 /* Disable hardware page aggregation. Enables mitigation for `CVE-2024-5660` */
 workaround_reset_start neoverse_v2, CVE(2024, 5660), WORKAROUND_CVE_2024_5660
 	sysreg_bit_set NEOVERSE_V2_CPUECTLR_EL1, BIT(46)
diff --git a/lib/cpus/aarch64/neoverse_v3.S b/lib/cpus/aarch64/neoverse_v3.S
index dad3709..29bfd0e 100644
--- a/lib/cpus/aarch64/neoverse_v3.S
+++ b/lib/cpus/aarch64/neoverse_v3.S
@@ -22,9 +22,11 @@
 #error "Neoverse V3 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+cpu_reset_prologue neoverse_v3
+
 .global check_erratum_neoverse_v3_3701767
 
-add_erratum_entry neoverse_v3, ERRATUM(3701767), ERRATA_V3_3701767, NO_APPLY_AT_RESET
+add_erratum_entry neoverse_v3, ERRATUM(3701767), ERRATA_V3_3701767
 
 check_erratum_ls neoverse_v3, ERRATUM(3701767), CPU_REV(0, 2)
 
diff --git a/lib/cpus/aarch64/nevis.S b/lib/cpus/aarch64/nevis.S
index 0180ab7..b2aa26e 100644
--- a/lib/cpus/aarch64/nevis.S
+++ b/lib/cpus/aarch64/nevis.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -21,12 +21,15 @@
 #error "Nevis supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+cpu_reset_prologue nevis
+
 cpu_reset_func_start nevis
 	/* ----------------------------------------------------
 	 * Disable speculative loads
 	 * ----------------------------------------------------
 	 */
 	msr	SSBS, xzr
+	enable_mpmm
 cpu_reset_func_end nevis
 
 func nevis_core_pwr_dwn
diff --git a/lib/cpus/aarch64/qemu_max.S b/lib/cpus/aarch64/qemu_max.S
index fb03cf1..a727379 100644
--- a/lib/cpus/aarch64/qemu_max.S
+++ b/lib/cpus/aarch64/qemu_max.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,6 +8,8 @@
 #include <cpu_macros.S>
 #include <qemu_max.h>
 
+cpu_reset_prologue qemu_max
+
 func qemu_max_core_pwr_dwn
 	/* ---------------------------------------------
 	 * Disable the Data Cache.
@@ -47,6 +49,9 @@
 	b	dcsw_op_all
 endfunc qemu_max_cluster_pwr_dwn
 
+cpu_reset_func_start qemu_max
+cpu_reset_func_end qemu_max
+
 	/* ---------------------------------------------
 	 * This function provides cpu specific
 	 * register information for crash reporting.
@@ -67,6 +72,6 @@
 
 
 /* cpu_ops for QEMU MAX */
-declare_cpu_ops qemu_max, QEMU_MAX_MIDR, CPU_NO_RESET_FUNC, \
+declare_cpu_ops qemu_max, QEMU_MAX_MIDR, qemu_max_reset_func, \
 	qemu_max_core_pwr_dwn, \
 	qemu_max_cluster_pwr_dwn
diff --git a/lib/cpus/aarch64/rainier.S b/lib/cpus/aarch64/rainier.S
index ea687be..9ad9362 100644
--- a/lib/cpus/aarch64/rainier.S
+++ b/lib/cpus/aarch64/rainier.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -21,6 +21,8 @@
 #error "Rainier CPU supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+cpu_reset_prologue rainier
+
 /* --------------------------------------------------
  * Disable speculative loads if Rainier supports
  * SSBS.
diff --git a/lib/cpus/aarch64/travis.S b/lib/cpus/aarch64/travis.S
index 2e41668..d53e46f 100644
--- a/lib/cpus/aarch64/travis.S
+++ b/lib/cpus/aarch64/travis.S
@@ -29,6 +29,8 @@
 #error "Travis needs ERRATA_SME_POWER_DOWN=1 to powerdown correctly"
 #endif
 
+cpu_reset_prologue travis
+
 cpu_reset_func_start travis
 	/* ----------------------------------------------------
 	 * Disable speculative loads
@@ -38,6 +40,7 @@
 	/* model bug: not cleared on reset */
 	sysreg_bit_clear TRAVIS_IMP_CPUPWRCTLR_EL1, \
 		TRAVIS_IMP_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT
+	enable_mpmm
 cpu_reset_func_end travis
 
 func travis_core_pwr_dwn
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index 6415cb3..1e6a42e 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -209,19 +209,6 @@
  */
 func sve_context_save
 .arch_extension sve
-	/* Temporarily enable SVE */
-	mrs	x10, cptr_el3
-	orr	x11, x10, #CPTR_EZ_BIT
-	bic	x11, x11, #TFP_BIT
-	msr	cptr_el3, x11
-	isb
-
-	/* zcr_el3 */
-	mrs	x12, S3_6_C1_C2_0
-	mov	x13, #((SVE_VECTOR_LEN >> 7) - 1)
-	msr	S3_6_C1_C2_0, x13
-	isb
-
 	/* Predicate registers */
 	mov x13, #CTX_SIMD_PREDICATES
 	add	x9, x0, x13
@@ -237,11 +224,6 @@
 	mov x13, #CTX_SIMD_VECTORS
 	add	x9, x0, x13
 	sve_vectors_op  str, x9
-
-	/* Restore SVE enablement */
-	msr	S3_6_C1_C2_0, x12 /* zcr_el3 */
-	msr	cptr_el3, x10
-	isb
 .arch_extension nosve
 
 	/* Save FPSR, FPCR and FPEXC32 */
@@ -260,19 +242,6 @@
  */
 func sve_context_restore
 .arch_extension sve
-	/* Temporarily enable SVE for EL3 */
-	mrs	x10, cptr_el3
-	orr	x11, x10, #CPTR_EZ_BIT
-	bic	x11, x11, #TFP_BIT
-	msr	cptr_el3, x11
-	isb
-
-	/* zcr_el3 */
-	mrs	x12, S3_6_C1_C2_0
-	mov	x13, #((SVE_VECTOR_LEN >> 7) - 1)
-	msr	S3_6_C1_C2_0, x13
-	isb
-
 	/* Restore FFR register before predicates */
 	mov x13, #CTX_SIMD_FFR
 	add	x9, x0, x13
@@ -288,11 +257,6 @@
 	mov x13, #CTX_SIMD_VECTORS
 	add	x9, x0, x13
 	sve_vectors_op	ldr, x9
-
-	/* Restore SVE enablement */
-	msr	S3_6_C1_C2_0, x12 /* zcr_el3 */
-	msr	cptr_el3, x10
-	isb
 .arch_extension nosve
 
 	/* Restore FPSR, FPCR and FPEXC32 */
@@ -604,10 +568,7 @@
 
 	/* ----------------------------------------------------------
 	 * Restore CPTR_EL3.
-	 * ZCR is only restored if SVE is supported and enabled.
-	 * Synchronization is required before zcr_el3 is addressed.
-	 * ----------------------------------------------------------
-	 */
+	 * ---------------------------------------------------------- */
 
 	/* The address of the per_world context is stored in x9 */
 	get_per_world_context x9
@@ -616,13 +577,6 @@
 	msr	cptr_el3, x19
 
 #if IMAGE_BL31
-	ands	x19, x19, #CPTR_EZ_BIT
-	beq	sve_not_enabled
-
-	isb
-	msr	S3_6_C1_C2_0, x20 /* zcr_el3 */
-sve_not_enabled:
-
 	restore_mpam3_el3
 
 #endif /* IMAGE_BL31 */
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 2e6bce0..e28e1c3 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -200,6 +200,9 @@
 		debugv8p9_extended_bp_wp_enable(ctx);
 	}
 
+	if (is_feat_brbe_supported()) {
+		brbe_enable(ctx);
+	}
 
 }
 #endif /* ENABLE_RME */
@@ -658,13 +661,17 @@
 /*******************************************************************************
  * Enable architecture extensions for EL3 execution. This function only updates
  * registers in-place which are expected to either never change or be
- * overwritten by el3_exit.
+ * overwritten by el3_exit. Expects the core_pos of the current core as argument.
  ******************************************************************************/
 #if IMAGE_BL31
-void cm_manage_extensions_el3(void)
+void cm_manage_extensions_el3(unsigned int my_idx)
 {
+	if (is_feat_sve_supported()) {
+		sve_init_el3();
+	}
+
 	if (is_feat_amu_supported()) {
-		amu_init_el3();
+		amu_init_el3(my_idx);
 	}
 
 	if (is_feat_sme_supported()) {
@@ -800,6 +807,7 @@
 static void manage_extensions_nonsecure(cpu_context_t *ctx)
 {
 #if IMAGE_BL31
+	/* NOTE: registers are not context switched */
 	if (is_feat_amu_supported()) {
 		amu_enable(ctx);
 	}
@@ -1521,6 +1529,10 @@
 		write_el2_ctx_sxpoe(el2_sysregs_ctx, por_el2, read_por_el2());
 	}
 
+	if (is_feat_brbe_supported()) {
+		write_el2_ctx_brbe(el2_sysregs_ctx, brbcr_el2, read_brbcr_el2());
+	}
+
 	if (is_feat_s2pie_supported()) {
 		write_el2_ctx_s2pie(el2_sysregs_ctx, s2pir_el2, read_s2pir_el2());
 	}
@@ -1624,6 +1636,10 @@
 	if (is_feat_sctlr2_supported()) {
 		write_sctlr2_el2(read_el2_ctx_sctlr2(el2_sysregs_ctx, sctlr2_el2));
 	}
+
+	if (is_feat_brbe_supported()) {
+		write_brbcr_el2(read_el2_ctx_brbe(el2_sysregs_ctx, brbcr_el2));
+	}
 }
 #endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */
 
diff --git a/lib/el3_runtime/aarch64/cpu_data.S b/lib/el3_runtime/aarch64/cpu_data.S
index 313f882..02d9415 100644
--- a/lib/el3_runtime/aarch64/cpu_data.S
+++ b/lib/el3_runtime/aarch64/cpu_data.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,29 +7,9 @@
 #include <asm_macros.S>
 #include <lib/el3_runtime/cpu_data.h>
 
-.globl	init_cpu_data_ptr
 .globl	_cpu_data_by_index
 
 /* -----------------------------------------------------------------
- * void init_cpu_data_ptr(void)
- *
- * Initialise the TPIDR_EL3 register to refer to the cpu_data_t
- * for the calling CPU. This must be called before cm_get_cpu_data()
- *
- * This can be called without a valid stack. It assumes that
- * plat_my_core_pos() does not clobber register x10.
- * clobbers: x0, x1, x10
- * -----------------------------------------------------------------
- */
-func init_cpu_data_ptr
-	mov	x10, x30
-	bl	plat_my_core_pos
-	bl	_cpu_data_by_index
-	msr	tpidr_el3, x0
-	ret	x10
-endfunc init_cpu_data_ptr
-
-/* -----------------------------------------------------------------
  * cpu_data_t *_cpu_data_by_index(uint32_t cpu_index)
  *
  * Return the cpu_data structure for the CPU with given linear index
diff --git a/lib/extensions/amu/aarch32/amu.c b/lib/extensions/amu/aarch32/amu.c
index 351a552..6faef87 100644
--- a/lib/extensions/amu/aarch32/amu.c
+++ b/lib/extensions/amu/aarch32/amu.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,7 +8,6 @@
 #include <cdefs.h>
 #include <stdbool.h>
 
-#include "../amu_private.h"
 #include <arch.h>
 #include <arch_features.h>
 #include <arch_helpers.h>
@@ -18,51 +17,7 @@
 
 #include <plat/common/platform.h>
 
-struct amu_ctx {
-	uint64_t group0_cnts[AMU_GROUP0_MAX_COUNTERS];
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-	uint64_t group1_cnts[AMU_GROUP1_MAX_COUNTERS];
-#endif
-
-	uint16_t group0_enable;
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-	uint16_t group1_enable;
-#endif
-};
-
-static struct amu_ctx amu_ctxs_[PLATFORM_CORE_COUNT];
-
-CASSERT((sizeof(amu_ctxs_[0].group0_enable) * CHAR_BIT) <= AMU_GROUP0_MAX_COUNTERS,
-	amu_ctx_group0_enable_cannot_represent_all_group0_counters);
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-CASSERT((sizeof(amu_ctxs_[0].group1_enable) * CHAR_BIT) <= AMU_GROUP1_MAX_COUNTERS,
-	amu_ctx_group1_enable_cannot_represent_all_group1_counters);
-#endif
-
-static inline __unused void write_hcptr_tam(uint32_t value)
-{
-	write_hcptr((read_hcptr() & ~TAM_BIT) |
-		((value << TAM_SHIFT) & TAM_BIT));
-}
-
-static inline __unused void write_amcr_cg1rz(uint32_t value)
-{
-	write_amcr((read_amcr() & ~AMCR_CG1RZ_BIT) |
-		((value << AMCR_CG1RZ_SHIFT) & AMCR_CG1RZ_BIT));
-}
-
-static inline __unused uint32_t read_amcfgr_ncg(void)
-{
-	return (read_amcfgr() >> AMCFGR_NCG_SHIFT) &
-		AMCFGR_NCG_MASK;
-}
-
-static inline __unused uint32_t read_amcgcr_cg0nc(void)
-{
-	return (read_amcgcr() >> AMCGCR_CG0NC_SHIFT) &
-		AMCGCR_CG0NC_MASK;
-}
+amu_regs_t amu_ctx[PLATFORM_CORE_COUNT];
 
 static inline __unused uint32_t read_amcgcr_cg1nc(void)
 {
@@ -70,134 +25,31 @@
 		AMCGCR_CG1NC_MASK;
 }
 
-static inline __unused uint32_t read_amcntenset0_px(void)
-{
-	return (read_amcntenset0() >> AMCNTENSET0_Pn_SHIFT) &
-		AMCNTENSET0_Pn_MASK;
-}
-
-static inline __unused uint32_t read_amcntenset1_px(void)
-{
-	return (read_amcntenset1() >> AMCNTENSET1_Pn_SHIFT) &
-		AMCNTENSET1_Pn_MASK;
-}
-
-static inline __unused void write_amcntenset0_px(uint32_t px)
-{
-	uint32_t value = read_amcntenset0();
-
-	value &= ~AMCNTENSET0_Pn_MASK;
-	value |= (px << AMCNTENSET0_Pn_SHIFT) &
-		AMCNTENSET0_Pn_MASK;
-
-	write_amcntenset0(value);
-}
-
-static inline __unused void write_amcntenset1_px(uint32_t px)
-{
-	uint32_t value = read_amcntenset1();
-
-	value &= ~AMCNTENSET1_Pn_MASK;
-	value |= (px << AMCNTENSET1_Pn_SHIFT) &
-		AMCNTENSET1_Pn_MASK;
-
-	write_amcntenset1(value);
-}
-
-static inline __unused void write_amcntenclr0_px(uint32_t px)
-{
-	uint32_t value = read_amcntenclr0();
-
-	value &= ~AMCNTENCLR0_Pn_MASK;
-	value |= (px << AMCNTENCLR0_Pn_SHIFT) & AMCNTENCLR0_Pn_MASK;
-
-	write_amcntenclr0(value);
-}
-
-static inline __unused void write_amcntenclr1_px(uint32_t px)
-{
-	uint32_t value = read_amcntenclr1();
-
-	value &= ~AMCNTENCLR1_Pn_MASK;
-	value |= (px << AMCNTENCLR1_Pn_SHIFT) & AMCNTENCLR1_Pn_MASK;
-
-	write_amcntenclr1(value);
-}
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-static __unused bool amu_group1_supported(void)
-{
-	return read_amcfgr_ncg() > 0U;
-}
-#endif
-
 /*
  * Enable counters. This function is meant to be invoked by the context
  * management library before exiting from EL3.
  */
 void amu_enable(bool el2_unused)
 {
-	uint32_t amcfgr_ncg;		/* Number of counter groups */
-	uint32_t amcgcr_cg0nc;		/* Number of group 0 counters */
-
-	uint32_t amcntenset0_px = 0x0;	/* Group 0 enable mask */
-	uint32_t amcntenset1_px = 0x0;	/* Group 1 enable mask */
-
 	if (el2_unused) {
 		/*
 		 * HCPTR.TAM: Set to zero so any accesses to the Activity
 		 * Monitor registers do not trap to EL2.
 		 */
-		write_hcptr_tam(0U);
+		write_hcptr(read_hcptr() & ~TAM_BIT);
 	}
 
-	/*
-	 * Retrieve the number of architected counters. All of these counters
-	 * are enabled by default.
-	 */
+	/* Architecture is currently pinned to 4 */
+	assert((read_amcgcr() & AMCGCR_CG0NC_MASK) == CTX_AMU_GRP0_ALL);
 
-	amcgcr_cg0nc = read_amcgcr_cg0nc();
-	amcntenset0_px = (UINT32_C(1) << (amcgcr_cg0nc)) - 1U;
-
-	assert(amcgcr_cg0nc <= AMU_AMCGCR_CG0NC_MAX);
-
-	/*
-	 * The platform may opt to enable specific auxiliary counters. This can
-	 * be done via the common FCONF getter, or via the platform-implemented
-	 * function.
-	 */
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-	const struct amu_topology *topology;
-
-#if ENABLE_AMU_FCONF
-	topology = FCONF_GET_PROPERTY(amu, config, topology);
-#else
-	topology = plat_amu_topology();
-#endif /* ENABLE_AMU_FCONF */
-
-	if (topology != NULL) {
+	/* Enable all architected counters by default */
+	write_amcntenset0(AMCNTENSET0_Pn_MASK);
+	if (is_feat_amu_aux_supported()) {
 		unsigned int core_pos = plat_my_core_pos();
 
-		amcntenset1_el0_px = topology->cores[core_pos].enable;
-	} else {
-		ERROR("AMU: failed to generate AMU topology\n");
-	}
-#endif /* ENABLE_AMU_AUXILIARY_COUNTERS */
-
-	/*
-	 * Enable the requested counters.
-	 */
-
-	write_amcntenset0_px(amcntenset0_px);
-
-	amcfgr_ncg = read_amcfgr_ncg();
-	if (amcfgr_ncg > 0U) {
-		write_amcntenset1_px(amcntenset1_px);
-
-#if !ENABLE_AMU_AUXILIARY_COUNTERS
-		VERBOSE("AMU: auxiliary counters detected but support is disabled\n");
-#endif
+		/* Something went wrong if we're trying to write higher bits */
+		assert((get_amu_aux_enables(core_pos) & ~AMCNTENSET1_Pn_MASK) == 0);
+		write_amcntenset1(get_amu_aux_enables(core_pos));
 	}
 
 	/* Bail out if FEAT_AMUv1p1 features are not present. */
@@ -214,180 +66,177 @@
 	 * mapped view are unaffected.
 	 */
 	VERBOSE("AMU group 1 counter access restricted.\n");
-	write_amcr_cg1rz(1U);
+	write_amcr(read_amcr() | 1U);
 #else
-	write_amcr_cg1rz(0U);
+	write_amcr(0);
 #endif
 }
 
-/* Read the group 0 counter identified by the given `idx`. */
-static uint64_t amu_group0_cnt_read(unsigned int idx)
-{
-	assert(is_feat_amu_supported());
-	assert(idx < read_amcgcr_cg0nc());
-
-	return amu_group0_cnt_read_internal(idx);
-}
-
-/* Write the group 0 counter identified by the given `idx` with `val` */
-static void amu_group0_cnt_write(unsigned  int idx, uint64_t val)
-{
-	assert(is_feat_amu_supported());
-	assert(idx < read_amcgcr_cg0nc());
-
-	amu_group0_cnt_write_internal(idx, val);
-	isb();
-}
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-/* Read the group 1 counter identified by the given `idx` */
-static uint64_t amu_group1_cnt_read(unsigned  int idx)
-{
-	assert(is_feat_amu_supported());
-	assert(amu_group1_supported());
-	assert(idx < read_amcgcr_cg1nc());
-
-	return amu_group1_cnt_read_internal(idx);
-}
-
-/* Write the group 1 counter identified by the given `idx` with `val` */
-static void amu_group1_cnt_write(unsigned  int idx, uint64_t val)
-{
-	assert(is_feat_amu_supported());
-	assert(amu_group1_supported());
-	assert(idx < read_amcgcr_cg1nc());
-
-	amu_group1_cnt_write_internal(idx, val);
-	isb();
-}
-#endif
-
 static void *amu_context_save(const void *arg)
 {
-	uint32_t i;
-
-	unsigned int core_pos;
-	struct amu_ctx *ctx;
-
-	uint32_t amcgcr_cg0nc;	/* Number of group 0 counters */
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-	uint32_t amcfgr_ncg;	/* Number of counter groups */
-	uint32_t amcgcr_cg1nc;	/* Number of group 1 counters */
-#endif
-
 	if (!is_feat_amu_supported()) {
 		return (void *)0;
 	}
 
-	core_pos = plat_my_core_pos();
-	ctx = &amu_ctxs_[core_pos];
+	unsigned int core_pos = *(unsigned int *)arg;
+	amu_regs_t *ctx = &amu_ctx[core_pos];
 
-	amcgcr_cg0nc = read_amcgcr_cg0nc();
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-	amcfgr_ncg = read_amcfgr_ncg();
-	amcgcr_cg1nc = (amcfgr_ncg > 0U) ? read_amcgcr_cg1nc() : 0U;
-#endif
-
-	/*
-	 * Disable all AMU counters.
-	 */
-
-	ctx->group0_enable = read_amcntenset0_px();
-	write_amcntenclr0_px(ctx->group0_enable);
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-	if (amcfgr_ncg > 0U) {
-		ctx->group1_enable = read_amcntenset1_px();
-		write_amcntenclr1_px(ctx->group1_enable);
+	/* Disable all counters so we can write to them safely later */
+	write_amcntenclr0(AMCNTENCLR0_Pn_MASK);
+	if (is_feat_amu_aux_supported()) {
+		write_amcntenclr1(get_amu_aux_enables(core_pos));
 	}
-#endif
-
-	/*
-	 * Save the counters to the local context.
-	 */
 
 	isb(); /* Ensure counters have been stopped */
 
-	for (i = 0U; i < amcgcr_cg0nc; i++) {
-		ctx->group0_cnts[i] = amu_group0_cnt_read(i);
-	}
+	write_amu_grp0_ctx_reg(ctx, 0, read64_amevcntr00());
+	write_amu_grp0_ctx_reg(ctx, 1, read64_amevcntr01());
+	write_amu_grp0_ctx_reg(ctx, 2, read64_amevcntr02());
+	write_amu_grp0_ctx_reg(ctx, 3, read64_amevcntr03());
 
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-	for (i = 0U; i < amcgcr_cg1nc; i++) {
-		ctx->group1_cnts[i] = amu_group1_cnt_read(i);
+	if (is_feat_amu_aux_supported()) {
+		uint8_t num_counters = read_amcgcr_cg1nc();
+
+		switch (num_counters) {
+		case 0x10:
+			write_amu_grp1_ctx_reg(ctx, 0xf, read64_amevcntr1f());
+			__fallthrough;
+		case 0x0f:
+			write_amu_grp1_ctx_reg(ctx, 0xe, read64_amevcntr1e());
+			__fallthrough;
+		case 0x0e:
+			write_amu_grp1_ctx_reg(ctx, 0xd, read64_amevcntr1d());
+			__fallthrough;
+		case 0x0d:
+			write_amu_grp1_ctx_reg(ctx, 0xc, read64_amevcntr1c());
+			__fallthrough;
+		case 0x0c:
+			write_amu_grp1_ctx_reg(ctx, 0xb, read64_amevcntr1b());
+			__fallthrough;
+		case 0x0b:
+			write_amu_grp1_ctx_reg(ctx, 0xa, read64_amevcntr1a());
+			__fallthrough;
+		case 0x0a:
+			write_amu_grp1_ctx_reg(ctx, 0x9, read64_amevcntr19());
+			__fallthrough;
+		case 0x09:
+			write_amu_grp1_ctx_reg(ctx, 0x8, read64_amevcntr18());
+			__fallthrough;
+		case 0x08:
+			write_amu_grp1_ctx_reg(ctx, 0x7, read64_amevcntr17());
+			__fallthrough;
+		case 0x07:
+			write_amu_grp1_ctx_reg(ctx, 0x6, read64_amevcntr16());
+			__fallthrough;
+		case 0x06:
+			write_amu_grp1_ctx_reg(ctx, 0x5, read64_amevcntr15());
+			__fallthrough;
+		case 0x05:
+			write_amu_grp1_ctx_reg(ctx, 0x4, read64_amevcntr14());
+			__fallthrough;
+		case 0x04:
+			write_amu_grp1_ctx_reg(ctx, 0x3, read64_amevcntr13());
+			__fallthrough;
+		case 0x03:
+			write_amu_grp1_ctx_reg(ctx, 0x2, read64_amevcntr12());
+			__fallthrough;
+		case 0x02:
+			write_amu_grp1_ctx_reg(ctx, 0x1, read64_amevcntr11());
+			__fallthrough;
+		case 0x01:
+			write_amu_grp1_ctx_reg(ctx, 0x0, read64_amevcntr10());
+			__fallthrough;
+		case 0x00:
+			break;
+		default:
+			assert(0); /* something is wrong */
+		}
 	}
-#endif
 
 	return (void *)0;
 }
 
 static void *amu_context_restore(const void *arg)
 {
-	uint32_t i;
-
-	unsigned int core_pos;
-	struct amu_ctx *ctx;
-
-	uint32_t amcfgr_ncg;	/* Number of counter groups */
-	uint32_t amcgcr_cg0nc;	/* Number of group 0 counters */
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-	uint32_t amcgcr_cg1nc;	/* Number of group 1 counters */
-#endif
-
 	if (!is_feat_amu_supported()) {
 		return (void *)0;
 	}
 
-	core_pos = plat_my_core_pos();
-	ctx = &amu_ctxs_[core_pos];
+	unsigned int core_pos = *(unsigned int *)arg;
+	amu_regs_t *ctx = &amu_ctx[core_pos];
 
-	amcfgr_ncg = read_amcfgr_ncg();
-	amcgcr_cg0nc = read_amcgcr_cg0nc();
+	write64_amevcntr00(read_amu_grp0_ctx_reg(ctx, 0));
+	write64_amevcntr01(read_amu_grp0_ctx_reg(ctx, 1));
+	write64_amevcntr02(read_amu_grp0_ctx_reg(ctx, 2));
+	write64_amevcntr03(read_amu_grp0_ctx_reg(ctx, 3));
 
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-	amcgcr_cg1nc = (amcfgr_ncg > 0U) ? read_amcgcr_cg1nc() : 0U;
-#endif
+	if (is_feat_amu_aux_supported()) {
+		uint8_t num_counters = read_amcgcr_cg1nc();
 
-	/*
-	 * Sanity check that all counters were disabled when the context was
-	 * previously saved.
-	 */
-
-	assert(read_amcntenset0_px() == 0U);
-
-	if (amcfgr_ncg > 0U) {
-		assert(read_amcntenset1_px() == 0U);
+		switch (num_counters) {
+		case 0x10:
+			write64_amevcntr1f(read_amu_grp1_ctx_reg(ctx, 0xf));
+			__fallthrough;
+		case 0x0f:
+			write64_amevcntr1e(read_amu_grp1_ctx_reg(ctx, 0xe));
+			__fallthrough;
+		case 0x0e:
+			write64_amevcntr1d(read_amu_grp1_ctx_reg(ctx, 0xd));
+			__fallthrough;
+		case 0x0d:
+			write64_amevcntr1c(read_amu_grp1_ctx_reg(ctx, 0xc));
+			__fallthrough;
+		case 0x0c:
+			write64_amevcntr1b(read_amu_grp1_ctx_reg(ctx, 0xb));
+			__fallthrough;
+		case 0x0b:
+			write64_amevcntr1a(read_amu_grp1_ctx_reg(ctx, 0xa));
+			__fallthrough;
+		case 0x0a:
+			write64_amevcntr19(read_amu_grp1_ctx_reg(ctx, 0x9));
+			__fallthrough;
+		case 0x09:
+			write64_amevcntr18(read_amu_grp1_ctx_reg(ctx, 0x8));
+			__fallthrough;
+		case 0x08:
+			write64_amevcntr17(read_amu_grp1_ctx_reg(ctx, 0x7));
+			__fallthrough;
+		case 0x07:
+			write64_amevcntr16(read_amu_grp1_ctx_reg(ctx, 0x6));
+			__fallthrough;
+		case 0x06:
+			write64_amevcntr15(read_amu_grp1_ctx_reg(ctx, 0x5));
+			__fallthrough;
+		case 0x05:
+			write64_amevcntr14(read_amu_grp1_ctx_reg(ctx, 0x4));
+			__fallthrough;
+		case 0x04:
+			write64_amevcntr13(read_amu_grp1_ctx_reg(ctx, 0x3));
+			__fallthrough;
+		case 0x03:
+			write64_amevcntr12(read_amu_grp1_ctx_reg(ctx, 0x2));
+			__fallthrough;
+		case 0x02:
+			write64_amevcntr11(read_amu_grp1_ctx_reg(ctx, 0x1));
+			__fallthrough;
+		case 0x01:
+			write64_amevcntr10(read_amu_grp1_ctx_reg(ctx, 0x0));
+			__fallthrough;
+		case 0x00:
+			break;
+		default:
+			assert(0); /* something is wrong */
+		}
 	}
 
-	/*
-	 * Restore the counter values from the local context.
-	 */
 
-	for (i = 0U; i < amcgcr_cg0nc; i++) {
-		amu_group0_cnt_write(i, ctx->group0_cnts[i]);
+	/* now enable them again */
+	write_amcntenset0(AMCNTENSET0_Pn_MASK);
+	if (is_feat_amu_aux_supported()) {
+		write_amcntenset1(get_amu_aux_enables(core_pos));
 	}
 
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-	for (i = 0U; i < amcgcr_cg1nc; i++) {
-		amu_group1_cnt_write(i, ctx->group1_cnts[i]);
-	}
-#endif
-
-	/*
-	 * Re-enable counters that were disabled during context save.
-	 */
-
-	write_amcntenset0_px(ctx->group0_enable);
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-	if (amcfgr_ncg > 0U) {
-		write_amcntenset1_px(ctx->group1_enable);
-	}
-#endif
-
+	isb();
 	return (void *)0;
 }
 
diff --git a/lib/extensions/amu/aarch32/amu_helpers.S b/lib/extensions/amu/aarch32/amu_helpers.S
deleted file mode 100644
index 7090b2d..0000000
--- a/lib/extensions/amu/aarch32/amu_helpers.S
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <arch.h>
-#include <assert_macros.S>
-#include <asm_macros.S>
-
-	.globl	amu_group0_cnt_read_internal
-	.globl	amu_group0_cnt_write_internal
-	.globl	amu_group1_cnt_read_internal
-	.globl	amu_group1_cnt_write_internal
-	.globl	amu_group1_set_evtype_internal
-
-/*
- * uint64_t amu_group0_cnt_read_internal(int idx);
- *
- * Given `idx`, read the corresponding AMU counter
- * and return it in `r0` and `r1`.
- */
-func amu_group0_cnt_read_internal
-#if ENABLE_ASSERTIONS
-	/* `idx` should be between [0, 3] */
-	mov	r1, r0
-	lsr	r1, r1, #2
-	cmp	r1, #0
-	ASM_ASSERT(eq)
-#endif
-
-	/*
-	 * Given `idx` calculate address of ldcopr16/bx lr instruction pair
-	 * in the table below.
-	 */
-	adr	r1, 1f
-	lsl	r0, r0, #3	/* each ldcopr16/bx lr sequence is 8 bytes */
-	add	r1, r1, r0
-	bx	r1
-1:
-	ldcopr16	r0, r1, AMEVCNTR00	/* index 0 */
-	bx		lr
-	ldcopr16	r0, r1, AMEVCNTR01	/* index 1 */
-	bx 		lr
-	ldcopr16	r0, r1, AMEVCNTR02	/* index 2 */
-	bx 		lr
-	ldcopr16	r0, r1, AMEVCNTR03	/* index 3 */
-	bx 		lr
-endfunc amu_group0_cnt_read_internal
-
-/*
- * void amu_group0_cnt_write_internal(int idx, uint64_t val);
- *
- * Given `idx`, write `val` to the corresponding AMU counter.
- * `idx` is passed in `r0` and `val` is passed in `r2` and `r3`.
- * `r1` is used as a scratch register.
- */
-func amu_group0_cnt_write_internal
-#if ENABLE_ASSERTIONS
-	/* `idx` should be between [0, 3] */
-	mov	r1, r0
-	lsr	r1, r1, #2
-	cmp	r1, #0
-	ASM_ASSERT(eq)
-#endif
-
-	/*
-	 * Given `idx` calculate address of stcopr16/bx lr instruction pair
-	 * in the table below.
-	 */
-	adr	r1, 1f
-	lsl	r0, r0, #3	/* each stcopr16/bx lr sequence is 8 bytes */
-	add	r1, r1, r0
-	bx	r1
-
-1:
-	stcopr16	r2, r3, AMEVCNTR00	/* index 0 */
-	bx		lr
-	stcopr16	r2, r3, AMEVCNTR01	/* index 1 */
-	bx		lr
-	stcopr16	r2, r3, AMEVCNTR02	/* index 2 */
-	bx		lr
-	stcopr16	r2, r3, AMEVCNTR03	/* index 3 */
-	bx		lr
-endfunc amu_group0_cnt_write_internal
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-/*
- * uint64_t amu_group1_cnt_read_internal(int idx);
- *
- * Given `idx`, read the corresponding AMU counter
- * and return it in `r0` and `r1`.
- */
-func amu_group1_cnt_read_internal
-#if ENABLE_ASSERTIONS
-	/* `idx` should be between [0, 15] */
-	mov	r1, r0
-	lsr	r1, r1, #4
-	cmp	r1, #0
-	ASM_ASSERT(eq)
-#endif
-
-	/*
-	 * Given `idx` calculate address of ldcopr16/bx lr instruction pair
-	 * in the table below.
-	 */
-	adr	r1, 1f
-	lsl	r0, r0, #3	/* each ldcopr16/bx lr sequence is 8 bytes */
-	add	r1, r1, r0
-	bx	r1
-
-1:
-	ldcopr16	r0, r1, AMEVCNTR10	/* index 0 */
-	bx		lr
-	ldcopr16	r0, r1, AMEVCNTR11	/* index 1 */
-	bx		lr
-	ldcopr16	r0, r1, AMEVCNTR12	/* index 2 */
-	bx		lr
-	ldcopr16	r0, r1, AMEVCNTR13	/* index 3 */
-	bx		lr
-	ldcopr16	r0, r1, AMEVCNTR14	/* index 4 */
-	bx		lr
-	ldcopr16	r0, r1, AMEVCNTR15	/* index 5 */
-	bx		lr
-	ldcopr16	r0, r1, AMEVCNTR16	/* index 6 */
-	bx		lr
-	ldcopr16	r0, r1, AMEVCNTR17	/* index 7 */
-	bx		lr
-	ldcopr16	r0, r1, AMEVCNTR18	/* index 8 */
-	bx		lr
-	ldcopr16	r0, r1, AMEVCNTR19	/* index 9 */
-	bx		lr
-	ldcopr16	r0, r1, AMEVCNTR1A	/* index 10 */
-	bx		lr
-	ldcopr16	r0, r1, AMEVCNTR1B	/* index 11 */
-	bx		lr
-	ldcopr16	r0, r1, AMEVCNTR1C	/* index 12 */
-	bx		lr
-	ldcopr16	r0, r1, AMEVCNTR1D	/* index 13 */
-	bx		lr
-	ldcopr16	r0, r1, AMEVCNTR1E	/* index 14 */
-	bx		lr
-	ldcopr16	r0, r1, AMEVCNTR1F	/* index 15 */
-	bx		lr
-endfunc amu_group1_cnt_read_internal
-
-/*
- * void amu_group1_cnt_write_internal(int idx, uint64_t val);
- *
- * Given `idx`, write `val` to the corresponding AMU counter.
- * `idx` is passed in `r0` and `val` is passed in `r2` and `r3`.
- * `r1` is used as a scratch register.
- */
-func amu_group1_cnt_write_internal
-#if ENABLE_ASSERTIONS
-	/* `idx` should be between [0, 15] */
-	mov	r1, r0
-	lsr	r1, r1, #4
-	cmp	r1, #0
-	ASM_ASSERT(eq)
-#endif
-
-	/*
-	 * Given `idx` calculate address of ldcopr16/bx lr instruction pair
-	 * in the table below.
-	 */
-	adr	r1, 1f
-	lsl	r0, r0, #3	/* each stcopr16/bx lr sequence is 8 bytes */
-	add	r1, r1, r0
-	bx	r1
-
-1:
-	stcopr16	r2, r3, AMEVCNTR10	/* index 0 */
-	bx		lr
-	stcopr16	r2, r3, AMEVCNTR11	/* index 1 */
-	bx		lr
-	stcopr16	r2, r3, AMEVCNTR12	/* index 2 */
-	bx		lr
-	stcopr16	r2, r3, AMEVCNTR13	/* index 3 */
-	bx		lr
-	stcopr16	r2, r3, AMEVCNTR14	/* index 4 */
-	bx		lr
-	stcopr16	r2, r3, AMEVCNTR15	/* index 5 */
-	bx		lr
-	stcopr16	r2, r3, AMEVCNTR16	/* index 6 */
-	bx		lr
-	stcopr16	r2, r3, AMEVCNTR17	/* index 7 */
-	bx		lr
-	stcopr16	r2, r3, AMEVCNTR18	/* index 8 */
-	bx		lr
-	stcopr16	r2, r3, AMEVCNTR19	/* index 9 */
-	bx		lr
-	stcopr16	r2, r3, AMEVCNTR1A	/* index 10 */
-	bx		lr
-	stcopr16	r2, r3, AMEVCNTR1B	/* index 11 */
-	bx		lr
-	stcopr16	r2, r3, AMEVCNTR1C	/* index 12 */
-	bx		lr
-	stcopr16	r2, r3, AMEVCNTR1D	/* index 13 */
-	bx		lr
-	stcopr16	r2, r3, AMEVCNTR1E	/* index 14 */
-	bx		lr
-	stcopr16	r2, r3, AMEVCNTR1F	/* index 15 */
-	bx		lr
-endfunc amu_group1_cnt_write_internal
-
-/*
- * void amu_group1_set_evtype_internal(int idx, unsigned int val);
- *
- * Program the AMU event type register indexed by `idx`
- * with the value `val`.
- */
-func amu_group1_set_evtype_internal
-#if ENABLE_ASSERTIONS
-	/* `idx` should be between [0, 15] */
-	mov	r2, r0
-	lsr	r2, r2, #4
-	cmp	r2, #0
-	ASM_ASSERT(eq)
-
-	/* val should be between [0, 65535] */
-	mov	r2, r1
-	lsr	r2, r2, #16
-	cmp	r2, #0
-	ASM_ASSERT(eq)
-#endif
-
-	/*
-	 * Given `idx` calculate address of stcopr/bx lr instruction pair
-	 * in the table below.
-	 */
-	adr	r2, 1f
-	lsl	r0, r0, #3	/* each stcopr/bx lr sequence is 8 bytes */
-	add	r2, r2, r0
-	bx	r2
-
-1:
-	stcopr	r1, AMEVTYPER10 /* index 0 */
-	bx	lr
-	stcopr	r1, AMEVTYPER11 /* index 1 */
-	bx	lr
-	stcopr	r1, AMEVTYPER12 /* index 2 */
-	bx	lr
-	stcopr	r1, AMEVTYPER13 /* index 3 */
-	bx	lr
-	stcopr	r1, AMEVTYPER14 /* index 4 */
-	bx	lr
-	stcopr	r1, AMEVTYPER15 /* index 5 */
-	bx	lr
-	stcopr	r1, AMEVTYPER16 /* index 6 */
-	bx	lr
-	stcopr	r1, AMEVTYPER17 /* index 7 */
-	bx	lr
-	stcopr	r1, AMEVTYPER18 /* index 8 */
-	bx	lr
-	stcopr	r1, AMEVTYPER19 /* index 9 */
-	bx	lr
-	stcopr	r1, AMEVTYPER1A /* index 10 */
-	bx	lr
-	stcopr	r1, AMEVTYPER1B /* index 11 */
-	bx	lr
-	stcopr	r1, AMEVTYPER1C /* index 12 */
-	bx	lr
-	stcopr	r1, AMEVTYPER1D /* index 13 */
-	bx	lr
-	stcopr	r1, AMEVTYPER1E /* index 14 */
-	bx	lr
-	stcopr	r1, AMEVTYPER1F /* index 15 */
-	bx	lr
-endfunc amu_group1_set_evtype_internal
-#endif
diff --git a/lib/extensions/amu/aarch64/amu.c b/lib/extensions/amu/aarch64/amu.c
index cb9a0f2..5f23c07 100644
--- a/lib/extensions/amu/aarch64/amu.c
+++ b/lib/extensions/amu/aarch64/amu.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,183 +10,37 @@
 #include <stdbool.h>
 #include <stdint.h>
 
-#include "../amu_private.h"
 #include <arch.h>
 #include <arch_features.h>
 #include <arch_helpers.h>
 #include <common/debug.h>
 #include <lib/el3_runtime/pubsub_events.h>
 #include <lib/extensions/amu.h>
+#include <lib/utils_def.h>
+#include <platform_def.h>
 
-#include <plat/common/platform.h>
+amu_regs_t amu_ctx[PLATFORM_CORE_COUNT];
 
-#if ENABLE_AMU_FCONF
-#	include <lib/fconf/fconf.h>
-#	include <lib/fconf/fconf_amu_getter.h>
-#endif
-
-#if ENABLE_MPMM
-#	include <lib/mpmm/mpmm.h>
-#endif
-
-struct amu_ctx {
-	uint64_t group0_cnts[AMU_GROUP0_MAX_COUNTERS];
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-	uint64_t group1_cnts[AMU_GROUP1_MAX_COUNTERS];
-#endif
-
-	/* Architected event counter 1 does not have an offset register */
-	uint64_t group0_voffsets[AMU_GROUP0_MAX_COUNTERS - 1U];
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-	uint64_t group1_voffsets[AMU_GROUP1_MAX_COUNTERS];
-#endif
-
-	uint16_t group0_enable;
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-	uint16_t group1_enable;
-#endif
-};
-
-static struct amu_ctx amu_ctxs_[PLATFORM_CORE_COUNT];
-
-CASSERT((sizeof(amu_ctxs_[0].group0_enable) * CHAR_BIT) <= AMU_GROUP0_MAX_COUNTERS,
-	amu_ctx_group0_enable_cannot_represent_all_group0_counters);
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-CASSERT((sizeof(amu_ctxs_[0].group1_enable) * CHAR_BIT) <= AMU_GROUP1_MAX_COUNTERS,
-	amu_ctx_group1_enable_cannot_represent_all_group1_counters);
-#endif
-
-static inline __unused uint64_t read_hcr_el2_amvoffen(void)
-{
-	return (read_hcr_el2() & HCR_AMVOFFEN_BIT) >>
-		HCR_AMVOFFEN_SHIFT;
-}
-
-static inline __unused void write_cptr_el2_tam(uint64_t value)
-{
-	write_cptr_el2((read_cptr_el2() & ~CPTR_EL2_TAM_BIT) |
-		((value << CPTR_EL2_TAM_SHIFT) & CPTR_EL2_TAM_BIT));
-}
-
-static inline __unused void ctx_write_scr_el3_amvoffen(cpu_context_t *ctx, uint64_t amvoffen)
-{
-	uint64_t value = read_ctx_reg(get_el3state_ctx(ctx), CTX_SCR_EL3);
-
-	value &= ~SCR_AMVOFFEN_BIT;
-	value |= (amvoffen << SCR_AMVOFFEN_SHIFT) & SCR_AMVOFFEN_BIT;
-
-	write_ctx_reg(get_el3state_ctx(ctx), CTX_SCR_EL3, value);
-}
-
-static inline __unused void write_hcr_el2_amvoffen(uint64_t value)
-{
-	write_hcr_el2((read_hcr_el2() & ~HCR_AMVOFFEN_BIT) |
-		((value << HCR_AMVOFFEN_SHIFT) & HCR_AMVOFFEN_BIT));
-}
-
-static inline __unused void write_amcr_el0_cg1rz(uint64_t value)
-{
-	write_amcr_el0((read_amcr_el0() & ~AMCR_CG1RZ_BIT) |
-		((value << AMCR_CG1RZ_SHIFT) & AMCR_CG1RZ_BIT));
-}
-
-static inline __unused uint64_t read_amcfgr_el0_ncg(void)
-{
-	return (read_amcfgr_el0() >> AMCFGR_EL0_NCG_SHIFT) &
-		AMCFGR_EL0_NCG_MASK;
-}
-
-static inline __unused uint64_t read_amcgcr_el0_cg0nc(void)
-{
-	return (read_amcgcr_el0() >> AMCGCR_EL0_CG0NC_SHIFT) &
-		AMCGCR_EL0_CG0NC_MASK;
-}
-
-static inline __unused uint64_t read_amcg1idr_el0_voff(void)
-{
-	return (read_amcg1idr_el0() >> AMCG1IDR_VOFF_SHIFT) &
-		AMCG1IDR_VOFF_MASK;
-}
-
-static inline __unused uint64_t read_amcgcr_el0_cg1nc(void)
+static inline uint8_t read_amcgcr_el0_cg1nc(void)
 {
 	return (read_amcgcr_el0() >> AMCGCR_EL0_CG1NC_SHIFT) &
 		AMCGCR_EL0_CG1NC_MASK;
 }
 
-static inline __unused uint64_t read_amcntenset0_el0_px(void)
-{
-	return (read_amcntenset0_el0() >> AMCNTENSET0_EL0_Pn_SHIFT) &
-		AMCNTENSET0_EL0_Pn_MASK;
-}
-
-static inline __unused uint64_t read_amcntenset1_el0_px(void)
-{
-	return (read_amcntenset1_el0() >> AMCNTENSET1_EL0_Pn_SHIFT) &
-		AMCNTENSET1_EL0_Pn_MASK;
-}
-
-static inline __unused void write_amcntenset0_el0_px(uint64_t px)
-{
-	uint64_t value = read_amcntenset0_el0();
-
-	value &= ~AMCNTENSET0_EL0_Pn_MASK;
-	value |= (px << AMCNTENSET0_EL0_Pn_SHIFT) & AMCNTENSET0_EL0_Pn_MASK;
-
-	write_amcntenset0_el0(value);
-}
-
-static inline __unused void write_amcntenset1_el0_px(uint64_t px)
-{
-	uint64_t value = read_amcntenset1_el0();
-
-	value &= ~AMCNTENSET1_EL0_Pn_MASK;
-	value |= (px << AMCNTENSET1_EL0_Pn_SHIFT) & AMCNTENSET1_EL0_Pn_MASK;
-
-	write_amcntenset1_el0(value);
-}
-
-static inline __unused void write_amcntenclr0_el0_px(uint64_t px)
-{
-	uint64_t value = read_amcntenclr0_el0();
-
-	value &= ~AMCNTENCLR0_EL0_Pn_MASK;
-	value |= (px << AMCNTENCLR0_EL0_Pn_SHIFT) & AMCNTENCLR0_EL0_Pn_MASK;
-
-	write_amcntenclr0_el0(value);
-}
-
-static inline __unused void write_amcntenclr1_el0_px(uint64_t px)
-{
-	uint64_t value = read_amcntenclr1_el0();
-
-	value &= ~AMCNTENCLR1_EL0_Pn_MASK;
-	value |= (px << AMCNTENCLR1_EL0_Pn_SHIFT) & AMCNTENCLR1_EL0_Pn_MASK;
-
-	write_amcntenclr1_el0(value);
-}
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-static __unused bool amu_group1_supported(void)
-{
-	return read_amcfgr_el0_ncg() > 0U;
-}
-#endif
-
-/*
- * Enable counters. This function is meant to be invoked by the context
- * management library before exiting from EL3.
- */
 void amu_enable(cpu_context_t *ctx)
 {
 	/* Initialize FEAT_AMUv1p1 features if present. */
 	if (is_feat_amuv1p1_supported()) {
+		el3_state_t *state = get_el3state_ctx(ctx);
+		u_register_t reg;
+
 		/*
 		 * Set SCR_EL3.AMVOFFEN to one so that accesses to virtual
 		 * offset registers at EL2 do not trap to EL3
 		 */
-		ctx_write_scr_el3_amvoffen(ctx, 1U);
+		reg = read_ctx_reg(state, CTX_SCR_EL3);
+		reg |= SCR_AMVOFFEN_BIT;
+		write_ctx_reg(state, CTX_SCR_EL3, reg);
 	}
 }
 
@@ -202,46 +56,18 @@
 	per_world_ctx->ctx_cptr_el3 = cptr_el3;
 }
 
-void amu_init_el3(void)
+void amu_init_el3(unsigned int core_pos)
 {
-	uint64_t group0_impl_ctr = read_amcgcr_el0_cg0nc();
-	uint64_t group0_en_mask = (1 << (group0_impl_ctr)) - 1U;
-	uint64_t num_ctr_groups = read_amcfgr_el0_ncg();
+	/* architecture is currently pinned to 4 */
+	assert((read_amcgcr_el0() & AMCGCR_EL0_CG0NC_MASK) == CTX_AMU_GRP0_ALL);
 
 	/* Enable all architected counters by default */
-	write_amcntenset0_el0_px(group0_en_mask);
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-	if (num_ctr_groups > 0U) {
-		uint64_t amcntenset1_el0_px = 0x0; /* Group 1 enable mask */
-		const struct amu_topology *topology;
-
-		/*
-		 * The platform may opt to enable specific auxiliary counters.
-		 * This can be done via the common FCONF getter, or via the
-		 * platform-implemented function.
-		 */
-#if ENABLE_AMU_FCONF
-		topology = FCONF_GET_PROPERTY(amu, config, topology);
-#else
-		topology = plat_amu_topology();
-#endif /* ENABLE_AMU_FCONF */
-
-		if (topology != NULL) {
-			unsigned int core_pos = plat_my_core_pos();
-
-			amcntenset1_el0_px = topology->cores[core_pos].enable;
-		} else {
-			ERROR("AMU: failed to generate AMU topology\n");
-		}
-
-		write_amcntenset1_el0_px(amcntenset1_el0_px);
+	write_amcntenset0_el0(AMCNTENSET0_EL0_Pn_MASK);
+	if (is_feat_amu_aux_supported()) {
+		/* something went wrong if we're trying to write higher bits */
+		assert((get_amu_aux_enables(core_pos) & ~AMCNTENSET1_EL0_Pn_MASK) == 0);
+		write_amcntenset1_el0(get_amu_aux_enables(core_pos));
 	}
-#else /* ENABLE_AMU_AUXILIARY_COUNTERS */
-	if (num_ctr_groups > 0U) {
-		VERBOSE("AMU: auxiliary counters detected but support is disabled\n");
-	}
-#endif /* ENABLE_AMU_AUXILIARY_COUNTERS */
 
 	if (is_feat_amuv1p1_supported()) {
 #if AMU_RESTRICT_COUNTERS
@@ -253,15 +79,12 @@
 		 * zero. Reads from the memory mapped view are unaffected.
 		 */
 		VERBOSE("AMU group 1 counter access restricted.\n");
-		write_amcr_el0_cg1rz(1U);
+		write_amcr_el0(AMCR_CG1RZ_BIT);
 #else
-		write_amcr_el0_cg1rz(0U);
+		/* HDBG = 0 in both cases */
+		write_amcr_el0(0);
 #endif
 	}
-
-#if ENABLE_MPMM
-	mpmm_enable();
-#endif
 }
 
 void amu_init_el2_unused(void)
@@ -270,230 +93,93 @@
 	 * CPTR_EL2.TAM: Set to zero so any accesses to the Activity Monitor
 	 *  registers do not trap to EL2.
 	 */
-	write_cptr_el2_tam(0U);
+	write_cptr_el2(read_cptr_el2() & ~CPTR_EL2_TAM_BIT);
 
-	/* Initialize FEAT_AMUv1p1 features if present. */
 	if (is_feat_amuv1p1_supported()) {
-		/* Make sure virtual offsets are disabled if EL2 not used. */
-		write_hcr_el2_amvoffen(0U);
+		/* Make sure virtual offsets are disabled */
+		write_hcr_el2(read_hcr_el2() & ~HCR_AMVOFFEN_BIT);
 	}
 }
 
-/* Read the group 0 counter identified by the given `idx`. */
-static uint64_t amu_group0_cnt_read(unsigned int idx)
-{
-	assert(is_feat_amu_supported());
-	assert(idx < read_amcgcr_el0_cg0nc());
-
-	return amu_group0_cnt_read_internal(idx);
-}
-
-/* Write the group 0 counter identified by the given `idx` with `val` */
-static void amu_group0_cnt_write(unsigned  int idx, uint64_t val)
-{
-	assert(is_feat_amu_supported());
-	assert(idx < read_amcgcr_el0_cg0nc());
-
-	amu_group0_cnt_write_internal(idx, val);
-	isb();
-}
-
-/*
- * Unlike with auxiliary counters, we cannot detect at runtime whether an
- * architected counter supports a virtual offset. These are instead fixed
- * according to FEAT_AMUv1p1, but this switch will need to be updated if later
- * revisions of FEAT_AMU add additional architected counters.
- */
-static bool amu_group0_voffset_supported(uint64_t idx)
-{
-	switch (idx) {
-	case 0U:
-	case 2U:
-	case 3U:
-		return true;
-
-	case 1U:
-		return false;
-
-	default:
-		ERROR("AMU: can't set up virtual offset for unknown "
-		      "architected counter %" PRIu64 "!\n", idx);
-
-		panic();
-	}
-}
-
-/*
- * Read the group 0 offset register for a given index. Index must be 0, 2,
- * or 3, the register for 1 does not exist.
- *
- * Using this function requires FEAT_AMUv1p1 support.
- */
-static uint64_t amu_group0_voffset_read(unsigned int idx)
-{
-	assert(is_feat_amuv1p1_supported());
-	assert(idx < read_amcgcr_el0_cg0nc());
-	assert(idx != 1U);
-
-	return amu_group0_voffset_read_internal(idx);
-}
-
-/*
- * Write the group 0 offset register for a given index. Index must be 0, 2, or
- * 3, the register for 1 does not exist.
- *
- * Using this function requires FEAT_AMUv1p1 support.
- */
-static void amu_group0_voffset_write(unsigned int idx, uint64_t val)
-{
-	assert(is_feat_amuv1p1_supported());
-	assert(idx < read_amcgcr_el0_cg0nc());
-	assert(idx != 1U);
-
-	amu_group0_voffset_write_internal(idx, val);
-	isb();
-}
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-/* Read the group 1 counter identified by the given `idx` */
-static uint64_t amu_group1_cnt_read(unsigned int idx)
-{
-	assert(is_feat_amu_supported());
-	assert(amu_group1_supported());
-	assert(idx < read_amcgcr_el0_cg1nc());
-
-	return amu_group1_cnt_read_internal(idx);
-}
-
-/* Write the group 1 counter identified by the given `idx` with `val` */
-static void amu_group1_cnt_write(unsigned int idx, uint64_t val)
-{
-	assert(is_feat_amu_supported());
-	assert(amu_group1_supported());
-	assert(idx < read_amcgcr_el0_cg1nc());
-
-	amu_group1_cnt_write_internal(idx, val);
-	isb();
-}
-
-/*
- * Read the group 1 offset register for a given index.
- *
- * Using this function requires FEAT_AMUv1p1 support.
- */
-static uint64_t amu_group1_voffset_read(unsigned int idx)
-{
-	assert(is_feat_amuv1p1_supported());
-	assert(amu_group1_supported());
-	assert(idx < read_amcgcr_el0_cg1nc());
-	assert((read_amcg1idr_el0_voff() & (UINT64_C(1) << idx)) != 0U);
-
-	return amu_group1_voffset_read_internal(idx);
-}
-
-/*
- * Write the group 1 offset register for a given index.
- *
- * Using this function requires FEAT_AMUv1p1 support.
- */
-static void amu_group1_voffset_write(unsigned int idx, uint64_t val)
-{
-	assert(is_feat_amuv1p1_supported());
-	assert(amu_group1_supported());
-	assert(idx < read_amcgcr_el0_cg1nc());
-	assert((read_amcg1idr_el0_voff() & (UINT64_C(1) << idx)) != 0U);
-
-	amu_group1_voffset_write_internal(idx, val);
-	isb();
-}
-#endif
-
 static void *amu_context_save(const void *arg)
 {
-	uint64_t i, j;
-
-	unsigned int core_pos;
-	struct amu_ctx *ctx;
-
-	uint64_t hcr_el2_amvoffen = 0;	/* AMU virtual offsets enabled */
-	uint64_t amcgcr_el0_cg0nc;	/* Number of group 0 counters */
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-	uint64_t amcg1idr_el0_voff;	/* Auxiliary counters with virtual offsets */
-	uint64_t amcfgr_el0_ncg;	/* Number of counter groups */
-	uint64_t amcgcr_el0_cg1nc;	/* Number of group 1 counters */
-#endif
-
 	if (!is_feat_amu_supported()) {
 		return (void *)0;
 	}
 
-	core_pos = plat_my_core_pos();
-	ctx = &amu_ctxs_[core_pos];
+	unsigned int core_pos = *(unsigned int *)arg;
+	amu_regs_t *ctx = &amu_ctx[core_pos];
 
-	amcgcr_el0_cg0nc = read_amcgcr_el0_cg0nc();
-	if (is_feat_amuv1p1_supported()) {
-		hcr_el2_amvoffen = read_hcr_el2_amvoffen();
+	/* disable all counters so we can write them safely later */
+	write_amcntenclr0_el0(AMCNTENCLR0_EL0_Pn_MASK);
+	if (is_feat_amu_aux_supported()) {
+		write_amcntenclr1_el0(get_amu_aux_enables(core_pos));
 	}
 
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-	amcfgr_el0_ncg = read_amcfgr_el0_ncg();
-	amcgcr_el0_cg1nc = (amcfgr_el0_ncg > 0U) ? read_amcgcr_el0_cg1nc() : 0U;
-	amcg1idr_el0_voff = (hcr_el2_amvoffen != 0U) ? read_amcg1idr_el0_voff() : 0U;
-#endif
+	isb();
 
-	/*
-	 * Disable all AMU counters.
-	 */
+	write_amu_grp0_ctx_reg(ctx, 0, read_amevcntr00_el0());
+	write_amu_grp0_ctx_reg(ctx, 1, read_amevcntr01_el0());
+	write_amu_grp0_ctx_reg(ctx, 2, read_amevcntr02_el0());
+	write_amu_grp0_ctx_reg(ctx, 3, read_amevcntr03_el0());
 
-	ctx->group0_enable = read_amcntenset0_el0_px();
-	write_amcntenclr0_el0_px(ctx->group0_enable);
+	if (is_feat_amu_aux_supported()) {
+		uint8_t num_counters = read_amcgcr_el0_cg1nc();
 
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-	if (amcfgr_el0_ncg > 0U) {
-		ctx->group1_enable = read_amcntenset1_el0_px();
-		write_amcntenclr1_el0_px(ctx->group1_enable);
-	}
-#endif
-
-	/*
-	 * Save the counters to the local context.
-	 */
-
-	isb(); /* Ensure counters have been stopped */
-
-	for (i = 0U; i < amcgcr_el0_cg0nc; i++) {
-		ctx->group0_cnts[i] = amu_group0_cnt_read(i);
-	}
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-	for (i = 0U; i < amcgcr_el0_cg1nc; i++) {
-		ctx->group1_cnts[i] = amu_group1_cnt_read(i);
-	}
-#endif
-
-	/*
-	 * Save virtual offsets for counters that offer them.
-	 */
-
-	if (hcr_el2_amvoffen != 0U) {
-		for (i = 0U, j = 0U; i < amcgcr_el0_cg0nc; i++) {
-			if (!amu_group0_voffset_supported(i)) {
-				continue; /* No virtual offset */
-			}
-
-			ctx->group0_voffsets[j++] = amu_group0_voffset_read(i);
+		switch (num_counters) {
+		case 0x10:
+			write_amu_grp1_ctx_reg(ctx, 0xf, read_amevcntr1f_el0());
+			__fallthrough;
+		case 0x0f:
+			write_amu_grp1_ctx_reg(ctx, 0xe, read_amevcntr1e_el0());
+			__fallthrough;
+		case 0x0e:
+			write_amu_grp1_ctx_reg(ctx, 0xd, read_amevcntr1d_el0());
+			__fallthrough;
+		case 0x0d:
+			write_amu_grp1_ctx_reg(ctx, 0xc, read_amevcntr1c_el0());
+			__fallthrough;
+		case 0x0c:
+			write_amu_grp1_ctx_reg(ctx, 0xb, read_amevcntr1b_el0());
+			__fallthrough;
+		case 0x0b:
+			write_amu_grp1_ctx_reg(ctx, 0xa, read_amevcntr1a_el0());
+			__fallthrough;
+		case 0x0a:
+			write_amu_grp1_ctx_reg(ctx, 0x9, read_amevcntr19_el0());
+			__fallthrough;
+		case 0x09:
+			write_amu_grp1_ctx_reg(ctx, 0x8, read_amevcntr18_el0());
+			__fallthrough;
+		case 0x08:
+			write_amu_grp1_ctx_reg(ctx, 0x7, read_amevcntr17_el0());
+			__fallthrough;
+		case 0x07:
+			write_amu_grp1_ctx_reg(ctx, 0x6, read_amevcntr16_el0());
+			__fallthrough;
+		case 0x06:
+			write_amu_grp1_ctx_reg(ctx, 0x5, read_amevcntr15_el0());
+			__fallthrough;
+		case 0x05:
+			write_amu_grp1_ctx_reg(ctx, 0x4, read_amevcntr14_el0());
+			__fallthrough;
+		case 0x04:
+			write_amu_grp1_ctx_reg(ctx, 0x3, read_amevcntr13_el0());
+			__fallthrough;
+		case 0x03:
+			write_amu_grp1_ctx_reg(ctx, 0x2, read_amevcntr12_el0());
+			__fallthrough;
+		case 0x02:
+			write_amu_grp1_ctx_reg(ctx, 0x1, read_amevcntr11_el0());
+			__fallthrough;
+		case 0x01:
+			write_amu_grp1_ctx_reg(ctx, 0x0, read_amevcntr10_el0());
+			__fallthrough;
+		case 0x00:
+			break;
+		default:
+			assert(0); /* something is wrong */
 		}
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-		for (i = 0U, j = 0U; i < amcgcr_el0_cg1nc; i++) {
-			if ((amcg1idr_el0_voff >> i) & 1U) {
-				continue; /* No virtual offset */
-			}
-
-			ctx->group1_voffsets[j++] = amu_group1_voffset_read(i);
-		}
-#endif
 	}
 
 	return (void *)0;
@@ -501,94 +187,85 @@
 
 static void *amu_context_restore(const void *arg)
 {
-	uint64_t i, j;
-
-	unsigned int core_pos;
-	struct amu_ctx *ctx;
-
-	uint64_t hcr_el2_amvoffen = 0;	/* AMU virtual offsets enabled */
-
-	uint64_t amcgcr_el0_cg0nc;	/* Number of group 0 counters */
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-	uint64_t amcfgr_el0_ncg;	/* Number of counter groups */
-	uint64_t amcgcr_el0_cg1nc;	/* Number of group 1 counters */
-	uint64_t amcg1idr_el0_voff;	/* Auxiliary counters with virtual offsets */
-#endif
-
 	if (!is_feat_amu_supported()) {
 		return (void *)0;
 	}
 
-	core_pos = plat_my_core_pos();
-	ctx = &amu_ctxs_[core_pos];
+	unsigned int core_pos = *(unsigned int *)arg;
+	amu_regs_t *ctx = &amu_ctx[core_pos];
 
-	amcgcr_el0_cg0nc = read_amcgcr_el0_cg0nc();
+	write_amevcntr00_el0(read_amu_grp0_ctx_reg(ctx, 0));
+	write_amevcntr01_el0(read_amu_grp0_ctx_reg(ctx, 1));
+	write_amevcntr02_el0(read_amu_grp0_ctx_reg(ctx, 2));
+	write_amevcntr03_el0(read_amu_grp0_ctx_reg(ctx, 3));
 
-	if (is_feat_amuv1p1_supported()) {
-		hcr_el2_amvoffen = read_hcr_el2_amvoffen();
-	}
+	if (is_feat_amu_aux_supported()) {
+		uint8_t num_counters = read_amcgcr_el0_cg1nc();
 
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-	amcfgr_el0_ncg = read_amcfgr_el0_ncg();
-	amcgcr_el0_cg1nc = (amcfgr_el0_ncg > 0U) ? read_amcgcr_el0_cg1nc() : 0U;
-	amcg1idr_el0_voff = (hcr_el2_amvoffen != 0U) ? read_amcg1idr_el0_voff() : 0U;
-#endif
-
-	/*
-	 * Restore the counter values from the local context.
-	 */
-
-	for (i = 0U; i < amcgcr_el0_cg0nc; i++) {
-		amu_group0_cnt_write(i, ctx->group0_cnts[i]);
-	}
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-	for (i = 0U; i < amcgcr_el0_cg1nc; i++) {
-		amu_group1_cnt_write(i, ctx->group1_cnts[i]);
-	}
-#endif
-
-	/*
-	 * Restore virtual offsets for counters that offer them.
-	 */
-
-	if (hcr_el2_amvoffen != 0U) {
-		for (i = 0U, j = 0U; i < amcgcr_el0_cg0nc; i++) {
-			if (!amu_group0_voffset_supported(i)) {
-				continue; /* No virtual offset */
-			}
-
-			amu_group0_voffset_write(i, ctx->group0_voffsets[j++]);
+		switch (num_counters) {
+		case 0x10:
+			write_amevcntr1f_el0(read_amu_grp1_ctx_reg(ctx, 0xf));
+			__fallthrough;
+		case 0x0f:
+			write_amevcntr1e_el0(read_amu_grp1_ctx_reg(ctx, 0xe));
+			__fallthrough;
+		case 0x0e:
+			write_amevcntr1d_el0(read_amu_grp1_ctx_reg(ctx, 0xd));
+			__fallthrough;
+		case 0x0d:
+			write_amevcntr1c_el0(read_amu_grp1_ctx_reg(ctx, 0xc));
+			__fallthrough;
+		case 0x0c:
+			write_amevcntr1b_el0(read_amu_grp1_ctx_reg(ctx, 0xb));
+			__fallthrough;
+		case 0x0b:
+			write_amevcntr1a_el0(read_amu_grp1_ctx_reg(ctx, 0xa));
+			__fallthrough;
+		case 0x0a:
+			write_amevcntr19_el0(read_amu_grp1_ctx_reg(ctx, 0x9));
+			__fallthrough;
+		case 0x09:
+			write_amevcntr18_el0(read_amu_grp1_ctx_reg(ctx, 0x8));
+			__fallthrough;
+		case 0x08:
+			write_amevcntr17_el0(read_amu_grp1_ctx_reg(ctx, 0x7));
+			__fallthrough;
+		case 0x07:
+			write_amevcntr16_el0(read_amu_grp1_ctx_reg(ctx, 0x6));
+			__fallthrough;
+		case 0x06:
+			write_amevcntr15_el0(read_amu_grp1_ctx_reg(ctx, 0x5));
+			__fallthrough;
+		case 0x05:
+			write_amevcntr14_el0(read_amu_grp1_ctx_reg(ctx, 0x4));
+			__fallthrough;
+		case 0x04:
+			write_amevcntr13_el0(read_amu_grp1_ctx_reg(ctx, 0x3));
+			__fallthrough;
+		case 0x03:
+			write_amevcntr12_el0(read_amu_grp1_ctx_reg(ctx, 0x2));
+			__fallthrough;
+		case 0x02:
+			write_amevcntr11_el0(read_amu_grp1_ctx_reg(ctx, 0x1));
+			__fallthrough;
+		case 0x01:
+			write_amevcntr10_el0(read_amu_grp1_ctx_reg(ctx, 0x0));
+			__fallthrough;
+		case 0x00:
+			break;
+		default:
+			assert(0); /* something is wrong */
 		}
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-		for (i = 0U, j = 0U; i < amcgcr_el0_cg1nc; i++) {
-			if ((amcg1idr_el0_voff >> i) & 1U) {
-				continue; /* No virtual offset */
-			}
-
-			amu_group1_voffset_write(i, ctx->group1_voffsets[j++]);
-		}
-#endif
 	}
 
-	/*
-	 * Re-enable counters that were disabled during context save.
-	 */
 
-	write_amcntenset0_el0_px(ctx->group0_enable);
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-	if (amcfgr_el0_ncg > 0) {
-		write_amcntenset1_el0_px(ctx->group1_enable);
+	/* now enable them again */
+	write_amcntenset0_el0(AMCNTENSET0_EL0_Pn_MASK);
+	if (is_feat_amu_aux_supported()) {
+		write_amcntenset1_el0(get_amu_aux_enables(core_pos));
 	}
-#endif
 
-#if ENABLE_MPMM
-	mpmm_enable();
-#endif
-
+	isb();
 	return (void *)0;
 }
 
diff --git a/lib/extensions/amu/aarch64/amu_helpers.S b/lib/extensions/amu/aarch64/amu_helpers.S
deleted file mode 100644
index 95d4ad6..0000000
--- a/lib/extensions/amu/aarch64/amu_helpers.S
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <arch.h>
-#include <assert_macros.S>
-#include <asm_macros.S>
-
-	.globl	amu_group0_cnt_read_internal
-	.globl	amu_group0_cnt_write_internal
-	.globl	amu_group1_cnt_read_internal
-	.globl	amu_group1_cnt_write_internal
-	.globl	amu_group1_set_evtype_internal
-
-	/* FEAT_AMUv1p1 virtualisation offset register functions */
-	.globl	amu_group0_voffset_read_internal
-	.globl	amu_group0_voffset_write_internal
-	.globl	amu_group1_voffset_read_internal
-	.globl	amu_group1_voffset_write_internal
-
-/*
- * uint64_t amu_group0_cnt_read_internal(int idx);
- *
- * Given `idx`, read the corresponding AMU counter
- * and return it in `x0`.
- */
-func amu_group0_cnt_read_internal
-	adr	x1, 1f
-#if ENABLE_ASSERTIONS
-	/*
-	 * It can be dangerous to call this function with an
-	 * out of bounds index.  Ensure `idx` is valid.
-	 */
-	tst	x0, #~3
-	ASM_ASSERT(eq)
-#endif
-	/*
-	 * Given `idx` calculate address of mrs/ret instruction pair
-	 * in the table below.
-	 */
-	add	x1, x1, x0, lsl #3	/* each mrs/ret sequence is 8 bytes */
-#if ENABLE_BTI
-	add	x1, x1, x0, lsl #2	/* + "bti j" instruction */
-#endif
-	br	x1
-
-1:	read	AMEVCNTR00_EL0		/* index 0 */
-	read	AMEVCNTR01_EL0		/* index 1 */
-	read	AMEVCNTR02_EL0		/* index 2 */
-	read	AMEVCNTR03_EL0		/* index 3 */
-endfunc amu_group0_cnt_read_internal
-
-/*
- * void amu_group0_cnt_write_internal(int idx, uint64_t val);
- *
- * Given `idx`, write `val` to the corresponding AMU counter.
- */
-func amu_group0_cnt_write_internal
-	adr	x2, 1f
-#if ENABLE_ASSERTIONS
-	/*
-	 * It can be dangerous to call this function with an
-	 * out of bounds index.  Ensure `idx` is valid.
-	 */
-	tst	x0, #~3
-	ASM_ASSERT(eq)
-#endif
-	/*
-	 * Given `idx` calculate address of mrs/ret instruction pair
-	 * in the table below.
-	 */
-	add	x2, x2, x0, lsl #3	/* each msr/ret sequence is 8 bytes */
-#if ENABLE_BTI
-	add	x2, x2, x0, lsl #2	/* + "bti j" instruction */
-#endif
-	br	x2
-
-1:	write	AMEVCNTR00_EL0		/* index 0 */
-	write	AMEVCNTR01_EL0		/* index 1 */
-	write	AMEVCNTR02_EL0		/* index 2 */
-	write	AMEVCNTR03_EL0		/* index 3 */
-endfunc amu_group0_cnt_write_internal
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-/*
- * uint64_t amu_group1_cnt_read_internal(int idx);
- *
- * Given `idx`, read the corresponding AMU counter
- * and return it in `x0`.
- */
-func amu_group1_cnt_read_internal
-	adr	x1, 1f
-#if ENABLE_ASSERTIONS
-	/*
-	 * It can be dangerous to call this function with an
-	 * out of bounds index.  Ensure `idx` is valid.
-	 */
-	tst	x0, #~0xF
-	ASM_ASSERT(eq)
-#endif
-	/*
-	 * Given `idx` calculate address of mrs/ret instruction pair
-	 * in the table below.
-	 */
-	add	x1, x1, x0, lsl #3	/* each mrs/ret sequence is 8 bytes */
-#if ENABLE_BTI
-	add	x1, x1, x0, lsl #2	/* + "bti j" instruction */
-#endif
-	br	x1
-
-1:	read	AMEVCNTR10_EL0		/* index 0 */
-	read	AMEVCNTR11_EL0		/* index 1 */
-	read	AMEVCNTR12_EL0		/* index 2 */
-	read	AMEVCNTR13_EL0		/* index 3 */
-	read	AMEVCNTR14_EL0		/* index 4 */
-	read	AMEVCNTR15_EL0		/* index 5 */
-	read	AMEVCNTR16_EL0		/* index 6 */
-	read	AMEVCNTR17_EL0		/* index 7 */
-	read	AMEVCNTR18_EL0		/* index 8 */
-	read	AMEVCNTR19_EL0		/* index 9 */
-	read	AMEVCNTR1A_EL0		/* index 10 */
-	read	AMEVCNTR1B_EL0		/* index 11 */
-	read	AMEVCNTR1C_EL0		/* index 12 */
-	read	AMEVCNTR1D_EL0		/* index 13 */
-	read	AMEVCNTR1E_EL0		/* index 14 */
-	read	AMEVCNTR1F_EL0		/* index 15 */
-endfunc amu_group1_cnt_read_internal
-
-/*
- * void amu_group1_cnt_write_internal(int idx, uint64_t val);
- *
- * Given `idx`, write `val` to the corresponding AMU counter.
- */
-func amu_group1_cnt_write_internal
-	adr	x2, 1f
-#if ENABLE_ASSERTIONS
-	/*
-	 * It can be dangerous to call this function with an
-	 * out of bounds index.  Ensure `idx` is valid.
-	 */
-	tst	x0, #~0xF
-	ASM_ASSERT(eq)
-#endif
-	/*
-	 * Given `idx` calculate address of mrs/ret instruction pair
-	 * in the table below.
-	 */
-	add	x2, x2, x0, lsl #3	/* each msr/ret sequence is 8 bytes */
-#if ENABLE_BTI
-	add	x2, x2, x0, lsl #2	/* + "bti j" instruction */
-#endif
-	br	x2
-
-1:	write	AMEVCNTR10_EL0		/* index 0 */
-	write	AMEVCNTR11_EL0		/* index 1 */
-	write	AMEVCNTR12_EL0		/* index 2 */
-	write	AMEVCNTR13_EL0		/* index 3 */
-	write	AMEVCNTR14_EL0		/* index 4 */
-	write	AMEVCNTR15_EL0		/* index 5 */
-	write	AMEVCNTR16_EL0		/* index 6 */
-	write	AMEVCNTR17_EL0		/* index 7 */
-	write	AMEVCNTR18_EL0		/* index 8 */
-	write	AMEVCNTR19_EL0		/* index 9 */
-	write	AMEVCNTR1A_EL0		/* index 10 */
-	write	AMEVCNTR1B_EL0		/* index 11 */
-	write	AMEVCNTR1C_EL0		/* index 12 */
-	write	AMEVCNTR1D_EL0		/* index 13 */
-	write	AMEVCNTR1E_EL0		/* index 14 */
-	write	AMEVCNTR1F_EL0		/* index 15 */
-endfunc amu_group1_cnt_write_internal
-
-/*
- * void amu_group1_set_evtype_internal(int idx, unsigned int val);
- *
- * Program the AMU event type register indexed by `idx`
- * with the value `val`.
- */
-func amu_group1_set_evtype_internal
-	adr	x2, 1f
-#if ENABLE_ASSERTIONS
-	/*
-	 * It can be dangerous to call this function with an
-	 * out of bounds index.  Ensure `idx` is valid.
-	 */
-	tst	x0, #~0xF
-	ASM_ASSERT(eq)
-
-	/* val should be between [0, 65535] */
-	tst	x1, #~0xFFFF
-	ASM_ASSERT(eq)
-#endif
-	/*
-	 * Given `idx` calculate address of msr/ret instruction pair
-	 * in the table below.
-	 */
-	add	x2, x2, x0, lsl #3	/* each msr/ret sequence is 8 bytes */
-#if ENABLE_BTI
-	add	x2, x2, x0, lsl #2	/* + "bti j" instruction */
-#endif
-	br	x2
-
-1:	write	AMEVTYPER10_EL0		/* index 0 */
-	write	AMEVTYPER11_EL0		/* index 1 */
-	write	AMEVTYPER12_EL0		/* index 2 */
-	write	AMEVTYPER13_EL0		/* index 3 */
-	write	AMEVTYPER14_EL0		/* index 4 */
-	write	AMEVTYPER15_EL0		/* index 5 */
-	write	AMEVTYPER16_EL0		/* index 6 */
-	write	AMEVTYPER17_EL0		/* index 7 */
-	write	AMEVTYPER18_EL0		/* index 8 */
-	write	AMEVTYPER19_EL0		/* index 9 */
-	write	AMEVTYPER1A_EL0		/* index 10 */
-	write	AMEVTYPER1B_EL0		/* index 11 */
-	write	AMEVTYPER1C_EL0		/* index 12 */
-	write	AMEVTYPER1D_EL0		/* index 13 */
-	write	AMEVTYPER1E_EL0		/* index 14 */
-	write	AMEVTYPER1F_EL0		/* index 15 */
-endfunc amu_group1_set_evtype_internal
-#endif
-
-/*
- * Accessor functions for virtual offset registers added with FEAT_AMUv1p1
- */
-
-/*
- * uint64_t amu_group0_voffset_read_internal(int idx);
- *
- * Given `idx`, read the corresponding AMU virtual offset register
- * and return it in `x0`.
- */
-func amu_group0_voffset_read_internal
-	adr	x1, 1f
-#if ENABLE_ASSERTIONS
-	/*
-	 * It can be dangerous to call this function with an
-	 * out of bounds index.  Ensure `idx` is valid.
-	 */
-	tst	x0, #~3
-	ASM_ASSERT(eq)
-	/* Make sure idx != 1 since AMEVCNTVOFF01_EL2 does not exist */
-	cmp	x0, #1
-	ASM_ASSERT(ne)
-#endif
-	/*
-	 * Given `idx` calculate address of mrs/ret instruction pair
-	 * in the table below.
-	 */
-	add	x1, x1, x0, lsl #3	/* each mrs/ret sequence is 8 bytes */
-#if ENABLE_BTI
-	add	x1, x1, x0, lsl #2	/* + "bti j" instruction */
-#endif
-	br	x1
-
-1:	read	AMEVCNTVOFF00_EL2	/* index 0 */
-	.skip	8			/* AMEVCNTVOFF01_EL2 does not exist */
-#if ENABLE_BTI
-	.skip	4
-#endif
-	read	AMEVCNTVOFF02_EL2	/* index 2 */
-	read	AMEVCNTVOFF03_EL2	/* index 3 */
-endfunc amu_group0_voffset_read_internal
-
-/*
- * void amu_group0_voffset_write_internal(int idx, uint64_t val);
- *
- * Given `idx`, write `val` to the corresponding AMU virtual offset register.
- */
-func amu_group0_voffset_write_internal
-	adr	x2, 1f
-#if ENABLE_ASSERTIONS
-	/*
-	 * It can be dangerous to call this function with an
-	 * out of bounds index.  Ensure `idx` is valid.
-	 */
-	tst	x0, #~3
-	ASM_ASSERT(eq)
-	/* Make sure idx != 1 since AMEVCNTVOFF01_EL2 does not exist */
-	cmp	x0, #1
-	ASM_ASSERT(ne)
-#endif
-	/*
-	 * Given `idx` calculate address of mrs/ret instruction pair
-	 * in the table below.
-	 */
-	add	x2, x2, x0, lsl #3	/* each msr/ret sequence is 8 bytes */
-#if ENABLE_BTI
-	add	x2, x2, x0, lsl #2	/* + "bti j" instruction */
-#endif
-	br	x2
-
-1:	write	AMEVCNTVOFF00_EL2	/* index 0 */
-	.skip	8			/* AMEVCNTVOFF01_EL2 does not exist */
-#if ENABLE_BTI
-	.skip	4
-#endif
-	write	AMEVCNTVOFF02_EL2	/* index 2 */
-	write	AMEVCNTVOFF03_EL2	/* index 3 */
-endfunc amu_group0_voffset_write_internal
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-/*
- * uint64_t amu_group1_voffset_read_internal(int idx);
- *
- * Given `idx`, read the corresponding AMU virtual offset register
- * and return it in `x0`.
- */
-func amu_group1_voffset_read_internal
-	adr	x1, 1f
-#if ENABLE_ASSERTIONS
-	/*
-	 * It can be dangerous to call this function with an
-	 * out of bounds index.  Ensure `idx` is valid.
-	 */
-	tst	x0, #~0xF
-	ASM_ASSERT(eq)
-#endif
-	/*
-	 * Given `idx` calculate address of mrs/ret instruction pair
-	 * in the table below.
-	 */
-	add	x1, x1, x0, lsl #3	/* each mrs/ret sequence is 8 bytes */
-#if ENABLE_BTI
-	add	x1, x1, x0, lsl #2	/* + "bti j" instruction */
-#endif
-	br	x1
-
-1:	read	AMEVCNTVOFF10_EL2	/* index 0 */
-	read	AMEVCNTVOFF11_EL2	/* index 1 */
-	read	AMEVCNTVOFF12_EL2	/* index 2 */
-	read	AMEVCNTVOFF13_EL2	/* index 3 */
-	read	AMEVCNTVOFF14_EL2	/* index 4 */
-	read	AMEVCNTVOFF15_EL2	/* index 5 */
-	read	AMEVCNTVOFF16_EL2	/* index 6 */
-	read	AMEVCNTVOFF17_EL2	/* index 7 */
-	read	AMEVCNTVOFF18_EL2	/* index 8 */
-	read	AMEVCNTVOFF19_EL2	/* index 9 */
-	read	AMEVCNTVOFF1A_EL2	/* index 10 */
-	read	AMEVCNTVOFF1B_EL2	/* index 11 */
-	read	AMEVCNTVOFF1C_EL2	/* index 12 */
-	read	AMEVCNTVOFF1D_EL2	/* index 13 */
-	read	AMEVCNTVOFF1E_EL2	/* index 14 */
-	read	AMEVCNTVOFF1F_EL2	/* index 15 */
-endfunc amu_group1_voffset_read_internal
-
-/*
- * void amu_group1_voffset_write_internal(int idx, uint64_t val);
- *
- * Given `idx`, write `val` to the corresponding AMU virtual offset register.
- */
-func amu_group1_voffset_write_internal
-	adr	x2, 1f
-#if ENABLE_ASSERTIONS
-	/*
-	 * It can be dangerous to call this function with an
-	 * out of bounds index.  Ensure `idx` is valid.
-	 */
-	tst	x0, #~0xF
-	ASM_ASSERT(eq)
-#endif
-	/*
-	 * Given `idx` calculate address of mrs/ret instruction pair
-	 * in the table below.
-	 */
-	add	x2, x2, x0, lsl #3	/* each msr/ret sequence is 8 bytes */
-#if ENABLE_BTI
-	add	x2, x2, x0, lsl #2	/* + "bti j" instruction */
-#endif
-	br	x2
-
-1:	write	AMEVCNTVOFF10_EL2	/* index 0 */
-	write	AMEVCNTVOFF11_EL2	/* index 1 */
-	write	AMEVCNTVOFF12_EL2	/* index 2 */
-	write	AMEVCNTVOFF13_EL2	/* index 3 */
-	write	AMEVCNTVOFF14_EL2	/* index 4 */
-	write	AMEVCNTVOFF15_EL2	/* index 5 */
-	write	AMEVCNTVOFF16_EL2	/* index 6 */
-	write	AMEVCNTVOFF17_EL2	/* index 7 */
-	write	AMEVCNTVOFF18_EL2	/* index 8 */
-	write	AMEVCNTVOFF19_EL2	/* index 9 */
-	write	AMEVCNTVOFF1A_EL2	/* index 10 */
-	write	AMEVCNTVOFF1B_EL2	/* index 11 */
-	write	AMEVCNTVOFF1C_EL2	/* index 12 */
-	write	AMEVCNTVOFF1D_EL2	/* index 13 */
-	write	AMEVCNTVOFF1E_EL2	/* index 14 */
-	write	AMEVCNTVOFF1F_EL2	/* index 15 */
-endfunc amu_group1_voffset_write_internal
-#endif
diff --git a/lib/extensions/amu/amu.mk b/lib/extensions/amu/amu.mk
index 868ab12..fba2c78 100644
--- a/lib/extensions/amu/amu.mk
+++ b/lib/extensions/amu/amu.mk
@@ -1,24 +1,13 @@
 #
-# Copyright (c) 2021, Arm Limited. All rights reserved.
+# Copyright (c) 2021-2025, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
-include lib/fconf/fconf.mk
-
-AMU_SOURCES	:=	lib/extensions/amu/${ARCH}/amu.c \
-			lib/extensions/amu/${ARCH}/amu_helpers.S
+AMU_SOURCES	:=	lib/extensions/amu/${ARCH}/amu.c
 
 ifneq (${ENABLE_AMU_AUXILIARY_COUNTERS},0)
         ifeq (${ENABLE_FEAT_AMU},0)
-                $(error AMU auxiliary counter support (`ENABLE_AMU_AUXILIARY_COUNTERS`) requires AMU support (`ENABLE_FEAT_AMU`))
+                $(error "ENABLE_AMU_AUXILIARY_COUNTERS requires ENABLE_FEAT_AMU")
         endif
 endif
-
-ifneq (${ENABLE_AMU_FCONF},0)
-        ifeq (${ENABLE_AMU_AUXILIARY_COUNTERS},0)
-                $(error AMU FCONF support (`ENABLE_AMU_FCONF`) is not necessary when auxiliary counter support (`ENABLE_AMU_AUXILIARY_COUNTERS`) is disabled)
-        endif
-
-        AMU_SOURCES	+=	${FCONF_AMU_SOURCES}
-endif
diff --git a/lib/extensions/amu/amu_private.h b/lib/extensions/amu/amu_private.h
deleted file mode 100644
index a3b6845..0000000
--- a/lib/extensions/amu/amu_private.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef AMU_PRIVATE_H
-#define AMU_PRIVATE_H
-
-#include <stdint.h>
-
-#include <lib/cassert.h>
-#include <lib/extensions/amu.h>
-#include <lib/utils_def.h>
-
-#include <platform_def.h>
-
-#define AMU_GROUP0_MAX_COUNTERS		U(16)
-#define AMU_GROUP1_MAX_COUNTERS		U(16)
-
-#define AMU_AMCGCR_CG0NC_MAX		U(16)
-
-uint64_t amu_group0_cnt_read_internal(unsigned int idx);
-void amu_group0_cnt_write_internal(unsigned int idx, uint64_t val);
-
-uint64_t amu_group1_cnt_read_internal(unsigned int idx);
-void amu_group1_cnt_write_internal(unsigned int idx, uint64_t val);
-void amu_group1_set_evtype_internal(unsigned int idx, unsigned int val);
-
-#if __aarch64__
-uint64_t amu_group0_voffset_read_internal(unsigned int idx);
-void amu_group0_voffset_write_internal(unsigned int idx, uint64_t val);
-
-uint64_t amu_group1_voffset_read_internal(unsigned int idx);
-void amu_group1_voffset_write_internal(unsigned int idx, uint64_t val);
-#endif
-
-#endif /* AMU_PRIVATE_H */
diff --git a/lib/extensions/sme/sme.c b/lib/extensions/sme/sme.c
index 98d57e9..e477da3 100644
--- a/lib/extensions/sme/sme.c
+++ b/lib/extensions/sme/sme.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -40,13 +40,8 @@
 
 void sme_init_el3(void)
 {
-	u_register_t cptr_el3 = read_cptr_el3();
 	u_register_t smcr_el3;
 
-	/* Set CPTR_EL3.ESM bit so we can access SMCR_EL3 without trapping. */
-	write_cptr_el3(cptr_el3 | ESM_BIT);
-	isb();
-
 	/*
 	 * Set the max LEN value and FA64 bit. This register is set up per_world
 	 * to be the least restrictive, then lower ELs can restrict as needed
@@ -69,10 +64,6 @@
 		smcr_el3 |= SMCR_ELX_EZT0_BIT;
 	}
 	write_smcr_el3(smcr_el3);
-
-	/* Reset CPTR_EL3 value. */
-	write_cptr_el3(cptr_el3);
-	isb();
 }
 
 void sme_init_el2_unused(void)
diff --git a/lib/extensions/sve/sve.c b/lib/extensions/sve/sve.c
index 143717e..4e18cdf 100644
--- a/lib/extensions/sve/sve.c
+++ b/lib/extensions/sve/sve.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -22,6 +22,12 @@
  */
 #define CONVERT_SVE_LENGTH(x)	(((x / 128) - 1))
 
+void sve_init_el3(void)
+{
+	/* Restrict maximum SVE vector length (SVE_VECTOR_LEN+1) * 128. */
+	write_zcr_el3(ZCR_EL3_LEN_MASK & CONVERT_SVE_LENGTH(SVE_VECTOR_LEN));
+}
+
 void sve_enable_per_world(per_world_context_t *per_world_ctx)
 {
 	u_register_t cptr_el3;
@@ -30,9 +36,6 @@
 	cptr_el3 = per_world_ctx->ctx_cptr_el3;
 	cptr_el3 = (cptr_el3 | CPTR_EZ_BIT) & ~(TFP_BIT);
 	per_world_ctx->ctx_cptr_el3 = cptr_el3;
-
-	/* Restrict maximum SVE vector length (SVE_VECTOR_LEN+1) * 128. */
-	per_world_ctx->ctx_zcr_el3 = (ZCR_EL3_LEN_MASK & CONVERT_SVE_LENGTH(SVE_VECTOR_LEN));
 }
 
 void sve_init_el2_unused(void)
diff --git a/lib/fconf/fconf.mk b/lib/fconf/fconf.mk
index ff781aa..d24f86b 100644
--- a/lib/fconf/fconf.mk
+++ b/lib/fconf/fconf.mk
@@ -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
 #
@@ -11,9 +11,3 @@
 
 FCONF_DYN_SOURCES	:=	lib/fconf/fconf_dyn_cfg_getter.c
 FCONF_DYN_SOURCES	+=	${FDT_WRAPPERS_SOURCES}
-
-FCONF_AMU_SOURCES	:=	lib/fconf/fconf_amu_getter.c
-FCONF_AMU_SOURCES	+=	${FDT_WRAPPERS_SOURCES}
-
-FCONF_MPMM_SOURCES	:=	lib/fconf/fconf_mpmm_getter.c
-FCONF_MPMM_SOURCES	+=	${FDT_WRAPPERS_SOURCES}
diff --git a/lib/fconf/fconf_amu_getter.c b/lib/fconf/fconf_amu_getter.c
deleted file mode 100644
index eff309c..0000000
--- a/lib/fconf/fconf_amu_getter.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <common/debug.h>
-#include <common/fdt_wrappers.h>
-#include <lib/fconf/fconf.h>
-#include <lib/fconf/fconf_amu_getter.h>
-#include <libfdt.h>
-
-#include <plat/common/platform.h>
-
-struct fconf_amu_config fconf_amu_config;
-static struct amu_topology fconf_amu_topology_;
-
-/*
- * Populate the core-specific AMU structure with information retrieved from a
- * device tree.
- *
- * Returns `0` on success, or a negative integer representing an error code.
- */
-static int fconf_populate_amu_cpu_amu(const void *fdt, int parent,
-				      struct amu_core *amu)
-{
-	int ret = 0;
-	int node = 0;
-
-	fdt_for_each_subnode(node, fdt, parent) {
-		const char *name;
-		const char *value;
-		int len;
-
-		uintptr_t idx = 0U;
-
-		name = fdt_get_name(fdt, node, &len);
-		if (strncmp(name, "counter@", 8) != 0) {
-			continue;
-		}
-
-		ret = fdt_get_reg_props_by_index(fdt, node, 0, &idx, NULL);
-		if (ret < 0) {
-			break;
-		}
-
-		value = fdt_getprop(fdt, node, "enable-at-el3", &len);
-		if ((value == NULL) && (len != -FDT_ERR_NOTFOUND)) {
-			break;
-		}
-
-		if (len != -FDT_ERR_NOTFOUND) {
-			amu->enable |= (1 << idx);
-		}
-	}
-
-	if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) {
-		return node;
-	}
-
-	return ret;
-}
-
-/*
- * Within a `cpu` node, attempt to dereference the `amu` property, and populate
- * the AMU information for the core.
- *
- * Returns `0` on success, or a negative integer representing an error code.
- */
-static int fconf_populate_amu_cpu(const void *fdt, int node, uintptr_t mpidr)
-{
-	int ret;
-	int idx;
-
-	uint32_t amu_phandle;
-	struct amu_core *amu;
-
-	ret = fdt_read_uint32(fdt, node, "amu", &amu_phandle);
-	if (ret < 0) {
-		if (ret == -FDT_ERR_NOTFOUND) {
-			ret = 0;
-		}
-
-		return ret;
-	}
-
-	node = fdt_node_offset_by_phandle(fdt, amu_phandle);
-	if (node < 0) {
-		return node;
-	}
-
-	idx = plat_core_pos_by_mpidr(mpidr);
-	if (idx < 0) {
-		return -FDT_ERR_BADVALUE;
-	}
-
-	amu = &fconf_amu_topology_.cores[idx];
-
-	return fconf_populate_amu_cpu_amu(fdt, node, amu);
-}
-
-/*
- * Populates the global `amu_topology` structure based on what's described by
- * the hardware configuration device tree blob.
- *
- * The device tree is expected to provide an `amu` property for each `cpu` node,
- * like so:
- *
- *     cpu@0 {
- *         amu = <&cpu0_amu>;
- *     };
- *
- *     amus {
- *         cpu0_amu: amu-0 {
- *             counters {
- *                 #address-cells = <2>;
- *                 #size-cells = <0>;
- *
- *                 counter@x,y {
- *                     reg = <x y>; // Group x, counter y
- *                 };
- *             };
- *         };
- *     };
- */
-static int fconf_populate_amu(uintptr_t config)
-{
-	int ret = fdtw_for_each_cpu(
-		(const void *)config, fconf_populate_amu_cpu);
-	if (ret == 0) {
-		fconf_amu_config.topology = &fconf_amu_topology_;
-	} else {
-		ERROR("FCONF: failed to parse AMU information: %d\n", ret);
-	}
-
-	return ret;
-}
-
-FCONF_REGISTER_POPULATOR(HW_CONFIG, amu, fconf_populate_amu);
diff --git a/lib/fconf/fconf_mpmm_getter.c b/lib/fconf/fconf_mpmm_getter.c
deleted file mode 100644
index 02a566d..0000000
--- a/lib/fconf/fconf_mpmm_getter.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <common/debug.h>
-#include <common/fdt_wrappers.h>
-#include <lib/fconf/fconf.h>
-#include <lib/fconf/fconf_mpmm_getter.h>
-#include <libfdt.h>
-
-#include <plat/common/platform.h>
-
-struct fconf_mpmm_config fconf_mpmm_config;
-static struct mpmm_topology fconf_mpmm_topology;
-
-/*
- * Within a `cpu` node, determine support for MPMM via the `supports-mpmm`
- * property.
- *
- * Returns `0` on success, or a negative integer representing an error code.
- */
-static int fconf_populate_mpmm_cpu(const void *fdt, int off, uintptr_t mpidr)
-{
-	int ret, len;
-
-	int core_pos;
-	struct mpmm_core *core;
-
-	core_pos = plat_core_pos_by_mpidr(mpidr);
-	if (core_pos < 0) {
-		return -FDT_ERR_BADVALUE;
-	}
-
-	core = &fconf_mpmm_topology.cores[core_pos];
-
-	fdt_getprop(fdt, off, "supports-mpmm", &len);
-	if (len >= 0) {
-		core->supported = true;
-		ret = 0;
-	} else {
-		core->supported = false;
-		ret = len;
-	}
-
-	return ret;
-}
-
-/*
- * Populates the global `fconf_mpmm_config` structure based on what's described
- * by the hardware configuration device tree blob.
- *
- * The device tree is expected to provide a `supports-mpmm` property for each
- * `cpu` node, like so:
- *
- *     cpu@0 {
- *       supports-mpmm;
- *     };
- *
- * This property indicates whether the core implements MPMM, as we cannot detect
- * support for it dynamically.
- */
-static int fconf_populate_mpmm(uintptr_t config)
-{
-	int ret = fdtw_for_each_cpu(
-		(const void *)config, fconf_populate_mpmm_cpu);
-	if (ret == 0) {
-		fconf_mpmm_config.topology = &fconf_mpmm_topology;
-	} else {
-		ERROR("FCONF: failed to configure MPMM: %d\n", ret);
-	}
-
-	return ret;
-}
-
-FCONF_REGISTER_POPULATOR(HW_CONFIG, mpmm, fconf_populate_mpmm);
diff --git a/lib/mpmm/mpmm.c b/lib/mpmm/mpmm.c
deleted file mode 100644
index dc61cf6..0000000
--- a/lib/mpmm/mpmm.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <stdbool.h>
-
-#include <common/debug.h>
-#include <lib/mpmm/mpmm.h>
-
-#include <plat/common/platform.h>
-
-#if ENABLE_MPMM_FCONF
-#	include <lib/fconf/fconf.h>
-#	include <lib/fconf/fconf_mpmm_getter.h>
-#endif
-
-static uint64_t read_cpuppmcr_el3_mpmmpinctl(void)
-{
-	return (read_cpuppmcr_el3() >> CPUPPMCR_EL3_MPMMPINCTL_SHIFT) &
-		CPUPPMCR_EL3_MPMMPINCTL_MASK;
-}
-
-static void write_cpumpmmcr_el3_mpmm_en(uint64_t mpmm_en)
-{
-	uint64_t value = read_cpumpmmcr_el3();
-
-	value &= ~(CPUMPMMCR_EL3_MPMM_EN_MASK << CPUMPMMCR_EL3_MPMM_EN_SHIFT);
-	value |= (mpmm_en & CPUMPMMCR_EL3_MPMM_EN_MASK) <<
-		CPUMPMMCR_EL3_MPMM_EN_SHIFT;
-
-	write_cpumpmmcr_el3(value);
-}
-
-static bool mpmm_supported(void)
-{
-	bool supported = false;
-	const struct mpmm_topology *topology;
-
-#if ENABLE_MPMM_FCONF
-	topology = FCONF_GET_PROPERTY(mpmm, config, topology);
-#else
-	topology = plat_mpmm_topology();
-#endif /* ENABLE_MPMM_FCONF */
-
-	/*
-	 * For the current core firstly try to find out if the platform
-	 * configuration has claimed support for MPMM, then make sure that MPMM
-	 * is controllable through the system registers.
-	 */
-
-	if (topology != NULL) {
-		unsigned int core_pos = plat_my_core_pos();
-
-		supported = topology->cores[core_pos].supported &&
-			(read_cpuppmcr_el3_mpmmpinctl() == 0U);
-	} else {
-		ERROR("MPMM: failed to generate MPMM topology\n");
-	}
-
-	return supported;
-}
-
-/* Defaults to false */
-static bool mpmm_disable_for_errata;
-
-void mpmm_enable(void)
-{
-	if (mpmm_supported()) {
-		if (mpmm_disable_for_errata) {
-			WARN("MPMM: disabled by errata workaround\n");
-			return;
-		}
-		write_cpumpmmcr_el3_mpmm_en(1U);
-	}
-}
-
-/*
- * This function is called from assembly code very early in BL31 so it must be
- * small and simple.
- */
-void mpmm_errata_disable(void)
-{
-	mpmm_disable_for_errata = true;
-}
diff --git a/lib/mpmm/mpmm.mk b/lib/mpmm/mpmm.mk
deleted file mode 100644
index 826f925..0000000
--- a/lib/mpmm/mpmm.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Copyright (c) 2021, Arm Limited. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-include lib/extensions/amu/amu.mk
-include lib/fconf/fconf.mk
-
-ifneq (${ENABLE_MPMM},0)
-        ifneq ($(ARCH),aarch64)
-                $(error MPMM support (`ENABLE_MPMM`) can only be enabled in AArch64 images (`ARCH`))
-        endif
-
-        ifeq (${ENABLE_AMU_AUXILIARY_COUNTERS},0) # For MPMM gear AMU counters
-                $(error MPMM support (`ENABLE_MPM`) requires auxiliary AMU counter support (`ENABLE_AMU_AUXILIARY_COUNTERS`))
-        endif
-endif
-
-MPMM_SOURCES	:=	lib/mpmm/mpmm.c
-MPMM_SOURCES	+=	${AMU_SOURCES}
-
-ifneq (${ENABLE_MPMM_FCONF},0)
-        ifeq (${ENABLE_MPMM},0)
-                $(error MPMM FCONF support (`ENABLE_MPMM_FCONF`) requires MPMM support (`ENABLE_MPMM`))
-        endif
-
-        MPMM_SOURCES	+= ${FCONF_MPMM_SOURCES}
-endif
diff --git a/lib/psci/psci_common.c b/lib/psci/psci_common.c
index 4bb23af..4c2601e 100644
--- a/lib/psci/psci_common.c
+++ b/lib/psci/psci_common.c
@@ -972,7 +972,7 @@
 	psci_power_state_t state_info = { {PSCI_LOCAL_STATE_RUN} };
 
 	/* Init registers that never change for the lifetime of TF-A */
-	cm_manage_extensions_el3();
+	cm_manage_extensions_el3(cpu_idx);
 
 	/*
 	 * Verify that we have been explicitly turned ON or resumed from
diff --git a/lib/psci/psci_suspend.c b/lib/psci/psci_suspend.c
index 05bbe39..0fb1ed3 100644
--- a/lib/psci/psci_suspend.c
+++ b/lib/psci/psci_suspend.c
@@ -42,12 +42,13 @@
  * This function does generic and platform specific suspend to power down
  * operations.
  ******************************************************************************/
-static void psci_suspend_to_pwrdown_start(unsigned int end_pwrlvl,
+static void psci_suspend_to_pwrdown_start(unsigned int idx,
+					  unsigned int end_pwrlvl,
 					  unsigned int max_off_lvl,
 					  const entry_point_info_t *ep,
 					  const psci_power_state_t *state_info)
 {
-	PUBLISH_EVENT(psci_suspend_pwrdown_start);
+	PUBLISH_EVENT_ARG(psci_suspend_pwrdown_start, &idx);
 
 #if PSCI_OS_INIT_MODE
 #ifdef PLAT_MAX_CPU_SUSPEND_PWR_LVL
@@ -223,7 +224,7 @@
 #endif
 #endif
 		max_off_lvl = psci_find_max_off_lvl(state_info);
-		psci_suspend_to_pwrdown_start(end_pwrlvl, max_off_lvl, ep, state_info);
+		psci_suspend_to_pwrdown_start(idx, end_pwrlvl, end_pwrlvl, ep, state_info);
 	}
 
 	/*
@@ -382,5 +383,5 @@
 	/* This loses its meaning when not suspending, reset so it's correct for OFF */
 	psci_set_suspend_pwrlvl(PLAT_MAX_PWR_LVL);
 
-	PUBLISH_EVENT(psci_suspend_pwrdown_finish);
+	PUBLISH_EVENT_ARG(psci_suspend_pwrdown_finish, &cpu_idx);
 }
diff --git a/make_helpers/arch_features.mk b/make_helpers/arch_features.mk
index 3c9e136..8dec522 100644
--- a/make_helpers/arch_features.mk
+++ b/make_helpers/arch_features.mk
@@ -291,7 +291,6 @@
 # Feature flags for supporting Activity monitor extensions.
 ENABLE_FEAT_AMU				?=	0
 ENABLE_AMU_AUXILIARY_COUNTERS		?=	0
-ENABLE_AMU_FCONF			?=	0
 AMU_RESTRICT_COUNTERS			?=	1
 
 # Build option to enable MPAM for lower ELs.
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index d514933..ec2aa1b 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -88,9 +88,6 @@
 # Enable support for powerdown abandons
 FEAT_PABANDON			:= 0
 
-# Enable MPMM configuration via FCONF.
-ENABLE_MPMM_FCONF		:= 0
-
 # Flag to Enable Position Independant support (PIE)
 ENABLE_PIE			:= 0
 
diff --git a/plat/arm/board/arm_fpga/platform.mk b/plat/arm/board/arm_fpga/platform.mk
index 967bf21..31835f1 100644
--- a/plat/arm/board/arm_fpga/platform.mk
+++ b/plat/arm/board/arm_fpga/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2021-2024, Arm Limited. All rights reserved.
+# Copyright (c) 2021-2025, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -78,7 +78,6 @@
 				lib/cpus/aarch64/cortex_a720.S			\
 				lib/cpus/aarch64/cortex_x3.S 			\
 				lib/cpus/aarch64/cortex_x4.S			\
-				lib/cpus/aarch64/neoverse_n_common.S		\
 				lib/cpus/aarch64/neoverse_n1.S			\
 				lib/cpus/aarch64/neoverse_n2.S			\
 				lib/cpus/aarch64/neoverse_v1.S			\
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 7b55571..7bd3e74 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -210,7 +210,6 @@
 					lib/cpus/aarch64/cortex_a715.S		\
 					lib/cpus/aarch64/cortex_a720.S		\
 					lib/cpus/aarch64/cortex_a720_ae.S	\
-					lib/cpus/aarch64/neoverse_n_common.S	\
 					lib/cpus/aarch64/neoverse_n1.S		\
 					lib/cpus/aarch64/neoverse_n2.S		\
 					lib/cpus/aarch64/neoverse_v1.S		\
diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk
index 1e12a12..a056bc2 100644
--- a/plat/arm/board/tc/platform.mk
+++ b/plat/arm/board/tc/platform.mk
@@ -32,10 +32,8 @@
 ENABLE_TRBE_FOR_NS		:=	1
 ENABLE_SYS_REG_TRACE_FOR_NS	:=	1
 ENABLE_FEAT_AMU			:=	1
-ENABLE_AMU_FCONF		:=	1
 ENABLE_AMU_AUXILIARY_COUNTERS	:=	1
 ENABLE_MPMM			:=	1
-ENABLE_MPMM_FCONF		:=	1
 ENABLE_FEAT_MTE2		:=	2
 ENABLE_SPE_FOR_NS		:=	3
 ENABLE_FEAT_TCR2		:=	3
diff --git a/plat/arm/board/tc/tc_bl31_setup.c b/plat/arm/board/tc/tc_bl31_setup.c
index c5ebfde..5d19aeb 100644
--- a/plat/arm/board/tc/tc_bl31_setup.c
+++ b/plat/arm/board/tc/tc_bl31_setup.c
@@ -72,6 +72,18 @@
 };
 #endif
 
+/* the bottom 3 AMU group 1 counters */
+#define MPMM_GEARS ((1 << 0) | (1 << 1) | (1 << 2))
+
+uint16_t plat_amu_aux_enables[PLATFORM_CORE_COUNT] = {
+	MPMM_GEARS, MPMM_GEARS, MPMM_GEARS, MPMM_GEARS,
+	MPMM_GEARS, MPMM_GEARS, MPMM_GEARS, MPMM_GEARS,
+#if PLATFORM_CORE_COUNT == 14
+	MPMM_GEARS, MPMM_GEARS, MPMM_GEARS, MPMM_GEARS,
+	MPMM_GEARS, MPMM_GEARS
+#endif
+};
+
 #if (TARGET_PLATFORM == 3) || (TARGET_PLATFORM == 4)
 static void enable_ns_mcn_pmu(void)
 {
diff --git a/plat/common/plat_psci_common.c b/plat/common/plat_psci_common.c
index c32e59f..4cea0b9 100644
--- a/plat/common/plat_psci_common.c
+++ b/plat/common/plat_psci_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2025, Arm Limited and Contributors. All rights reserved.
  * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -30,6 +30,12 @@
 #define PSCI_STAT_ID_EXIT_LOW_PWR		1
 #define PSCI_STAT_TOTAL_IDS			2
 
+#if HW_ASSISTED_COHERENCY
+#define CACHE_MAINTENANCE_ATTR	PMF_NO_CACHE_MAINT
+#else
+#define CACHE_MAINTENANCE_ATTR	PMF_CACHE_MAINT
+#endif
+
 PMF_DECLARE_CAPTURE_TIMESTAMP(psci_svc)
 PMF_DECLARE_GET_TIMESTAMP(psci_svc)
 PMF_REGISTER_SERVICE(psci_svc, PMF_PSCI_STAT_SVC_ID, PSCI_STAT_TOTAL_IDS,
@@ -70,7 +76,7 @@
 {
 	assert(state_info != NULL);
 	PMF_CAPTURE_TIMESTAMP(psci_svc, PSCI_STAT_ID_ENTER_LOW_PWR,
-		PMF_CACHE_MAINT);
+		CACHE_MAINTENANCE_ATTR);
 }
 
 /*
@@ -82,7 +88,7 @@
 {
 	assert(state_info != NULL);
 	PMF_CAPTURE_TIMESTAMP(psci_svc, PSCI_STAT_ID_EXIT_LOW_PWR,
-		PMF_CACHE_MAINT);
+		CACHE_MAINTENANCE_ATTR);
 }
 
 /*
@@ -93,22 +99,27 @@
 	const psci_power_state_t *state_info,
 	unsigned int last_cpu_idx)
 {
-	plat_local_state_t state;
 	unsigned long long pwrup_ts = 0, pwrdn_ts = 0;
 	unsigned int pmf_flags;
 
 	assert((lvl >= PSCI_CPU_PWR_LVL) && (lvl <= PLAT_MAX_PWR_LVL));
-	assert(state_info != NULL);
 	assert(last_cpu_idx <= PLATFORM_CORE_COUNT);
 
 	if (lvl == PSCI_CPU_PWR_LVL)
 		assert(last_cpu_idx == plat_my_core_pos());
 
+#if HW_ASSISTED_COHERENCY
+	/* HW coherency allows for the capture and access to happen with caches
+	 * ON. So these timestamps don't need cache maintenance */
+	pmf_flags = PMF_NO_CACHE_MAINT;
+#else
 	/*
 	 * If power down is requested, then timestamp capture will
 	 * be with caches OFF.  Hence we have to do cache maintenance
 	 * when reading the timestamp.
 	 */
+	plat_local_state_t state;
+	assert(state_info != NULL);
 	state = state_info->pwr_domain_state[PSCI_CPU_PWR_LVL];
 	if (is_local_state_off(state) != 0) {
 		pmf_flags = PMF_CACHE_MAINT;
@@ -116,6 +127,7 @@
 		assert(is_local_state_retn(state) == 1);
 		pmf_flags = PMF_NO_CACHE_MAINT;
 	}
+#endif
 
 	PMF_GET_TIMESTAMP_BY_INDEX(psci_svc,
 		PSCI_STAT_ID_ENTER_LOW_PWR,
diff --git a/plat/intel/soc/agilex5/bl2_plat_setup.c b/plat/intel/soc/agilex5/bl2_plat_setup.c
index fe5dc6e..f4010f9 100644
--- a/plat/intel/soc/agilex5/bl2_plat_setup.c
+++ b/plat/intel/soc/agilex5/bl2_plat_setup.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved.
  * Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
- * Copyright (c) 2024, Altera Corporation. All rights reserved.
+ * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -31,6 +31,8 @@
 #include "nand/nand.h"
 #include "qspi/cadence_qspi.h"
 #include "sdmmc/sdmmc.h"
+/* TODO: DTB not available */
+// #include "socfpga_dt.h"
 #include "socfpga_emac.h"
 #include "socfpga_f2sdram_manager.h"
 #include "socfpga_handoff.h"
@@ -138,6 +140,12 @@
 	/* DDR and IOSSM driver init */
 	agilex5_ddr_init(&reverse_handoff_ptr);
 
+	/* TODO: DTB not available */
+	// if (socfpga_dt_open_and_check(SOCFPGA_DTB_BASE, DT_COMPATIBLE_STR) < 0) {
+		// ERROR("SOCFPGA: Failed to open device tree\n");
+		// panic();
+	// }
+
 	if (combo_phy_init(&reverse_handoff_ptr) != 0) {
 		ERROR("SOCFPGA: Combo Phy initialization failed\n");
 	}
@@ -165,13 +173,13 @@
 
 	switch (boot_source) {
 	case BOOT_SOURCE_SDMMC:
-		NOTICE("SDMMC boot\n");
+		NOTICE("SOCFPGA: SDMMC boot\n");
 		cdns_mmc_init(&params, &mmc_info);
 		socfpga_io_setup(boot_source, PLAT_SDMMC_DATA_BASE);
 		break;
 
 	case BOOT_SOURCE_QSPI:
-		NOTICE("QSPI boot\n");
+		NOTICE("SOCFPGA: QSPI boot\n");
 		cad_qspi_init(0, QSPI_CONFIG_CPHA, QSPI_CONFIG_CPOL,
 			QSPI_CONFIG_CSDA, QSPI_CONFIG_CSDADS,
 			QSPI_CONFIG_CSEOT, QSPI_CONFIG_CSSOT, 0);
@@ -182,13 +190,13 @@
 		break;
 
 	case BOOT_SOURCE_NAND:
-		NOTICE("NAND boot\n");
+		NOTICE("SOCFPGA: SOCFPGA: NAND boot\n");
 		nand_init(&reverse_handoff_ptr);
 		socfpga_io_setup(boot_source, PLAT_NAND_DATA_BASE);
 		break;
 
 	default:
-		ERROR("Unsupported boot source\n");
+		ERROR("SOCFPGA: Unsupported boot source\n");
 		panic();
 		break;
 	}
@@ -230,7 +238,7 @@
 
 	ret = socfpga_vab_init(image_id);
 	if (ret < 0) {
-		ERROR("SOCFPGA VAB Authentication failed\n");
+		ERROR("SOCFPGA: VAB Authentication failed\n");
 		wfi();
 	}
 #endif
diff --git a/plat/intel/soc/agilex5/bl31_plat_setup.c b/plat/intel/soc/agilex5/bl31_plat_setup.c
index 03559e1..17d955a 100644
--- a/plat/intel/soc/agilex5/bl31_plat_setup.c
+++ b/plat/intel/soc/agilex5/bl31_plat_setup.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2019-2024, ARM Limited and Contributors. All rights reserved.
  * Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
- * Copyright (c) 2024, Altera Corporation. All rights reserved.
+ * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -21,6 +21,7 @@
 #include "agilex5_cache.h"
 #include "agilex5_power_manager.h"
 #include "ccu/ncore_ccu.h"
+#include "socfpga_dt.h"
 #include "socfpga_mailbox.h"
 #include "socfpga_private.h"
 #include "socfpga_reset_manager.h"
@@ -146,7 +147,7 @@
 	PLAT_INTEL_SOCFPGA_G0_IRQ_PROPS(INTR_GROUP0)
 };
 
-static const gicv3_driver_data_t plat_gicv3_gic_data = {
+gicv3_driver_data_t plat_gicv3_gic_data = {
 	.gicd_base = PLAT_INTEL_SOCFPGA_GICD_BASE,
 	.gicr_base = PLAT_INTEL_SOCFPGA_GICR_BASE,
 	.interrupt_props = agx5_interrupt_props,
@@ -162,6 +163,11 @@
 {
 	socfpga_delay_timer_init();
 
+	/* TODO: DTB not available */
+	// socfpga_dt_populate_gicv3_config(SOCFPGA_DTB_BASE, &plat_gicv3_gic_data);
+	// NOTICE("SOCFPGA: GIC GICD base address 0x%lx\n", plat_gicv3_gic_data.gicd_base);
+	// NOTICE("SOCFPGA: GIC GICR base address 0x%lx\n", plat_gicv3_gic_data.gicr_base);
+
 	/* Initialize the gic cpu and distributor interfaces */
 	gicv3_driver_init(&plat_gicv3_gic_data);
 	gicv3_distif_init();
@@ -192,9 +198,9 @@
 
 	cpuid = MPIDR_AFFLVL1_VAL(read_mpidr());
 	boot_core = ((mmio_read_32(AGX5_PWRMGR(MPU_BOOTCONFIG)) & 0xC00) >> 10);
-	NOTICE("BL31: Boot Core = %x\n", boot_core);
-	NOTICE("BL31: CPU ID = %x\n", cpuid);
-	INFO("BL31: Invalidate Data cache\n");
+	NOTICE("SOCFPGA: Boot Core = %x\n", boot_core);
+	NOTICE("SOCFPGA: CPU ID = %x\n", cpuid);
+	INFO("SOCFPGA: Invalidate Data cache\n");
 	invalidate_dcache_all();
 
 	/* Invalidate for NS EL2 and EL1 */
@@ -282,6 +288,11 @@
 	mmio_write_32(AGX5_PWRMGR(MPU_PCHCTLR), pch_cpu);
 }
 
+void bl31_plat_runtime_setup(void)
+{
+	console_switch_state(CONSOLE_FLAG_RUNTIME|CONSOLE_FLAG_BOOT);
+}
+
 void bl31_plat_enable_mmu(uint32_t flags)
 {
 	/* TODO: Enable mmu when needed */
diff --git a/plat/intel/soc/agilex5/include/socfpga_plat_def.h b/plat/intel/soc/agilex5/include/socfpga_plat_def.h
index 282958a..42d8ccf 100644
--- a/plat/intel/soc/agilex5/include/socfpga_plat_def.h
+++ b/plat/intel/soc/agilex5/include/socfpga_plat_def.h
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
  * Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
- * Copyright (c) 2024, Altera Corporation. All rights reserved.
+ * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -29,6 +29,8 @@
 #define PLAT_L2_RESET_REQ					0xB007C0DE
 #define PLAT_HANDOFF_OFFSET					0x0007F000
 #define PLAT_TIMER_BASE_ADDR					0x10D01000
+#define SOCFPGA_DTB_BASE			0x80020000
+#define DT_COMPATIBLE_STR			"arm,altera socfpga-agilex5"
 
 /* System Counter */
 /* TODO: Update back to 400MHz.
diff --git a/plat/intel/soc/agilex5/platform.mk b/plat/intel/soc/agilex5/platform.mk
index a831c39..58d4b2e 100644
--- a/plat/intel/soc/agilex5/platform.mk
+++ b/plat/intel/soc/agilex5/platform.mk
@@ -1,11 +1,12 @@
 #
 # Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
 # Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
-# Copyright (c) 2024, Altera Corporation. All rights reserved.
+# Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 include lib/xlat_tables_v2/xlat_tables.mk
+include lib/libfdt/libfdt.mk
 PLAT_INCLUDES		:=	\
 			-Iplat/intel/soc/agilex5/include/		\
 			-Iplat/intel/soc/common/drivers/		\
@@ -22,6 +23,7 @@
 
 PLAT_BL_COMMON_SOURCES	:=	\
 			${AGX5_GICv3_SOURCES}				\
+			common/fdt_wrappers.c				\
 			drivers/cadence/combo_phy/cdns_combo_phy.c	\
 			drivers/cadence/emmc/cdns_sdmmc.c	\
 			drivers/cadence/nand/cdns_nand.c	\
@@ -36,7 +38,8 @@
 			plat/intel/soc/common/drivers/ddr/ddr.c			\
 			plat/intel/soc/common/drivers/nand/nand.c			\
 			plat/intel/soc/common/lib/sha/sha.c				\
-			plat/intel/soc/common/socfpga_delay_timer.c
+			plat/intel/soc/common/socfpga_delay_timer.c	\
+			plat/intel/soc/common/socfpga_dt.c
 
 BL2_SOURCES		+=	\
 		common/desc_image_load.c				\
diff --git a/plat/intel/soc/common/fdts/agilex5_fdt.dts b/plat/intel/soc/common/fdts/agilex5_fdt.dts
new file mode 100644
index 0000000..e16034f
--- /dev/null
+++ b/plat/intel/soc/common/fdts/agilex5_fdt.dts
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2019-2024, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+	model = "ALTERA SOCFPGA AGILEX5";
+	compatible = "arm,altera socfpga-agilex5";
+	owner = "jit.loon.lim@intel.com";
+	interrupt-parent = <&gic>;
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	psci {
+		compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci";
+		method = "smc";
+
+		cpu_on = <0xdeadc0de>;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		enable-method = "psci";
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a5";
+			reg = <0>;
+		};
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a5";
+			reg = <1>;
+		};
+		cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a5";
+			reg = <2>;
+		};
+		cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a5";
+			reg = <3>;
+		};
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x90000000>;
+	};
+
+	gic: interrupt-controller@2c010000 {
+		compatible = "arm,gic-600", "arm,gic-v3";
+		#address-cells = <2>;
+		#interrupt-cells = <3>;
+		#size-cells = <1>;
+		#ranges;
+		interrupt-controller;
+		reg = <0x1D000000 0>, /* GICD */
+		      <0x1D060000 0>; /* GICR */
+		interrupts = <0x1 0x9 0x4>;
+	};
+
+	serial0: uart@1a200000 {
+		compatible = "arm,console-16550";
+		reg = <0x10C02000 0x1000>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 8 0xf04>;
+		clock-frequency = <100000000>;
+		uart-baudrate = <115200>;
+	};
+
+	timer0: timer@1a040000 {
+		compatible = "arm,armv7-timer-mem";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		reg = <0x1a040000 0x1000>;
+		clock-frequency = <7500000>;
+
+		frame@1a050000 {
+			frame-number = <0>;
+			interrupts = <0 2 0xf04>;
+			reg = <0x1a050000 0x1000>;
+		};
+	};
+
+};
diff --git a/plat/intel/soc/common/include/socfpga_dt.h b/plat/intel/soc/common/include/socfpga_dt.h
new file mode 100644
index 0000000..3ff4cb7
--- /dev/null
+++ b/plat/intel/soc/common/include/socfpga_dt.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOCFPGA_DT_H
+#define SOCFPGA_DT_H
+
+
+#include <stdlib.h>
+#include <drivers/arm/gicv3.h>
+#include <drivers/delay_timer.h>
+/*
+ * This macro takes three arguments:
+ *   config:	Configuration identifier
+ *   name:	property namespace
+ *   callback:	populate() function
+ */
+#define SOCFPGA_REGISTER_POPULATOR(config, name, callback)			\
+	__section(".socfpga_populator") __used			\
+	static const struct socfpga_populator (name##__populator) = {		\
+		.config_type = (#config),					\
+		.info = (#name),						\
+		.populate = (callback)						\
+	}
+
+/*
+ * Populator callback
+ *
+ * This structure are used by the fconf_populate function and should only be
+ * defined by the SOCFPGA_REGISTER_POPULATOR macro.
+ */
+struct socfpga_populator {
+	/* Description of the data loaded by the callback */
+	const char *config_type;
+	const char *info;
+
+	/* Callback used by fconf_populate function with a provided config dtb.
+	 * Return 0 on success, err_code < 0 otherwise.
+	 */
+	int (*populate)(uintptr_t config);
+};
+
+/* Hardware Config related getter */
+#define hw_config__gicv3_config_getter(prop) plat_gicv3_gic_data.prop
+
+/* Function Definitions */
+int socfpga_dt_open_and_check(uintptr_t dt_addr, char *compatible_str);
+int socfpga_dt_populate_gicv3_config(uintptr_t dt_addr, gicv3_driver_data_t *plat_driver_data);
+int socfpga_dt_populate_dram_layout(uintptr_t dt_addr);
+
+#endif
diff --git a/plat/intel/soc/common/socfpga_dt.c b/plat/intel/soc/common/socfpga_dt.c
new file mode 100644
index 0000000..0333b9b
--- /dev/null
+++ b/plat/intel/soc/common/socfpga_dt.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv3.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <libfdt.h>
+#include <platform_def.h>
+#include <tools_share/firmware_image_package.h>
+
+#include "socfpga_dt.h"
+
+static const void *fdt;
+/*******************************************************************************
+ * This function checks device tree file with its header.
+ * Returns 0 on success and a negative FDT error code on failure.
+ ******************************************************************************/
+int socfpga_dt_open_and_check(uintptr_t dt_addr, char *compatible_str)
+{
+	int ret = 0;
+	int node = 1;
+
+	ret = fdt_check_header((void *)dt_addr);
+
+	if (ret != 0) {
+		ERROR("SOCFPGA: FDT Header invalid\n");
+		return ret;
+	}
+
+	fdt = (const void *)dt_addr;
+
+	/* As libfdt use void *, we can't avoid this cast */
+	const void *dtb = (void *)dt_addr;
+
+	/* Assert the node offset point to compatible property */
+	node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
+	if (node < 0) {
+		ERROR("SOCFPGA: Can't find `%s` compatible in dtb\n",
+						compatible_str);
+		return node;
+	}
+
+	NOTICE("SOCFPGA: Successfully open and check FDT\n");
+
+	return ret;
+}
+
+int socfpga_dt_populate_gicv3_config(uintptr_t dt_addr, gicv3_driver_data_t *plat_driver_data)
+{
+	int err;
+	int node;
+	uintptr_t addr;
+
+	/* Necessary to work with libfdt APIs */
+	const void *hw_config_dtb = (const void *)dt_addr;
+	/*
+	 * Find the offset of the node containing "arm,gic-v3" compatible property.
+	 * Populating fconf strucutures dynamically is not supported for legacy
+	 * systems which use GICv2 IP. Simply skip extracting GIC properties.
+	 */
+	node = fdt_node_offset_by_compatible(hw_config_dtb, -1, "arm,gic-v3");
+	if (node < 0) {
+		ERROR("SOCFPGA: Unable to locate node with arm,gic-v3 compatible property\n");
+		return 0;
+	}
+	/* The GICv3 DT binding holds at least two address/size pairs,
+	 * the first describing the distributor, the second the redistributors.
+	 * See: bindings/interrupt-controller/arm,gic-v3.yaml
+	 */
+	err = fdt_get_reg_props_by_index(hw_config_dtb, node, 0, &addr, NULL);
+	if (err < 0) {
+		ERROR("SOCFPGA: Failed to read GICD reg property of GIC node\n");
+	} else {
+		plat_driver_data->gicd_base = addr;
+	}
+
+	err = fdt_get_reg_props_by_index(hw_config_dtb, node, 1, &addr, NULL);
+	if (err < 0) {
+		ERROR("SOCFPGA: Failed to read GICR reg property of GIC node\n");
+	} else {
+		plat_driver_data->gicr_base = addr;
+	}
+	return err;
+}
+
+int socfpga_dt_populate_dram_layout(uintptr_t dt_addr)
+{
+	int node;
+	uintptr_t addr;
+	size_t size;
+
+	/* Necessary to work with libfdt APIs */
+	const void *hw_config_dtb = (const void *)dt_addr;
+
+	/* Find 'memory' node */
+	node = fdt_node_offset_by_prop_value(hw_config_dtb, -1, "device_type",
+					     "memory", sizeof("memory"));
+	if (node < 0) {
+		NOTICE("SOCFPGA: Unable to locate 'memory' node\n");
+		return node;
+	}
+
+	int err = fdt_get_reg_props_by_index(
+			hw_config_dtb, node, 0,
+			&addr, (size_t *)&size);
+
+	NOTICE("SOCFPGA: Mem base 0x%lx, Mem size 0x%lx\n", addr, size);
+	if (err < 0) {
+		ERROR("SOCFPGA: Failed to read 'reg' property of 'memory' node\n");
+		return err;
+	}
+
+	return 0;
+}
diff --git a/plat/qemu/common/common.mk b/plat/qemu/common/common.mk
index 2dc89bc..da981e5 100644
--- a/plat/qemu/common/common.mk
+++ b/plat/qemu/common/common.mk
@@ -23,7 +23,6 @@
 				lib/cpus/aarch64/cortex_a72.S		\
 				lib/cpus/aarch64/cortex_a76.S		\
 				lib/cpus/aarch64/cortex_a710.S		\
-				lib/cpus/aarch64/neoverse_n_common.S	\
 				lib/cpus/aarch64/neoverse_n1.S		\
 				lib/cpus/aarch64/neoverse_v1.S		\
 				lib/cpus/aarch64/neoverse_n2.S		\
diff --git a/plat/rockchip/common/params_setup.c b/plat/rockchip/common/params_setup.c
index 68054ad..a27c755 100644
--- a/plat/rockchip/common/params_setup.c
+++ b/plat/rockchip/common/params_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2025, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -37,7 +37,7 @@
 static uint32_t rk_uart_base = PLAT_RK_UART_BASE;
 static uint32_t rk_uart_baudrate = PLAT_RK_UART_BAUDRATE;
 static uint32_t rk_uart_clock = PLAT_RK_UART_CLOCK;
-#define FDT_BUFFER_SIZE 0x20000
+#define FDT_BUFFER_SIZE 0x60000
 static uint64_t fdt_buffer[FDT_BUFFER_SIZE / 8];
 
 void *plat_get_fdt(void)
diff --git a/plat/rockchip/rk3399/rk3399_def.h b/plat/rockchip/rk3399/rk3399_def.h
index ba83242..8d6ecfb 100644
--- a/plat/rockchip/rk3399/rk3399_def.h
+++ b/plat/rockchip/rk3399/rk3399_def.h
@@ -17,7 +17,7 @@
 /**************************************************************************
  * UART related constants
  **************************************************************************/
-#define RK3399_BAUDRATE			115200
+#define RK3399_BAUDRATE			1500000
 #define RK3399_UART_CLOCK		24000000
 
 /******************************************************************************