Merge pull request #1221 from hzhuang1/fix_HLE

emmc/dw_mmc: fix the assert on HLE bit
diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S
index d8fbb9b..9b7735f 100644
--- a/bl31/aarch64/runtime_exceptions.S
+++ b/bl31/aarch64/runtime_exceptions.S
@@ -14,6 +14,26 @@
 
 	.globl	runtime_exceptions
 
+	.globl	sync_exception_sp_el0
+	.globl	irq_sp_el0
+	.globl	fiq_sp_el0
+	.globl	serror_sp_el0
+
+	.globl	sync_exception_sp_elx
+	.globl	irq_sp_elx
+	.globl	fiq_sp_elx
+	.globl	serror_sp_elx
+
+	.globl	sync_exception_aarch64
+	.globl	irq_aarch64
+	.globl	fiq_aarch64
+	.globl	serror_aarch64
+
+	.globl	sync_exception_aarch32
+	.globl	irq_aarch32
+	.globl	fiq_aarch32
+	.globl	serror_aarch32
+
 	/* ---------------------------------------------------------------------
 	 * This macro handles Synchronous exceptions.
 	 * Only SMC exceptions are supported.
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index fdcc931..2db4856 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -51,13 +51,19 @@
 endif
 
 ifeq (${ENABLE_AMU},1)
-BL31_SOURCES		+=	lib/extensions/amu/aarch64/amu.c
+BL31_SOURCES		+=	lib/extensions/amu/aarch64/amu.c		\
+				lib/extensions/amu/aarch64/amu_helpers.S
 endif
 
 ifeq (${ENABLE_SVE_FOR_NS},1)
 BL31_SOURCES		+=	lib/extensions/sve/sve.c
 endif
 
+ifeq (${WORKAROUND_CVE_2017_5715},1)
+BL31_SOURCES		+=	lib/cpus/aarch64/workaround_cve_2017_5715_mmu.S		\
+				lib/cpus/aarch64/workaround_cve_2017_5715_bpiall.S
+endif
+
 BL31_LINKERFILE		:=	bl31/bl31.ld.S
 
 # Flag used to indicate if Crash reporting via console should be included
diff --git a/docs/cpu-specific-build-macros.rst b/docs/cpu-specific-build-macros.rst
index f74b459..014817d 100644
--- a/docs/cpu-specific-build-macros.rst
+++ b/docs/cpu-specific-build-macros.rst
@@ -11,6 +11,15 @@
 operations framework to enable errata workarounds and to enable optimizations
 for a specific CPU on a platform.
 
+Security Vulnerability Workarounds
+----------------------------------
+
+ARM Trusted Firmware exports a series of build flags which control which
+security vulnerability workarounds should be applied at runtime.
+
+-  ``WORKAROUND_CVE_2017_5715``: Enables the security workaround for
+   `CVE-2017-5715`_. Defaults to 1.
+
 CPU Errata Workarounds
 ----------------------
 
@@ -142,6 +151,7 @@
 
 *Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.*
 
+.. _CVE-2017-5715: http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=2017-5715
 .. _Cortex-A53 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm048406/Cortex_A53_MPCore_Software_Developers_Errata_Notice.pdf
 .. _Cortex-A57 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm049219/cortex_a57_mpcore_software_developers_errata_notice.pdf
 .. _Cortex-A72 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm012079/index.html
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index f020ec9..2e2cc4f 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -549,6 +549,22 @@
    doesn't print anything to the console. If ``PLAT_LOG_LEVEL_ASSERT`` isn't
    defined, it defaults to ``LOG_LEVEL``.
 
+If the platform port uses the Activity Monitor Unit, the following constants
+may be defined:
+
+-  **PLAT\_AMU\_GROUP1\_COUNTERS\_MASK**
+   This mask reflects the set of group counters that should be enabled.  The
+   maximum number of group 1 counters supported by AMUv1 is 16 so the mask
+   can be at most 0xffff. If the platform does not define this mask, no group 1
+   counters are enabled. If the platform defines this mask, the following
+   constant needs to also be defined.
+
+-  **PLAT\_AMU\_GROUP1\_NR\_COUNTERS**
+   This value is used to allocate an array to save and restore the counters
+   specified by ``PLAT_AMU_GROUP1_COUNTERS_MASK`` on CPU suspend.
+   This value should be equal to the highest bit position set in the
+   mask, plus 1.  The maximum number of group 1 counters in AMUv1 is 16.
+
 File : plat\_macros.S [mandatory]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -1128,6 +1144,9 @@
 for performing any remaining platform-specific setup that can occur after the
 MMU and data cache have been enabled.
 
+if support for multiple boot sources is required, it initializes the boot
+sequence used by plat\_try\_next\_boot\_source().
+
 In ARM standard platforms, this function initializes the storage abstraction
 layer used to load the next bootloader image.
 
diff --git a/include/bl32/payloads/tlk.h b/include/bl32/payloads/tlk.h
index 4e06bcd..941b6cc 100644
--- a/include/bl32/payloads/tlk.h
+++ b/include/bl32/payloads/tlk.h
@@ -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
  */
@@ -20,6 +20,7 @@
  */
 #define TLK_REGISTER_LOGBUF	TLK_TOS_YIELD_FID(0x1)
 #define TLK_REGISTER_REQBUF	TLK_TOS_YIELD_FID(0x2)
+#define TLK_REGISTER_NS_DRAM	TLK_TOS_YIELD_FID(0x4)
 #define TLK_RESUME_FID		TLK_TOS_YIELD_FID(0x100)
 #define TLK_SYSTEM_SUSPEND	TLK_TOS_YIELD_FID(0xE001)
 #define TLK_SYSTEM_RESUME	TLK_TOS_YIELD_FID(0xE002)
diff --git a/include/common/aarch64/el3_common_macros.S b/include/common/aarch64/el3_common_macros.S
index 63a0fa7..defd4a2 100644
--- a/include/common/aarch64/el3_common_macros.S
+++ b/include/common/aarch64/el3_common_macros.S
@@ -13,7 +13,7 @@
 	/*
 	 * Helper macro to initialise EL3 registers we care about.
 	 */
-	.macro el3_arch_init_common _exception_vectors
+	.macro el3_arch_init_common
 	/* ---------------------------------------------------------------------
 	 * SCTLR_EL3 has already been initialised - read current value before
 	 * modifying.
@@ -50,14 +50,6 @@
 #endif /* IMAGE_BL31 */
 
 	/* ---------------------------------------------------------------------
-	 * Set the exception vectors.
-	 * ---------------------------------------------------------------------
-	 */
-	adr	x0, \_exception_vectors
-	msr	vbar_el3, x0
-	isb
-
-	/* ---------------------------------------------------------------------
 	 * Initialise SCR_EL3, setting all fields rather than relying on hw.
 	 * All fields are architecturally UNKNOWN on reset. The following fields
 	 * do not change during the TF lifetime. The remaining fields are set to
@@ -221,6 +213,14 @@
 	.endif /* _warm_boot_mailbox */
 
 	/* ---------------------------------------------------------------------
+	 * Set the exception vectors.
+	 * ---------------------------------------------------------------------
+	 */
+	adr	x0, \_exception_vectors
+	msr	vbar_el3, x0
+	isb
+
+	/* ---------------------------------------------------------------------
 	 * It is a cold boot.
 	 * Perform any processor specific actions upon reset e.g. cache, TLB
 	 * invalidations etc.
@@ -228,7 +228,7 @@
 	 */
 	bl	reset_handler
 
-	el3_arch_init_common \_exception_vectors
+	el3_arch_init_common
 
 	.if \_secondary_cold_boot
 		/* -------------------------------------------------------------
diff --git a/include/lib/aarch32/arch_helpers.h b/include/lib/aarch32/arch_helpers.h
index 0230195..beae5d0 100644
--- a/include/lib/aarch32/arch_helpers.h
+++ b/include/lib/aarch32/arch_helpers.h
@@ -287,6 +287,11 @@
 DEFINE_COPROCR_RW_FUNCS(amcntenclr0, AMCNTENCLR0)
 DEFINE_COPROCR_RW_FUNCS(amcntenclr1, AMCNTENCLR1)
 
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr00, AMEVCNTR00)
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr01, AMEVCNTR01)
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr02, AMEVCNTR02)
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr03, AMEVCNTR03)
+
 /*
  * TLBI operation prototypes
  */
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index 96e2d5f..91aa484 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -117,6 +117,9 @@
 #define ID_AA64PFR0_SVE_SHIFT	U(32)
 #define ID_AA64PFR0_SVE_MASK	U(0xf)
 #define ID_AA64PFR0_SVE_LENGTH	U(4)
+#define ID_AA64PFR0_CSV2_SHIFT	U(56)
+#define ID_AA64PFR0_CSV2_MASK	U(0xf)
+#define ID_AA64PFR0_CSV2_LENGTH	U(4)
 
 /* ID_AA64DFR0_EL1.PMS definitions (for ARMv8.2+) */
 #define ID_AA64DFR0_PMS_SHIFT	U(32)
@@ -337,6 +340,11 @@
 #define SPSR_T_ARM		U(0x0)
 #define SPSR_T_THUMB		U(0x1)
 
+#define SPSR_M_SHIFT		U(4)
+#define SPSR_M_MASK		U(0x1)
+#define SPSR_M_AARCH64		U(0x0)
+#define SPSR_M_AARCH32		U(0x1)
+
 #define DISABLE_ALL_EXCEPTIONS \
 		(DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT | DAIF_DBG_BIT)
 
@@ -656,4 +664,45 @@
 #define AMEVTYPER02_EL0		S3_3_C13_C6_2
 #define AMEVTYPER03_EL0		S3_3_C13_C6_3
 
+/* Activity Monitor Group 1 Event Counter Registers */
+#define AMEVCNTR10_EL0		S3_3_C13_C12_0
+#define AMEVCNTR11_EL0		S3_3_C13_C12_1
+#define AMEVCNTR12_EL0		S3_3_C13_C12_2
+#define AMEVCNTR13_EL0		S3_3_C13_C12_3
+#define AMEVCNTR14_EL0		S3_3_C13_C12_4
+#define AMEVCNTR15_EL0		S3_3_C13_C12_5
+#define AMEVCNTR16_EL0		S3_3_C13_C12_6
+#define AMEVCNTR17_EL0		S3_3_C13_C12_7
+#define AMEVCNTR18_EL0		S3_3_C13_C13_0
+#define AMEVCNTR19_EL0		S3_3_C13_C13_1
+#define AMEVCNTR1A_EL0		S3_3_C13_C13_2
+#define AMEVCNTR1B_EL0		S3_3_C13_C13_3
+#define AMEVCNTR1C_EL0		S3_3_C13_C13_4
+#define AMEVCNTR1D_EL0		S3_3_C13_C13_5
+#define AMEVCNTR1E_EL0		S3_3_C13_C13_6
+#define AMEVCNTR1F_EL0		S3_3_C13_C13_7
+
+/* Activity Monitor Group 1 Event Type Registers */
+#define AMEVTYPER10_EL0		S3_3_C13_C14_0
+#define AMEVTYPER11_EL0		S3_3_C13_C14_1
+#define AMEVTYPER12_EL0		S3_3_C13_C14_2
+#define AMEVTYPER13_EL0		S3_3_C13_C14_3
+#define AMEVTYPER14_EL0		S3_3_C13_C14_4
+#define AMEVTYPER15_EL0		S3_3_C13_C14_5
+#define AMEVTYPER16_EL0		S3_3_C13_C14_6
+#define AMEVTYPER17_EL0		S3_3_C13_C14_7
+#define AMEVTYPER18_EL0		S3_3_C13_C15_0
+#define AMEVTYPER19_EL0		S3_3_C13_C15_1
+#define AMEVTYPER1A_EL0		S3_3_C13_C15_2
+#define AMEVTYPER1B_EL0		S3_3_C13_C15_3
+#define AMEVTYPER1C_EL0		S3_3_C13_C15_4
+#define AMEVTYPER1D_EL0		S3_3_C13_C15_5
+#define AMEVTYPER1E_EL0		S3_3_C13_C15_6
+#define AMEVTYPER1F_EL0		S3_3_C13_C15_7
+
+/* AMCGCR_EL0 definitions */
+#define AMCGCR_EL0_CG1NC_SHIFT	U(8)
+#define AMCGCR_EL0_CG1NC_LENGTH	U(8)
+#define AMCGCR_EL0_CG1NC_MASK	U(0xff)
+
 #endif /* __ARCH_H__ */
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index 831dfb0..485ed43 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -322,6 +322,7 @@
 DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_eoir1_el1, ICC_EOIR1_EL1)
 DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_sgi0r_el1, ICC_SGI0R_EL1)
 
+DEFINE_RENAME_SYSREG_RW_FUNCS(amcgcr_el0, AMCGCR_EL0)
 DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr0_el0, AMCNTENCLR0_EL0)
 DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset0_el0, AMCNTENSET0_EL0)
 DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr1_el0, AMCNTENCLR1_EL0)
diff --git a/include/lib/cpus/aarch64/cortex_a75.h b/include/lib/cpus/aarch64/cortex_a75.h
index d68c957..940125d 100644
--- a/include/lib/cpus/aarch64/cortex_a75.h
+++ b/include/lib/cpus/aarch64/cortex_a75.h
@@ -50,7 +50,19 @@
  * 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)
 
+#ifndef __ASSEMBLY__
+#include <stdint.h>
+
+uint64_t cortex_a75_amu_cnt_read(int idx);
+void cortex_a75_amu_cnt_write(int idx, uint64_t val);
+unsigned int cortex_a75_amu_read_cpuamcntenset_el0(void);
+unsigned int cortex_a75_amu_read_cpuamcntenclr_el0(void);
+void cortex_a75_amu_write_cpuamcntenset_el0(unsigned int mask);
+void cortex_a75_amu_write_cpuamcntenclr_el0(unsigned int mask);
+#endif /* __ASSEMBLY__ */
+
 #endif /* __CORTEX_A75_H__ */
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index 5889904..5e212ec 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -46,12 +46,26 @@
 #define CTX_GPREG_SP_EL0	U(0xf8)
 #define CTX_GPREGS_END		U(0x100)
 
+#if WORKAROUND_CVE_2017_5715
+#define CTX_CVE_2017_5715_OFFSET	(CTX_GPREGS_OFFSET + CTX_GPREGS_END)
+#define CTX_CVE_2017_5715_QUAD0		U(0x0)
+#define CTX_CVE_2017_5715_QUAD1		U(0x8)
+#define	CTX_CVE_2017_5715_QUAD2		U(0x10)
+#define CTX_CVE_2017_5715_QUAD3		U(0x18)
+#define CTX_CVE_2017_5715_QUAD4		U(0x20)
+#define CTX_CVE_2017_5715_QUAD5		U(0x28)
+#define CTX_CVE_2017_5715_END		U(0x30)
+#else
+#define CTX_CVE_2017_5715_OFFSET	CTX_GPREGS_OFFSET
+#define CTX_CVE_2017_5715_END		CTX_GPREGS_END
+#endif
+
 /*******************************************************************************
  * Constants that allow assembler code to access members of and the 'el3_state'
  * structure at their correct offsets. Note that some of the registers are only
  * 32-bits wide but are stored as 64-bit values for convenience
  ******************************************************************************/
-#define CTX_EL3STATE_OFFSET	(CTX_GPREGS_OFFSET + CTX_GPREGS_END)
+#define CTX_EL3STATE_OFFSET	(CTX_CVE_2017_5715_OFFSET + CTX_CVE_2017_5715_END)
 #define CTX_SCR_EL3		U(0x0)
 #define CTX_RUNTIME_SP		U(0x8)
 #define CTX_SPSR_EL3		U(0x10)
@@ -186,6 +200,9 @@
 
 /* Constants to determine the size of individual context structures */
 #define CTX_GPREG_ALL		(CTX_GPREGS_END >> DWORD_SHIFT)
+#if WORKAROUND_CVE_2017_5715
+#define CTX_CVE_2017_5715_ALL	(CTX_CVE_2017_5715_END >> DWORD_SHIFT)
+#endif
 #define CTX_SYSREG_ALL		(CTX_SYSREGS_END >> DWORD_SHIFT)
 #if CTX_INCLUDE_FPREGS
 #define CTX_FPREG_ALL		(CTX_FPREGS_END >> DWORD_SHIFT)
@@ -201,6 +218,10 @@
  */
 DEFINE_REG_STRUCT(gp_regs, CTX_GPREG_ALL);
 
+#if WORKAROUND_CVE_2017_5715
+DEFINE_REG_STRUCT(cve_2017_5715_regs, CTX_CVE_2017_5715_ALL);
+#endif
+
 /*
  * AArch64 EL1 system register context structure for preserving the
  * architectural state during switches from one security state to
@@ -242,6 +263,9 @@
  */
 typedef struct cpu_context {
 	gp_regs_t gpregs_ctx;
+#if WORKAROUND_CVE_2017_5715
+	cve_2017_5715_regs_t cve_2017_5715_regs_ctx;
+#endif
 	el3_state_t el3state_ctx;
 	el1_sys_regs_t sysregs_ctx;
 #if CTX_INCLUDE_FPREGS
diff --git a/include/lib/el3_runtime/pubsub_events.h b/include/lib/el3_runtime/pubsub_events.h
index 9cfedb4..64b3f63 100644
--- a/include/lib/el3_runtime/pubsub_events.h
+++ b/include/lib/el3_runtime/pubsub_events.h
@@ -17,6 +17,13 @@
  */
 REGISTER_PUBSUB_EVENT(psci_cpu_on_finish);
 
+/*
+ * These events are published before/after a CPU has been powered down/up
+ * via the PSCI CPU SUSPEND API.
+ */
+REGISTER_PUBSUB_EVENT(psci_suspend_pwrdown_start);
+REGISTER_PUBSUB_EVENT(psci_suspend_pwrdown_finish);
+
 #ifdef AARCH64
 /*
  * These events are published by the AArch64 context management framework
diff --git a/include/lib/extensions/amu.h b/include/lib/extensions/amu.h
index bbefe8f..faa0ee1 100644
--- a/include/lib/extensions/amu.h
+++ b/include/lib/extensions/amu.h
@@ -7,9 +7,39 @@
 #ifndef __AMU_H__
 #define __AMU_H__
 
-/* Enable all group 0 counters */
+#include <sys/cdefs.h> /* for CASSERT() */
+#include <cassert.h>
+#include <platform_def.h>
+#include <stdint.h>
+
+/* All group 0 counters */
 #define AMU_GROUP0_COUNTERS_MASK	0xf
 
+#ifdef PLAT_AMU_GROUP1_COUNTERS_MASK
+#define AMU_GROUP1_COUNTERS_MASK	PLAT_AMU_GROUP1_COUNTERS_MASK
+#else
+#define AMU_GROUP1_COUNTERS_MASK	0
+#endif
+
+#ifdef PLAT_AMU_GROUP1_NR_COUNTERS
+#define AMU_GROUP1_NR_COUNTERS		PLAT_AMU_GROUP1_NR_COUNTERS
+#else
+#define AMU_GROUP1_NR_COUNTERS		0
+#endif
+
+CASSERT(AMU_GROUP1_COUNTERS_MASK <= 0xffff, invalid_amu_group1_counters_mask);
+CASSERT(AMU_GROUP1_NR_COUNTERS <= 16, invalid_amu_group1_nr_counters);
+
+int amu_supported(void);
 void amu_enable(int el2_unused);
 
+/* Group 0 configuration helpers */
+uint64_t amu_group0_cnt_read(int idx);
+void amu_group0_cnt_write(int idx, uint64_t val);
+
+/* Group 1 configuration helpers */
+uint64_t amu_group1_cnt_read(int idx);
+void amu_group1_cnt_write(int idx, uint64_t val);
+void amu_group1_set_evtype(int idx, unsigned int val);
+
 #endif /* __AMU_H__ */
diff --git a/include/lib/extensions/amu_private.h b/include/lib/extensions/amu_private.h
new file mode 100644
index 0000000..0c660bb
--- /dev/null
+++ b/include/lib/extensions/amu_private.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __AMU_PRIVATE_H__
+#define __AMU_PRIVATE_H__
+
+#include <stdint.h>
+
+uint64_t amu_group0_cnt_read_internal(int idx);
+void amu_group0_cnt_write_internal(int idx, uint64_t);
+
+uint64_t amu_group1_cnt_read_internal(int idx);
+void amu_group1_cnt_write_internal(int idx, uint64_t);
+void amu_group1_set_evtype_internal(int idx, unsigned int val);
+
+#endif /* __AMU_PRIVATE_H__ */
diff --git a/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h
index e0c3c86..888629e 100644
--- a/include/plat/arm/board/common/board_arm_def.h
+++ b/include/plat/arm/board/common/board_arm_def.h
@@ -90,7 +90,7 @@
  * PLAT_ARM_MAX_BL31_SIZE is calculated using the current BL31 debug size plus a
  * little space for growth.
  */
-#define PLAT_ARM_MAX_BL31_SIZE		0x1E000
+#define PLAT_ARM_MAX_BL31_SIZE		0x20000
 
 #ifdef AARCH32
 /*
diff --git a/include/services/mm_svc.h b/include/services/mm_svc.h
new file mode 100644
index 0000000..7a8a3eb
--- /dev/null
+++ b/include/services/mm_svc.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __MM_SVC_H__
+#define __MM_SVC_H__
+
+#include <utils_def.h>
+
+#define MM_VERSION_MAJOR	U(1)
+#define MM_VERSION_MAJOR_SHIFT	16
+#define MM_VERSION_MAJOR_MASK	U(0x7FFF)
+#define MM_VERSION_MINOR	U(0)
+#define MM_VERSION_MINOR_SHIFT	0
+#define MM_VERSION_MINOR_MASK	U(0xFFFF)
+#define MM_VERSION_FORM(major, minor)	((major << MM_VERSION_MAJOR_SHIFT) | (minor))
+#define MM_VERSION_COMPILED	MM_VERSION_FORM(MM_VERSION_MAJOR, MM_VERSION_MINOR)
+
+/*
+ * SMC IDs defined in [1] for accessing MM services from the Non-secure world.
+ * These FIDs occupy the range 0x40 - 0x5f.
+ * [1] DEN0060A_ARM_MM_Interface_Specification.pdf
+ */
+#define MM_VERSION_AARCH32		U(0x84000040)
+
+#define MM_COMMUNICATE_AARCH64		U(0xC4000041)
+#define MM_COMMUNICATE_AARCH32		U(0x84000041)
+
+#endif /* __MM_SVC_H__ */
diff --git a/include/services/spm_svc.h b/include/services/spm_svc.h
index 738979e..8f872c3 100644
--- a/include/services/spm_svc.h
+++ b/include/services/spm_svc.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
  */
@@ -10,15 +10,14 @@
 #include <utils_def.h>
 
 #define SPM_VERSION_MAJOR	U(0)
+#define SPM_VERSION_MAJOR_SHIFT	16
+#define SPM_VERSION_MAJOR_MASK	U(0x7FFF)
 #define SPM_VERSION_MINOR	U(1)
-#define SPM_VERSION_FORM(major, minor)	((major << 16) | (minor))
+#define SPM_VERSION_MINOR_SHIFT	0
+#define SPM_VERSION_MINOR_MASK	U(0xFFFF)
+#define SPM_VERSION_FORM(major, minor)	((major << SPM_VERSION_MAJOR_SHIFT) | (minor))
 #define SPM_VERSION_COMPILED	SPM_VERSION_FORM(SPM_VERSION_MAJOR, SPM_VERSION_MINOR)
 
-#define SP_VERSION_MAJOR	U(1)
-#define SP_VERSION_MINOR	U(0)
-#define SP_VERSION_FORM(major, minor)	((major << 16) | (minor))
-#define SP_VERSION_COMPILED	SP_VERSION_FORM(SP_VERSION_MAJOR, SP_VERSION_MINOR)
-
 /* The macros below are used to identify SPM calls from the SMC function ID */
 #define SPM_FID_MASK			U(0xffff)
 #define SPM_FID_MIN_VALUE		U(0x40)
@@ -31,6 +30,7 @@
  * SMC IDs defined for accessing services implemented by the Secure Partition
  * Manager from the Secure Partition(s). These services enable a partition to
  * handle delegated events and request privileged operations from the manager.
+ * They occupy the range 0x60-0x7f.
  */
 #define SPM_VERSION_AARCH32			U(0x84000060)
 #define SP_EVENT_COMPLETE_AARCH64		U(0xC4000061)
@@ -51,16 +51,6 @@
 #define SP_MEMORY_ATTRIBUTES_EXEC		(U(0) << 2)
 #define SP_MEMORY_ATTRIBUTES_NON_EXEC		(U(1) << 2)
 
-/*
- * SMC IDs defined in [1] for accessing secure partition services from the
- * Non-secure world. These FIDs occupy the range 0x40 - 0x5f
- * [1] DEN0060A_ARM_MM_Interface_Specification.pdf
- */
-#define SP_VERSION_AARCH64		U(0xC4000040)
-#define SP_VERSION_AARCH32		U(0x84000040)
-
-#define MM_COMMUNICATE_AARCH64		U(0xC4000041)
-#define MM_COMMUNICATE_AARCH32		U(0x84000041)
 
 /* SPM error codes. */
 #define SPM_SUCCESS		0
diff --git a/lib/cpus/aarch64/cortex_a57.S b/lib/cpus/aarch64/cortex_a57.S
index a720e98..683be47 100644
--- a/lib/cpus/aarch64/cortex_a57.S
+++ b/lib/cpus/aarch64/cortex_a57.S
@@ -383,6 +383,11 @@
 	bl	errata_a57_859972_wa
 #endif
 
+#if IMAGE_BL31 && WORKAROUND_CVE_2017_5715
+	adr	x0, workaround_mmu_runtime_exceptions
+	msr	vbar_el3, x0
+#endif
+
 	/* ---------------------------------------------
 	 * Enable the SMP bit.
 	 * ---------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a72.S b/lib/cpus/aarch64/cortex_a72.S
index b034125..93821b7 100644
--- a/lib/cpus/aarch64/cortex_a72.S
+++ b/lib/cpus/aarch64/cortex_a72.S
@@ -110,6 +110,12 @@
 	mov	x0, x18
 	bl	errata_a72_859971_wa
 #endif
+
+#if IMAGE_BL31 && WORKAROUND_CVE_2017_5715
+	adr	x0, workaround_mmu_runtime_exceptions
+	msr	vbar_el3, x0
+#endif
+
 	/* ---------------------------------------------
 	 * Enable the SMP bit.
 	 * ---------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a73.S b/lib/cpus/aarch64/cortex_a73.S
index f642816..c43f07e 100644
--- a/lib/cpus/aarch64/cortex_a73.S
+++ b/lib/cpus/aarch64/cortex_a73.S
@@ -36,6 +36,11 @@
 endfunc cortex_a73_disable_smp
 
 func cortex_a73_reset_func
+#if IMAGE_BL31 && WORKAROUND_CVE_2017_5715
+	adr	x0, workaround_bpiall_vbar0_runtime_exceptions
+	msr	vbar_el3, x0
+#endif
+
 	/* ---------------------------------------------
 	 * Enable the SMP bit.
 	 * Clobbers : x0
diff --git a/lib/cpus/aarch64/cortex_a75.S b/lib/cpus/aarch64/cortex_a75.S
index 4cab9e4..e66ad06 100644
--- a/lib/cpus/aarch64/cortex_a75.S
+++ b/lib/cpus/aarch64/cortex_a75.S
@@ -11,7 +11,120 @@
 #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
+
 func cortex_a75_reset_func
+#if IMAGE_BL31 && WORKAROUND_CVE_2017_5715
+	mrs	x0, id_aa64pfr0_el1
+	ubfx	x0, x0, #ID_AA64PFR0_CSV2_SHIFT, #ID_AA64PFR0_CSV2_LENGTH
+	/*
+	 * If the field equals to 1 then branch targets trained in one
+	 * context cannot affect speculative execution in a different context.
+	 */
+	cmp	x0, #1
+	beq	1f
+
+	adr	x0, workaround_bpiall_vbar0_runtime_exceptions
+	msr	vbar_el3, x0
+1:
+#endif
+
 #if ENABLE_AMU
 	/* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */
 	mrs	x0, actlr_el3
diff --git a/lib/cpus/aarch64/cortex_a75_pubsub.c b/lib/cpus/aarch64/cortex_a75_pubsub.c
new file mode 100644
index 0000000..c1089a6
--- /dev/null
+++ b/lib/cpus/aarch64/cortex_a75_pubsub.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <cortex_a75.h>
+#include <pubsub_events.h>
+#include <platform.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);
+
+	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);
+
+	return 0;
+}
+
+SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, cortex_a75_context_save);
+SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, cortex_a75_context_restore);
diff --git a/lib/cpus/aarch64/workaround_cve_2017_5715_bpiall.S b/lib/cpus/aarch64/workaround_cve_2017_5715_bpiall.S
new file mode 100644
index 0000000..cd29266
--- /dev/null
+++ b/lib/cpus/aarch64/workaround_cve_2017_5715_bpiall.S
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <context.h>
+
+	.globl	workaround_bpiall_vbar0_runtime_exceptions
+
+#define EMIT_BPIALL		0xee070fd5
+#define EMIT_MOV_R0_IMM(v)	0xe3a0000##v
+#define EMIT_SMC		0xe1600070
+
+	.macro	enter_workaround _stub_name
+	/* Save GP regs */
+	stp	x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
+	stp	x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
+	stp	x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4]
+	stp	x6, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X6]
+	stp	x8, x9, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X8]
+	stp	x10, x11, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X10]
+	stp	x12, x13, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X12]
+	stp	x14, x15, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X14]
+	stp	x16, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X16]
+	stp	x18, x19, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X18]
+	stp	x20, x21, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X20]
+	stp	x22, x23, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X22]
+	stp	x24, x25, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X24]
+	stp	x26, x27, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X26]
+	stp	x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28]
+
+	adr	x4, \_stub_name
+
+	/*
+	 * Load SPSR_EL3 and VBAR_EL3.  SPSR_EL3 is set up to have
+	 * all interrupts masked in preparation to running the workaround
+	 * stub in S-EL1.  VBAR_EL3 points to the vector table that
+	 * will handle the SMC back from the workaround stub.
+	 */
+	ldp	x0, x1, [x4, #0]
+
+	/*
+	 * Load SCTLR_EL1 and ELR_EL3.  SCTLR_EL1 is configured to disable
+	 * the MMU in S-EL1.  ELR_EL3 points to the appropriate stub in S-EL1.
+	 */
+	ldp	x2, x3, [x4, #16]
+
+	mrs	x4, scr_el3
+	mrs	x5, spsr_el3
+	mrs	x6, elr_el3
+	mrs	x7, sctlr_el1
+	mrs	x8, esr_el3
+
+	/* Preserve system registers in the workaround context */
+	stp	x4, x5, [sp, #CTX_CVE_2017_5715_OFFSET + CTX_CVE_2017_5715_QUAD0]
+	stp	x6, x7, [sp, #CTX_CVE_2017_5715_OFFSET + CTX_CVE_2017_5715_QUAD2]
+	stp	x8, x30, [sp, #CTX_CVE_2017_5715_OFFSET + CTX_CVE_2017_5715_QUAD4]
+
+	/*
+	 * Setting SCR_EL3 to all zeroes means that the NS, RW
+	 * and SMD bits are configured as expected.
+	 */
+	msr	scr_el3, xzr
+
+	/*
+	 * Reload system registers with the crafted values
+	 * in preparation for entry in S-EL1.
+	 */
+	msr	spsr_el3, x0
+	msr	vbar_el3, x1
+	msr	sctlr_el1, x2
+	msr	elr_el3, x3
+
+	eret
+	.endm
+
+	/* ---------------------------------------------------------------------
+	 * This vector table is used at runtime to enter the workaround at
+	 * AArch32 S-EL1 for Sync/IRQ/FIQ/SError exceptions.  If the workaround
+	 * is not enabled, the existing runtime exception vector table is used.
+	 * ---------------------------------------------------------------------
+	 */
+vector_base workaround_bpiall_vbar0_runtime_exceptions
+
+	/* ---------------------------------------------------------------------
+	 * Current EL with SP_EL0 : 0x0 - 0x200
+	 * ---------------------------------------------------------------------
+	 */
+vector_entry workaround_bpiall_vbar0_sync_exception_sp_el0
+	b	sync_exception_sp_el0
+	/*
+	 * Since each vector table entry is 128 bytes, we can store the
+	 * stub context in the unused space to minimize memory footprint.
+	 */
+aarch32_stub_smc:
+	.word	EMIT_BPIALL
+	.word	EMIT_MOV_R0_IMM(1)
+	.word	EMIT_SMC
+aarch32_stub_ctx_smc:
+	/* Mask all interrupts and set AArch32 Supervisor mode */
+	.quad	(SPSR_AIF_MASK << SPSR_AIF_SHIFT | \
+	         SPSR_M_AARCH32 << SPSR_M_SHIFT | \
+	         MODE32_svc << MODE32_SHIFT)
+
+	/*
+	 * VBAR_EL3 points to vbar1 which is the vector table
+	 * used while the workaround is executing.
+	 */
+	.quad	workaround_bpiall_vbar1_runtime_exceptions
+
+	/* Setup SCTLR_EL1 with MMU off and I$ on */
+	.quad	SCTLR_AARCH32_EL1_RES1 | SCTLR_I_BIT
+
+	/* ELR_EL3 is setup to point to the sync exception stub in AArch32 */
+	.quad	aarch32_stub_smc
+	check_vector_size workaround_bpiall_vbar0_sync_exception_sp_el0
+
+vector_entry workaround_bpiall_vbar0_irq_sp_el0
+	b	irq_sp_el0
+aarch32_stub_irq:
+	.word	EMIT_BPIALL
+	.word	EMIT_MOV_R0_IMM(2)
+	.word	EMIT_SMC
+aarch32_stub_ctx_irq:
+	.quad	(SPSR_AIF_MASK << SPSR_AIF_SHIFT | \
+	         SPSR_M_AARCH32 << SPSR_M_SHIFT | \
+	         MODE32_svc << MODE32_SHIFT)
+	.quad	workaround_bpiall_vbar1_runtime_exceptions
+	.quad	SCTLR_AARCH32_EL1_RES1 | SCTLR_I_BIT
+	.quad	aarch32_stub_irq
+	check_vector_size workaround_bpiall_vbar0_irq_sp_el0
+
+vector_entry workaround_bpiall_vbar0_fiq_sp_el0
+	b	fiq_sp_el0
+aarch32_stub_fiq:
+	.word	EMIT_BPIALL
+	.word	EMIT_MOV_R0_IMM(4)
+	.word	EMIT_SMC
+aarch32_stub_ctx_fiq:
+	.quad	(SPSR_AIF_MASK << SPSR_AIF_SHIFT | \
+	         SPSR_M_AARCH32 << SPSR_M_SHIFT | \
+	         MODE32_svc << MODE32_SHIFT)
+	.quad	workaround_bpiall_vbar1_runtime_exceptions
+	.quad	SCTLR_AARCH32_EL1_RES1 | SCTLR_I_BIT
+	.quad	aarch32_stub_fiq
+	check_vector_size workaround_bpiall_vbar0_fiq_sp_el0
+
+vector_entry workaround_bpiall_vbar0_serror_sp_el0
+	b	serror_sp_el0
+aarch32_stub_serror:
+	.word	EMIT_BPIALL
+	.word	EMIT_MOV_R0_IMM(8)
+	.word	EMIT_SMC
+aarch32_stub_ctx_serror:
+	.quad	(SPSR_AIF_MASK << SPSR_AIF_SHIFT | \
+	         SPSR_M_AARCH32 << SPSR_M_SHIFT | \
+	         MODE32_svc << MODE32_SHIFT)
+	.quad	workaround_bpiall_vbar1_runtime_exceptions
+	.quad	SCTLR_AARCH32_EL1_RES1 | SCTLR_I_BIT
+	.quad	aarch32_stub_serror
+	check_vector_size workaround_bpiall_vbar0_serror_sp_el0
+
+	/* ---------------------------------------------------------------------
+	 * Current EL with SP_ELx: 0x200 - 0x400
+	 * ---------------------------------------------------------------------
+	 */
+vector_entry workaround_bpiall_vbar0_sync_exception_sp_elx
+	b	sync_exception_sp_elx
+	check_vector_size workaround_bpiall_vbar0_sync_exception_sp_elx
+
+vector_entry workaround_bpiall_vbar0_irq_sp_elx
+	b	irq_sp_elx
+	check_vector_size workaround_bpiall_vbar0_irq_sp_elx
+
+vector_entry workaround_bpiall_vbar0_fiq_sp_elx
+	b	fiq_sp_elx
+	check_vector_size workaround_bpiall_vbar0_fiq_sp_elx
+
+vector_entry workaround_bpiall_vbar0_serror_sp_elx
+	b	serror_sp_elx
+	check_vector_size workaround_bpiall_vbar0_serror_sp_elx
+
+	/* ---------------------------------------------------------------------
+	 * Lower EL using AArch64 : 0x400 - 0x600
+	 * ---------------------------------------------------------------------
+	 */
+vector_entry workaround_bpiall_vbar0_sync_exception_aarch64
+	enter_workaround aarch32_stub_ctx_smc
+	check_vector_size workaround_bpiall_vbar0_sync_exception_aarch64
+
+vector_entry workaround_bpiall_vbar0_irq_aarch64
+	enter_workaround aarch32_stub_ctx_irq
+	check_vector_size workaround_bpiall_vbar0_irq_aarch64
+
+vector_entry workaround_bpiall_vbar0_fiq_aarch64
+	enter_workaround aarch32_stub_ctx_fiq
+	check_vector_size workaround_bpiall_vbar0_fiq_aarch64
+
+vector_entry workaround_bpiall_vbar0_serror_aarch64
+	enter_workaround aarch32_stub_ctx_serror
+	check_vector_size workaround_bpiall_vbar0_serror_aarch64
+
+	/* ---------------------------------------------------------------------
+	 * Lower EL using AArch32 : 0x600 - 0x800
+	 * ---------------------------------------------------------------------
+	 */
+vector_entry workaround_bpiall_vbar0_sync_exception_aarch32
+	enter_workaround aarch32_stub_ctx_smc
+	check_vector_size workaround_bpiall_vbar0_sync_exception_aarch32
+
+vector_entry workaround_bpiall_vbar0_irq_aarch32
+	enter_workaround aarch32_stub_ctx_irq
+	check_vector_size workaround_bpiall_vbar0_irq_aarch32
+
+vector_entry workaround_bpiall_vbar0_fiq_aarch32
+	enter_workaround aarch32_stub_ctx_fiq
+	check_vector_size workaround_bpiall_vbar0_fiq_aarch32
+
+vector_entry workaround_bpiall_vbar0_serror_aarch32
+	enter_workaround aarch32_stub_ctx_serror
+	check_vector_size workaround_bpiall_vbar0_serror_aarch32
+
+	/* ---------------------------------------------------------------------
+	 * This vector table is used while the workaround is executing.  It
+	 * installs a simple SMC handler to allow the Sync/IRQ/FIQ/SError
+	 * workaround stubs to enter EL3 from S-EL1.  It restores the previous
+	 * EL3 state before proceeding with the normal runtime exception vector.
+	 * ---------------------------------------------------------------------
+	 */
+vector_base workaround_bpiall_vbar1_runtime_exceptions
+
+	/* ---------------------------------------------------------------------
+	 * Current EL with SP_EL0 : 0x0 - 0x200 (UNUSED)
+	 * ---------------------------------------------------------------------
+	 */
+vector_entry workaround_bpiall_vbar1_sync_exception_sp_el0
+	b	report_unhandled_exception
+	check_vector_size workaround_bpiall_vbar1_sync_exception_sp_el0
+
+vector_entry workaround_bpiall_vbar1_irq_sp_el0
+	b	report_unhandled_interrupt
+	check_vector_size workaround_bpiall_vbar1_irq_sp_el0
+
+vector_entry workaround_bpiall_vbar1_fiq_sp_el0
+	b	report_unhandled_interrupt
+	check_vector_size workaround_bpiall_vbar1_fiq_sp_el0
+
+vector_entry workaround_bpiall_vbar1_serror_sp_el0
+	b	report_unhandled_exception
+	check_vector_size workaround_bpiall_vbar1_serror_sp_el0
+
+	/* ---------------------------------------------------------------------
+	 * Current EL with SP_ELx: 0x200 - 0x400 (UNUSED)
+	 * ---------------------------------------------------------------------
+	 */
+vector_entry workaround_bpiall_vbar1_sync_exception_sp_elx
+	b	report_unhandled_exception
+	check_vector_size workaround_bpiall_vbar1_sync_exception_sp_elx
+
+vector_entry workaround_bpiall_vbar1_irq_sp_elx
+	b	report_unhandled_interrupt
+	check_vector_size workaround_bpiall_vbar1_irq_sp_elx
+
+vector_entry workaround_bpiall_vbar1_fiq_sp_elx
+	b	report_unhandled_interrupt
+	check_vector_size workaround_bpiall_vbar1_fiq_sp_elx
+
+vector_entry workaround_bpiall_vbar1_serror_sp_elx
+	b	report_unhandled_exception
+	check_vector_size workaround_bpiall_vbar1_serror_sp_elx
+
+	/* ---------------------------------------------------------------------
+	 * Lower EL using AArch64 : 0x400 - 0x600 (UNUSED)
+	 * ---------------------------------------------------------------------
+	 */
+vector_entry workaround_bpiall_vbar1_sync_exception_aarch64
+	b	report_unhandled_exception
+	check_vector_size workaround_bpiall_vbar1_sync_exception_aarch64
+
+vector_entry workaround_bpiall_vbar1_irq_aarch64
+	b	report_unhandled_interrupt
+	check_vector_size workaround_bpiall_vbar1_irq_aarch64
+
+vector_entry workaround_bpiall_vbar1_fiq_aarch64
+	b	report_unhandled_interrupt
+	check_vector_size workaround_bpiall_vbar1_fiq_aarch64
+
+vector_entry workaround_bpiall_vbar1_serror_aarch64
+	b	report_unhandled_exception
+	check_vector_size workaround_bpiall_vbar1_serror_aarch64
+
+	/* ---------------------------------------------------------------------
+	 * Lower EL using AArch32 : 0x600 - 0x800
+	 * ---------------------------------------------------------------------
+	 */
+vector_entry workaround_bpiall_vbar1_sync_exception_aarch32
+	/* Restore register state from the workaround context */
+	ldp	x2, x3, [sp, #CTX_CVE_2017_5715_OFFSET + CTX_CVE_2017_5715_QUAD0]
+	ldp	x4, x5, [sp, #CTX_CVE_2017_5715_OFFSET + CTX_CVE_2017_5715_QUAD2]
+	ldp	x6, x30, [sp, #CTX_CVE_2017_5715_OFFSET + CTX_CVE_2017_5715_QUAD4]
+
+	/* Apply the restored system register state */
+	msr	scr_el3, x2
+	msr	spsr_el3, x3
+	msr	elr_el3, x4
+	msr	sctlr_el1, x5
+	msr	esr_el3, x6
+
+	/*
+	 * Workaround is complete, so swap VBAR_EL3 to point
+	 * to workaround entry table in preparation for subsequent
+	 * Sync/IRQ/FIQ/SError exceptions.
+	 */
+	adr	x2, workaround_bpiall_vbar0_runtime_exceptions
+	msr	vbar_el3, x2
+
+	/*
+	 * Restore all GP regs except x0 and x1.  The value in x0
+	 * indicates the type of the original exception.
+	 */
+	ldp	x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
+	ldp	x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4]
+	ldp	x6, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X6]
+	ldp	x8, x9, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X8]
+	ldp	x10, x11, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X10]
+	ldp	x12, x13, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X12]
+	ldp	x14, x15, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X14]
+	ldp	x16, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X16]
+	ldp	x18, x19, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X18]
+	ldp	x20, x21, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X20]
+	ldp	x22, x23, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X22]
+	ldp	x24, x25, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X24]
+	ldp	x26, x27, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X26]
+	ldp	x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28]
+
+	/*
+	 * Each of these handlers will first restore x0 and x1 from
+	 * the context and the branch to the common implementation for
+	 * each of the exception types.
+	 */
+	tbnz	x0, #1, workaround_bpiall_vbar1_irq
+	tbnz	x0, #2, workaround_bpiall_vbar1_fiq
+	tbnz	x0, #3, workaround_bpiall_vbar1_serror
+
+	/* Fallthrough case for Sync exception */
+	ldp	x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
+	b	sync_exception_aarch64
+	check_vector_size workaround_bpiall_vbar1_sync_exception_aarch32
+
+vector_entry workaround_bpiall_vbar1_irq_aarch32
+	b	report_unhandled_interrupt
+workaround_bpiall_vbar1_irq:
+	ldp	x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
+	b	irq_aarch64
+	check_vector_size workaround_bpiall_vbar1_irq_aarch32
+
+vector_entry workaround_bpiall_vbar1_fiq_aarch32
+	b	report_unhandled_interrupt
+workaround_bpiall_vbar1_fiq:
+	ldp	x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
+	b	fiq_aarch64
+	check_vector_size workaround_bpiall_vbar1_fiq_aarch32
+
+vector_entry workaround_bpiall_vbar1_serror_aarch32
+	b	report_unhandled_exception
+workaround_bpiall_vbar1_serror:
+	ldp	x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
+	b	serror_aarch64
+	check_vector_size workaround_bpiall_vbar1_serror_aarch32
diff --git a/lib/cpus/aarch64/workaround_cve_2017_5715_mmu.S b/lib/cpus/aarch64/workaround_cve_2017_5715_mmu.S
new file mode 100644
index 0000000..f478148
--- /dev/null
+++ b/lib/cpus/aarch64/workaround_cve_2017_5715_mmu.S
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <context.h>
+
+	.globl	workaround_mmu_runtime_exceptions
+
+vector_base workaround_mmu_runtime_exceptions
+
+	.macro	apply_workaround
+	stp	x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
+	mrs	x0, sctlr_el3
+	/* Disable MMU */
+	bic	x1, x0, #SCTLR_M_BIT
+	msr	sctlr_el3, x1
+	isb
+	/* Restore MMU config */
+	msr	sctlr_el3, x0
+	isb
+	ldp	x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
+	.endm
+
+	/* ---------------------------------------------------------------------
+	 * Current EL with SP_EL0 : 0x0 - 0x200
+	 * ---------------------------------------------------------------------
+	 */
+vector_entry workaround_mmu_sync_exception_sp_el0
+	b	sync_exception_sp_el0
+	check_vector_size workaround_mmu_sync_exception_sp_el0
+
+vector_entry workaround_mmu_irq_sp_el0
+	b	irq_sp_el0
+	check_vector_size workaround_mmu_irq_sp_el0
+
+vector_entry workaround_mmu_fiq_sp_el0
+	b	fiq_sp_el0
+	check_vector_size workaround_mmu_fiq_sp_el0
+
+vector_entry workaround_mmu_serror_sp_el0
+	b	serror_sp_el0
+	check_vector_size workaround_mmu_serror_sp_el0
+
+	/* ---------------------------------------------------------------------
+	 * Current EL with SP_ELx: 0x200 - 0x400
+	 * ---------------------------------------------------------------------
+	 */
+vector_entry workaround_mmu_sync_exception_sp_elx
+	b	sync_exception_sp_elx
+	check_vector_size workaround_mmu_sync_exception_sp_elx
+
+vector_entry workaround_mmu_irq_sp_elx
+	b	irq_sp_elx
+	check_vector_size workaround_mmu_irq_sp_elx
+
+vector_entry workaround_mmu_fiq_sp_elx
+	b	fiq_sp_elx
+	check_vector_size workaround_mmu_fiq_sp_elx
+
+vector_entry workaround_mmu_serror_sp_elx
+	b	serror_sp_elx
+	check_vector_size workaround_mmu_serror_sp_elx
+
+	/* ---------------------------------------------------------------------
+	 * Lower EL using AArch64 : 0x400 - 0x600
+	 * ---------------------------------------------------------------------
+	 */
+vector_entry workaround_mmu_sync_exception_aarch64
+	apply_workaround
+	b	sync_exception_aarch64
+	check_vector_size workaround_mmu_sync_exception_aarch64
+
+vector_entry workaround_mmu_irq_aarch64
+	apply_workaround
+	b	irq_aarch64
+	check_vector_size workaround_mmu_irq_aarch64
+
+vector_entry workaround_mmu_fiq_aarch64
+	apply_workaround
+	b	fiq_aarch64
+	check_vector_size workaround_mmu_fiq_aarch64
+
+vector_entry workaround_mmu_serror_aarch64
+	apply_workaround
+	b	serror_aarch64
+	check_vector_size workaround_mmu_serror_aarch64
+
+	/* ---------------------------------------------------------------------
+	 * Lower EL using AArch32 : 0x600 - 0x800
+	 * ---------------------------------------------------------------------
+	 */
+vector_entry workaround_mmu_sync_exception_aarch32
+	apply_workaround
+	b	sync_exception_aarch32
+	check_vector_size workaround_mmu_sync_exception_aarch32
+
+vector_entry workaround_mmu_irq_aarch32
+	apply_workaround
+	b	irq_aarch32
+	check_vector_size workaround_mmu_irq_aarch32
+
+vector_entry workaround_mmu_fiq_aarch32
+	apply_workaround
+	b	fiq_aarch32
+	check_vector_size workaround_mmu_fiq_aarch32
+
+vector_entry workaround_mmu_serror_aarch32
+	apply_workaround
+	b	serror_aarch32
+	check_vector_size workaround_mmu_serror_aarch32
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index 31adfb4..3ba8c1f 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -16,6 +16,8 @@
 # It is enabled by default.
 A57_DISABLE_NON_TEMPORAL_HINT	?=1
 
+WORKAROUND_CVE_2017_5715	?=1
+
 # Process SKIP_A57_L1_FLUSH_PWR_DWN flag
 $(eval $(call assert_boolean,SKIP_A57_L1_FLUSH_PWR_DWN))
 $(eval $(call add_define,SKIP_A57_L1_FLUSH_PWR_DWN))
@@ -28,6 +30,9 @@
 $(eval $(call assert_boolean,A57_DISABLE_NON_TEMPORAL_HINT))
 $(eval $(call add_define,A57_DISABLE_NON_TEMPORAL_HINT))
 
+# Process WORKAROUND_CVE_2017_5715 flag
+$(eval $(call assert_boolean,WORKAROUND_CVE_2017_5715))
+$(eval $(call add_define,WORKAROUND_CVE_2017_5715))
 
 # CPU Errata Build flags.
 # These should be enabled by the platform if the erratum workaround needs to be
diff --git a/lib/extensions/amu/aarch32/amu.c b/lib/extensions/amu/aarch32/amu.c
index d450bd6..effc5bd 100644
--- a/lib/extensions/amu/aarch32/amu.c
+++ b/lib/extensions/amu/aarch32/amu.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
  */
@@ -7,26 +7,100 @@
 #include <amu.h>
 #include <arch.h>
 #include <arch_helpers.h>
+#include <platform.h>
+#include <pubsub_events.h>
+
+#define AMU_GROUP0_NR_COUNTERS	4
+
+struct amu_ctx {
+	uint64_t group0_cnts[AMU_GROUP0_NR_COUNTERS];
+};
+
+static struct amu_ctx amu_ctxs[PLATFORM_CORE_COUNT];
 
 void amu_enable(int el2_unused)
 {
 	uint64_t features;
 
 	features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT;
-	if ((features & ID_PFR0_AMU_MASK) == 1) {
-		if (el2_unused) {
-			uint64_t v;
+	if ((features & ID_PFR0_AMU_MASK) != 1)
+		return;
 
-			/*
-			 * Non-secure access from EL0 or EL1 to the Activity Monitor
-			 * registers do not trap to EL2.
-			 */
-			v = read_hcptr();
-			v &= ~TAM_BIT;
-			write_hcptr(v);
-		}
+	if (el2_unused) {
+		uint64_t v;
 
-		/* Enable group 0 counters */
-		write_amcntenset0(AMU_GROUP0_COUNTERS_MASK);
+		/*
+		 * Non-secure access from EL0 or EL1 to the Activity Monitor
+		 * registers do not trap to EL2.
+		 */
+		v = read_hcptr();
+		v &= ~TAM_BIT;
+		write_hcptr(v);
 	}
+
+	/* Enable group 0 counters */
+	write_amcntenset0(AMU_GROUP0_COUNTERS_MASK);
 }
+
+static void *amu_context_save(const void *arg)
+{
+	struct amu_ctx *ctx;
+	uint64_t features;
+
+	features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT;
+	if ((features & ID_PFR0_AMU_MASK) != 1)
+		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);
+
+	/*
+	 * Disable group 0 counters to avoid other observers like SCP sampling
+	 * counter values from the future via the memory mapped view.
+	 */
+	write_amcntenclr0(AMU_GROUP0_COUNTERS_MASK);
+	isb();
+
+	ctx->group0_cnts[0] = read64_amevcntr00();
+	ctx->group0_cnts[1] = read64_amevcntr01();
+	ctx->group0_cnts[2] = read64_amevcntr02();
+	ctx->group0_cnts[3] = read64_amevcntr03();
+
+	return 0;
+}
+
+static void *amu_context_restore(const void *arg)
+{
+	struct amu_ctx *ctx;
+	uint64_t features;
+
+	features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT;
+	if ((features & ID_PFR0_AMU_MASK) != 1)
+		return (void *)-1;
+
+	ctx = &amu_ctxs[plat_my_core_pos()];
+
+	/* Counters were disabled in `amu_context_save()` */
+	assert(read_amcntenset0() == 0);
+
+	/* Restore group 0 counters */
+	if (AMU_GROUP0_COUNTERS_MASK & (1U << 0))
+		write64_amevcntr00(ctx->group0_cnts[0]);
+	if (AMU_GROUP0_COUNTERS_MASK & (1U << 1))
+		write64_amevcntr01(ctx->group0_cnts[1]);
+	if (AMU_GROUP0_COUNTERS_MASK & (1U << 2))
+		write64_amevcntr02(ctx->group0_cnts[2]);
+	if (AMU_GROUP0_COUNTERS_MASK & (1U << 3))
+		write64_amevcntr03(ctx->group0_cnts[3]);
+	isb();
+
+	/* Enable group 0 counters */
+	write_amcntenset0(AMU_GROUP0_COUNTERS_MASK);
+
+	return 0;
+}
+
+SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, amu_context_save);
+SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, amu_context_restore);
diff --git a/lib/extensions/amu/aarch64/amu.c b/lib/extensions/amu/aarch64/amu.c
index 007b349..d7645a9 100644
--- a/lib/extensions/amu/aarch64/amu.c
+++ b/lib/extensions/amu/aarch64/amu.c
@@ -1,40 +1,185 @@
 /*
- * 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 <amu.h>
+#include <amu_private.h>
 #include <arch.h>
 #include <arch_helpers.h>
+#include <assert.h>
+#include <platform.h>
+#include <pubsub_events.h>
 
-void amu_enable(int el2_unused)
+#define AMU_GROUP0_NR_COUNTERS	4
+
+struct amu_ctx {
+	uint64_t group0_cnts[AMU_GROUP0_NR_COUNTERS];
+	uint64_t group1_cnts[AMU_GROUP1_NR_COUNTERS];
+};
+
+static struct amu_ctx amu_ctxs[PLATFORM_CORE_COUNT];
+
+int amu_supported(void)
 {
 	uint64_t features;
 
 	features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT;
-	if ((features & ID_AA64PFR0_AMU_MASK) == 1) {
-		uint64_t v;
+	return (features & ID_AA64PFR0_AMU_MASK) == 1;
+}
+
+/*
+ * Enable counters.  This function is meant to be invoked
+ * by the context management library before exiting from EL3.
+ */
+void amu_enable(int el2_unused)
+{
+	uint64_t v;
 
-		if (el2_unused) {
-			/*
-			 * CPTR_EL2.TAM: Set to zero so any accesses to
-			 * the Activity Monitor registers do not trap to EL2.
-			 */
-			v = read_cptr_el2();
-			v &= ~CPTR_EL2_TAM_BIT;
-			write_cptr_el2(v);
-		}
+	if (!amu_supported())
+		return;
 
+	if (el2_unused) {
 		/*
-		 * CPTR_EL3.TAM: Set to zero so that any accesses to
-		 * the Activity Monitor registers do not trap to EL3.
+		 * CPTR_EL2.TAM: Set to zero so any accesses to
+		 * the Activity Monitor registers do not trap to EL2.
 		 */
-		v = read_cptr_el3();
-		v &= ~TAM_BIT;
-		write_cptr_el3(v);
-
-		/* Enable group 0 counters */
-		write_amcntenset0_el0(AMU_GROUP0_COUNTERS_MASK);
+		v = read_cptr_el2();
+		v &= ~CPTR_EL2_TAM_BIT;
+		write_cptr_el2(v);
 	}
+
+	/*
+	 * CPTR_EL3.TAM: Set to zero so that any accesses to
+	 * the Activity Monitor registers do not trap to EL3.
+	 */
+	v = read_cptr_el3();
+	v &= ~TAM_BIT;
+	write_cptr_el3(v);
+
+	/* Enable group 0 counters */
+	write_amcntenset0_el0(AMU_GROUP0_COUNTERS_MASK);
+	/* Enable group 1 counters */
+	write_amcntenset1_el0(AMU_GROUP1_COUNTERS_MASK);
+}
+
+/* Read the group 0 counter identified by the given `idx`. */
+uint64_t amu_group0_cnt_read(int idx)
+{
+	assert(amu_supported());
+	assert(idx >= 0 && idx < AMU_GROUP0_NR_COUNTERS);
+
+	return amu_group0_cnt_read_internal(idx);
+}
+
+/* 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(idx >= 0 && idx < AMU_GROUP0_NR_COUNTERS);
+
+	amu_group0_cnt_write_internal(idx, val);
+	isb();
+}
+
+/* Read the group 1 counter identified by the given `idx`. */
+uint64_t amu_group1_cnt_read(int idx)
+{
+	assert(amu_supported());
+	assert(idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS);
+
+	return amu_group1_cnt_read_internal(idx);
+}
+
+/* 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(idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS);
+
+	amu_group1_cnt_write_internal(idx, val);
+	isb();
 }
+
+/*
+ * Program the event type register for the given `idx` with
+ * the event number `val`.
+ */
+void amu_group1_set_evtype(int idx, unsigned int val)
+{
+	assert(amu_supported());
+	assert (idx >= 0 && idx < AMU_GROUP1_NR_COUNTERS);
+
+	amu_group1_set_evtype_internal(idx, val);
+	isb();
+}
+
+static void *amu_context_save(const void *arg)
+{
+	struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()];
+	int i;
+
+	if (!amu_supported())
+		return (void *)-1;
+
+	/* Assert that group 0/1 counter configuration is what we expect */
+	assert(read_amcntenset0_el0() == AMU_GROUP0_COUNTERS_MASK &&
+	       read_amcntenset1_el0() == AMU_GROUP1_COUNTERS_MASK);
+
+	assert((sizeof(int) * 8) - __builtin_clz(AMU_GROUP1_COUNTERS_MASK)
+		<= AMU_GROUP1_NR_COUNTERS);
+
+	/*
+	 * Disable group 0/1 counters to avoid other observers like SCP sampling
+	 * counter values from the future via the memory mapped view.
+	 */
+	write_amcntenclr0_el0(AMU_GROUP0_COUNTERS_MASK);
+	write_amcntenclr1_el0(AMU_GROUP1_COUNTERS_MASK);
+	isb();
+
+	/* Save group 0 counters */
+	for (i = 0; i < AMU_GROUP0_NR_COUNTERS; i++)
+		ctx->group0_cnts[i] = amu_group0_cnt_read(i);
+
+	/* Save group 1 counters */
+	for (i = 0; i < AMU_GROUP1_NR_COUNTERS; i++)
+		ctx->group1_cnts[i] = amu_group1_cnt_read(i);
+
+	return 0;
+}
+
+static void *amu_context_restore(const void *arg)
+{
+	struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()];
+	int i;
+
+	if (!amu_supported())
+		return (void *)-1;
+
+	/* Counters were disabled in `amu_context_save()` */
+	assert(read_amcntenset0_el0() == 0 && read_amcntenset1_el0() == 0);
+
+	assert((sizeof(int) * 8) - __builtin_clz(AMU_GROUP1_COUNTERS_MASK)
+		<= AMU_GROUP1_NR_COUNTERS);
+
+	/* Restore group 0 counters */
+	for (i = 0; i < AMU_GROUP0_NR_COUNTERS; i++)
+		if (AMU_GROUP0_COUNTERS_MASK & (1U << i))
+			amu_group0_cnt_write(i, ctx->group0_cnts[i]);
+
+	/* Restore group 1 counters */
+	for (i = 0; i < AMU_GROUP1_NR_COUNTERS; i++)
+		if (AMU_GROUP1_COUNTERS_MASK & (1U << i))
+			amu_group1_cnt_write(i, ctx->group1_cnts[i]);
+	isb();
+
+	/* Restore group 0/1 counter configuration */
+	write_amcntenset0_el0(AMU_GROUP0_COUNTERS_MASK);
+	write_amcntenset1_el0(AMU_GROUP1_COUNTERS_MASK);
+
+	return 0;
+}
+
+SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, amu_context_save);
+SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, amu_context_restore);
diff --git a/lib/extensions/amu/aarch64/amu_helpers.S b/lib/extensions/amu/aarch64/amu_helpers.S
new file mode 100644
index 0000000..e0b1f56
--- /dev/null
+++ b/lib/extensions/amu/aarch64/amu_helpers.S
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2017, 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 `x0`.
+ */
+func amu_group0_cnt_read_internal
+#if ENABLE_ASSERTIONS
+	/*
+	 * It can be dangerous to call this function with an
+	 * out of bounds index.  Ensure `idx` is valid.
+	 */
+	mov	x1, x0
+	lsr	x1, x1, #2
+	cmp	x1, #0
+	ASM_ASSERT(eq)
+#endif
+
+	/*
+	 * Given `idx` calculate address of mrs/ret instruction pair
+	 * in the table below.
+	 */
+	adr	x1, 1f
+	lsl	x0, x0, #3		/* each mrs/ret sequence is 8 bytes */
+	add	x1, x1, x0
+	br	x1
+
+1:
+	mrs	x0, AMEVCNTR00_EL0	/* index 0 */
+	ret
+	mrs	x0, AMEVCNTR01_EL0	/* index 1 */
+	ret
+	mrs	x0, AMEVCNTR02_EL0	/* index 2 */
+	ret
+	mrs	x0, AMEVCNTR03_EL0	/* index 3 */
+	ret
+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
+#if ENABLE_ASSERTIONS
+	/*
+	 * It can be dangerous to call this function with an
+	 * out of bounds index.  Ensure `idx` is valid.
+	 */
+	mov	x2, x0
+	lsr	x2, x2, #2
+	cmp	x2, #0
+	ASM_ASSERT(eq)
+#endif
+
+	/*
+	 * Given `idx` calculate address of mrs/ret instruction pair
+	 * in the table below.
+	 */
+	adr	x2, 1f
+	lsl	x0, x0, #3		/* each msr/ret sequence is 8 bytes */
+	add	x2, x2, x0
+	br	x2
+
+1:
+	msr	AMEVCNTR00_EL0, x1	/* index 0 */
+	ret
+	msr	AMEVCNTR01_EL0, x1	/* index 1 */
+	ret
+	msr	AMEVCNTR02_EL0, x1	/* index 2 */
+	ret
+	msr	AMEVCNTR03_EL0, x1	/* index 3 */
+	ret
+endfunc amu_group0_cnt_write_internal
+
+/*
+ * 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
+#if ENABLE_ASSERTIONS
+	/*
+	 * It can be dangerous to call this function with an
+	 * out of bounds index.  Ensure `idx` is valid.
+	 */
+	mov	x1, x0
+	lsr	x1, x1, #4
+	cmp	x1, #0
+	ASM_ASSERT(eq)
+#endif
+
+	/*
+	 * Given `idx` calculate address of mrs/ret instruction pair
+	 * in the table below.
+	 */
+	adr	x1, 1f
+	lsl	x0, x0, #3		/* each mrs/ret sequence is 8 bytes */
+	add	x1, x1, x0
+	br	x1
+
+1:
+	mrs	x0, AMEVCNTR10_EL0	/* index 0 */
+	ret
+	mrs	x0, AMEVCNTR11_EL0	/* index 1 */
+	ret
+	mrs	x0, AMEVCNTR12_EL0	/* index 2 */
+	ret
+	mrs	x0, AMEVCNTR13_EL0	/* index 3 */
+	ret
+	mrs	x0, AMEVCNTR14_EL0	/* index 4 */
+	ret
+	mrs	x0, AMEVCNTR15_EL0	/* index 5 */
+	ret
+	mrs	x0, AMEVCNTR16_EL0	/* index 6 */
+	ret
+	mrs	x0, AMEVCNTR17_EL0	/* index 7 */
+	ret
+	mrs	x0, AMEVCNTR18_EL0	/* index 8 */
+	ret
+	mrs	x0, AMEVCNTR19_EL0	/* index 9 */
+	ret
+	mrs	x0, AMEVCNTR1A_EL0	/* index 10 */
+	ret
+	mrs	x0, AMEVCNTR1B_EL0	/* index 11 */
+	ret
+	mrs	x0, AMEVCNTR1C_EL0	/* index 12 */
+	ret
+	mrs	x0, AMEVCNTR1D_EL0	/* index 13 */
+	ret
+	mrs	x0, AMEVCNTR1E_EL0	/* index 14 */
+	ret
+	mrs	x0, AMEVCNTR1F_EL0	/* index 15 */
+	ret
+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
+#if ENABLE_ASSERTIONS
+	/*
+	 * It can be dangerous to call this function with an
+	 * out of bounds index.  Ensure `idx` is valid.
+	 */
+	mov	x2, x0
+	lsr	x2, x2, #4
+	cmp	x2, #0
+	ASM_ASSERT(eq)
+#endif
+
+	/*
+	 * Given `idx` calculate address of mrs/ret instruction pair
+	 * in the table below.
+	 */
+	adr	x2, 1f
+	lsl	x0, x0, #3		/* each msr/ret sequence is 8 bytes */
+	add	x2, x2, x0
+	br	x2
+
+1:
+	msr	AMEVCNTR10_EL0, x1	/* index 0 */
+	ret
+	msr	AMEVCNTR11_EL0, x1	/* index 1 */
+	ret
+	msr	AMEVCNTR12_EL0, x1	/* index 2 */
+	ret
+	msr	AMEVCNTR13_EL0, x1	/* index 3 */
+	ret
+	msr	AMEVCNTR14_EL0, x1	/* index 4 */
+	ret
+	msr	AMEVCNTR15_EL0, x1	/* index 5 */
+	ret
+	msr	AMEVCNTR16_EL0, x1	/* index 6 */
+	ret
+	msr	AMEVCNTR17_EL0, x1	/* index 7 */
+	ret
+	msr	AMEVCNTR18_EL0, x1	/* index 8 */
+	ret
+	msr	AMEVCNTR19_EL0, x1	/* index 9 */
+	ret
+	msr	AMEVCNTR1A_EL0, x1	/* index 10 */
+	ret
+	msr	AMEVCNTR1B_EL0, x1	/* index 11 */
+	ret
+	msr	AMEVCNTR1C_EL0, x1	/* index 12 */
+	ret
+	msr	AMEVCNTR1D_EL0, x1	/* index 13 */
+	ret
+	msr	AMEVCNTR1E_EL0, x1	/* index 14 */
+	ret
+	msr	AMEVCNTR1F_EL0, x1	/* index 15 */
+	ret
+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
+	/*
+	 * It can be dangerous to call this function with an
+	 * out of bounds index.  Ensure `idx` is valid.
+	 */
+	mov	x2, x0
+	lsr	x2, x2, #4
+	cmp	x2, #0
+	ASM_ASSERT(eq)
+
+	/* val should be between [0, 65535] */
+	mov	x2, x1
+	lsr	x2, x2, #16
+	cmp	x2, #0
+	ASM_ASSERT(eq)
+#endif
+
+	/*
+	 * Given `idx` calculate address of msr/ret instruction pair
+	 * in the table below.
+	 */
+	adr	x2, 1f
+	lsl	x0, x0, #3		/* each msr/ret sequence is 8 bytes */
+	add	x2, x2, x0
+	br	x2
+
+1:
+	msr	AMEVTYPER10_EL0, x1	/* index 0 */
+	ret
+	msr	AMEVTYPER11_EL0, x1	/* index 1 */
+	ret
+	msr	AMEVTYPER12_EL0, x1	/* index 2 */
+	ret
+	msr	AMEVTYPER13_EL0, x1	/* index 3 */
+	ret
+	msr	AMEVTYPER14_EL0, x1	/* index 4 */
+	ret
+	msr	AMEVTYPER15_EL0, x1	/* index 5 */
+	ret
+	msr	AMEVTYPER16_EL0, x1	/* index 6 */
+	ret
+	msr	AMEVTYPER17_EL0, x1	/* index 7 */
+	ret
+	msr	AMEVTYPER18_EL0, x1	/* index 8 */
+	ret
+	msr	AMEVTYPER19_EL0, x1	/* index 9 */
+	ret
+	msr	AMEVTYPER1A_EL0, x1	/* index 10 */
+	ret
+	msr	AMEVTYPER1B_EL0, x1	/* index 11 */
+	ret
+	msr	AMEVTYPER1C_EL0, x1	/* index 12 */
+	ret
+	msr	AMEVTYPER1D_EL0, x1	/* index 13 */
+	ret
+	msr	AMEVTYPER1E_EL0, x1	/* index 14 */
+	ret
+	msr	AMEVTYPER1F_EL0, x1	/* index 15 */
+	ret
+endfunc amu_group1_set_evtype_internal
diff --git a/lib/psci/psci_suspend.c b/lib/psci/psci_suspend.c
index d949067..a77972d 100644
--- a/lib/psci/psci_suspend.c
+++ b/lib/psci/psci_suspend.c
@@ -14,6 +14,7 @@
 #include <debug.h>
 #include <platform.h>
 #include <pmf.h>
+#include <pubsub_events.h>
 #include <runtime_instr.h>
 #include <stddef.h>
 #include "psci_private.h"
@@ -68,6 +69,8 @@
 {
 	unsigned int max_off_lvl = psci_find_max_off_lvl(state_info);
 
+	PUBLISH_EVENT(psci_suspend_pwrdown_start);
+
 	/* Save PSCI target power level for the suspend finisher handler */
 	psci_set_suspend_pwrlvl(end_pwrlvl);
 
@@ -308,6 +311,8 @@
 	/* Invalidate the suspend level for the cpu */
 	psci_set_suspend_pwrlvl(PSCI_INVALID_PWR_LVL);
 
+	PUBLISH_EVENT(psci_suspend_pwrdown_finish);
+
 	/*
 	 * Generic management: Now we just need to retrieve the
 	 * information that we had stashed away during the suspend
diff --git a/lib/xlat_tables_v2/xlat_tables_internal.c b/lib/xlat_tables_v2/xlat_tables_internal.c
index 0acfacb..75c5a91 100644
--- a/lib/xlat_tables_v2/xlat_tables_internal.c
+++ b/lib/xlat_tables_v2/xlat_tables_internal.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
  */
@@ -893,7 +893,7 @@
 			 * Check if the mapping function actually managed to map
 			 * anything. If not, just return now.
 			 */
-			if (mm_cursor->base_va >= end_va)
+			if (mm->base_va >= end_va)
 				return -ENOMEM;
 
 			/*
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 7edbd3d..9d3c5f6 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -150,6 +150,10 @@
 # Enable Activity Monitor Unit extensions by default
 ENABLE_AMU			:=	1
 
+ifeq (${ENABLE_AMU},1)
+BL31_SOURCES		+= lib/cpus/aarch64/cortex_a75_pubsub.c
+endif
+
 ifneq (${ENABLE_STACK_PROTECTOR},0)
 PLAT_BL_COMMON_SOURCES	+=	plat/arm/board/fvp/fvp_stack_protector.c
 endif
diff --git a/plat/hisilicon/hikey960/hikey960_bl1_setup.c b/plat/hisilicon/hikey960/hikey960_bl1_setup.c
index ae33bd2..11f143a 100644
--- a/plat/hisilicon/hikey960/hikey960_bl1_setup.c
+++ b/plat/hisilicon/hikey960/hikey960_bl1_setup.c
@@ -647,6 +647,8 @@
 	}
 	/* GPIO005 - PMU SSI, 10mA */
 	mmio_write_32(IOCG_006_REG, 2 << 4);
+	/* GPIO213 - PCIE_CLKREQ_N */
+	mmio_write_32(IOMG_AO_033_REG, 1);
 }
 
 /*
diff --git a/plat/hisilicon/hikey960/include/hi3660.h b/plat/hisilicon/hikey960/include/hi3660.h
index 83d1b36..ab7b8aa 100644
--- a/plat/hisilicon/hikey960/include/hi3660.h
+++ b/plat/hisilicon/hikey960/include/hi3660.h
@@ -335,6 +335,8 @@
 #define IOMG_AO_026_REG			(IOMG_AO_REG_BASE + 0x068)
 /* GPIO219: PD interrupt. pull up */
 #define IOMG_AO_039_REG			(IOMG_AO_REG_BASE + 0x09C)
+/* GPIO213: PCIE_CLKREQ_N */
+#define IOMG_AO_033_REG			(IOMG_AO_REG_BASE + 0x084)
 
 #define IOCG_AO_REG_BASE		0xFFF1187C
 /* GPIO219: PD interrupt. pull up */
diff --git a/plat/socionext/uniphier/platform.mk b/plat/socionext/uniphier/platform.mk
index 41d0444..f99bbf5 100644
--- a/plat/socionext/uniphier/platform.mk
+++ b/plat/socionext/uniphier/platform.mk
@@ -117,4 +117,4 @@
 bl1_gzip: $(BUILD_PLAT)/bl1.bin.gzip
 %.gzip: %
 	@echo "  GZIP    $@"
-	$(Q)(cat $< | gzip -n -f -9 > $@) || (rm -f $@ || false)
+	$(Q)gzip -n -f -9 $< --stdout > $@
diff --git a/services/spd/tlkd/tlkd_main.c b/services/spd/tlkd/tlkd_main.c
index 78e9853..cb68bff 100644
--- a/services/spd/tlkd/tlkd_main.c
+++ b/services/spd/tlkd/tlkd_main.c
@@ -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
  */
@@ -193,12 +193,14 @@
 	 * b. register shared memory with the SP for passing args
 	 *    required for maintaining sessions with the Trusted
 	 *    Applications.
-	 * c. open/close sessions
-	 * d. issue commands to the Trusted Apps
-	 * e. resume the preempted yielding SMC call.
+	 * c. register non-secure world's memory map with the OS
+	 * d. open/close sessions
+	 * e. issue commands to the Trusted Apps
+	 * f. resume the preempted yielding SMC call.
 	 */
 	case TLK_REGISTER_LOGBUF:
 	case TLK_REGISTER_REQBUF:
+	case TLK_REGISTER_NS_DRAM:
 	case TLK_OPEN_TA_SESSION:
 	case TLK_CLOSE_TA_SESSION:
 	case TLK_TA_LAUNCH_OP:
diff --git a/services/std_svc/spm/spm_main.c b/services/std_svc/spm/spm_main.c
index 979b9a8..d31fad6 100644
--- a/services/std_svc/spm/spm_main.c
+++ b/services/std_svc/spm/spm_main.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
  */
@@ -10,6 +10,7 @@
 #include <context_mgmt.h>
 #include <debug.h>
 #include <errno.h>
+#include <mm_svc.h>
 #include <platform.h>
 #include <runtime_svc.h>
 #include <secure_partition.h>
@@ -423,9 +424,8 @@
 
 		switch (smc_fid) {
 
-		case SP_VERSION_AARCH64:
-		case SP_VERSION_AARCH32:
-			SMC_RET1(handle, SP_VERSION_COMPILED);
+		case MM_VERSION_AARCH32:
+			SMC_RET1(handle, MM_VERSION_COMPILED);
 
 		case MM_COMMUNICATE_AARCH32:
 		case MM_COMMUNICATE_AARCH64: