Merge "docs/fvp: update SGI and RD FVP list" into integration
diff --git a/docs/components/index.rst b/docs/components/index.rst
index b4d8c14..ffeef80 100644
--- a/docs/components/index.rst
+++ b/docs/components/index.rst
@@ -17,7 +17,8 @@
    ras
    romlib-design
    sdei
-   secure-partition-manager-design
+   secure-partition-manager
+   secure-partition-manager-mm
    psa-ffa-manifest-binding
    xlat-tables-lib-v2-design
    cot-binding
diff --git a/docs/components/secure-partition-manager-design.rst b/docs/components/secure-partition-manager-mm.rst
similarity index 97%
rename from docs/components/secure-partition-manager-design.rst
rename to docs/components/secure-partition-manager-mm.rst
index 4f67185..87fc91d 100644
--- a/docs/components/secure-partition-manager-design.rst
+++ b/docs/components/secure-partition-manager-mm.rst
@@ -1,5 +1,22 @@
-Secure Partition Manager
-************************
+Secure Partition Manager (MM)
+*****************************
+
+Foreword
+========
+
+Two implementations of a Secure Partition Manager co-exist in the TF-A codebase:
+
+-  SPM based on the PSA FF-A specification (`Secure Partition Manager`__).
+-  SPM based on the MM interface.
+
+.. __: secure-partition-manager.html
+
+Both implementations differ in their architectures and only one can be selected
+at build time.
+
+This document describes the latter implementation where the Secure Partition Manager
+resides at EL3 and management services run from isolated Secure Partitions at S-EL0.
+The communication protocol is established through the Management Mode (MM) interface.
 
 Background
 ==========
diff --git a/docs/components/secure-partition-manager.rst b/docs/components/secure-partition-manager.rst
new file mode 100644
index 0000000..2169f30
--- /dev/null
+++ b/docs/components/secure-partition-manager.rst
@@ -0,0 +1,867 @@
+Secure Partition Manager
+************************
+
+.. contents::
+
+Acronyms
+========
+
++--------+-----------------------------------+
+| DTB    | Device Tree Blob                  |
++--------+-----------------------------------+
+| DTS    | Device Tree Source                |
++--------+-----------------------------------+
+| EC     | Execution Context                 |
++--------+-----------------------------------+
+| FIP    | Firmware Image Package            |
++--------+-----------------------------------+
+| FF-A   | Firmware Framework for A-class    |
++--------+-----------------------------------+
+| IPA    | Intermediate Physical Address     |
++--------+-----------------------------------+
+| NWd    | Normal World                      |
++--------+-----------------------------------+
+| ODM    | Original Design Manufacturer      |
++--------+-----------------------------------+
+| OEM    | Original Equipment Manufacturer   |
++--------+-----------------------------------+
+| PA     | Physical Address                  |
++--------+-----------------------------------+
+| PE     | Processing Element                |
++--------+-----------------------------------+
+| PVM    | Primary VM                        |
++--------+-----------------------------------+
+| PSA    | Platform Security Architecture    |
++--------+-----------------------------------+
+| SP     | Secure Partition                  |
++--------+-----------------------------------+
+| SPM    | Secure Partition Manager          |
++--------+-----------------------------------+
+| SPMC   | SPM Core                          |
++--------+-----------------------------------+
+| SPMD   | SPM Dispatcher                    |
++--------+-----------------------------------+
+| SiP    | Silicon Provider                  |
++--------+-----------------------------------+
+| SWd    | Secure World                      |
++--------+-----------------------------------+
+| TLV    | Tag-Length-Value                  |
++--------+-----------------------------------+
+| TOS    | Trusted Operating System          |
++--------+-----------------------------------+
+| VM     | Virtual Machine                   |
++--------+-----------------------------------+
+
+Foreword
+========
+
+Two implementations of a Secure Partition Manager co-exist in the TF-A codebase:
+
+-  SPM based on the PSA FF-A specification `[1]`_.
+-  SPM based on the MM interface to communicate with an S-EL0 partition `[2]`_.
+
+Both implementations differ in their architectures and only one can be selected
+at build time.
+
+This document:
+
+-  describes the PSA FF-A implementation where the Secure Partition Manager
+   resides at EL3 and S-EL2 (or EL3 and S-EL1).
+-  is not an architecture specification and it might provide assumptions
+   on sections mandated as implementation-defined in the specification.
+-  covers the implications to TF-A used as a bootloader, and Hafnium
+   used as a reference code base for an S-EL2 secure firmware on
+   platforms implementing Armv8.4-SecEL2.
+
+Terminology
+-----------
+
+-  Hypervisor refers to the NS-EL2 component managing Virtual Machines (or
+   partitions) in the Normal World.
+-  SPMC refers to the S-EL2 component managing Virtual Machines (or Secure
+   Partitions) in the Secure World when Armv8.4-SecEL2 extension is implemented.
+-  Alternatively, SPMC can refer to an S-EL1 component, itself being a Secure
+   Partition and implementing the FF-A ABI on pre-Armv8.4 platforms.
+-  VM refers to a Normal World Virtual Machine managed by an Hypervisor.
+-  SP refers to a Secure World "Virtual Machine" managed by the SPMC component.
+
+Support for legacy platforms
+----------------------------
+
+In the implementation, the SPM is split into SPMD and SPMC components
+(although not strictly mandated by the specification). SPMD is located
+at EL3 and principally relays FF-A messages from NWd (Hypervisor or OS
+kernel) to SPMC located either at S-EL1 or S-EL2.
+
+Hence TF-A must support both cases where SPMC is either located at:
+
+-  S-EL1 supporting pre-Armv8.4 platforms. SPMD conveys FF-A protocol
+   from EL3 to S-EL1.
+-  S-EL2 supporting platforms implementing Armv8.4-SecEL2 extension.
+   SPMD conveys FF-A protocol from EL3 to S-EL2.
+
+The same SPMD component is used to support both configurations. The SPMC
+execution level is a build time choice.
+
+Sample reference stack
+======================
+
+The following diagram illustrates a possible configuration with SPMD and SPMC,
+one or multiple Secure Partitions, with or without an optional Hypervisor:
+
+.. image:: ../resources/diagrams/ff-a-spm-sel2.png
+
+TF-A build options
+==================
+
+The following TF-A build options are provisioned:
+
+-  **SPD=spmd**: this option selects the SPMD component to relay FF-A
+   protocol from NWd to SWd back and forth. It is not possible to
+   enable another Secure Payload Dispatcher when this option is chosen.
+-  **SPMD_SPM_AT_SEL2**: this option adjusts the SPMC execution
+   level to being S-EL1 or S-EL2. It defaults to enabled (value 1) when
+   SPD=spmd is chosen.
+-  **CTX_INCLUDE_EL2_REGS**: this option permits saving (resp.
+   restoring) the EL2 system register context before entering (resp.
+   after leaving) the SPMC. It is mandatory when ``SPMD_SPM_AT_SEL2`` is
+   enabled. The context save/restore routine and exhaustive list of
+   registers is visible at `[4] <#References>`__.
+-  **SP_LAYOUT_FILE**: this option provides a text description file
+   providing paths to SP binary images and DTS format manifests
+   (see `Specifying partition binary image and DT`_). It
+   is required when ``SPMD_SPM_AT_SEL2`` is enabled hence when multiple
+   secure partitions are to be loaded on behalf of SPMC.
+
++------------------------------+----------------------+------------------+
+|                              | CTX_INCLUDE_EL2_REGS | SPMD_SPM_AT_SEL2 |
++------------------------------+----------------------+------------------+
+| SPMC at S-EL1 (e.g. OP-TEE)  |           0          |        0         |
++------------------------------+----------------------+------------------+
+| SPMC at S-EL2 (e.g. Hafnium) |           1          | 1 (default when  |
+|                              |                      |    SPD=spmd)     |
++------------------------------+----------------------+------------------+
+
+Other combinations of such build options either break the build or are not
+supported.
+
+Note, the ``CTX_INCLUDE_EL2_REGS`` option provides the generic support for
+barely saving/restoring EL2 registers from an Arm arch perspective. As such
+it is decoupled from the ``SPD=spmd`` option.
+
+BL32 option is re-purposed to specify the SPMC image. It can specify either the
+Hafnium binary path (built for the secure world) or the path to a TEE binary
+implementing the FF-A protocol.
+
+BL33 option can specify either:
+
+-  the TFTF binary or
+-  the Hafnium binary path (built for the normal world) if VMs were loaded by
+   TF-A beforehand or
+-  a minimal loader performing the loading of VMs and Hafnium.
+
+Sample TF-A build command line when SPMC is located at S-EL1
+(typically pre-Armv8.4):
+
+.. code:: shell
+
+    make \
+    CROSS_COMPILE=aarch64-none-elf- \
+    SPD=spmd \
+    SPMD_SPM_AT_SEL2=0 \
+    BL32=<path-to-tee-binary> \
+    BL33=<path-to-nwd-binary> \
+    PLAT=fvp \
+    all fip
+
+Sample TF-A build command line for an Armv8.4-SecEL2 enabled system
+where SPMC is located at S-EL2:
+
+.. code:: shell
+
+    make \
+    CROSS_COMPILE=aarch64-none-elf- \
+    SPD=spmd \
+    CTX_INCLUDE_EL2_REGS=1 \
+    ARM_ARCH_MINOR=4 \
+    BL32=<path-to-swd-hafnium-binary>
+    BL33=<path-to-nwd-binary> \
+    SP_LAYOUT_FILE=sp_layout.json \
+    PLAT=fvp \
+    all fip
+
+Build options to enable secure boot:
+
+.. code:: shell
+
+    make \
+    CROSS_COMPILE=aarch64-none-elf- \
+    SPD=spmd \
+    CTX_INCLUDE_EL2_REGS=1 \
+    ARM_ARCH_MINOR=4 \
+    BL32=<path-to-swd-hafnium-binary>
+    BL33=<path-to-nwd-binary> \
+    SP_LAYOUT_FILE=../tf-a-tests/build/fvp/debug/sp_layout.json \
+    MBEDTLS_DIR=<path-to-mbedtls-lib> \
+    TRUSTED_BOARD_BOOT=1 \
+    COT=dualroot \
+    ARM_ROTPK_LOCATION=devel_rsa \
+    ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \
+    GENERATE_COT=1 \
+    PLAT=fvp \
+    all fip
+
+Boot process
+============
+
+Loading Hafnium and Secure Partitions in the secure world
+---------------------------------------------------------
+
+The Hafnium implementation in normal world requires VMs to be loaded in
+memory prior to booting. The mechanism upon which VMs are loaded and
+exposed to Hafnium are either:
+
+-  by supplying a ramdisk image where VM images are concatenated (1)
+-  or by providing VM load addresses within Hafnium manifest (2)
+
+TF-A is the bootlader for the Hafnium and SPs in the secure world. TF-A
+does not provide tooling or libraries manipulating ramdisks as required
+by (1). Thus BL2 loads SPs payloads independently.
+SPs may be signed by different parties (SiP, OEM/ODM, TOS vendor, etc.).
+Thus they are supplied as distinct “self-contained” signed entities within
+the FIP flash image. The FIP image itself is not signed hence providing
+ability to upgrade SPs in the field.
+
+Booting through TF-A
+--------------------
+
+SP manifests
+~~~~~~~~~~~~
+
+An SP manifest describes SP attributes as defined in `[1]`_
+section 3.1 (partition manifest at virtual FF-A instance) in DTS text format. It
+is represented as a single file associated with the SP. A sample is
+provided by `[5]`_. A binding document is provided by `[6]`_.
+
+Secure Partition packages
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Secure Partitions are bundled as independent package files consisting
+of:
+
+-  a header
+-  a DTB
+-  an image payload
+
+The header starts with a magic value and offset values to SP DTB and
+image payload. Each SP package is loaded independently by BL2 loader
+and verified for authenticity and integrity.
+
+The SP package identified by its UUID (matching FF-A uuid) is inserted
+as a single entry into the FIP at end of the TF-A build flow as shown:
+
+.. code:: shell
+
+    Trusted Boot Firmware BL2: offset=0x1F0, size=0x8AE1, cmdline="--tb-fw"
+    EL3 Runtime Firmware BL31: offset=0x8CD1, size=0x13000, cmdline="--soc-fw"
+    Secure Payload BL32 (Trusted OS): offset=0x1BCD1, size=0x15270, cmdline="--tos-fw"
+    Non-Trusted Firmware BL33: offset=0x30F41, size=0x92E0, cmdline="--nt-fw"
+    HW_CONFIG: offset=0x3A221, size=0x2348, cmdline="--hw-config"
+    TB_FW_CONFIG: offset=0x3C569, size=0x37A, cmdline="--tb-fw-config"
+    SOC_FW_CONFIG: offset=0x3C8E3, size=0x48, cmdline="--soc-fw-config"
+    TOS_FW_CONFIG: offset=0x3C92B, size=0x427, cmdline="--tos-fw-config"
+    NT_FW_CONFIG: offset=0x3CD52, size=0x48, cmdline="--nt-fw-config"
+    B4B5671E-4A90-4FE1-B81F-FB13DAE1DACB: offset=0x3CD9A, size=0xC168, cmdline="--blob"
+    D1582309-F023-47B9-827C-4464F5578FC8: offset=0x48F02, size=0xC168, cmdline="--blob"
+
+.. uml:: ../resources/diagrams/plantuml/fip-secure-partitions.puml
+
+Specifying partition binary image and DT
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A description file (json format) is passed to the build flow specifying
+paths to the SP binary image and associated DTS partition manifest file.
+The latter is going through the dtc compiler to generate the dtb fed into
+the SP package.
+
+.. code:: shell
+
+    {
+        "tee1" : {
+            "image": "tee1.bin",
+             "pm": "tee1.dts"
+        },
+
+        "tee2" : {
+            "image": "tee2.bin",
+            "pm": "tee2.dts"
+        }
+    }
+
+SPMC manifest
+~~~~~~~~~~~~~
+
+This manifest contains an SPMC attributes node consumed by SPMD at boot time. It
+is implementing the description from `[1]`_ section 3.2 (SP manifest at physical
+FF-A instance). The SP manifest at physical FF-A instance is used by the SPMD to
+setup a SP that co-resides with the SPMC and executes at S-EL1 or Secure
+Supervisor mode.
+
+In this implementation its usage is extended to the secure physical FF-A
+instance where SPMC executes at S-EL2.
+
+.. code:: shell
+
+    attribute {
+        spmc_id = <0x8000>;
+        maj_ver = <0x1>;
+        min_ver = <0x0>;
+        exec_state = <0x0>;
+        load_address = <0x0 0x6000000>;
+        entrypoint = <0x0 0x6000000>;
+        binary_size = <0x60000>;
+    };
+
+-  *spmc_id* defines the endpoint ID value that SPMC can query through
+   ``FFA_ID_GET``.
+-  *maj_ver/min_ver*. SPMD checks provided version versus its internal
+   version and aborts if not matching.
+-  *exec_state* defines SPMC execution state (can be AArch64 for
+   Hafnium, or AArch64/AArch32 for OP-TEE at S-EL1).
+-  *load_address* and *binary_size* are mostly used to verify secondary
+   entry points fit into the loaded binary image.
+-  *entrypoint* defines the cold boot primary core entry point used by
+   SPMD (currently matches ``BL32_BASE``)
+
+Other nodes in the manifest are consumed by Hafnium in the secure world.
+A sample can be found at [7]:
+
+-  The *chosen* node is currently unused in SWd. It is meant for NWd to
+   specify the init ramdisk image.
+-  The *hypervisor* node describes SPs. *is_ffa_partition* boolean
+   attribute indicates an SP. Load-addr field specifies the load address
+   at which TF-A loaded the SP package.
+-  *cpus* node provide the platform topology and allows MPIDR to VMPIDR
+   mapping. Notice with current implementation primary cpu is declared
+   first, then secondary cpus must be declared in reverse order.
+
+SPMC boot
+~~~~~~~~~
+
+The SPMC is loaded by BL2 as the BL32 image.
+
+The SPMC manifest is loaded by BL2 as the ``TOS_FW_CONFIG`` image.
+
+BL2 passes the SPMC manifest address to BL31 through a register.
+
+BL31(SPMD) runs from primary core, initializes the core contexts and
+launches BL32 passing the SPMC manifest address through a register.
+
+Loading of SPs
+~~~~~~~~~~~~~~
+
+.. uml:: ../resources/diagrams/plantuml/bl2-loading-sp.puml
+
+
+Notice this boot flow is an implementation sample on Arm's FVP platform. Platforms
+not using FW_CONFIG would adjust to a different implementation.
+
+Secure boot
+~~~~~~~~~~~
+
+The SP content certificate is inserted as a separate FIP item so that BL2 loads SPMC,
+SPMC manifest and Secure Partitions and verifies them for authenticity and integrity.
+Refer to TBBR specification `[3]`_.
+
+The multiple-signing domain feature (in current state dual signing domain) allows
+the use of two root keys namely S-ROTPK and NS-ROTPK (see `[8]`_):
+
+-  SPMC(BL32), SPMC manifest, SPs may be signed by the SiP using the S-ROTPK.
+-  BL33 may be signed by the OEM using NS-ROTPK.
+
+Longer term multiple signing domain will allow additional signing keys, e.g.
+if SPs originate from different parties.
+
+See `TF-A build options`_ for a sample build command line.
+
+Hafnium in the secure world
+===========================
+
+**NOTE: this section is work in progress. Descriptions and implementation choices
+are subject to evolve.**
+
+General considerations
+----------------------
+
+Build platform for the secure world
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The implementation might add specific code parts only relevant to the
+secure world. Such code parts might be isolated into different files
+and/or conditional code enclosed by a ``SECURE_WORLD`` macro.
+
+Secure Partitions CPU scheduling
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In the normal world, VMs are scheduled by the FFA_RUN ABI invoked from the
+primary scheduler (in the primary VM), or by a direct message request or
+response.
+
+With the FF-A EAC specification, Secure Partitions are scheduled by direct
+message invocations from a NWd VM or another SP.
+
+Platform topology
+~~~~~~~~~~~~~~~~~
+
+As stated in `[1]`_ section 4.4.1 the SPMC implementation assumes the
+following SP types:
+
+-  Pinned MP SPs: an Execution Context id matches a physical PE id. MP
+   SPs must implement the same number of ECs as the number of PEs in the
+   platform. Hence the *execution-ctx-count* as defined by
+   `[1]`_ (or NWd-Hafnium *vcpu_count*) can only take the
+   value of one or the number of physical PEs.
+-  Migratable UP SPs: a single execution context can run and be migrated
+   on any physical PE. It declares a single EC in its SP manifest. An UP
+   SP can receive a direct message request on any physical core.
+
+Usage of PSCI services in the secure world
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- The normal world Hypervisor (optional) or OS kernel issues PSCI service
+  invocations e.g. to request PSCI version, wake-up a secondary core, or request
+  core suspend. This happens at the non-secure physical FF-A instance. In the
+  example case of Hafnium in the normal world, it boots on the primary core and
+  one of the first initialization step is to request the PSCI version. It then
+  launches the primary VM. The primary VM upon initializing performs PSCI service
+  calls (at non-secure virtual FF-A instance) which are trapped by the
+  Hypervisor. Invocation from OS Kernel ends straight at EL3. The PVM issues
+  ``PSCI_CPU_ON`` service calls to wake-up secondary cores by passing an
+  ``MPIDR``, entry point address and a CPU context address. The EL3 PSCI layer
+  then performs an exception return to the secondary core entry point on the
+  targeted core. Other PSCI calls can happen at run-time from the PVM e.g. to
+  request core suspend.
+- In the existing TF-A PSCI standard library, PSCI service calls are filtered at
+  EL3 to only originate from the NWd. Thus concerning the SPMC (at secure
+  physical FF-A instance) the PSCI service invocations cannot happen as in the
+  normal world. For example, a ``PSCI_CPU_ON`` service invocation from the SPMC
+  does not reach the PSCI layer.
+
+Parsing SP partition manifests
+------------------------------
+
+Hafnium must be able to consume SP manifests as defined in
+`[1]`_ section 3.1, at least for the mandatory fields.
+
+The SP manifest may contain memory and device regions nodes.
+
+-  Memory regions shall be mapped in the SP Stage-2 translation regime at
+   load time. A memory region node can specify RX/TX buffer regions in which
+   case it is not necessary for an SP to explicitly call the ``FFA_RXTX_MAP``
+   service.
+-  Device regions shall be mapped in SP Stage-2 translation regime as
+   peripherals and possibly allocate additional resources (e.g. interrupts)
+
+Base addresses for memory and device region nodes are IPAs provided SPMC
+identity maps IPAs to PAs within SP Stage-2 translation regime.
+
+Note: currently both VTTBR_EL2 and VSTTBR_EL2 resolve to the same set of page
+tables. It is still open whether two sets of page tables shall be provided per
+SP. The memory region node as defined in the spec (section 3.1 Table 10)
+provides a memory security attribute hinting to map either to the secure or
+non-secure stage-2 table.
+
+Passing boot data to the SP
+---------------------------
+
+`[1]`_ Section 3.4.2 “Protocol for passing data” defines a
+method to passing boot data to SPs (not currently implemented).
+
+Provided that the whole Secure Partition package image (see `Secure
+Partition packages`_) is mapped to the SP's secure Stage-2 translation
+regime, an SP can access its own manifest DTB blob and extract its partition
+manifest properties.
+
+SP Boot order
+-------------
+
+SP manifests provide an optional boot order attribute meant to resolve
+dependencies such as an SP providing a service required to properly boot
+another SP.
+
+Boot phases
+-----------
+
+Primary core boot-up
+~~~~~~~~~~~~~~~~~~~~
+
+The SPMC performs its platform initializations then loads and creates
+secure partitions based on SP packages and manifests. Then each secure
+partition is launched in sequence (see `SP Boot order`_) on their primary
+Execution Context.
+
+Notice the primary physical core may not be core 0. Hence if the primary
+core linear id is N, the 1:1 mapping requires MP SPs are launched using
+EC[N] on PE[N] (see `Platform topology`_).
+
+The SP's primary Execution Context (or the EC used when the partition is booted)
+exits through ``FFA_MSG_WAIT`` to indicate successful initialization.
+
+Secondary physical core boot-up
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Upon boot-up, the SPMC running on the primary core performs
+implementation-defined SPMD service calls at secure physical FF-A instance
+to register the secondary physical cores entry points and context information:
+
+-  This is done through a direct message request invocation to the SPMD
+   (``SET_ENTRY_POINT``). This service call does not wake-up the targeted
+   core immediately. The secondary core is woken up later by a NWd
+   ``PSCI_CPU_ON`` service invocation. A notification is passed from EL3
+   PSCI layer to the SPMD, and then to SPMC through an implementation-defined
+   interface.
+-  The SPMC/SPMD interface can consist of FF-A direct message requests/responses
+   transporting PM events.
+
+If there is no Hypervisor in the normal world, the OS Kernel issues
+``PSCI_CPU_ON`` calls that are directly trapped to EL3.
+
+When a secondary physical core wakes-up the SPMD notifies the SPMC which updates
+its internal states reflecting current physical core is being turned on.
+It might then return straight to the SPMD and then to the NWd.
+
+*(under discussion)* There may be possibility that an SP registers "PM events"
+(during primary EC boot stage) through an ad-hoc interface. Such events would
+be relayed by SPMC to one or more registered SPs on need basis
+(see `Power management`_).
+
+Secondary virtual core boot-up
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In the example case where Hafnium exists in the normal world, secondary VMs
+issue a ``PSCI_CPU_ON`` service call which is trapped to the Hypervisor. The
+latter then enables the vCPU context for the targeted core, and switches to
+the PVM down to the kernel driver with an ``HF_WAKE_UP`` message. The NWd
+driver in PVM can then schedule the newly woken up vCPU context.
+
+In the secure world the primary EC of a given SP passes the secondary EC entry
+point and context. The SMC service call is trapped into the SPMC. This can be
+either *(under discussion)*:
+
+-  a specific interface registering the secondary EC entry point,
+   similarly to above ``SET_ENTRY_POINT`` service.
+-  Re-purposing the ``PSCI_CPU_ON`` function id. It is
+   assumed that even if the input arguments are the same as the ones defined in
+   the PSCI standard, the usage deviates by the fact the secondary EC is not
+   woken up immediately. At least for the PSA-FF-A EAC where only
+   direct messaging is allowed, it is only after the first direct
+   message invocation that the secondary EC is entered. This option
+   might be preferred when the same code base is re-used for a VM or
+   an SP. The ABI to wake-up a secondary EC can remain similar.
+
+SPs are always scheduled from the NWd, this paradigm did not change from legacy
+TEEs. There must always be some logic (or driver) in the NWd to relinquish CPU
+cycles to the SWd. If primary core is 0, an SP EC[x>0] entry point is supplied
+by the SP EC[0] when the system boots in SWd. But this EC[x] is not immediately
+entered at boot. Later in the boot process when NWd is up, a direct message
+request issued from physical core 1 ends up in SP EC[1], and only at this stage
+this context is effectively scheduled.
+
+It should be possible for an SP to call into another SP through direct message
+provided the latter SP has been booted already. The "boot-order" field in
+partition manifests (`SP Boot order`_) fulfills the dependency towards availability
+of a service within an SP offered to another SP.
+
+Mandatory interfaces
+--------------------
+
+The following interfaces must be exposed to any VM or SP:
+
+-  ``FFA_STATUS``
+-  ``FFA_ERROR``
+-  ``FFA_INTERRUPT``
+-  ``FFA_VERSION``
+-  ``FFA_FEATURES``
+-  ``FFA_RX_RELEASE``
+-  ``FFA_RXTX_MAP``
+-  ``FFA_RXTX_UNMAP``
+-  ``FFA_PARTITION_INFO_GET``
+-  ``FFA_ID_GET``
+
+FFA_VERSION
+~~~~~~~~~~~
+
+Per `[1]`_ section 8.1 ``FFA_VERSION`` requires a
+*requested_version* parameter from the caller.
+
+In the current implementation when ``FFA_VERSION`` is invoked from:
+
+-  Hypervisor in NS-EL2: the SPMD returns the SPMC version specified
+   in the SPMC manifest.
+-  OS kernel in NS-EL1 when NS-EL2 is not present: the SPMD returns the
+   SPMC version specified in the SPMC manifest.
+-  VM in NWd: the Hypervisor returns its implemented version.
+-  SP in SWd: the SPMC returns its implemented version.
+-  SPMC at S-EL1/S-EL2: the SPMD returns its implemented version.
+
+FFA_FEATURES
+~~~~~~~~~~~~
+
+FF-A features may be discovered by Secure Partitions while booting
+through the SPMC. However, SPMC cannot get features from Hypervisor
+early at boot time as NS world is not setup yet.
+
+The Hypervisor may decide to gather FF-A features from SPMC through SPMD
+once at boot time and store the result. Later when a VM requests FF-A
+features, the Hypervisor can adjust its own set of features with what
+SPMC advertised, if necessary. Another approach is to always forward FF-A
+features to the SPMC when a VM requests it to the Hypervisor. Although
+the result is not supposed to change over time so there may not be added
+value doing the systematic forwarding.
+
+FFA_RXTX_MAP/FFA_RXTX_UNMAP
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+VM mailboxes are re-purposed to serve as SP RX/TX buffers. The RX/TX
+map API maps the send and receive buffer IPAs to the SP Stage-2 translation regime.
+
+Hafnium in the normal world defines VMs and their attributes as logical structures,
+including a mailbox used for FF-A indirect messaging, memory sharing, or the
+`FFA_PARTITION_INFO_GET`_  ABI.
+This same mailbox structure is re-used in the SPMC. `[1]`_ states only direct
+messaging is allowed to SPs. Thus mailbox usage is restricted to implementing
+`FFA_PARTITION_INFO_GET`_ and memory sharing ABIs.
+
+FFA_PARTITION_INFO_GET
+~~~~~~~~~~~~~~~~~~~~~~
+
+Partition info get service call can originate:
+
+-  from SP to SPM
+-  from VM to Hypervisor
+-  from Hypervisor to SPM
+
+For the latter case, the service call must be forwarded through the SPMD.
+
+FFA_ID_GET
+~~~~~~~~~~
+
+The SPMD returns:
+
+-  a default zero value on invocation from the Hypervisor.
+-  The ``spmc_id`` value specified in the SPMC manifest on invocation from
+   the SPMC (see `SPMC manifest`_)
+
+The FF-A id space is split into a non-secure space and secure space:
+
+-  FF-A id with bit 15 clear refer to normal world VMs.
+-  FF-A id with bit 15 set refer to secure world SPs
+
+Such convention helps the SPMC discriminating the origin and destination worlds
+in an FF-A service invocation. In particular the SPMC shall filter unauthorized
+transactions in its world switch routine. It must not be permitted for a VM to
+use a secure FF-A id as origin world through spoofing:
+
+-  A VM-to-SP messaging passing shall have an origin world being non-secure
+   (FF-A id bit 15 clear) and destination world being secure (FF-A id bit 15
+   set).
+-  Similarly, an SP-to-SP message shall have FF-A id bit 15 set for both origin
+   and destination ids.
+
+An incoming direct message request arriving at SPMD from NWd is forwarded to
+SPMC without a specific check. The SPMC is resumed through eret and "knows" the
+message is coming from normal world in this specific code path. Thus the origin
+endpoint id must be checked by SPMC for being a normal world id.
+
+An SP sending a direct message request must have bit 15 set in its origin
+endpoint id and this can be checked by the SPMC when the SP invokes the ABI.
+
+The SPMC shall reject the direct message if the claimed world in origin endpoint
+id is not consistent:
+
+-  It is either forwarded by SPMD and thus origin endpoint id must be a "normal
+   world id",
+-  or initiated by an SP and thus origin endpoint id must be a "secure world id".
+
+Direct messaging
+----------------
+
+This is a mandatory interface for Secure Partitions consisting in direct
+message request and responses.
+
+The ``ffa_handler`` Hafnium function may:
+
+-  trigger a world change e.g. when an SP invokes the direct message
+   response ABI to a VM.
+-  handle multiple requests from the NWd without resuming an SP.
+
+SP-to-SP
+~~~~~~~~
+
+-  An SP can send a direct message request to another SP
+-  An SP can receive a direct message response from another SP.
+
+VM-to-SP
+~~~~~~~~
+
+-  A VM can send a direct message request to an SP
+-  An SP can send a direct message response to a VM
+
+SPMC-SPMD messaging
+~~~~~~~~~~~~~~~~~~~
+
+Specific implementation-defined endpoint IDs are allocated to the SPMC and SPMD.
+Referring those IDs in source/destination fields of a direct message
+request/response permits SPMD to SPMC messaging back and forth.
+
+Per `[1]`_ Table 114 Config No. 1 (physical FF-A instance):
+
+-  SPMC=>SPMD direct message request uses SMC conduit
+-  SPMD=>SPMC direct message request uses ERET conduit
+
+Per `[1]`_ Table 118 Config No. 1 (physical FF-A instance):
+
+-  SPMC=>SPMD direct message response uses SMC conduit
+-  SPMD=>SPMC direct message response uses ERET conduit
+
+Memory management
+-----------------
+
+This section only deals with the PE MMU configuration.
+
+Hafnium in the normal world deals with NS buffers only and provisions
+a single root page table directory to VMs. In context of S-EL2 enabled
+firmware, two IPA spaces are output from Stage-1 translation (secure
+and non-secure). The Stage-2 translation handles:
+
+-  A single secure IPA space when an SP Stage-1 MMU is disabled.
+-  Two IPA spaces (secure and non-secure) when Stage-1 MMU is enabled.
+
+``VTCR_EL2`` and ``VSTCR_EL2`` provide additional bits for controlling the
+NS/S IPA translations (``VSTCR_EL2.SW``, ``VSTCR_EL2.SA``, ``VTCR_EL2.NSW``,
+``VTCR_EL2.NSA``). There may be two approaches:
+
+-  secure and non-secure mappings are rooted as two separate root page
+   tables
+-  secure and non-secure mappings use the same root page table. Access
+   from S-EL1 to an NS region translates to a secure physical address
+   space access.
+
+Interrupt management
+--------------------
+
+Road to a para-virtualized interface
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Current Hafnium implementation uses an ad-hoc mechanism for a VM to get
+a pending interrupt number through an hypercall. The PVM injects
+interrupts to VMs by delegation from the Hypervisor. The PVM probes a
+pending interrupt directly from the GIC distributor.
+
+The short-term plan is to have Hafnium/SPMC in the secure world owner
+of the GIC configuration.
+
+The SPMC fully owns the GIC configuration at S-EL2. The SPMC manages
+interrupt resources and allocates interrupt ID based on SP manifests.
+The SPMC acknowledges physical interrupts and injects virtual interrupts
+by setting the vIRQ bit when resuming an SP. A Secure Partition gathers
+the interrupt number through an hypercall.
+
+Notice the SPMC/SPMD has to handle Group0 secure interrupts in addition
+to Group1 S/NS interrupts.
+
+Power management
+----------------
+
+Assumption on the Nwd:
+
+-  NWd is the best candidate to own the platform Power Management
+   policy. It is master to invoking PSCI service calls from physical
+   CPUs.
+-  EL3 monitor is in charge of the PM control part (its PSCI layer
+   actually writing to platform registers).
+-  It is fine for the Hypervisor to trap PSCI calls and relay to EL3, or
+   OS kernel driver to emit PSCI service calls.
+
+PSCI notification are relayed through the SPMD/SPD PM hooks to the SPMC.
+This can either be through re-use of PSCI FIDs or an FF-A direct message
+from SPMD to SPMC.
+
+The SPMD performs an exception return to the SPMC which is resumed to
+its ``eret_handler`` routine. It is then either consuming a PSCI FID or
+an FF-A FID. Depending on the servicing, the SPMC may return directly to
+the SPMD (and then NWd) without resuming an SP at this stage. An example
+of this is invocation of ``FFA_PARTITION_INFO_GET`` from NWd relayed by
+the SPMD to the SPMC. The SPMC returns the needed partition information
+to the SPMD (then NWd) without actually resuming a partition in secure world.
+
+*(under discussion)*
+About using PSCI FIDs from SPMD to SPMC to notify of PM events, it is still
+questioned what to use as the return code from the SPMC.
+If the function ID used by the SPMC is not an FF-A ID when doing SMC, then the
+EL3 std svc handler won't route the response to the SPMD. That's where comes the
+idea to embed the notification into an FF-A message. The SPMC can discriminate
+this message as being a PSCI event, process it, and reply with an FF-A return
+message that the SPMD receives as an acknowledgement.
+
+SP notification
+---------------
+
+Power management notifications are conveyed from PSCI library to the
+SPMD / SPD hooks. A range of events can be relayed to SPMC.
+
+SPs may need to be notified about specific PM events.
+
+-  SPs might register PM events to the SPMC
+-  On SPMD to SPMC notification, a limited range of SPs may be notified
+   through a direct message.
+-  This assumes the mentioned SPs supports managed exit.
+
+The SPMC is the first to be notified about PM events from the SPMD. It is up
+to the SPMC to arbitrate to which SP it needs to send PM events.
+An SP explicitly registers to receive notifications to specific PM events.
+The register operation can either be an implementation-defined service call
+to the SPMC when the primary SP EC boots, or be supplied through the SP
+manifest.
+
+References
+==========
+
+.. _[1]:
+
+[1] `Platform Security Architecture Firmware Framework for Arm® v8-A 1.0 Platform Design Document <https://developer.arm.com/docs/den0077/latest>`__
+
+.. _[2]:
+
+[2] `Secure Partition Manager using MM interface`__
+
+.. __: secure-partition-manager-mm.html
+
+.. _[3]:
+
+[3] `Trusted Boot Board Requirements
+Client <https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a>`__
+
+.. _[4]:
+
+[4] https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/lib/el3_runtime/aarch64/context.S#n45
+
+.. _[5]:
+
+[5] https://git.trustedfirmware.org/TF-A/tf-a-tests.git/tree/spm/cactus/cactus.dts
+
+.. _[6]:
+
+[6] https://trustedfirmware-a.readthedocs.io/en/latest/components/psa-ffa-manifest-binding.html
+
+.. _[7]:
+
+[7] https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
+
+.. _[8]:
+
+[8] https://developer.trustedfirmware.org/w/tf_a/poc-multiple-signing-domains/
+
+--------------
+
+*Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.*
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index 78a80f6..6b6c639 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -278,9 +278,6 @@
 -  ``ERRATA_N1_1542419``: This applies errata 1542419 workaround to Neoverse-N1
    CPU. This needs to be enabled only for revisions r3p0 - r4p0 of the CPU.
 
--  ``ERRATA_N1_1800710``: This applies errata 1800710 workaround to Neoverse-N1
-   CPU. This needs to be enabled only for revisions <= r4p0 of the CPU.
-
 DSU Errata Workarounds
 ----------------------
 
diff --git a/docs/design/firmware-design.rst b/docs/design/firmware-design.rst
index 891a9a2..ae6dd46 100644
--- a/docs/design/firmware-design.rst
+++ b/docs/design/firmware-design.rst
@@ -988,7 +988,7 @@
 Exception Handling Framework
 ----------------------------
 
-Please refer to the `Exception Handling Framework`_ document.
+Please refer to the :ref:`Exception Handling Framework` document.
 
 Power State Coordination Interface
 ----------------------------------
diff --git a/docs/getting_started/docs-build.rst b/docs/getting_started/docs-build.rst
index 91b1b3a..87c677f 100644
--- a/docs/getting_started/docs-build.rst
+++ b/docs/getting_started/docs-build.rst
@@ -67,7 +67,7 @@
 
 ::
 
-   docs/build/html/
+   docs/build/html
 
 We also support building documentation in other formats. From the ``docs``
 directory of the project, run the following command to see the supported
@@ -79,6 +79,31 @@
 
    make help
 
+Building rendered documentation from a container
+------------------------------------------------
+
+There may be cases where you can not either install or upgrade required
+dependencies to generate the documents, so in this case, one way to
+create the documentation is through a docker container. The first step is
+to check if `docker`_ is installed in your host, otherwise check main docker
+page for installation instructions. Once installed, run the following script
+from project root directory
+
+.. code:: shell
+
+   docker run --rm -v $PWD:/TF sphinxdoc/sphinx \
+          bash -c 'cd /TF && \
+          pip3 install plantuml -r ./docs/requirements.txt && make doc'
+
+The above command fetches the ``sphinxdoc/sphinx`` container from `docker
+hub`_, launches the container, installs documentation requirements and finally
+creates the documentation. Once done, exit the container and output from the
+build process will be placed in:
+
+::
+
+   docs/build/html
+
 --------------
 
 *Copyright (c) 2019, Arm Limited. All rights reserved.*
@@ -86,3 +111,5 @@
 .. _Sphinx: http://www.sphinx-doc.org/en/master/
 .. _pip homepage: https://pip.pypa.io/en/stable/
 .. _Dia: https://wiki.gnome.org/Apps/Dia
+.. _docker: https://www.docker.com/
+.. _docker hub: https://hub.docker.com/repository/docker/sphinxdoc/sphinx
diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst
index c98f3cc..7aaeae2 100644
--- a/docs/getting_started/porting-guide.rst
+++ b/docs/getting_started/porting-guide.rst
@@ -1130,6 +1130,7 @@
 
     soc_version[30:24] = JEP-106 continuation code for the SiP
     soc_version[23:16] = JEP-106 identification code with parity bit for the SiP
+    soc_version[15:0]  = Implementation defined SoC ID
 
 Function : plat_get_soc_revision()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1145,6 +1146,18 @@
 
     soc_revision[0:30] = SOC revision of specific SOC
 
+Function : plat_is_smccc_feature_available()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : u_register_t
+    Return   : int32_t
+
+This function returns SMC_ARCH_CALL_SUCCESS if the platform supports
+the SMCCC function specified in the argument; otherwise returns
+SMC_ARCH_CALL_NOT_SUPPORTED.
+
 Modifications specific to a Boot Loader stage
 ---------------------------------------------
 
diff --git a/docs/resources/diagrams/ff-a-spm-sel2.png b/docs/resources/diagrams/ff-a-spm-sel2.png
new file mode 100644
index 0000000..6479ff5
--- /dev/null
+++ b/docs/resources/diagrams/ff-a-spm-sel2.png
Binary files differ
diff --git a/docs/resources/diagrams/plantuml/bl2-loading-sp.puml b/docs/resources/diagrams/plantuml/bl2-loading-sp.puml
new file mode 100644
index 0000000..3cf7c36
--- /dev/null
+++ b/docs/resources/diagrams/plantuml/bl2-loading-sp.puml
@@ -0,0 +1,44 @@
+/'
+ ' Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ '
+ ' SPDX-License-Identifier: BSD-3-Clause
+ '/
+
+@startuml
+participant bl1
+participant FIP
+
+bl1 -> FIP : read(FW_CONFIG)
+create FW_CONFIG
+bl1 -> FW_CONFIG : load
+
+bl1 -> FIP : read(bl2)
+create bl2
+bl1 -> bl2 : load
+bl1 --> bl2 : hand off (FW_CONFIG)
+
+bl2 -> FW_CONFIG : read_node(SPKs)
+loop for each spkg subnode
+  bl2 -> FW_CONFIG : read(UUID)
+  bl2 -> FW_CONFIG : read(load_address)
+  bl2 -> FIP : read(spkg@UUID)
+  create SPKG
+  bl2 -> SPKG : load
+end loop
+
+bl2 -> FW_CONFIG : read_node(TOS_FW_CONFIG)
+create TOS_FW_CONFIG
+bl2 -> TOS_FW_CONFIG : load
+
+bl2 -> FIP : read(bl32/SPMC)
+create SPMC
+bl2 -> SPMC : load
+
+bl2 -> FIP : read(bl31)
+create bl31
+bl2 -> bl31 : load
+bl2 --> bl31 : hand off (TOS_FW_CONFIG)
+
+bl31 --> SPMC : hand off (TOS_FW_CONFIG)
+
+@enduml
diff --git a/docs/resources/diagrams/plantuml/fip-secure-partitions.puml b/docs/resources/diagrams/plantuml/fip-secure-partitions.puml
new file mode 100644
index 0000000..40621db
--- /dev/null
+++ b/docs/resources/diagrams/plantuml/fip-secure-partitions.puml
@@ -0,0 +1,122 @@
+/'
+ ' Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ '
+ ' SPDX-License-Identifier: BSD-3-Clause
+ '/
+
+@startuml
+
+folder SP_vendor_1 {
+ artifact sp_binary_1
+ artifact sp_manifest_1 [
+ sp_manifest_1
+ ===
+ UUID = xxx
+ load_address = 0xaaa
+ ...
+ ]
+}
+
+folder SP_vendor_2 {
+ artifact sp_binary_2
+ artifact sp_manifest_2 [
+ sp_manifest_2
+ ===
+ UUID = yyy
+ load_address = 0xbbb
+ ]
+}
+
+artifact config.json [
+ SP_LAYOUT.json
+ ===
+ path to sp_binary_1
+ path to sp_manifest_1
+ ---
+ path to sp_binary_2
+ path to sp_manifest_2
+ ---
+ ...
+]
+
+control sp_mk_generator
+
+artifact fconf_node [
+ fconf_sp.dts
+ ===
+ spkg_1 UUID
+ spkg_1 load_address
+ ---
+ spkg_2 UUID
+ spkg_2 load_address
+]
+
+artifact sp_gen [
+ sp_gen.mk
+ ===
+ FDT_SOURCE = ...
+ SPTOOL_ARGS = ...
+ FIP_ARG = ...
+]
+
+control dtc
+control sptool
+
+artifact FW_CONFIG
+
+artifact spkg_1 [
+ spkg_1.bin
+ ===
+ <i>header</i>
+ ---
+ manifest
+ ---
+ binary
+]
+
+artifact spkg_2 [
+ spkg_2.bin
+ ===
+ <i>header</i>
+ ---
+ manifest
+ ---
+ binary
+]
+
+control fiptool
+
+artifact fip [
+ fip.bin
+ ===
+ FW_CONFIG.dtb
+ ---
+ ...
+ ---
+ SPKG1
+ ---
+ SPKG2
+ ---
+ ...
+]
+
+config.json .up.> SP_vendor_1
+config.json .up.> SP_vendor_2
+config.json --> sp_mk_generator
+sp_mk_generator --> fconf_node
+sp_mk_generator --> sp_gen
+
+sp_gen --> sptool
+sptool --> spkg_1
+sptool --> spkg_2
+
+fconf_node -down-> dtc
+dtc --> FW_CONFIG
+
+sp_gen --> fiptool
+FW_CONFIG --> fiptool
+spkg_1 -down-> fiptool
+spkg_2 -down-> fiptool
+fiptool -down-> fip
+
+@enduml
diff --git a/drivers/arm/tzc/tzc_dmc620.c b/drivers/arm/tzc/tzc_dmc620.c
index 64ec5ab..7e307ee 100644
--- a/drivers/arm/tzc/tzc_dmc620.c
+++ b/drivers/arm/tzc/tzc_dmc620.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -17,7 +17,7 @@
 
 /* Helper macro for getting dmc_base addr of a dmc_inst */
 #define DMC_BASE(plat_data, dmc_inst) \
-	((uintptr_t)(plat_data->dmc_base[dmc_inst]))
+	((uintptr_t)((plat_data)->dmc_base[(dmc_inst)]))
 
 /* Pointer to the tzc_dmc620_config_data structure populated by the platform */
 static const tzc_dmc620_config_data_t *g_plat_config_data;
@@ -31,8 +31,7 @@
 static void tzc_dmc620_validate_plat_driver_data(
 			const tzc_dmc620_driver_data_t *plat_driver_data)
 {
-	uint8_t dmc_inst, dmc_count;
-	unsigned int dmc_id;
+	unsigned int dmc_inst, dmc_count, dmc_id;
 	uintptr_t base;
 
 	assert(plat_driver_data != NULL);
@@ -59,7 +58,7 @@
 {
 	uint32_t min_31_00, min_47_32;
 	uint32_t max_31_00, max_47_32;
-	uint8_t dmc_inst, dmc_count;
+	unsigned int dmc_inst, dmc_count;
 	uintptr_t base;
 	const tzc_dmc620_driver_data_t *plat_driver_data;
 
@@ -67,19 +66,19 @@
 	assert(plat_driver_data != NULL);
 
 	/* Do range checks on regions. */
-	assert((region_no >= 0U) && (region_no <= DMC620_ACC_ADDR_COUNT));
+	assert((region_no >= 0) && (region_no <= DMC620_ACC_ADDR_COUNT));
 
 	/* region_base and (region_top + 1) must be 4KB aligned */
 	assert(((region_base | (region_top + 1U)) & (4096U - 1U)) == 0U);
 
 	dmc_count = plat_driver_data->dmc_count;
 	for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) {
-		min_31_00 = (region_base & MASK_31_16) | sec_attr;
-		min_47_32 = (region_base & MASK_47_32)
-				>> DMC620_ACC_ADDR_WIDTH;
-		max_31_00 = (region_top  & MASK_31_16);
-		max_47_32 = (region_top  & MASK_47_32)
-				>> DMC620_ACC_ADDR_WIDTH;
+		min_31_00 = (uint32_t)((region_base & MASK_31_16) | sec_attr);
+		min_47_32 = (uint32_t)((region_base & MASK_47_32)
+				>> DMC620_ACC_ADDR_WIDTH);
+		max_31_00 = (uint32_t)(region_top  & MASK_31_16);
+		max_47_32 = (uint32_t)((region_top  & MASK_47_32)
+				>> DMC620_ACC_ADDR_WIDTH);
 
 		/* Extract the base address of the DMC-620 instance */
 		base = DMC_BASE(plat_driver_data, dmc_inst);
@@ -100,7 +99,7 @@
  */
 static void tzc_dmc620_set_action(void)
 {
-	uint8_t dmc_inst, dmc_count;
+	unsigned int dmc_inst, dmc_count;
 	uintptr_t base;
 	const tzc_dmc620_driver_data_t *plat_driver_data;
 
@@ -123,7 +122,7 @@
  */
 static void tzc_dmc620_verify_complete(void)
 {
-	uint8_t dmc_inst, dmc_count;
+	unsigned int dmc_inst, dmc_count;
 	uintptr_t base;
 	const tzc_dmc620_driver_data_t *plat_driver_data;
 
@@ -133,8 +132,9 @@
 		/* Extract the base address of the DMC-620 instance */
 		base = DMC_BASE(plat_driver_data, dmc_inst);
 		while ((mmio_read_32(base + DMC620_MEMC_STATUS) &
-				DMC620_MEMC_CMD_MASK) != DMC620_MEMC_CMD_GO)
+				DMC620_MEMC_CMD_MASK) != DMC620_MEMC_CMD_GO) {
 			continue;
+		}
 	}
 }
 
@@ -145,7 +145,7 @@
  */
 void arm_tzc_dmc620_setup(const tzc_dmc620_config_data_t *plat_config_data)
 {
-	int i;
+	uint8_t i;
 
 	/* Check if valid pointer is passed */
 	assert(plat_config_data != NULL);
@@ -164,11 +164,12 @@
 	g_plat_config_data = plat_config_data;
 
 	INFO("Configuring DMC-620 TZC settings\n");
-	for (i = 0U; i < g_plat_config_data->acc_addr_count; i++)
+	for (i = 0U; i < g_plat_config_data->acc_addr_count; i++) {
 		tzc_dmc620_configure_region(i,
 			g_plat_config_data->plat_acc_addr_data[i].region_base,
 			g_plat_config_data->plat_acc_addr_data[i].region_top,
 			g_plat_config_data->plat_acc_addr_data[i].sec_attr);
+	}
 
 	tzc_dmc620_set_action();
 	tzc_dmc620_verify_complete();
diff --git a/include/drivers/arm/tzc_dmc620.h b/include/drivers/arm/tzc_dmc620.h
index e0e6760..26c444d 100644
--- a/include/drivers/arm/tzc_dmc620.h
+++ b/include/drivers/arm/tzc_dmc620.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -32,16 +32,16 @@
 /* Address offsets of access address next registers */
 #define DMC620_ACC_ADDR_MIN_31_00_NEXT(region_no)	\
 		(DMC620_ACC_ADDR_MIN_31_00_NEXT_BASE +	\
-			(region_no * DMC620_ACC_ADDR_NEXT_SIZE))
+			((region_no) * DMC620_ACC_ADDR_NEXT_SIZE))
 #define DMC620_ACC_ADDR_MIN_47_32_NEXT(region_no)	\
 		(DMC620_ACC_ADDR_MIN_47_32_NEXT_BASE +	\
-			(region_no * DMC620_ACC_ADDR_NEXT_SIZE))
+			((region_no) * DMC620_ACC_ADDR_NEXT_SIZE))
 #define DMC620_ACC_ADDR_MAX_31_00_NEXT(region_no)	\
 		(DMC620_ACC_ADDR_MAX_31_00_NEXT_BASE +	\
-			(region_no * DMC620_ACC_ADDR_NEXT_SIZE))
+			((region_no) * DMC620_ACC_ADDR_NEXT_SIZE))
 #define DMC620_ACC_ADDR_MAX_47_32_NEXT(region_no)	\
 		(DMC620_ACC_ADDR_MAX_47_32_NEXT_BASE +	\
-			(region_no * DMC620_ACC_ADDR_NEXT_SIZE))
+			((region_no) * DMC620_ACC_ADDR_NEXT_SIZE))
 
 /* Number of TZC address regions in DMC-620 */
 #define DMC620_ACC_ADDR_COUNT	U(8)
diff --git a/include/lib/cpus/aarch64/neoverse_n1.h b/include/lib/cpus/aarch64/neoverse_n1.h
index 155a90e..b50befa 100644
--- a/include/lib/cpus/aarch64/neoverse_n1.h
+++ b/include/lib/cpus/aarch64/neoverse_n1.h
@@ -35,7 +35,6 @@
 
 #define NEOVERSE_N1_WS_THR_L2_MASK	(ULL(3) << 24)
 #define NEOVERSE_N1_CPUECTLR_EL1_MM_TLBPF_DIS_BIT	(ULL(1) << 51)
-#define NEOVERSE_N1_CPUECTLR_EL1_BIT_53			(ULL(1) << 53)
 #define NEOVERSE_N1_CPUECTLR_EL1_EXTLLC_BIT		(ULL(1) << 0)
 
 /*******************************************************************************
diff --git a/include/lib/fconf/fconf_dyn_cfg_getter.h b/include/lib/fconf/fconf_dyn_cfg_getter.h
index 9816d6f..6f8da0d 100644
--- a/include/lib/fconf/fconf_dyn_cfg_getter.h
+++ b/include/lib/fconf/fconf_dyn_cfg_getter.h
@@ -14,14 +14,15 @@
 
 struct dyn_cfg_dtb_info_t {
 	uintptr_t config_addr;
-	size_t config_max_size;
+	uint32_t config_max_size;
 	unsigned int config_id;
 };
 
 struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id);
 int fconf_populate_dtb_registry(uintptr_t config);
 
-/* Set fw_config information in global DTB array */
-void set_fw_config_info(uintptr_t config_addr, uint32_t config_max_size);
+/* Set config information in global DTB array */
+void set_config_info(uintptr_t config_addr, uint32_t config_max_size,
+			unsigned int config_id);
 
 #endif /* FCONF_DYN_CFG_GETTER_H */
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 139145b..293e7ce 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -294,12 +294,19 @@
 #define ARM_V2M_MAP_MEM_PROTECT		MAP_REGION_FLAT(PLAT_ARM_MEM_PROT_ADDR,	\
 						V2M_FLASH_BLOCK_SIZE,		\
 						MT_DEVICE | MT_RW | MT_SECURE)
+/*
+ * Map the region for device tree configuration with read and write permissions
+ */
+#define ARM_MAP_BL_CONFIG_REGION	MAP_REGION_FLAT(ARM_BL_RAM_BASE,	\
+						(ARM_FW_CONFIGS_LIMIT		\
+							- ARM_BL_RAM_BASE),	\
+						MT_MEMORY | MT_RW | MT_SECURE)
 
 /*
  * The max number of regions like RO(code), coherent and data required by
  * different BL stages which need to be mapped in the MMU.
  */
-#define ARM_BL_REGIONS			5
+#define ARM_BL_REGIONS			6
 
 #define MAX_MMAP_REGIONS		(PLAT_ARM_MMAP_ENTRIES +	\
 					 ARM_BL_REGIONS)
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index 658b423..2c1a180 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -341,4 +341,9 @@
  */
 int32_t plat_get_soc_revision(void);
 
+/*
+ * Optional function to check for SMCCC function availability for platform
+ */
+int32_t plat_is_smccc_feature_available(u_register_t fid);
+
 #endif /* PLATFORM_H */
diff --git a/lib/cpus/aarch64/neoverse_n1.S b/lib/cpus/aarch64/neoverse_n1.S
index 0f80de1..d537ed6 100644
--- a/lib/cpus/aarch64/neoverse_n1.S
+++ b/lib/cpus/aarch64/neoverse_n1.S
@@ -375,35 +375,6 @@
 	b	cpu_rev_var_range
 endfunc check_errata_1542419
 
-/* --------------------------------------------------
- * Errata Workaround for Neoverse N1 Erratum 1800710.
- * This applies to revisions <= r4p0 of Neoverse N1
- * Inputs:
- * x0: variant[4:7] and revision[0:3] of current cpu.
- * Shall clobber: x0-x17
- * --------------------------------------------------
- */
-func errata_n1_1800710_wa
-	/* Compare x0 against revision <= r4p0 */
-	mov	x17, x30
-	bl	check_errata_1800710
-	cbz	x0, 1f
-
-	/* Disable allocation of splintered pages in the L2 TLB */
-	mrs	x1, NEOVERSE_N1_CPUECTLR_EL1
-	orr	x1, x1, NEOVERSE_N1_CPUECTLR_EL1_BIT_53
-	msr	NEOVERSE_N1_CPUECTLR_EL1, x1
-	isb
-1:
-	ret	x17
-endfunc errata_n1_1800710_wa
-
-func check_errata_1800710
-	/* Applies to everything <= r4p0 */
-	mov	x1, #0x40
-	b	cpu_rev_var_ls
-endfunc check_errata_1800710
-
 func neoverse_n1_reset_func
 	mov	x19, x30
 
@@ -478,11 +449,6 @@
 	bl	errata_n1_1542419_wa
 #endif
 
-#if ERRATA_N1_1800710
-	mov	x0, x18
-	bl	errata_n1_1800710_wa
-#endif
-
 #if ENABLE_AMU
 	/* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */
 	mrs	x0, actlr_el3
@@ -556,7 +522,6 @@
 	report_errata ERRATA_N1_1275112, neoverse_n1, 1275112
 	report_errata ERRATA_N1_1315703, neoverse_n1, 1315703
 	report_errata ERRATA_N1_1542419, neoverse_n1, 1542419
-	report_errata ERRATA_N1_1800710, neoverse_n1, 1800710
 	report_errata ERRATA_DSU_936184, neoverse_n1, dsu_936184
 
 	ldp	x8, x30, [sp], #16
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index 3c895f5..e494375 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -314,10 +314,6 @@
 # to revisions r3p0 - r4p0 of the Neoverse N1 cpu.
 ERRATA_N1_1542419	?=0
 
-# Flag to apply erratum 1800710 workaround during reset. This erratum applies
-# to revisions <= r4p0 of the Neoverse N1 cpu.
-ERRATA_N1_1800710	?=0
-
 # Flag to apply DSU erratum 798953. This erratum applies to DSUs revision r0p0.
 # Applying the workaround results in higher DSU power consumption on idle.
 ERRATA_DSU_798953	?=0
@@ -567,10 +563,6 @@
 $(eval $(call assert_boolean,ERRATA_N1_1542419))
 $(eval $(call add_define,ERRATA_N1_1542419))
 
-# Process ERRATA_N1_1800710 flag
-$(eval $(call assert_boolean,ERRATA_N1_1800710))
-$(eval $(call add_define,ERRATA_N1_1800710))
-
 # Process ERRATA_DSU_798953 flag
 $(eval $(call assert_boolean,ERRATA_DSU_798953))
 $(eval $(call add_define,ERRATA_DSU_798953))
diff --git a/lib/fconf/fconf.c b/lib/fconf/fconf.c
index bc4fa8e..24b6bcc 100644
--- a/lib/fconf/fconf.c
+++ b/lib/fconf/fconf.c
@@ -32,8 +32,7 @@
 	assert(config_info != NULL);
 
 	config_image_info.image_base = config_info->config_addr;
-	config_image_info.image_max_size =
-		(uint32_t)config_info->config_max_size;
+	config_image_info.image_max_size = config_info->config_max_size;
 
 	VERBOSE("FCONF: Loading config with image ID: %d\n", image_id);
 	err = load_auth_image(image_id, &config_image_info);
diff --git a/lib/fconf/fconf_dyn_cfg_getter.c b/lib/fconf/fconf_dyn_cfg_getter.c
index 16bbe42..25dd7f9 100644
--- a/lib/fconf/fconf_dyn_cfg_getter.c
+++ b/lib/fconf/fconf_dyn_cfg_getter.c
@@ -14,64 +14,57 @@
 
 /* We currently use FW, TB_FW, SOC_FW, TOS_FW, NT_FW and HW configs  */
 #define MAX_DTB_INFO	U(6)
+/*
+ * Compile time assert if FW_CONFIG_ID is 0 which is more
+ * unlikely as 0 is a valid image ID for FIP as per the current
+ * code but still to avoid code breakage in case of unlikely
+ * event when image IDs get changed.
+ */
+CASSERT(FW_CONFIG_ID != U(0), assert_invalid_fw_config_id);
 
 static struct dyn_cfg_dtb_info_t dtb_infos[MAX_DTB_INFO];
 static OBJECT_POOL_ARRAY(dtb_info_pool, dtb_infos);
 
 /*
- * This function is used to alloc memory for fw config information from
- * global pool and set fw configuration information.
- * Specifically used by BL1 to set fw_config information in global array
+ * This function is used to alloc memory for config information from
+ * global pool and set the configuration information.
  */
-void set_fw_config_info(uintptr_t config_addr, uint32_t config_max_size)
+void set_config_info(uintptr_t config_addr, uint32_t config_max_size,
+			unsigned int config_id)
 {
 	struct dyn_cfg_dtb_info_t *dtb_info;
 
 	dtb_info = pool_alloc(&dtb_info_pool);
 	dtb_info->config_addr = config_addr;
 	dtb_info->config_max_size = config_max_size;
-	dtb_info->config_id = FW_CONFIG_ID;
+	dtb_info->config_id = config_id;
 }
 
 struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id)
 {
 	unsigned int index;
-	struct dyn_cfg_dtb_info_t *info;
 
 	/* Positions index to the proper config-id */
-	for (index = 0; index < MAX_DTB_INFO; index++) {
+	for (index = 0U; index < MAX_DTB_INFO; index++) {
 		if (dtb_infos[index].config_id == config_id) {
-			info = &dtb_infos[index];
-			break;
+			return &dtb_infos[index];
 		}
 	}
 
-	if (index == MAX_DTB_INFO) {
-		WARN("FCONF: Invalid config id %u\n", config_id);
-		info = NULL;
-	}
+	WARN("FCONF: Invalid config id %u\n", config_id);
 
-	return info;
+	return NULL;
 }
 
 int fconf_populate_dtb_registry(uintptr_t config)
 {
 	int rc;
 	int node, child;
-	struct dyn_cfg_dtb_info_t *dtb_info;
 
 	/* As libfdt use void *, we can't avoid this cast */
 	const void *dtb = (void *)config;
 
 	/*
-	 * Compile time assert if FW_CONFIG_ID is 0 which is more
-	 * unlikely as 0 is a valid image id for FIP as per the current
-	 * code but still to avoid code breakage in case of unlikely
-	 * event when image ids gets changed.
-	 */
-	CASSERT(FW_CONFIG_ID != 0, assert_invalid_fw_config_id);
-
-	/*
 	 * In case of BL1, fw_config dtb information is already
 	 * populated in global dtb_infos array by 'set_fw_config_info'
 	 * function, Below check is present to avoid re-population of
@@ -80,11 +73,9 @@
 	 * Other BLs, satisfy below check and populate fw_config information
 	 * in global dtb_infos array.
 	 */
-	if (dtb_infos[0].config_id == 0) {
-		dtb_info = pool_alloc(&dtb_info_pool);
-		dtb_info->config_addr = config;
-		dtb_info->config_max_size = fdt_totalsize(dtb);
-		dtb_info->config_id = FW_CONFIG_ID;
+	if (dtb_infos[0].config_id == 0U) {
+		uint32_t config_max_size = fdt_totalsize(dtb);
+		set_config_info(config, config_max_size, FW_CONFIG_ID);
 	}
 
 	/* Find the node offset point to "fconf,dyn_cfg-dtb_registry" compatible property */
@@ -96,37 +87,36 @@
 	}
 
 	fdt_for_each_subnode(child, dtb, node) {
-		uint32_t val32;
+		uint32_t config_max_size, config_id;
+		uintptr_t config_addr;
 		uint64_t val64;
 
-		dtb_info = pool_alloc(&dtb_info_pool);
-
 		/* Read configuration dtb information */
 		rc = fdt_read_uint64(dtb, child, "load-address", &val64);
 		if (rc < 0) {
 			ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
 			return rc;
 		}
-		dtb_info->config_addr = (uintptr_t)val64;
+		config_addr = (uintptr_t)val64;
 
-		rc = fdt_read_uint32(dtb, child, "max-size", &val32);
+		rc = fdt_read_uint32(dtb, child, "max-size", &config_max_size);
 		if (rc < 0) {
 			ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
 			return rc;
 		}
-		dtb_info->config_max_size = val32;
 
-		rc = fdt_read_uint32(dtb, child, "id", &val32);
+		rc = fdt_read_uint32(dtb, child, "id", &config_id);
 		if (rc < 0) {
 			ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
 			return rc;
 		}
-		dtb_info->config_id = val32;
 
 		VERBOSE("FCONF: dyn_cfg.dtb_registry cell found with:\n");
-		VERBOSE("\tload-address = %lx\n", dtb_info->config_addr);
-		VERBOSE("\tmax-size = 0x%zx\n", dtb_info->config_max_size);
-		VERBOSE("\tconfig-id = %u\n", dtb_info->config_id);
+		VERBOSE("\tload-address = %lx\n", config_addr);
+		VERBOSE("\tmax-size = 0x%x\n", config_max_size);
+		VERBOSE("\tconfig-id = %u\n", config_id);
+
+		set_config_info(config_addr, config_max_size, config_id);
 	}
 
 	if ((child < 0) && (child != -FDT_ERR_NOTFOUND)) {
diff --git a/plat/arm/board/a5ds/include/platform_def.h b/plat/arm/board/a5ds/include/platform_def.h
index 0745316..792a754 100644
--- a/plat/arm/board/a5ds/include/platform_def.h
+++ b/plat/arm/board/a5ds/include/platform_def.h
@@ -152,10 +152,18 @@
 #endif
 
 /*
+ * Map the region for device tree configuration with read and write permissions
+ */
+#define ARM_MAP_BL_CONFIG_REGION	MAP_REGION_FLAT(ARM_BL_RAM_BASE,	\
+						(ARM_FW_CONFIGS_LIMIT		\
+							- ARM_BL_RAM_BASE),	\
+						MT_MEMORY | MT_RW | MT_SECURE)
+
+/*
  * The max number of regions like RO(code), coherent and data required by
  * different BL stages which need to be mapped in the MMU.
  */
-#define ARM_BL_REGIONS			5
+#define ARM_BL_REGIONS			6
 
 #define MAX_MMAP_REGIONS		(PLAT_ARM_MMAP_ENTRIES +	\
 					 ARM_BL_REGIONS)
@@ -194,6 +202,12 @@
 #define ARM_FW_CONFIG_BASE		(ARM_BL_RAM_BASE + sizeof(meminfo_t))
 #define ARM_FW_CONFIG_LIMIT		(ARM_BL_RAM_BASE + PAGE_SIZE)
 
+/*
+ * Define limit of firmware configuration memory:
+ * ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory
+ */
+#define ARM_FW_CONFIGS_LIMIT		(ARM_BL_RAM_BASE + (PAGE_SIZE * 2))
+
 /*******************************************************************************
  * BL1 specific defines.
  * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of
@@ -221,6 +235,8 @@
 
 /* Put BL32 below BL2 in NS DRAM.*/
 #define ARM_BL2_MEM_DESC_BASE		ARM_FW_CONFIG_LIMIT
+#define ARM_BL2_MEM_DESC_LIMIT		(ARM_BL2_MEM_DESC_BASE \
+					+ (PAGE_SIZE / 2U))
 
 #define BL32_BASE			((ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)\
 						- PLAT_ARM_MAX_BL32_SIZE)
diff --git a/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S b/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S
index aeed310..20120c9 100644
--- a/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S
+++ b/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S
@@ -7,6 +7,8 @@
 #include <arch.h>
 #include <asm_macros.S>
 #include <common/bl_common.h>
+#include "../fpga_private.h"
+
 #include <platform_def.h>
 
 	.globl	plat_get_my_entrypoint
@@ -14,10 +16,10 @@
 	.globl	plat_is_my_cpu_primary
 	.globl	platform_mem_init
 	.globl	plat_my_core_pos
-	.globl	plat_fpga_calc_core_pos
 	.globl	plat_crash_console_init
 	.globl	plat_crash_console_putc
 	.globl	plat_crash_console_flush
+	.globl	plat_fpga_calc_core_pos
 
 /* -----------------------------------------------------------------------
  * Indicate a cold boot for every CPU - warm boot is unsupported for the
@@ -34,23 +36,59 @@
  * -----------------------------------------------------------------------
  */
 func plat_secondary_cold_boot_setup
+
+	/*
+	 * Wait for the primary processor to initialise the .BSS segment
+	 * to avoid a race condition that would erase fpga_valid_mpids
+	 * if it is populated before the C runtime is ready.
+	 *
+	 * We cannot use the current spin-lock implementation until the
+	 * runtime is up and we should not rely on sevl/wfe instructions as
+	 * it is optional whether they are implemented or not, so we use
+	 * a global variable as lock and wait for the primary processor to
+	 * finish the C runtime bring-up.
+	 */
+
+	ldr	w0, =C_RUNTIME_READY_KEY
+	adrp	x1, secondary_core_spinlock
+	add	x1, x1, :lo12:secondary_core_spinlock
+1:
+	wfe
+	ldr	w2, [x1]
+	cmp	w2, w0
+	b.ne	1b
+	/* Prevent reordering of the store into fpga_valid_mpids below */
+	dmb	ish
+
+	mov	x10, x30
+	bl	plat_my_core_pos
+	mov	x30, x10
+
+	adrp	x4, fpga_valid_mpids
+	add	x4, x4, :lo12:fpga_valid_mpids
+	mov	x5, #VALID_MPID
+	strb	w5, [x4, x0]
+
 	/*
 	 * Poll the CPU's hold entry until it indicates to jump
 	 * to the entrypoint address.
 	 */
-	bl	plat_my_core_pos
-	lsl	x0, x0, #PLAT_FPGA_HOLD_ENTRY_SHIFT
-	ldr	x1, =hold_base
-	ldr	x2, =fpga_sec_entrypoint
+
+	adrp	x1, hold_base
+	add	x1, x1, :lo12:hold_base
 poll_hold_entry:
-	ldr	x3, [x1, x0]
+	ldr	x3, [x1, x0, LSL #PLAT_FPGA_HOLD_ENTRY_SHIFT]
 	cmp	x3, #PLAT_FPGA_HOLD_STATE_GO
 	b.ne	1f
+
+	adrp	x2, fpga_sec_entrypoint
+	add	x2, x2, :lo12:fpga_sec_entrypoint
 	ldr	x3, [x2]
 	br	x3
 1:
 	wfe
 	b	poll_hold_entry
+
 endfunc plat_secondary_cold_boot_setup
 
 /* -----------------------------------------------------------------------
@@ -73,12 +111,16 @@
 endfunc platform_mem_init
 
 func plat_my_core_pos
+	ldr	x1, =(MPID_MASK & ~(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT))
 	mrs	x0, mpidr_el1
+	and	x0, x0, x1
 	b	plat_fpga_calc_core_pos
+
 endfunc plat_my_core_pos
 
 /* -----------------------------------------------------------------------
- * unsigned int plat_fpga_calc_core_pos(u_register_t mpidr)
+ * unsigned int plat_fpga_calc_core_pos (uint32_t mpid)
+ * Clobber registers: x0 to x5
  * -----------------------------------------------------------------------
  */
 func plat_fpga_calc_core_pos
@@ -88,6 +130,7 @@
 	 *
 	 * If not set, shift MPIDR to left to make it look as if in a
 	 * multi-threaded implementation.
+	 *
 	 */
 	tst	x0, #MPIDR_MT_MASK
 	lsl	x3, x0, #MPIDR_AFFINITY_BITS
@@ -98,11 +141,13 @@
 	ubfx	x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
 	ubfx	x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
 
-	/* Compute linear position */
 	mov	x4, #FPGA_MAX_CPUS_PER_CLUSTER
-	madd	x1, x2, x4, x1
 	mov	x5, #FPGA_MAX_PE_PER_CPU
+
+	/* Compute linear position */
+	madd	x1, x2, x4, x1
 	madd	x0, x1, x5, x0
+
 	ret
 endfunc plat_fpga_calc_core_pos
 
diff --git a/plat/arm/board/arm_fpga/fpga_bl31_setup.c b/plat/arm/board/arm_fpga/fpga_bl31_setup.c
index e4b9767..6eeff45 100644
--- a/plat/arm/board/arm_fpga/fpga_bl31_setup.c
+++ b/plat/arm/board/arm_fpga/fpga_bl31_setup.c
@@ -7,23 +7,23 @@
 #include <assert.h>
 
 #include <common/fdt_wrappers.h>
+#include <drivers/delay_timer.h>
 #include <drivers/generic_delay_timer.h>
-#include <lib/mmio.h>
 #include <libfdt.h>
 
+#include "fpga_private.h"
 #include <plat/common/platform.h>
 #include <platform_def.h>
 
-#include "fpga_private.h"
-
 static entry_point_info_t bl33_image_ep_info;
+volatile uint32_t secondary_core_spinlock;
 
 uintptr_t plat_get_ns_image_entrypoint(void)
 {
 #ifdef PRELOADED_BL33_BASE
 	return PRELOADED_BL33_BASE;
 #else
-	return 0;
+	return 0ULL;
 #endif
 }
 
@@ -35,6 +35,17 @@
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				u_register_t arg2, u_register_t arg3)
 {
+	/* Add this core to the VALID mpids list */
+	fpga_valid_mpids[plat_my_core_pos()] = VALID_MPID;
+
+	/*
+	 * Notify the secondary CPUs that the C runtime is ready
+	 * so they can announce themselves.
+	 */
+	secondary_core_spinlock = C_RUNTIME_READY_KEY;
+	dsbish();
+	sev();
+
 	fpga_console_init();
 
 	bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
@@ -54,11 +65,37 @@
 
 void bl31_platform_setup(void)
 {
-	/* Initialize the GIC driver, cpu and distributor interfaces */
-	plat_fpga_gic_init();
-
 	/* Write frequency to CNTCRL and initialize timer */
 	generic_delay_timer_init();
+
+	/*
+	 * Before doing anything else, wait for some time to ensure that
+	 * the secondary CPUs have populated the fpga_valid_mpids array.
+	 * As the number of secondary cores is unknown and can even be 0,
+	 * it is not possible to rely on any signal from them, so use a
+	 * delay instead.
+	 */
+	mdelay(5);
+
+	/*
+	 * On the event of a cold reset issued by, for instance, a reset pin
+	 * assertion, we cannot guarantee memory to be initialized to zero.
+	 * In such scenario, if the secondary cores reached
+	 * plat_secondary_cold_boot_setup before the primary one initialized
+	 * .BSS, we could end up having a race condition if the spinlock
+	 * was not cleared before.
+	 *
+	 * Similarly, if there were a reset before the spinlock had been
+	 * cleared, the secondary cores would find the lock opened before
+	 * .BSS is cleared, causing another race condition.
+	 *
+	 * So clean the spinlock as soon as we think it is safe to reduce the
+	 * chances of any race condition on a reset.
+	 */
+	secondary_core_spinlock = 0UL;
+
+	/* Initialize the GIC driver, cpu and distributor interfaces */
+	plat_fpga_gic_init();
 }
 
 entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
diff --git a/plat/arm/board/arm_fpga/fpga_def.h b/plat/arm/board/arm_fpga/fpga_def.h
index 5f1951f..2884ea6 100644
--- a/plat/arm/board/arm_fpga/fpga_def.h
+++ b/plat/arm/board/arm_fpga/fpga_def.h
@@ -18,6 +18,7 @@
  * that are present will still be indexed appropriately regardless of any empty
  * entries in the array used to represent the topology.
  */
+
 #define FPGA_MAX_CLUSTER_COUNT			4
 #define FPGA_MAX_CPUS_PER_CLUSTER		8
 #define FPGA_MAX_PE_PER_CPU			4
diff --git a/plat/arm/board/arm_fpga/fpga_private.h b/plat/arm/board/arm_fpga/fpga_private.h
index 7545bd1..46287ad 100644
--- a/plat/arm/board/arm_fpga/fpga_private.h
+++ b/plat/arm/board/arm_fpga/fpga_private.h
@@ -7,12 +7,23 @@
 #ifndef FPGA_PRIVATE_H
 #define FPGA_PRIVATE_H
 
-unsigned int plat_fpga_calc_core_pos(u_register_t mpidr);
+#include "../fpga_def.h"
+#include <platform_def.h>
+
+#define C_RUNTIME_READY_KEY	(0xaa55aa55)
+#define VALID_MPID		(1U)
+
+#ifndef __ASSEMBLER__
+
+extern unsigned char fpga_valid_mpids[PLATFORM_CORE_COUNT];
 
 void fpga_console_init(void);
 
 void plat_fpga_gic_init(void);
 void fpga_pwr_gic_on_finish(void);
 void fpga_pwr_gic_off(void);
+unsigned int plat_fpga_calc_core_pos(uint32_t mpid);
+
+#endif /* __ASSEMBLER__ */
 
-#endif
+#endif /* FPGA_PRIVATE_H */
diff --git a/plat/arm/board/arm_fpga/fpga_topology.c b/plat/arm/board/arm_fpga/fpga_topology.c
index a2908d7..7fead86 100644
--- a/plat/arm/board/arm_fpga/fpga_topology.c
+++ b/plat/arm/board/arm_fpga/fpga_topology.c
@@ -5,15 +5,20 @@
  */
 
 #include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/spinlock.h>
 
 #include "fpga_private.h"
+#include <plat/common/platform.h>
 #include <platform_def.h>
 
-static unsigned char fpga_power_domain_tree_desc[FPGA_MAX_CLUSTER_COUNT + 2];
+unsigned char fpga_power_domain_tree_desc[FPGA_MAX_CLUSTER_COUNT + 2];
+unsigned char fpga_valid_mpids[PLATFORM_CORE_COUNT];
 
 const unsigned char *plat_get_power_domain_tree_desc(void)
 {
-	int i;
+	unsigned int i;
+
 	/*
 	* The highest level is the system level. The next level is constituted
 	* by clusters and then cores in clusters.
@@ -21,12 +26,26 @@
 	* This description of the power domain topology is aligned with the CPU
 	* indices returned by the plat_core_pos_by_mpidr() and plat_my_core_pos()
 	* APIs.
+	*
+	* A description of the topology tree can be found at
+	* https://trustedfirmware-a.readthedocs.io/en/latest/design/psci-pd-tree.html#design
 	*/
-	fpga_power_domain_tree_desc[0] = 1;
-	fpga_power_domain_tree_desc[1] = FPGA_MAX_CLUSTER_COUNT;
 
-	for (i = 0; i < FPGA_MAX_CLUSTER_COUNT; i++) {
-		fpga_power_domain_tree_desc[i + 2] = FPGA_MAX_CPUS_PER_CLUSTER * FPGA_MAX_PE_PER_CPU;
+	if (fpga_power_domain_tree_desc[0] == 0U) {
+		/*
+		 * As fpga_power_domain_tree_desc[0] == 0, assume that the
+		 * Power Domain Topology Tree has not been initialized, so
+		 * perform the initialization here.
+		 */
+
+		fpga_power_domain_tree_desc[0] = 1U;
+		fpga_power_domain_tree_desc[1] = FPGA_MAX_CLUSTER_COUNT;
+
+		for (i = 0U; i < FPGA_MAX_CLUSTER_COUNT; i++) {
+			fpga_power_domain_tree_desc[2 + i] =
+				(FPGA_MAX_CPUS_PER_CLUSTER *
+				 FPGA_MAX_PE_PER_CPU);
+		}
 	}
 
 	return fpga_power_domain_tree_desc;
@@ -34,40 +53,25 @@
 
 int plat_core_pos_by_mpidr(u_register_t mpidr)
 {
-	unsigned int cluster_id, cpu_id, thread_id;
+	unsigned int core_pos;
 
-	/*
-	 * The image running on the FPGA may or may not implement
-	 * multithreading, and it shouldn't be assumed this is consistent
-	 * across all CPUs.
-	 * This ensures that any passed mpidr values reflect the status of the
-	 * primary CPU's MT bit.
-	 */
+	mpidr &= (MPID_MASK & ~(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT));
 	mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
-	mpidr &= MPID_MASK;
 
-	if (mpidr & MPIDR_MT_MASK) {
-		thread_id = MPIDR_AFFLVL0_VAL(mpidr);
-		cpu_id = MPIDR_AFFLVL1_VAL(mpidr);
-		cluster_id = MPIDR_AFFLVL2_VAL(mpidr);
-	} else {
-		thread_id = 0;
-		cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
-		cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+	if ((MPIDR_AFFLVL2_VAL(mpidr) >= FPGA_MAX_CLUSTER_COUNT) ||
+	    (MPIDR_AFFLVL1_VAL(mpidr) >= FPGA_MAX_CPUS_PER_CLUSTER) ||
+	    (MPIDR_AFFLVL0_VAL(mpidr) >= FPGA_MAX_PE_PER_CPU)) {
+		ERROR ("Invalid mpidr: 0x%08x\n", (uint32_t)mpidr);
+		panic();
 	}
 
-	if (cluster_id >= FPGA_MAX_CLUSTER_COUNT) {
-		return -1;
-	}
-
-	if (cpu_id >= FPGA_MAX_CPUS_PER_CLUSTER) {
-		return -1;
-	}
+	/* Calculate the core position, based on the maximum topology. */
+	core_pos = plat_fpga_calc_core_pos(mpidr);
 
-	if (thread_id >= FPGA_MAX_PE_PER_CPU) {
+	/* Check whether this core is actually present. */
+	if (fpga_valid_mpids[core_pos] != VALID_MPID) {
 		return -1;
 	}
 
-	/* Calculate the correct core, catering for multi-threaded images */
-	return (int) plat_fpga_calc_core_pos(mpidr);
+	return core_pos;
 }
diff --git a/plat/arm/board/arm_fpga/include/platform_def.h b/plat/arm/board/arm_fpga/include/platform_def.h
index 31fc987..411b936 100644
--- a/plat/arm/board/arm_fpga/include/platform_def.h
+++ b/plat/arm/board/arm_fpga/include/platform_def.h
@@ -21,11 +21,12 @@
 #define CACHE_WRITEBACK_SHIFT		U(6)
 #define CACHE_WRITEBACK_GRANULE		(U(1) << CACHE_WRITEBACK_SHIFT)
 
-#define PLATFORM_CORE_COUNT \
-	(FPGA_MAX_CLUSTER_COUNT * FPGA_MAX_CPUS_PER_CLUSTER * FPGA_MAX_PE_PER_CPU)
+#define PLATFORM_CORE_COUNT		\
+	(FPGA_MAX_CLUSTER_COUNT *	\
+	 FPGA_MAX_CPUS_PER_CLUSTER *	\
+	 FPGA_MAX_PE_PER_CPU)
 
-#define PLAT_NUM_PWR_DOMAINS		(FPGA_MAX_CLUSTER_COUNT + \
-					PLATFORM_CORE_COUNT) + 1
+#define PLAT_NUM_PWR_DOMAINS (FPGA_MAX_CLUSTER_COUNT + PLATFORM_CORE_COUNT + 1)
 
 #if !ENABLE_PIE
 #define BL31_BASE			UL(0x80000000)
diff --git a/plat/arm/board/corstone700/common/include/platform_def.h b/plat/arm/board/corstone700/common/include/platform_def.h
index c92086c..57b0551 100644
--- a/plat/arm/board/corstone700/common/include/platform_def.h
+++ b/plat/arm/board/corstone700/common/include/platform_def.h
@@ -93,10 +93,23 @@
 #define ARM_FW_CONFIG_LIMIT		(ARM_BL_RAM_BASE + (PAGE_SIZE / 2U))
 
 /*
+ * Boot parameters passed from BL2 to BL31/BL32 are stored here
+ */
+#define ARM_BL2_MEM_DESC_BASE		(ARM_FW_CONFIG_LIMIT)
+#define ARM_BL2_MEM_DESC_LIMIT		(ARM_BL2_MEM_DESC_BASE \
+					+ (PAGE_SIZE / 2U))
+
+/*
+ * Define limit of firmware configuration memory:
+ * ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory
+ */
+#define ARM_FW_CONFIGS_LIMIT		(ARM_BL_RAM_BASE + (PAGE_SIZE * 2))
+
+/*
  * The max number of regions like RO(code), coherent and data required by
  * different BL stages which need to be mapped in the MMU.
  */
-#define ARM_BL_REGIONS			2
+#define ARM_BL_REGIONS			3
 #define PLAT_ARM_MMAP_ENTRIES		8
 #define MAX_XLAT_TABLES			5
 #define MAX_MMAP_REGIONS		(PLAT_ARM_MMAP_ENTRIES +        \
@@ -201,6 +214,14 @@
 						MT_DEVICE | MT_RW | MT_SECURE)
 #endif
 
+/*
+ * Map the region for device tree configuration with read and write permissions
+ */
+#define ARM_MAP_BL_CONFIG_REGION	MAP_REGION_FLAT(ARM_BL_RAM_BASE,	\
+						(ARM_FW_CONFIGS_LIMIT		\
+							- ARM_BL_RAM_BASE),	\
+						MT_MEMORY | MT_RW | MT_SECURE)
+
 #define CORSTONE700_DEVICE_BASE		(0x1A000000)
 #define CORSTONE700_DEVICE_SIZE		(0x26000000)
 #define CORSTONE700_MAP_DEVICE		MAP_REGION_FLAT(		\
diff --git a/plat/arm/board/fvp_ve/include/platform_def.h b/plat/arm/board/fvp_ve/include/platform_def.h
index 3591b4d..3f2fcee 100644
--- a/plat/arm/board/fvp_ve/include/platform_def.h
+++ b/plat/arm/board/fvp_ve/include/platform_def.h
@@ -121,10 +121,19 @@
 #endif
 
 /*
+ * Map the region for device tree configuration with read and write permissions
+ */
+#define ARM_MAP_BL_CONFIG_REGION	MAP_REGION_FLAT(ARM_BL_RAM_BASE,	\
+						(ARM_FW_CONFIGS_LIMIT		\
+							- ARM_BL_RAM_BASE),	\
+						MT_MEMORY | MT_RW | MT_SECURE)
+
+
+/*
  * The max number of regions like RO(code), coherent and data required by
  * different BL stages which need to be mapped in the MMU.
  */
-#define ARM_BL_REGIONS			5
+#define ARM_BL_REGIONS			6
 
 #define MAX_MMAP_REGIONS		(PLAT_ARM_MMAP_ENTRIES +	\
 					 ARM_BL_REGIONS)
@@ -173,7 +182,14 @@
  * and limit. Leave enough space of BL2 meminfo.
  */
 #define ARM_FW_CONFIG_BASE		(ARM_BL_RAM_BASE + sizeof(meminfo_t))
-#define ARM_FW_CONFIG_LIMIT		(ARM_BL_RAM_BASE + PAGE_SIZE)
+#define ARM_FW_CONFIG_LIMIT		((ARM_BL_RAM_BASE + PAGE_SIZE) \
+					+ (PAGE_SIZE / 2U))
+
+/*
+ * Define limit of firmware configuration memory:
+ * ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory
+ */
+#define ARM_FW_CONFIGS_LIMIT		(ARM_BL_RAM_BASE + (PAGE_SIZE * 2))
 
 /*******************************************************************************
  * BL1 specific defines.
@@ -205,6 +221,8 @@
 
 /* Put BL32 below BL2 in NS DRAM.*/
 #define ARM_BL2_MEM_DESC_BASE		ARM_FW_CONFIG_LIMIT
+#define ARM_BL2_MEM_DESC_LIMIT		(ARM_BL2_MEM_DESC_BASE \
+					+ (PAGE_SIZE / 2U))
 
 #define BL32_BASE			((ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)\
 						- PLAT_ARM_MAX_BL32_SIZE)
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index 6b630b9..4b2a062 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -54,6 +54,9 @@
 /* Data structure which holds the extents of the trusted SRAM for BL1*/
 static meminfo_t bl1_tzram_layout;
 
+/* Boolean variable to hold condition whether firmware update needed or not */
+static bool is_fwu_needed;
+
 struct meminfo *bl1_plat_sec_mem_layout(void)
 {
 	return &bl1_tzram_layout;
@@ -152,15 +155,15 @@
 	plat_arm_io_setup();
 
 	/* Check if we need FWU before further processing */
-	err = plat_arm_bl1_fwu_needed();
-	if (err) {
+	is_fwu_needed = plat_arm_bl1_fwu_needed();
+	if (is_fwu_needed) {
 		ERROR("Skip platform setup as FWU detected\n");
 		return;
 	}
 
 	/* Set global DTB info for fixed fw_config information */
 	fw_config_max_size = ARM_FW_CONFIG_LIMIT - ARM_FW_CONFIG_BASE;
-	set_fw_config_info(ARM_FW_CONFIG_BASE, fw_config_max_size);
+	set_config_info(ARM_FW_CONFIG_BASE, fw_config_max_size, FW_CONFIG_ID);
 
 	/* Fill the device tree information struct with the info from the config dtb */
 	err = fconf_load_config(FW_CONFIG_ID);
@@ -247,5 +250,5 @@
  ******************************************************************************/
 unsigned int bl1_plat_get_next_image_id(void)
 {
-	return plat_arm_bl1_fwu_needed() ? NS_BL1U_IMAGE_ID : BL2_IMAGE_ID;
+	return  is_fwu_needed ? NS_BL1U_IMAGE_ID : BL2_IMAGE_ID;
 }
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index 80f3b32..60d8f6e 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -26,6 +26,9 @@
 /* Data structure which holds the extents of the trusted SRAM for BL2 */
 static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
 
+/* Base address of fw_config received from BL1 */
+static uintptr_t fw_config_base;
+
 /*
  * Check that BL2_BASE is above ARM_FW_CONFIG_LIMIT. This reserved page is
  * for `meminfo_t` data structure and fw_configs passed from BL1.
@@ -57,21 +60,13 @@
 void arm_bl2_early_platform_setup(uintptr_t fw_config,
 				  struct meminfo *mem_layout)
 {
-	const struct dyn_cfg_dtb_info_t *tb_fw_config_info;
 	/* Initialize the console to provide early debug support */
 	arm_console_boot_init();
 
 	/* Setup the BL2 memory layout */
 	bl2_tzram_layout = *mem_layout;
 
-	/* Fill the properties struct with the info from the config dtb */
-	fconf_populate("FW_CONFIG", fw_config);
-
-	/* TB_FW_CONFIG was also loaded by BL1 */
-	tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID);
-	assert(tb_fw_config_info != NULL);
-
-	fconf_populate("TB_FW", tb_fw_config_info->config_addr);
+	fw_config_base = fw_config;
 
 	/* Initialise the IO layer and register platform IO devices */
 	plat_arm_io_setup();
@@ -135,6 +130,7 @@
 #if ARM_CRYPTOCELL_INTEG
 		ARM_MAP_BL_COHERENT_RAM,
 #endif
+		ARM_MAP_BL_CONFIG_REGION,
 		{0}
 	};
 
@@ -151,7 +147,18 @@
 
 void bl2_plat_arch_setup(void)
 {
+	const struct dyn_cfg_dtb_info_t *tb_fw_config_info;
+
 	arm_bl2_plat_arch_setup();
+
+	/* Fill the properties struct with the info from the config dtb */
+	fconf_populate("FW_CONFIG", fw_config_base);
+
+	/* TB_FW_CONFIG was also loaded by BL1 */
+	tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID);
+	assert(tb_fw_config_info != NULL);
+
+	fconf_populate("TB_FW", tb_fw_config_info->config_addr);
 }
 
 int arm_bl2_handle_post_image_load(unsigned int image_id)
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index ded8f89..58ccf0e 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -114,6 +114,18 @@
 	SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
 	bl32_image_ep_info.pc = BL32_BASE;
 	bl32_image_ep_info.spsr = arm_get_spsr_for_bl32_entry();
+
+#if defined(SPD_spmd)
+	/* SPM (hafnium in secure world) expects SPM Core manifest base address
+	 * in x0, which in !RESET_TO_BL31 case loaded after base of non shared
+	 * SRAM(after 4KB offset of SRAM). But in RESET_TO_BL31 case all non
+	 * shared SRAM is allocated to BL31, so to avoid overwriting of manifest
+	 * keep it in the last page.
+	 */
+	bl32_image_ep_info.args.arg0 = ARM_TRUSTED_SRAM_BASE +
+				PLAT_ARM_TRUSTED_SRAM_SIZE - PAGE_SIZE;
+#endif
+
 # endif /* BL32_BASE */
 
 	/* Populate entry point information for BL33 */
@@ -130,6 +142,14 @@
 	bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry();
 	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
 
+#if defined(SPD_spmd) && !(ARM_LINUX_KERNEL_AS_BL33)
+	/*
+	 * Hafnium in normal world expects its manifest address in x0, which
+	 * is loaded at base of DRAM.
+	 */
+	bl33_image_ep_info.args.arg0 = (u_register_t)ARM_DRAM1_BASE;
+#endif
+
 # if ARM_LINUX_KERNEL_AS_BL33
 	/*
 	 * According to the file ``Documentation/arm64/booting.txt`` of the
diff --git a/plat/arm/common/arm_common.c b/plat/arm/common/arm_common.c
index 60c777e..e2b99a3 100644
--- a/plat/arm/common/arm_common.c
+++ b/plat/arm/common/arm_common.c
@@ -13,7 +13,9 @@
 #include <common/debug.h>
 #include <common/romlib.h>
 #include <lib/mmio.h>
+#include <lib/smccc.h>
 #include <lib/xlat_tables/xlat_tables_compat.h>
+#include <services/arm_arch_svc.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 
@@ -235,6 +237,23 @@
 }
 #endif
 
+/*****************************************************************************
+ * plat_is_smccc_feature_available() - This function checks whether SMCCC
+ *                                     feature is availabile for platform.
+ * @fid: SMCCC function id
+ *
+ * Return SMC_OK if SMCCC feature is available and SMC_ARCH_CALL_NOT_SUPPORTED
+ * otherwise.
+ *****************************************************************************/
+int32_t plat_is_smccc_feature_available(u_register_t fid)
+{
+	switch (fid) {
+	case SMCCC_ARCH_SOC_ID:
+	default:
+		return SMC_ARCH_CALL_NOT_SUPPORTED;
+	}
+}
+
 /*
  * Weak function to get ARM platform SOC-ID, Always return SOC-ID=0
  * ToDo: Get proper SOC-ID for every ARM platform and define this
diff --git a/plat/arm/common/arm_dyn_cfg.c b/plat/arm/common/arm_dyn_cfg.c
index b31870b..6b3a611 100644
--- a/plat/arm/common/arm_dyn_cfg.c
+++ b/plat/arm/common/arm_dyn_cfg.c
@@ -203,7 +203,7 @@
 	unsigned int i;
 	bl_mem_params_node_t *cfg_mem_params = NULL;
 	uintptr_t image_base;
-	size_t image_size;
+	uint32_t image_size;
 	const unsigned int config_ids[] = {
 			HW_CONFIG_ID,
 			SOC_FW_CONFIG_ID,
diff --git a/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts b/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts
index e416540..54b2423 100644
--- a/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts
+++ b/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts
@@ -8,7 +8,7 @@
 
 / {
 	/* Platform Config */
-	plat_arm_bl2 {
+	tb_fw-config {
 		compatible = "arm,tb_fw";
 		hw_config_addr = <0x0 0x83000000>;
 		hw_config_max_size = <0x01000000>;
diff --git a/plat/common/plat_bl_common.c b/plat/common/plat_bl_common.c
index d38fc6f..89b77ba 100644
--- a/plat/common/plat_bl_common.c
+++ b/plat/common/plat_bl_common.c
@@ -11,6 +11,7 @@
 #include <common/debug.h>
 #include <lib/xlat_tables/xlat_tables_compat.h>
 #include <plat/common/platform.h>
+#include <services/arm_arch_svc.h>
 #include <smccc_helpers.h>
 #include <tools_share/firmware_encrypted.h>
 
@@ -25,6 +26,7 @@
 #pragma weak bl2_plat_handle_post_image_load
 #pragma weak plat_try_next_boot_source
 #pragma weak plat_get_enc_key_info
+#pragma weak plat_is_smccc_feature_available
 #pragma weak plat_get_soc_version
 #pragma weak plat_get_soc_revision
 
@@ -38,6 +40,11 @@
 	return SMC_ARCH_CALL_NOT_SUPPORTED;
 }
 
+int32_t plat_is_smccc_feature_available(u_register_t fid __unused)
+{
+	return SMC_ARCH_CALL_NOT_SUPPORTED;
+}
+
 void bl2_el3_plat_prepare_exit(void)
 {
 }
diff --git a/plat/imx/common/imx_sip_handler.c b/plat/imx/common/imx_sip_handler.c
index 62048b6..f9f5577 100644
--- a/plat/imx/common/imx_sip_handler.c
+++ b/plat/imx/common/imx_sip_handler.c
@@ -4,6 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <arch.h>
 #include <stdlib.h>
 #include <stdint.h>
 #include <services/std_svc.h>
@@ -12,6 +13,7 @@
 #include <common/debug.h>
 #include <common/runtime_svc.h>
 #include <imx_sip_svc.h>
+#include <lib/el3_runtime/context_mgmt.h>
 #include <sci/sci.h>
 
 #if defined(PLAT_imx8qm) || defined(PLAT_imx8qx)
@@ -185,3 +187,37 @@
 
 	return ret;
 }
+
+int imx_kernel_entry_handler(uint32_t smc_fid,
+		u_register_t x1,
+		u_register_t x2,
+		u_register_t x3,
+		u_register_t x4)
+{
+	static entry_point_info_t bl33_image_ep_info;
+	entry_point_info_t *next_image_info;
+	unsigned int mode;
+
+	if (x1 < (PLAT_NS_IMAGE_OFFSET & 0xF0000000))
+		return SMC_UNK;
+
+	mode = MODE32_svc;
+
+	next_image_info = &bl33_image_ep_info;
+
+	next_image_info->pc = x1;
+
+	next_image_info->spsr = SPSR_MODE32(mode, SPSR_T_ARM, SPSR_E_LITTLE,
+			(DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT));
+
+	next_image_info->args.arg0 = 0;
+	next_image_info->args.arg1 = 0;
+	next_image_info->args.arg2 = x3;
+
+	SET_SECURITY_STATE(next_image_info->h.attr, NON_SECURE);
+
+	cm_init_my_context(next_image_info);
+	cm_prepare_el3_exit(NON_SECURE);
+
+	return 0;
+}
diff --git a/plat/imx/common/imx_sip_svc.c b/plat/imx/common/imx_sip_svc.c
index 4893b9f..20e1479 100644
--- a/plat/imx/common/imx_sip_svc.c
+++ b/plat/imx/common/imx_sip_svc.c
@@ -26,6 +26,9 @@
 			u_register_t flags)
 {
 	switch (smc_fid) {
+	case IMX_SIP_AARCH32:
+		SMC_RET1(handle, imx_kernel_entry_handler(smc_fid, x1, x2, x3, x4));
+		break;
 #if defined(PLAT_imx8mq)
 	case IMX_SIP_GET_SOC_INFO:
 		SMC_RET1(handle, imx_soc_info_handler(smc_fid, x1, x2, x3));
diff --git a/plat/imx/common/include/imx_sip_svc.h b/plat/imx/common/include/imx_sip_svc.h
index 5898f7a..0a2d750 100644
--- a/plat/imx/common/include/imx_sip_svc.h
+++ b/plat/imx/common/include/imx_sip_svc.h
@@ -28,6 +28,11 @@
 
 #define IMX_SIP_MISC_SET_TEMP		0xC200000C
 
+#define IMX_SIP_AARCH32			0xC20000FD
+
+int imx_kernel_entry_handler(uint32_t smc_fid, u_register_t x1,
+			     u_register_t x2, u_register_t x3,
+			     u_register_t x4);
 #if defined(PLAT_imx8mq)
 int imx_soc_info_handler(uint32_t smc_fid, u_register_t x1,
 			 u_register_t x2, u_register_t x3);
diff --git a/plat/nvidia/tegra/common/tegra_platform.c b/plat/nvidia/tegra/common/tegra_platform.c
index e4338b9..0804135 100644
--- a/plat/nvidia/tegra/common/tegra_platform.c
+++ b/plat/nvidia/tegra/common/tegra_platform.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
  * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -8,6 +8,8 @@
 #include <arch_helpers.h>
 #include <assert.h>
 #include <lib/mmio.h>
+#include <lib/smccc.h>
+#include <services/arm_arch_svc.h>
 #include <tegra_def.h>
 #include <tegra_platform.h>
 #include <tegra_private.h>
@@ -286,3 +288,21 @@
 {
 	return (int32_t)((tegra_get_chipid_major() << 8) | tegra_get_chipid_minor());
 }
+
+/*****************************************************************************
+ * plat_smccc_feature_available() - This function checks whether SMCCC feature
+ *                                  is availabile for the platform or not.
+ * @fid: SMCCC function id
+ *
+ * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and
+ * SMC_ARCH_CALL_NOT_SUPPORTED otherwise.
+ *****************************************************************************/
+int32_t plat_smccc_feature_available(u_register_t fid)
+{
+	switch (fid) {
+	case SMCCC_ARCH_SOC_ID:
+		return SMC_ARCH_CALL_SUCCESS;
+	default:
+		return SMC_ARCH_CALL_NOT_SUPPORTED;
+	}
+}
diff --git a/services/arm_arch_svc/arm_arch_svc_setup.c b/services/arm_arch_svc/arm_arch_svc_setup.c
index 588656d..37bfc62 100644
--- a/services/arm_arch_svc/arm_arch_svc_setup.c
+++ b/services/arm_arch_svc/arm_arch_svc_setup.c
@@ -24,8 +24,9 @@
 	switch (arg1) {
 	case SMCCC_VERSION:
 	case SMCCC_ARCH_FEATURES:
+		return SMC_ARCH_CALL_SUCCESS;
 	case SMCCC_ARCH_SOC_ID:
-		return SMC_OK;
+		return plat_is_smccc_feature_available(arg1);
 #if WORKAROUND_CVE_2017_5715
 	case SMCCC_ARCH_WORKAROUND_1:
 		if (check_wa_cve_2017_5715() == ERRATA_NOT_APPLIES)