Merge pull request #1287 from davidcunado-arm/dc/fix_misra

Update ULL() macro and instances of ull to comply with MISRA
diff --git a/bl1/bl1.ld.S b/bl1/bl1.ld.S
index e4c454b..26c0ae4 100644
--- a/bl1/bl1.ld.S
+++ b/bl1/bl1.ld.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -129,7 +129,8 @@
     /*
      * The xlat_table section is for full, aligned page tables (4K).
      * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section and eliminates the unecessary zero init
+     * the .bss section. The tables are initialized to zero by the translation
+     * tables library.
      */
     xlat_table (NOLOAD) : {
         *(xlat_table)
diff --git a/bl2/bl2.ld.S b/bl2/bl2.ld.S
index 4fe78f9..69c22eb 100644
--- a/bl2/bl2.ld.S
+++ b/bl2/bl2.ld.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -108,7 +108,8 @@
     /*
      * The xlat_table section is for full, aligned page tables (4K).
      * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section and eliminates the unecessary zero init
+     * the .bss section. The tables are initialized to zero by the translation
+     * tables library.
      */
     xlat_table (NOLOAD) : {
         *(xlat_table)
diff --git a/bl2/bl2_el3.ld.S b/bl2/bl2_el3.ld.S
index 57709e3..3728643 100644
--- a/bl2/bl2_el3.ld.S
+++ b/bl2/bl2_el3.ld.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -139,7 +139,8 @@
     /*
      * The xlat_table section is for full, aligned page tables (4K).
      * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section and eliminates the unnecessary zero init
+     * the .bss section. The tables are initialized to zero by the translation
+     * tables library.
      */
     xlat_table (NOLOAD) : {
         *(xlat_table)
diff --git a/bl2u/bl2u.ld.S b/bl2u/bl2u.ld.S
index da58717..7b97758 100644
--- a/bl2u/bl2u.ld.S
+++ b/bl2u/bl2u.ld.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -95,7 +95,8 @@
     /*
      * The xlat_table section is for full, aligned page tables (4K).
      * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section and eliminates the unecessary zero init
+     * the .bss section. The tables are initialized to zero by the translation
+     * tables library.
      */
     xlat_table (NOLOAD) : {
         *(xlat_table)
diff --git a/bl31/aarch64/bl31_entrypoint.S b/bl31/aarch64/bl31_entrypoint.S
index 924f295..0d1077c 100644
--- a/bl31/aarch64/bl31_entrypoint.S
+++ b/bl31/aarch64/bl31_entrypoint.S
@@ -9,7 +9,7 @@
 #include <el3_common_macros.S>
 #include <pmf_asm_macros.S>
 #include <runtime_instr.h>
-#include <xlat_tables_defs.h>
+#include <xlat_mmu_helpers.h>
 
 	.globl	bl31_entrypoint
 	.globl	bl31_warm_entrypoint
diff --git a/bl31/bl31.ld.S b/bl31/bl31.ld.S
index dd046c4..c6a4fe4 100644
--- a/bl31/bl31.ld.S
+++ b/bl31/bl31.ld.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -217,7 +217,8 @@
     /*
      * The xlat_table section is for full, aligned page tables (4K).
      * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section and eliminates the unecessary zero init
+     * the .bss section. The tables are initialized to zero by the translation
+     * tables library.
      */
     xlat_table (NOLOAD) : {
 #if ENABLE_SPM
diff --git a/bl31/ehf.c b/bl31/ehf.c
index 39ee635..8673564 100644
--- a/bl31/ehf.c
+++ b/bl31/ehf.c
@@ -9,6 +9,8 @@
  */
 
 #include <assert.h>
+#include <context.h>
+#include <context_mgmt.h>
 #include <cpu_data.h>
 #include <debug.h>
 #include <ehf.h>
@@ -308,15 +310,17 @@
 /*
  * Program Priority Mask to the original Non-secure priority such that
  * Non-secure interrupts may preempt Secure execution, viz. during Yielding SMC
- * calls.
+ * calls. The 'preempt_ret_code' parameter indicates the Yielding SMC's return
+ * value in case the call was preempted.
  *
  * This API is expected to be invoked before delegating a yielding SMC to Secure
  * EL1. I.e. within the window of secure execution after Non-secure context is
  * saved (after entry into EL3) and Secure context is restored (before entering
  * Secure EL1).
  */
-void ehf_allow_ns_preemption(void)
+void ehf_allow_ns_preemption(uint64_t preempt_ret_code)
 {
+	cpu_context_t *ns_ctx;
 	unsigned int old_pmr __unused;
 	pe_exc_data_t *pe_data = this_cpu_data();
 
@@ -333,6 +337,15 @@
 		panic();
 	}
 
+	/*
+	 * Program preempted return code to x0 right away so that, if the
+	 * Yielding SMC was indeed preempted before a dispatcher gets a chance
+	 * to populate it, the caller would find the correct return value.
+	 */
+	ns_ctx = cm_get_context(NON_SECURE);
+	assert(ns_ctx);
+	write_ctx_reg(get_gpregs_ctx(ns_ctx), CTX_GPREG_X0, preempt_ret_code);
+
 	old_pmr = plat_ic_set_priority_mask(pe_data->ns_pri_mask);
 
 	EHF_LOG("Priority Mask: 0x%x => 0x%x\n", old_pmr, pe_data->ns_pri_mask);
diff --git a/bl32/sp_min/sp_min.ld.S b/bl32/sp_min/sp_min.ld.S
index e798a0d..71de883 100644
--- a/bl32/sp_min/sp_min.ld.S
+++ b/bl32/sp_min/sp_min.ld.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -176,7 +176,8 @@
     /*
      * The xlat_table section is for full, aligned page tables (4K).
      * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section and eliminates the unecessary zero init
+     * the .bss section. The tables are initialized to zero by the translation
+     * tables library.
      */
     xlat_table (NOLOAD) : {
         *(xlat_table)
diff --git a/bl32/tsp/tsp.ld.S b/bl32/tsp/tsp.ld.S
index d256b46..31c5a67 100644
--- a/bl32/tsp/tsp.ld.S
+++ b/bl32/tsp/tsp.ld.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -94,7 +94,8 @@
     /*
      * The xlat_table section is for full, aligned page tables (4K).
      * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section and eliminates the unecessary zero init
+     * the .bss section. The tables are initialized to zero by the translation
+     * tables library.
      */
     xlat_table (NOLOAD) : {
         *(xlat_table)
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index f21baf5..21db86b 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -2022,9 +2022,9 @@
 Critical SDEI events on the platform. This must have a lower value (therefore of
 higher priority) than ``PLAT_SDEI_NORMAL_PRI``.
 
-It's recommended that SDEI exception priorities in general are assigned the
-lowest among Secure priorities. Among the SDEI exceptions, Critical SDEI
-priority must be higher than Normal SDEI priority.
+**Note**: SDEI exception priorities must be the lowest among Secure priorities.
+Among the SDEI exceptions, Critical SDEI priority must be higher than Normal
+SDEI priority.
 
 Functions
 .........
diff --git a/include/bl31/ehf.h b/include/bl31/ehf.h
index be8c957..f963f8d 100644
--- a/include/bl31/ehf.h
+++ b/include/bl31/ehf.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -82,7 +82,7 @@
 void ehf_activate_priority(unsigned int priority);
 void ehf_deactivate_priority(unsigned int priority);
 void ehf_register_priority_handler(unsigned int pri, ehf_handler_t handler);
-void ehf_allow_ns_preemption(void);
+void ehf_allow_ns_preemption(uint64_t preempt_ret_code);
 unsigned int ehf_is_ns_preemption_allowed(void);
 
 #endif /* __ASSEMBLY__ */
diff --git a/include/lib/cpus/aarch64/cortex_a75.h b/include/lib/cpus/aarch64/cortex_a75.h
index 940125d..20f0251 100644
--- a/include/lib/cpus/aarch64/cortex_a75.h
+++ b/include/lib/cpus/aarch64/cortex_a75.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -19,28 +19,6 @@
 /* Definitions of register field mask in CORTEX_A75_CPUPWRCTLR_EL1 */
 #define CORTEX_A75_CORE_PWRDN_EN_MASK	0x1
 
-/*******************************************************************************
- * CPU Activity Monitor Unit register specific definitions.
- ******************************************************************************/
-#define CPUAMCNTENCLR_EL0	S3_3_C15_C9_7
-#define CPUAMCNTENSET_EL0	S3_3_C15_C9_6
-#define CPUAMCFGR_EL0		S3_3_C15_C10_6
-#define CPUAMUSERENR_EL0	S3_3_C15_C10_7
-
-/* Activity Monitor Event Counter Registers */
-#define CPUAMEVCNTR0_EL0	S3_3_C15_C9_0
-#define CPUAMEVCNTR1_EL0	S3_3_C15_C9_1
-#define CPUAMEVCNTR2_EL0	S3_3_C15_C9_2
-#define CPUAMEVCNTR3_EL0	S3_3_C15_C9_3
-#define CPUAMEVCNTR4_EL0	S3_3_C15_C9_4
-
-/* Activity Monitor Event Type Registers */
-#define CPUAMEVTYPER0_EL0	S3_3_C15_C10_0
-#define CPUAMEVTYPER1_EL0	S3_3_C15_C10_1
-#define CPUAMEVTYPER2_EL0	S3_3_C15_C10_2
-#define CPUAMEVTYPER3_EL0	S3_3_C15_C10_3
-#define CPUAMEVTYPER4_EL0	S3_3_C15_C10_4
-
 #define CORTEX_A75_ACTLR_AMEN_BIT	(U(1) << 4)
 
 /*
@@ -50,9 +28,9 @@
  * CPUAMEVTYPER<n> register and are disabled by default. Platforms may
  * enable this with suitable programming.
  */
-#define CORTEX_A75_AMU_NR_COUNTERS	5
-#define CORTEX_A75_AMU_GROUP0_MASK	0x7
-#define CORTEX_A75_AMU_GROUP1_MASK	(0 << 3)
+#define CORTEX_A75_AMU_NR_COUNTERS	U(5)
+#define CORTEX_A75_AMU_GROUP0_MASK	U(0x7)
+#define CORTEX_A75_AMU_GROUP1_MASK	(U(0) << 3)
 
 #ifndef __ASSEMBLY__
 #include <stdint.h>
diff --git a/include/lib/cpus/aarch64/cpuamu.h b/include/lib/cpus/aarch64/cpuamu.h
new file mode 100644
index 0000000..960a524
--- /dev/null
+++ b/include/lib/cpus/aarch64/cpuamu.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __CPUAMU_H__
+#define __CPUAMU_H__
+
+/*******************************************************************************
+ * CPU Activity Monitor Unit register specific definitions.
+ ******************************************************************************/
+#define CPUAMCNTENCLR_EL0	S3_3_C15_C9_7
+#define CPUAMCNTENSET_EL0	S3_3_C15_C9_6
+#define CPUAMCFGR_EL0		S3_3_C15_C10_6
+#define CPUAMUSERENR_EL0	S3_3_C15_C10_7
+
+/* Activity Monitor Event Counter Registers */
+#define CPUAMEVCNTR0_EL0	S3_3_C15_C9_0
+#define CPUAMEVCNTR1_EL0	S3_3_C15_C9_1
+#define CPUAMEVCNTR2_EL0	S3_3_C15_C9_2
+#define CPUAMEVCNTR3_EL0	S3_3_C15_C9_3
+#define CPUAMEVCNTR4_EL0	S3_3_C15_C9_4
+
+/* Activity Monitor Event Type Registers */
+#define CPUAMEVTYPER0_EL0	S3_3_C15_C10_0
+#define CPUAMEVTYPER1_EL0	S3_3_C15_C10_1
+#define CPUAMEVTYPER2_EL0	S3_3_C15_C10_2
+#define CPUAMEVTYPER3_EL0	S3_3_C15_C10_3
+#define CPUAMEVTYPER4_EL0	S3_3_C15_C10_4
+
+#ifndef __ASSEMBLY__
+#include <stdint.h>
+
+uint64_t cpuamu_cnt_read(int idx);
+void cpuamu_cnt_write(int idx, uint64_t val);
+unsigned int cpuamu_read_cpuamcntenset_el0(void);
+unsigned int cpuamu_read_cpuamcntenclr_el0(void);
+void cpuamu_write_cpuamcntenset_el0(unsigned int mask);
+void cpuamu_write_cpuamcntenclr_el0(unsigned int mask);
+
+int midr_match(unsigned int cpu_midr);
+void cpuamu_context_save(unsigned int nr_counters);
+void cpuamu_context_restore(unsigned int nr_counters);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __CPUAMU_H__ */
diff --git a/include/lib/extensions/spe.h b/include/lib/extensions/spe.h
index 8a74127..b2b188e 100644
--- a/include/lib/extensions/spe.h
+++ b/include/lib/extensions/spe.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,6 +7,7 @@
 #ifndef __SPE_H__
 #define __SPE_H__
 
+int spe_supported(void);
 void spe_enable(int el2_unused);
 void spe_disable(void);
 
diff --git a/include/lib/extensions/sve.h b/include/lib/extensions/sve.h
index 28923e3..9c7f37f 100644
--- a/include/lib/extensions/sve.h
+++ b/include/lib/extensions/sve.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,6 +7,7 @@
 #ifndef __SVE_H__
 #define __SVE_H__
 
+int sve_supported(void);
 void sve_enable(int el2_unused);
 
 #endif /* __SVE_H__ */
diff --git a/include/lib/xlat_tables/xlat_mmu_helpers.h b/include/lib/xlat_tables/xlat_mmu_helpers.h
index fd3efc3..d83d764 100644
--- a/include/lib/xlat_tables/xlat_mmu_helpers.h
+++ b/include/lib/xlat_tables/xlat_mmu_helpers.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,13 +7,51 @@
 #ifndef __XLAT_MMU_HELPERS_H__
 #define __XLAT_MMU_HELPERS_H__
 
+/*
+ * The following flags are passed to enable_mmu_xxx() to override the default
+ * values used to program system registers while enabling the MMU.
+ */
+
+/*
+ * When this flag is used, all data access to Normal memory from this EL and all
+ * Normal memory accesses to the translation tables of this EL are non-cacheable
+ * for all levels of data and unified cache until the caches are enabled by
+ * setting the bit SCTLR_ELx.C.
+ */
+#define DISABLE_DCACHE			(U(1) << 0)
+
+/*
+ * Mark the translation tables as non-cacheable for the MMU table walker, which
+ * is a different observer from the PE/CPU. If the flag is not specified, the
+ * tables are cacheable for the MMU table walker.
+ *
+ * Note that, as far as the PE/CPU observer is concerned, the attributes used
+ * are the ones specified in the translation tables themselves. The MAIR
+ * register specifies the cacheability through the field AttrIndx of the lower
+ * attributes of the translation tables. The shareability is specified in the SH
+ * field of the lower attributes.
+ *
+ * The MMU table walker uses the attributes specified in the fields ORGNn, IRGNn
+ * and SHn of the TCR register to access the translation tables.
+ *
+ * The attributes specified in the TCR register and the tables can be different
+ * as there are no checks to prevent that. Special care must be taken to ensure
+ * that there aren't mismatches. The behaviour in that case is described in the
+ * sections 'Mismatched memory attributes' in the ARMv8 ARM.
+ */
+#define XLAT_TABLE_NC			(U(1) << 1)
+
+#ifndef __ASSEMBLY__
+
 #ifdef AARCH32
 /* AArch32 specific translation table API */
-void enable_mmu_secure(uint32_t flags);
+void enable_mmu_secure(unsigned int flags);
 #else
 /* AArch64 specific translation table APIs */
 void enable_mmu_el1(unsigned int flags);
 void enable_mmu_el3(unsigned int flags);
 #endif /* AARCH32 */
 
+#endif /* __ASSEMBLY__ */
+
 #endif /* __XLAT_MMU_HELPERS_H__ */
diff --git a/include/lib/xlat_tables/xlat_tables_defs.h b/include/lib/xlat_tables/xlat_tables_defs.h
index 3a7f245..1c84fe0 100644
--- a/include/lib/xlat_tables/xlat_tables_defs.h
+++ b/include/lib/xlat_tables/xlat_tables_defs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,6 +9,7 @@
 
 #include <arch.h>
 #include <utils_def.h>
+#include <xlat_mmu_helpers.h>
 
 /* Miscellaneous MMU related constants */
 #define NUM_2MB_IN_GB		(U(1) << 9)
@@ -165,16 +166,4 @@
 #define XN_SHIFT			54
 #define UXN_SHIFT			XN_SHIFT
 
-/*
- * Flags to override default values used to program system registers while
- * enabling the MMU.
- */
-#define DISABLE_DCACHE			(U(1) << 0)
-
-/*
- * This flag marks the translation tables are Non-cacheable for MMU accesses.
- * If the flag is not specified, by default the tables are cacheable.
- */
-#define XLAT_TABLE_NC			(U(1) << 1)
-
 #endif /* __XLAT_TABLES_DEFS_H__ */
diff --git a/lib/cpus/aarch64/cortex_a75.S b/lib/cpus/aarch64/cortex_a75.S
index 946f988..12ea304 100644
--- a/lib/cpus/aarch64/cortex_a75.S
+++ b/lib/cpus/aarch64/cortex_a75.S
@@ -6,108 +6,9 @@
 
 #include <arch.h>
 #include <asm_macros.S>
-#include <bl_common.h>
-#include <cpu_macros.S>
-#include <plat_macros.S>
 #include <cortex_a75.h>
-
-	.globl	cortex_a75_amu_cnt_read
-	.globl	cortex_a75_amu_cnt_write
-	.globl	cortex_a75_amu_read_cpuamcntenset_el0
-	.globl	cortex_a75_amu_read_cpuamcntenclr_el0
-	.globl	cortex_a75_amu_write_cpuamcntenset_el0
-	.globl	cortex_a75_amu_write_cpuamcntenclr_el0
-
-/*
- * uint64_t cortex_a75_amu_cnt_read(int idx);
- *
- * Given `idx`, read the corresponding AMU counter
- * and return it in `x0`.
- */
-func cortex_a75_amu_cnt_read
-	adr	x1, 1f
-	lsl	x0, x0, #3
-	add	x1, x1, x0
-	br	x1
-
-1:
-	mrs	x0, CPUAMEVCNTR0_EL0
-	ret
-	mrs	x0, CPUAMEVCNTR1_EL0
-	ret
-	mrs	x0, CPUAMEVCNTR2_EL0
-	ret
-	mrs	x0, CPUAMEVCNTR3_EL0
-	ret
-	mrs	x0, CPUAMEVCNTR4_EL0
-	ret
-endfunc cortex_a75_amu_cnt_read
-
-/*
- * void cortex_a75_amu_cnt_write(int idx, uint64_t val);
- *
- * Given `idx`, write `val` to the corresponding AMU counter.
- */
-func cortex_a75_amu_cnt_write
-	adr	x2, 1f
-	lsl	x0, x0, #3
-	add	x2, x2, x0
-	br	x2
-
-1:
-	msr	CPUAMEVCNTR0_EL0, x0
-	ret
-	msr	CPUAMEVCNTR1_EL0, x0
-	ret
-	msr	CPUAMEVCNTR2_EL0, x0
-	ret
-	msr	CPUAMEVCNTR3_EL0, x0
-	ret
-	msr	CPUAMEVCNTR4_EL0, x0
-	ret
-endfunc cortex_a75_amu_cnt_write
-
-/*
- * unsigned int cortex_a75_amu_read_cpuamcntenset_el0(void);
- *
- * Read the `CPUAMCNTENSET_EL0` CPU register and return
- * it in `x0`.
- */
-func cortex_a75_amu_read_cpuamcntenset_el0
-	mrs	x0, CPUAMCNTENSET_EL0
-	ret
-endfunc cortex_a75_amu_read_cpuamcntenset_el0
-
-/*
- * unsigned int cortex_a75_amu_read_cpuamcntenclr_el0(void);
- *
- * Read the `CPUAMCNTENCLR_EL0` CPU register and return
- * it in `x0`.
- */
-func cortex_a75_amu_read_cpuamcntenclr_el0
-	mrs	x0, CPUAMCNTENCLR_EL0
-	ret
-endfunc cortex_a75_amu_read_cpuamcntenclr_el0
-
-/*
- * void cortex_a75_amu_write_cpuamcntenset_el0(unsigned int mask);
- *
- * Write `mask` to the `CPUAMCNTENSET_EL0` CPU register.
- */
-func cortex_a75_amu_write_cpuamcntenset_el0
-	msr	CPUAMCNTENSET_EL0, x0
-	ret
-endfunc cortex_a75_amu_write_cpuamcntenset_el0
-
-/*
- * void cortex_a75_amu_write_cpuamcntenclr_el0(unsigned int mask);
- *
- * Write `mask` to the `CPUAMCNTENCLR_EL0` CPU register.
- */
-func cortex_a75_amu_write_cpuamcntenclr_el0
-	mrs	x0, CPUAMCNTENCLR_EL0
-	ret
-endfunc cortex_a75_amu_write_cpuamcntenclr_el0
+#include <cpuamu.h>
+#include <cpu_macros.S>
 
 func cortex_a75_reset_func
 #if IMAGE_BL31 && WORKAROUND_CVE_2017_5715
diff --git a/lib/cpus/aarch64/cortex_a75_pubsub.c b/lib/cpus/aarch64/cortex_a75_pubsub.c
index a1ffcb0..16f62f4 100644
--- a/lib/cpus/aarch64/cortex_a75_pubsub.c
+++ b/lib/cpus/aarch64/cortex_a75_pubsub.c
@@ -1,73 +1,24 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <cortex_a75.h>
-#include <platform.h>
+#include <cpuamu.h>
 #include <pubsub_events.h>
 
-struct amu_ctx {
-	uint64_t cnts[CORTEX_A75_AMU_NR_COUNTERS];
-	uint16_t mask;
-};
-
-static struct amu_ctx amu_ctxs[PLATFORM_CORE_COUNT];
-
 static void *cortex_a75_context_save(const void *arg)
 {
-	struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()];
-	unsigned int midr;
-	unsigned int midr_mask;
-	int i;
-
-	midr = read_midr();
-	midr_mask = (MIDR_IMPL_MASK << MIDR_IMPL_SHIFT) |
-		(MIDR_PN_MASK << MIDR_PN_SHIFT);
-	if ((midr & midr_mask) != (CORTEX_A75_MIDR & midr_mask))
-		return 0;
-
-	/* Save counter configuration */
-	ctx->mask = cortex_a75_amu_read_cpuamcntenset_el0();
-
-	/* Ensure counters are disabled */
-	cortex_a75_amu_write_cpuamcntenclr_el0(ctx->mask);
-	isb();
-
-	/* Save counters */
-	for (i = 0; i < CORTEX_A75_AMU_NR_COUNTERS; i++)
-		ctx->cnts[i] = cortex_a75_amu_cnt_read(i);
-
+	if (midr_match(CORTEX_A75_MIDR) != 0)
+		cpuamu_context_save(CORTEX_A75_AMU_NR_COUNTERS);
 	return 0;
 }
 
 static void *cortex_a75_context_restore(const void *arg)
 {
-	struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()];
-	unsigned int midr;
-	unsigned int midr_mask;
-	int i;
-
-	midr = read_midr();
-	midr_mask = (MIDR_IMPL_MASK << MIDR_IMPL_SHIFT) |
-		(MIDR_PN_MASK << MIDR_PN_SHIFT);
-	if ((midr & midr_mask) != (CORTEX_A75_MIDR & midr_mask))
-		return 0;
-
-	ctx = &amu_ctxs[plat_my_core_pos()];
-
-	/* Counters were disabled in `cortex_a75_context_save()` */
-	assert(cortex_a75_amu_read_cpuamcntenset_el0() == 0);
-
-	/* Restore counters */
-	for (i = 0; i < CORTEX_A75_AMU_NR_COUNTERS; i++)
-		cortex_a75_amu_cnt_write(i, ctx->cnts[i]);
-	isb();
-
-	/* Restore counter configuration */
-	cortex_a75_amu_write_cpuamcntenset_el0(ctx->mask);
-
+	if (midr_match(CORTEX_A75_MIDR) != 0)
+		cpuamu_context_restore(CORTEX_A75_AMU_NR_COUNTERS);
 	return 0;
 }
 
diff --git a/lib/cpus/aarch64/cpuamu.c b/lib/cpus/aarch64/cpuamu.c
new file mode 100644
index 0000000..b9bad86
--- /dev/null
+++ b/lib/cpus/aarch64/cpuamu.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <cpuamu.h>
+#include <platform.h>
+#include <pubsub_events.h>
+
+#define CPUAMU_NR_COUNTERS	5U
+
+struct amu_ctx {
+	uint64_t cnts[CPUAMU_NR_COUNTERS];
+	unsigned int mask;
+};
+
+static struct amu_ctx amu_ctxs[PLATFORM_CORE_COUNT];
+
+int midr_match(unsigned int cpu_midr)
+{
+	unsigned int midr, midr_mask;
+
+	midr = (unsigned int)read_midr();
+	midr_mask = (MIDR_IMPL_MASK << MIDR_IMPL_SHIFT) |
+		(MIDR_PN_MASK << MIDR_PN_SHIFT);
+	return ((midr & midr_mask) == (cpu_midr & midr_mask));
+}
+
+void cpuamu_context_save(unsigned int nr_counters)
+{
+	struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()];
+	unsigned int i;
+
+	assert(nr_counters <= CPUAMU_NR_COUNTERS);
+
+	/* Save counter configuration */
+	ctx->mask = cpuamu_read_cpuamcntenset_el0();
+
+	/* Disable counters */
+	cpuamu_write_cpuamcntenclr_el0(ctx->mask);
+	isb();
+
+	/* Save counters */
+	for (i = 0; i < nr_counters; i++)
+		ctx->cnts[i] = cpuamu_cnt_read(i);
+}
+
+void cpuamu_context_restore(unsigned int nr_counters)
+{
+	struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()];
+	unsigned int i;
+
+	assert(nr_counters <= CPUAMU_NR_COUNTERS);
+
+	/*
+	 * Disable counters.  They were enabled early in the
+	 * CPU reset function.
+	 */
+	cpuamu_write_cpuamcntenclr_el0(ctx->mask);
+	isb();
+
+	/* Restore counters */
+	for (i = 0; i < nr_counters; i++)
+		cpuamu_cnt_write(i, ctx->cnts[i]);
+	isb();
+
+	/* Restore counter configuration */
+	cpuamu_write_cpuamcntenset_el0(ctx->mask);
+}
diff --git a/lib/cpus/aarch64/cpuamu_helpers.S b/lib/cpus/aarch64/cpuamu_helpers.S
new file mode 100644
index 0000000..8965d6d
--- /dev/null
+++ b/lib/cpus/aarch64/cpuamu_helpers.S
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <cpuamu.h>
+
+	.globl	cpuamu_cnt_read
+	.globl	cpuamu_cnt_write
+	.globl	cpuamu_read_cpuamcntenset_el0
+	.globl	cpuamu_read_cpuamcntenclr_el0
+	.globl	cpuamu_write_cpuamcntenset_el0
+	.globl	cpuamu_write_cpuamcntenclr_el0
+
+/*
+ * uint64_t cpuamu_cnt_read(int idx);
+ *
+ * Given `idx`, read the corresponding AMU counter
+ * and return it in `x0`.
+ */
+func cpuamu_cnt_read
+	adr	x1, 1f
+	lsl	x0, x0, #3
+	add	x1, x1, x0
+	br	x1
+
+1:
+	mrs	x0, CPUAMEVCNTR0_EL0
+	ret
+	mrs	x0, CPUAMEVCNTR1_EL0
+	ret
+	mrs	x0, CPUAMEVCNTR2_EL0
+	ret
+	mrs	x0, CPUAMEVCNTR3_EL0
+	ret
+	mrs	x0, CPUAMEVCNTR4_EL0
+	ret
+endfunc cpuamu_cnt_read
+
+/*
+ * void cpuamu_cnt_write(int idx, uint64_t val);
+ *
+ * Given `idx`, write `val` to the corresponding AMU counter.
+ */
+func cpuamu_cnt_write
+	adr	x2, 1f
+	lsl	x0, x0, #3
+	add	x2, x2, x0
+	br	x2
+
+1:
+	msr	CPUAMEVCNTR0_EL0, x0
+	ret
+	msr	CPUAMEVCNTR1_EL0, x0
+	ret
+	msr	CPUAMEVCNTR2_EL0, x0
+	ret
+	msr	CPUAMEVCNTR3_EL0, x0
+	ret
+	msr	CPUAMEVCNTR4_EL0, x0
+	ret
+endfunc cpuamu_cnt_write
+
+/*
+ * unsigned int cpuamu_read_cpuamcntenset_el0(void);
+ *
+ * Read the `CPUAMCNTENSET_EL0` CPU register and return
+ * it in `x0`.
+ */
+func cpuamu_read_cpuamcntenset_el0
+	mrs	x0, CPUAMCNTENSET_EL0
+	ret
+endfunc cpuamu_read_cpuamcntenset_el0
+
+/*
+ * unsigned int cpuamu_read_cpuamcntenclr_el0(void);
+ *
+ * Read the `CPUAMCNTENCLR_EL0` CPU register and return
+ * it in `x0`.
+ */
+func cpuamu_read_cpuamcntenclr_el0
+	mrs	x0, CPUAMCNTENCLR_EL0
+	ret
+endfunc cpuamu_read_cpuamcntenclr_el0
+
+/*
+ * void cpuamu_write_cpuamcntenset_el0(unsigned int mask);
+ *
+ * Write `mask` to the `CPUAMCNTENSET_EL0` CPU register.
+ */
+func cpuamu_write_cpuamcntenset_el0
+	msr	CPUAMCNTENSET_EL0, x0
+	ret
+endfunc cpuamu_write_cpuamcntenset_el0
+
+/*
+ * void cpuamu_write_cpuamcntenclr_el0(unsigned int mask);
+ *
+ * Write `mask` to the `CPUAMCNTENCLR_EL0` CPU register.
+ */
+func cpuamu_write_cpuamcntenclr_el0
+	msr	CPUAMCNTENCLR_EL0, x0
+	ret
+endfunc cpuamu_write_cpuamcntenclr_el0
diff --git a/lib/extensions/amu/aarch32/amu.c b/lib/extensions/amu/aarch32/amu.c
index 68cc4b3..05c98f1 100644
--- a/lib/extensions/amu/aarch32/amu.c
+++ b/lib/extensions/amu/aarch32/amu.c
@@ -30,7 +30,7 @@
 
 void amu_enable(int el2_unused)
 {
-	if (!amu_supported())
+	if (amu_supported() == 0)
 		return;
 
 	if (el2_unused) {
@@ -54,7 +54,7 @@
 /* Read the group 0 counter identified by the given `idx`. */
 uint64_t amu_group0_cnt_read(int idx)
 {
-	assert(amu_supported());
+	assert(amu_supported() != 0);
 	assert(idx >= 0 && idx < AMU_GROUP0_NR_COUNTERS);
 
 	return amu_group0_cnt_read_internal(idx);
@@ -63,7 +63,7 @@
 /* Write the group 0 counter identified by the given `idx` with `val`. */
 void amu_group0_cnt_write(int idx, uint64_t val)
 {
-	assert(amu_supported());
+	assert(amu_supported() != 0);
 	assert(idx >= 0 && idx < AMU_GROUP0_NR_COUNTERS);
 
 	amu_group0_cnt_write_internal(idx, val);
@@ -73,7 +73,7 @@
 /* Read the group 1 counter identified by the given `idx`. */
 uint64_t amu_group1_cnt_read(int idx)
 {
-	assert(amu_supported());
+	assert(amu_supported() != 0);
 	assert(idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS);
 
 	return amu_group1_cnt_read_internal(idx);
@@ -82,7 +82,7 @@
 /* Write the group 1 counter identified by the given `idx` with `val`. */
 void amu_group1_cnt_write(int idx, uint64_t val)
 {
-	assert(amu_supported());
+	assert(amu_supported() != 0);
 	assert(idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS);
 
 	amu_group1_cnt_write_internal(idx, val);
@@ -91,7 +91,7 @@
 
 void amu_group1_set_evtype(int idx, unsigned int val)
 {
-	assert(amu_supported());
+	assert(amu_supported() != 0);
 	assert(idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS);
 
 	amu_group1_set_evtype_internal(idx, val);
@@ -103,13 +103,14 @@
 	struct amu_ctx *ctx;
 	int i;
 
-	if (!amu_supported())
+	if (amu_supported() == 0)
 		return (void *)-1;
 
 	ctx = &amu_ctxs[plat_my_core_pos()];
 
 	/* Assert that group 0 counter configuration is what we expect */
-	assert(read_amcntenset0() == AMU_GROUP0_COUNTERS_MASK);
+	assert(read_amcntenset0() == AMU_GROUP0_COUNTERS_MASK &&
+	       read_amcntenset1() == AMU_GROUP1_COUNTERS_MASK);
 
 	/*
 	 * Disable group 0 counters to avoid other observers like SCP sampling
@@ -131,17 +132,15 @@
 static void *amu_context_restore(const void *arg)
 {
 	struct amu_ctx *ctx;
-	uint64_t features;
 	int i;
 
-	features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT;
-	if ((features & ID_PFR0_AMU_MASK) != 1)
+	if (amu_supported() == 0)
 		return (void *)-1;
 
 	ctx = &amu_ctxs[plat_my_core_pos()];
 
 	/* Counters were disabled in `amu_context_save()` */
-	assert(read_amcntenset0() == 0);
+	assert(read_amcntenset0() == 0 && read_amcntenset1() == 0);
 
 	/* Restore group 0 counters */
 	for (i = 0; i < AMU_GROUP0_NR_COUNTERS; i++)
diff --git a/lib/extensions/amu/aarch32/amu_helpers.S b/lib/extensions/amu/aarch32/amu_helpers.S
index 84dca04..effb8e5 100644
--- a/lib/extensions/amu/aarch32/amu_helpers.S
+++ b/lib/extensions/amu/aarch32/amu_helpers.S
@@ -18,7 +18,7 @@
  * uint64_t amu_group0_cnt_read_internal(int idx);
  *
  * Given `idx`, read the corresponding AMU counter
- * and return it in `r0`.
+ * and return it in `r0` and `r1`.
  */
 func amu_group0_cnt_read_internal
 #if ENABLE_ASSERTIONS
@@ -52,13 +52,15 @@
  * 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	r2, r0
-	lsr	r2, r2, #2
-	cmp	r2, #0
+	mov	r1, r0
+	lsr	r1, r1, #2
+	cmp	r1, #0
 	ASM_ASSERT(eq)
 #endif
 
@@ -66,19 +68,19 @@
 	 * Given `idx` calculate address of stcopr16/bx lr instruction pair
 	 * in the table below.
 	 */
-	adr	r2, 1f
+	adr	r1, 1f
 	lsl	r0, r0, #3	/* each stcopr16/bx lr sequence is 8 bytes */
-	add	r2, r2, r0
-	bx	r2
+	add	r1, r1, r0
+	bx	r1
 
 1:
-	stcopr16	r0,r1, AMEVCNTR00	/* index 0 */
+	stcopr16	r2, r3, AMEVCNTR00	/* index 0 */
 	bx 		lr
-	stcopr16	r0,r1, AMEVCNTR01	/* index 1 */
+	stcopr16	r2, r3, AMEVCNTR01	/* index 1 */
 	bx 		lr
-	stcopr16	r0,r1, AMEVCNTR02	/* index 2 */
+	stcopr16	r2, r3, AMEVCNTR02	/* index 2 */
 	bx 		lr
-	stcopr16	r0,r1, AMEVCNTR03	/* index 3 */
+	stcopr16	r2, r3, AMEVCNTR03	/* index 3 */
 	bx 		lr
 endfunc amu_group0_cnt_write_internal
 
@@ -86,14 +88,14 @@
  * uint64_t amu_group1_cnt_read_internal(int idx);
  *
  * Given `idx`, read the corresponding AMU counter
- * and return it in `r0`.
+ * and return it in `r0` and `r1`.
  */
 func amu_group1_cnt_read_internal
 #if ENABLE_ASSERTIONS
 	/* `idx` should be between [0, 15] */
-	mov	r2, r0
-	lsr	r2, r2, #4
-	cmp	r2, #0
+	mov	r1, r0
+	lsr	r1, r1, #4
+	cmp	r1, #0
 	ASM_ASSERT(eq)
 #endif
 
@@ -107,51 +109,53 @@
 	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
+	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	r2, r0
-	lsr	r2, r2, #4
-	cmp	r2, #0
+	mov	r1, r0
+	lsr	r1, r1, #4
+	cmp	r1, #0
 	ASM_ASSERT(eq)
 #endif
 
@@ -159,43 +163,43 @@
 	 * Given `idx` calculate address of ldcopr16/bx lr instruction pair
 	 * in the table below.
 	 */
-	adr	r2, 1f
+	adr	r1, 1f
 	lsl	r0, r0, #3	/* each stcopr16/bx lr sequence is 8 bytes */
-	add	r2, r2, r0
-	bx	r2
+	add	r1, r1, r0
+	bx	r1
 
 1:
-	stcopr16	r0,r1,	AMEVCNTR10	/* index 0 */
+	stcopr16	r2, r3,	AMEVCNTR10	/* index 0 */
 	bx		lr
-	stcopr16	r0,r1,	AMEVCNTR11	/* index 1 */
+	stcopr16	r2, r3,	AMEVCNTR11	/* index 1 */
 	bx		lr
-	stcopr16	r0,r1,	AMEVCNTR12	/* index 2 */
+	stcopr16	r2, r3,	AMEVCNTR12	/* index 2 */
 	bx		lr
-	stcopr16	r0,r1,	AMEVCNTR13	/* index 3 */
+	stcopr16	r2, r3,	AMEVCNTR13	/* index 3 */
 	bx		lr
-	stcopr16	r0,r1,	AMEVCNTR14	/* index 4 */
+	stcopr16	r2, r3,	AMEVCNTR14	/* index 4 */
 	bx		lr
-	stcopr16	r0,r1,	AMEVCNTR15	/* index 5 */
+	stcopr16	r2, r3,	AMEVCNTR15	/* index 5 */
 	bx		lr
-	stcopr16	r0,r1,	AMEVCNTR16	/* index 6 */
+	stcopr16	r2, r3,	AMEVCNTR16	/* index 6 */
 	bx		lr
-	stcopr16	r0,r1,	AMEVCNTR17	/* index 7 */
+	stcopr16	r2, r3,	AMEVCNTR17	/* index 7 */
 	bx		lr
-	stcopr16	r0,r1,	AMEVCNTR18	/* index 8 */
+	stcopr16	r2, r3,	AMEVCNTR18	/* index 8 */
 	bx		lr
-	stcopr16	r0,r1,	AMEVCNTR19	/* index 9 */
+	stcopr16	r2, r3,	AMEVCNTR19	/* index 9 */
 	bx		lr
-	stcopr16	r0,r1,	AMEVCNTR1A	/* index 10 */
+	stcopr16	r2, r3,	AMEVCNTR1A	/* index 10 */
 	bx		lr
-	stcopr16	r0,r1,	AMEVCNTR1B	/* index 11 */
+	stcopr16	r2, r3,	AMEVCNTR1B	/* index 11 */
 	bx		lr
-	stcopr16	r0,r1,	AMEVCNTR1C	/* index 12 */
+	stcopr16	r2, r3,	AMEVCNTR1C	/* index 12 */
 	bx		lr
-	stcopr16	r0,r1,	AMEVCNTR1D	/* index 13 */
+	stcopr16	r2, r3,	AMEVCNTR1D	/* index 13 */
 	bx		lr
-	stcopr16	r0,r1,	AMEVCNTR1E	/* index 14 */
+	stcopr16	r2, r3,	AMEVCNTR1E	/* index 14 */
 	bx		lr
-	stcopr16	r0,r1,	AMEVCNTR1F	/* index 15 */
+	stcopr16	r2, r3,	AMEVCNTR1F	/* index 15 */
 	bx		lr
 endfunc amu_group1_cnt_write_internal
 
@@ -230,36 +234,36 @@
 	bx	r2
 
 1:
-	stcopr	r0,	AMEVTYPER10 /* index 0 */
+	stcopr	r1,	AMEVTYPER10 /* index 0 */
 	bx	lr
-	stcopr	r0,	AMEVTYPER11 /* index 1 */
+	stcopr	r1,	AMEVTYPER11 /* index 1 */
 	bx	lr
-	stcopr	r0,	AMEVTYPER12 /* index 2 */
+	stcopr	r1,	AMEVTYPER12 /* index 2 */
 	bx	lr
-	stcopr	r0,	AMEVTYPER13 /* index 3 */
+	stcopr	r1,	AMEVTYPER13 /* index 3 */
 	bx	lr
-	stcopr	r0,	AMEVTYPER14 /* index 4 */
+	stcopr	r1,	AMEVTYPER14 /* index 4 */
 	bx	lr
-	stcopr	r0,	AMEVTYPER15 /* index 5 */
+	stcopr	r1,	AMEVTYPER15 /* index 5 */
 	bx	lr
-	stcopr	r0,	AMEVTYPER16 /* index 6 */
+	stcopr	r1,	AMEVTYPER16 /* index 6 */
 	bx	lr
-	stcopr	r0,	AMEVTYPER17 /* index 7 */
+	stcopr	r1,	AMEVTYPER17 /* index 7 */
 	bx	lr
-	stcopr	r0,	AMEVTYPER18 /* index 8 */
+	stcopr	r1,	AMEVTYPER18 /* index 8 */
 	bx	lr
-	stcopr	r0,	AMEVTYPER19 /* index 9 */
+	stcopr	r1,	AMEVTYPER19 /* index 9 */
 	bx	lr
-	stcopr	r0,	AMEVTYPER1A /* index 10 */
+	stcopr	r1,	AMEVTYPER1A /* index 10 */
 	bx	lr
-	stcopr	r0,	AMEVTYPER1B /* index 11 */
+	stcopr	r1,	AMEVTYPER1B /* index 11 */
 	bx	lr
-	stcopr	r0,	AMEVTYPER1C /* index 12 */
+	stcopr	r1,	AMEVTYPER1C /* index 12 */
 	bx	lr
-	stcopr	r0,	AMEVTYPER1D /* index 13 */
+	stcopr	r1,	AMEVTYPER1D /* index 13 */
 	bx	lr
-	stcopr	r0,	AMEVTYPER1E /* index 14 */
+	stcopr	r1,	AMEVTYPER1E /* index 14 */
 	bx	lr
-	stcopr	r0,	AMEVTYPER1F /* index 15 */
+	stcopr	r1,	AMEVTYPER1F /* index 15 */
 	bx	lr
 endfunc amu_group1_set_evtype_internal
diff --git a/lib/extensions/amu/aarch64/amu.c b/lib/extensions/amu/aarch64/amu.c
index 7d39f35..5d556e5 100644
--- a/lib/extensions/amu/aarch64/amu.c
+++ b/lib/extensions/amu/aarch64/amu.c
@@ -37,7 +37,7 @@
 {
 	uint64_t v;
 
-	if (!amu_supported())
+	if (amu_supported() == 0)
 		return;
 
 	if (el2_unused) {
@@ -67,7 +67,7 @@
 /* Read the group 0 counter identified by the given `idx`. */
 uint64_t amu_group0_cnt_read(int idx)
 {
-	assert(amu_supported());
+	assert(amu_supported() != 0);
 	assert(idx >= 0 && idx < AMU_GROUP0_NR_COUNTERS);
 
 	return amu_group0_cnt_read_internal(idx);
@@ -76,7 +76,7 @@
 /* Write the group 0 counter identified by the given `idx` with `val`. */
 void amu_group0_cnt_write(int idx, uint64_t val)
 {
-	assert(amu_supported());
+	assert(amu_supported() != 0);
 	assert(idx >= 0 && idx < AMU_GROUP0_NR_COUNTERS);
 
 	amu_group0_cnt_write_internal(idx, val);
@@ -86,7 +86,7 @@
 /* Read the group 1 counter identified by the given `idx`. */
 uint64_t amu_group1_cnt_read(int idx)
 {
-	assert(amu_supported());
+	assert(amu_supported() != 0);
 	assert(idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS);
 
 	return amu_group1_cnt_read_internal(idx);
@@ -95,7 +95,7 @@
 /* Write the group 1 counter identified by the given `idx` with `val`. */
 void amu_group1_cnt_write(int idx, uint64_t val)
 {
-	assert(amu_supported());
+	assert(amu_supported() != 0);
 	assert(idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS);
 
 	amu_group1_cnt_write_internal(idx, val);
@@ -108,7 +108,7 @@
  */
 void amu_group1_set_evtype(int idx, unsigned int val)
 {
-	assert(amu_supported());
+	assert(amu_supported() != 0);
 	assert (idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS);
 
 	amu_group1_set_evtype_internal(idx, val);
@@ -120,7 +120,7 @@
 	struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()];
 	int i;
 
-	if (!amu_supported())
+	if (amu_supported() == 0)
 		return (void *)-1;
 
 	/* Assert that group 0/1 counter configuration is what we expect */
@@ -154,7 +154,7 @@
 	struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()];
 	int i;
 
-	if (!amu_supported())
+	if (amu_supported() == 0)
 		return (void *)-1;
 
 	/* Counters were disabled in `amu_context_save()` */
diff --git a/lib/extensions/spe/spe.c b/lib/extensions/spe/spe.c
index 3b297f2..a9bed49 100644
--- a/lib/extensions/spe/spe.c
+++ b/lib/extensions/spe/spe.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,71 +14,72 @@
  */
 #define psb_csync()	asm volatile("hint #17")
 
-void spe_enable(int el2_unused)
+int spe_supported(void)
 {
 	uint64_t features;
 
 	features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMS_SHIFT;
-	if ((features & ID_AA64DFR0_PMS_MASK) == 1) {
-		uint64_t v;
+	return (features & ID_AA64DFR0_PMS_MASK) == 1;
+}
 
-		if (el2_unused) {
-			/*
-			 * MDCR_EL2.TPMS (ARM v8.2): Do not trap statistical
-			 * profiling controls to EL2.
-			 *
-			 * MDCR_EL2.E2PB (ARM v8.2): SPE enabled in Non-secure
-			 * state. Accesses to profiling buffer controls at
-			 * Non-secure EL1 are not trapped to EL2.
-			 */
-			v = read_mdcr_el2();
-			v &= ~MDCR_EL2_TPMS;
-			v |= MDCR_EL2_E2PB(MDCR_EL2_E2PB_EL1);
-			write_mdcr_el2(v);
-		}
+void spe_enable(int el2_unused)
+{
+	uint64_t v;
 
+	if (spe_supported() == 0)
+		return;
+
+	if (el2_unused) {
 		/*
-		 * MDCR_EL2.NSPB (ARM v8.2): SPE enabled in Non-secure state
-		 * and disabled in secure state. Accesses to SPE registers at
-		 * S-EL1 generate trap exceptions to EL3.
+		 * MDCR_EL2.TPMS (ARM v8.2): Do not trap statistical
+		 * profiling controls to EL2.
+		 *
+		 * MDCR_EL2.E2PB (ARM v8.2): SPE enabled in Non-secure
+		 * state. Accesses to profiling buffer controls at
+		 * Non-secure EL1 are not trapped to EL2.
 		 */
-		v = read_mdcr_el3();
-		v |= MDCR_NSPB(MDCR_NSPB_EL1);
-		write_mdcr_el3(v);
+		v = read_mdcr_el2();
+		v &= ~MDCR_EL2_TPMS;
+		v |= MDCR_EL2_E2PB(MDCR_EL2_E2PB_EL1);
+		write_mdcr_el2(v);
 	}
+
+	/*
+	 * MDCR_EL2.NSPB (ARM v8.2): SPE enabled in Non-secure state
+	 * and disabled in secure state. Accesses to SPE registers at
+	 * S-EL1 generate trap exceptions to EL3.
+	 */
+	v = read_mdcr_el3();
+	v |= MDCR_NSPB(MDCR_NSPB_EL1);
+	write_mdcr_el3(v);
 }
 
 void spe_disable(void)
 {
-	uint64_t features;
+	uint64_t v;
 
-	features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMS_SHIFT;
-	if ((features & ID_AA64DFR0_PMS_MASK) == 1) {
-		uint64_t v;
+	if (spe_supported() == 0)
+		return;
 
-		/* Drain buffered data */
-		psb_csync();
-		dsbnsh();
+	/* Drain buffered data */
+	psb_csync();
+	dsbnsh();
 
-		/* Disable profiling buffer */
-		v = read_pmblimitr_el1();
-		v &= ~(1ULL << 0);
-		write_pmblimitr_el1(v);
-		isb();
-	}
+	/* Disable profiling buffer */
+	v = read_pmblimitr_el1();
+	v &= ~(1ULL << 0);
+	write_pmblimitr_el1(v);
+	isb();
 }
 
 static void *spe_drain_buffers_hook(const void *arg)
 {
-	uint64_t features;
+	if (spe_supported() == 0)
+		return (void *)-1;
 
-	features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMS_SHIFT;
-	if ((features & ID_AA64DFR0_PMS_MASK) == 1) {
-		/* Drain buffered data */
-		psb_csync();
-		dsbnsh();
-	}
-
+	/* Drain buffered data */
+	psb_csync();
+	dsbnsh();
 	return 0;
 }
 
diff --git a/lib/extensions/sve/sve.c b/lib/extensions/sve/sve.c
index 14e51bd..6442487 100644
--- a/lib/extensions/sve/sve.c
+++ b/lib/extensions/sve/sve.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,117 +9,120 @@
 #include <pubsub.h>
 #include <sve.h>
 
-static void *disable_sve_hook(const void *arg)
+int sve_supported(void)
 {
 	uint64_t features;
 
 	features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT;
-	if ((features & ID_AA64PFR0_SVE_MASK) == 1) {
-		uint64_t cptr;
+	return (features & ID_AA64PFR0_SVE_MASK) == 1;
+}
 
-		/*
-		 * Disable SVE, SIMD and FP access for the Secure world.
-		 * As the SIMD/FP registers are part of the SVE Z-registers, any
-		 * use of SIMD/FP functionality will corrupt the SVE registers.
-		 * Therefore it is necessary to prevent use of SIMD/FP support
-		 * in the Secure world as well as SVE functionality.
-		 */
-		cptr = read_cptr_el3();
-		cptr = (cptr | TFP_BIT) & ~(CPTR_EZ_BIT);
-		write_cptr_el3(cptr);
+static void *disable_sve_hook(const void *arg)
+{
+	uint64_t cptr;
 
-		/*
-		 * No explicit ISB required here as ERET to switch to Secure
-		 * world covers it
-		 */
-	}
+	if (sve_supported() == 0)
+		return (void *)-1;
+
+	/*
+	 * Disable SVE, SIMD and FP access for the Secure world.
+	 * As the SIMD/FP registers are part of the SVE Z-registers, any
+	 * use of SIMD/FP functionality will corrupt the SVE registers.
+	 * Therefore it is necessary to prevent use of SIMD/FP support
+	 * in the Secure world as well as SVE functionality.
+	 */
+	cptr = read_cptr_el3();
+	cptr = (cptr | TFP_BIT) & ~(CPTR_EZ_BIT);
+	write_cptr_el3(cptr);
+
+	/*
+	 * No explicit ISB required here as ERET to switch to Secure
+	 * world covers it
+	 */
 	return 0;
 }
 
 static void *enable_sve_hook(const void *arg)
 {
-	uint64_t features;
+	uint64_t cptr;
 
-	features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT;
-	if ((features & ID_AA64PFR0_SVE_MASK) == 1) {
-		uint64_t cptr;
+	if (sve_supported() == 0)
+		return (void *)-1;
 
-		/*
-		 * Enable SVE, SIMD and FP access for the Non-secure world.
-		 */
-		cptr = read_cptr_el3();
-		cptr = (cptr | CPTR_EZ_BIT) & ~(TFP_BIT);
-		write_cptr_el3(cptr);
+	/*
+	 * Enable SVE, SIMD and FP access for the Non-secure world.
+	 */
+	cptr = read_cptr_el3();
+	cptr = (cptr | CPTR_EZ_BIT) & ~(TFP_BIT);
+	write_cptr_el3(cptr);
 
-		/*
-		 * No explicit ISB required here as ERET to switch to Non-secure
-		 * world covers it
-		 */
-	}
+	/*
+	 * No explicit ISB required here as ERET to switch to Non-secure
+	 * world covers it
+	 */
 	return 0;
 }
 
 void sve_enable(int el2_unused)
 {
-	uint64_t features;
+	uint64_t cptr;
 
-	features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT;
-	if ((features & ID_AA64PFR0_SVE_MASK) == 1) {
-		uint64_t cptr;
+	if (sve_supported() == 0)
+		return;
+
 #if CTX_INCLUDE_FPREGS
-		/*
-		 * CTX_INCLUDE_FPREGS is not supported on SVE enabled systems.
-		 */
-		assert(0);
+	/*
+	 * CTX_INCLUDE_FPREGS is not supported on SVE enabled systems.
+	 */
+	assert(0);
 #endif
-		/*
-		 * Update CPTR_EL3 to enable access to SVE functionality for the
-		 * Non-secure world.
-		 * NOTE - assumed that CPTR_EL3.TFP is set to allow access to
-		 * the SIMD, floating-point and SVE support.
-		 *
-		 * CPTR_EL3.EZ: Set to 1 to enable access to SVE  functionality
-		 *  in the Non-secure world.
-		 */
-		cptr = read_cptr_el3();
-		cptr |= CPTR_EZ_BIT;
-		write_cptr_el3(cptr);
+	/*
+	 * Update CPTR_EL3 to enable access to SVE functionality for the
+	 * Non-secure world.
+	 * NOTE - assumed that CPTR_EL3.TFP is set to allow access to
+	 * the SIMD, floating-point and SVE support.
+	 *
+	 * CPTR_EL3.EZ: Set to 1 to enable access to SVE  functionality
+	 *  in the Non-secure world.
+	 */
+	cptr = read_cptr_el3();
+	cptr |= CPTR_EZ_BIT;
+	write_cptr_el3(cptr);
 
+	/*
+	 * Need explicit ISB here to guarantee that update to ZCR_ELx
+	 * and CPTR_EL2.TZ do not result in trap to EL3.
+	 */
+	isb();
+
+	/*
+	 * Ensure lower ELs have access to full vector length.
+	 */
+	write_zcr_el3(ZCR_EL3_LEN_MASK);
+
+	if (el2_unused) {
 		/*
-		 * Need explicit ISB here to guarantee that update to ZCR_ELx
-		 * and CPTR_EL2.TZ do not result in trap to EL3.
+		 * Update CPTR_EL2 to enable access to SVE functionality
+		 * for Non-secure world, EL2 and Non-secure EL1 and EL0.
+		 * NOTE - assumed that CPTR_EL2.TFP is set to allow
+		 * access to the SIMD, floating-point and SVE support.
+		 *
+		 * CPTR_EL2.TZ: Set to 0 to enable access to SVE support
+		 *  for EL2 and Non-secure EL1 and EL0.
 		 */
-		isb();
+		cptr = read_cptr_el2();
+		cptr &= ~(CPTR_EL2_TZ_BIT);
+		write_cptr_el2(cptr);
 
 		/*
 		 * Ensure lower ELs have access to full vector length.
 		 */
-		write_zcr_el3(ZCR_EL3_LEN_MASK);
-
-		if (el2_unused) {
-			/*
-			 * Update CPTR_EL2 to enable access to SVE functionality
-			 * for Non-secure world, EL2 and Non-secure EL1 and EL0.
-			 * NOTE - assumed that CPTR_EL2.TFP is set to allow
-			 * access to the SIMD, floating-point and SVE support.
-			 *
-			 * CPTR_EL2.TZ: Set to 0 to enable access to SVE support
-			 *  for EL2 and Non-secure EL1 and EL0.
-			 */
-			cptr = read_cptr_el2();
-			cptr &= ~(CPTR_EL2_TZ_BIT);
-			write_cptr_el2(cptr);
-
-			/*
-			 * Ensure lower ELs have access to full vector length.
-			 */
-			write_zcr_el2(ZCR_EL2_LEN_MASK);
-		}
-		/*
-		 * No explicit ISB required here as ERET to switch to
-		 * Non-secure world covers it.
-		 */
+		write_zcr_el2(ZCR_EL2_LEN_MASK);
 	}
+	/*
+	 * No explicit ISB required here as ERET to switch to
+	 * Non-secure world covers it.
+	 */
 }
 
 SUBSCRIBE_TO_EVENT(cm_exited_normal_world, disable_sve_hook);
diff --git a/lib/psci/aarch32/psci_helpers.S b/lib/psci/aarch32/psci_helpers.S
index 9373d4f..a29a29c 100644
--- a/lib/psci/aarch32/psci_helpers.S
+++ b/lib/psci/aarch32/psci_helpers.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -91,6 +91,28 @@
 	stcopr	r0, SCTLR
 	isb
 
+#if PLAT_XLAT_TABLES_DYNAMIC
+	/* ---------------------------------------------
+	 * During warm boot the MMU is enabled with data
+	 * cache disabled, then the interconnect is set
+	 * up and finally the data cache is enabled.
+	 *
+	 * During this period, if another CPU modifies
+	 * the translation tables, the MMU table walker
+	 * may read the old entries. This is only a
+	 * problem for dynamic regions, the warm boot
+	 * code isn't affected because it is static.
+	 *
+	 * Invalidate all TLB entries loaded while the
+	 * CPU wasn't coherent with the rest of the
+	 * system.
+	 * ---------------------------------------------
+	 */
+	stcopr	r0, TLBIALL
+	dsb	ish
+	isb
+#endif
+
 	pop	{r12, pc}
 endfunc psci_do_pwrup_cache_maintenance
 
diff --git a/lib/psci/aarch64/psci_helpers.S b/lib/psci/aarch64/psci_helpers.S
index afe21eb..d37ca76 100644
--- a/lib/psci/aarch64/psci_helpers.S
+++ b/lib/psci/aarch64/psci_helpers.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -115,6 +115,28 @@
 	msr	sctlr_el3, x0
 	isb
 
+#if PLAT_XLAT_TABLES_DYNAMIC
+	/* ---------------------------------------------
+	 * During warm boot the MMU is enabled with data
+	 * cache disabled, then the interconnect is set
+	 * up and finally the data cache is enabled.
+	 *
+	 * During this period, if another CPU modifies
+	 * the translation tables, the MMU table walker
+	 * may read the old entries. This is only a
+	 * problem for dynamic regions, the warm boot
+	 * code isn't affected because it is static.
+	 *
+	 * Invalidate all TLB entries loaded while the
+	 * CPU wasn't coherent with the rest of the
+	 * system.
+	 * ---------------------------------------------
+	 */
+	tlbi	alle3
+	dsb	ish
+	isb
+#endif
+
 	ldp	x29, x30, [sp], #16
 	ret
 endfunc psci_do_pwrup_cache_maintenance
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 6857c1f..8b913fb 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -182,7 +182,9 @@
 ENABLE_AMU			:=	1
 
 ifeq (${ENABLE_AMU},1)
-BL31_SOURCES		+= lib/cpus/aarch64/cortex_a75_pubsub.c
+BL31_SOURCES		+=	lib/cpus/aarch64/cortex_a75_pubsub.c	\
+				lib/cpus/aarch64/cpuamu.c		\
+				lib/cpus/aarch64/cpuamu_helpers.S
 endif
 
 ifneq (${ENABLE_STACK_PROTECTOR},0)
diff --git a/plat/mediatek/mt6795/bl31.ld.S b/plat/mediatek/mt6795/bl31.ld.S
index eacb1b2..0fbd3f7 100644
--- a/plat/mediatek/mt6795/bl31.ld.S
+++ b/plat/mediatek/mt6795/bl31.ld.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -132,7 +132,8 @@
     /*
      * The xlat_table section is for full, aligned page tables (4K).
      * Removing them from .bss avoids forcing 4K alignment on
-     * the .bss section and eliminates the unecessary zero init
+     * the .bss section. The tables are initialized to zero by the translation
+     * tables library.
      */
     xlat_table (NOLOAD) : {
         *(xlat_table)
diff --git a/services/spd/tspd/tspd_main.c b/services/spd/tspd/tspd_main.c
index c564f8b..3d06e0b 100644
--- a/services/spd/tspd/tspd_main.c
+++ b/services/spd/tspd/tspd_main.c
@@ -549,9 +549,10 @@
 				 * preempt Secure execution. However, for
 				 * yielding SMCs, we want preemption to happen;
 				 * so explicitly allow NS preemption in this
-				 * case.
+				 * case, and supply the preemption return code
+				 * for TSP.
 				 */
-				ehf_allow_ns_preemption();
+				ehf_allow_ns_preemption(TSP_PREEMPTED);
 #endif
 			}
 
@@ -662,9 +663,10 @@
 #if EL3_EXCEPTION_HANDLING
 		/*
 		 * Allow the resumed yielding SMC processing to be preempted by
-		 * Non-secure interrupts.
+		 * Non-secure interrupts. Also, supply the preemption return
+		 * code for TSP.
 		 */
-		ehf_allow_ns_preemption();
+		ehf_allow_ns_preemption(TSP_PREEMPTED);
 #endif
 
 		/* We just need to return to the preempted point in
diff --git a/services/std_svc/sdei/sdei_intr_mgmt.c b/services/std_svc/sdei/sdei_intr_mgmt.c
index 42bf46d..2717ea4 100644
--- a/services/std_svc/sdei/sdei_intr_mgmt.c
+++ b/services/std_svc/sdei/sdei_intr_mgmt.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -556,7 +556,7 @@
 	unsigned int client_el = sdei_client_el();
 
 	/* Return error if called without an active event */
-	disp_ctx = pop_dispatch();
+	disp_ctx = get_outstanding_dispatch();
 	if (!disp_ctx)
 		return SDEI_EDENY;
 
@@ -566,15 +566,8 @@
 
 	map = disp_ctx->map;
 	assert(map);
-
 	se = get_event_entry(map);
 
-	SDEI_LOG("EOI:%lx, %d spsr:%lx elr:%lx\n", read_mpidr_el1(),
-			map->ev_num, read_spsr_el3(), read_elr_el3());
-
-	if (is_event_shared(map))
-		sdei_map_lock(map);
-
 	act = resume ? DO_COMPLETE_RESUME : DO_COMPLETE;
 	if (!can_sdei_state_trans(se, act)) {
 		if (is_event_shared(map))
@@ -582,6 +575,15 @@
 		return SDEI_EDENY;
 	}
 
+	/* Having done sanity checks, pop dispatch */
+	pop_dispatch();
+
+	SDEI_LOG("EOI:%lx, %d spsr:%lx elr:%lx\n", read_mpidr_el1(),
+			map->ev_num, read_spsr_el3(), read_elr_el3());
+
+	if (is_event_shared(map))
+		sdei_map_lock(map);
+
 	/*
 	 * Restore Non-secure to how it was originally interrupted. Once done,
 	 * it's up-to-date with the saved copy.