Merge pull request #1100 from ajs-sun/master

trusty: save/restore FPU registers in world switch
diff --git a/Makefile b/Makefile
index 267fc82..a7d3a87 100644
--- a/Makefile
+++ b/Makefile
@@ -162,11 +162,13 @@
 include lib/stdlib/stdlib.mk
 
 BL_COMMON_SOURCES	+=	common/bl_common.c			\
+				common/tf_log.c				\
 				common/tf_printf.c			\
 				common/tf_snprintf.c			\
 				common/${ARCH}/debug.S			\
 				lib/${ARCH}/cache_helpers.S		\
 				lib/${ARCH}/misc_helpers.S		\
+				plat/common/plat_log_common.c		\
 				plat/common/${ARCH}/plat_common.c	\
 				plat/common/${ARCH}/platform_helpers.S	\
 				${COMPILER_RT_SRCS}			\
diff --git a/common/tf_log.c b/common/tf_log.c
new file mode 100644
index 0000000..54c0a43
--- /dev/null
+++ b/common/tf_log.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <platform.h>
+
+/* Set the default maximum log level to the `LOG_LEVEL` build flag */
+static unsigned int max_log_level = LOG_LEVEL;
+
+/*
+ * The common log function which is invoked by ARM Trusted Firmware code.
+ * This function should not be directly invoked and is meant to be
+ * only used by the log macros defined in debug.h. The function
+ * expects the first character in the format string to be one of the
+ * LOG_MARKER_* macros defined in debug.h.
+ */
+void tf_log(const char *fmt, ...)
+{
+	unsigned int log_level;
+	va_list args;
+	const char *prefix_str;
+
+	/* We expect the LOG_MARKER_* macro as the first character */
+	log_level = fmt[0];
+
+	/* Verify that log_level is one of LOG_MARKER_* macro defined in debug.h */
+	assert(log_level && log_level <= LOG_LEVEL_VERBOSE);
+	assert(log_level % 10 == 0);
+
+	if (log_level > max_log_level)
+		return;
+
+	prefix_str = plat_log_get_prefix(log_level);
+
+	if (prefix_str != NULL)
+		tf_string_print(prefix_str);
+
+	va_start(args, fmt);
+	tf_vprintf(fmt+1, args);
+	va_end(args);
+}
+
+/*
+ * The helper function to set the log level dynamically by platform. The
+ * maximum log level is determined by `LOG_LEVEL` build flag at compile time
+ * and this helper can set a lower log level than the one at compile.
+ */
+void tf_log_set_max_level(unsigned int log_level)
+{
+	assert(log_level <= LOG_LEVEL_VERBOSE);
+	assert((log_level % 10) == 0);
+
+	/* Cap log_level to the compile time maximum. */
+	if (log_level < LOG_LEVEL)
+		max_log_level = log_level;
+
+}
diff --git a/common/tf_printf.c b/common/tf_printf.c
index c18e2f9..f73842a 100644
--- a/common/tf_printf.c
+++ b/common/tf_printf.c
@@ -23,8 +23,10 @@
 	(((lcount) > 1) ? va_arg(args, unsigned long long int) :	\
 	((lcount) ? va_arg(args, unsigned long int) : va_arg(args, unsigned int)))
 
-static void string_print(const char *str)
+void tf_string_print(const char *str)
 {
+	assert(str);
+
 	while (*str)
 		putchar(*str++);
 }
@@ -64,15 +66,13 @@
  * The print exits on all other formats specifiers other than valid
  * combinations of the above specifiers.
  *******************************************************************/
-void tf_printf(const char *fmt, ...)
+void tf_vprintf(const char *fmt, va_list args)
 {
-	va_list args;
 	int l_count;
 	long long int num;
 	unsigned long long int unum;
 	char *str;
 
-	va_start(args, fmt);
 	while (*fmt) {
 		l_count = 0;
 
@@ -94,12 +94,12 @@
 				break;
 			case 's':
 				str = va_arg(args, char *);
-				string_print(str);
+				tf_string_print(str);
 				break;
 			case 'p':
 				unum = (uintptr_t)va_arg(args, void *);
 				if (unum)
-					string_print("0x");
+					tf_string_print("0x");
 
 				unsigned_num_print(unum, 16);
 				break;
@@ -123,13 +123,20 @@
 				break;
 			default:
 				/* Exit on any other format specifier */
-				goto exit;
+				return;
 			}
 			fmt++;
 			continue;
 		}
 		putchar(*fmt++);
 	}
-exit:
-	va_end(args);
+}
+
+void tf_printf(const char *fmt, ...)
+{
+	va_list va;
+
+	va_start(va, fmt);
+	tf_vprintf(fmt, va);
+	va_end(va);
 }
diff --git a/docs/auth-framework.rst b/docs/auth-framework.rst
index 765d9f8..3a054c7 100644
--- a/docs/auth-framework.rst
+++ b/docs/auth-framework.rst
@@ -921,9 +921,12 @@
     int verify_hash(void *data_ptr, unsigned int data_len,
                     void *digest_info_ptr, unsigned int digest_info_len);
 
-The key algorithm (rsa, ecdsa) must be specified in the build system using the
-``TF_MBEDTLS_KEY_ALG`` variable, so the Makefile can include the corresponding
-sources in the build.
+The mbedTLS library algorithm support is configured by the
+``TF_MBEDTLS_KEY_ALG`` variable which can take in 3 values: `rsa`, `ecdsa` or
+`rsa+ecdsa`. This variable allows the Makefile to include the corresponding
+sources in the build for the various algorthms. Setting the variable to
+`rsa+ecdsa` enables support for both rsa and ecdsa algorithms in the mbedTLS
+library.
 
 Note: If code size is a concern, the build option ``MBEDTLS_SHA256_SMALLER`` can
 be defined in the platform Makefile. It will make mbed TLS use an implementation
@@ -931,7 +934,7 @@
 
 --------------
 
-*Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.*
+*Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.*
 
 .. _Trusted Board Boot: ./trusted-board-boot.rst
 .. _Platform Porting Guide: ./porting-guide.rst
diff --git a/docs/plat/hikey.rst b/docs/plat/hikey.rst
index e194ede..1c48104 100644
--- a/docs/plat/hikey.rst
+++ b/docs/plat/hikey.rst
@@ -38,6 +38,16 @@
 -  Fetch all the above repositories into local host.
    Make all the repositories in the same ${BUILD\_PATH}.
 
+  .. code:: shell
+
+       git clone https://github.com/ARM-software/arm-trusted-firmware -b integration
+       git clone https://github.com/OP-TEE/optee_os
+       git clone https://github.com/96boards-hikey/edk2 -b testing/hikey960_v2.5
+       git clone https://github.com/96boards-hikey/OpenPlatformPkg -b testing/hikey960_v1.3.4
+       git clone https://github.com/96boards-hikey/l-loader -b testing/hikey960_v1.2
+       git clone https://git.linaro.org/uefi/uefi-tools
+       git clone https://github.com/96boards-hikey/atf-fastboot
+
 -  Create the symbol link to OpenPlatformPkg in edk2.
 
    .. code:: shell
@@ -74,20 +84,15 @@
        cd ${EDK2_DIR}
        # Build UEFI & ARM Trust Firmware
        ${UEFI_TOOLS_DIR}/uefi-build.sh -b ${BUILD_OPTION} -a ../arm-trusted-firmware -s ../optee_os hikey
-       # Generate l-loader.bin
-       cd ${BUILD_PATH}/l-loader
-       ln -sf ${EDK2_OUTPUT_DIR}/FV/bl1.bin
-       ln -sf ${BUILD_PATH}/atf-fastboot/build/hikey/${FASTBOOT_BUILD_OPTION}/bl1.bin fastboot.bin
-       arm-linux-gnueabihf-gcc -c -o start.o start.S
-       arm-linux-gnueabihf-ld -Bstatic -Tl-loader.lds -Ttext 0xf9800800 start.o -o loader
-       arm-linux-gnueabihf-objcopy -O binary loader temp
-       python gen_loader_hikey.py -o l-loader.bin --img_loader=temp --img_bl1=bl1.bin --img_ns_bl1u=fastboot.bin
 
--  Generate partition table for aosp. The eMMC capacity is either 4GB or 8GB. Just change "aosp-4g" to "linux-4g" for debian.
+-  Generate l-loader.bin and partition table for aosp. The eMMC capacity is either 8GB or 4GB. Just change "aosp-8g" to "linux-8g" for debian.
 
    .. code:: shell
 
-       PTABLE=aosp-4g SECTOR_SIZE=512 bash -x generate_ptable.sh
+       cd ${BUILD_PATH}/l-loader
+       ln -sf ${EDK2_OUTPUT_DIR}/FV/bl1.bin
+       ln -sf ${BUILD_PATH}/atf-fastboot/build/hikey/${FASTBOOT_BUILD_OPTION}/bl1.bin fastboot.bin
+       make hikey PTABLE_LST=aosp-8g
 
 Setup Console
 -------------
diff --git a/docs/plat/hikey960.rst b/docs/plat/hikey960.rst
index cd1880e..8524b48 100644
--- a/docs/plat/hikey960.rst
+++ b/docs/plat/hikey960.rst
@@ -35,6 +35,15 @@
 -  Fetch all the above 5 repositories into local host.
    Make all the repositories in the same ${BUILD\_PATH}.
 
+  .. code:: shell
+
+       git clone https://github.com/ARM-software/arm-trusted-firmware -b integration
+       git clone https://github.com/OP-TEE/optee_os
+       git clone https://github.com/96boards-hikey/edk2 -b testing/hikey960_v2.5
+       git clone https://github.com/96boards-hikey/OpenPlatformPkg -b testing/hikey960_v1.3.4
+       git clone https://github.com/96boards-hikey/l-loader -b testing/hikey960_v1.2
+       git clone https://git.linaro.org/uefi/uefi-tools
+
 -  Create the symbol link to OpenPlatformPkg in edk2.
 
    .. code:: shell
@@ -66,19 +75,17 @@
        cd ${EDK2_DIR}
        # Build UEFI & ARM Trust Firmware
        ${UEFI_TOOLS_DIR}/uefi-build.sh -b ${BUILD_OPTION} -a ../arm-trusted-firmware -s ../optee_os hikey960
-       # Generate l-loader.bin
-       cd ${BUILD_PATH}/l-loader
-       ln -sf ${EDK2_OUTPUT_DIR}/FV/bl1.bin
-       ln -sf ${EDK2_OUTPUT_DIR}/FV/fip.bin
-       ln -sf ${EDK2_OUTPUT_DIR}/FV/BL33_AP_UEFI.fd
-       python gen_loader_hikey960.py -o l-loader.bin --img_bl1=bl1.bin --img_ns_bl1u=BL33_AP_UEFI.fd
 
--  Generate partition table.
+-  Generate l-loader.bin and partition table.
    *Make sure that you're using the sgdisk in the l-loader directory.*
 
    .. code:: shell
 
-       PTABLE=aosp-32g SECTOR_SIZE=4096 SGDISK=./sgdisk bash -x generate_ptable.sh
+       cd ${BUILD_PATH}/l-loader
+       ln -sf ${EDK2_OUTPUT_DIR}/FV/bl1.bin
+       ln -sf ${EDK2_OUTPUT_DIR}/FV/fip.bin
+       ln -sf ${EDK2_OUTPUT_DIR}/FV/BL33_AP_UEFI.fd
+       make hikey960
 
 Setup Console
 -------------
@@ -129,6 +136,7 @@
 
        $cd tools-images-hikey960
        $ln -sf ${BUILD_PATH}/l-loader/l-loader.bin
+       $ln -sf ${BUILD_PATH}/l-loader/fip.bin
 
 -  Prepare config file.
 
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index c8d61ed..6c07b2e 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -1014,6 +1014,21 @@
 next image. This function is currently invoked in BL2 to flush this information
 to the next BL image, when LOAD\_IMAGE\_V2 is enabled.
 
+Function : plat\_log\_get\_prefix()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : unsigned int
+    Return   : const char *
+
+This function defines the prefix string corresponding to the `log_level` to be
+prepended to all the log output from ARM Trusted Firmware. The `log_level`
+(argument) will correspond to one of the standard log levels defined in
+debug.h. The platform can override the common implementation to define a
+different prefix string for the log output.  The implementation should be
+robust to future changes that increase the number of log levels.
+
 Modifications specific to a Boot Loader stage
 ---------------------------------------------
 
@@ -2092,13 +2107,32 @@
 corresponding to the local state at each power level. The generic code
 expects the handler to succeed.
 
-The difference between turning a power domain off versus suspending it
-is that in the former case, the power domain is expected to re-initialize
-its state when it is next powered on (see ``pwr_domain_on_finish()``). In the
-latter case, the power domain is expected to save enough state so that it can
-resume execution by restoring this state when its powered on (see
+The difference between turning a power domain off versus suspending it is that
+in the former case, the power domain is expected to re-initialize its state
+when it is next powered on (see ``pwr_domain_on_finish()``). In the latter
+case, the power domain is expected to save enough state so that it can resume
+execution by restoring this state when its powered on (see
 ``pwr_domain_suspend_finish()``).
 
+When suspending a core, the platform can also choose to power off the GICv3
+Redistributor and ITS through an implementation-defined sequence. To achieve
+this safely, the ITS context must be saved first. The architectural part is
+implemented by the ``gicv3_its_save_disable()`` helper, but most of the needed
+sequence is implementation defined and it is therefore the responsibility of
+the platform code to implement the necessary sequence. Then the GIC
+Redistributor context can be saved using the ``gicv3_rdistif_save()`` helper.
+Powering off the Redistributor requires the implementation to support it and it
+is the responsibility of the platform code to execute the right implementation
+defined sequence.
+
+When a system suspend is requested, the platform can also make use of the
+``gicv3_distif_save()`` helper to save the context of the GIC Distributor after
+it has saved the context of the Redistributors and ITS of all the cores in the
+system. The context of the Distributor can be large and may require it to be
+allocated in a special area if it cannot fit in the platform's global static
+data, for example in DRAM. The Distributor can then be powered down using an
+implementation-defined sequence.
+
 plat\_psci\_ops.pwr\_domain\_pwr\_down\_wfi()
 .............................................
 
@@ -2144,6 +2178,10 @@
 the ``pwr_domain_on_finish()`` operation. The generic code expects the platform
 to succeed.
 
+If the Distributor, Redistributors or ITS have been powered off as part of a
+suspend, their context must be restored in this function in the reverse order
+to how they were saved during suspend sequence.
+
 plat\_psci\_ops.system\_off()
 .............................
 
diff --git a/docs/user-guide.rst b/docs/user-guide.rst
index 1ff080d..67af425 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -643,6 +643,11 @@
       ``arm_rotpk_rsa.der``, located in ``plat/arm/board/common/rotpk``. To use
       this option, ``arm_rotprivk_rsa.pem`` must be specified as ``ROT_KEY`` when
       creating the certificates.
+   -  ``devel_ecdsa`` : return a development public key hash embedded in the BL1
+      and BL2 binaries. This hash has been obtained from the ECDSA public key
+      ``arm_rotpk_ecdsa.der``, located in ``plat/arm/board/common/rotpk``. To use
+      this option, ``arm_rotprivk_ecdsa.pem`` must be specified as ``ROT_KEY``
+      when creating the certificates.
 
 -  ``ARM_TSP_RAM_LOCATION``: location of the TSP binary. Options:
 
@@ -990,6 +995,10 @@
       in the ARM platform port. The private/public RSA key pair may be
       found in ``plat/arm/board/common/rotpk``.
 
+   -  ``ARM_ROTPK_LOCATION=devel_ecdsa``: use the ROTPK hash that is hardcoded
+      in the ARM platform port. The private/public ECDSA key pair may be
+      found in ``plat/arm/board/common/rotpk``.
+
    Example of command line using RSA development keys:
 
    ::
diff --git a/docs/xlat-tables-lib-v2-design.rst b/docs/xlat-tables-lib-v2-design.rst
index 3006ce7..07cbf86 100644
--- a/docs/xlat-tables-lib-v2-design.rst
+++ b/docs/xlat-tables-lib-v2-design.rst
@@ -66,7 +66,8 @@
 - its physical base address;
 - its virtual base address;
 - its size;
-- its attributes.
+- its attributes;
+- its mapping granularity (optional).
 
 See the ``struct mmap_region`` type in `xlat\_tables\_v2.h`_.
 
@@ -76,9 +77,37 @@
 
 The region attributes specify the type of memory (for example device or cached
 normal memory) as well as the memory access permissions (read-only or
-read-write, executable or not, secure or non-secure, and so on). See the
-``mmap_attr_t`` enumeration type in `xlat\_tables\_v2.h`_.
+read-write, executable or not, secure or non-secure, and so on). In the case of
+the EL1&0 translation regime, the attributes also specify whether the region is
+a User region (EL0) or Privileged region (EL1). See the ``mmap_attr_t``
+enumeration type in `xlat\_tables\_v2.h`_. Note that for the EL1&0 translation
+regime the Execute Never attribute is set simultaneously for both EL1 and EL0.
 
+The granularity controls the translation table level to go down to when mapping
+the region. For example, assuming the MMU has been configured to use a 4KB
+granule size, the library might map a 2MB memory region using either of the two
+following options:
+
+- using a single level-2 translation table entry;
+- using a level-2 intermediate entry to a level-3 translation table (which
+  contains 512 entries, each mapping 4KB).
+
+The first solution potentially requires less translation tables, hence
+potentially less memory.  However, if part of this 2MB region is later remapped
+with different memory attributes, the library might need to split the existing
+page tables to refine the mappings. If a single level-2 entry has been used
+here, a level-3 table will need to be allocated on the fly and the level-2
+modified to point to this new level-3 table. This has a performance cost at
+run-time.
+
+If the user knows upfront that such a remapping operation is likely to happen
+then they might enforce a 4KB mapping granularity for this 2MB region from the
+beginning; remapping some of these 4KB pages on the fly then becomes a
+lightweight operation.
+
+The region's granularity is an optional field; if it is not specified the
+library will choose the mapping granularity for this region as it sees fit (more
+details can be found in `The memory mapping algorithm`_ section below).
 
 Translation Context
 ~~~~~~~~~~~~~~~~~~~
@@ -190,6 +219,11 @@
 compatibility breaks, should the ``mmap_region`` structure type evolve in the
 future.
 
+The ``MAP_REGION()`` and ``MAP_REGION_FLAT()`` macros do not allow specifying a
+mapping granularity, which leaves the library implementation free to choose
+it. However, in cases where a specific granularity is required, the
+``MAP_REGION2()`` macro might be used instead.
+
 As explained earlier in this document, when the dynamic mapping feature is
 disabled, there is no notion of dynamic regions. Conceptually, there are only
 static regions. For this reason (and to retain backward compatibility with the
@@ -265,6 +299,9 @@
 Core module
 ~~~~~~~~~~~
 
+From mmap regions to translation tables
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 All the APIs in this module work on a translation context. The translation
 context contains the list of ``mmap_region``, which holds the information of all
 the regions that are mapped at any given time. Whenever there is a request to
@@ -288,14 +325,18 @@
 be added. Changes to the translation tables (as well as the mmap regions list)
 will take effect immediately.
 
+The memory mapping algorithm
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 The mapping function is implemented as a recursive algorithm. It is however
 bound by the level of depth of the translation tables (the ARMv8-A architecture
 allows up to 4 lookup levels).
 
-By default, the algorithm will attempt to minimize the number of translation
-tables created to satisfy the user's request. It will favour mapping a region
-using the biggest possible blocks, only creating a sub-table if it is strictly
-necessary. This is to reduce the memory footprint of the firmware.
+By default [#granularity-ref]_, the algorithm will attempt to minimize the
+number of translation tables created to satisfy the user's request. It will
+favour mapping a region using the biggest possible blocks, only creating a
+sub-table if it is strictly necessary. This is to reduce the memory footprint of
+the firmware.
 
 The most common reason for needing a sub-table is when a specific mapping
 requires a finer granularity. Misaligned regions also require a finer
@@ -322,6 +363,12 @@
 refer to the comments in the source code of the core module for more details
 about the sorting algorithm in use.
 
+.. [#granularity-ref] That is, when mmap regions do not enforce their mapping
+                      granularity.
+
+TLB maintenance operations
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 The library takes care of performing TLB maintenance operations when required.
 For example, when the user requests removing a dynamic region, the library
 invalidates all TLB entries associated to that region to ensure that these
diff --git a/drivers/arm/ccn/ccn.c b/drivers/arm/ccn/ccn.c
index ec264d2..afb7d9d 100644
--- a/drivers/arm/ccn/ccn.c
+++ b/drivers/arm/ccn/ccn.c
@@ -236,7 +236,7 @@
 		node_id = ccn_plat_desc->master_to_rn_id_map[iface_id];
 
 		/* Set the bit corresponding to this node ID */
-		rn_id_map |= (1UL << node_id);
+		rn_id_map |= (1ULL << node_id);
 	}
 
 	return rn_id_map;
diff --git a/drivers/arm/ccn/ccn_private.h b/drivers/arm/ccn/ccn_private.h
index f71597c..c17c274 100644
--- a/drivers/arm/ccn/ccn_private.h
+++ b/drivers/arm/ccn/ccn_private.h
@@ -134,13 +134,13 @@
 #define HNF_SAM_CTRL_SN1_ID_SHIFT	8
 #define HNF_SAM_CTRL_SN2_ID_SHIFT	16
 
-#define HNF_SAM_CTRL_TAB0_MASK		0x3fUL
+#define HNF_SAM_CTRL_TAB0_MASK		ULL(0x3f)
 #define HNF_SAM_CTRL_TAB0_SHIFT		48
-#define HNF_SAM_CTRL_TAB1_MASK		0x3fUL
+#define HNF_SAM_CTRL_TAB1_MASK		ULL(0x3f)
 #define HNF_SAM_CTRL_TAB1_SHIFT		56
 
 #define HNF_SAM_CTRL_3SN_ENB_SHIFT	32
-#define HNF_SAM_CTRL_3SN_ENB_MASK	0x01UL
+#define HNF_SAM_CTRL_3SN_ENB_MASK	ULL(0x01)
 
 /*
  * Macro to create a value suitable for programming into a HNF SAM Control
@@ -169,7 +169,7 @@
 #define FOR_EACH_BIT(bit_pos, bit_map)			\
 	for (bit_pos = __builtin_ctzll(bit_map);	\
 	     bit_map;					\
-	     bit_map &= ~(1UL << bit_pos),		\
+	     bit_map &= ~(1ULL << (bit_pos)),		\
 	     bit_pos = __builtin_ctzll(bit_map))
 
 /*
diff --git a/drivers/arm/gic/v3/arm_gicv3_common.c b/drivers/arm/gic/v3/arm_gicv3_common.c
new file mode 100644
index 0000000..8d552ca
--- /dev/null
+++ b/drivers/arm/gic/v3/arm_gicv3_common.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Driver for implementation defined features that are identical in ARM GICv3
+* implementations (GIC-500 and GIC-600 for now). This driver only overrides
+* APIs that are different to those generic ones in GICv3 driver.
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <gicv3.h>
+
+#include "gicv3_private.h"
+#include "arm_gicv3_common.h"
+
+/*
+ * Flush the internal GIC cache of the LPIs pending tables to memory before
+ * saving the state of the Redistributor. This is required before powering off
+ * the GIC when the pending status must be preserved.
+ * `rdist_proc_num` is the processor number corresponding to the Redistributor of the
+ * current CPU.
+ */
+void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num)
+{
+	uintptr_t gicr_base = 0;
+
+	assert(gicv3_driver_data);
+	assert(gicv3_driver_data->rdistif_base_addrs);
+
+	/*
+	 * The GICR_WAKER.Sleep bit should be set only when both
+	 * GICR_WAKER.ChildrenAsleep and GICR_WAKER.ProcessorSleep are set on
+	 * all the Redistributors.
+	 */
+	for (unsigned int i = 0; i < gicv3_driver_data->rdistif_num; i++) {
+		gicr_base = gicv3_driver_data->rdistif_base_addrs[i];
+		assert(gicr_base);
+		assert(gicr_read_waker(gicr_base) & WAKER_CA_BIT);
+		assert(gicr_read_waker(gicr_base) & WAKER_PS_BIT);
+	}
+
+	gicr_base = gicv3_driver_data->rdistif_base_addrs[rdist_proc_num];
+	/*
+	 * According to the TRM, there is only one instance of the
+	 * GICR_WAKER.Sleep and GICR_WAKER.Quiescent bits that can be accessed
+	 * through any of the Redistributor.
+	 */
+
+	/*
+	 * Set GICR_WAKER.Sleep
+	 * After this point, the system must be configured so that the
+	 * wake_request signals for the right cores are asserted when a wakeup
+	 * interrupt is detected. The GIC will not be able to do that anymore
+	 * when the GICR_WAKER.Sleep bit is set to 1.
+	 */
+	gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) | WAKER_SL_BIT);
+
+	/* Wait until the GICR_WAKER.Quiescent bit is set */
+	while (!(gicr_read_waker(gicr_base) & WAKER_QSC_BIT))
+		;
+}
+
+/*
+ * Allow the LPIs pending state to be read back from the tables in memory after
+ * having restored the state of the GIC Redistributor.
+ */
+void arm_gicv3_distif_post_restore(unsigned int rdist_proc_num)
+{
+	uintptr_t gicr_base;
+
+	assert(gicv3_driver_data);
+	assert(gicv3_driver_data->rdistif_base_addrs);
+
+	/*
+	 * According to the TRM, there is only one instance of the
+	 * GICR_WAKER.Sleep and GICR_WAKER.Quiescent bits that can be accessed
+	 * through any of the Redistributor.
+	 */
+	gicr_base = gicv3_driver_data->rdistif_base_addrs[rdist_proc_num];
+	assert(gicr_base);
+
+	/*
+	 * Writes to GICR_WAKER.Sleep bit are ignored if GICR_WAKER.Quiescent
+	 * bit is not set. We should be alright on power on path, therefore
+	 * coming out of sleep and Quiescent should be set, but we assert in
+	 * case.
+	 */
+	assert(gicr_read_waker(gicr_base) & WAKER_QSC_BIT);
+
+	/* Clear GICR_WAKER.Sleep */
+	gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) & ~WAKER_SL_BIT);
+
+	/*
+	 * We don't know if the effects of setting GICR_WAKER.Sleep bit is
+	 * instantaneous, so we wait until the interface is not Quiescent
+	 * anymore.
+	 */
+	while (gicr_read_waker(gicr_base) & WAKER_QSC_BIT)
+		;
+}
+
diff --git a/drivers/arm/gic/v3/gic500.c b/drivers/arm/gic/v3/gic500.c
new file mode 100644
index 0000000..f03e33f
--- /dev/null
+++ b/drivers/arm/gic/v3/gic500.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Driver for GIC500-specific features. This driver only overrides APIs that are
+ * different to those generic ones in GICv3 driver.
+ */
+#include "gicv3_private.h"
+
+void gicv3_distif_pre_save(unsigned int proc_num)
+{
+	arm_gicv3_distif_pre_save(proc_num);
+}
+
+void gicv3_distif_post_restore(unsigned int proc_num)
+{
+	arm_gicv3_distif_post_restore(proc_num);
+}
+
diff --git a/drivers/arm/gic/v3/gic600.c b/drivers/arm/gic/v3/gic600.c
index 4ea31ab..eb4fc54 100644
--- a/drivers/arm/gic/v3/gic600.c
+++ b/drivers/arm/gic/v3/gic600.c
@@ -18,32 +18,29 @@
 #include "gicv3_private.h"
 
 /* GIC600-specific register offsets */
-#define GICR_PWRR		0x24
+#define GICR_PWRR	0x24
 
 /* GICR_PWRR fields */
 #define PWRR_RDPD_SHIFT		0
 #define PWRR_RDGPD_SHIFT	2
 #define PWRR_RDGPO_SHIFT	3
 
-#define PWRR_RDGPD		(1 << PWRR_RDGPD_SHIFT)
-#define PWRR_RDGPO		(1 << PWRR_RDGPO_SHIFT)
+#define PWRR_RDGPD	(1 << PWRR_RDGPD_SHIFT)
+#define PWRR_RDGPO	(1 << PWRR_RDGPO_SHIFT)
 
 /* Values to write to GICR_PWRR register to power redistributor */
-#define PWRR_ON			(0 << PWRR_RDPD_SHIFT)
-#define PWRR_OFF		(1 << PWRR_RDPD_SHIFT)
-
-/* Generic GICv3 resources */
-extern const gicv3_driver_data_t *gicv3_driver_data;
+#define PWRR_ON		(0 << PWRR_RDPD_SHIFT)
+#define PWRR_OFF	(1 << PWRR_RDPD_SHIFT)
 
 /* GIC600-specific accessor functions */
 static void gicr_write_pwrr(uintptr_t base, unsigned int val)
 {
-       mmio_write_32(base + GICR_PWRR, val);
+	mmio_write_32(base + GICR_PWRR, val);
 }
 
 static uint32_t gicr_read_pwrr(uintptr_t base)
 {
-       return mmio_read_32(base + GICR_PWRR);
+	return mmio_read_32(base + GICR_PWRR);
 }
 
 static int gicr_group_powering_down(uint32_t pwrr)
@@ -82,6 +79,16 @@
 	}
 }
 
+void gicv3_distif_pre_save(unsigned int proc_num)
+{
+	arm_gicv3_distif_pre_save(proc_num);
+}
+
+void gicv3_distif_post_restore(unsigned int proc_num)
+{
+	arm_gicv3_distif_post_restore(proc_num);
+}
+
 /*
  * Power off GIC600 redistributor
  */
diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c
index b68d998..1a018d8 100644
--- a/drivers/arm/gic/v3/gicv3_main.c
+++ b/drivers/arm/gic/v3/gicv3_main.c
@@ -21,6 +21,27 @@
 #pragma weak gicv3_rdistif_off
 #pragma weak gicv3_rdistif_on
 
+
+/* Helper macros to save and restore GICD registers to and from the context */
+#define RESTORE_GICD_REGS(base, ctx, intr_num, reg, REG)		\
+	do {								\
+		for (unsigned int int_id = MIN_SPI_ID; int_id < intr_num; \
+				int_id += (1 << REG##_SHIFT)) {		\
+			gicd_write_##reg(base, int_id,			\
+				ctx->gicd_##reg[(int_id - MIN_SPI_ID) >> REG##_SHIFT]); \
+		}							\
+	} while (0)
+
+#define SAVE_GICD_REGS(base, ctx, intr_num, reg, REG)			\
+	do {								\
+		for (unsigned int int_id = MIN_SPI_ID; int_id < intr_num; \
+				int_id += (1 << REG##_SHIFT)) {		\
+			ctx->gicd_##reg[(int_id - MIN_SPI_ID) >> REG##_SHIFT] =\
+					gicd_read_##reg(base, int_id);	\
+		}							\
+	} while (0)
+
+
 /*******************************************************************************
  * This function initialises the ARM GICv3 driver in EL3 with provided platform
  * inputs.
@@ -406,3 +427,345 @@
 	/* Else it is a Group 0 Secure interrupt */
 	return INTR_GROUP0;
 }
+
+/*****************************************************************************
+ * Function to save and disable the GIC ITS register context. The power
+ * management of GIC ITS is implementation-defined and this function doesn't
+ * save any memory structures required to support ITS. As the sequence to save
+ * this state is implementation defined, it should be executed in platform
+ * specific code. Calling this function alone and then powering down the GIC and
+ * ITS without implementing the aforementioned platform specific code will
+ * corrupt the ITS state.
+ *
+ * This function must be invoked after the GIC CPU interface is disabled.
+ *****************************************************************************/
+void gicv3_its_save_disable(uintptr_t gits_base, gicv3_its_ctx_t * const its_ctx)
+{
+	int i;
+
+	assert(gicv3_driver_data);
+	assert(IS_IN_EL3());
+	assert(its_ctx);
+	assert(gits_base);
+
+	its_ctx->gits_ctlr = gits_read_ctlr(gits_base);
+
+	/* Disable the ITS */
+	gits_write_ctlr(gits_base, its_ctx->gits_ctlr &
+					(~GITS_CTLR_ENABLED_BIT));
+
+	/* Wait for quiescent state */
+	gits_wait_for_quiescent_bit(gits_base);
+
+	its_ctx->gits_cbaser = gits_read_cbaser(gits_base);
+	its_ctx->gits_cwriter = gits_read_cwriter(gits_base);
+
+	for (i = 0; i < ARRAY_SIZE(its_ctx->gits_baser); i++)
+		its_ctx->gits_baser[i] = gits_read_baser(gits_base, i);
+}
+
+/*****************************************************************************
+ * Function to restore the GIC ITS register context. The power
+ * management of GIC ITS is implementation defined and this function doesn't
+ * restore any memory structures required to support ITS. The assumption is
+ * that these structures are in memory and are retained during system suspend.
+ *
+ * This must be invoked before the GIC CPU interface is enabled.
+ *****************************************************************************/
+void gicv3_its_restore(uintptr_t gits_base, const gicv3_its_ctx_t * const its_ctx)
+{
+	int i;
+
+	assert(gicv3_driver_data);
+	assert(IS_IN_EL3());
+	assert(its_ctx);
+	assert(gits_base);
+
+	/* Assert that the GITS is disabled and quiescent */
+	assert((gits_read_ctlr(gits_base) & GITS_CTLR_ENABLED_BIT) == 0);
+	assert((gits_read_ctlr(gits_base) & GITS_CTLR_QUIESCENT_BIT) != 0);
+
+	gits_write_cbaser(gits_base, its_ctx->gits_cbaser);
+	gits_write_cwriter(gits_base, its_ctx->gits_cwriter);
+
+	for (i = 0; i < ARRAY_SIZE(its_ctx->gits_baser); i++)
+		gits_write_baser(gits_base, i, its_ctx->gits_baser[i]);
+
+	/* Restore the ITS CTLR but leave the ITS disabled */
+	gits_write_ctlr(gits_base, its_ctx->gits_ctlr &
+			(~GITS_CTLR_ENABLED_BIT));
+}
+
+/*****************************************************************************
+ * Function to save the GIC Redistributor register context. This function
+ * must be invoked after CPU interface disable and prior to Distributor save.
+ *****************************************************************************/
+void gicv3_rdistif_save(unsigned int proc_num, gicv3_redist_ctx_t * const rdist_ctx)
+{
+	uintptr_t gicr_base;
+	unsigned int int_id;
+
+	assert(gicv3_driver_data);
+	assert(proc_num < gicv3_driver_data->rdistif_num);
+	assert(gicv3_driver_data->rdistif_base_addrs);
+	assert(IS_IN_EL3());
+	assert(rdist_ctx);
+
+	gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+
+	/*
+	 * Wait for any write to GICR_CTLR to complete before trying to save any
+	 * state.
+	 */
+	gicr_wait_for_pending_write(gicr_base);
+
+	rdist_ctx->gicr_ctlr = gicr_read_ctlr(gicr_base);
+
+	rdist_ctx->gicr_propbaser = gicr_read_propbaser(gicr_base);
+	rdist_ctx->gicr_pendbaser = gicr_read_pendbaser(gicr_base);
+
+	rdist_ctx->gicr_igroupr0 = gicr_read_igroupr0(gicr_base);
+	rdist_ctx->gicr_isenabler0 = gicr_read_isenabler0(gicr_base);
+	rdist_ctx->gicr_ispendr0 = gicr_read_ispendr0(gicr_base);
+	rdist_ctx->gicr_isactiver0 = gicr_read_isactiver0(gicr_base);
+	rdist_ctx->gicr_icfgr0 = gicr_read_icfgr0(gicr_base);
+	rdist_ctx->gicr_icfgr1 = gicr_read_icfgr1(gicr_base);
+	rdist_ctx->gicr_igrpmodr0 = gicr_read_igrpmodr0(gicr_base);
+	rdist_ctx->gicr_nsacr = gicr_read_nsacr(gicr_base);
+	for (int_id = MIN_SGI_ID; int_id < TOTAL_PCPU_INTR_NUM;
+			int_id += (1 << IPRIORITYR_SHIFT)) {
+		rdist_ctx->gicr_ipriorityr[(int_id - MIN_SGI_ID) >> IPRIORITYR_SHIFT] =
+				gicr_read_ipriorityr(gicr_base, int_id);
+	}
+
+
+	/*
+	 * Call the pre-save hook that implements the IMP DEF sequence that may
+	 * be required on some GIC implementations. As this may need to access
+	 * the Redistributor registers, we pass it proc_num.
+	 */
+	gicv3_distif_pre_save(proc_num);
+}
+
+/*****************************************************************************
+ * Function to restore the GIC Redistributor register context. We disable
+ * LPI and per-cpu interrupts before we start restore of the Redistributor.
+ * This function must be invoked after Distributor restore but prior to
+ * CPU interface enable. The pending and active interrupts are restored
+ * after the interrupts are fully configured and enabled.
+ *****************************************************************************/
+void gicv3_rdistif_init_restore(unsigned int proc_num,
+				const gicv3_redist_ctx_t * const rdist_ctx)
+{
+	uintptr_t gicr_base;
+	unsigned int int_id;
+
+	assert(gicv3_driver_data);
+	assert(proc_num < gicv3_driver_data->rdistif_num);
+	assert(gicv3_driver_data->rdistif_base_addrs);
+	assert(IS_IN_EL3());
+	assert(rdist_ctx);
+
+	gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+
+	/* Power on redistributor */
+	gicv3_rdistif_on(proc_num);
+
+	/*
+	 * Call the post-restore hook that implements the IMP DEF sequence that
+	 * may be required on some GIC implementations. As this may need to
+	 * access the Redistributor registers, we pass it proc_num.
+	 */
+	gicv3_distif_post_restore(proc_num);
+
+	/*
+	 * Disable all SGIs (imp. def.)/PPIs before configuring them. This is a
+	 * more scalable approach as it avoids clearing the enable bits in the
+	 * GICD_CTLR
+	 */
+	gicr_write_icenabler0(gicr_base, ~0);
+	/* Wait for pending writes to GICR_ICENABLER */
+	gicr_wait_for_pending_write(gicr_base);
+
+	/*
+	 * Disable the LPIs to avoid unpredictable behavior when writing to
+	 * GICR_PROPBASER and GICR_PENDBASER.
+	 */
+	gicr_write_ctlr(gicr_base,
+			rdist_ctx->gicr_ctlr & ~(GICR_CTLR_EN_LPIS_BIT));
+
+	/* Restore registers' content */
+	gicr_write_propbaser(gicr_base, rdist_ctx->gicr_propbaser);
+	gicr_write_pendbaser(gicr_base, rdist_ctx->gicr_pendbaser);
+
+	gicr_write_igroupr0(gicr_base, rdist_ctx->gicr_igroupr0);
+
+	for (int_id = MIN_SGI_ID; int_id < TOTAL_PCPU_INTR_NUM;
+			int_id += (1 << IPRIORITYR_SHIFT)) {
+		gicr_write_ipriorityr(gicr_base, int_id,
+		rdist_ctx->gicr_ipriorityr[
+				(int_id - MIN_SGI_ID) >> IPRIORITYR_SHIFT]);
+	}
+
+	gicr_write_icfgr0(gicr_base, rdist_ctx->gicr_icfgr0);
+	gicr_write_icfgr1(gicr_base, rdist_ctx->gicr_icfgr1);
+	gicr_write_igrpmodr0(gicr_base, rdist_ctx->gicr_igrpmodr0);
+	gicr_write_nsacr(gicr_base, rdist_ctx->gicr_nsacr);
+
+	/* Restore after group and priorities are set */
+	gicr_write_ispendr0(gicr_base, rdist_ctx->gicr_ispendr0);
+	gicr_write_isactiver0(gicr_base, rdist_ctx->gicr_isactiver0);
+
+	/*
+	 * Wait for all writes to the Distributor to complete before enabling
+	 * the SGI and PPIs.
+	 */
+	gicr_wait_for_upstream_pending_write(gicr_base);
+	gicr_write_isenabler0(gicr_base, rdist_ctx->gicr_isenabler0);
+
+	/*
+	 * Restore GICR_CTLR.Enable_LPIs bit and wait for pending writes in case
+	 * the first write to GICR_CTLR was still in flight (this write only
+	 * restores GICR_CTLR.Enable_LPIs and no waiting is required for this
+	 * bit).
+	 */
+	gicr_write_ctlr(gicr_base, rdist_ctx->gicr_ctlr);
+	gicr_wait_for_pending_write(gicr_base);
+}
+
+/*****************************************************************************
+ * Function to save the GIC Distributor register context. This function
+ * must be invoked after CPU interface disable and Redistributor save.
+ *****************************************************************************/
+void gicv3_distif_save(gicv3_dist_ctx_t * const dist_ctx)
+{
+	unsigned int num_ints;
+
+	assert(gicv3_driver_data);
+	assert(gicv3_driver_data->gicd_base);
+	assert(IS_IN_EL3());
+	assert(dist_ctx);
+
+	uintptr_t gicd_base = gicv3_driver_data->gicd_base;
+
+	num_ints = gicd_read_typer(gicd_base);
+	num_ints &= TYPER_IT_LINES_NO_MASK;
+	num_ints = (num_ints + 1) << 5;
+
+	assert(num_ints <= MAX_SPI_ID + 1);
+
+	/* Wait for pending write to complete */
+	gicd_wait_for_pending_write(gicd_base);
+
+	/* Save the GICD_CTLR */
+	dist_ctx->gicd_ctlr = gicd_read_ctlr(gicd_base);
+
+	/* Save GICD_IGROUPR for INTIDs 32 - 1020 */
+	SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, igroupr, IGROUPR);
+
+	/* Save GICD_ISENABLER for INT_IDs 32 - 1020 */
+	SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, isenabler, ISENABLER);
+
+	/* Save GICD_ISPENDR for INTIDs 32 - 1020 */
+	SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, ispendr, ISPENDR);
+
+	/* Save GICD_ISACTIVER for INTIDs 32 - 1020 */
+	SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, isactiver, ISACTIVER);
+
+	/* Save GICD_IPRIORITYR for INTIDs 32 - 1020 */
+	SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, ipriorityr, IPRIORITYR);
+
+	/* Save GICD_ICFGR for INTIDs 32 - 1020 */
+	SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, icfgr, ICFGR);
+
+	/* Save GICD_IGRPMODR for INTIDs 32 - 1020 */
+	SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, igrpmodr, IGRPMODR);
+
+	/* Save GICD_NSACR for INTIDs 32 - 1020 */
+	SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, nsacr, NSACR);
+
+	/* Save GICD_IROUTER for INTIDs 32 - 1024 */
+	SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, irouter, IROUTER);
+
+	/*
+	 * GICD_ITARGETSR<n> and GICD_SPENDSGIR<n> are RAZ/WI when
+	 * GICD_CTLR.ARE_(S|NS) bits are set which is the case for our GICv3
+	 * driver.
+	 */
+}
+
+/*****************************************************************************
+ * Function to restore the GIC Distributor register context. We disable G0, G1S
+ * and G1NS interrupt groups before we start restore of the Distributor. This
+ * function must be invoked prior to Redistributor restore and CPU interface
+ * enable. The pending and active interrupts are restored after the interrupts
+ * are fully configured and enabled.
+ *****************************************************************************/
+void gicv3_distif_init_restore(const gicv3_dist_ctx_t * const dist_ctx)
+{
+	unsigned int num_ints = 0;
+
+	assert(gicv3_driver_data);
+	assert(gicv3_driver_data->gicd_base);
+	assert(IS_IN_EL3());
+	assert(dist_ctx);
+
+	uintptr_t gicd_base = gicv3_driver_data->gicd_base;
+
+	/*
+	 * Clear the "enable" bits for G0/G1S/G1NS interrupts before configuring
+	 * the ARE_S bit. The Distributor might generate a system error
+	 * otherwise.
+	 */
+	gicd_clr_ctlr(gicd_base,
+		      CTLR_ENABLE_G0_BIT |
+		      CTLR_ENABLE_G1S_BIT |
+		      CTLR_ENABLE_G1NS_BIT,
+		      RWP_TRUE);
+
+	/* Set the ARE_S and ARE_NS bit now that interrupts have been disabled */
+	gicd_set_ctlr(gicd_base, CTLR_ARE_S_BIT | CTLR_ARE_NS_BIT, RWP_TRUE);
+
+	num_ints = gicd_read_typer(gicd_base);
+	num_ints &= TYPER_IT_LINES_NO_MASK;
+	num_ints = (num_ints + 1) << 5;
+
+	assert(num_ints <= MAX_SPI_ID + 1);
+
+	/* Restore GICD_IGROUPR for INTIDs 32 - 1020 */
+	RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, igroupr, IGROUPR);
+
+	/* Restore GICD_IPRIORITYR for INTIDs 32 - 1020 */
+	RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, ipriorityr, IPRIORITYR);
+
+	/* Restore GICD_ICFGR for INTIDs 32 - 1020 */
+	RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, icfgr, ICFGR);
+
+	/* Restore GICD_IGRPMODR for INTIDs 32 - 1020 */
+	RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, igrpmodr, IGRPMODR);
+
+	/* Restore GICD_NSACR for INTIDs 32 - 1020 */
+	RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, nsacr, NSACR);
+
+	/* Restore GICD_IROUTER for INTIDs 32 - 1020 */
+	RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, irouter, IROUTER);
+
+	/*
+	 * Restore ISENABLER, ISPENDR and ISACTIVER after the interrupts are
+	 * configured.
+	 */
+
+	/* Restore GICD_ISENABLER for INT_IDs 32 - 1020 */
+	RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, isenabler, ISENABLER);
+
+	/* Restore GICD_ISPENDR for INTIDs 32 - 1020 */
+	RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, ispendr, ISPENDR);
+
+	/* Restore GICD_ISACTIVER for INTIDs 32 - 1020 */
+	RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, isactiver, ISACTIVER);
+
+	/* Restore the GICD_CTLR */
+	gicd_write_ctlr(gicd_base, dist_ctx->gicd_ctlr);
+	gicd_wait_for_pending_write(gicd_base);
+
+}
diff --git a/drivers/arm/gic/v3/gicv3_private.h b/drivers/arm/gic/v3/gicv3_private.h
index f95cfab..59298ed 100644
--- a/drivers/arm/gic/v3/gicv3_private.h
+++ b/drivers/arm/gic/v3/gicv3_private.h
@@ -7,6 +7,7 @@
 #ifndef __GICV3_PRIVATE_H__
 #define __GICV3_PRIVATE_H__
 
+#include <assert.h>
 #include <gic_common.h>
 #include <gicv3.h>
 #include <mmio.h>
@@ -22,17 +23,6 @@
 #define RWP_FALSE		0
 
 /*
- * Macro to wait for updates to :
- * GICD_CTLR[2:0] - the Group Enables
- * GICD_CTLR[5:4] - the ARE bits
- * GICD_ICENABLERn - the clearing of enable state for SPIs
- */
-#define gicd_wait_for_pending_write(gicd_base)			\
-	do {							\
-		;						\
-	} while (gicd_read_ctlr(gicd_base) & GICD_CTLR_RWP_BIT)
-
-/*
  * Macro to convert an mpidr to a value suitable for programming into a
  * GICD_IROUTER. Bits[31:24] in the MPIDR are cleared as they are not relevant
  * to GICv3.
@@ -42,18 +32,6 @@
 	 (irm & IROUTER_IRM_MASK) << IROUTER_IRM_SHIFT)
 
 /*
- * Macro to wait for updates to :
- * GICR_ICENABLER0
- * GICR_CTLR.DPG1S
- * GICR_CTLR.DPG1NS
- * GICR_CTLR.DPG0
- */
-#define gicr_wait_for_pending_write(gicr_base)			\
-	do {							\
-		;						\
-	} while (gicr_read_ctlr(gicr_base) & GICR_CTLR_RWP_BIT)
-
-/*
  * Macro to convert a GICR_TYPER affinity value into a MPIDR value. Bits[31:24]
  * are zeroes.
  */
@@ -66,6 +44,11 @@
 #endif
 
 /*******************************************************************************
+ * GICv3 private global variables declarations
+ ******************************************************************************/
+extern const gicv3_driver_data_t *gicv3_driver_data;
+
+/*******************************************************************************
  * Private GICv3 function prototypes for accessing entire registers.
  * Note: The raw register values correspond to multiple interrupt IDs and
  * the number of interrupt IDs involved depends on the register accessed.
@@ -116,6 +99,18 @@
 /*******************************************************************************
  * GIC Distributor interface accessors
  ******************************************************************************/
+/*
+ * Wait for updates to :
+ * GICD_CTLR[2:0] - the Group Enables
+ * GICD_CTLR[5:4] - the ARE bits
+ * GICD_ICENABLERn - the clearing of enable state for SPIs
+ */
+static inline void gicd_wait_for_pending_write(uintptr_t gicd_base)
+{
+	while (gicd_read_ctlr(gicd_base) & GICD_CTLR_RWP_BIT)
+		;
+}
+
 static inline unsigned int gicd_read_pidr2(uintptr_t base)
 {
 	return mmio_read_32(base + GICD_PIDR2_GICV3);
@@ -161,6 +156,11 @@
 	return mmio_read_64(base + GICR_CTLR);
 }
 
+static inline void gicr_write_ctlr(uintptr_t base, uint64_t val)
+{
+	mmio_write_64(base + GICR_CTLR, val);
+}
+
 static inline unsigned long long gicr_read_typer(uintptr_t base)
 {
 	return mmio_read_64(base + GICR_TYPER);
@@ -176,6 +176,29 @@
 	mmio_write_32(base + GICR_WAKER, val);
 }
 
+/*
+ * Wait for updates to :
+ * GICR_ICENABLER0
+ * GICR_CTLR.DPG1S
+ * GICR_CTLR.DPG1NS
+ * GICR_CTLR.DPG0
+ */
+static inline void gicr_wait_for_pending_write(uintptr_t gicr_base)
+{
+	while (gicr_read_ctlr(gicr_base) & GICR_CTLR_RWP_BIT)
+		;
+}
+
+static inline void gicr_wait_for_upstream_pending_write(uintptr_t gicr_base)
+{
+	while (gicr_read_ctlr(gicr_base) & GICR_CTLR_UWP_BIT)
+		;
+}
+
+/* Private implementation of Distributor power control hooks */
+void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num);
+void arm_gicv3_distif_post_restore(unsigned int rdist_proc_num);
+
 /*******************************************************************************
  * GIC Re-distributor functions for accessing entire registers.
  * Note: The raw register values correspond to multiple interrupt IDs and
@@ -206,6 +229,16 @@
 	return mmio_read_32(base + GICR_IGROUPR0);
 }
 
+static inline unsigned int gicr_read_ispendr0(uintptr_t base)
+{
+	return mmio_read_32(base + GICR_ISPENDR0);
+}
+
+static inline void gicr_write_ispendr0(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICR_ISPENDR0, val);
+}
+
 static inline void gicr_write_igroupr0(uintptr_t base, unsigned int val)
 {
 	mmio_write_32(base + GICR_IGROUPR0, val);
@@ -221,14 +254,120 @@
 	mmio_write_32(base + GICR_IGRPMODR0, val);
 }
 
+static inline unsigned int gicr_read_nsacr(uintptr_t base)
+{
+	return mmio_read_32(base + GICR_NSACR);
+}
+
+static inline void gicr_write_nsacr(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICR_NSACR, val);
+}
+
+static inline unsigned int gicr_read_isactiver0(uintptr_t base)
+{
+	return mmio_read_32(base + GICR_ISACTIVER0);
+}
+
+static inline void gicr_write_isactiver0(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICR_ISACTIVER0, val);
+}
+
+static inline unsigned int gicr_read_icfgr0(uintptr_t base)
+{
+	return mmio_read_32(base + GICR_ICFGR0);
+}
+
 static inline unsigned int gicr_read_icfgr1(uintptr_t base)
 {
 	return mmio_read_32(base + GICR_ICFGR1);
 }
 
+static inline void gicr_write_icfgr0(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICR_ICFGR0, val);
+}
+
 static inline void gicr_write_icfgr1(uintptr_t base, unsigned int val)
 {
 	mmio_write_32(base + GICR_ICFGR1, val);
 }
 
+static inline unsigned int gicr_read_propbaser(uintptr_t base)
+{
+	return mmio_read_32(base + GICR_PROPBASER);
+}
+
+static inline void gicr_write_propbaser(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICR_PROPBASER, val);
+}
+
+static inline unsigned int gicr_read_pendbaser(uintptr_t base)
+{
+	return mmio_read_32(base + GICR_PENDBASER);
+}
+
+static inline void gicr_write_pendbaser(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICR_PENDBASER, val);
+}
+
+/*******************************************************************************
+ * GIC ITS functions to read and write entire ITS registers.
+ ******************************************************************************/
+static inline uint32_t gits_read_ctlr(uintptr_t base)
+{
+	return mmio_read_32(base + GITS_CTLR);
+}
+
+static inline void gits_write_ctlr(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GITS_CTLR, val);
+}
+
+static inline uint64_t gits_read_cbaser(uintptr_t base)
+{
+	return mmio_read_64(base + GITS_CBASER);
+}
+
+static inline void gits_write_cbaser(uintptr_t base, uint64_t val)
+{
+	mmio_write_32(base + GITS_CBASER, val);
+}
+
+static inline uint64_t gits_read_cwriter(uintptr_t base)
+{
+	return mmio_read_64(base + GITS_CWRITER);
+}
+
+static inline void gits_write_cwriter(uintptr_t base, uint64_t val)
+{
+	mmio_write_32(base + GITS_CWRITER, val);
+}
+
+static inline uint64_t gits_read_baser(uintptr_t base, unsigned int its_table_id)
+{
+	assert(its_table_id < 8);
+	return mmio_read_64(base + GITS_BASER + (8 * its_table_id));
+}
+
+static inline void gits_write_baser(uintptr_t base, unsigned int its_table_id, uint64_t val)
+{
+	assert(its_table_id < 8);
+	mmio_write_64(base + GITS_BASER + (8 * its_table_id), val);
+}
+
+/*
+ * Wait for Quiescent bit when GIC ITS is disabled
+ */
+static inline void gits_wait_for_quiescent_bit(uintptr_t gits_base)
+{
+	assert(!(gits_read_ctlr(gits_base) & GITS_CTLR_ENABLED_BIT));
+	while ((gits_read_ctlr(gits_base) & GITS_CTLR_QUIESCENT_BIT) == 0)
+		;
+}
+
+
 #endif /* __GICV3_PRIVATE_H__ */
diff --git a/drivers/auth/mbedtls/mbedtls_common.c b/drivers/auth/mbedtls/mbedtls_common.c
index e9aa409..205c243 100644
--- a/drivers/auth/mbedtls/mbedtls_common.c
+++ b/drivers/auth/mbedtls/mbedtls_common.c
@@ -14,8 +14,9 @@
 /*
  * mbed TLS heap
  */
-#if (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA)
-#define MBEDTLS_HEAP_SIZE		(14*1024)
+#if (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA) \
+	|| (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA)
+#define MBEDTLS_HEAP_SIZE		(13*1024)
 #elif (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA)
 #define MBEDTLS_HEAP_SIZE		(7*1024)
 #endif
diff --git a/drivers/auth/mbedtls/mbedtls_crypto.mk b/drivers/auth/mbedtls/mbedtls_crypto.mk
index 21b857b..d6fc7eb 100644
--- a/drivers/auth/mbedtls/mbedtls_crypto.mk
+++ b/drivers/auth/mbedtls/mbedtls_crypto.mk
@@ -41,18 +41,26 @@
 					)
 
 # Key algorithm specific files
+MBEDTLS_ECDSA_CRYPTO_SOURCES	+=	$(addprefix ${MBEDTLS_DIR}/library/,	\
+					ecdsa.c					\
+					ecp_curves.c				\
+					ecp.c					\
+					)
+
+MBEDTLS_RSA_CRYPTO_SOURCES	+=	$(addprefix ${MBEDTLS_DIR}/library/,	\
+					rsa.c					\
+					)
+
 ifeq (${TF_MBEDTLS_KEY_ALG},ecdsa)
-    MBEDTLS_CRYPTO_SOURCES	+=	$(addprefix ${MBEDTLS_DIR}/library/,	\
-    					ecdsa.c					\
-    					ecp_curves.c				\
-    					ecp.c					\
-    					)
+    MBEDTLS_CRYPTO_SOURCES	+=	$(MBEDTLS_ECDSA_CRYPTO_SOURCES)
     TF_MBEDTLS_KEY_ALG_ID	:=	TF_MBEDTLS_ECDSA
 else ifeq (${TF_MBEDTLS_KEY_ALG},rsa)
-    MBEDTLS_CRYPTO_SOURCES	+=	$(addprefix ${MBEDTLS_DIR}/library/,	\
-    					rsa.c					\
-    					)
+    MBEDTLS_CRYPTO_SOURCES	+=	$(MBEDTLS_RSA_CRYPTO_SOURCES)
     TF_MBEDTLS_KEY_ALG_ID	:=	TF_MBEDTLS_RSA
+else ifeq (${TF_MBEDTLS_KEY_ALG},rsa+ecdsa)
+    MBEDTLS_CRYPTO_SOURCES	+=	$(MBEDTLS_ECDSA_CRYPTO_SOURCES)
+    MBEDTLS_CRYPTO_SOURCES	+=	$(MBEDTLS_RSA_CRYPTO_SOURCES)
+    TF_MBEDTLS_KEY_ALG_ID	:=	TF_MBEDTLS_RSA_AND_ECDSA
 else
     $(error "TF_MBEDTLS_KEY_ALG=${TF_MBEDTLS_KEY_ALG} not supported on mbed TLS")
 endif
diff --git a/include/common/debug.h b/include/common/debug.h
index 814cf84..3f0f84a 100644
--- a/include/common/debug.h
+++ b/include/common/debug.h
@@ -24,47 +24,62 @@
 #define LOG_LEVEL_VERBOSE		50
 
 #ifndef __ASSEMBLY__
+#include <stdarg.h>
 #include <stdio.h>
 
+/*
+ * Define Log Markers corresponding to each log level which will
+ * be embedded in the format string and is expected by tf_log() to determine
+ * the log level.
+ */
+#define LOG_MARKER_ERROR		"\xa"	/* 10 */
+#define LOG_MARKER_NOTICE		"\x14"	/* 20 */
+#define LOG_MARKER_WARNING		"\x1e"	/* 30 */
+#define LOG_MARKER_INFO			"\x28"	/* 40 */
+#define LOG_MARKER_VERBOSE		"\x32"	/* 50 */
+
 #if LOG_LEVEL >= LOG_LEVEL_NOTICE
-# define NOTICE(...)	tf_printf("NOTICE:  " __VA_ARGS__)
+# define NOTICE(...)	tf_log(LOG_MARKER_NOTICE __VA_ARGS__)
 #else
 # define NOTICE(...)
 #endif
 
 #if LOG_LEVEL >= LOG_LEVEL_ERROR
-# define ERROR(...)	tf_printf("ERROR:   " __VA_ARGS__)
+# define ERROR(...)	tf_log(LOG_MARKER_ERROR __VA_ARGS__)
 #else
 # define ERROR(...)
 #endif
 
 #if LOG_LEVEL >= LOG_LEVEL_WARNING
-# define WARN(...)	tf_printf("WARNING: " __VA_ARGS__)
+# define WARN(...)	tf_log(LOG_MARKER_WARNING __VA_ARGS__)
 #else
 # define WARN(...)
 #endif
 
 #if LOG_LEVEL >= LOG_LEVEL_INFO
-# define INFO(...)	tf_printf("INFO:    " __VA_ARGS__)
+# define INFO(...)	tf_log(LOG_MARKER_INFO __VA_ARGS__)
 #else
 # define INFO(...)
 #endif
 
 #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
-# define VERBOSE(...)	tf_printf("VERBOSE: " __VA_ARGS__)
+# define VERBOSE(...)	tf_log(LOG_MARKER_VERBOSE __VA_ARGS__)
 #else
 # define VERBOSE(...)
 #endif
 
-
 void __dead2 do_panic(void);
 #define panic()	do_panic()
 
 /* Function called when stack protection check code detects a corrupted stack */
 void __dead2 __stack_chk_fail(void);
 
+void tf_log(const char *fmt, ...) __printflike(1, 2);
 void tf_printf(const char *fmt, ...) __printflike(1, 2);
 int tf_snprintf(char *s, size_t n, const char *fmt, ...) __printflike(3, 4);
+void tf_vprintf(const char *fmt, va_list args);
+void tf_string_print(const char *str);
+void tf_log_set_max_level(unsigned int log_level);
 
 #endif /* __ASSEMBLY__ */
 #endif /* __DEBUG_H__ */
diff --git a/include/drivers/arm/arm_gicv3_common.h b/include/drivers/arm/arm_gicv3_common.h
new file mode 100644
index 0000000..8970e3f
--- /dev/null
+++ b/include/drivers/arm/arm_gicv3_common.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef __ARM_GICV3_COMMON_H__
+#define __ARM_GICV3_COMMON_H__
+
+/*******************************************************************************
+ * GIC500/GIC600 Re-distributor interface registers & constants
+ ******************************************************************************/
+
+/* GICR_WAKER implementation-defined bit definitions */
+#define	WAKER_SL_SHIFT		0
+#define	WAKER_QSC_SHIFT		31
+
+#define WAKER_SL_BIT		(1U << WAKER_SL_SHIFT)
+#define WAKER_QSC_BIT		(1U << WAKER_QSC_SHIFT)
+
+#endif /* __ARM_GICV3_COMMON_H__ */
diff --git a/include/drivers/arm/gic_common.h b/include/drivers/arm/gic_common.h
index 7e097ad..b9cae80 100644
--- a/include/drivers/arm/gic_common.h
+++ b/include/drivers/arm/gic_common.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,6 +14,10 @@
 #define MIN_SGI_ID		0
 #define MIN_PPI_ID		16
 #define MIN_SPI_ID		32
+#define MAX_SPI_ID		1019
+
+#define TOTAL_SPI_INTR_NUM	(MAX_SPI_ID - MIN_SPI_ID + 1)
+#define TOTAL_PCPU_INTR_NUM	(MIN_SPI_ID - MIN_SGI_ID)
 
 /* Mask for the priority field common to all GIC interfaces */
 #define GIC_PRI_MASK			0xff
diff --git a/include/drivers/arm/gic_v3.h b/include/drivers/arm/gic_v3.h
index ee8f26b..02f9006 100644
--- a/include/drivers/arm/gic_v3.h
+++ b/include/drivers/arm/gic_v3.h
@@ -26,17 +26,17 @@
 #define GICR_WAKER		0x14
 
 /* GICR_WAKER bit definitions */
-#define WAKER_CA		(1UL << 2)
-#define WAKER_PS		(1UL << 1)
+#define WAKER_CA		(U(1) << 2)
+#define WAKER_PS		(U(1) << 1)
 
 /* GICR_TYPER bit definitions */
 #define GICR_TYPER_AFF_SHIFT	32
 #define GICR_TYPER_AFF_MASK	0xffffffff
-#define GICR_TYPER_LAST		(1UL << 4)
+#define GICR_TYPER_LAST		(U(1) << 4)
 
 /* GICv3 ICC_SRE register bit definitions*/
-#define ICC_SRE_EN		(1UL << 3)
-#define ICC_SRE_SRE		(1UL << 0)
+#define ICC_SRE_EN		(U(1) << 3)
+#define ICC_SRE_SRE		(U(1) << 0)
 
 /*******************************************************************************
  * GICv3 defintions
diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h
index 8d9981a..c52fe48 100644
--- a/include/drivers/arm/gicv3.h
+++ b/include/drivers/arm/gicv3.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016, 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,6 +7,8 @@
 #ifndef __GICV3_H__
 #define __GICV3_H__
 
+#include "utils_def.h"
+
 /*******************************************************************************
  * GICv3 miscellaneous definitions
  ******************************************************************************/
@@ -66,9 +68,12 @@
 #define GICD_CTLR_RWP_BIT		(1 << GICD_CTLR_RWP_SHIFT)
 
 /* GICD_IROUTER shifts and masks */
+#define IROUTER_SHIFT		0
 #define IROUTER_IRM_SHIFT	31
 #define IROUTER_IRM_MASK	0x1
 
+#define NUM_OF_DIST_REGS	30
+
 /*******************************************************************************
  * GICv3 Re-distributor interface registers & constants
  ******************************************************************************/
@@ -77,18 +82,29 @@
 #define GICR_CTLR		0x0
 #define GICR_TYPER		0x08
 #define GICR_WAKER		0x14
+#define GICR_PROPBASER		0x70
+#define GICR_PENDBASER		0x78
 #define GICR_IGROUPR0		(GICR_SGIBASE_OFFSET + 0x80)
 #define GICR_ISENABLER0		(GICR_SGIBASE_OFFSET + 0x100)
 #define GICR_ICENABLER0		(GICR_SGIBASE_OFFSET + 0x180)
+#define GICR_ISPENDR0		(GICR_SGIBASE_OFFSET + 0x200)
+#define GICR_ICPENDR0		(GICR_SGIBASE_OFFSET + 0x280)
+#define GICR_ISACTIVER0		(GICR_SGIBASE_OFFSET + 0x300)
+#define GICR_ICACTIVER0		(GICR_SGIBASE_OFFSET + 0x380)
 #define GICR_IPRIORITYR		(GICR_SGIBASE_OFFSET + 0x400)
 #define GICR_ICFGR0		(GICR_SGIBASE_OFFSET + 0xc00)
 #define GICR_ICFGR1		(GICR_SGIBASE_OFFSET + 0xc04)
 #define GICR_IGRPMODR0		(GICR_SGIBASE_OFFSET + 0xd00)
+#define GICR_NSACR		(GICR_SGIBASE_OFFSET + 0xe00)
 
 /* GICR_CTLR bit definitions */
+#define GICR_CTLR_UWP_SHIFT	31
+#define GICR_CTLR_UWP_MASK	0x1
+#define GICR_CTLR_UWP_BIT	(1U << GICR_CTLR_UWP_SHIFT)
 #define GICR_CTLR_RWP_SHIFT	3
 #define GICR_CTLR_RWP_MASK	0x1
-#define GICR_CTLR_RWP_BIT	(1 << GICR_CTLR_RWP_SHIFT)
+#define GICR_CTLR_RWP_BIT	(1U << GICR_CTLR_RWP_SHIFT)
+#define GICR_CTLR_EN_LPIS_BIT	(1U << 0)
 
 /* GICR_WAKER bit definitions */
 #define WAKER_CA_SHIFT		2
@@ -111,6 +127,8 @@
 
 #define TYPER_LAST_BIT		(1 << TYPER_LAST_SHIFT)
 
+#define NUM_OF_REDIST_REGS	30
+
 /*******************************************************************************
  * GICv3 CPU interface registers & constants
  ******************************************************************************/
@@ -147,10 +165,29 @@
 #define IAR1_EL1_INTID_SHIFT		0
 #define IAR1_EL1_INTID_MASK		0xffffff
 
+/*****************************************************************************
+ * GICv3 ITS registers and constants
+ *****************************************************************************/
+
+#define GITS_CTLR			0x0
+#define GITS_IIDR			0x4
+#define GITS_TYPER			0x8
+#define GITS_CBASER			0x80
+#define GITS_CWRITER			0x88
+#define GITS_CREADR			0x90
+#define GITS_BASER			0x100
+
+/* GITS_CTLR bit definitions */
+#define GITS_CTLR_ENABLED_BIT		1
+#define GITS_CTLR_QUIESCENT_SHIFT	31
+#define GITS_CTLR_QUIESCENT_BIT		(1U << GITS_CTLR_QUIESCENT_SHIFT)
+
 #ifndef __ASSEMBLY__
 
+#include <gic_common.h>
 #include <stdint.h>
 #include <types.h>
+#include <utils_def.h>
 
 #define gicv3_is_intr_id_special_identifier(id)	\
 	(((id) >= PENDING_G1S_INTID) && ((id) <= GIC_SPURIOUS_INTERRUPT))
@@ -172,6 +209,16 @@
 							IAR0_EL1_INTID_MASK
 #define gicv3_end_of_interrupt(id)		write_icc_eoir0_el1(id)
 
+/*
+ * This macro returns the total number of GICD registers corresponding to
+ * the name.
+ */
+#define GICD_NUM_REGS(reg_name)	\
+	DIV_ROUND_UP_2EVAL(TOTAL_SPI_INTR_NUM, (1 << reg_name ## _SHIFT))
+
+#define GICR_NUM_REGS(reg_name)	\
+	DIV_ROUND_UP_2EVAL(TOTAL_PCPU_INTR_NUM, (1 << reg_name ## _SHIFT))
+
 /*******************************************************************************
  * This structure describes some of the implementation defined attributes of the
  * GICv3 IP. It is used by the platform port to specify these attributes in order
@@ -229,6 +276,50 @@
 	mpidr_hash_fn mpidr_to_core_pos;
 } gicv3_driver_data_t;
 
+typedef struct gicv3_redist_ctx {
+	/* 64 bits registers */
+	uint64_t gicr_propbaser;
+	uint64_t gicr_pendbaser;
+
+	/* 32 bits registers */
+	uint32_t gicr_ctlr;
+	uint32_t gicr_igroupr0;
+	uint32_t gicr_isenabler0;
+	uint32_t gicr_ispendr0;
+	uint32_t gicr_isactiver0;
+	uint32_t gicr_ipriorityr[GICR_NUM_REGS(IPRIORITYR)];
+	uint32_t gicr_icfgr0;
+	uint32_t gicr_icfgr1;
+	uint32_t gicr_igrpmodr0;
+	uint32_t gicr_nsacr;
+} gicv3_redist_ctx_t;
+
+typedef struct gicv3_dist_ctx {
+	/* 64 bits registers */
+	uint64_t gicd_irouter[TOTAL_SPI_INTR_NUM];
+
+	/* 32 bits registers */
+	uint32_t gicd_ctlr;
+	uint32_t gicd_igroupr[GICD_NUM_REGS(IGROUPR)];
+	uint32_t gicd_isenabler[GICD_NUM_REGS(ISENABLER)];
+	uint32_t gicd_ispendr[GICD_NUM_REGS(ISPENDR)];
+	uint32_t gicd_isactiver[GICD_NUM_REGS(ISACTIVER)];
+	uint32_t gicd_ipriorityr[GICD_NUM_REGS(IPRIORITYR)];
+	uint32_t gicd_icfgr[GICD_NUM_REGS(ICFGR)];
+	uint32_t gicd_igrpmodr[GICD_NUM_REGS(IGRPMODR)];
+	uint32_t gicd_nsacr[GICD_NUM_REGS(NSACR)];
+} gicv3_dist_ctx_t;
+
+typedef struct gicv3_its_ctx {
+	/* 64 bits registers */
+	uint64_t gits_cbaser;
+	uint64_t gits_cwriter;
+	uint64_t gits_baser[8];
+
+	/* 32 bits registers */
+	uint32_t gits_ctlr;
+} gicv3_its_ctx_t;
+
 /*******************************************************************************
  * GICv3 EL3 driver API
  ******************************************************************************/
@@ -243,7 +334,20 @@
 unsigned int gicv3_get_pending_interrupt_id(void);
 unsigned int gicv3_get_interrupt_type(unsigned int id,
 					  unsigned int proc_num);
-
+void gicv3_distif_init_restore(const gicv3_dist_ctx_t * const dist_ctx);
+void gicv3_distif_save(gicv3_dist_ctx_t * const dist_ctx);
+/*
+ * gicv3_distif_post_restore and gicv3_distif_pre_save must be implemented if
+ * gicv3_distif_save and gicv3_rdistif_init_restore are used. If no
+ * implementation-defined sequence is needed at these steps, an empty function
+ * can be provided.
+ */
+void gicv3_distif_post_restore(unsigned int proc_num);
+void gicv3_distif_pre_save(unsigned int proc_num);
+void gicv3_rdistif_init_restore(unsigned int proc_num, const gicv3_redist_ctx_t * const rdist_ctx);
+void gicv3_rdistif_save(unsigned int proc_num, gicv3_redist_ctx_t * const rdist_ctx);
+void gicv3_its_save_disable(uintptr_t gits_base, gicv3_its_ctx_t * const its_ctx);
+void gicv3_its_restore(uintptr_t gits_base, const gicv3_its_ctx_t * const its_ctx);
 
 #endif /* __ASSEMBLY__ */
 #endif /* __GICV3_H__ */
diff --git a/include/drivers/auth/mbedtls/mbedtls_config.h b/include/drivers/auth/mbedtls/mbedtls_config.h
index fdeb52b..ca2d9fa 100644
--- a/include/drivers/auth/mbedtls/mbedtls_config.h
+++ b/include/drivers/auth/mbedtls/mbedtls_config.h
@@ -9,8 +9,9 @@
 /*
  * Key algorithms currently supported on mbed TLS libraries
  */
-#define TF_MBEDTLS_RSA		1
-#define TF_MBEDTLS_ECDSA	2
+#define TF_MBEDTLS_RSA			1
+#define TF_MBEDTLS_ECDSA		2
+#define TF_MBEDTLS_RSA_AND_ECDSA	3
 
 /*
  * Configuration file to build mbed TLS with the required features for
@@ -30,7 +31,6 @@
 #define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
 #define MBEDTLS_X509_CHECK_KEY_USAGE
 #define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
-#define MBEDTLS_X509_RSASSA_PSS_SUPPORT
 
 #define MBEDTLS_ASN1_PARSE_C
 #define MBEDTLS_ASN1_WRITE_C
@@ -56,6 +56,13 @@
 #define MBEDTLS_ECP_DP_SECP256R1_ENABLED
 #elif (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA)
 #define MBEDTLS_RSA_C
+#define MBEDTLS_X509_RSASSA_PSS_SUPPORT
+#elif (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA)
+#define MBEDTLS_RSA_C
+#define MBEDTLS_X509_RSASSA_PSS_SUPPORT
+#define MBEDTLS_ECDSA_C
+#define MBEDTLS_ECP_C
+#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
 #endif
 
 #define MBEDTLS_SHA256_C
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index e38a530..f85e789 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -312,7 +312,7 @@
 /*
  * TCR defintions
  */
-#define TCR_EL3_RES1		((1UL << 31) | (1UL << 23))
+#define TCR_EL3_RES1		((U(1) << 31) | (U(1) << 23))
 #define TCR_EL1_IPS_SHIFT	U(32)
 #define TCR_EL3_PS_SHIFT	U(16)
 
@@ -348,6 +348,8 @@
 #define TCR_SH_OUTER_SHAREABLE	(U(0x2) << 12)
 #define TCR_SH_INNER_SHAREABLE	(U(0x3) << 12)
 
+#define TCR_EPD1_BIT		(U(1) << 23)
+
 #define MODE_SP_SHIFT		U(0x0)
 #define MODE_SP_MASK		U(0x1)
 #define MODE_SP_EL0		U(0x0)
diff --git a/include/lib/psci/psci.h b/include/lib/psci/psci.h
index 0ed39c9..0b44ab2 100644
--- a/include/lib/psci/psci.h
+++ b/include/lib/psci/psci.h
@@ -65,6 +65,9 @@
 #define PSCI_STAT_RESIDENCY_AARCH64	U(0xc4000010)
 #define PSCI_STAT_COUNT_AARCH32		U(0x84000011)
 #define PSCI_STAT_COUNT_AARCH64		U(0xc4000011)
+#define PSCI_MEM_PROTECT		U(0x84000013)
+#define PSCI_MEM_CHK_RANGE_AARCH32	U(0x84000014)
+#define PSCI_MEM_CHK_RANGE_AARCH64	U(0xc4000014)
 
 /* Macro to help build the psci capabilities bitfield */
 #define define_psci_cap(x)		(U(1) << (x & U(0x1f)))
@@ -288,6 +291,9 @@
 				    unsigned int power_state,
 				    psci_power_state_t *output_state);
 	int (*get_node_hw_state)(u_register_t mpidr, unsigned int power_level);
+	int (*mem_protect_chk)(uintptr_t base, u_register_t length);
+	int (*read_mem_protect)(int *val);
+	int (*write_mem_protect)(int val);
 } plat_psci_ops_t;
 
 /*******************************************************************************
diff --git a/include/lib/utils.h b/include/lib/utils.h
index b75813f..cfc8302 100644
--- a/include/lib/utils.h
+++ b/include/lib/utils.h
@@ -19,6 +19,25 @@
 
 #include <types.h>
 
+typedef struct mem_region_t {
+	uintptr_t base;
+	size_t nbytes;
+} mem_region_t;
+
+/*
+ * zero_normalmem all the regions defined in tbl.
+ */
+void clear_mem_regions(mem_region_t *tbl, size_t nregions);
+
+
+/*
+ * checks that a region (addr + nbytes-1) of memory is totally covered by
+ * one of the regions defined in tbl. Caller must ensure that (addr+nbytes-1)
+ * doesn't overflow.
+ */
+int mem_region_in_array_chk(mem_region_t *tbl, size_t nregions,
+			    uintptr_t addr, size_t nbytes);
+
 /*
  * Fill a region of normal memory of size "length" in bytes with zero bytes.
  *
diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h
index 26ac440..185a1c1 100644
--- a/include/lib/utils_def.h
+++ b/include/lib/utils_def.h
@@ -16,7 +16,13 @@
 
 #define SIZE_FROM_LOG2_WORDS(n)		(4 << (n))
 
-#define BIT(nr)				(1UL << (nr))
+#define BIT(nr)				(1ULL << (nr))
+
+/*
+ * This variant of div_round_up can be used in macro definition but should not
+ * be used in C code as the `div` parameter is evaluated twice.
+ */
+#define DIV_ROUND_UP_2EVAL(n, d)	(((n) + (d) - 1) / (d))
 
 #define MIN(x, y) __extension__ ({	\
 	__typeof__(x) _x = (x);		\
@@ -49,6 +55,11 @@
 #define round_down(value, boundary)		\
 	((value) & ~round_boundary(value, boundary))
 
+#define div_round_up(val, div) __extension__ ({	\
+	__typeof__(div) _div = (div);		\
+	round_up((val), _div)/_div;		\
+})
+
 /*
  * Evaluates to 1 if (ptr + inc) overflows, 0 otherwise.
  * Both arguments must be unsigned pointer values (i.e. uintptr_t).
diff --git a/include/lib/xlat_tables/xlat_tables_defs.h b/include/lib/xlat_tables/xlat_tables_defs.h
index b0f5a04..7cb9d37 100644
--- a/include/lib/xlat_tables/xlat_tables_defs.h
+++ b/include/lib/xlat_tables/xlat_tables_defs.h
@@ -89,9 +89,22 @@
  * AP[1] bit is ignored by hardware and is
  * treated as if it is One in EL2/EL3
  */
-#define AP_RO				(U(0x1) << 5)
-#define AP_RW				(U(0x0) << 5)
+#define AP2_SHIFT			U(0x7)
+#define AP2_RO				U(0x1)
+#define AP2_RW				U(0x0)
+
+#define AP1_SHIFT			U(0x6)
+#define AP1_ACCESS_UNPRIVILEGED		U(0x1)
+#define AP1_NO_ACCESS_UNPRIVILEGED	U(0x0)
 
+/*
+ * The following definitions must all be passed to the LOWER_ATTRS() macro to
+ * get the right bitmask.
+ */
+#define AP_RO				(AP2_RO << 5)
+#define AP_RW				(AP2_RW << 5)
+#define AP_ACCESS_UNPRIVILEGED		(AP1_ACCESS_UNPRIVILEGED    << 4)
+#define AP_NO_ACCESS_UNPRIVILEGED	(AP1_NO_ACCESS_UNPRIVILEGED << 4)
 #define NS				(U(0x1) << 3)
 #define ATTR_NON_CACHEABLE_INDEX	U(0x2)
 #define ATTR_DEVICE_INDEX		U(0x1)
diff --git a/include/lib/xlat_tables/xlat_tables_v2.h b/include/lib/xlat_tables/xlat_tables_v2.h
index 288a8e0..1a55fba 100644
--- a/include/lib/xlat_tables/xlat_tables_v2.h
+++ b/include/lib/xlat_tables/xlat_tables_v2.h
@@ -15,15 +15,36 @@
 #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.
+/*
+ * Default granularity size for an mmap_region_t.
+ * Useful when no specific granularity is required.
+ *
+ * By default, choose the biggest possible block size allowed by the
+ * architectural state and granule size in order to minimize the number of page
+ * tables required for the mapping.
  */
-#define MAP_REGION_FLAT(adr, sz, attr) MAP_REGION(adr, adr, sz, attr)
+#define REGION_DEFAULT_GRANULARITY	XLAT_BLOCK_SIZE(MIN_LVL_BLOCK_DESC)
 
-/* Helper macro to define entries for mmap_region_t. It allows to
- * re-map address mappings from 'pa' to 'va' for each region.
+/* Helper macro to define an mmap_region_t. */
+#define MAP_REGION(_pa, _va, _sz, _attr)	\
+	_MAP_REGION_FULL_SPEC(_pa, _va, _sz, _attr, REGION_DEFAULT_GRANULARITY)
+
+/* Helper macro to define an mmap_region_t with an identity mapping. */
+#define MAP_REGION_FLAT(_adr, _sz, _attr)			\
+	MAP_REGION(_adr, _adr, _sz, _attr)
+
+/*
+ * Helper macro to define an mmap_region_t to map with the desired granularity
+ * of translation tables.
+ *
+ * The granularity value passed to this macro must be a valid block or page
+ * size. When using a 4KB translation granule, this might be 4KB, 2MB or 1GB.
+ * Passing REGION_DEFAULT_GRANULARITY is also allowed and means that the library
+ * is free to choose the granularity for this region. In this case, it is
+ * equivalent to the MAP_REGION() macro.
  */
-#define MAP_REGION(pa, va, sz, attr) {(pa), (va), (sz), (attr)}
+#define MAP_REGION2(_pa, _va, _sz, _attr, _gr)			\
+	_MAP_REGION_FULL_SPEC(_pa, _va, _sz, _attr, _gr)
 
 /*
  * Shifts and masks to access fields of an mmap_attr_t
@@ -36,6 +57,11 @@
 #define MT_SEC_SHIFT		U(4)
 /* Access permissions for instruction execution (EXECUTE/EXECUTE_NEVER) */
 #define MT_EXECUTE_SHIFT	U(5)
+/*
+ * In the EL1&0 translation regime, mark the region as User (EL0) or
+ * Privileged (EL1). In the EL3 translation regime this has no effect.
+ */
+#define MT_USER_SHIFT		U(6)
 /* All other bits are reserved */
 
 /*
@@ -68,10 +94,20 @@
 	 */
 	MT_EXECUTE		= U(0) << MT_EXECUTE_SHIFT,
 	MT_EXECUTE_NEVER	= U(1) << MT_EXECUTE_SHIFT,
+
+	/*
+	 * When mapping a region at EL0 or EL1, this attribute will be used to
+	 * determine if a User mapping (EL0) will be created or a Privileged
+	 * mapping (EL1).
+	 */
+	MT_USER				= U(1) << MT_USER_SHIFT,
+	MT_PRIVILEGED			= U(0) << MT_USER_SHIFT,
 } mmap_attr_t;
 
+/* Compound attributes for most common usages */
 #define MT_CODE		(MT_MEMORY | MT_RO | MT_EXECUTE)
 #define MT_RO_DATA	(MT_MEMORY | MT_RO | MT_EXECUTE_NEVER)
+#define MT_RW_DATA	(MT_MEMORY | MT_RW | MT_EXECUTE_NEVER)
 
 /*
  * Structure for specifying a single region of memory.
@@ -81,9 +117,19 @@
 	uintptr_t		base_va;
 	size_t			size;
 	mmap_attr_t		attr;
+	/* Desired granularity. See the MAP_REGION2() macro for more details. */
+	size_t			granularity;
 } mmap_region_t;
 
 /*
+ * Translation regimes supported by this library.
+ */
+typedef enum xlat_regime {
+	EL1_EL0_REGIME,
+	EL3_REGIME,
+} xlat_regime_t;
+
+/*
  * Declare the translation context type.
  * Its definition is private.
  */
@@ -118,8 +164,25 @@
  */
 #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)
+	_REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count,	\
+					 _xlat_tables_count,		\
+					 _virt_addr_space_size,		\
+					 _phy_addr_space_size,		\
+					 IMAGE_XLAT_DEFAULT_REGIME)
+
+/*
+ * Same as REGISTER_XLAT_CONTEXT plus the additional parameter _xlat_regime to
+ * specify the translation regime managed by this xlat_ctx_t instance. The
+ * values are the one from xlat_regime_t enumeration.
+ */
+#define REGISTER_XLAT_CONTEXT2(_ctx_name, _mmap_count, _xlat_tables_count,	\
+			_virt_addr_space_size, _phy_addr_space_size,		\
+			_xlat_regime)					\
+	_REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count,	\
+					 _xlat_tables_count,		\
+					 _virt_addr_space_size,		\
+					 _phy_addr_space_size,		\
+					 _xlat_regime)
 
 /******************************************************************************
  * Generic translation table APIs.
diff --git a/include/lib/xlat_tables/xlat_tables_v2_helpers.h b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
index f5e3100..0ebdc93 100644
--- a/include/lib/xlat_tables/xlat_tables_v2_helpers.h
+++ b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
@@ -27,6 +27,20 @@
 /* Forward declaration */
 struct mmap_region;
 
+/*
+ * Helper macro to define an mmap_region_t.  This macro allows to specify all
+ * the fields of the structure but its parameter list is not guaranteed to
+ * remain stable as we add members to mmap_region_t.
+ */
+#define _MAP_REGION_FULL_SPEC(_pa, _va, _sz, _attr, _gr)	\
+	{							\
+		.base_pa = (_pa),				\
+		.base_va = (_va),				\
+		.size = (_sz),					\
+		.attr = (_attr),				\
+		.granularity = (_gr),				\
+	}
+
 /* Struct that holds all information about the translation tables. */
 struct xlat_ctx {
 	/*
@@ -85,11 +99,12 @@
 	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.
+	 * Translation regime managed by this xlat_ctx_t. It takes the values of
+	 * the enumeration xlat_regime_t. The type is "int" to avoid a circular
+	 * dependency on xlat_tables_v2.h, but this member must be treated as
+	 * xlat_regime_t.
 	 */
-	uint64_t execute_never_mask;
+	int xlat_regime;
 };
 
 #if PLAT_XLAT_TABLES_DYNAMIC
@@ -106,9 +121,9 @@
 	/* 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)		\
+#define _REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count, _xlat_tables_count,	\
+			_virt_addr_space_size, _phy_addr_space_size,		\
+			_xlat_regime)					\
 	CASSERT(CHECK_VIRT_ADDR_SPACE_SIZE(_virt_addr_space_size),		\
 		assert_invalid_virtual_addr_space_size_for_##_ctx_name);	\
 										\
@@ -140,12 +155,23 @@
 		.tables = _ctx_name##_xlat_tables,				\
 		.tables_num = _xlat_tables_count,				\
 		 _REGISTER_DYNMAP_STRUCT(_ctx_name)				\
+		.xlat_regime = (_xlat_regime),					\
 		.max_pa = 0,							\
 		.max_va = 0,							\
 		.next_table = 0,						\
 		.initialized = 0,						\
 	}
 
+
+/* This IMAGE_EL macro must not to be used outside the library */
+#if IMAGE_BL1 || IMAGE_BL31
+# define IMAGE_EL	3
+# define IMAGE_XLAT_DEFAULT_REGIME EL3_REGIME
+#else
+# define IMAGE_EL	1
+# define IMAGE_XLAT_DEFAULT_REGIME EL1_EL0_REGIME
+#endif
+
 #endif /*__ASSEMBLY__*/
 
 #endif /* __XLAT_TABLES_V2_HELPERS_H__ */
diff --git a/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h
index 751c3bb..49ab601 100644
--- a/include/plat/arm/board/common/board_arm_def.h
+++ b/include/plat/arm/board/common/board_arm_def.h
@@ -54,9 +54,9 @@
  */
 #if defined(IMAGE_BL31) || defined(IMAGE_BL32)
 # define PLAT_ARM_MMAP_ENTRIES		6
-# define MAX_XLAT_TABLES		4
+# define MAX_XLAT_TABLES		5
 #else
-# define PLAT_ARM_MMAP_ENTRIES		10
+# define PLAT_ARM_MMAP_ENTRIES		11
 # define MAX_XLAT_TABLES		5
 #endif
 
@@ -64,7 +64,7 @@
  * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
  * plus a little space for growth.
  */
-#define PLAT_ARM_MAX_BL1_RW_SIZE	0xA000
+#define PLAT_ARM_MAX_BL1_RW_SIZE	0xB000
 
 /*
  * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
@@ -89,11 +89,26 @@
 
 #define PLAT_ARM_TRUSTED_SRAM_SIZE	0x00040000	/* 256 KB */
 
+/* Reserve the last block of flash for PSCI MEM PROTECT flag */
 #define PLAT_ARM_FIP_BASE		V2M_FLASH0_BASE
-#define PLAT_ARM_FIP_MAX_SIZE		V2M_FLASH0_SIZE
+#define PLAT_ARM_FIP_MAX_SIZE		(V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
 
 #define PLAT_ARM_NVM_BASE		V2M_FLASH0_BASE
-#define PLAT_ARM_NVM_SIZE		V2M_FLASH0_SIZE
+#define PLAT_ARM_NVM_SIZE		(V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+/* PSCI memory protect definitions:
+ * This variable is stored in a non-secure flash because some ARM reference
+ * platforms do not have secure NVRAM. Real systems that provided MEM_PROTECT
+ * support must use a secure NVRAM to store the PSCI MEM_PROTECT definitions.
+ */
+#define PLAT_ARM_MEM_PROT_ADDR		(V2M_FLASH0_BASE + \
+					 V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
 
+/*
+ * Map mem_protect flash region with read and write permissions
+ */
+#define ARM_V2M_MAP_MEM_PROTECT		MAP_REGION_FLAT(PLAT_ARM_MEM_PROT_ADDR,	\
+						V2M_FLASH_BLOCK_SIZE,		\
+						MT_DEVICE | MT_RW | MT_SECURE)
 
 #endif /* __BOARD_ARM_DEF_H__ */
diff --git a/include/plat/arm/board/common/v2m_def.h b/include/plat/arm/board/common/v2m_def.h
index 2ad513a..364b780 100644
--- a/include/plat/arm/board/common/v2m_def.h
+++ b/include/plat/arm/board/common/v2m_def.h
@@ -69,6 +69,7 @@
 /* NOR Flash */
 #define V2M_FLASH0_BASE			0x08000000
 #define V2M_FLASH0_SIZE			0x04000000
+#define V2M_FLASH_BLOCK_SIZE		0x00040000	/* 256 KB */
 
 #define V2M_IOFPGA_BASE			0x1c000000
 #define V2M_IOFPGA_SIZE			0x03000000
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 787ccb0..dbf102b 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -177,7 +177,12 @@
 						ARM_NS_DRAM1_SIZE,	\
 						MT_MEMORY | MT_RW | MT_NS)
 
+#define ARM_MAP_DRAM2			MAP_REGION_FLAT(		\
+						ARM_DRAM2_BASE,		\
+						ARM_DRAM2_SIZE,		\
+						MT_MEMORY | MT_RW | MT_NS)
 #ifdef SPD_tspd
+
 #define ARM_MAP_TSP_SEC_MEM		MAP_REGION_FLAT(		\
 						TSP_SEC_MEM_BASE,	\
 						TSP_SEC_MEM_SIZE,	\
@@ -224,8 +229,18 @@
  * Required platform porting definitions common to all ARM standard platforms
  *****************************************************************************/
 
+/*
+ * We need to access DRAM2 from BL2 for PSCI_MEM_PROTECT for
+ * AArch64 builds
+ */
+#ifdef AARCH64
+#define PLAT_PHY_ADDR_SPACE_SIZE			(1ull << 36)
+#define PLAT_VIRT_ADDR_SPACE_SIZE			(1ull << 36)
+#else
 #define PLAT_PHY_ADDR_SPACE_SIZE			(1ull << 32)
 #define PLAT_VIRT_ADDR_SPACE_SIZE			(1ull << 32)
+#endif
+
 
 /*
  * This macro defines the deepest retention state possible. A higher state
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index f0e9767..4e589c0 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -122,6 +122,10 @@
 int arm_validate_ns_entrypoint(uintptr_t entrypoint);
 void arm_system_pwr_domain_resume(void);
 void arm_program_trusted_mailbox(uintptr_t address);
+int arm_psci_read_mem_protect(int *val);
+int arm_nor_psci_write_mem_protect(int val);
+void arm_nor_psci_do_mem_protect(void);
+int arm_psci_mem_protect_chk(uintptr_t base, u_register_t length);
 
 /* Topology utility function */
 int arm_check_mpidr(u_register_t mpidr);
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index bd721bb..e189f64 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -79,6 +79,7 @@
 int plat_crash_console_flush(void);
 void plat_error_handler(int err) __dead2;
 void plat_panic_handler(void) __dead2;
+const char *plat_log_get_prefix(unsigned int log_level);
 
 /*******************************************************************************
  * Mandatory BL1 functions
diff --git a/lib/psci/psci_lib.mk b/lib/psci/psci_lib.mk
index 29080db..1d4aac4 100644
--- a/lib/psci/psci_lib.mk
+++ b/lib/psci/psci_lib.mk
@@ -17,6 +17,7 @@
 				lib/psci/psci_main.c			\
 				lib/psci/psci_setup.c			\
 				lib/psci/psci_system_off.c		\
+				lib/psci/psci_mem_protect.c		\
 				lib/psci/${ARCH}/psci_helpers.S
 
 ifeq (${ARCH}, aarch64)
diff --git a/lib/psci/psci_main.c b/lib/psci/psci_main.c
index 257479a..a5d707e 100644
--- a/lib/psci/psci_main.c
+++ b/lib/psci/psci_main.c
@@ -408,6 +408,11 @@
 		case PSCI_STAT_COUNT_AARCH32:
 			return psci_stat_count(x1, x2);
 #endif
+		case PSCI_MEM_PROTECT:
+			return psci_mem_protect(x1);
+
+		case PSCI_MEM_CHK_RANGE_AARCH32:
+			return psci_mem_chk_range(x1, x2);
 
 		default:
 			break;
@@ -445,6 +450,10 @@
 			return psci_stat_count(x1, x2);
 #endif
 
+		case PSCI_MEM_CHK_RANGE_AARCH64:
+			return psci_mem_chk_range(x1, x2);
+
+
 		default:
 			break;
 		}
diff --git a/lib/psci/psci_mem_protect.c b/lib/psci/psci_mem_protect.c
new file mode 100644
index 0000000..fca84e9
--- /dev/null
+++ b/lib/psci/psci_mem_protect.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <limits.h>
+#include <utils.h>
+#include "psci_private.h"
+
+int psci_mem_protect(unsigned int enable)
+{
+	int val;
+
+	assert(psci_plat_pm_ops->read_mem_protect);
+	assert(psci_plat_pm_ops->write_mem_protect);
+
+	if (psci_plat_pm_ops->read_mem_protect(&val) < 0)
+		return PSCI_E_NOT_SUPPORTED;
+	if (psci_plat_pm_ops->write_mem_protect(enable) < 0)
+		return PSCI_E_NOT_SUPPORTED;
+
+	return val != 0;
+}
+
+int psci_mem_chk_range(uintptr_t base, u_register_t length)
+{
+	int ret;
+
+	assert(psci_plat_pm_ops->mem_protect_chk);
+
+	if (length == 0 || check_uptr_overflow(base, length-1))
+		return PSCI_E_DENIED;
+
+	ret = psci_plat_pm_ops->mem_protect_chk(base, length);
+	return (ret < 0) ? PSCI_E_DENIED : PSCI_E_SUCCESS;
+}
diff --git a/lib/psci/psci_private.h b/lib/psci/psci_private.h
index da6a20f..facfacb 100644
--- a/lib/psci/psci_private.h
+++ b/lib/psci/psci_private.h
@@ -269,4 +269,8 @@
 u_register_t psci_stat_count(u_register_t target_cpu,
 			unsigned int power_state);
 
+/* Private exported functions from psci_mem_protect.c */
+int psci_mem_protect(unsigned int enable);
+int psci_mem_chk_range(uintptr_t base, u_register_t length);
+
 #endif /* __PSCI_PRIVATE_H__ */
diff --git a/lib/psci/psci_setup.c b/lib/psci/psci_setup.c
index f70e34d..5ef49ac 100644
--- a/lib/psci/psci_setup.c
+++ b/lib/psci/psci_setup.c
@@ -243,6 +243,11 @@
 		psci_caps |=  define_psci_cap(PSCI_SYSTEM_RESET);
 	if (psci_plat_pm_ops->get_node_hw_state)
 		psci_caps |= define_psci_cap(PSCI_NODE_HW_STATE_AARCH64);
+	if (psci_plat_pm_ops->read_mem_protect &&
+			psci_plat_pm_ops->write_mem_protect)
+		psci_caps |= define_psci_cap(PSCI_MEM_PROTECT);
+	if (psci_plat_pm_ops->mem_protect_chk)
+		psci_caps |= define_psci_cap(PSCI_MEM_CHK_RANGE_AARCH64);
 
 #if ENABLE_PSCI_STAT
 	psci_caps |=  define_psci_cap(PSCI_STAT_RESIDENCY_AARCH64);
diff --git a/lib/utils/mem_region.c b/lib/utils/mem_region.c
new file mode 100644
index 0000000..31c6231
--- /dev/null
+++ b/lib/utils/mem_region.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <utils.h>
+
+/*
+ * All the regions defined in mem_region_t must have the following properties
+ *
+ * - Any contiguous regions must be merged into a single entry.
+ * - The number of bytes of each region must be greater than zero.
+ * - The calculation of the highest address within the region (base + nbytes-1)
+ *   doesn't produce an overflow.
+ *
+ * These conditions must be fulfilled by the caller and they aren't checked
+ * at runtime.
+ */
+
+/*
+ * zero_normalmem all the regions defined in tbl.
+ * It assumes that MMU is enabled and the memory is Normal memory.
+ * tbl must be a valid pointer to a memory mem_region_t array,
+ * nregions is the size of the array.
+ */
+void clear_mem_regions(mem_region_t *tbl, size_t nregions)
+{
+	size_t i;
+
+	assert(tbl);
+	assert(nregions > 0);
+
+	for (i = 0; i < nregions; i++) {
+		assert(tbl->nbytes > 0);
+		assert(!check_uptr_overflow(tbl->base, tbl->nbytes-1));
+		zero_normalmem((void *) (tbl->base), tbl->nbytes);
+		tbl++;
+	}
+}
+
+/*
+ * This function checks that a region (addr + nbytes-1) of memory is totally
+ * covered by one of the regions defined in tbl.
+ * tbl must be a valid pointer to a memory mem_region_t array, nregions
+ * is the size of the array and the region described by addr and nbytes must
+ * not generate an overflow.
+ * Returns:
+ *  -1 means that the region is not covered by any of the regions
+ *     described in tbl.
+ *   0 the region (addr + nbytes-1) is covered by one of the regions described
+ *     in tbl
+ */
+int mem_region_in_array_chk(mem_region_t *tbl, size_t nregions,
+			    uintptr_t addr, size_t nbytes)
+{
+	uintptr_t region_start, region_end, start, end;
+	size_t i;
+
+	assert(tbl);
+	assert(nbytes > 0);
+	assert(!check_uptr_overflow(addr, nbytes-1));
+
+	region_start = addr;
+	region_end = addr + (nbytes - 1);
+	for (i = 0; i < nregions; i++) {
+		assert(tbl->nbytes > 0);
+		assert(!check_uptr_overflow(tbl->base, tbl->nbytes-1));
+		start = tbl->base;
+		end = start + (tbl->nbytes - 1);
+		if (region_start >= start && region_end <= end)
+			return 0;
+		tbl++;
+	}
+
+	return -1;
+}
diff --git a/lib/xlat_tables/aarch64/xlat_tables.c b/lib/xlat_tables/aarch64/xlat_tables.c
index 2ddf8cb..28ae1f7 100644
--- a/lib/xlat_tables/aarch64/xlat_tables.c
+++ b/lib/xlat_tables/aarch64/xlat_tables.c
@@ -182,7 +182,11 @@
 
 /* Define EL1 and EL3 variants of the function enabling the MMU */
 DEFINE_ENABLE_MMU_EL(1,
-		(tcr_ps_bits << TCR_EL1_IPS_SHIFT),
+		/*
+		 * TCR_EL1.EPD1: Disable translation table walk for addresses
+		 * that are translated using TTBR1_EL1.
+		 */
+		TCR_EPD1_BIT | (tcr_ps_bits << TCR_EL1_IPS_SHIFT),
 		tlbivmalle1)
 DEFINE_ENABLE_MMU_EL(3,
 		TCR_EL3_RES1 | (tcr_ps_bits << TCR_EL3_PS_SHIFT),
diff --git a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
index e66b927..cbc8685 100644
--- a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
+++ b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
@@ -22,7 +22,7 @@
 }
 #endif /* ENABLE_ASSERTIONS*/
 
-int is_mmu_enabled(void)
+int is_mmu_enabled_ctx(const xlat_ctx_t *ctx __unused)
 {
 	return (read_sctlr() & SCTLR_M_BIT) != 0;
 }
@@ -40,6 +40,17 @@
 	tlbimvaais(TLBI_ADDR(va));
 }
 
+void xlat_arch_tlbi_va_regime(uintptr_t va, xlat_regime_t xlat_regime __unused)
+{
+	/*
+	 * Ensure the translation table write has drained into memory before
+	 * invalidating the TLB entry.
+	 */
+	dsbishst();
+
+	tlbimvaais(TLBI_ADDR(va));
+}
+
 void xlat_arch_tlbi_va_sync(void)
 {
 	/* Invalidate all entries from branch predictors. */
@@ -77,11 +88,6 @@
 	return 3;
 }
 
-uint64_t xlat_arch_get_xn_desc(int el __unused)
-{
-	return UPPER_ATTRS(XN);
-}
-
 /*******************************************************************************
  * Function for enabling the MMU in Secure PL1, assuming that the page tables
  * have already been created.
diff --git a/lib/xlat_tables_v2/aarch32/xlat_tables_arch_private.h b/lib/xlat_tables_v2/aarch32/xlat_tables_arch_private.h
new file mode 100644
index 0000000..509395d
--- /dev/null
+++ b/lib/xlat_tables_v2/aarch32/xlat_tables_arch_private.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __XLAT_TABLES_ARCH_PRIVATE_H__
+#define __XLAT_TABLES_ARCH_PRIVATE_H__
+
+#include <xlat_tables_defs.h>
+#include <xlat_tables_v2.h>
+
+/*
+ * Return the execute-never mask that will prevent instruction fetch at the
+ * given translation regime.
+ */
+static inline uint64_t xlat_arch_regime_get_xn_desc(xlat_regime_t regime __unused)
+{
+	return UPPER_ATTRS(XN);
+}
+
+#endif /* __XLAT_TABLES_ARCH_PRIVATE_H__ */
diff --git a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
index 097e815..eda38d3 100644
--- a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
+++ b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
@@ -10,19 +10,12 @@
 #include <bl_common.h>
 #include <cassert.h>
 #include <common_def.h>
-#include <platform_def.h>
 #include <sys/types.h>
 #include <utils.h>
 #include <utils_def.h>
 #include <xlat_tables_v2.h>
 #include "../xlat_tables_private.h"
 
-#if defined(IMAGE_BL1) || defined(IMAGE_BL31)
-# define IMAGE_EL	3
-#else
-# define IMAGE_EL	1
-#endif
-
 static unsigned long long calc_physical_addr_size_bits(
 					unsigned long long max_addr)
 {
@@ -71,20 +64,31 @@
 }
 #endif /* ENABLE_ASSERTIONS*/
 
+int is_mmu_enabled_ctx(const xlat_ctx_t *ctx)
+{
+	if (ctx->xlat_regime == EL1_EL0_REGIME) {
+		assert(xlat_arch_current_el() >= 1);
+		return (read_sctlr_el1() & SCTLR_M_BIT) != 0;
+	} else {
+		assert(ctx->xlat_regime == EL3_REGIME);
+		assert(xlat_arch_current_el() >= 3);
+		return (read_sctlr_el3() & SCTLR_M_BIT) != 0;
+	}
+}
+
-int is_mmu_enabled(void)
+
+void xlat_arch_tlbi_va(uintptr_t va)
 {
 #if IMAGE_EL == 1
 	assert(IS_IN_EL(1));
-	return (read_sctlr_el1() & SCTLR_M_BIT) != 0;
+	xlat_arch_tlbi_va_regime(va, EL1_EL0_REGIME);
 #elif IMAGE_EL == 3
 	assert(IS_IN_EL(3));
-	return (read_sctlr_el3() & SCTLR_M_BIT) != 0;
+	xlat_arch_tlbi_va_regime(va, EL3_REGIME);
 #endif
 }
 
-#if PLAT_XLAT_TABLES_DYNAMIC
-
-void xlat_arch_tlbi_va(uintptr_t va)
+void xlat_arch_tlbi_va_regime(uintptr_t va, xlat_regime_t xlat_regime)
 {
 	/*
 	 * Ensure the translation table write has drained into memory before
@@ -92,13 +96,21 @@
 	 */
 	dsbishst();
 
-#if IMAGE_EL == 1
-	assert(IS_IN_EL(1));
-	tlbivaae1is(TLBI_ADDR(va));
-#elif IMAGE_EL == 3
-	assert(IS_IN_EL(3));
-	tlbivae3is(TLBI_ADDR(va));
-#endif
+	/*
+	 * This function only supports invalidation of TLB entries for the EL3
+	 * and EL1&0 translation regimes.
+	 *
+	 * Also, it is architecturally UNDEFINED to invalidate TLBs of a higher
+	 * exception level (see section D4.9.2 of the ARM ARM rev B.a).
+	 */
+	if (xlat_regime == EL1_EL0_REGIME) {
+		assert(xlat_arch_current_el() >= 1);
+		tlbivaae1is(TLBI_ADDR(va));
+	} else {
+		assert(xlat_regime == EL3_REGIME);
+		assert(xlat_arch_current_el() >= 3);
+		tlbivae3is(TLBI_ADDR(va));
+	}
 }
 
 void xlat_arch_tlbi_va_sync(void)
@@ -124,8 +136,6 @@
 	isb();
 }
 
-#endif /* PLAT_XLAT_TABLES_DYNAMIC */
-
 int xlat_arch_current_el(void)
 {
 	int el = GET_EL(read_CurrentEl());
@@ -135,16 +145,6 @@
 	return el;
 }
 
-uint64_t xlat_arch_get_xn_desc(int el)
-{
-	if (el == 3) {
-		return UPPER_ATTRS(XN);
-	} else {
-		assert(el == 1);
-		return UPPER_ATTRS(PXN);
-	}
-}
-
 /*******************************************************************************
  * Macro generating the code for the function enabling the MMU in the given
  * exception level, assuming that the pagetables have already been created.
@@ -256,7 +256,11 @@
 
 #if IMAGE_EL == 1
 	assert(IS_IN_EL(1));
-	tcr |= tcr_ps_bits << TCR_EL1_IPS_SHIFT;
+	/*
+	 * TCR_EL1.EPD1: Disable translation table walk for addresses that are
+	 * translated using TTBR1_EL1.
+	 */
+	tcr |= TCR_EPD1_BIT | (tcr_ps_bits << TCR_EL1_IPS_SHIFT);
 	enable_mmu_internal_el1(flags, mair, tcr, ttbr);
 #elif IMAGE_EL == 3
 	assert(IS_IN_EL(3));
diff --git a/lib/xlat_tables_v2/aarch64/xlat_tables_arch_private.h b/lib/xlat_tables_v2/aarch64/xlat_tables_arch_private.h
new file mode 100644
index 0000000..d201590
--- /dev/null
+++ b/lib/xlat_tables_v2/aarch64/xlat_tables_arch_private.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __XLAT_TABLES_ARCH_PRIVATE_H__
+#define __XLAT_TABLES_ARCH_PRIVATE_H__
+
+#include <assert.h>
+#include <xlat_tables_defs.h>
+#include <xlat_tables_v2.h>
+
+/*
+ * Return the execute-never mask that will prevent instruction fetch at all ELs
+ * that are part of the given translation regime.
+ */
+static inline uint64_t xlat_arch_regime_get_xn_desc(xlat_regime_t regime)
+{
+	if (regime == EL1_EL0_REGIME) {
+		return UPPER_ATTRS(UXN) | UPPER_ATTRS(PXN);
+	} else {
+		assert(regime == EL3_REGIME);
+		return UPPER_ATTRS(XN);
+	}
+}
+
+#endif /* __XLAT_TABLES_ARCH_PRIVATE_H__ */
diff --git a/lib/xlat_tables_v2/xlat_tables.mk b/lib/xlat_tables_v2/xlat_tables.mk
index b94ce5d..06dd844 100644
--- a/lib/xlat_tables_v2/xlat_tables.mk
+++ b/lib/xlat_tables_v2/xlat_tables.mk
@@ -7,3 +7,5 @@
 XLAT_TABLES_LIB_SRCS	:=	$(addprefix lib/xlat_tables_v2/,	\
 				${ARCH}/xlat_tables_arch.c		\
 				xlat_tables_internal.c)
+
+INCLUDES		+=	-Ilib/xlat_tables_v2/${ARCH}
diff --git a/lib/xlat_tables_v2/xlat_tables_internal.c b/lib/xlat_tables_v2/xlat_tables_internal.c
index cd6e11c..9faeb7e 100644
--- a/lib/xlat_tables_v2/xlat_tables_internal.c
+++ b/lib/xlat_tables_v2/xlat_tables_internal.c
@@ -14,7 +14,7 @@
 #include <string.h>
 #include <types.h>
 #include <utils.h>
-#include <xlat_tables_arch.h>
+#include <xlat_tables_arch_private.h>
 #include <xlat_tables_defs.h>
 #include <xlat_tables_v2.h>
 
@@ -112,9 +112,11 @@
 
 #endif /* PLAT_XLAT_TABLES_DYNAMIC */
 
-/* Returns a block/page table descriptor for the given level and attributes. */
-static uint64_t xlat_desc(mmap_attr_t attr, unsigned long long addr_pa,
-			  int level, uint64_t execute_never_mask)
+/*
+ * Returns a block/page table descriptor for the given level and attributes.
+ */
+uint64_t xlat_desc(const xlat_ctx_t *ctx, mmap_attr_t attr,
+		   unsigned long long addr_pa, int level)
 {
 	uint64_t desc;
 	int mem_type;
@@ -133,9 +135,28 @@
 	 * Deduce other fields of the descriptor based on the MT_NS and MT_RW
 	 * memory region attributes.
 	 */
+	desc |= LOWER_ATTRS(ACCESS_FLAG);
+
 	desc |= (attr & MT_NS) ? LOWER_ATTRS(NS) : 0;
 	desc |= (attr & MT_RW) ? LOWER_ATTRS(AP_RW) : LOWER_ATTRS(AP_RO);
-	desc |= LOWER_ATTRS(ACCESS_FLAG);
+
+	/*
+	 * Do not allow unprivileged access when the mapping is for a privileged
+	 * EL. For translation regimes that do not have mappings for access for
+	 * lower exception levels, set AP[2] to AP_NO_ACCESS_UNPRIVILEGED.
+	 */
+	if (ctx->xlat_regime == EL1_EL0_REGIME) {
+		if (attr & MT_USER) {
+			/* EL0 mapping requested, so we give User access */
+			desc |= LOWER_ATTRS(AP_ACCESS_UNPRIVILEGED);
+		} else {
+			/* EL1 mapping requested, no User access granted */
+			desc |= LOWER_ATTRS(AP_NO_ACCESS_UNPRIVILEGED);
+		}
+	} else {
+		assert(ctx->xlat_regime == EL3_REGIME);
+		desc |= LOWER_ATTRS(AP_NO_ACCESS_UNPRIVILEGED);
+	}
 
 	/*
 	 * Deduce shareability domain and executability of the memory region
@@ -156,7 +177,7 @@
 		 * fetch, which could be an issue if this memory region
 		 * corresponds to a read-sensitive peripheral.
 		 */
-		desc |= execute_never_mask;
+		desc |= xlat_arch_regime_get_xn_desc(ctx->xlat_regime);
 
 	} else { /* Normal memory */
 		/*
@@ -171,10 +192,13 @@
 		 * translation table.
 		 *
 		 * For read-only memory, rely on the MT_EXECUTE/MT_EXECUTE_NEVER
-		 * attribute to figure out the value of the XN bit.
+		 * attribute to figure out the value of the XN bit.  The actual
+		 * XN bit(s) to set in the descriptor depends on the context's
+		 * translation regime and the policy applied in
+		 * xlat_arch_regime_get_xn_desc().
 		 */
 		if ((attr & MT_RW) || (attr & MT_EXECUTE_NEVER)) {
-			desc |= execute_never_mask;
+			desc |= xlat_arch_regime_get_xn_desc(ctx->xlat_regime);
 		}
 
 		if (mem_type == MT_MEMORY) {
@@ -314,7 +338,7 @@
 		if (action == ACTION_WRITE_BLOCK_ENTRY) {
 
 			table_base[table_idx] = INVALID_DESC;
-			xlat_arch_tlbi_va(table_idx_va);
+			xlat_arch_tlbi_va_regime(table_idx_va, ctx->xlat_regime);
 
 		} else if (action == ACTION_RECURSE_INTO_TABLE) {
 
@@ -330,7 +354,8 @@
 			 */
 			if (xlat_table_is_empty(ctx, subtable)) {
 				table_base[table_idx] = INVALID_DESC;
-				xlat_arch_tlbi_va(table_idx_va);
+				xlat_arch_tlbi_va_regime(table_idx_va,
+						ctx->xlat_regime);
 			}
 
 		} else {
@@ -417,7 +442,8 @@
 				 * descriptors. If not, create a table instead.
 				 */
 				if ((dest_pa & XLAT_BLOCK_MASK(level)) ||
-				    (level < MIN_LVL_BLOCK_DESC))
+				    (level < MIN_LVL_BLOCK_DESC) ||
+				    (mm->granularity < XLAT_BLOCK_SIZE(level)))
 					return ACTION_CREATE_NEW_TABLE;
 				else
 					return ACTION_WRITE_BLOCK_ENTRY;
@@ -535,8 +561,7 @@
 		if (action == ACTION_WRITE_BLOCK_ENTRY) {
 
 			table_base[table_idx] =
-				xlat_desc(mm->attr, table_idx_pa, level,
-					  ctx->execute_never_mask);
+				xlat_desc(ctx, mm->attr, table_idx_pa, level);
 
 		} else if (action == ACTION_CREATE_NEW_TABLE) {
 
@@ -590,9 +615,10 @@
 	mmap_region_t *mm = mmap;
 
 	while (mm->size) {
-		tf_printf(" VA:%p  PA:0x%llx  size:0x%zx  attr:0x%x\n",
+		tf_printf(" VA:%p  PA:0x%llx  size:0x%zx  attr:0x%x",
 				(void *)mm->base_va, mm->base_pa,
 				mm->size, mm->attr);
+		tf_printf(" granularity:0x%zx\n", mm->granularity);
 		++mm;
 	};
 	tf_printf("\n");
@@ -608,11 +634,13 @@
  *   ENOMEM: There is not enough memory in the mmap array.
  *    EPERM: Region overlaps another one in an invalid way.
  */
-static int mmap_add_region_check(xlat_ctx_t *ctx, unsigned long long base_pa,
-				 uintptr_t base_va, size_t size,
-				 mmap_attr_t attr)
+static int mmap_add_region_check(xlat_ctx_t *ctx, const mmap_region_t *mm)
 {
-	mmap_region_t *mm = ctx->mmap;
+	unsigned long long base_pa = mm->base_pa;
+	uintptr_t base_va = mm->base_va;
+	size_t size = mm->size;
+	size_t granularity = mm->granularity;
+
 	unsigned long long end_pa = base_pa + size - 1;
 	uintptr_t end_va = base_va + size - 1;
 
@@ -620,6 +648,12 @@
 			!IS_PAGE_ALIGNED(size))
 		return -EINVAL;
 
+	if ((granularity != XLAT_BLOCK_SIZE(1)) &&
+		(granularity != XLAT_BLOCK_SIZE(2)) &&
+		(granularity != XLAT_BLOCK_SIZE(3))) {
+		return -EINVAL;
+	}
+
 	/* Check for overflows */
 	if ((base_pa > end_pa) || (base_va > end_va))
 		return -ERANGE;
@@ -630,22 +664,27 @@
 	if ((base_pa + (unsigned long long)size - 1ULL) > ctx->pa_max_address)
 		return -ERANGE;
 
-	/* Check that there is space in the mmap array */
+	/* Check that there is space in the ctx->mmap array */
 	if (ctx->mmap[ctx->mmap_num - 1].size != 0)
 		return -ENOMEM;
 
 	/* Check for PAs and VAs overlaps with all other regions */
-	for (mm = ctx->mmap; mm->size; ++mm) {
+	for (mmap_region_t *mm_cursor = ctx->mmap;
+						mm_cursor->size; ++mm_cursor) {
 
-		uintptr_t mm_end_va = mm->base_va + mm->size - 1;
+		uintptr_t mm_cursor_end_va = mm_cursor->base_va
+							+ mm_cursor->size - 1;
 
 		/*
 		 * Check if one of the regions is completely inside the other
 		 * one.
 		 */
 		int fully_overlapped_va =
-			((base_va >= mm->base_va) && (end_va <= mm_end_va)) ||
-			((mm->base_va >= base_va) && (mm_end_va <= end_va));
+			((base_va >= mm_cursor->base_va) &&
+					(end_va <= mm_cursor_end_va)) ||
+
+			((mm_cursor->base_va >= base_va) &&
+						(mm_cursor_end_va <= end_va));
 
 		/*
 		 * Full VA overlaps are only allowed if both regions are
@@ -656,13 +695,16 @@
 		if (fully_overlapped_va) {
 
 #if PLAT_XLAT_TABLES_DYNAMIC
-			if ((attr & MT_DYNAMIC) || (mm->attr & MT_DYNAMIC))
+			if ((mm->attr & MT_DYNAMIC) ||
+						(mm_cursor->attr & MT_DYNAMIC))
 				return -EPERM;
 #endif /* PLAT_XLAT_TABLES_DYNAMIC */
-			if ((mm->base_va - mm->base_pa) != (base_va - base_pa))
+			if ((mm_cursor->base_va - mm_cursor->base_pa) !=
+							(base_va - base_pa))
 				return -EPERM;
 
-			if ((base_va == mm->base_va) && (size == mm->size))
+			if ((base_va == mm_cursor->base_va) &&
+						(size == mm_cursor->size))
 				return -EPERM;
 
 		} else {
@@ -672,13 +714,15 @@
 			 * Partial overlaps are not allowed
 			 */
 
-			unsigned long long mm_end_pa =
-						     mm->base_pa + mm->size - 1;
+			unsigned long long mm_cursor_end_pa =
+				     mm_cursor->base_pa + mm_cursor->size - 1;
 
 			int separated_pa =
-				(end_pa < mm->base_pa) || (base_pa > mm_end_pa);
+				(end_pa < mm_cursor->base_pa) ||
+				(base_pa > mm_cursor_end_pa);
 			int separated_va =
-				(end_va < mm->base_va) || (base_va > mm_end_va);
+				(end_va < mm_cursor->base_va) ||
+				(base_va > mm_cursor_end_va);
 
 			if (!(separated_va && separated_pa))
 				return -EPERM;
@@ -703,8 +747,7 @@
 	/* Static regions must be added before initializing the xlat tables. */
 	assert(!ctx->initialized);
 
-	ret = mmap_add_region_check(ctx, mm->base_pa, mm->base_va, mm->size,
-				    mm->attr);
+	ret = mmap_add_region_check(ctx, mm);
 	if (ret != 0) {
 		ERROR("mmap_add_region_check() failed. error %d\n", ret);
 		assert(0);
@@ -754,10 +797,7 @@
 	 */
 	assert(mm_last->size == 0);
 
-	mm_cursor->base_pa = mm->base_pa;
-	mm_cursor->base_va = mm->base_va;
-	mm_cursor->size = mm->size;
-	mm_cursor->attr = mm->attr;
+	*mm_cursor = *mm;
 
 	if (end_pa > ctx->max_pa)
 		ctx->max_pa = end_pa;
@@ -770,12 +810,7 @@
 				size_t size,
 				mmap_attr_t attr)
 {
-	mmap_region_t mm = {
-		.base_va = base_va,
-		.base_pa = base_pa,
-		.size = size,
-		.attr = attr,
-	};
+	mmap_region_t mm = MAP_REGION(base_pa, base_va, size, attr);
 	mmap_add_region_ctx(&tf_xlat_ctx, &mm);
 }
 
@@ -807,7 +842,10 @@
 	if (!mm->size)
 		return 0;
 
-	ret = mmap_add_region_check(ctx, mm->base_pa, mm->base_va, mm->size, mm->attr | MT_DYNAMIC);
+	/* Now this region is a dynamic one */
+	mm->attr |= MT_DYNAMIC;
+
+	ret = mmap_add_region_check(ctx, mm);
 	if (ret != 0)
 		return ret;
 
@@ -816,14 +854,17 @@
 	 * static regions in mmap_add_region_ctx().
 	 */
 
-	while ((mm_cursor->base_va + mm_cursor->size - 1) < end_va && mm_cursor->size)
+	while ((mm_cursor->base_va + mm_cursor->size - 1)
+					< end_va && mm_cursor->size)
 		++mm_cursor;
 
-	while ((mm_cursor->base_va + mm_cursor->size - 1 == end_va) && (mm_cursor->size < mm->size))
+	while ((mm_cursor->base_va + mm_cursor->size - 1 == end_va)
+				&& (mm_cursor->size < mm->size))
 		++mm_cursor;
 
 	/* Make room for new region by moving other regions up by one place */
-	memmove(mm_cursor + 1, mm_cursor, (uintptr_t)mm_last - (uintptr_t)mm_cursor);
+	memmove(mm_cursor + 1, mm_cursor,
+		     (uintptr_t)mm_last - (uintptr_t)mm_cursor);
 
 	/*
 	 * Check we haven't lost the empty sentinal from the end of the array.
@@ -832,22 +873,21 @@
 	 */
 	assert(mm_last->size == 0);
 
-	mm_cursor->base_pa = mm->base_pa;
-	mm_cursor->base_va = mm->base_va;
-	mm_cursor->size = mm->size;
-	mm_cursor->attr = mm->attr | MT_DYNAMIC;
+	*mm_cursor = *mm;
 
 	/*
 	 * Update the translation tables if the xlat tables are initialized. If
 	 * not, this region will be mapped when they are initialized.
 	 */
 	if (ctx->initialized) {
-		uintptr_t end_va = xlat_tables_map_region(ctx, mm_cursor, 0, ctx->base_table,
-				ctx->base_table_entries, ctx->base_level);
+		uintptr_t end_va = xlat_tables_map_region(ctx, mm_cursor,
+				0, ctx->base_table, ctx->base_table_entries,
+				ctx->base_level);
 
 		/* Failed to map, remove mmap entry, unmap and return error. */
 		if (end_va != mm_cursor->base_va + mm_cursor->size - 1) {
-			memmove(mm_cursor, mm_cursor + 1, (uintptr_t)mm_last - (uintptr_t)mm_cursor);
+			memmove(mm_cursor, mm_cursor + 1,
+				(uintptr_t)mm_last - (uintptr_t)mm_cursor);
 
 			/*
 			 * Check if the mapping function actually managed to map
@@ -857,8 +897,8 @@
 				return -ENOMEM;
 
 			/*
-			 * Something went wrong after mapping some table entries,
-			 * undo every change done up to this point.
+			 * Something went wrong after mapping some table
+			 * entries, undo every change done up to this point.
 			 */
 			mmap_region_t unmap_mm = {
 					.base_pa = 0,
@@ -892,12 +932,7 @@
 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,
-	};
+	mmap_region_t mm = MAP_REGION(base_pa, base_va, size, attr);
 	return mmap_add_dynamic_region_ctx(&tf_xlat_ctx, &mm);
 }
 
@@ -987,9 +1022,10 @@
 #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
 
 /* Print the attributes of the specified block descriptor. */
-static void xlat_desc_print(uint64_t desc, uint64_t execute_never_mask)
+static void xlat_desc_print(xlat_ctx_t *ctx, uint64_t desc)
 {
 	int mem_type_index = ATTR_INDEX_GET(desc);
+	xlat_regime_t xlat_regime = ctx->xlat_regime;
 
 	if (mem_type_index == ATTR_IWBWA_OWBWA_NTR_INDEX) {
 		tf_printf("MEM");
@@ -1000,9 +1036,49 @@
 		tf_printf("DEV");
 	}
 
+	const char *priv_str = "(PRIV)";
+	const char *user_str = "(USER)";
+
+	/*
+	 * Showing Privileged vs Unprivileged only makes sense for EL1&0
+	 * mappings
+	 */
+	const char *ro_str = "-RO";
+	const char *rw_str = "-RW";
+	const char *no_access_str = "-NOACCESS";
+
+	if (xlat_regime == EL3_REGIME) {
+		/* For EL3, the AP[2] bit is all what matters */
+		tf_printf((desc & LOWER_ATTRS(AP_RO)) ? ro_str : rw_str);
+	} else {
+		const char *ap_str = (desc & LOWER_ATTRS(AP_RO)) ? ro_str : rw_str;
+		tf_printf(ap_str);
+		tf_printf(priv_str);
+		/*
+		 * EL0 can only have the same permissions as EL1 or no
+		 * permissions at all.
+		 */
+		tf_printf((desc & LOWER_ATTRS(AP_ACCESS_UNPRIVILEGED))
+			  ? ap_str : no_access_str);
+		tf_printf(user_str);
+	}
+
+	const char *xn_str = "-XN";
+	const char *exec_str = "-EXEC";
+
+	if (xlat_regime == EL3_REGIME) {
+		/* For EL3, the XN bit is all what matters */
+		tf_printf(LOWER_ATTRS(XN) & desc ? xn_str : exec_str);
+	} else {
+		/* For EL0 and EL1, we need to know who has which rights */
+		tf_printf(LOWER_ATTRS(PXN) & desc ? xn_str : exec_str);
+		tf_printf(priv_str);
+
+		tf_printf(LOWER_ATTRS(UXN) & desc ? xn_str : exec_str);
+		tf_printf(user_str);
+	}
+
-	tf_printf(LOWER_ATTRS(AP_RO) & desc ? "-RO" : "-RW");
 	tf_printf(LOWER_ATTRS(NS) & desc ? "-NS" : "-S");
-	tf_printf(execute_never_mask & desc ? "-XN" : "-EXEC");
 }
 
 static const char * const level_spacers[] = {
@@ -1019,9 +1095,10 @@
  * Recursive function that reads the translation tables passed as an argument
  * and prints their status.
  */
-static void xlat_tables_print_internal(const uintptr_t table_base_va,
+static void xlat_tables_print_internal(xlat_ctx_t *ctx,
+		const uintptr_t table_base_va,
 		uint64_t *const table_base, const int table_entries,
-		const unsigned int level, const uint64_t execute_never_mask)
+		const unsigned int level)
 {
 	assert(level <= XLAT_TABLE_LEVEL_MAX);
 
@@ -1080,17 +1157,16 @@
 
 				uintptr_t addr_inner = desc & TABLE_ADDR_MASK;
 
-				xlat_tables_print_internal(table_idx_va,
+				xlat_tables_print_internal(ctx, table_idx_va,
 					(uint64_t *)addr_inner,
-					XLAT_TABLE_ENTRIES, level+1,
-					execute_never_mask);
+					XLAT_TABLE_ENTRIES, level + 1);
 			} else {
 				tf_printf("%sVA:%p PA:0x%llx size:0x%zx ",
 					  level_spacers[level],
 					  (void *)table_idx_va,
 					  (unsigned long long)(desc & TABLE_ADDR_MASK),
 					  level_size);
-				xlat_desc_print(desc, execute_never_mask);
+				xlat_desc_print(ctx, desc);
 				tf_printf("\n");
 			}
 		}
@@ -1110,7 +1186,15 @@
 void xlat_tables_print(xlat_ctx_t *ctx)
 {
 #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+	const char *xlat_regime_str;
+	if (ctx->xlat_regime == EL1_EL0_REGIME) {
+		xlat_regime_str = "1&0";
+	} else {
+		assert(ctx->xlat_regime == EL3_REGIME);
+		xlat_regime_str = "3";
+	}
 	VERBOSE("Translation tables state:\n");
+	VERBOSE("  Xlat regime:     EL%s\n", xlat_regime_str);
 	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);
@@ -1134,22 +1218,21 @@
 		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);
+	xlat_tables_print_internal(ctx, 0, ctx->base_table,
+				   ctx->base_table_entries, ctx->base_level);
 #endif /* LOG_LEVEL >= LOG_LEVEL_VERBOSE */
 }
 
 void init_xlat_tables_ctx(xlat_ctx_t *ctx)
 {
-	mmap_region_t *mm = ctx->mmap;
-
-	assert(!is_mmu_enabled());
+	assert(ctx != NULL);
 	assert(!ctx->initialized);
+	assert(ctx->xlat_regime == EL3_REGIME || ctx->xlat_regime == EL1_EL0_REGIME);
+	assert(!is_mmu_enabled_ctx(ctx));
 
-	print_mmap(mm);
+	mmap_region_t *mm = ctx->mmap;
 
-	ctx->execute_never_mask =
-			xlat_arch_get_xn_desc(xlat_arch_current_el());
+	print_mmap(mm);
 
 	/* All tables must be zeroed before mapping any region. */
 
diff --git a/lib/xlat_tables_v2/xlat_tables_private.h b/lib/xlat_tables_v2/xlat_tables_private.h
index d352583..79efbeb 100644
--- a/lib/xlat_tables_v2/xlat_tables_private.h
+++ b/lib/xlat_tables_v2/xlat_tables_private.h
@@ -34,12 +34,24 @@
 	MT_DYNAMIC	= 1 << MT_DYN_SHIFT
 } mmap_priv_attr_t;
 
+#endif /* PLAT_XLAT_TABLES_DYNAMIC */
+
 /*
- * Function used to invalidate all levels of the translation walk for a given
- * virtual address. It must be called for every translation table entry that is
- * modified.
+ * Invalidate all TLB entries that match the given virtual address. This
+ * operation applies to all PEs in the same Inner Shareable domain as the PE
+ * that executes this function. This functions must be called for every
+ * translation table entry that is modified.
+ *
+ * xlat_arch_tlbi_va() applies the invalidation to the exception level of the
+ * current translation regime, whereas xlat_arch_tlbi_va_regime() applies it to
+ * the given translation regime.
+ *
+ * Note, however, that it is architecturally UNDEFINED to invalidate TLB entries
+ * pertaining to a higher exception level, e.g. invalidating EL3 entries from
+ * S-EL1.
  */
 void xlat_arch_tlbi_va(uintptr_t va);
+void xlat_arch_tlbi_va_regime(uintptr_t va, xlat_regime_t xlat_regime);
 
 /*
  * This function has to be called at the end of any code that uses the function
@@ -47,8 +59,6 @@
  */
 void xlat_arch_tlbi_va_sync(void);
 
-#endif /* PLAT_XLAT_TABLES_DYNAMIC */
-
 /* Print VA, PA, size and attributes of all regions in the mmap array. */
 void print_mmap(mmap_region_t *const mmap);
 
@@ -66,13 +76,6 @@
 int xlat_arch_current_el(void);
 
 /*
- * Returns the bit mask that has to be ORed to the rest of a translation table
- * descriptor so that execution of code is prohibited at the given Exception
- * Level.
- */
-uint64_t xlat_arch_get_xn_desc(int el);
-
-/*
  * Return the maximum physical address supported by the hardware.
  * This value depends on the execution state (AArch32/AArch64).
  */
@@ -82,7 +85,10 @@
 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);
+/*
+ * Return 1 if the MMU of the translation regime managed by the given xlat_ctx_t
+ * is enabled, 0 otherwise.
+ */
+int is_mmu_enabled_ctx(const xlat_ctx_t *ctx);
 
 #endif /* __XLAT_TABLES_PRIVATE_H__ */
diff --git a/plat/arm/board/common/board_arm_trusted_boot.c b/plat/arm/board/common/board_arm_trusted_boot.c
index 5d36d17..6c03c91 100644
--- a/plat/arm/board/common/board_arm_trusted_boot.c
+++ b/plat/arm/board/common/board_arm_trusted_boot.c
@@ -18,6 +18,7 @@
 /* ROTPK locations */
 #define ARM_ROTPK_REGS_ID		1
 #define ARM_ROTPK_DEVEL_RSA_ID		2
+#define ARM_ROTPK_DEVEL_ECDSA_ID	3
 
 static const unsigned char rotpk_hash_hdr[] =		\
 		"\x30\x31\x30\x0D\x06\x09\x60\x86\x48"	\
@@ -41,6 +42,12 @@
 		"\x37\x7A\x72\x47\x1B\xEC\x32\x73"	\
 		"\xE9\x92\x32\xE2\x49\x59\xF6\x5E"	\
 		"\x8B\x4A\x4A\x46\xD8\x22\x9A\xDA";
+#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID)
+static const unsigned char arm_devel_rotpk_hash[] =	\
+		"\x2E\x40\xBF\x6E\xF9\x12\xBB\x98"	\
+		"\x31\x71\x09\x0E\x1E\x15\x3D\x0B"	\
+		"\xFD\xD1\xCC\x69\x4A\x98\xEB\x8B"	\
+		"\xA0\xB0\x20\x86\x4E\x6C\x07\x17";
 #endif
 
 /*
@@ -69,7 +76,8 @@
 	memcpy(rotpk_hash_der, rotpk_hash_hdr, rotpk_hash_hdr_len);
 	dst = (uint8_t *)&rotpk_hash_der[rotpk_hash_hdr_len];
 
-#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID)
+#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) \
+	|| (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID)
 	memcpy(dst, arm_devel_rotpk_hash, SHA256_BYTES);
 #elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID)
 	uint32_t *src, tmp;
@@ -121,7 +129,8 @@
 		*dst++ = (uint8_t)((tmp >> 8) & 0xFF);
 		*dst++ = (uint8_t)(tmp & 0xFF);
 	}
-#endif /* (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) */
+#endif /* (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) \
+		  || (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID) */
 
 	*key_ptr = (void *)rotpk_hash_der;
 	*key_len = (unsigned int)sizeof(rotpk_hash_der);
diff --git a/plat/arm/board/common/board_common.mk b/plat/arm/board/common/board_common.mk
index 4667298..d63ae9a 100644
--- a/plat/arm/board/common/board_common.mk
+++ b/plat/arm/board/common/board_common.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -12,9 +12,13 @@
 
 BL1_SOURCES		+=	plat/arm/board/common/drivers/norflash/norflash.c
 
-BL2_SOURCES		+=	plat/arm/board/common/drivers/norflash/norflash.c
+BL2_SOURCES		+=	lib/utils/mem_region.c					\
+				plat/arm/common/arm_nor_psci_mem_protect.c		\
+				plat/arm/board/common/drivers/norflash/norflash.c
 
-#BL31_SOURCES		+=
+BL31_SOURCES		+=	lib/utils/mem_region.c					\
+				plat/arm/board/common/drivers/norflash/norflash.c	\
+				plat/arm/common/arm_nor_psci_mem_protect.c
 
 ifneq (${TRUSTED_BOARD_BOOT},0)
   ifneq (${ARM_CRYPTOCELL_INTEG}, 1)
@@ -22,7 +26,11 @@
     ifeq (${ARM_ROTPK_LOCATION}, regs)
         ARM_ROTPK_LOCATION_ID = ARM_ROTPK_REGS_ID
     else ifeq (${ARM_ROTPK_LOCATION}, devel_rsa)
+        KEY_ALG := rsa
         ARM_ROTPK_LOCATION_ID = ARM_ROTPK_DEVEL_RSA_ID
+    else ifeq (${ARM_ROTPK_LOCATION}, devel_ecdsa)
+        KEY_ALG := ecdsa
+        ARM_ROTPK_LOCATION_ID = ARM_ROTPK_DEVEL_ECDSA_ID
     else
         $(error "Unsupported ARM_ROTPK_LOCATION value")
     endif
diff --git a/plat/arm/board/common/board_css_common.c b/plat/arm/board/common/board_css_common.c
index 159bf86..032ebdf 100644
--- a/plat/arm/board/common/board_css_common.c
+++ b/plat/arm/board/common/board_css_common.c
@@ -29,10 +29,16 @@
 const mmap_region_t plat_arm_mmap[] = {
 	ARM_MAP_SHARED_RAM,
 	V2M_MAP_FLASH0_RO,
+#ifdef PLAT_ARM_MEM_PROT_ADDR
+	ARM_V2M_MAP_MEM_PROTECT,
+#endif
 	V2M_MAP_IOFPGA,
 	CSS_MAP_DEVICE,
 	SOC_CSS_MAP_DEVICE,
 	ARM_MAP_NS_DRAM1,
+#ifdef AARCH64
+	ARM_MAP_DRAM2,
+#endif
 #ifdef SPD_tspd
 	ARM_MAP_TSP_SEC_MEM,
 #endif
@@ -56,6 +62,9 @@
 	ARM_MAP_SHARED_RAM,
 	V2M_MAP_IOFPGA,
 	CSS_MAP_DEVICE,
+#ifdef PLAT_ARM_MEM_PROT_ADDR
+	ARM_V2M_MAP_MEM_PROTECT,
+#endif
 	SOC_CSS_MAP_DEVICE,
 	{0}
 };
diff --git a/plat/arm/board/common/rotpk/arm_rotpk_ecdsa.der b/plat/arm/board/common/rotpk/arm_rotpk_ecdsa.der
new file mode 100644
index 0000000..2547877
--- /dev/null
+++ b/plat/arm/board/common/rotpk/arm_rotpk_ecdsa.der
Binary files differ
diff --git a/plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin b/plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin
new file mode 100644
index 0000000..c5e123a
--- /dev/null
+++ b/plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin
@@ -0,0 +1 @@
+.@¿nù»˜1q	=ýÑÌiJ˜ë‹ ° †Nl
\ No newline at end of file
diff --git a/plat/arm/board/common/rotpk/arm_rotprivk_ecdsa.pem b/plat/arm/board/common/rotpk/arm_rotprivk_ecdsa.pem
new file mode 100644
index 0000000..fb328e3
--- /dev/null
+++ b/plat/arm/board/common/rotpk/arm_rotprivk_ecdsa.pem
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEINSaX6nvzS3teiBJA7WlTLRKJOajpy29o2cArLbUXoZBoAoGCCqGSM49
+AwEHoUQDQgAEm+ZIvTQ44aKk83DhVLsvsFpKDP/Ch9vA+4Hp+fmVfX6gDH8K1OBi
+SpRf7FJ9RGPIn2H6xst+a1OtLMWUDRqGkQ==
+-----END EC PRIVATE KEY-----
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index e869f5b..7015ac0 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -79,6 +79,9 @@
 	MAP_DEVICE0,
 	MAP_DEVICE1,
 	ARM_MAP_NS_DRAM1,
+#ifdef AARCH64
+	ARM_MAP_DRAM2,
+#endif
 #ifdef SPD_tspd
 	ARM_MAP_TSP_SEC_MEM,
 #endif
@@ -109,6 +112,7 @@
 	V2M_MAP_IOFPGA,
 	MAP_DEVICE0,
 	MAP_DEVICE1,
+	ARM_V2M_MAP_MEM_PROTECT,
 	{0}
 };
 #endif
diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c
index 9a02089..dad3a79 100644
--- a/plat/arm/board/fvp/fvp_pm.c
+++ b/plat/arm/board/fvp/fvp_pm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -324,5 +324,14 @@
 	.system_reset = fvp_system_reset,
 	.validate_power_state = arm_validate_power_state,
 	.validate_ns_entrypoint = arm_validate_ns_entrypoint,
-	.get_node_hw_state = fvp_node_hw_state
+	.get_node_hw_state = fvp_node_hw_state,
+/*
+ * mem_protect is not supported in RESET_TO_BL31 and RESET_TO_SP_MIN,
+ * as that would require mapping in all of NS DRAM into BL31 or BL32.
+ */
+#if !RESET_TO_BL31 && !RESET_TO_SP_MIN
+	.mem_protect_chk	= arm_psci_mem_protect_chk,
+	.read_mem_protect	= arm_psci_read_mem_protect,
+	.write_mem_protect	= arm_nor_psci_write_mem_protect,
+#endif
 };
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index bf038e9..e4f9425 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -11,7 +11,7 @@
 #include <board_arm_def.h>
 #include <common_def.h>
 #include <tzc400.h>
-#include <utils.h>
+#include <utils_def.h>
 #include <v2m_def.h>
 #include "../fvp_def.h"
 
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 6d8aa5f..29da12e 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -48,7 +48,8 @@
 
 # Choose the GIC sources depending upon the how the FVP will be invoked
 ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV3)
-FVP_GIC_SOURCES		:=	${FVP_GICV3_SOURCES}
+FVP_GIC_SOURCES		:=	${FVP_GICV3_SOURCES}			\
+				drivers/arm/gic/v3/gic500.c
 else ifeq (${FVP_USE_GIC_DRIVER},FVP_GIC600)
 FVP_GIC_SOURCES		:=	${FVP_GICV3_SOURCES}			\
 				drivers/arm/gic/v3/gic600.c
diff --git a/plat/arm/board/fvp/sp_min/sp_min-fvp.mk b/plat/arm/board/fvp/sp_min/sp_min-fvp.mk
index 864df1b..b370fd5 100644
--- a/plat/arm/board/fvp/sp_min/sp_min-fvp.mk
+++ b/plat/arm/board/fvp/sp_min/sp_min-fvp.mk
@@ -5,11 +5,14 @@
 #
 
 # SP_MIN source files specific to FVP platform
-BL32_SOURCES		+=	plat/arm/board/fvp/aarch32/fvp_helpers.S	\
+BL32_SOURCES		+=	lib/utils/mem_region.c				\
+				plat/arm/board/fvp/aarch32/fvp_helpers.S	\
 				plat/arm/board/fvp/drivers/pwrc/fvp_pwrc.c	\
 				plat/arm/board/fvp/fvp_pm.c			\
 				plat/arm/board/fvp/fvp_topology.c		\
 				plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c	\
+				plat/arm/board/common/drivers/norflash/norflash.c	\
+				plat/arm/common/arm_nor_psci_mem_protect.c	\
 				${FVP_CPU_LIBS}					\
 				${FVP_GIC_SOURCES}				\
 				${FVP_INTERCONNECT_SOURCES}			\
diff --git a/plat/arm/board/fvp/tsp/tsp-fvp.mk b/plat/arm/board/fvp/tsp/tsp-fvp.mk
index 880072c..861fe72 100644
--- a/plat/arm/board/fvp/tsp/tsp-fvp.mk
+++ b/plat/arm/board/fvp/tsp/tsp-fvp.mk
@@ -1,12 +1,13 @@
 #
-# Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
 # TSP source files specific to FVP platform
-BL32_SOURCES		+=	plat/arm/board/fvp/fvp_topology.c		\
+BL32_SOURCES		+=	plat/arm/board/fvp/aarch64/fvp_helpers.S	\
 				plat/arm/board/fvp/drivers/pwrc/fvp_pwrc.c	\
+				plat/arm/board/fvp/fvp_topology.c		\
 				plat/arm/board/fvp/tsp/fvp_tsp_setup.c		\
 				${FVP_GIC_SOURCES}
 
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index f1714e1..3c44a1e 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -68,11 +68,11 @@
 
 #ifdef IMAGE_BL2
 #ifdef SPD_opteed
-# define PLAT_ARM_MMAP_ENTRIES		9
-# define MAX_XLAT_TABLES		4
+# define PLAT_ARM_MMAP_ENTRIES		11
+# define MAX_XLAT_TABLES		5
 #else
-# define PLAT_ARM_MMAP_ENTRIES		8
-# define MAX_XLAT_TABLES		3
+# define PLAT_ARM_MMAP_ENTRIES		10
+# define MAX_XLAT_TABLES		4
 #endif
 #endif
 
@@ -82,8 +82,8 @@
 #endif
 
 #ifdef IMAGE_BL31
-#  define PLAT_ARM_MMAP_ENTRIES		5
-#  define MAX_XLAT_TABLES		2
+#  define PLAT_ARM_MMAP_ENTRIES		7
+#  define MAX_XLAT_TABLES		3
 #endif
 
 #ifdef IMAGE_BL32
@@ -96,7 +96,7 @@
  * plus a little space for growth.
  */
 #if TRUSTED_BOARD_BOOT
-# define PLAT_ARM_MAX_BL1_RW_SIZE	0x9000
+# define PLAT_ARM_MAX_BL1_RW_SIZE	0xA000
 #else
 # define PLAT_ARM_MAX_BL1_RW_SIZE	0x6000
 #endif
@@ -106,7 +106,7 @@
  * little space for growth.
  */
 #if TRUSTED_BOARD_BOOT
-# define PLAT_ARM_MAX_BL2_SIZE		0x18000
+# define PLAT_ARM_MAX_BL2_SIZE		0x19000
 #else
 # define PLAT_ARM_MAX_BL2_SIZE		0xC000
 #endif
@@ -114,8 +114,12 @@
 /*
  * PLAT_ARM_MAX_BL31_SIZE is calculated using the current BL31 debug size plus a
  * little space for growth.
+ * SCP_BL2 image is loaded into the space BL31 -> BL1_RW_BASE.
+ * For TBB use case, PLAT_ARM_MAX_BL1_RW_SIZE has been increased and therefore
+ * PLAT_ARM_MAX_BL31_SIZE has been increased to ensure SCP_BL2 has the same
+ * space available.
  */
-#define PLAT_ARM_MAX_BL31_SIZE		0x1D000
+#define PLAT_ARM_MAX_BL31_SIZE		0x1E000
 
 /*
  * Since free SRAM space is scant, enable the ASSERTION message size
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index 79916cd..5cd125b 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -91,6 +91,3 @@
 include plat/arm/soc/common/soc_css.mk
 include plat/arm/css/common/css_common.mk
 
-ifeq (${KEY_ALG},ecdsa)
-    $(error "ECDSA key algorithm is not fully supported on Juno.")
-endif
diff --git a/plat/arm/board/juno/sp_min/sp_min-juno.mk b/plat/arm/board/juno/sp_min/sp_min-juno.mk
index 336c4e7..cd1f497 100644
--- a/plat/arm/board/juno/sp_min/sp_min-juno.mk
+++ b/plat/arm/board/juno/sp_min/sp_min-juno.mk
@@ -8,7 +8,10 @@
 BL32_SOURCES	+=	lib/cpus/aarch32/cortex_a53.S		\
 			lib/cpus/aarch32/cortex_a57.S		\
 			lib/cpus/aarch32/cortex_a72.S		\
+			lib/utils/mem_region.c			\
+			plat/arm/board/common/drivers/norflash/norflash.c	\
 			plat/arm/board/juno/juno_topology.c	\
+			plat/arm/common/arm_nor_psci_mem_protect.c	\
 			plat/arm/soc/common/soc_css_security.c	\
 			${JUNO_GIC_SOURCES}			\
 			${JUNO_INTERCONNECT_SOURCES}		\
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index cab6113..5d83118 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -193,6 +193,10 @@
 {
 	/* Initialize the secure environment */
 	plat_arm_security_setup();
+
+#if defined(PLAT_ARM_MEM_PROT_ADDR)
+	arm_nor_psci_do_mem_protect();
+#endif
 }
 
 void bl2_platform_setup(void)
diff --git a/plat/arm/common/arm_nor_psci_mem_protect.c b/plat/arm/common/arm_nor_psci_mem_protect.c
new file mode 100644
index 0000000..c5263fd
--- /dev/null
+++ b/plat/arm/common/arm_nor_psci_mem_protect.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <mmio.h>
+#include <norflash.h>
+#include <plat_arm.h>
+#include <platform_def.h>
+#include <psci.h>
+#include <utils.h>
+
+mem_region_t arm_ram_ranges[] = {
+	{ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_SIZE},
+#ifdef AARCH64
+	{ARM_DRAM2_BASE, ARM_DRAM2_SIZE},
+#endif
+};
+
+/*******************************************************************************
+ * Function that reads the content of the memory protect variable that
+ * enables clearing of non secure memory when system boots. This variable
+ * should be stored in a secure NVRAM.
+ ******************************************************************************/
+int arm_psci_read_mem_protect(int *enabled)
+{
+	int tmp;
+
+	tmp = *(int *) PLAT_ARM_MEM_PROT_ADDR;
+	*enabled = (tmp == 1);
+	return 0;
+}
+
+/*******************************************************************************
+ * Function that writes the content of the memory protect variable that
+ * enables overwritten of non secure memory when system boots.
+ ******************************************************************************/
+int arm_nor_psci_write_mem_protect(int val)
+{
+	int enable = (val != 0);
+
+	if (nor_unlock(PLAT_ARM_MEM_PROT_ADDR) != 0) {
+		ERROR("unlocking memory protect variable\n");
+		return -1;
+	}
+
+	if (enable) {
+		/*
+		 * If we want to write a value different than 0
+		 * then we have to erase the full block because
+		 * otherwise we cannot ensure that the value programmed
+		 * into the flash is going to be the same than the value
+		 * requested by the caller
+		 */
+		if (nor_erase(PLAT_ARM_MEM_PROT_ADDR) != 0) {
+			ERROR("erasing block containing memory protect variable\n");
+			return -1;
+		}
+	}
+
+	if (nor_word_program(PLAT_ARM_MEM_PROT_ADDR, enable) != 0) {
+		ERROR("programming memory protection variable\n");
+		return -1;
+	}
+	return 0;
+}
+
+/*******************************************************************************
+ * Function used for required psci operations performed when
+ * system boots
+ ******************************************************************************/
+void arm_nor_psci_do_mem_protect(void)
+{
+	int enable;
+
+	arm_psci_read_mem_protect(&enable);
+	if (!enable)
+		return;
+	INFO("PSCI: Overwritting non secure memory\n");
+	clear_mem_regions(arm_ram_ranges, ARRAY_SIZE(arm_ram_ranges));
+	arm_nor_psci_write_mem_protect(0);
+}
+
+/*******************************************************************************
+ * Function that checks if a region is protected by the memory protect
+ * mechanism
+ ******************************************************************************/
+int arm_psci_mem_protect_chk(uintptr_t base, u_register_t length)
+{
+	return mem_region_in_array_chk(arm_ram_ranges,
+				       ARRAY_SIZE(arm_ram_ranges),
+				       base, length);
+}
diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c
index e0e5200..93d51fe 100644
--- a/plat/arm/css/common/css_pm.c
+++ b/plat/arm/css/common/css_pm.c
@@ -290,5 +290,14 @@
 	.validate_ns_entrypoint = arm_validate_ns_entrypoint,
 	.translate_power_state_by_mpidr = css_translate_power_state_by_mpidr,
 	.get_node_hw_state	= css_node_hw_state,
-	.get_sys_suspend_power_state = css_get_sys_suspend_power_state
+	.get_sys_suspend_power_state = css_get_sys_suspend_power_state,
+/*
+ * mem_protect is not supported in RESET_TO_BL31 and RESET_TO_SP_MIN,
+ * as that would require mapping in all of NS DRAM into BL31 or BL32.
+ */
+#if defined(PLAT_ARM_MEM_PROT_ADDR) && !RESET_TO_BL31 && !RESET_TO_SP_MIN
+	.mem_protect_chk	= arm_psci_mem_protect_chk,
+	.read_mem_protect	= arm_psci_read_mem_protect,
+	.write_mem_protect	= arm_nor_psci_write_mem_protect,
+#endif
 };
diff --git a/plat/common/plat_log_common.c b/plat/common/plat_log_common.c
new file mode 100644
index 0000000..30dcb12
--- /dev/null
+++ b/plat/common/plat_log_common.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <platform.h>
+
+/* Allow platforms to override the log prefix string */
+#pragma weak plat_log_get_prefix
+
+static const char *prefix_str[] = {
+	"ERROR:   ", "NOTICE:  ", "WARNING: ", "INFO:    ", "VERBOSE: "};
+
+const char *plat_log_get_prefix(unsigned int log_level)
+{
+	if (log_level < LOG_LEVEL_ERROR)
+		log_level = LOG_LEVEL_ERROR;
+	else if (log_level > LOG_LEVEL_VERBOSE)
+		log_level = LOG_LEVEL_VERBOSE;
+
+	return prefix_str[(log_level/10) - 1];
+}
diff --git a/plat/nvidia/tegra/common/tegra_gic.c b/plat/nvidia/tegra/common/tegra_gic.c
index e480e77..3ace554 100644
--- a/plat/nvidia/tegra/common/tegra_gic.c
+++ b/plat/nvidia/tegra/common/tegra_gic.c
@@ -237,10 +237,10 @@
 
 	id = gicc_read_hppir(TEGRA_GICC_BASE) & INT_ID_MASK;
 
-	if (id < 1022UL) {
+	if (id < 1022U) {
 		ret = id;
-	} else if (id == 1023UL) {
-		ret = 0xFFFFFFFFUL; /* INTR_ID_UNAVAILABLE */
+	} else if (id == 1023U) {
+		ret = 0xFFFFFFFFU; /* INTR_ID_UNAVAILABLE */
 	} else {
 		/*
 		 * Find out which non-secure interrupt it is under the assumption that
diff --git a/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c b/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c
index d34f7e2..7eb6c6c 100644
--- a/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c
+++ b/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c
@@ -435,7 +435,7 @@
 
 	ret = ari_request_wait(ari_base, 0U, TEGRA_ARI_MCA,
 			       (uint32_t)mca_arg_data,
-			       (uint32_t)(mca_arg_data >> 32UL));
+			       (uint32_t)(mca_arg_data >> 32U));
 	if (ret == 0) {
 		resp_lo = ari_get_response_low(ari_base);
 		resp_hi = ari_get_response_high(ari_base);
@@ -450,7 +450,7 @@
 			if (data != NULL) {
 				resp_lo = ari_get_request_low(ari_base);
 				resp_hi = ari_get_request_high(ari_base);
-				*data = ((uint64_t)resp_hi << 32UL) |
+				*data = ((uint64_t)resp_hi << 32U) |
 					 (uint64_t)resp_lo;
 			}
 		}
@@ -513,7 +513,7 @@
 		 * to the uncore perfmon registers
 		 */
 		val = (req_cmd == UNCORE_PERFMON_CMD_WRITE) ?
-			(uint32_t)*data : 0UL;
+			(uint32_t)*data : 0U;
 
 		ret = ari_request_wait(ari_base, 0U, TEGRA_ARI_PERFMON, val,
 				       (uint32_t)req);
diff --git a/plat/socionext/uniphier/platform.mk b/plat/socionext/uniphier/platform.mk
index 72792f8..e6f510e 100644
--- a/plat/socionext/uniphier/platform.mk
+++ b/plat/socionext/uniphier/platform.mk
@@ -21,6 +21,9 @@
 $(eval $(call add_define,UNIPHIER_LOAD_BL32))
 endif
 
+# Libraries
+include lib/xlat_tables_v2/xlat_tables.mk
+
 PLAT_PATH		:=	plat/socionext/uniphier
 PLAT_INCLUDES		:=	-I$(PLAT_PATH)/include
 
@@ -37,12 +40,11 @@
 
 # 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_internal.c \
 				$(PLAT_PATH)/uniphier_console.S		\
 				$(PLAT_PATH)/uniphier_helpers.S		\
 				$(PLAT_PATH)/uniphier_soc_info.c	\
-				$(PLAT_PATH)/uniphier_xlat_setup.c
+				$(PLAT_PATH)/uniphier_xlat_setup.c	\
+				${XLAT_TABLES_LIB_SRCS}
 
 BL1_SOURCES		+=	lib/cpus/aarch64/cortex_a53.S		\
 				lib/cpus/aarch64/cortex_a72.S		\
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
index b533345..af7b252 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
@@ -85,8 +85,8 @@
 				 unsigned int mask,
 				 unsigned int value);
 enum pm_ret_status pm_mmio_read(uintptr_t address, unsigned int *value);
-enum pm_ret_status pm_fpga_load(uint32_t address_high,
-				uint32_t address_low,
+enum pm_ret_status pm_fpga_load(uint32_t address_low,
+				uint32_t address_high,
 				uint32_t size,
 				uint32_t flags);
 enum pm_ret_status pm_fpga_get_status(unsigned int *value);
diff --git a/tools/cert_create/src/key.c b/tools/cert_create/src/key.c
index c1bde5d..e8257e9 100644
--- a/tools/cert_create/src/key.c
+++ b/tools/cert_create/src/key.c
@@ -91,9 +91,10 @@
 
 typedef int (*key_create_fn_t)(key_t *key);
 static const key_create_fn_t key_create_fn[KEY_ALG_MAX_NUM] = {
-	key_create_rsa,
+	key_create_rsa, 	/* KEY_ALG_RSA */
+	key_create_rsa, 	/* KEY_ALG_RSA_1_5 */
 #ifndef OPENSSL_NO_EC
-	key_create_ecdsa,
+	key_create_ecdsa, 	/* KEY_ALG_ECDSA */
 #endif /* OPENSSL_NO_EC */
 };