Merge pull request #1043 from tekkamanninja/qemu_xlat_tables_v2_upstream

qemu: use translation tables library v2 as default.
diff --git a/Makefile b/Makefile
index 6aa4e9a..23ebcaa 100644
--- a/Makefile
+++ b/Makefile
@@ -438,6 +438,7 @@
 $(eval $(call assert_boolean,ENABLE_PMF))
 $(eval $(call assert_boolean,ENABLE_PSCI_STAT))
 $(eval $(call assert_boolean,ENABLE_RUNTIME_INSTRUMENTATION))
+$(eval $(call assert_boolean,ENABLE_SPE_FOR_LOWER_ELS))
 $(eval $(call assert_boolean,ERROR_DEPRECATED))
 $(eval $(call assert_boolean,GENERATE_COT))
 $(eval $(call assert_boolean,HW_ASSISTED_COHERENCY))
@@ -454,7 +455,6 @@
 $(eval $(call assert_boolean,USE_COHERENT_MEM))
 $(eval $(call assert_boolean,USE_TBBR_DEFS))
 $(eval $(call assert_boolean,WARMBOOT_ENABLE_DCACHE_EARLY))
-$(eval $(call assert_boolean,ENABLE_SPE_FOR_LOWER_ELS))
 
 $(eval $(call assert_numeric,ARM_ARCH_MAJOR))
 $(eval $(call assert_numeric,ARM_ARCH_MINOR))
@@ -477,6 +477,7 @@
 $(eval $(call add_define,ENABLE_PMF))
 $(eval $(call add_define,ENABLE_PSCI_STAT))
 $(eval $(call add_define,ENABLE_RUNTIME_INSTRUMENTATION))
+$(eval $(call add_define,ENABLE_SPE_FOR_LOWER_ELS))
 $(eval $(call add_define,ERROR_DEPRECATED))
 $(eval $(call add_define,HW_ASSISTED_COHERENCY))
 $(eval $(call add_define,LOAD_IMAGE_V2))
@@ -494,7 +495,6 @@
 $(eval $(call add_define,USE_COHERENT_MEM))
 $(eval $(call add_define,USE_TBBR_DEFS))
 $(eval $(call add_define,WARMBOOT_ENABLE_DCACHE_EARLY))
-$(eval $(call add_define,ENABLE_SPE_FOR_LOWER_ELS))
 
 # Define the EL3_PAYLOAD_BASE flag only if it is provided.
 ifdef EL3_PAYLOAD_BASE
diff --git a/docs/change-log.rst b/docs/change-log.rst
index 708ec05..f5ad562 100644
--- a/docs/change-log.rst
+++ b/docs/change-log.rst
@@ -266,7 +266,7 @@
    pre-empted SMC during PSCI power management requests.
 
 Issues resolved since last release
-==================================
+----------------------------------
 
 -  ARM TF can be built with the latest mbed TLS version (v2.4.2). The earlier
    version 2.3.0 cannot be used due to build warnings that the ARM TF build
@@ -280,7 +280,7 @@
    shutdown request using the PSCI SYSTEM_OFF API.
 
 Known Issues
-============
+------------
 
 -  Building TF with compiler optimisations disabled (-O0) fails.
 
diff --git a/docs/cpu-specific-build-macros.rst b/docs/cpu-specific-build-macros.rst
index ce564a2..5738927 100644
--- a/docs/cpu-specific-build-macros.rst
+++ b/docs/cpu-specific-build-macros.rst
@@ -51,10 +51,20 @@
 -  ``ERRATA_A53_826319``: This applies errata 826319 workaround to Cortex-A53
    CPU. This needs to be enabled only for revision <= r0p2 of the CPU.
 
+-  ``ERRATA_A53_835769``: This applies erratum 835769 workaround at compile and
+   link time to Cortex-A53 CPU. This needs to be enabled for some variants of
+   revision <= r0p4. This workaround can lead the linker to create ``*.stub``
+   sections.
+
 -  ``ERRATA_A53_836870``: This applies errata 836870 workaround to Cortex-A53
    CPU. This needs to be enabled only for revision <= r0p3 of the CPU. From
    r0p4 and onwards, this errata is enabled by default in hardware.
 
+-  ``ERRATA_A53_843419``: This applies erratum 843419 workaround at link time
+   to Cortex-A53 CPU.  This needs to be enabled for some variants of revision
+   <= r0p4. This workaround can lead the linker to emit ``*.stub`` sections
+   which are 4kB aligned.
+
 -  ``ERRATA_A53_855873``: This applies errata 855873 workaround to Cortex-A53
    CPUs. Though the erratum is present in every revision of the CPU,
    this workaround is only applied to CPUs from r0p3 onwards, which feature
diff --git a/docs/platform-migration-guide.rst b/docs/platform-migration-guide.rst
index 5e8eeba..638033e 100644
--- a/docs/platform-migration-guide.rst
+++ b/docs/platform-migration-guide.rst
@@ -146,6 +146,7 @@
         void (*cpu_standby)(plat_local_state_t cpu_state);
         int (*pwr_domain_on)(u_register_t mpidr);
         void (*pwr_domain_off)(const psci_power_state_t *target_state);
+        void (*pwr_domain_suspend_early)(const psci_power_state_t *target_state);
         void (*pwr_domain_suspend)(const psci_power_state_t *target_state);
         void (*pwr_domain_on_finish)(const psci_power_state_t *target_state);
         void (*pwr_domain_suspend_finish)(
@@ -170,12 +171,12 @@
 passed in a PSCI ``CPU_SUSPEND`` to the ``psci_power_state`` format. This handler
 is now mandatory for PSCI ``CPU_SUSPEND`` support.
 
-The ``plat_psci_ops`` handlers, ``pwr_domain_off`` and ``pwr_domain_suspend``, are
-passed the target local state for each affected power domain. The platform
-must execute operations specific to these target states. Similarly,
-``pwr_domain_on_finish`` and ``pwr_domain_suspend_finish`` are passed the local
-states of the affected power domains before wakeup. The platform
-must execute actions to restore these power domains from these specific
+The ``plat_psci_ops`` handlers, ``pwr_domain_off``, ``pwr_domain_suspend_early``
+and ``pwr_domain_suspend``, are passed the target local state for each affected
+power domain. The platform must execute operations specific to these target
+states. Similarly, ``pwr_domain_on_finish`` and ``pwr_domain_suspend_finish``
+are passed the local states of the affected power domains before wakeup. The
+platform must execute actions to restore these power domains from these specific
 local states.
 
 -  Difference in invocation
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index 66fe0f1..bf8dea7 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -60,11 +60,16 @@
 instruction and data caches for each BL stage. Setting up the translation
 tables is the responsibility of the platform port because memory maps differ
 across platforms. A memory translation library (see ``lib/xlat_tables/``) is
-provided to help in this setup. Note that although this library supports
-non-identity mappings, this is intended only for re-mapping peripheral physical
-addresses and allows platforms with high I/O addresses to reduce their virtual
-address space. All other addresses corresponding to code and data must currently
-use an identity mapping.
+provided to help in this setup.
+
+Note that although this library supports non-identity mappings, this is intended
+only for re-mapping peripheral physical addresses and allows platforms with high
+I/O addresses to reduce their virtual address space. All other addresses
+corresponding to code and data must currently use an identity mapping.
+
+Also, the only translation granule size supported in Trusted Firmware is 4KB, as
+various parts of the code assume that is the case. It is not possible to switch
+to 16 KB or 64 KB granule sizes at the moment.
 
 In ARM standard platforms, each BL stage configures the MMU in the
 platform-specific architecture setup function, ``blX_plat_arch_setup()``, and uses
@@ -2055,6 +2060,23 @@
 for the higher power domain levels depending on the result of state
 coordination. The generic code expects the handler to succeed.
 
+plat\_psci\_ops.pwr\_domain\_suspend\_pwrdown\_early() [optional]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This optional function may be used as a performance optimization to replace
+or complement pwr_domain_suspend() on some platforms. Its calling semantics
+are identical to pwr_domain_suspend(), except the PSCI implementation only
+calls this function when suspending to a power down state, and it guarantees
+that data caches are enabled.
+
+When HW_ASSISTED_COHERENCY = 0, the PSCI implementation disables data caches
+before calling pwr_domain_suspend(). If the target_state corresponds to a
+power down state and it is safe to perform some or all of the platform
+specific actions in that function with data caches enabled, it may be more
+efficient to move those actions to this function. When HW_ASSISTED_COHERENCY
+= 1, data caches remain enabled throughout, and so there is no advantage to
+moving platform specific actions to this function.
+
 plat\_psci\_ops.pwr\_domain\_suspend()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/docs/user-guide.rst b/docs/user-guide.rst
index 6b82e3d..ec8c233 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -337,6 +337,11 @@
    Currently, only PSCI is instrumented. Enabling this option enables
    the ``ENABLE_PMF`` build option as well. Default is 0.
 
+-  ``ENABLE_SPE_FOR_LOWER_ELS`` : Boolean option to enable Statistical Profiling
+   extensions. This is an optional architectural feature available only for
+   AArch64 8.2 onwards. This option defaults to 1 but is automatically
+   disabled when the target architecture is AArch32 or AArch64 8.0/8.1.
+
 -  ``ENABLE_STACK_PROTECTOR``: String option to enable the stack protection
    checks in GCC. Allowed values are "all", "strong" and "0" (default).
    "strong" is the recommended stack protection level if this feature is
@@ -563,11 +568,6 @@
    cluster platforms). If this option is enabled, then warm boot path
    enables D-caches immediately after enabling MMU. This option defaults to 0.
 
--  ``ENABLE_SPE_FOR_LOWER_ELS`` : Boolean option to enable Statistical Profiling
-   extensions. This is an optional architectural feature available only for
-   AArch64 8.2 onwards. This option defaults to 1 but is automatically
-   disabled when the target architecture is AArch32 or AArch64 8.0/8.1.
-
 ARM development platform specific build options
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/include/lib/psci/psci.h b/include/lib/psci/psci.h
index fee6a24..0ed39c9 100644
--- a/include/lib/psci/psci.h
+++ b/include/lib/psci/psci.h
@@ -267,6 +267,8 @@
 	void (*cpu_standby)(plat_local_state_t cpu_state);
 	int (*pwr_domain_on)(u_register_t mpidr);
 	void (*pwr_domain_off)(const psci_power_state_t *target_state);
+	void (*pwr_domain_suspend_pwrdown_early)(
+				const psci_power_state_t *target_state);
 	void (*pwr_domain_suspend)(const psci_power_state_t *target_state);
 	void (*pwr_domain_on_finish)(const psci_power_state_t *target_state);
 	void (*pwr_domain_suspend_finish)(
diff --git a/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h b/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h
new file mode 100644
index 0000000..a418d2d
--- /dev/null
+++ b/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __XLAT_TABLES_AARCH32_H__
+#define __XLAT_TABLES_AARCH32_H__
+
+#include <arch.h>
+#include <utils_def.h>
+#include <xlat_tables_defs.h>
+
+#if !defined(PAGE_SIZE)
+#error "PAGE_SIZE is not defined."
+#endif
+
+/*
+ * In AArch32 state, the MMU only supports 4KB page granularity, which means
+ * that the first translation table level is either 1 or 2. Both of them are
+ * allowed to have block and table descriptors. See section G4.5.6 of the
+ * ARMv8-A Architecture Reference Manual (DDI 0487A.k) for more information.
+ *
+ * The define below specifies the first table level that allows block
+ * descriptors.
+ */
+#if PAGE_SIZE != (4 * 1024)
+#error "Invalid granule size. AArch32 supports 4KB pages only."
+#endif
+
+#define MIN_LVL_BLOCK_DESC	U(1)
+
+#define XLAT_TABLE_LEVEL_MIN	U(1)
+
+/*
+ * Define the architectural limits of the virtual address space in AArch32
+ * state.
+ *
+ * TTBCR.TxSZ is calculated as 32 minus the width of said address space. The
+ * value of TTBCR.TxSZ must be in the range 0 to 7 [1], which means that the
+ * virtual address space width must be in the range 32 to 25 bits.
+ *
+ * [1] See the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more
+ * information, Section G4.6.5
+ */
+#define MIN_VIRT_ADDR_SPACE_SIZE	(ULL(1) << (32 - TTBCR_TxSZ_MAX))
+#define MAX_VIRT_ADDR_SPACE_SIZE	(ULL(1) << (32 - TTBCR_TxSZ_MIN))
+
+/*
+ * Here we calculate the initial lookup level from the value of the given
+ * virtual address space size. For a 4 KB page size,
+ * - level 1 supports virtual address spaces of widths 32 to 31 bits;
+ * - level 2 from 30 to 25.
+ *
+ * Wider or narrower address spaces are not supported. As a result, level 3
+ * cannot be used as the initial lookup level with 4 KB granularity.
+ * See the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more
+ * information, Section G4.6.5
+ *
+ * For example, for a 31-bit address space (i.e. virt_addr_space_size ==
+ * 1 << 31), TTBCR.TxSZ will be programmed to (32 - 31) = 1. According to Table
+ * G4-5 in the ARM ARM, the initial lookup level for an address space like that
+ * is 1.
+ *
+ * Note that this macro assumes that the given virtual address space size is
+ * valid. Therefore, the caller is expected to check it is the case using the
+ * CHECK_VIRT_ADDR_SPACE_SIZE() macro first.
+ */
+#define GET_XLAT_TABLE_LEVEL_BASE(virt_addr_space_size)			\
+	(((virt_addr_space_size) > (ULL(1) << L1_XLAT_ADDRESS_SHIFT)) ? 1 : 2)
+
+#endif /* __XLAT_TABLES_AARCH32_H__ */
diff --git a/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h b/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h
new file mode 100644
index 0000000..7381bc8
--- /dev/null
+++ b/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __XLAT_TABLES_AARCH64_H__
+#define __XLAT_TABLES_AARCH64_H__
+
+#include <arch.h>
+#include <utils_def.h>
+#include <xlat_tables_defs.h>
+
+#if !defined(PAGE_SIZE)
+#error "PAGE_SIZE is not defined."
+#endif
+
+/*
+ * In AArch64 state, the MMU may support 4 KB, 16 KB and 64 KB page
+ * granularity. For 4KB granularity, a level 0 table descriptor doesn't support
+ * block translation. For 16KB, the same thing happens to levels 0 and 1. For
+ * 64KB, same for level 1. See section D4.3.1 of the ARMv8-A Architecture
+ * Reference Manual (DDI 0487A.k) for more information.
+ *
+ * The define below specifies the first table level that allows block
+ * descriptors.
+ */
+#if PAGE_SIZE == (4 * 1024)
+# define MIN_LVL_BLOCK_DESC	U(1)
+#elif PAGE_SIZE == (16 * 1024) || PAGE_SIZE == (64 * 1024)
+# define MIN_LVL_BLOCK_DESC	U(2)
+#endif
+
+#define XLAT_TABLE_LEVEL_MIN	U(0)
+
+/*
+ * Define the architectural limits of the virtual address space in AArch64
+ * state.
+ *
+ * TCR.TxSZ is calculated as 64 minus the width of said address space.
+ * The value of TCR.TxSZ must be in the range 16 to 39 [1], which means that
+ * the virtual address space width must be in the range 48 to 25 bits.
+ *
+ * [1] See the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more
+ * information:
+ * Page 1730: 'Input address size', 'For all translation stages'.
+ */
+#define MIN_VIRT_ADDR_SPACE_SIZE	(ULL(1) << (64 - TCR_TxSZ_MAX))
+#define MAX_VIRT_ADDR_SPACE_SIZE	(ULL(1) << (64 - TCR_TxSZ_MIN))
+
+/*
+ * Here we calculate the initial lookup level from the value of the given
+ * virtual address space size. For a 4 KB page size,
+ * - level 0 supports virtual address spaces of widths 48 to 40 bits;
+ * - level 1 from 39 to 31;
+ * - level 2 from 30 to 25.
+ *
+ * Wider or narrower address spaces are not supported. As a result, level 3
+ * cannot be used as initial lookup level with 4 KB granularity. See section
+ * D4.2.5 in the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more
+ * information.
+ *
+ * For example, for a 35-bit address space (i.e. virt_addr_space_size ==
+ * 1 << 35), TCR.TxSZ will be programmed to (64 - 35) = 29. According to Table
+ * D4-11 in the ARM ARM, the initial lookup level for an address space like that
+ * is 1.
+ *
+ * Note that this macro assumes that the given virtual address space size is
+ * valid. Therefore, the caller is expected to check it is the case using the
+ * CHECK_VIRT_ADDR_SPACE_SIZE() macro first.
+ */
+#define GET_XLAT_TABLE_LEVEL_BASE(virt_addr_space_size)				\
+	(((virt_addr_space_size) > (ULL(1) << L0_XLAT_ADDRESS_SHIFT))		\
+	? 0									\
+	 : (((virt_addr_space_size) > (ULL(1) << L1_XLAT_ADDRESS_SHIFT))	\
+	 ? 1 : 2))
+
+#endif /* __XLAT_TABLES_AARCH64_H__ */
diff --git a/include/lib/xlat_tables/xlat_tables_arch.h b/include/lib/xlat_tables/xlat_tables_arch.h
new file mode 100644
index 0000000..165b161d
--- /dev/null
+++ b/include/lib/xlat_tables/xlat_tables_arch.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __XLAT_TABLES_ARCH_H__
+#define __XLAT_TABLES_ARCH_H__
+
+#ifdef AARCH32
+#include "aarch32/xlat_tables_aarch32.h"
+#else
+#include "aarch64/xlat_tables_aarch64.h"
+#endif
+
+/*
+ * Evaluates to 1 if the given virtual address space size is valid, or 0 if it's
+ * not.
+ *
+ * A valid size is one that is a power of 2 and is within the architectural
+ * limits. Not that these limits are different for AArch32 and AArch64.
+ */
+#define CHECK_VIRT_ADDR_SPACE_SIZE(size)			\
+	(((size) >= MIN_VIRT_ADDR_SPACE_SIZE) &&		\
+	((size) <= MAX_VIRT_ADDR_SPACE_SIZE) &&			\
+	IS_POWER_OF_TWO(size))
+
+/*
+ * Evaluates to 1 if the given physical address space size is a power of 2,
+ * or 0 if it's not.
+ */
+#define CHECK_PHY_ADDR_SPACE_SIZE(size)				\
+	(IS_POWER_OF_TWO(size))
+
+/*
+ * Compute the number of entries required at the initial lookup level to address
+ * the whole virtual address space.
+ */
+#define GET_NUM_BASE_LEVEL_ENTRIES(addr_space_size)			\
+	((addr_space_size) >>						\
+		XLAT_ADDR_SHIFT(GET_XLAT_TABLE_LEVEL_BASE(addr_space_size)))
+
+#endif /* __XLAT_TABLES_ARCH_H__ */
diff --git a/include/lib/xlat_tables/xlat_tables_defs.h b/include/lib/xlat_tables/xlat_tables_defs.h
index 4b993a0..008ae9b 100644
--- a/include/lib/xlat_tables/xlat_tables_defs.h
+++ b/include/lib/xlat_tables/xlat_tables_defs.h
@@ -48,7 +48,11 @@
 
 #define TABLE_ADDR_MASK		ULL(0x0000FFFFFFFFF000)
 
-#define PAGE_SIZE_SHIFT		FOUR_KB_SHIFT /* 4, 16 or 64 KB */
+/*
+ * The ARMv8-A architecture allows translation granule sizes of 4KB, 16KB or
+ * 64KB. However, TF only supports the 4KB case at the moment.
+ */
+#define PAGE_SIZE_SHIFT		FOUR_KB_SHIFT
 #define PAGE_SIZE		(U(1) << PAGE_SIZE_SHIFT)
 #define PAGE_SIZE_MASK		(PAGE_SIZE - 1)
 #define IS_PAGE_ALIGNED(addr)	(((addr) & PAGE_SIZE_MASK) == 0)
@@ -59,12 +63,6 @@
 #define XLAT_TABLE_SIZE_SHIFT	PAGE_SIZE_SHIFT /* Size of one complete table */
 #define XLAT_TABLE_SIZE		(U(1) << XLAT_TABLE_SIZE_SHIFT)
 
-#ifdef AARCH32
-#define XLAT_TABLE_LEVEL_MIN	U(1)
-#else
-#define XLAT_TABLE_LEVEL_MIN	U(0)
-#endif /* AARCH32 */
-
 #define XLAT_TABLE_LEVEL_MAX	U(3)
 
 /* Values for number of entries in each MMU translation table */
diff --git a/include/lib/xlat_tables/xlat_tables_v2.h b/include/lib/xlat_tables/xlat_tables_v2.h
index 9db6719..288a8e0 100644
--- a/include/lib/xlat_tables/xlat_tables_v2.h
+++ b/include/lib/xlat_tables/xlat_tables_v2.h
@@ -13,6 +13,7 @@
 #include <stddef.h>
 #include <stdint.h>
 #include <xlat_mmu_helpers.h>
+#include <xlat_tables_v2_helpers.h>
 
 /* Helper macro to define entries for mmap_region_t. It creates
  * identity mappings for each region.
@@ -82,14 +83,59 @@
 	mmap_attr_t		attr;
 } mmap_region_t;
 
-/* Generic translation table APIs */
+/*
+ * Declare the translation context type.
+ * Its definition is private.
+ */
+typedef struct xlat_ctx xlat_ctx_t;
 
 /*
+ * Statically allocate a translation context and associated structures. Also
+ * initialize them.
+ *
+ * _ctx_name:
+ *   Prefix for the translation context variable.
+ *   E.g. If _ctx_name is 'foo', the variable will be called 'foo_xlat_ctx'.
+ *   Useful to distinguish multiple contexts from one another.
+ *
+ * _mmap_count:
+ *   Number of mmap_region_t to allocate.
+ *   Would typically be MAX_MMAP_REGIONS for the translation context describing
+ *   the BL image currently executing.
+ *
+ * _xlat_tables_count:
+ *   Number of sub-translation tables to allocate.
+ *   Would typically be MAX_XLAT_TABLES for the translation context describing
+ *   the BL image currently executing.
+ *   Note that this is only for sub-tables ; at the initial lookup level, there
+ *   is always a single table.
+ *
+ * _virt_addr_space_size, _phy_addr_space_size:
+ *   Size (in bytes) of the virtual (resp. physical) address space.
+ *   Would typically be PLAT_VIRT_ADDR_SPACE_SIZE
+ *   (resp. PLAT_PHY_ADDR_SPACE_SIZE) for the translation context describing the
+ *   BL image currently executing.
+ */
+#define REGISTER_XLAT_CONTEXT(_ctx_name, _mmap_count, _xlat_tables_count,	\
+			_virt_addr_space_size, _phy_addr_space_size)		\
+	_REGISTER_XLAT_CONTEXT(_ctx_name, _mmap_count, _xlat_tables_count,	\
+		_virt_addr_space_size, _phy_addr_space_size)
+
+/******************************************************************************
+ * Generic translation table APIs.
+ * Each API comes in 2 variants:
+ * - one that acts on the current translation context for this BL image
+ * - another that acts on the given translation context instead. This variant
+ *   is named after the 1st version, with an additional '_ctx' suffix.
+ *****************************************************************************/
+
+/*
  * Initialize translation tables from the current list of mmap regions. Calling
  * this function marks the transition point after which static regions can no
  * longer be added.
  */
 void init_xlat_tables(void);
+void init_xlat_tables_ctx(xlat_ctx_t *ctx);
 
 /*
  * Add a static region with defined base PA and base VA. This function can only
@@ -98,7 +144,18 @@
  */
 void mmap_add_region(unsigned long long base_pa, uintptr_t base_va,
 				size_t size, mmap_attr_t attr);
+void mmap_add_region_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm);
+
+/*
+ * Add an array of static regions with defined base PA and base VA. This
+ * function can only be used before initializing the translation tables. The
+ * regions cannot be removed afterwards.
+ */
+void mmap_add(const mmap_region_t *mm);
+void mmap_add_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm);
 
+
+#if PLAT_XLAT_TABLES_DYNAMIC
 /*
  * Add a dynamic region with defined base PA and base VA. This type of region
  * can be added and removed even after the translation tables are initialized.
@@ -112,15 +169,9 @@
  */
 int mmap_add_dynamic_region(unsigned long long base_pa, uintptr_t base_va,
 				size_t size, mmap_attr_t attr);
+int mmap_add_dynamic_region_ctx(xlat_ctx_t *ctx, mmap_region_t *mm);
 
 /*
- * Add an array of static regions with defined base PA and base VA. This
- * function can only be used before initializing the translation tables. The
- * regions cannot be removed afterwards.
- */
-void mmap_add(const mmap_region_t *mm);
-
-/*
  * Remove a region with the specified base VA and size. Only dynamic regions can
  * be removed, and they can be removed even if the translation tables are
  * initialized.
@@ -131,6 +182,11 @@
  *    EPERM: Trying to remove a static region.
  */
 int mmap_remove_dynamic_region(uintptr_t base_va, size_t size);
+int mmap_remove_dynamic_region_ctx(xlat_ctx_t *ctx,
+				uintptr_t base_va,
+				size_t size);
+
+#endif /* PLAT_XLAT_TABLES_DYNAMIC */
 
 #endif /*__ASSEMBLY__*/
 #endif /* __XLAT_TABLES_V2_H__ */
diff --git a/include/lib/xlat_tables/xlat_tables_v2_helpers.h b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
new file mode 100644
index 0000000..f5e3100
--- /dev/null
+++ b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * This header file contains internal definitions that are not supposed to be
+ * used outside of this library code.
+ */
+
+#ifndef __XLAT_TABLES_V2_HELPERS_H__
+#define __XLAT_TABLES_V2_HELPERS_H__
+
+#ifndef __XLAT_TABLES_V2_H__
+#error "Do not include this header file directly. Include xlat_tables_v2.h instead."
+#endif
+
+#ifndef __ASSEMBLY__
+
+#include <cassert.h>
+#include <platform_def.h>
+#include <stddef.h>
+#include <xlat_tables_arch.h>
+#include <xlat_tables_defs.h>
+
+/* Forward declaration */
+struct mmap_region;
+
+/* Struct that holds all information about the translation tables. */
+struct xlat_ctx {
+	/*
+	 * Max allowed Virtual and Physical Addresses.
+	 */
+	unsigned long long pa_max_address;
+	uintptr_t va_max_address;
+
+	/*
+	 * Array of all memory regions stored in order of ascending end address
+	 * and ascending size to simplify the code that allows overlapping
+	 * regions. The list is terminated by the first entry with size == 0.
+	 * The max size of the list is stored in `mmap_num`. `mmap` points to an
+	 * array of mmap_num + 1 elements, so that there is space for the final
+	 * null entry.
+	 */
+	struct mmap_region *mmap;
+	unsigned int mmap_num;
+
+	/*
+	 * Array of finer-grain translation tables.
+	 * For example, if the initial lookup level is 1 then this array would
+	 * contain both level-2 and level-3 entries.
+	 */
+	uint64_t (*tables)[XLAT_TABLE_ENTRIES];
+	unsigned int tables_num;
+	/*
+	 * Keep track of how many regions are mapped in each table. The base
+	 * table can't be unmapped so it isn't needed to keep track of it.
+	 */
+#if PLAT_XLAT_TABLES_DYNAMIC
+	int *tables_mapped_regions;
+#endif /* PLAT_XLAT_TABLES_DYNAMIC */
+
+	unsigned int next_table;
+
+	/*
+	 * Base translation table. It doesn't need to have the same amount of
+	 * entries as the ones used for other levels.
+	 */
+	uint64_t *base_table;
+	unsigned int base_table_entries;
+
+	/*
+	* Max Physical and Virtual addresses currently in use by the
+	* translation tables. These might get updated as we map/unmap memory
+	* regions but they will never go beyond pa/va_max_address.
+	*/
+	unsigned long long max_pa;
+	uintptr_t max_va;
+
+	/* Level of the base translation table. */
+	unsigned int base_level;
+
+	/* Set to 1 when the translation tables are initialized. */
+	unsigned int initialized;
+
+	/*
+	 * Bit mask that has to be ORed to the rest of a translation table
+	 * descriptor in order to prohibit execution of code at the exception
+	 * level of this translation context.
+	 */
+	uint64_t execute_never_mask;
+};
+
+#if PLAT_XLAT_TABLES_DYNAMIC
+#define _ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count)		\
+	static int _ctx_name##_mapped_regions[_xlat_tables_count];
+
+#define _REGISTER_DYNMAP_STRUCT(_ctx_name)				\
+	.tables_mapped_regions = _ctx_name##_mapped_regions,
+#else
+#define _ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count)		\
+	/* do nothing */
+
+#define _REGISTER_DYNMAP_STRUCT(_ctx_name)				\
+	/* do nothing */
+#endif /* PLAT_XLAT_TABLES_DYNAMIC */
+
+
+#define _REGISTER_XLAT_CONTEXT(_ctx_name, _mmap_count, _xlat_tables_count,	\
+			_virt_addr_space_size, _phy_addr_space_size)		\
+	CASSERT(CHECK_VIRT_ADDR_SPACE_SIZE(_virt_addr_space_size),		\
+		assert_invalid_virtual_addr_space_size_for_##_ctx_name);	\
+										\
+	CASSERT(CHECK_PHY_ADDR_SPACE_SIZE(_phy_addr_space_size),		\
+		assert_invalid_physical_addr_space_sizefor_##_ctx_name);	\
+										\
+	static mmap_region_t _ctx_name##_mmap[_mmap_count + 1];			\
+										\
+	static uint64_t _ctx_name##_xlat_tables[_xlat_tables_count]		\
+		[XLAT_TABLE_ENTRIES]						\
+		__aligned(XLAT_TABLE_SIZE) __section("xlat_table");		\
+										\
+	static uint64_t _ctx_name##_base_xlat_table				\
+		[GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)]		\
+		__aligned(GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)	\
+			* sizeof(uint64_t));					\
+										\
+	_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count)			\
+										\
+	static xlat_ctx_t _ctx_name##_xlat_ctx = {				\
+		.va_max_address = (_virt_addr_space_size) - 1,			\
+		.pa_max_address = (_phy_addr_space_size) - 1,			\
+		.mmap = _ctx_name##_mmap,					\
+		.mmap_num = _mmap_count,					\
+		.base_level = GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_size),	\
+		.base_table = _ctx_name##_base_xlat_table,			\
+		.base_table_entries =						\
+			GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size),	\
+		.tables = _ctx_name##_xlat_tables,				\
+		.tables_num = _xlat_tables_count,				\
+		 _REGISTER_DYNMAP_STRUCT(_ctx_name)				\
+		.max_pa = 0,							\
+		.max_va = 0,							\
+		.next_table = 0,						\
+		.initialized = 0,						\
+	}
+
+#endif /*__ASSEMBLY__*/
+
+#endif /* __XLAT_TABLES_V2_HELPERS_H__ */
diff --git a/include/plat/arm/css/common/css_def.h b/include/plat/arm/css/common/css_def.h
index 0b74ced..9d025f6 100644
--- a/include/plat/arm/css/common/css_def.h
+++ b/include/plat/arm/css/common/css_def.h
@@ -128,16 +128,22 @@
  * an SCP_BL2/SCP_BL2U image.
  */
 #if CSS_LOAD_SCP_IMAGES
+
+#if ARM_BL31_IN_DRAM
+#error "SCP_BL2 is not expected to be loaded by BL2 for ARM_BL31_IN_DRAM config"
+#endif
+
 /*
  * Load address of SCP_BL2 in CSS platform ports
- * SCP_BL2 is loaded to the same place as BL31.  Once SCP_BL2 is transferred to the
- * SCP, it is discarded and BL31 is loaded over the top.
+ * SCP_BL2 is loaded to the same place as BL31 but it shouldn't overwrite BL1
+ * rw data.  Once SCP_BL2 is transferred to the SCP, it is discarded and BL31
+ * is loaded over the top.
  */
-#define SCP_BL2_BASE			BL31_BASE
-#define SCP_BL2_LIMIT			(SCP_BL2_BASE + PLAT_CSS_MAX_SCP_BL2_SIZE)
+#define SCP_BL2_BASE			(BL1_RW_BASE - PLAT_CSS_MAX_SCP_BL2_SIZE)
+#define SCP_BL2_LIMIT			BL1_RW_BASE
 
-#define SCP_BL2U_BASE			BL31_BASE
-#define SCP_BL2U_LIMIT			(SCP_BL2U_BASE + PLAT_CSS_MAX_SCP_BL2U_SIZE)
+#define SCP_BL2U_BASE			(BL1_RW_BASE - PLAT_CSS_MAX_SCP_BL2U_SIZE)
+#define SCP_BL2U_LIMIT			BL1_RW_BASE
 #endif /* CSS_LOAD_SCP_IMAGES */
 
 /* Load address of Non-Secure Image for CSS platform ports */
diff --git a/include/plat/arm/soc/common/soc_css_def.h b/include/plat/arm/soc/common/soc_css_def.h
index dc3d7dc..3206f4e 100644
--- a/include/plat/arm/soc/common/soc_css_def.h
+++ b/include/plat/arm/soc/common/soc_css_def.h
@@ -24,8 +24,8 @@
 #define SOC_CSS_UART0_BASE		0x7ff80000
 #define SOC_CSS_UART1_BASE		0x7ff70000
 
-#define SOC_CSS_UART0_CLK_IN_HZ		7273800
-#define SOC_CSS_UART1_CLK_IN_HZ		7273800
+#define SOC_CSS_UART0_CLK_IN_HZ		7372800
+#define SOC_CSS_UART1_CLK_IN_HZ		7372800
 
 /* SoC NIC-400 Global Programmers View (GPV) */
 #define SOC_CSS_NIC400_BASE		0x7fd00000
diff --git a/lib/compiler-rt/builtins/ctzdi2.c b/lib/compiler-rt/builtins/ctzdi2.c
new file mode 100644
index 0000000..db3c6fd
--- /dev/null
+++ b/lib/compiler-rt/builtins/ctzdi2.c
@@ -0,0 +1,29 @@
+/* ===-- ctzdi2.c - Implement __ctzdi2 -------------------------------------===
+ *
+ *                     The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ *
+ * This file implements __ctzdi2 for the compiler_rt library.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#include "int_lib.h"
+
+/* Returns: the number of trailing 0-bits  */
+
+/* Precondition: a != 0 */
+
+COMPILER_RT_ABI si_int
+__ctzdi2(di_int a)
+{
+    dwords x;
+    x.all = a;
+    const si_int f = -(x.s.low == 0);
+    return __builtin_ctz((x.s.high & f) | (x.s.low & ~f)) +
+              (f & ((si_int)(sizeof(si_int) * CHAR_BIT)));
+}
diff --git a/lib/compiler-rt/compiler-rt.mk b/lib/compiler-rt/compiler-rt.mk
index 3bdd319..cb5ab31 100644
--- a/lib/compiler-rt/compiler-rt.mk
+++ b/lib/compiler-rt/compiler-rt.mk
@@ -30,5 +30,6 @@
 
 ifeq (${ARCH},aarch32)
 COMPILER_RT_SRCS	:=	lib/compiler-rt/builtins/arm/aeabi_uldivmod.S	\
-				lib/compiler-rt/builtins/udivmoddi4.c
+				lib/compiler-rt/builtins/udivmoddi4.c		\
+				lib/compiler-rt/builtins/ctzdi2.c
 endif
diff --git a/lib/psci/psci_on.c b/lib/psci/psci_on.c
index 16b22c2..d3d0e2f 100644
--- a/lib/psci/psci_on.c
+++ b/lib/psci/psci_on.c
@@ -64,7 +64,20 @@
 	/*
 	 * Generic management: Ensure that the cpu is off to be
 	 * turned on.
+	 * Perform cache maintanence ahead of reading the target CPU state to
+	 * ensure that the data is not stale.
+	 * There is a theoretical edge case where the cache may contain stale
+	 * data for the target CPU data - this can occur under the following
+	 * conditions:
+	 * - the target CPU is in another cluster from the current
+	 * - the target CPU was the last CPU to shutdown on its cluster
+	 * - the cluster was removed from coherency as part of the CPU shutdown
+	 *
+	 * In this case the cache maintenace that was performed as part of the
+	 * target CPUs shutdown was not seen by the current CPU's cluster. And
+	 * so the cache may contain stale data for the target CPU.
 	 */
+	flush_cpu_data_by_index(target_idx, psci_svc_cpu_data.aff_info_state);
 	rc = cpu_on_validate_state(psci_get_aff_info_state_by_idx(target_idx));
 	if (rc != PSCI_E_SUCCESS)
 		goto exit;
diff --git a/lib/psci/psci_suspend.c b/lib/psci/psci_suspend.c
index 0d1589e..40ecdee 100644
--- a/lib/psci/psci_suspend.c
+++ b/lib/psci/psci_suspend.c
@@ -80,6 +80,17 @@
 	if (psci_spd_pm && psci_spd_pm->svc_suspend)
 		psci_spd_pm->svc_suspend(max_off_lvl);
 
+#if !HW_ASSISTED_COHERENCY
+	/*
+	 * Plat. management: Allow the platform to perform any early
+	 * actions required to power down the CPU. This might be useful for
+	 * HW_ASSISTED_COHERENCY = 0 platforms that can safely perform these
+	 * actions with data caches enabled.
+	 */
+	if (psci_plat_pm_ops->pwr_domain_suspend_pwrdown_early)
+		psci_plat_pm_ops->pwr_domain_suspend_pwrdown_early(state_info);
+#endif
+
 	/*
 	 * Store the re-entry information for the non-secure world.
 	 */
diff --git a/lib/stdlib/assert.c b/lib/stdlib/assert.c
index 41f7070..97fab4b 100644
--- a/lib/stdlib/assert.c
+++ b/lib/stdlib/assert.c
@@ -17,14 +17,14 @@
 #if PLAT_LOG_LEVEL_ASSERT >= LOG_LEVEL_VERBOSE
 void __assert(const char *file, unsigned int line, const char *assertion)
 {
-	tf_printf("ASSERT: %s <%d> : %s\n", file, line, assertion);
+	tf_printf("ASSERT: %s:%d:%s\n", file, line, assertion);
 	console_flush();
 	plat_panic_handler();
 }
 #elif PLAT_LOG_LEVEL_ASSERT >= LOG_LEVEL_INFO
 void __assert(const char *file, unsigned int line)
 {
-	tf_printf("ASSERT: %s <%d>\n", file, line);
+	tf_printf("ASSERT: %s:%d\n", file, line);
 	console_flush();
 	plat_panic_handler();
 }
diff --git a/lib/xlat_tables/aarch32/xlat_tables.c b/lib/xlat_tables/aarch32/xlat_tables.c
index 9c15624..c7e34f2 100644
--- a/lib/xlat_tables/aarch32/xlat_tables.c
+++ b/lib/xlat_tables/aarch32/xlat_tables.c
@@ -7,56 +7,17 @@
 #include <arch.h>
 #include <arch_helpers.h>
 #include <assert.h>
-#include <cassert.h>
 #include <platform_def.h>
 #include <utils.h>
+#include <xlat_tables_arch.h>
 #include <xlat_tables.h>
 #include "../xlat_tables_private.h"
 
-/*
- * Each platform can define the size of the virtual address space, which is
- * defined in PLAT_VIRT_ADDR_SPACE_SIZE. TTBCR.TxSZ is calculated as 32 minus
- * the width of said address space. The value of TTBCR.TxSZ must be in the
- * range 0 to 7 [1], which means that the virtual address space width must be
- * in the range 32 to 25 bits.
- *
- * Here we calculate the initial lookup level from the value of
- * PLAT_VIRT_ADDR_SPACE_SIZE. For a 4 KB page size, level 1 supports virtual
- * address spaces of widths 32 to 31 bits, and level 2 from 30 to 25. Wider or
- * narrower address spaces are not supported. As a result, level 3 cannot be
- * used as initial lookup level with 4 KB granularity [1].
- *
- * For example, for a 31-bit address space (i.e. PLAT_VIRT_ADDR_SPACE_SIZE ==
- * 1 << 31), TTBCR.TxSZ will be programmed to (32 - 31) = 1. According to Table
- * G4-5 in the ARM ARM, the initial lookup level for an address space like that
- * is 1.
- *
- * See the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more
- * information:
- * [1] Section G4.6.5
- */
+#define XLAT_TABLE_LEVEL_BASE	\
+       GET_XLAT_TABLE_LEVEL_BASE(PLAT_VIRT_ADDR_SPACE_SIZE)
 
-#if PLAT_VIRT_ADDR_SPACE_SIZE > (1ULL << (32 - TTBCR_TxSZ_MIN))
-
-# error "PLAT_VIRT_ADDR_SPACE_SIZE is too big."
-
-#elif PLAT_VIRT_ADDR_SPACE_SIZE > (1 << L1_XLAT_ADDRESS_SHIFT)
-
-# define XLAT_TABLE_LEVEL_BASE	1
-# define NUM_BASE_LEVEL_ENTRIES	\
-		(PLAT_VIRT_ADDR_SPACE_SIZE >> L1_XLAT_ADDRESS_SHIFT)
-
-#elif PLAT_VIRT_ADDR_SPACE_SIZE >= (1 << (32 - TTBCR_TxSZ_MAX))
-
-# define XLAT_TABLE_LEVEL_BASE	2
-# define NUM_BASE_LEVEL_ENTRIES	\
-		(PLAT_VIRT_ADDR_SPACE_SIZE >> L2_XLAT_ADDRESS_SHIFT)
-
-#else
-
-# error "PLAT_VIRT_ADDR_SPACE_SIZE is too small."
-
-#endif
+#define NUM_BASE_LEVEL_ENTRIES	\
+       GET_NUM_BASE_LEVEL_ENTRIES(PLAT_VIRT_ADDR_SPACE_SIZE)
 
 static uint64_t base_xlation_table[NUM_BASE_LEVEL_ENTRIES]
 		__aligned(NUM_BASE_LEVEL_ENTRIES * sizeof(uint64_t));
@@ -127,13 +88,13 @@
 		ttbcr = TTBCR_EAE_BIT |
 			TTBCR_SH0_NON_SHAREABLE | TTBCR_RGN0_OUTER_NC |
 			TTBCR_RGN0_INNER_NC |
-			(32 - __builtin_ctzl((uintptr_t)PLAT_VIRT_ADDR_SPACE_SIZE));
+			(32 - __builtin_ctzll(PLAT_VIRT_ADDR_SPACE_SIZE));
 	} else {
 		/* Inner & outer WBWA & shareable. */
 		ttbcr = TTBCR_EAE_BIT |
 			TTBCR_SH0_INNER_SHAREABLE | TTBCR_RGN0_OUTER_WBA |
 			TTBCR_RGN0_INNER_WBA |
-			(32 - __builtin_ctzl((uintptr_t)PLAT_VIRT_ADDR_SPACE_SIZE));
+			(32 - __builtin_ctzll(PLAT_VIRT_ADDR_SPACE_SIZE));
 	}
 	ttbcr |= TTBCR_EPD1_BIT;
 	write_ttbcr(ttbcr);
diff --git a/lib/xlat_tables/aarch64/xlat_tables.c b/lib/xlat_tables/aarch64/xlat_tables.c
index 309cb9b..2ddf8cb 100644
--- a/lib/xlat_tables/aarch64/xlat_tables.c
+++ b/lib/xlat_tables/aarch64/xlat_tables.c
@@ -8,66 +8,19 @@
 #include <arch_helpers.h>
 #include <assert.h>
 #include <bl_common.h>
-#include <cassert.h>
 #include <common_def.h>
 #include <platform_def.h>
 #include <sys/types.h>
 #include <utils.h>
 #include <xlat_tables.h>
+#include <xlat_tables_arch.h>
 #include "../xlat_tables_private.h"
 
-/*
- * Each platform can define the size of the virtual address space, which is
- * defined in PLAT_VIRT_ADDR_SPACE_SIZE. TCR.TxSZ is calculated as 64 minus the
- * width of said address space. The value of TCR.TxSZ must be in the range 16
- * to 39 [1], which means that the virtual address space width must be in the
- * range 48 to 25 bits.
- *
- * Here we calculate the initial lookup level from the value of
- * PLAT_VIRT_ADDR_SPACE_SIZE. For a 4 KB page size, level 0 supports virtual
- * address spaces of widths 48 to 40 bits, level 1 from 39 to 31, and level 2
- * from 30 to 25. Wider or narrower address spaces are not supported. As a
- * result, level 3 cannot be used as initial lookup level with 4 KB
- * granularity. [2]
- *
- * For example, for a 35-bit address space (i.e. PLAT_VIRT_ADDR_SPACE_SIZE ==
- * 1 << 35), TCR.TxSZ will be programmed to (64 - 35) = 29. According to Table
- * D4-11 in the ARM ARM, the initial lookup level for an address space like
- * that is 1.
- *
- * See the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more
- * information:
- * [1] Page 1730: 'Input address size', 'For all translation stages'.
- * [2] Section D4.2.5
- */
-
-#if PLAT_VIRT_ADDR_SPACE_SIZE > (1ULL << (64 - TCR_TxSZ_MIN))
-
-# error "PLAT_VIRT_ADDR_SPACE_SIZE is too big."
-
-#elif PLAT_VIRT_ADDR_SPACE_SIZE > (1ULL << L0_XLAT_ADDRESS_SHIFT)
-
-# define XLAT_TABLE_LEVEL_BASE	0
-# define NUM_BASE_LEVEL_ENTRIES	\
-		(PLAT_VIRT_ADDR_SPACE_SIZE >> L0_XLAT_ADDRESS_SHIFT)
-
-#elif PLAT_VIRT_ADDR_SPACE_SIZE > (1 << L1_XLAT_ADDRESS_SHIFT)
-
-# define XLAT_TABLE_LEVEL_BASE	1
-# define NUM_BASE_LEVEL_ENTRIES	\
-		(PLAT_VIRT_ADDR_SPACE_SIZE >> L1_XLAT_ADDRESS_SHIFT)
-
-#elif PLAT_VIRT_ADDR_SPACE_SIZE >= (1 << (64 - TCR_TxSZ_MAX))
-
-# define XLAT_TABLE_LEVEL_BASE	2
-# define NUM_BASE_LEVEL_ENTRIES	\
-		(PLAT_VIRT_ADDR_SPACE_SIZE >> L2_XLAT_ADDRESS_SHIFT)
-
-#else
-
-# error "PLAT_VIRT_ADDR_SPACE_SIZE is too small."
+#define XLAT_TABLE_LEVEL_BASE	\
+       GET_XLAT_TABLE_LEVEL_BASE(PLAT_VIRT_ADDR_SPACE_SIZE)
 
-#endif
+#define NUM_BASE_LEVEL_ENTRIES	\
+       GET_NUM_BASE_LEVEL_ENTRIES(PLAT_VIRT_ADDR_SPACE_SIZE)
 
 static uint64_t base_xlation_table[NUM_BASE_LEVEL_ENTRIES]
 		__aligned(NUM_BASE_LEVEL_ENTRIES * sizeof(uint64_t));
@@ -192,12 +145,12 @@
 			/* Inner & outer non-cacheable non-shareable. */\
 			tcr = TCR_SH_NON_SHAREABLE |			\
 				TCR_RGN_OUTER_NC | TCR_RGN_INNER_NC |	\
-				(64 - __builtin_ctzl(PLAT_VIRT_ADDR_SPACE_SIZE));\
+				(64 - __builtin_ctzll(PLAT_VIRT_ADDR_SPACE_SIZE));\
 		} else {						\
 			/* Inner & outer WBWA & shareable. */		\
 			tcr = TCR_SH_INNER_SHAREABLE |			\
 				TCR_RGN_OUTER_WBA | TCR_RGN_INNER_WBA |	\
-				(64 - __builtin_ctzl(PLAT_VIRT_ADDR_SPACE_SIZE));\
+				(64 - __builtin_ctzll(PLAT_VIRT_ADDR_SPACE_SIZE));\
 		}							\
 		tcr |= _tcr_extra;					\
 		write_tcr_el##_el(tcr);					\
diff --git a/lib/xlat_tables/xlat_tables_private.h b/lib/xlat_tables/xlat_tables_private.h
index b5c3ac8..50d6bd5 100644
--- a/lib/xlat_tables/xlat_tables_private.h
+++ b/lib/xlat_tables/xlat_tables_private.h
@@ -9,7 +9,7 @@
 
 #include <cassert.h>
 #include <platform_def.h>
-#include <utils_def.h>
+#include <xlat_tables_arch.h>
 
 /*
  * If the platform hasn't defined a physical and a virtual address space size
@@ -28,41 +28,14 @@
 # endif
 #endif
 
-/* The virtual and physical address space sizes must be powers of two. */
-CASSERT(IS_POWER_OF_TWO(PLAT_VIRT_ADDR_SPACE_SIZE),
+CASSERT(CHECK_VIRT_ADDR_SPACE_SIZE(PLAT_VIRT_ADDR_SPACE_SIZE),
 	assert_valid_virt_addr_space_size);
-CASSERT(IS_POWER_OF_TWO(PLAT_PHY_ADDR_SPACE_SIZE),
-	assert_valid_phy_addr_space_size);
-
-/*
- * In AArch32 state, the MMU only supports 4KB page granularity, which means
- * that the first translation table level is either 1 or 2. Both of them are
- * allowed to have block and table descriptors. See section G4.5.6 of the
- * ARMv8-A Architecture Reference Manual (DDI 0487A.k) for more information.
- *
- * In AArch64 state, the MMU may support 4 KB, 16 KB and 64 KB page
- * granularity. For 4KB granularity, a level 0 table descriptor doesn't support
- * block translation. For 16KB, the same thing happens to levels 0 and 1. For
- * 64KB, same for level 1. See section D4.3.1 of the ARMv8-A Architecture
- * Reference Manual (DDI 0487A.k) for more information.
- *
- * The define below specifies the first table level that allows block
- * descriptors.
- */
-
-#ifdef AARCH32
 
-# define XLAT_BLOCK_LEVEL_MIN 1
-
-#else /* if AArch64 */
-
-# if PAGE_SIZE == (4*1024) /* 4KB */
-#  define XLAT_BLOCK_LEVEL_MIN 1
-# else /* 16KB or 64KB */
-#  define XLAT_BLOCK_LEVEL_MIN 2
-# endif
+CASSERT(CHECK_PHY_ADDR_SPACE_SIZE(PLAT_PHY_ADDR_SPACE_SIZE),
+	assert_valid_phy_addr_space_size);
 
-#endif /* AARCH32 */
+/* Alias to retain compatibility with the old #define name */
+#define XLAT_BLOCK_LEVEL_MIN	MIN_LVL_BLOCK_DESC
 
 void print_mmap(void);
 
diff --git a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
index 40fd2d0..be18552 100644
--- a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
+++ b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
@@ -14,7 +14,7 @@
 #include "../xlat_tables_private.h"
 
 #if ENABLE_ASSERTIONS
-static unsigned long long xlat_arch_get_max_supported_pa(void)
+unsigned long long xlat_arch_get_max_supported_pa(void)
 {
 	/* Physical address space size for long descriptor format. */
 	return (1ull << 40) - 1ull;
@@ -81,24 +81,22 @@
 	return UPPER_ATTRS(XN);
 }
 
-void init_xlat_tables_arch(unsigned long long max_pa)
-{
-	assert((PLAT_PHY_ADDR_SPACE_SIZE - 1) <=
-	       xlat_arch_get_max_supported_pa());
-}
-
 /*******************************************************************************
- * Function for enabling the MMU in Secure PL1, assuming that the
- * page-tables have already been created.
+ * Function for enabling the MMU in Secure PL1, assuming that the page tables
+ * have already been created.
  ******************************************************************************/
-void enable_mmu_internal_secure(unsigned int flags, uint64_t *base_table)
-
+void enable_mmu_arch(unsigned int flags,
+		uint64_t *base_table,
+		unsigned long long max_pa,
+		uintptr_t max_va)
 {
 	u_register_t mair0, ttbcr, sctlr;
 	uint64_t ttbr0;
 
 	assert(IS_IN_SECURE());
-	assert((read_sctlr() & SCTLR_M_BIT) == 0);
+
+	sctlr = read_sctlr();
+	assert((sctlr & SCTLR_M_BIT) == 0);
 
 	/* Invalidate TLBs at the current exception level */
 	tlbiall();
@@ -109,29 +107,56 @@
 			ATTR_IWBWA_OWBWA_NTR_INDEX);
 	mair0 |= MAIR0_ATTR_SET(ATTR_NON_CACHEABLE,
 			ATTR_NON_CACHEABLE_INDEX);
-	write_mair0(mair0);
+
+	/*
+	 * Configure the control register for stage 1 of the PL1&0 translation
+	 * regime.
+	 */
+
+	/* Use the Long-descriptor translation table format. */
+	ttbcr = TTBCR_EAE_BIT;
+
+	/*
+	 * Disable translation table walk for addresses that are translated
+	 * using TTBR1. Therefore, only TTBR0 is used.
+	 */
+	ttbcr |= TTBCR_EPD1_BIT;
 
 	/*
-	 * Set TTBCR bits as well. Set TTBR0 table properties. Disable TTBR1.
+	 * Limit the input address ranges and memory region sizes translated
+	 * using TTBR0 to the given virtual address space size, if smaller than
+	 * 32 bits.
+	 */
+	if (max_va != UINT32_MAX) {
+		uintptr_t virtual_addr_space_size = max_va + 1;
+		assert(CHECK_VIRT_ADDR_SPACE_SIZE(virtual_addr_space_size));
+		/*
+		 * __builtin_ctzll(0) is undefined but here we are guaranteed
+		 * that virtual_addr_space_size is in the range [1, UINT32_MAX].
+		 */
+		ttbcr |= 32 - __builtin_ctzll(virtual_addr_space_size);
+	}
+
+	/*
+	 * Set the cacheability and shareability attributes for memory
+	 * associated with translation table walks using TTBR0.
 	 */
 	if (flags & XLAT_TABLE_NC) {
 		/* Inner & outer non-cacheable non-shareable. */
-		ttbcr = TTBCR_EAE_BIT |
-			TTBCR_SH0_NON_SHAREABLE | TTBCR_RGN0_OUTER_NC |
-			TTBCR_RGN0_INNER_NC |
-			(32 - __builtin_ctzl((uintptr_t)PLAT_VIRT_ADDR_SPACE_SIZE));
+		ttbcr |= TTBCR_SH0_NON_SHAREABLE | TTBCR_RGN0_OUTER_NC |
+			TTBCR_RGN0_INNER_NC;
 	} else {
 		/* Inner & outer WBWA & shareable. */
-		ttbcr = TTBCR_EAE_BIT |
-			TTBCR_SH0_INNER_SHAREABLE | TTBCR_RGN0_OUTER_WBA |
-			TTBCR_RGN0_INNER_WBA |
-			(32 - __builtin_ctzl((uintptr_t)PLAT_VIRT_ADDR_SPACE_SIZE));
+		ttbcr |= TTBCR_SH0_INNER_SHAREABLE | TTBCR_RGN0_OUTER_WBA |
+			TTBCR_RGN0_INNER_WBA;
 	}
-	ttbcr |= TTBCR_EPD1_BIT;
-	write_ttbcr(ttbcr);
 
 	/* Set TTBR0 bits as well */
 	ttbr0 = (uint64_t)(uintptr_t) base_table;
+
+	/* Now program the relevant system registers */
+	write_mair0(mair0);
+	write_ttbcr(ttbcr);
 	write64_ttbr0(ttbr0);
 	write64_ttbr1(0);
 
@@ -144,7 +169,6 @@
 	dsbish();
 	isb();
 
-	sctlr = read_sctlr();
 	sctlr |= SCTLR_WXN_BIT | SCTLR_M_BIT;
 
 	if (flags & DISABLE_DCACHE)
@@ -157,8 +181,3 @@
 	/* Ensure the MMU enable takes effect immediately */
 	isb();
 }
-
-void enable_mmu_arch(unsigned int flags, uint64_t *base_table)
-{
-	enable_mmu_internal_secure(flags, base_table);
-}
diff --git a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.h b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.h
deleted file mode 100644
index f75ab79..0000000
--- a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef __XLAT_TABLES_ARCH_H__
-#define __XLAT_TABLES_ARCH_H__
-
-#include <arch.h>
-#include <platform_def.h>
-#include <xlat_tables_defs.h>
-#include "../xlat_tables_private.h"
-
-/*
- * In AArch32 state, the MMU only supports 4KB page granularity, which means
- * that the first translation table level is either 1 or 2. Both of them are
- * allowed to have block and table descriptors. See section G4.5.6 of the
- * ARMv8-A Architecture Reference Manual (DDI 0487A.k) for more information.
- *
- * The define below specifies the first table level that allows block
- * descriptors.
- */
-
-#define MIN_LVL_BLOCK_DESC 1
-
-/*
- * Each platform can define the size of the virtual address space, which is
- * defined in PLAT_VIRT_ADDR_SPACE_SIZE. TTBCR.TxSZ is calculated as 32 minus
- * the width of said address space. The value of TTBCR.TxSZ must be in the
- * range 0 to 7 [1], which means that the virtual address space width must be
- * in the range 32 to 25 bits.
- *
- * Here we calculate the initial lookup level from the value of
- * PLAT_VIRT_ADDR_SPACE_SIZE. For a 4 KB page size, level 1 supports virtual
- * address spaces of widths 32 to 31 bits, and level 2 from 30 to 25. Wider or
- * narrower address spaces are not supported. As a result, level 3 cannot be
- * used as initial lookup level with 4 KB granularity [1].
- *
- * For example, for a 31-bit address space (i.e. PLAT_VIRT_ADDR_SPACE_SIZE ==
- * 1 << 31), TTBCR.TxSZ will be programmed to (32 - 31) = 1. According to Table
- * G4-5 in the ARM ARM, the initial lookup level for an address space like that
- * is 1.
- *
- * See the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more
- * information:
- * [1] Section G4.6.5
- */
-
-#if PLAT_VIRT_ADDR_SPACE_SIZE > (1ULL << (32 - TTBCR_TxSZ_MIN))
-
-# error "PLAT_VIRT_ADDR_SPACE_SIZE is too big."
-
-#elif PLAT_VIRT_ADDR_SPACE_SIZE > (1 << L1_XLAT_ADDRESS_SHIFT)
-
-# define XLAT_TABLE_LEVEL_BASE	1
-# define NUM_BASE_LEVEL_ENTRIES	\
-		(PLAT_VIRT_ADDR_SPACE_SIZE >> L1_XLAT_ADDRESS_SHIFT)
-
-#elif PLAT_VIRT_ADDR_SPACE_SIZE >= (1 << (32 - TTBCR_TxSZ_MAX))
-
-# define XLAT_TABLE_LEVEL_BASE	2
-# define NUM_BASE_LEVEL_ENTRIES	\
-		(PLAT_VIRT_ADDR_SPACE_SIZE >> L2_XLAT_ADDRESS_SHIFT)
-
-#else
-
-# error "PLAT_VIRT_ADDR_SPACE_SIZE is too small."
-
-#endif
-
-#endif /* __XLAT_TABLES_ARCH_H__ */
diff --git a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
index 14f6cd6..61eac10 100644
--- a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
+++ b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
@@ -22,8 +22,6 @@
 # define IMAGE_EL	1
 #endif
 
-static unsigned long long tcr_ps_bits;
-
 static unsigned long long calc_physical_addr_size_bits(
 					unsigned long long max_addr)
 {
@@ -60,7 +58,7 @@
 	PARANGE_0101
 };
 
-static unsigned long long xlat_arch_get_max_supported_pa(void)
+unsigned long long xlat_arch_get_max_supported_pa(void)
 {
 	u_register_t pa_range = read_id_aa64mmfr0_el1() &
 						ID_AA64MMFR0_EL1_PARANGE_MASK;
@@ -146,73 +144,28 @@
 	}
 }
 
-void init_xlat_tables_arch(unsigned long long max_pa)
-{
-	assert((PLAT_PHY_ADDR_SPACE_SIZE - 1) <=
-	       xlat_arch_get_max_supported_pa());
-
-	/*
-	 * If dynamic allocation of new regions is enabled the code can't make
-	 * assumptions about the max physical address because it could change
-	 * after adding new regions. If this functionality is disabled it is
-	 * safer to restrict the max physical address as much as possible.
-	 */
-#ifdef PLAT_XLAT_TABLES_DYNAMIC
-	tcr_ps_bits = calc_physical_addr_size_bits(PLAT_PHY_ADDR_SPACE_SIZE);
-#else
-	tcr_ps_bits = calc_physical_addr_size_bits(max_pa);
-#endif
-}
-
 /*******************************************************************************
  * Macro generating the code for the function enabling the MMU in the given
  * exception level, assuming that the pagetables have already been created.
  *
  *   _el:		Exception level at which the function will run
- *   _tcr_extra:	Extra bits to set in the TCR register. This mask will
- *			be OR'ed with the default TCR value.
  *   _tlbi_fct:		Function to invalidate the TLBs at the current
  *			exception level
  ******************************************************************************/
-#define DEFINE_ENABLE_MMU_EL(_el, _tcr_extra, _tlbi_fct)		\
-	void enable_mmu_internal_el##_el(unsigned int flags,		\
-					 uint64_t *base_table)		\
+#define DEFINE_ENABLE_MMU_EL(_el, _tlbi_fct)				\
+	static void enable_mmu_internal_el##_el(int flags,		\
+						uint64_t mair,		\
+						uint64_t tcr,		\
+						uint64_t ttbr)		\
 	{								\
-		uint64_t mair, tcr, ttbr;				\
-		uint32_t sctlr;						\
-									\
-		assert(IS_IN_EL(_el));					\
-		assert((read_sctlr_el##_el() & SCTLR_M_BIT) == 0);	\
+		uint32_t sctlr = read_sctlr_el##_el();			\
+		assert((sctlr & SCTLR_M_BIT) == 0);			\
 									\
 		/* Invalidate TLBs at the current exception level */	\
 		_tlbi_fct();						\
 									\
-		/* Set attributes in the right indices of the MAIR */	\
-		mair = MAIR_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX);	\
-		mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR,		\
-				ATTR_IWBWA_OWBWA_NTR_INDEX);		\
-		mair |= MAIR_ATTR_SET(ATTR_NON_CACHEABLE,		\
-				ATTR_NON_CACHEABLE_INDEX);		\
 		write_mair_el##_el(mair);				\
-									\
-		/* Set TCR bits as well. */				\
-		/* Set T0SZ to (64 - width of virtual address space) */	\
-		if (flags & XLAT_TABLE_NC) {				\
-			/* Inner & outer non-cacheable non-shareable. */\
-			tcr = TCR_SH_NON_SHAREABLE |			\
-				TCR_RGN_OUTER_NC | TCR_RGN_INNER_NC |	\
-				(64 - __builtin_ctzl(PLAT_VIRT_ADDR_SPACE_SIZE));\
-		} else {						\
-			/* Inner & outer WBWA & shareable. */		\
-			tcr = TCR_SH_INNER_SHAREABLE |			\
-				TCR_RGN_OUTER_WBA | TCR_RGN_INNER_WBA |	\
-				(64 - __builtin_ctzl(PLAT_VIRT_ADDR_SPACE_SIZE));\
-		}							\
-		tcr |= _tcr_extra;					\
 		write_tcr_el##_el(tcr);					\
-									\
-		/* Set TTBR bits as well */				\
-		ttbr = (uint64_t) base_table;				\
 		write_ttbr0_el##_el(ttbr);				\
 									\
 		/* Ensure all translation table writes have drained */	\
@@ -222,9 +175,7 @@
 		dsbish();						\
 		isb();							\
 									\
-		sctlr = read_sctlr_el##_el();				\
 		sctlr |= SCTLR_WXN_BIT | SCTLR_M_BIT;			\
-									\
 		if (flags & DISABLE_DCACHE)				\
 			sctlr &= ~SCTLR_C_BIT;				\
 		else							\
@@ -238,22 +189,69 @@
 
 /* Define EL1 and EL3 variants of the function enabling the MMU */
 #if IMAGE_EL == 1
-DEFINE_ENABLE_MMU_EL(1,
-		(tcr_ps_bits << TCR_EL1_IPS_SHIFT),
-		tlbivmalle1)
+DEFINE_ENABLE_MMU_EL(1, tlbivmalle1)
 #elif IMAGE_EL == 3
-DEFINE_ENABLE_MMU_EL(3,
-		TCR_EL3_RES1 | (tcr_ps_bits << TCR_EL3_PS_SHIFT),
-		tlbialle3)
+DEFINE_ENABLE_MMU_EL(3, tlbialle3)
 #endif
 
-void enable_mmu_arch(unsigned int flags, uint64_t *base_table)
+void enable_mmu_arch(unsigned int flags,
+		uint64_t *base_table,
+		unsigned long long max_pa,
+		uintptr_t max_va)
 {
+	uint64_t mair, ttbr, tcr;
+
+	/* Set attributes in the right indices of the MAIR. */
+	mair = MAIR_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX);
+	mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, ATTR_IWBWA_OWBWA_NTR_INDEX);
+	mair |= MAIR_ATTR_SET(ATTR_NON_CACHEABLE, ATTR_NON_CACHEABLE_INDEX);
+
+	ttbr = (uint64_t) base_table;
+
+	/*
+	 * Set TCR bits as well.
+	 */
+
+	/*
+	 * Limit the input address ranges and memory region sizes translated
+	 * using TTBR0 to the given virtual address space size.
+	 */
+	assert(max_va < UINTPTR_MAX);
+	uintptr_t virtual_addr_space_size = max_va + 1;
+	assert(CHECK_VIRT_ADDR_SPACE_SIZE(virtual_addr_space_size));
+	/*
+	 * __builtin_ctzll(0) is undefined but here we are guaranteed that
+	 * virtual_addr_space_size is in the range [1,UINTPTR_MAX].
+	 */
+	tcr = 64 - __builtin_ctzll(virtual_addr_space_size);
+
+	/*
+	 * Set the cacheability and shareability attributes for memory
+	 * associated with translation table walks.
+	 */
+	if (flags & XLAT_TABLE_NC) {
+		/* Inner & outer non-cacheable non-shareable. */
+		tcr |= TCR_SH_NON_SHAREABLE |
+			TCR_RGN_OUTER_NC | TCR_RGN_INNER_NC;
+	} else {
+		/* Inner & outer WBWA & shareable. */
+		tcr |= TCR_SH_INNER_SHAREABLE |
+			TCR_RGN_OUTER_WBA | TCR_RGN_INNER_WBA;
+	}
+
+	/*
+	 * It is safer to restrict the max physical address accessible by the
+	 * hardware as much as possible.
+	 */
+	unsigned long long tcr_ps_bits = calc_physical_addr_size_bits(max_pa);
+
 #if IMAGE_EL == 1
 	assert(IS_IN_EL(1));
-	enable_mmu_internal_el1(flags, base_table);
+	tcr |= tcr_ps_bits << TCR_EL1_IPS_SHIFT;
+	enable_mmu_internal_el1(flags, mair, tcr, ttbr);
 #elif IMAGE_EL == 3
 	assert(IS_IN_EL(3));
-	enable_mmu_internal_el3(flags, base_table);
+	tcr |= TCR_EL3_RES1 | (tcr_ps_bits << TCR_EL3_PS_SHIFT);
+	enable_mmu_internal_el3(flags, mair, tcr, ttbr);
 #endif
 }
diff --git a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.h b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.h
deleted file mode 100644
index caccb73..0000000
--- a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef __XLAT_TABLES_ARCH_H__
-#define __XLAT_TABLES_ARCH_H__
-
-#include <arch.h>
-#include <platform_def.h>
-#include <xlat_tables_defs.h>
-#include "../xlat_tables_private.h"
-
-/*
- * In AArch64 state, the MMU may support 4 KB, 16 KB and 64 KB page
- * granularity. For 4KB granularity, a level 0 table descriptor doesn't support
- * block translation. For 16KB, the same thing happens to levels 0 and 1. For
- * 64KB, same for level 1. See section D4.3.1 of the ARMv8-A Architecture
- * Reference Manual (DDI 0487A.k) for more information.
- *
- * The define below specifies the first table level that allows block
- * descriptors.
- */
-
-#if PAGE_SIZE == (4*1024) /* 4KB */
-# define MIN_LVL_BLOCK_DESC 1
-#else /* 16KB or 64KB */
-# define MIN_LVL_BLOCK_DESC 2
-#endif
-
-/*
- * Each platform can define the size of the virtual address space, which is
- * defined in PLAT_VIRT_ADDR_SPACE_SIZE. TCR.TxSZ is calculated as 64 minus the
- * width of said address space. The value of TCR.TxSZ must be in the range 16
- * to 39 [1], which means that the virtual address space width must be in the
- * range 48 to 25 bits.
- *
- * Here we calculate the initial lookup level from the value of
- * PLAT_VIRT_ADDR_SPACE_SIZE. For a 4 KB page size, level 0 supports virtual
- * address spaces of widths 48 to 40 bits, level 1 from 39 to 31, and level 2
- * from 30 to 25. Wider or narrower address spaces are not supported. As a
- * result, level 3 cannot be used as initial lookup level with 4 KB
- * granularity. [2]
- *
- * For example, for a 35-bit address space (i.e. PLAT_VIRT_ADDR_SPACE_SIZE ==
- * 1 << 35), TCR.TxSZ will be programmed to (64 - 35) = 29. According to Table
- * D4-11 in the ARM ARM, the initial lookup level for an address space like
- * that is 1.
- *
- * See the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more
- * information:
- * [1] Page 1730: 'Input address size', 'For all translation stages'.
- * [2] Section D4.2.5
- */
-
-#if PLAT_VIRT_ADDR_SPACE_SIZE > (1ULL << (64 - TCR_TxSZ_MIN))
-
-# error "PLAT_VIRT_ADDR_SPACE_SIZE is too big."
-
-#elif PLAT_VIRT_ADDR_SPACE_SIZE > (1ULL << L0_XLAT_ADDRESS_SHIFT)
-
-# define XLAT_TABLE_LEVEL_BASE	0
-# define NUM_BASE_LEVEL_ENTRIES	\
-		(PLAT_VIRT_ADDR_SPACE_SIZE >> L0_XLAT_ADDRESS_SHIFT)
-
-#elif PLAT_VIRT_ADDR_SPACE_SIZE > (1 << L1_XLAT_ADDRESS_SHIFT)
-
-# define XLAT_TABLE_LEVEL_BASE	1
-# define NUM_BASE_LEVEL_ENTRIES	\
-		(PLAT_VIRT_ADDR_SPACE_SIZE >> L1_XLAT_ADDRESS_SHIFT)
-
-#elif PLAT_VIRT_ADDR_SPACE_SIZE >= (1 << (64 - TCR_TxSZ_MAX))
-
-# define XLAT_TABLE_LEVEL_BASE	2
-# define NUM_BASE_LEVEL_ENTRIES	\
-		(PLAT_VIRT_ADDR_SPACE_SIZE >> L2_XLAT_ADDRESS_SHIFT)
-
-#else
-
-# error "PLAT_VIRT_ADDR_SPACE_SIZE is too small."
-
-#endif
-
-#endif /* __XLAT_TABLES_ARCH_H__ */
diff --git a/lib/xlat_tables_v2/xlat_tables.mk b/lib/xlat_tables_v2/xlat_tables.mk
index 4f80434..b94ce5d 100644
--- a/lib/xlat_tables_v2/xlat_tables.mk
+++ b/lib/xlat_tables_v2/xlat_tables.mk
@@ -6,5 +6,4 @@
 
 XLAT_TABLES_LIB_SRCS	:=	$(addprefix lib/xlat_tables_v2/,	\
 				${ARCH}/xlat_tables_arch.c		\
-				xlat_tables_common.c			\
 				xlat_tables_internal.c)
diff --git a/lib/xlat_tables_v2/xlat_tables_common.c b/lib/xlat_tables_v2/xlat_tables_common.c
deleted file mode 100644
index f20bf93..0000000
--- a/lib/xlat_tables_v2/xlat_tables_common.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <arch.h>
-#include <arch_helpers.h>
-#include <assert.h>
-#include <cassert.h>
-#include <common_def.h>
-#include <debug.h>
-#include <errno.h>
-#include <platform_def.h>
-#include <string.h>
-#include <types.h>
-#include <utils.h>
-#include <xlat_tables_v2.h>
-#ifdef AARCH32
-# include "aarch32/xlat_tables_arch.h"
-#else
-# include "aarch64/xlat_tables_arch.h"
-#endif
-#include "xlat_tables_private.h"
-
-/*
- * Private variables used by the TF
- */
-static mmap_region_t tf_mmap[MAX_MMAP_REGIONS + 1];
-
-static uint64_t tf_xlat_tables[MAX_XLAT_TABLES][XLAT_TABLE_ENTRIES]
-			__aligned(XLAT_TABLE_SIZE) __section("xlat_table");
-
-static uint64_t tf_base_xlat_table[NUM_BASE_LEVEL_ENTRIES]
-		__aligned(NUM_BASE_LEVEL_ENTRIES * sizeof(uint64_t));
-
-#if PLAT_XLAT_TABLES_DYNAMIC
-static int xlat_tables_mapped_regions[MAX_XLAT_TABLES];
-#endif /* PLAT_XLAT_TABLES_DYNAMIC */
-
-xlat_ctx_t tf_xlat_ctx = {
-
-	.pa_max_address = PLAT_PHY_ADDR_SPACE_SIZE - 1,
-	.va_max_address = PLAT_VIRT_ADDR_SPACE_SIZE - 1,
-
-	.mmap = tf_mmap,
-	.mmap_num = MAX_MMAP_REGIONS,
-
-	.tables = tf_xlat_tables,
-	.tables_num = MAX_XLAT_TABLES,
-#if PLAT_XLAT_TABLES_DYNAMIC
-	.tables_mapped_regions = xlat_tables_mapped_regions,
-#endif /* PLAT_XLAT_TABLES_DYNAMIC */
-
-	.base_table = tf_base_xlat_table,
-	.base_table_entries = NUM_BASE_LEVEL_ENTRIES,
-
-	.max_pa = 0,
-	.max_va = 0,
-
-	.next_table = 0,
-
-	.base_level = XLAT_TABLE_LEVEL_BASE,
-
-	.initialized = 0
-};
-
-void mmap_add_region(unsigned long long base_pa, uintptr_t base_va,
-			size_t size, mmap_attr_t attr)
-{
-	mmap_region_t mm = {
-		.base_va = base_va,
-		.base_pa = base_pa,
-		.size = size,
-		.attr = attr,
-	};
-	mmap_add_region_ctx(&tf_xlat_ctx, (mmap_region_t *)&mm);
-}
-
-void mmap_add(const mmap_region_t *mm)
-{
-	while (mm->size) {
-		mmap_add_region_ctx(&tf_xlat_ctx, (mmap_region_t *)mm);
-		mm++;
-	}
-}
-
-#if PLAT_XLAT_TABLES_DYNAMIC
-
-int mmap_add_dynamic_region(unsigned long long base_pa,
-			    uintptr_t base_va, size_t size, mmap_attr_t attr)
-{
-	mmap_region_t mm = {
-		.base_va = base_va,
-		.base_pa = base_pa,
-		.size = size,
-		.attr = attr,
-	};
-	return mmap_add_dynamic_region_ctx(&tf_xlat_ctx, &mm);
-}
-
-int mmap_remove_dynamic_region(uintptr_t base_va, size_t size)
-{
-	return mmap_remove_dynamic_region_ctx(&tf_xlat_ctx, base_va, size);
-}
-
-#endif /* PLAT_XLAT_TABLES_DYNAMIC */
-
-void init_xlat_tables(void)
-{
-	assert(!is_mmu_enabled());
-	assert(!tf_xlat_ctx.initialized);
-	print_mmap(tf_xlat_ctx.mmap);
-	tf_xlat_ctx.execute_never_mask =
-			xlat_arch_get_xn_desc(xlat_arch_current_el());
-	init_xlation_table(&tf_xlat_ctx);
-	xlat_tables_print(&tf_xlat_ctx);
-
-	assert(tf_xlat_ctx.max_va <= PLAT_VIRT_ADDR_SPACE_SIZE - 1);
-	assert(tf_xlat_ctx.max_pa <= PLAT_PHY_ADDR_SPACE_SIZE - 1);
-
-	init_xlat_tables_arch(tf_xlat_ctx.max_pa);
-}
-
-#ifdef AARCH32
-
-void enable_mmu_secure(unsigned int flags)
-{
-	enable_mmu_arch(flags, tf_xlat_ctx.base_table);
-}
-
-#else
-
-void enable_mmu_el1(unsigned int flags)
-{
-	enable_mmu_arch(flags, tf_xlat_ctx.base_table);
-}
-
-void enable_mmu_el3(unsigned int flags)
-{
-	enable_mmu_arch(flags, tf_xlat_ctx.base_table);
-}
-
-#endif /* AARCH32 */
diff --git a/lib/xlat_tables_v2/xlat_tables_internal.c b/lib/xlat_tables_v2/xlat_tables_internal.c
index f60d78c..cd6e11c 100644
--- a/lib/xlat_tables_v2/xlat_tables_internal.c
+++ b/lib/xlat_tables_v2/xlat_tables_internal.c
@@ -7,7 +7,6 @@
 #include <arch.h>
 #include <arch_helpers.h>
 #include <assert.h>
-#include <cassert.h>
 #include <common_def.h>
 #include <debug.h>
 #include <errno.h>
@@ -15,14 +14,37 @@
 #include <string.h>
 #include <types.h>
 #include <utils.h>
+#include <xlat_tables_arch.h>
+#include <xlat_tables_defs.h>
 #include <xlat_tables_v2.h>
-#ifdef AARCH32
-# include "aarch32/xlat_tables_arch.h"
-#else
-# include "aarch64/xlat_tables_arch.h"
-#endif
+
 #include "xlat_tables_private.h"
 
+/*
+ * Each platform can define the size of its physical and virtual address spaces.
+ * If the platform hasn't defined one or both of them, default to
+ * ADDR_SPACE_SIZE. The latter is deprecated, though.
+ */
+#if ERROR_DEPRECATED
+# ifdef ADDR_SPACE_SIZE
+#  error "ADDR_SPACE_SIZE is deprecated. Use PLAT_xxx_ADDR_SPACE_SIZE instead."
+# endif
+#elif defined(ADDR_SPACE_SIZE)
+# ifndef PLAT_PHY_ADDR_SPACE_SIZE
+#  define PLAT_PHY_ADDR_SPACE_SIZE	ADDR_SPACE_SIZE
+# endif
+# ifndef PLAT_VIRT_ADDR_SPACE_SIZE
+#  define PLAT_VIRT_ADDR_SPACE_SIZE	ADDR_SPACE_SIZE
+# endif
+#endif
+
+/*
+ * Allocate and initialise the default translation context for the BL image
+ * currently executing.
+ */
+REGISTER_XLAT_CONTEXT(tf, MAX_MMAP_REGIONS, MAX_XLAT_TABLES,
+		PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE);
+
 #if PLAT_XLAT_TABLES_DYNAMIC
 
 /*
@@ -335,7 +357,7 @@
  */
 static action_t xlat_tables_map_region_action(const mmap_region_t *mm,
 		const int desc_type, const unsigned long long dest_pa,
-		const uintptr_t table_entry_base_va, const int level)
+		const uintptr_t table_entry_base_va, const unsigned int level)
 {
 	uintptr_t mm_end_va = mm->base_va + mm->size - 1;
 	uintptr_t table_entry_end_va =
@@ -666,7 +688,7 @@
 	return 0;
 }
 
-void mmap_add_region_ctx(xlat_ctx_t *ctx, mmap_region_t *mm)
+void mmap_add_region_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm)
 {
 	mmap_region_t *mm_cursor = ctx->mmap;
 	mmap_region_t *mm_last = mm_cursor + ctx->mmap_num;
@@ -743,6 +765,34 @@
 		ctx->max_va = end_va;
 }
 
+void mmap_add_region(unsigned long long base_pa,
+				uintptr_t base_va,
+				size_t size,
+				mmap_attr_t attr)
+{
+	mmap_region_t mm = {
+		.base_va = base_va,
+		.base_pa = base_pa,
+		.size = size,
+		.attr = attr,
+	};
+	mmap_add_region_ctx(&tf_xlat_ctx, &mm);
+}
+
+
+void mmap_add_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm)
+{
+	while (mm->size) {
+		mmap_add_region_ctx(ctx, mm);
+		mm++;
+	}
+}
+
+void mmap_add(const mmap_region_t *mm)
+{
+	mmap_add_ctx(&tf_xlat_ctx, mm);
+}
+
 #if PLAT_XLAT_TABLES_DYNAMIC
 
 int mmap_add_dynamic_region_ctx(xlat_ctx_t *ctx, mmap_region_t *mm)
@@ -839,6 +889,18 @@
 	return 0;
 }
 
+int mmap_add_dynamic_region(unsigned long long base_pa,
+			    uintptr_t base_va, size_t size, mmap_attr_t attr)
+{
+	mmap_region_t mm = {
+		.base_va = base_va,
+		.base_pa = base_pa,
+		.size = size,
+		.attr = attr,
+	};
+	return mmap_add_dynamic_region_ctx(&tf_xlat_ctx, &mm);
+}
+
 /*
  * Removes the region with given base Virtual Address and size from the given
  * context.
@@ -914,6 +976,12 @@
 	return 0;
 }
 
+int mmap_remove_dynamic_region(uintptr_t base_va, size_t size)
+{
+	return mmap_remove_dynamic_region_ctx(&tf_xlat_ctx,
+					base_va, size);
+}
+
 #endif /* PLAT_XLAT_TABLES_DYNAMIC */
 
 #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
@@ -1042,15 +1110,47 @@
 void xlat_tables_print(xlat_ctx_t *ctx)
 {
 #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+	VERBOSE("Translation tables state:\n");
+	VERBOSE("  Max allowed PA:  0x%llx\n", ctx->pa_max_address);
+	VERBOSE("  Max allowed VA:  %p\n", (void *) ctx->va_max_address);
+	VERBOSE("  Max mapped PA:   0x%llx\n", ctx->max_pa);
+	VERBOSE("  Max mapped VA:   %p\n", (void *) ctx->max_va);
+
+	VERBOSE("  Initial lookup level: %i\n", ctx->base_level);
+	VERBOSE("  Entries @initial lookup level: %i\n",
+		ctx->base_table_entries);
+
+	int used_page_tables;
+#if PLAT_XLAT_TABLES_DYNAMIC
+	used_page_tables = 0;
+	for (unsigned int i = 0; i < ctx->tables_num; ++i) {
+		if (ctx->tables_mapped_regions[i] != 0)
+			++used_page_tables;
+	}
+#else
+	used_page_tables = ctx->next_table;
+#endif
+	VERBOSE("  Used %i sub-tables out of %i (spare: %i)\n",
+		used_page_tables, ctx->tables_num,
+		ctx->tables_num - used_page_tables);
+
 	xlat_tables_print_internal(0, ctx->base_table, ctx->base_table_entries,
 				   ctx->base_level, ctx->execute_never_mask);
 #endif /* LOG_LEVEL >= LOG_LEVEL_VERBOSE */
 }
 
-void init_xlation_table(xlat_ctx_t *ctx)
+void init_xlat_tables_ctx(xlat_ctx_t *ctx)
 {
 	mmap_region_t *mm = ctx->mmap;
 
+	assert(!is_mmu_enabled());
+	assert(!ctx->initialized);
+
+	print_mmap(mm);
+
+	ctx->execute_never_mask =
+			xlat_arch_get_xn_desc(xlat_arch_current_el());
+
 	/* All tables must be zeroed before mapping any region. */
 
 	for (unsigned int i = 0; i < ctx->base_table_entries; i++)
@@ -1078,5 +1178,57 @@
 		mm++;
 	}
 
+	assert(ctx->pa_max_address <= xlat_arch_get_max_supported_pa());
+	assert(ctx->max_va <= ctx->va_max_address);
+	assert(ctx->max_pa <= ctx->pa_max_address);
+
 	ctx->initialized = 1;
+
+	xlat_tables_print(ctx);
+}
+
+void init_xlat_tables(void)
+{
+	init_xlat_tables_ctx(&tf_xlat_ctx);
+}
+
+/*
+ * If dynamic allocation of new regions is disabled then by the time we call the
+ * function enabling the MMU, we'll have registered all the memory regions to
+ * map for the system's lifetime. Therefore, at this point we know the maximum
+ * physical address that will ever be mapped.
+ *
+ * If dynamic allocation is enabled then we can't make any such assumption
+ * because the maximum physical address could get pushed while adding a new
+ * region. Therefore, in this case we have to assume that the whole address
+ * space size might be mapped.
+ */
+#ifdef PLAT_XLAT_TABLES_DYNAMIC
+#define MAX_PHYS_ADDR	tf_xlat_ctx.pa_max_address
+#else
+#define MAX_PHYS_ADDR	tf_xlat_ctx.max_pa
+#endif
+
+#ifdef AARCH32
+
+void enable_mmu_secure(unsigned int flags)
+{
+	enable_mmu_arch(flags, tf_xlat_ctx.base_table, MAX_PHYS_ADDR,
+			tf_xlat_ctx.va_max_address);
 }
+
+#else
+
+void enable_mmu_el1(unsigned int flags)
+{
+	enable_mmu_arch(flags, tf_xlat_ctx.base_table, MAX_PHYS_ADDR,
+			tf_xlat_ctx.va_max_address);
+}
+
+void enable_mmu_el3(unsigned int flags)
+{
+	enable_mmu_arch(flags, tf_xlat_ctx.base_table, MAX_PHYS_ADDR,
+			tf_xlat_ctx.va_max_address);
+}
+
+#endif /* AARCH32 */
diff --git a/lib/xlat_tables_v2/xlat_tables_private.h b/lib/xlat_tables_v2/xlat_tables_private.h
index 83e0b6e..d352583 100644
--- a/lib/xlat_tables_v2/xlat_tables_private.h
+++ b/lib/xlat_tables_v2/xlat_tables_private.h
@@ -7,100 +7,9 @@
 #ifndef __XLAT_TABLES_PRIVATE_H__
 #define __XLAT_TABLES_PRIVATE_H__
 
-#include <cassert.h>
 #include <platform_def.h>
-#include <utils_def.h>
+#include <xlat_tables_defs.h>
 
-/*
- * If the platform hasn't defined a physical and a virtual address space size
- * default to ADDR_SPACE_SIZE.
- */
-#if ERROR_DEPRECATED
-# ifdef ADDR_SPACE_SIZE
-#  error "ADDR_SPACE_SIZE is deprecated. Use PLAT_xxx_ADDR_SPACE_SIZE instead."
-# endif
-#elif defined(ADDR_SPACE_SIZE)
-# ifndef PLAT_PHY_ADDR_SPACE_SIZE
-#  define PLAT_PHY_ADDR_SPACE_SIZE	ADDR_SPACE_SIZE
-# endif
-# ifndef PLAT_VIRT_ADDR_SPACE_SIZE
-#  define PLAT_VIRT_ADDR_SPACE_SIZE	ADDR_SPACE_SIZE
-# endif
-#endif
-
-/* The virtual and physical address space sizes must be powers of two. */
-CASSERT(IS_POWER_OF_TWO(PLAT_VIRT_ADDR_SPACE_SIZE),
-	assert_valid_virt_addr_space_size);
-CASSERT(IS_POWER_OF_TWO(PLAT_PHY_ADDR_SPACE_SIZE),
-	assert_valid_phy_addr_space_size);
-
-/* Struct that holds all information about the translation tables. */
-typedef struct {
-
-	/*
-	 * Max allowed Virtual and Physical Addresses.
-	 */
-	unsigned long long pa_max_address;
-	uintptr_t va_max_address;
-
-	/*
-	 * Array of all memory regions stored in order of ascending end address
-	 * and ascending size to simplify the code that allows overlapping
-	 * regions. The list is terminated by the first entry with size == 0.
-	 * The max size of the list is stored in `mmap_num`. `mmap` points to an
-	 * array of mmap_num + 1 elements, so that there is space for the final
-	 * null entry.
-	 */
-	mmap_region_t *mmap;
-	unsigned int mmap_num;
-
-	/*
-	 * Array of finer-grain translation tables.
-	 * For example, if the initial lookup level is 1 then this array would
-	 * contain both level-2 and level-3 entries.
-	 */
-	uint64_t (*tables)[XLAT_TABLE_ENTRIES];
-	unsigned int tables_num;
-	/*
-	 * Keep track of how many regions are mapped in each table. The base
-	 * table can't be unmapped so it isn't needed to keep track of it.
-	 */
-#if PLAT_XLAT_TABLES_DYNAMIC
-	int *tables_mapped_regions;
-#endif /* PLAT_XLAT_TABLES_DYNAMIC */
-
-	unsigned int next_table;
-
-	/*
-	 * Base translation table. It doesn't need to have the same amount of
-	 * entries as the ones used for other levels.
-	 */
-	uint64_t *base_table;
-	unsigned int base_table_entries;
-
-	/*
-	 * Max Physical and Virtual addresses currently in use by the
-	 * translation tables. These might get updated as we map/unmap memory
-	 * regions but they will never go beyond pa/va_max_address.
-	 */
-	unsigned long long max_pa;
-	uintptr_t max_va;
-
-	/* Level of the base translation table. */
-	unsigned int base_level;
-
-	/* Set to 1 when the translation tables are initialized. */
-	unsigned int initialized;
-
-	/*
-	 * Bit mask that has to be ORed to the rest of a translation table
-	 * descriptor in order to prohibit execution of code at the exception
-	 * level of this translation context.
-	 */
-	uint64_t execute_never_mask;
-
-} xlat_ctx_t;
-
 #if PLAT_XLAT_TABLES_DYNAMIC
 /*
  * Shifts and masks to access fields of an mmap_attr_t
@@ -138,13 +47,6 @@
  */
 void xlat_arch_tlbi_va_sync(void);
 
-/* Add a dynamic region to the specified context. */
-int mmap_add_dynamic_region_ctx(xlat_ctx_t *ctx, mmap_region_t *mm);
-
-/* Remove a dynamic region from the specified context. */
-int mmap_remove_dynamic_region_ctx(xlat_ctx_t *ctx, uintptr_t base_va,
-			size_t size);
-
 #endif /* PLAT_XLAT_TABLES_DYNAMIC */
 
 /* Print VA, PA, size and attributes of all regions in the mmap array. */
@@ -157,15 +59,6 @@
 void xlat_tables_print(xlat_ctx_t *ctx);
 
 /*
- * Initialize the translation tables by mapping all regions added to the
- * specified context.
- */
-void init_xlation_table(xlat_ctx_t *ctx);
-
-/* Add a static region to the specified context. */
-void mmap_add_region_ctx(xlat_ctx_t *ctx, mmap_region_t *mm);
-
-/*
  * Architecture-specific initialization code.
  */
 
@@ -179,11 +72,15 @@
  */
 uint64_t xlat_arch_get_xn_desc(int el);
 
-/* Execute architecture-specific translation table initialization code. */
-void init_xlat_tables_arch(unsigned long long max_pa);
+/*
+ * Return the maximum physical address supported by the hardware.
+ * This value depends on the execution state (AArch32/AArch64).
+ */
+unsigned long long xlat_arch_get_max_supported_pa(void);
 
 /* Enable MMU and configure it to use the specified translation tables. */
-void enable_mmu_arch(unsigned int flags, uint64_t *base_table);
+void enable_mmu_arch(unsigned int flags, uint64_t *base_table,
+		unsigned long long pa, uintptr_t max_va);
 
 /* Return 1 if the MMU of this Exception Level is enabled, 0 otherwise. */
 int is_mmu_enabled(void);
diff --git a/plat/arm/board/common/board_css_common.c b/plat/arm/board/common/board_css_common.c
index 42f754e..f6a554f 100644
--- a/plat/arm/board/common/board_css_common.c
+++ b/plat/arm/board/common/board_css_common.c
@@ -19,6 +19,7 @@
 	CSS_MAP_DEVICE,
 	SOC_CSS_MAP_DEVICE,
 #if TRUSTED_BOARD_BOOT
+	/* Map DRAM to authenticate NS_BL2U image. */
 	ARM_MAP_NS_DRAM1,
 #endif
 	{0}
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index eb37f11..2f5d7fc 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -36,6 +36,10 @@
 					DEVICE1_SIZE,			\
 					MT_DEVICE | MT_RW | MT_SECURE)
 
+/*
+ * Need to be mapped with write permissions in order to set a new non-volatile
+ * counter value.
+ */
 #define MAP_DEVICE2	MAP_REGION_FLAT(DEVICE2_BASE,			\
 					DEVICE2_SIZE,			\
 					MT_DEVICE | MT_RW | MT_SECURE)
@@ -56,8 +60,10 @@
 	V2M_MAP_IOFPGA,
 	MAP_DEVICE0,
 	MAP_DEVICE1,
-	MAP_DEVICE2,
 #if TRUSTED_BOARD_BOOT
+	/* To access the Root of Trust Public Key registers. */
+	MAP_DEVICE2,
+	/* Map DRAM to authenticate NS_BL2U image. */
 	ARM_MAP_NS_DRAM1,
 #endif
 	{0}
@@ -70,9 +76,12 @@
 	V2M_MAP_IOFPGA,
 	MAP_DEVICE0,
 	MAP_DEVICE1,
-	MAP_DEVICE2,
 	ARM_MAP_NS_DRAM1,
 	ARM_MAP_TSP_SEC_MEM,
+#if TRUSTED_BOARD_BOOT
+	/* To access the Root of Trust Public Key registers. */
+	MAP_DEVICE2,
+#endif
 #if ARM_BL31_IN_DRAM
 	ARM_MAP_BL31_SEC_DRAM,
 #endif
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index ea128b6..46afb71 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -106,7 +106,7 @@
  * little space for growth.
  */
 #if TRUSTED_BOARD_BOOT
-# define PLAT_ARM_MAX_BL2_SIZE		0x1D000
+# define PLAT_ARM_MAX_BL2_SIZE		0x18000
 #else
 # define PLAT_ARM_MAX_BL2_SIZE		0xC000
 #endif
@@ -172,13 +172,13 @@
  * PLAT_CSS_MAX_SCP_BL2_SIZE is calculated using the current
  * SCP_BL2 size plus a little space for growth.
  */
-#define PLAT_CSS_MAX_SCP_BL2_SIZE	0x1D000
+#define PLAT_CSS_MAX_SCP_BL2_SIZE	0x14000
 
 /*
  * PLAT_CSS_MAX_SCP_BL2U_SIZE is calculated using the current
  * SCP_BL2U size plus a little space for growth.
  */
-#define PLAT_CSS_MAX_SCP_BL2U_SIZE	0x1D000
+#define PLAT_CSS_MAX_SCP_BL2U_SIZE	0x14000
 
 /*
  * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
diff --git a/plat/arm/css/common/css_bl2_setup.c b/plat/arm/css/common/css_bl2_setup.c
index 73549aa..0712e3a 100644
--- a/plat/arm/css/common/css_bl2_setup.c
+++ b/plat/arm/css/common/css_bl2_setup.c
@@ -11,7 +11,7 @@
 #include <plat_arm.h>
 #include <string.h>
 #include <utils.h>
-#include "css_scp_bootloader.h"
+#include "../drivers/scp/css_scp.h"
 
 /* Weak definition may be overridden in specific CSS based platform */
 #if LOAD_IMAGE_V2
@@ -34,10 +34,13 @@
 
 	INFO("BL2: Initiating SCP_BL2 transfer to SCP\n");
 
-	ret = scp_bootloader_transfer((void *)scp_bl2_image_info->image_base,
+	ret = css_scp_boot_image_xfer((void *)scp_bl2_image_info->image_base,
 		scp_bl2_image_info->image_size);
 
 	if (ret == 0)
+		ret = css_scp_boot_ready();
+
+	if (ret == 0)
 		INFO("BL2: SCP_BL2 transferred to SCP\n");
 	else
 		ERROR("BL2: SCP_BL2 transfer failure\n");
diff --git a/plat/arm/css/common/css_bl2u_setup.c b/plat/arm/css/common/css_bl2u_setup.c
index cc18758..d225151 100644
--- a/plat/arm/css/common/css_bl2u_setup.c
+++ b/plat/arm/css/common/css_bl2u_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,7 +7,7 @@
 #include <bl_common.h>
 #include <debug.h>
 #include <plat_arm.h>
-#include "css_scp_bootloader.h"
+#include "../drivers/scp/css_scp.h"
 
 /* Weak definition may be overridden in specific CSS based platform */
 #pragma weak bl2u_plat_handle_scp_bl2u
@@ -40,10 +40,13 @@
 
 	INFO("BL2U: Initiating SCP_BL2U transfer to SCP\n");
 
-	ret = scp_bootloader_transfer((void *)scp_bl2u_image_info.image_base,
+	ret = css_scp_boot_image_xfer((void *)scp_bl2u_image_info.image_base,
 		scp_bl2u_image_info.image_size);
 
 	if (ret == 0)
+		ret = css_scp_boot_ready();
+
+	if (ret == 0)
 		INFO("BL2U: SCP_BL2U transferred to SCP\n");
 	else
 		ERROR("BL2U: SCP_BL2U transfer failure\n");
diff --git a/plat/arm/css/common/css_common.mk b/plat/arm/css/common/css_common.mk
index c2ae921..9381e4c 100644
--- a/plat/arm/css/common/css_common.mk
+++ b/plat/arm/css/common/css_common.mk
@@ -56,8 +56,8 @@
     $(eval $(call FWU_FIP_ADD_IMG,SCP_BL2U,--scp-fwu-cfg))
   endif
 
-  BL2U_SOURCES		+=	plat/arm/css/common/css_scp_bootloader.c
-  BL2_SOURCES		+=	plat/arm/css/common/css_scp_bootloader.c
+  BL2U_SOURCES		+=	plat/arm/css/drivers/scp/css_bom_bootloader.c
+  BL2_SOURCES		+=	plat/arm/css/drivers/scp/css_bom_bootloader.c
 endif
 
 # Enable option to detect whether the SCP ROM firmware in use predates version
diff --git a/plat/arm/css/common/css_scp_bootloader.h b/plat/arm/css/common/css_scp_bootloader.h
deleted file mode 100644
index 0d6a6a2..0000000
--- a/plat/arm/css/common/css_scp_bootloader.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef __CSS_SCP_BOOTLOADER_H__
-#define __CSS_SCP_BOOTLOADER_H__
-
-int scp_bootloader_transfer(void *image, unsigned int image_size);
-
-#endif /* __CSS_SCP_BOOTLOADER_H__ */
diff --git a/plat/arm/css/common/css_scp_bootloader.c b/plat/arm/css/drivers/scp/css_bom_bootloader.c
similarity index 85%
rename from plat/arm/css/common/css_scp_bootloader.c
rename to plat/arm/css/drivers/scp/css_bom_bootloader.c
index 3db5cf5..047e069 100644
--- a/plat/arm/css/common/css_scp_bootloader.c
+++ b/plat/arm/css/drivers/scp/css_bom_bootloader.c
@@ -1,18 +1,17 @@
 /*
- * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <arch_helpers.h>
 #include <assert.h>
+#include <cassert.h>
 #include <css_def.h>
 #include <debug.h>
 #include <platform.h>
 #include <stdint.h>
-#include "../drivers/scpi/css_mhu.h"
-#include "../drivers/scpi/css_scpi.h"
-#include "css_scp_bootloader.h"
+#include "../scpi/css_mhu.h"
 
 /* ID of the MHU slot used for the BOM protocol */
 #define BOM_MHU_SLOT_ID		0
@@ -46,6 +45,18 @@
 	uint32_t block_size;
 } cmd_data_payload_t;
 
+/*
+ * All CSS platforms load SCP_BL2/SCP_BL2U just below BL rw-data and above
+ * BL2/BL2U (this is where BL31 usually resides except when ARM_BL31_IN_DRAM is
+ * set. Ensure that SCP_BL2/SCP_BL2U do not overflow into BL1 rw-data nor
+ * BL2/BL2U.
+ */
+CASSERT(SCP_BL2_LIMIT <= BL1_RW_BASE, assert_scp_bl2_overwrite_bl1);
+CASSERT(SCP_BL2U_LIMIT <= BL1_RW_BASE, assert_scp_bl2u_overwrite_bl1);
+
+CASSERT(SCP_BL2_BASE >= BL2_LIMIT, assert_scp_bl2_overwrite_bl2);
+CASSERT(SCP_BL2U_BASE >= BL2U_LIMIT, assert_scp_bl2u_overwrite_bl2u);
+
 static void scp_boot_message_start(void)
 {
 	mhu_secure_message_start(BOM_MHU_SLOT_ID);
@@ -88,7 +99,7 @@
 	mhu_secure_message_end(BOM_MHU_SLOT_ID);
 }
 
-int scp_bootloader_transfer(void *image, unsigned int image_size)
+int css_scp_boot_image_xfer(void *image, unsigned int image_size)
 {
 	uint32_t response;
 	uint32_t checksum;
@@ -170,8 +181,5 @@
 		return -1;
 	}
 
-	VERBOSE("Waiting for SCP to signal it is ready to go on\n");
-
-	/* Wait for SCP to signal it's ready */
-	return scpi_wait_ready();
+	return 0;
 }
diff --git a/plat/arm/css/drivers/scp/css_scp.h b/plat/arm/css/drivers/scp/css_scp.h
index 165226d..097a9f5 100644
--- a/plat/arm/css/drivers/scp/css_scp.h
+++ b/plat/arm/css/drivers/scp/css_scp.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,13 +7,31 @@
 #ifndef __CSS_SCP_H__
 #define __CSS_SCP_H__
 
-#include <psci.h>
+#include <types.h>
+#include "../scpi/css_scpi.h"
 
-void css_scp_suspend(const psci_power_state_t *target_state);
-void css_scp_off(const psci_power_state_t *target_state);
+/* Forward declarations */
+struct psci_power_state;
+
+/* API for power management by SCP */
+void css_scp_suspend(const struct psci_power_state *target_state);
+void css_scp_off(const struct psci_power_state *target_state);
 void css_scp_on(u_register_t mpidr);
 int css_scp_get_power_state(u_register_t mpidr, unsigned int power_level);
 void __dead2 css_scp_sys_shutdown(void);
 void __dead2 css_scp_sys_reboot(void);
 
+/* API for SCP Boot Image transfer. Return 0 on success, -1 on error */
+int css_scp_boot_image_xfer(void *image, unsigned int image_size);
+
+/*
+ * API to wait for SCP to signal till it's ready after booting the transferred
+ * image.
+ */
+static inline int css_scp_boot_ready(void)
+{
+	VERBOSE("Waiting for SCP to signal it is ready to go on\n");
+	return scpi_wait_ready();
+}
+
 #endif	/* __CSS_SCP_H__ */
diff --git a/plat/arm/css/drivers/scpi/css_scpi.h b/plat/arm/css/drivers/scpi/css_scpi.h
index 0e26c3d..2a7e624 100644
--- a/plat/arm/css/drivers/scpi/css_scpi.h
+++ b/plat/arm/css/drivers/scpi/css_scpi.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -97,11 +97,11 @@
 	scpi_system_reset = 2
 } scpi_system_state_t;
 
-extern int scpi_wait_ready(void);
-extern void scpi_set_css_power_state(unsigned int mpidr,
-					scpi_power_state_t cpu_state,
-					scpi_power_state_t cluster_state,
-					scpi_power_state_t css_state);
+int scpi_wait_ready(void);
+void scpi_set_css_power_state(unsigned int mpidr,
+				scpi_power_state_t cpu_state,
+				scpi_power_state_t cluster_state,
+				scpi_power_state_t css_state);
 int scpi_get_css_power_state(unsigned int mpidr, unsigned int *cpu_state_p,
 		unsigned int *cluster_state_p);
 uint32_t scpi_sys_power_state(scpi_system_state_t system_state);
diff --git a/plat/hisilicon/hikey/hikey_bl1_setup.c b/plat/hisilicon/hikey/hikey_bl1_setup.c
index b005874..05e2e35 100644
--- a/plat/hisilicon/hikey/hikey_bl1_setup.c
+++ b/plat/hisilicon/hikey/hikey_bl1_setup.c
@@ -288,6 +288,11 @@
 
 	/* select 32.764KHz */
 	mmio_write_8(HI6553_CLK19M2_600_586_EN, 0x01);
+
+	/* Disable vbus_det interrupts */
+	data = mmio_read_8(HI6553_IRQ2_MASK);
+	data = data | 0x3;
+	mmio_write_8(HI6553_IRQ2_MASK, data);
 }
 
 static void init_mmc0_pll(void)
diff --git a/plat/hisilicon/hikey/include/hi6553.h b/plat/hisilicon/hikey/include/hi6553.h
index 76cb8ff..a80d36d 100644
--- a/plat/hisilicon/hikey/include/hi6553.h
+++ b/plat/hisilicon/hikey/include/hi6553.h
@@ -19,6 +19,7 @@
 #define DISABLE6_XO_CLK_RF2			(1 << 4)
 
 #define HI6553_VERSION_REG			(PMUSSI_BASE + (0x000 << 2))
+#define HI6553_IRQ2_MASK			(PMUSSI_BASE + (0x008 << 2))
 #define HI6553_ENABLE2_LDO1_8			(PMUSSI_BASE + (0x029 << 2))
 #define HI6553_DISABLE2_LDO1_8			(PMUSSI_BASE + (0x02a << 2))
 #define HI6553_ONOFF_STATUS2_LDO1_8		(PMUSSI_BASE + (0x02b << 2))
diff --git a/plat/nvidia/tegra/common/tegra_pm.c b/plat/nvidia/tegra/common/tegra_pm.c
index 0c25934..86021ba 100644
--- a/plat/nvidia/tegra/common/tegra_pm.c
+++ b/plat/nvidia/tegra/common/tegra_pm.c
@@ -36,6 +36,7 @@
  * The following platform setup functions are weakly defined. They
  * provide typical implementations that will be overridden by a SoC.
  */
+#pragma weak tegra_soc_pwr_domain_suspend_pwrdown_early
 #pragma weak tegra_soc_pwr_domain_suspend
 #pragma weak tegra_soc_pwr_domain_on
 #pragma weak tegra_soc_pwr_domain_off
@@ -45,6 +46,11 @@
 #pragma weak tegra_soc_prepare_system_off
 #pragma weak tegra_soc_get_target_pwr_state
 
+int tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state)
+{
+	return PSCI_E_NOT_SUPPORTED;
+}
+
 int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
 {
 	return PSCI_E_NOT_SUPPORTED;
@@ -145,6 +151,17 @@
 /*******************************************************************************
  * Handler called when a power domain is about to be suspended. The
  * target_state encodes the power state that each level should transition to.
+ * This handler is called with SMP and data cache enabled, when
+ * HW_ASSISTED_COHERENCY = 0
+ ******************************************************************************/
+void tegra_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state)
+{
+	tegra_soc_pwr_domain_suspend_pwrdown_early(target_state);
+}
+
+/*******************************************************************************
+ * Handler called when a power domain is about to be suspended. The
+ * target_state encodes the power state that each level should transition to.
  ******************************************************************************/
 void tegra_pwr_domain_suspend(const psci_power_state_t *target_state)
 {
@@ -315,6 +332,7 @@
 	.cpu_standby			= tegra_cpu_standby,
 	.pwr_domain_on			= tegra_pwr_domain_on,
 	.pwr_domain_off			= tegra_pwr_domain_off,
+	.pwr_domain_suspend_pwrdown_early = tegra_pwr_domain_suspend_pwrdown_early,
 	.pwr_domain_suspend		= tegra_pwr_domain_suspend,
 	.pwr_domain_on_finish		= tegra_pwr_domain_on_finish,
 	.pwr_domain_suspend_finish	= tegra_pwr_domain_suspend_finish,
diff --git a/plat/socionext/uniphier/platform.mk b/plat/socionext/uniphier/platform.mk
index 7ea0f10..72792f8 100644
--- a/plat/socionext/uniphier/platform.mk
+++ b/plat/socionext/uniphier/platform.mk
@@ -38,7 +38,6 @@
 # common sources for BL1, BL2, BL31
 PLAT_BL_COMMON_SOURCES	+=	drivers/console/aarch64/console.S	\
 				lib/xlat_tables_v2/aarch64/xlat_tables_arch.c \
-				lib/xlat_tables_v2/xlat_tables_common.c	\
 				lib/xlat_tables_v2/xlat_tables_internal.c \
 				$(PLAT_PATH)/uniphier_console.S		\
 				$(PLAT_PATH)/uniphier_helpers.S		\
diff --git a/readme.rst b/readme.rst
index a83338f..c3c0319 100644
--- a/readme.rst
+++ b/readme.rst
@@ -27,13 +27,15 @@
 This project contains code from other projects as listed below. The original
 license text is included in those source files.
 
--  The stdlib source code is derived from FreeBSD code.
+-  The stdlib source code is derived from FreeBSD code, which uses various
+   BSD licenses, including BSD-3-Clause and BSD-2-Clause.
 
 -  The libfdt source code is dual licensed. It is used by this project under
    the terms of the BSD-2-Clause license.
 
 -  The LLVM compiler-rt source code is dual licensed. It is used by this
-   project under the terms of the University of Illinois "BSD-Like" license.
+   project under the terms of the NCSA license (also known as the University of
+   Illinois/NCSA Open Source License).
 
 This Release
 ------------
diff --git a/tools/fiptool/Makefile b/tools/fiptool/Makefile
index 5e2ecc1..e0e3923 100644
--- a/tools/fiptool/Makefile
+++ b/tools/fiptool/Makefile
@@ -27,7 +27,7 @@
   Q :=
 endif
 
-INCLUDE_PATHS := -I. -I../../include/tools_share
+INCLUDE_PATHS := -I../../include/tools_share
 
 HOSTCC ?= gcc
 
diff --git a/tools/fiptool/fiptool.c b/tools/fiptool/fiptool.c
index 65e4a25..4d80f2f 100644
--- a/tools/fiptool/fiptool.c
+++ b/tools/fiptool/fiptool.c
@@ -19,6 +19,7 @@
 #include <unistd.h>
 
 #include <openssl/sha.h>
+
 #include <firmware_image_package.h>
 
 #include "fiptool.h"
diff --git a/tools/fiptool/fiptool.h b/tools/fiptool/fiptool.h
index 889b0fd..4b5cdd9 100644
--- a/tools/fiptool/fiptool.h
+++ b/tools/fiptool/fiptool.h
@@ -7,11 +7,10 @@
 #ifndef __FIPTOOL_H__
 #define __FIPTOOL_H__
 
-#include <firmware_image_package.h>
-
 #include <stddef.h>
 #include <stdint.h>
 
+#include <firmware_image_package.h>
 #include <uuid.h>
 
 #define NELEM(x) (sizeof (x) / sizeof *(x))
diff --git a/tools/fiptool/tbbr_config.c b/tools/fiptool/tbbr_config.c
index 6231cd4..7c6c24b 100644
--- a/tools/fiptool/tbbr_config.c
+++ b/tools/fiptool/tbbr_config.c
@@ -4,9 +4,10 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <firmware_image_package.h>
 #include <stddef.h>
 
+#include <firmware_image_package.h>
+
 #include "tbbr_config.h"
 
 /* The images used depends on the platform. */