Merge "feat(sme): fall back to SVE if SME is not there" into integration
diff --git a/changelog.yaml b/changelog.yaml
index 37a9c6d..01e91b4 100644
--- a/changelog.yaml
+++ b/changelog.yaml
@@ -563,6 +563,9 @@
           - title: TRP
             scope: trp
 
+          - title: RMMD
+            scope: rmmd
+
       - title: SPM
         scope: spm
 
diff --git a/docs/components/index.rst b/docs/components/index.rst
index 2f81f23..192773f 100644
--- a/docs/components/index.rst
+++ b/docs/components/index.rst
@@ -24,4 +24,5 @@
    xlat-tables-lib-v2-design
    cot-binding
    realm-management-extension
+   rmm-el3-comms-spec
    granule-protection-tables-design
diff --git a/docs/components/realm-management-extension.rst b/docs/components/realm-management-extension.rst
index 5fa5140..ea921fc 100644
--- a/docs/components/realm-management-extension.rst
+++ b/docs/components/realm-management-extension.rst
@@ -73,6 +73,14 @@
 world. It initializes the RMM and handles Realm Management Interface (RMI)
 SMC calls from Non-secure and Realm worlds.
 
+There is a contract between RMM and RMMD that defines the arguments that the
+former needs to take in order to initialize and also the possible return values.
+This contract is defined in the RMM Boot Interface, which can be found at
+:ref:`rmm_el3_boot_interface`.
+
+There is also a specification of the runtime services provided by TF-A
+to RMM. This can be found at :ref:`runtime_services_and_interface`.
+
 Test Realm Payload (TRP)
 *************************
 TRP is a small test payload that runs at R-EL2 and implements a subset of
diff --git a/docs/components/rmm-el3-comms-spec.rst b/docs/components/rmm-el3-comms-spec.rst
new file mode 100644
index 0000000..9140d54
--- /dev/null
+++ b/docs/components/rmm-el3-comms-spec.rst
@@ -0,0 +1,413 @@
+RMM-EL3 Communication interface
+*******************************
+
+This document defines the communication interface between RMM and EL3.
+There are two parts in this interface: the boot interface and the runtime
+interface.
+
+The Boot Interface defines the ABI between EL3 and RMM when the CPU enters
+R-EL2 for the first time after boot. The cold boot interface defines the ABI
+for the cold boot path and the warm boot interface defines the same for the
+warm path.
+
+The RMM-EL3 runtime interface defines the ABI for EL3 services which can be
+invoked by RMM as well as the register save-restore convention when handling an
+SMC call from NS.
+
+The below sections discuss these interfaces more in detail.
+
+.. _rmm_el3_ifc_versioning:
+
+RMM-EL3 Interface versioning
+____________________________
+
+The RMM Boot and Runtime Interface uses a version number to check
+compatibility with the register arguments passed as part of Boot Interface and
+RMM-EL3 runtime interface.
+
+The Boot Manifest, discussed later in section :ref:`rmm_el3_boot_manifest`,
+uses a separate version number but with the same scheme.
+
+The version number is a 32-bit type with the following fields:
+
+.. csv-table::
+   :header: "Bits", "Value"
+
+   [0:15],``VERSION_MINOR``
+   [16:30],``VERSION_MAJOR``
+   [31],RES0
+
+The version numbers are sequentially increased and the rules for updating them
+are explained below:
+
+  - ``VERSION_MAJOR``: This value is increased when changes break
+    compatibility with previous versions. If the changes
+    on the ABI are compatible with the previous one, ``VERSION_MAJOR``
+    remains unchanged.
+
+  - ``VERSION_MINOR``: This value is increased on any change that is backwards
+    compatible with the previous version. When ``VERSION_MAJOR`` is increased,
+    ``VERSION_MINOR`` must be set to 0.
+
+  - ``RES0``: Bit 31 of the version number is reserved 0 as to maintain
+    consistency with the versioning schemes used in other parts of RMM.
+
+This document specifies the 0.1 version of Boot Interface ABI and RMM-EL3
+services specification and the 0.1 version of the Boot Manifest.
+
+.. _rmm_el3_boot_interface:
+
+RMM Boot Interface
+__________________
+
+This section deals with the Boot Interface part of the specification.
+
+One of the goals of the Boot Interface is to allow EL3 firmware to pass
+down into RMM certain platform specific information dynamically. This allows
+RMM to be less platform dependent and be more generic across platform
+variations. It also allows RMM to be decoupled from the other boot loader
+images in the boot sequence and remain agnostic of any particular format used
+for configuration files.
+
+The Boot Interface ABI defines a set of register conventions and
+also a memory based manifest file to pass information from EL3 to RMM. The
+boot manifest and the associated platform data in it can be dynamically created
+by EL3 and there is no restriction on how the data can be obtained (e.g by DTB,
+hoblist or other).
+
+The register convention and the manifest are versioned separately to manage
+future enhancements and compatibility.
+
+RMM completes the boot by issuing the ``RMM_BOOT_COMPLETE`` SMC (0xC40001CF)
+back to EL3. After the RMM has finished the boot process, it can only be
+entered from EL3 as part of RMI handling.
+
+If RMM returns an error during boot (in any CPU), then RMM must not be entered
+from any CPU.
+
+.. _rmm_cold_boot_interface:
+
+Cold Boot Interface
+~~~~~~~~~~~~~~~~~~~
+
+During cold boot RMM expects the following register values:
+
+.. csv-table::
+   :header: "Register", "Value"
+   :widths: 1, 5
+
+   x0,Linear index of this PE. This index starts from 0 and must be less than the maximum number of CPUs to be supported at runtime (see x2).
+   x1,Version for this Boot Interface as defined in :ref:`rmm_el3_ifc_versioning`.
+   x2,Maximum number of CPUs to be supported at runtime. RMM should ensure that it can support this maximum number.
+   x3,Base address for the shared buffer used for communication between EL3 firmware and RMM. This buffer must be of 4KB size (1 page). The boot manifest must be present at the base of this shared buffer during cold boot.
+
+During cold boot, EL3 firmware needs to allocate a 4K page that will be
+passed to RMM in x3. This memory will be used as shared buffer for communication
+between EL3 and RMM. It must be assigned to Realm world and must be mapped with
+Normal memory attributes (IWB-OWB-ISH) at EL3. At boot, this memory will be
+used to populate the Boot Manifest. Since the Boot Manifest can be accessed by
+RMM prior to enabling its MMU, EL3 must ensure that proper cache maintenance
+operations are performed after the Boot Manifest is populated.
+
+EL3 should also ensure that this shared buffer is always available for use by RMM
+during the lifetime of the system and that it can be used for runtime
+communication between RMM and EL3. For example, when RMM invokes attestation
+service commands in EL3, this buffer can be used to exchange data between RMM
+and EL3. It is also allowed for RMM to invoke runtime services provided by EL3
+utilizing this buffer during the boot phase, prior to return back to EL3 via
+RMM_BOOT_COMPLETE SMC.
+
+RMM should map this memory page into its Stage 1 page-tables using Normal
+memory attributes.
+
+During runtime, it is the RMM which initiates any communication with EL3. If that
+communication requires the use of the shared area, it is expected that RMM needs
+to do the necessary concurrency protection to prevent the use of the same buffer
+by other PEs.
+
+The following sequence diagram shows how a generic EL3 Firmware would boot RMM.
+
+.. image:: ../resources/diagrams/rmm_cold_boot_generic.png
+
+Warm Boot Interface
+~~~~~~~~~~~~~~~~~~~
+
+At warm boot, RMM is already initialized and only some per-CPU initialization
+is still pending. The only argument that is required by RMM at this stage is
+the CPU Id, which will be passed through register x0 whilst x1 to x3 are RES0.
+This is summarized in the following table:
+
+.. csv-table::
+   :header: "Register", "Value"
+   :widths: 1, 5
+
+   x0,Linear index of this PE. This index starts from 0 and must be less than the maximum number of CPUs to be supported at runtime (see x2).
+   x1 - x3,RES0
+
+Boot error handling and return values
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+After boot up and initialization, RMM returns control back to EL3 through a
+``RMM_BOOT_COMPLETE`` SMC call. The only argument of this SMC call will
+be returned in x1 and it will encode a signed integer with the error reason
+as per the following table:
+
+.. csv-table::
+   :header: "Error code", "Description", "ID"
+   :widths: 2 4 1
+
+   ``E_RMM_BOOT_SUCCESS``,Boot successful,0
+   ``E_RMM_BOOT_ERR_UNKNOWN``,Unknown error,-1
+   ``E_RMM_BOOT_VERSION_NOT_VALID``,Boot Interface version reported by EL3 is not supported by RMM,-2
+   ``E_RMM_BOOT_CPUS_OUT_OF_RAGE``,Number of CPUs reported by EL3 larger than maximum supported by RMM,-3
+   ``E_RMM_BOOT_CPU_ID_OUT_OF_RAGE``,Current CPU Id is higher or equal than the number of CPUs supported by RMM,-4
+   ``E_RMM_BOOT_INVALID_SHARED_BUFFER``,Invalid pointer to shared memory area,-5
+   ``E_RMM_BOOT_MANIFEST_VERSION_NOT_SUPPORTED``,Version reported by the boot manifest not supported by RMM,-6
+   ``E_RMM_BOOT_MANIFEST_DATA_ERROR``,Error parsing core boot manifest,-7
+
+For any error detected in RMM during cold or warm boot, RMM will return back to
+EL3 using ``RMM_BOOT_COMPLETE`` SMC with an appropriate error code. It is
+expected that EL3 will take necessary action to disable Realm world for further
+entry from NS Host on receiving an error. This will be done across all the PEs
+in the system so as to present a symmetric view to the NS Host. Any further
+warm boot by any PE should not enter RMM using the warm boot interface.
+
+.. _rmm_el3_boot_manifest:
+
+Boot Manifest
+~~~~~~~~~~~~~
+
+During cold boot, EL3 Firmware passes a memory boot manifest to RMM containing
+platform information.
+
+This boot manifest is versioned independently of the boot interface, to help
+evolve the boot manifest independent of the rest of Boot Manifest.
+The current version for the boot manifest is ``v0.1`` and the rules explained
+in :ref:`rmm_el3_ifc_versioning` apply on this version as well.
+
+The boot manifest is divided into two different components:
+
+   - Core Manifest: This is the generic parameters passed to RMM by EL3 common to all platforms.
+   - Platform data: This is defined by the platform owner and contains information specific to that platform.
+
+For the current version of the manifest, the core manifest contains a pointer
+to the platform data. EL3 must ensure that the whole boot manifest,
+including the platform data, if available, fits inside the RMM EL3 shared
+buffer.
+
+For the type specification of the RMM Boot Manifest v0.1, refer to
+:ref:`rmm_el3_manifest_struct`
+
+.. _runtime_services_and_interface:
+
+RMMM-EL3 Runtime Interface
+__________________________
+
+This section defines the RMM-EL3 runtime interface which specifies the ABI for
+EL3 services expected by RMM at runtime as well as the register save and
+restore convention between EL3 and RMM as part of RMI call handling. It is
+important to note that RMM is allowed to invoke EL3-RMM runtime interface
+services during the boot phase as well. The EL3 runtime service handling must
+not result in a world switch to another world unless specified. Both the RMM
+and EL3 are allowed to make suitable optimizations based on this assumption.
+
+If the interface requires the use of memory, then the memory references should
+be within the shared buffer communicated as part of the boot interface. See
+:ref:`rmm_cold_boot_interface` for properties of this shared buffer which both
+EL3 and RMM must adhere to.
+
+RMM-EL3 runtime service return codes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The return codes from EL3 to RMM is a 32 bit signed integer which encapsulates
+error condition as described in the following table:
+
+.. csv-table::
+   :header: "Error code", "Description", "ID"
+   :widths: 2 4 1
+
+   ``E_RMM_OK``,No errors detected,0
+   ``E_RMM_UNK``,Unknown/Generic error,-1
+   ``E_RMM_BAD_ADDR``,The value of an address used as argument was invalid,-2
+   ``E_RMM_BAD_PAS``,Incorrect PAS,-3
+   ``E_RMM_NOMEM``,Not enough memory to perform an operation,-4
+   ``E_RMM_INVAL``,The value of an argument was invalid,-5
+
+If multiple failure conditions are detected in an RMM to EL3 command, then EL3
+is allowed to return an error code corresponding to any of the failure
+conditions.
+
+RMM-EL3 runtime services
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following table summarizes the RMM runtime services that need to be
+implemented by EL3 Firmware.
+
+.. csv-table::
+   :header: "FID", "Command"
+   :widths: 2 5
+
+   0xC40001B2,``RMM_ATTEST_GET_REALM_KEY``
+   0xC40001B3,``RMM_ATTEST_GET_PLAT_TOKEN``
+
+RMM_ATTEST_GET_REALM_KEY command
+================================
+
+Retrieve the Realm Attestation Token Signing key from EL3.
+
+FID
+---
+
+``0xC40001B2``
+
+Input values
+------------
+
+.. csv-table::
+   :header: "Name", "Register", "Field", "Type", "Description"
+   :widths: 1 1 1 1 5
+
+   fid,x0,[63:0],UInt64,Command FID
+   buf_pa,x1,[63:0],Address,PA where the Realm Attestation Key must be stored by EL3. The PA must belong to the shared buffer
+   buf_size,x2,[63:0],Size,Size in bytes of the Realm Attestation Key buffer. ``bufPa + bufSize`` must lie within the shared buffer
+   ecc_curve,x3,[63:0],Enum,Type of the elliptic curve to which the requested attestation key belongs to. See :ref:`ecc_curves`
+
+Output values
+-------------
+
+.. csv-table::
+   :header: "Name", "Register", "Field", "Type", "Description"
+   :widths: 1 1 1 1 5
+
+   Result,x0,[63:0],Error Code,Command return status
+   keySize,x1,[63:0],Size,Size of the Realm Attestation Key
+
+Failure conditions
+------------------
+
+The table below shows all the possible error codes returned in ``Result`` upon
+a failure. The errors are ordered by condition check.
+
+.. csv-table::
+   :header: "ID", "Condition"
+   :widths: 1 5
+
+   ``E_RMM_BAD_ADDR``,``PA`` is outside the shared buffer
+   ``E_RMM_INVAL``,``PA + BSize`` is outside the shared buffer
+   ``E_RMM_INVAL``,``Curve`` is not one of the listed in :ref:`ecc_curves`
+   ``E_RMM_UNK``,An unknown error occurred whilst processing the command
+   ``E_RMM_OK``,No errors detected
+
+.. _ecc_curves:
+
+Supported ECC Curves
+--------------------
+
+.. csv-table::
+   :header: "ID", "Curve"
+   :widths: 1 5
+
+   0,ECC SECP384R1
+
+RMM_ATTEST_GET_PLAT_TOKEN command
+=================================
+
+Retrieve the Platform Token from EL3.
+
+FID
+---
+
+``0xC40001B3``
+
+Input values
+------------
+
+.. csv-table::
+   :header: "Name", "Register", "Field", "Type", "Description"
+   :widths: 1 1 1 1 5
+
+   fid,x0,[63:0],UInt64,Command FID
+   buf_pa,x1,[63:0],Address,PA of the platform attestation token. The challenge object is passed in this buffer. The PA must belong to the shared buffer
+   buf_size,x2,[63:0],Size,Size in bytes of the platform attestation token buffer. ``bufPa + bufSize`` must lie within the shared buffer
+   c_size,x3,[63:0],Size,Size in bytes of the challenge object. It corresponds to the size of one of the defined SHA algorithms
+
+Output values
+-------------
+
+.. csv-table::
+   :header: "Name", "Register", "Field", "Type", "Description"
+   :widths: 1 1 1 1 5
+
+   Result,x0,[63:0],Error Code,Command return status
+   tokenSize,x1,[63:0],Size,Size of the platform token
+
+Failure conditions
+------------------
+
+The table below shows all the possible error codes returned in ``Result`` upon
+a failure. The errors are ordered by condition check.
+
+.. csv-table::
+   :header: "ID", "Condition"
+   :widths: 1 5
+
+   ``E_RMM_BAD_ADDR``,``PA`` is outside the shared buffer
+   ``E_RMM_INVAL``,``PA + BSize`` is outside the shared buffer
+   ``E_RMM_INVAL``,``CSize`` does not represent the size of a supported SHA algorithm
+   ``E_RMM_UNK``,An unknown error occurred whilst processing the command
+   ``E_RMM_OK``,No errors detected
+
+RMM-EL3 world switch register save restore convention
+_____________________________________________________
+
+As part of NS world switch, EL3 is expected to maintain a register context
+specific to each world and will save and restore the registers
+appropriately. This section captures the contract between EL3 and RMM on the
+register set to be saved and restored.
+
+EL3 must maintain a separate register context for the following:
+
+   #. General purpose registers (x0-x30) and ``sp_el0``, ``sp_el2`` stack pointers
+   #. EL2 system register context for all enabled features by EL3. These include system registers with the ``_EL2`` prefix. The EL2 physical and virtual timer registers must not be included in this.
+
+It is the responsibility of EL3 that the above registers will not be leaked to
+the NS Host and to maintain the confidentiality of the Realm World.
+
+EL3 will not save some registers as mentioned in the below list. It is the
+responsibility of RMM to ensure that these are appropriately saved if the
+Realm World makes use of them:
+
+   #. FP/SIMD registers
+   #. SVE registers
+   #. SME registers
+   #. EL1/0 registers
+
+SMCCC v1.3 allows NS world to specify whether SVE context is in use. In this
+case, RMM could choose to not save the incoming SVE context but must ensure
+to clear SVE registers if they have been used in Realm World. The same applies
+to SME registers.
+
+Types
+_____
+
+.. _rmm_el3_manifest_struct:
+
+RMM-EL3 Boot Manifest Version
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The RMM-EL3 Boot Manifest structure contains platform boot information passed
+from EL3 to RMM. The width of the Boot Manifest is 128 bits
+
+.. image:: ../resources/diagrams/rmm_el3_manifest_struct.png
+
+The members of the RMM-EL3 Boot Manifest structure are shown in the following
+table:
+
+.. csv-table::
+   :header: "Name", "Range", "Type", Description
+   :widths: 2 1 1 4
+
+   ``Version Minor``,15:0,uint16_t,Version Minor part of the Boot Manifest Version.
+   ``Version Major``,30:16,uint16_t,Version Major part of the Boot Manifest Version.
+   ``RES0``,31,bit,Reserved. Set to 0.
+   ``Platform Data``,127:64,Address,Pointer to the Platform Data section of the Boot Manifest.
diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst
index 2c6a005..d49ddeb 100644
--- a/docs/getting_started/porting-guide.rst
+++ b/docs/getting_started/porting-guide.rst
@@ -89,6 +89,8 @@
 The following variables, functions and constants must be defined by the platform
 for the firmware to work correctly.
 
+.. _platform_def_mandatory:
+
 File : platform_def.h [mandatory]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -2017,7 +2019,7 @@
 (that was copied during ``bl31_early_platform_setup()``) if the image exists. It
 should return NULL otherwise.
 
-Function : plat_get_cca_attest_token() [mandatory when ENABLE_RME == 1]
+Function : plat_rmmd_get_cca_attest_token() [mandatory when ENABLE_RME == 1]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 ::
@@ -2043,8 +2045,8 @@
 
 The function returns 0 on success, -EINVAL on failure.
 
-Function : plat_get_cca_realm_attest_key() [mandatory when ENABLE_RME == 1]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Function : plat_rmmd_get_cca_realm_attest_key() [mandatory when ENABLE_RME == 1]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 ::
 
@@ -2069,6 +2071,31 @@
 
 The function returns 0 on success, -EINVAL on failure.
 
+Function : plat_rmmd_get_el3_rmm_shared_mem() [when ENABLE_RME == 1]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+   Argument : uintptr_t *
+   Return   : size_t
+
+This function returns the size of the shared area between EL3 and RMM (or 0 on
+failure). A pointer to the shared area (or a NULL pointer on failure) is stored
+in the pointer passed as argument.
+
+Function : plat_rmmd_load_manifest() [when ENABLE_RME == 1]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Arguments : rmm_manifest_t *manifest
+    Return    : int
+
+When ENABLE_RME is enabled, this function populates a boot manifest for the
+RMM image and stores it in the area specified by manifest.
+
+When ENABLE_RME is disabled, this function is not used.
+
 Function : bl31_plat_enable_mmu [optional]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/docs/resources/diagrams/Makefile b/docs/resources/diagrams/Makefile
index 7f583b5..4e65569 100644
--- a/docs/resources/diagrams/Makefile
+++ b/docs/resources/diagrams/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -61,7 +61,19 @@
 xlat_align_layers					= "bg,translations"
 xlat_align_opts						=
 
-all:$(RESET_PNGS) $(INT_PNGS) $(XLAT_PNG)
+RMM_DIA					= rmm_cold_boot_generic.dia
+RMM_PNG					= rmm_cold_boot_generic.png
+
+rmm_cold_boot_generic_layers		= "background"
+rmm_cold_boot_generic_opts		=
+
+RMM_EL3_MANIFEST_DIA			= rmm_el3_manifest_struct.dia
+RMM_EL3_MANIFEST_PNG			= rmm_el3_manifest_struct.png
+
+rmm_el3_manifest_struct_layers		= "Background"
+rmm_el3_manifest_struct_opts		=
+
+all:$(RESET_PNGS) $(INT_PNGS) $(XLAT_PNG) $(RMM_PNG) $(RMM_EL3_MANIFEST_PNG)
 
 $(RESET_PNGS):$(RESET_DIA)
 	$(call generate_image,$($(patsubst %.png,%_layers,$@)),$@,png,$($(patsubst %.png,%_opts,$@)),$<)
@@ -72,3 +84,9 @@
 $(XLAT_PNG):$(XLAT_DIA)
 	$(call generate_image,$($(patsubst %.png,%_layers,$@)),$(patsubst %.png,%.svg,$@),svg,$($(patsubst %.png,%_opts,$@)),$<)
 	inkscape -z $(patsubst %.png,%.svg,$@) -e $@ -d 45
+
+$(RMM_PNG):$(RMM_DIA)
+	$(call generate_image,$($(patsubst %.png,%_layers,$@)),$@,png,$($(patsubst %.png,%_opts,$@)),$<)
+
+$(RMM_EL3_MANIFEST_PNG):$(RMM_EL3_MANIFEST_DIA)
+	$(call generate_image,$($(patsubst %.png,%_layers,$@)),$@,png,$($(patsubst %.png,%_opts,$@)),$<)
diff --git a/docs/resources/diagrams/rmm_cold_boot_generic.dia b/docs/resources/diagrams/rmm_cold_boot_generic.dia
new file mode 100644
index 0000000..739a1df
--- /dev/null
+++ b/docs/resources/diagrams/rmm_cold_boot_generic.dia
Binary files differ
diff --git a/docs/resources/diagrams/rmm_cold_boot_generic.png b/docs/resources/diagrams/rmm_cold_boot_generic.png
new file mode 100644
index 0000000..df4c1ba
--- /dev/null
+++ b/docs/resources/diagrams/rmm_cold_boot_generic.png
Binary files differ
diff --git a/docs/resources/diagrams/rmm_el3_manifest_struct.dia b/docs/resources/diagrams/rmm_el3_manifest_struct.dia
new file mode 100644
index 0000000..7b7a9c2
--- /dev/null
+++ b/docs/resources/diagrams/rmm_el3_manifest_struct.dia
Binary files differ
diff --git a/docs/resources/diagrams/rmm_el3_manifest_struct.png b/docs/resources/diagrams/rmm_el3_manifest_struct.png
new file mode 100644
index 0000000..8b5776c
--- /dev/null
+++ b/docs/resources/diagrams/rmm_el3_manifest_struct.png
Binary files differ
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index caab14e..47fbe76 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -79,6 +79,7 @@
  *   - SCP TZC DRAM: If present, DRAM reserved for SCP use
  *   - L1 GPT DRAM: Reserved for L1 GPT if RME is enabled
  *   - REALM DRAM: Reserved for Realm world if RME is enabled
+ *   - TF-A <-> RMM SHARED: Area shared for communication between TF-A and RMM
  *   - AP TZC DRAM: The remaining TZC secured DRAM reserved for AP use
  *
  *              RME enabled(64MB)                RME not enabled(16MB)
@@ -87,11 +88,16 @@
  *              |  AP TZC (~28MB)  |             |  AP TZC (~14MB) |
  *              --------------------             -------------------
  *              |                  |             |                 |
- *              |  REALM (32MB)    |             |  EL3 TZC (2MB)  |
- *              --------------------             -------------------
- *              |                  |             |                 |
- *              |  EL3 TZC (3MB)   |             |    SCP TZC      |
- *              --------------------  0xFFFF_FFFF-------------------
+ *              |   REALM (RMM)    |             |  EL3 TZC (2MB)  |
+ *              |   (32MB - 4KB)   |             -------------------
+ *              --------------------             |                 |
+ *              |                  |             |    SCP TZC      |
+ *              |   TF-A <-> RMM   |  0xFFFF_FFFF-------------------
+ *              |   SHARED (4KB)   |
+ *              --------------------
+ *              |                  |
+ *              |  EL3 TZC (3MB)   |
+ *              --------------------
  *              | L1 GPT + SCP TZC |
  *              |       (~1MB)     |
  *  0xFFFF_FFFF --------------------
@@ -106,12 +112,17 @@
  */
 #define ARM_EL3_TZC_DRAM1_SIZE		UL(0x00300000) /* 3MB */
 #define ARM_L1_GPT_SIZE			UL(0x00100000) /* 1MB */
-#define ARM_REALM_SIZE			UL(0x02000000) /* 32MB */
+
+/* 32MB - ARM_EL3_RMM_SHARED_SIZE */
+#define ARM_REALM_SIZE			(UL(0x02000000) -		\
+						ARM_EL3_RMM_SHARED_SIZE)
+#define ARM_EL3_RMM_SHARED_SIZE		(PAGE_SIZE)    /* 4KB */
 #else
 #define ARM_TZC_DRAM1_SIZE		UL(0x01000000) /* 16MB */
 #define ARM_EL3_TZC_DRAM1_SIZE		UL(0x00200000) /* 2MB */
 #define ARM_L1_GPT_SIZE			UL(0)
 #define ARM_REALM_SIZE			UL(0)
+#define ARM_EL3_RMM_SHARED_SIZE		UL(0)
 #endif /* ENABLE_RME */
 
 #define ARM_SCP_TZC_DRAM1_BASE		(ARM_DRAM1_BASE +		\
@@ -128,13 +139,20 @@
 #define ARM_L1_GPT_END			(ARM_L1_GPT_ADDR_BASE +		\
 					ARM_L1_GPT_SIZE - 1U)
 
-#define ARM_REALM_BASE			(ARM_DRAM1_BASE +		\
-					ARM_DRAM1_SIZE -		\
-					(ARM_SCP_TZC_DRAM1_SIZE +	\
-					ARM_EL3_TZC_DRAM1_SIZE +	\
-					ARM_REALM_SIZE +		\
-					ARM_L1_GPT_SIZE))
+#define ARM_REALM_BASE			(ARM_EL3_RMM_SHARED_BASE -	\
+					 ARM_REALM_SIZE)
+
 #define ARM_REALM_END                   (ARM_REALM_BASE + ARM_REALM_SIZE - 1U)
+
+#define ARM_EL3_RMM_SHARED_BASE		(ARM_DRAM1_BASE +		\
+					 ARM_DRAM1_SIZE -		\
+					(ARM_SCP_TZC_DRAM1_SIZE +	\
+					ARM_L1_GPT_SIZE +		\
+					ARM_EL3_RMM_SHARED_SIZE +	\
+					ARM_EL3_TZC_DRAM1_SIZE))
+
+#define ARM_EL3_RMM_SHARED_END		(ARM_EL3_RMM_SHARED_BASE +	\
+					 ARM_EL3_RMM_SHARED_SIZE - 1U)
 #endif /* ENABLE_RME */
 
 #define ARM_EL3_TZC_DRAM1_BASE		(ARM_SCP_TZC_DRAM1_BASE -	\
@@ -148,6 +166,7 @@
 #define ARM_AP_TZC_DRAM1_SIZE		(ARM_TZC_DRAM1_SIZE -		\
 					(ARM_SCP_TZC_DRAM1_SIZE +	\
 					ARM_EL3_TZC_DRAM1_SIZE +	\
+					ARM_EL3_RMM_SHARED_SIZE +	\
 					ARM_REALM_SIZE +		\
 					ARM_L1_GPT_SIZE))
 #define ARM_AP_TZC_DRAM1_END		(ARM_AP_TZC_DRAM1_BASE +	\
@@ -197,6 +216,7 @@
 #define ARM_NS_DRAM1_BASE		ARM_DRAM1_BASE
 #define ARM_NS_DRAM1_SIZE		(ARM_DRAM1_SIZE -		\
 					 ARM_TZC_DRAM1_SIZE)
+
 #define ARM_NS_DRAM1_END		(ARM_NS_DRAM1_BASE +		\
 					 ARM_NS_DRAM1_SIZE - 1U)
 #ifdef PLAT_ARM_DRAM1_BASE
@@ -301,6 +321,12 @@
 					ARM_L1_GPT_SIZE,		\
 					MT_MEMORY | MT_RW | EL3_PAS)
 
+#define ARM_MAP_EL3_RMM_SHARED_MEM					\
+				MAP_REGION_FLAT(			\
+					ARM_EL3_RMM_SHARED_BASE,	\
+					ARM_EL3_RMM_SHARED_SIZE,	\
+					MT_MEMORY | MT_RW | MT_REALM)
+
 #endif /* ENABLE_RME */
 
 /*
@@ -595,6 +621,8 @@
 #if ENABLE_RME
 #define RMM_BASE			(ARM_REALM_BASE)
 #define RMM_LIMIT			(RMM_BASE + ARM_REALM_SIZE)
+#define RMM_SHARED_BASE			(ARM_EL3_RMM_SHARED_BASE)
+#define RMM_SHARED_SIZE			(ARM_EL3_RMM_SHARED_SIZE)
 #endif
 
 #if !defined(__aarch64__) || JUNO_AARCH32_EL3_RUNTIME
diff --git a/include/plat/arm/common/arm_pas_def.h b/include/plat/arm/common/arm_pas_def.h
index 4fee41b..c199302 100644
--- a/include/plat/arm/common/arm_pas_def.h
+++ b/include/plat/arm/common/arm_pas_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -61,6 +61,10 @@
 #define ARM_PAS_2_BASE			(ARM_PAS_1_BASE + ARM_PAS_1_SIZE)
 #define ARM_PAS_2_SIZE			(ARM_NS_DRAM1_SIZE)
 
+/* Shared area between EL3 and RMM */
+#define ARM_PAS_SHARED_BASE		(ARM_EL3_RMM_SHARED_BASE)
+#define ARM_PAS_SHARED_SIZE		(ARM_EL3_RMM_SHARED_SIZE)
+
 /* Secure TZC region */
 #define ARM_PAS_3_BASE			(ARM_AP_TZC_DRAM1_BASE)
 #define ARM_PAS_3_SIZE			(ARM_AP_TZC_DRAM1_SIZE)
@@ -76,8 +80,13 @@
 							       ARM_PAS_3_SIZE, \
 							       GPT_GPI_SECURE)
 
+/*
+ * REALM and Shared area share the same PAS, so consider them a single
+ * PAS region to configure in GPT.
+ */
 #define ARM_PAS_REALM			GPT_MAP_REGION_GRANULE(ARM_REALM_BASE, \
-							       ARM_REALM_SIZE, \
+							       (ARM_PAS_SHARED_SIZE + \
+								ARM_REALM_SIZE), \
 							       GPT_GPI_REALM)
 
 #define ARM_PAS_EL3_DRAM		GPT_MAP_REGION_GRANULE(ARM_EL3_TZC_DRAM1_BASE, \
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 9618700..d060332 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -57,7 +57,8 @@
 	{ARM_EL3_TZC_DRAM1_BASE, ARM_L1_GPT_END, TZC_REGION_S_RDWR, 0},	    \
 	{ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS,	    \
 		PLAT_ARM_TZC_NS_DEV_ACCESS},				    \
-	{ARM_REALM_BASE, ARM_REALM_END, ARM_TZC_NS_DRAM_S_ACCESS,	    \
+	/* Realm and Shared area share the same PAS */		    \
+	{ARM_REALM_BASE, ARM_EL3_RMM_SHARED_END, ARM_TZC_NS_DRAM_S_ACCESS,  \
 		PLAT_ARM_TZC_NS_DEV_ACCESS},				    \
 	{ARM_DRAM2_BASE, ARM_DRAM2_END, ARM_TZC_NS_DRAM_S_ACCESS,	    \
 		PLAT_ARM_TZC_NS_DEV_ACCESS}
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index b62a631..184606a 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -13,6 +13,9 @@
 #if defined(SPD_spmd)
  #include <services/spm_core_manifest.h>
 #endif
+#if ENABLE_RME
+#include <services/rmm_core_manifest.h>
+#endif
 #if TRNG_SUPPORT
 #include "plat_trng.h"
 #endif
@@ -305,10 +308,14 @@
 /*******************************************************************************
  * Mandatory BL31 functions when ENABLE_RME=1
  ******************************************************************************/
-int plat_get_cca_attest_token(uintptr_t buf, size_t *len,
-			       uintptr_t hash, size_t hash_size);
-int plat_get_cca_realm_attest_key(uintptr_t buf, size_t *len,
-				   unsigned int type);
+#if ENABLE_RME
+int plat_rmmd_get_cca_attest_token(uintptr_t buf, size_t *len,
+				   uintptr_t hash, size_t hash_size);
+int plat_rmmd_get_cca_realm_attest_key(uintptr_t buf, size_t *len,
+				       unsigned int type);
+size_t plat_rmmd_get_el3_rmm_shared_mem(uintptr_t *shared);
+int plat_rmmd_load_manifest(rmm_manifest_t *manifest);
+#endif
 
 /*******************************************************************************
  * Optional BL31 functions (may be overridden)
diff --git a/include/services/rmm_core_manifest.h b/include/services/rmm_core_manifest.h
new file mode 100644
index 0000000..2f25858
--- /dev/null
+++ b/include/services/rmm_core_manifest.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RMM_CORE_MANIFEST_H
+#define RMM_CORE_MANIFEST_H
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <lib/cassert.h>
+
+#define RMMD_MANIFEST_VERSION_MAJOR		U(0)
+#define RMMD_MANIFEST_VERSION_MINOR		U(1)
+
+/*
+ * Manifest version encoding:
+ *	- Bit[31] RES0
+ *	- Bits [30:16] Major version
+ *	- Bits [15:0] Minor version
+ */
+#define _RMMD_MANIFEST_VERSION(_major, _minor)				\
+	((((_major) & 0x7FFF) << 16) | ((_minor) & 0xFFFF))
+
+#define RMMD_MANIFEST_VERSION _RMMD_MANIFEST_VERSION(			\
+				RMMD_MANIFEST_VERSION_MAJOR,		\
+				RMMD_MANIFEST_VERSION_MINOR)
+
+#define RMMD_GET_MANIFEST_VERSION_MAJOR(_version)			\
+	((_version >> 16) & 0x7FFF)
+
+#define RMMD_GET_MANIFEST_VERSION_MINOR(_version)			\
+	(_version & 0xFFFF)
+
+/* Boot manifest core structure as per v0.1 */
+typedef struct rmm_manifest {
+	uint32_t version;	/* Manifest version */
+	uintptr_t plat_data;	/* Manifest platform data */
+} rmm_manifest_t;
+
+CASSERT(offsetof(rmm_manifest_t, version) == 0,
+				rmm_manifest_t_version_unaligned);
+CASSERT(offsetof(rmm_manifest_t, plat_data) == 8,
+				rmm_manifest_t_plat_data_unaligned);
+
+#endif /* RMM_CORE_MANIFEST_H */
diff --git a/include/services/rmmd_svc.h b/include/services/rmmd_svc.h
index 156d89c..6adc5f3 100644
--- a/include/services/rmmd_svc.h
+++ b/include/services/rmmd_svc.h
@@ -40,7 +40,17 @@
 					/* 0x18F */
 #define RMMD_RMI_REQ_COMPLETE		SMC64_RMI_FID(U(0x3F))
 
-/* The SMC in the range 0x8400 0190 - 0x8400 01AF are reserved for RSIs.*/
+/* RMM_BOOT_COMPLETE arg0 error codes */
+#define E_RMM_BOOT_SUCCESS				(0)
+#define E_RMM_BOOT_UNKNOWN				(-1)
+#define E_RMM_BOOT_VERSION_MISMATCH			(-2)
+#define E_RMM_BOOT_CPUS_OUT_OF_RANGE			(-3)
+#define E_RMM_BOOT_CPU_ID_OUT_OF_RANGE			(-4)
+#define E_RMM_BOOT_INVALID_SHARED_BUFFER		(-5)
+#define E_RMM_BOOT_MANIFEST_VERSION_NOT_SUPPORTED	(-6)
+#define E_RMM_BOOT_MANIFEST_DATA_ERROR			(-7)
+
+/* The SMC in the range 0x8400 0191 - 0x8400 01AF are reserved for RSIs.*/
 
 /*
  * EL3 - RMM SMCs used for requesting RMMD services. These SMCs originate in Realm
@@ -74,12 +84,12 @@
 #define RMMD_GTSI_UNDELEGATE		SMC64_RMMD_EL3_FID(U(1))
 
 /* Return error codes from RMM-EL3 SMCs */
-#define RMMD_OK				0
-#define RMMD_ERR_BAD_ADDR		-2
-#define RMMD_ERR_BAD_PAS		-3
-#define RMMD_ERR_NOMEM			-4
-#define RMMD_ERR_INVAL			-5
-#define RMMD_ERR_UNK			-6
+#define E_RMM_OK			 0
+#define E_RMM_UNK			-1
+#define E_RMM_BAD_ADDR			-2
+#define E_RMM_BAD_PAS			-3
+#define E_RMM_NOMEM			-4
+#define E_RMM_INVAL			-5
 
 /* Acceptable SHA sizes for Challenge object */
 #define SHA256_DIGEST_SIZE	32U
@@ -121,6 +131,36 @@
 /* ECC Curve types for attest key generation */
 #define ATTEST_KEY_CURVE_ECC_SECP384R1		0
 
+/*
+ * RMM_BOOT_COMPLETE originates on RMM when the boot finishes (either cold
+ * or warm boot). This is handled by the RMM-EL3 interface SMC handler.
+ *
+ * RMM_BOOT_COMPLETE FID is located at the end of the available range.
+ */
+					 /* 0x1CF */
+#define RMM_BOOT_COMPLETE		SMC64_RMMD_EL3_FID(U(0x1F))
+
+/*
+ * The major version number of the RMM Boot Interface implementation.
+ * Increase this whenever the semantics of the boot arguments change making it
+ * backwards incompatible.
+ */
+#define RMM_EL3_IFC_VERSION_MAJOR	(U(0))
+
+/*
+ * The minor version number of the RMM Boot Interface implementation.
+ * Increase this when a bug is fixed, or a feature is added without
+ * breaking compatibility.
+ */
+#define RMM_EL3_IFC_VERSION_MINOR	(U(1))
+
+#define RMM_EL3_INTERFACE_VERSION				\
+	(((RMM_EL3_IFC_VERSION_MAJOR << 16) & 0x7FFFF) |	\
+		RMM_EL3_IFC_VERSION_MINOR)
+
+#define RMM_EL3_IFC_VERSION_GET_MAJOR(_version) (((_version) >> 16) \
+								& 0x7FFF)
+#define RMM_EL3_IFC_VERSION_GET_MAJOR_MINOR(_version) ((_version) & 0xFFFF)
 
 #ifndef __ASSEMBLER__
 #include <stdint.h>
diff --git a/include/services/trp/platform_trp.h b/include/services/trp/platform_trp.h
index b34da85..1c963c8 100644
--- a/include/services/trp/platform_trp.h
+++ b/include/services/trp/platform_trp.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,9 +7,11 @@
 #ifndef PLATFORM_TRP_H
 #define PLATFORM_TRP_H
 
+#include <services/rmm_core_manifest.h>
+
 /*******************************************************************************
  * Mandatory TRP functions (only if platform contains a TRP)
  ******************************************************************************/
-void trp_early_platform_setup(void);
+void trp_early_platform_setup(rmm_manifest_t *manifest);
 
 #endif /* PLATFORM_TRP_H */
diff --git a/include/services/trp/trp_helpers.h b/include/services/trp/trp_helpers.h
new file mode 100644
index 0000000..8e786e2
--- /dev/null
+++ b/include/services/trp/trp_helpers.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TRP_HELPERS_H
+#define TRP_HELPERS_H
+
+/* Definitions to help the assembler access the SMC/ERET args structure */
+#define TRP_ARGS_SIZE		TRP_ARGS_END
+#define TRP_ARG0		0x0
+#define TRP_ARG1		0x8
+#define TRP_ARG2		0x10
+#define TRP_ARG3		0x18
+#define TRP_ARG4		0x20
+#define TRP_ARG5		0x28
+#define TRP_ARG6		0x30
+#define TRP_ARG7		0x38
+#define TRP_ARGS_END		0x40
+
+#ifndef __ASSEMBLER__
+
+#include <platform_def.h>
+
+/* Data structure to hold SMC arguments */
+typedef struct trp_args {
+	uint64_t regs[TRP_ARGS_END >> 3];
+} __aligned(CACHE_WRITEBACK_GRANULE) trp_args_t;
+
+trp_args_t *set_smc_args(uint64_t arg0,
+			 uint64_t arg1,
+			 uint64_t arg2,
+			 uint64_t arg3,
+			 uint64_t arg4,
+			 uint64_t arg5,
+			 uint64_t arg6,
+			 uint64_t arg7);
+
+__dead2 void trp_boot_abort(uint64_t err);
+
+#endif /* __ASSEMBLER __ */
+#endif /* TRP_HELPERS_H */
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index a7028f6..f8463f1 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -17,6 +17,9 @@
 #include <lib/xlat_tables/xlat_tables_compat.h>
 #include <platform_def.h>
 #include <services/arm_arch_svc.h>
+#if ENABLE_RME
+#include <services/rmm_core_manifest.h>
+#endif
 #if SPM_MM
 #include <services/spm_mm_partition.h>
 #endif
@@ -169,6 +172,7 @@
 #endif
 #if ENABLE_RME
 	ARM_MAP_GPT_L1_DRAM,
+	ARM_MAP_EL3_RMM_SHARED_MEM,
 #endif
 	{0}
 };
@@ -512,3 +516,29 @@
 	return (int32_t)(((sys_id >> V2M_SYS_ID_REV_SHIFT) &
 			  V2M_SYS_ID_REV_MASK) & SOC_ID_REV_MASK);
 }
+
+#if ENABLE_RME
+/*
+ * Get a pointer to the RMM-EL3 Shared buffer and return it
+ * through the pointer passed as parameter.
+ *
+ * This function returns the size of the shared buffer.
+ */
+size_t plat_rmmd_get_el3_rmm_shared_mem(uintptr_t *shared)
+{
+	*shared = (uintptr_t)RMM_SHARED_BASE;
+
+	return (size_t)RMM_SHARED_SIZE;
+}
+
+int plat_rmmd_load_manifest(rmm_manifest_t *manifest)
+{
+	assert(manifest != NULL);
+
+	manifest->version = RMMD_MANIFEST_VERSION;
+	manifest->plat_data = (uintptr_t)NULL;
+
+	return 0;
+}
+
+#endif
diff --git a/plat/arm/board/fvp/fvp_plat_attest_token.c b/plat/arm/board/fvp/fvp_plat_attest_token.c
index 5463f33..1b0854b 100644
--- a/plat/arm/board/fvp/fvp_plat_attest_token.c
+++ b/plat/arm/board/fvp/fvp_plat_attest_token.c
@@ -300,8 +300,8 @@
 	0xB0, 0x3A
 };
 
-int plat_get_cca_attest_token(uintptr_t buf, size_t *len,
-			       uintptr_t hash, size_t hash_size)
+int plat_rmmd_get_cca_attest_token(uintptr_t buf, size_t *len,
+				   uintptr_t hash, size_t hash_size)
 {
 	(void)hash;
 	(void)hash_size;
diff --git a/plat/arm/board/fvp/fvp_realm_attest_key.c b/plat/arm/board/fvp/fvp_realm_attest_key.c
index b32f557..1af1f0d 100644
--- a/plat/arm/board/fvp/fvp_realm_attest_key.c
+++ b/plat/arm/board/fvp/fvp_realm_attest_key.c
@@ -19,7 +19,8 @@
 	0xEB, 0x1A, 0x41, 0x85, 0xBD, 0x11, 0x7F, 0x68
 };
 
-int plat_get_cca_realm_attest_key(uintptr_t buf, size_t *len, unsigned int type)
+int plat_rmmd_get_cca_realm_attest_key(uintptr_t buf, size_t *len,
+				       unsigned int type)
 {
 	assert(type == ATTEST_KEY_CURVE_ECC_SECP384R1);
 
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index c75aca7..d0f8aa9 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -127,11 +127,7 @@
 #if defined(IMAGE_BL31)
 # if SPM_MM
 #  define PLAT_ARM_MMAP_ENTRIES		10
-#  if ENABLE_RME
-#   define MAX_XLAT_TABLES		11
-#  else
-#   define MAX_XLAT_TABLES		9
-#  endif
+#  define MAX_XLAT_TABLES		9
 #  define PLAT_SP_IMAGE_MMAP_REGIONS	30
 #  define PLAT_SP_IMAGE_MAX_XLAT_TABLES	10
 # elif SPMC_AT_EL3
@@ -141,13 +137,13 @@
 #  define PLAT_ARM_MMAP_ENTRIES		9
 #  if USE_DEBUGFS
 #   if ENABLE_RME
-#    define MAX_XLAT_TABLES		10
+#    define MAX_XLAT_TABLES		9
 #   else
 #    define MAX_XLAT_TABLES		8
 #   endif
 #  else
 #   if ENABLE_RME
-#    define MAX_XLAT_TABLES		9
+#    define MAX_XLAT_TABLES		8
 #   else
 #    define MAX_XLAT_TABLES		7
 #   endif
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index f9053a8..a7e27e8 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -341,10 +341,6 @@
     endif
 endif
 
-ifeq (${ENABLE_RME},1)
-    BL31_CPPFLAGS	+=	-DPLAT_XLAT_TABLES_DYNAMIC
-endif
-
 ifeq (${ALLOW_RO_XLAT_TABLES}, 1)
     ifeq (${ARCH},aarch32)
         BL32_CPPFLAGS	+=	-DPLAT_RO_XLAT_TABLES
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index a6f7df5..cf403b1 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -164,6 +164,14 @@
 	bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry();
 	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
 
+#if ENABLE_RME
+	/*
+	 * Populate entry point information for RMM.
+	 * Only PC needs to be set as other fields are determined by RMMD.
+	 */
+	rmm_image_ep_info.pc = RMM_BASE;
+#endif /* ENABLE_RME */
+
 #else /* RESET_TO_BL31 */
 
 	/*
diff --git a/plat/arm/common/trp/arm_trp.mk b/plat/arm/common/trp/arm_trp.mk
index 997111f..204c14a 100644
--- a/plat/arm/common/trp/arm_trp.mk
+++ b/plat/arm/common/trp/arm_trp.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -8,3 +8,5 @@
 RMM_SOURCES		+=	plat/arm/common/trp/arm_trp_setup.c	\
 				plat/arm/common/arm_topology.c		\
 				plat/common/aarch64/platform_mp_stack.S
+
+INCLUDES		+=	-Iinclude/services/trp
diff --git a/plat/arm/common/trp/arm_trp_setup.c b/plat/arm/common/trp/arm_trp_setup.c
index 8e48293..59b4c06 100644
--- a/plat/arm/common/trp/arm_trp_setup.c
+++ b/plat/arm/common/trp/arm_trp_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,33 +8,65 @@
 #include <common/debug.h>
 #include <drivers/arm/pl011.h>
 #include <drivers/console.h>
+#include <services/rmm_core_manifest.h>
+#include <services/rmmd_svc.h>
+#include <services/trp/platform_trp.h>
+#include <trp_helpers.h>
+
 #include <plat/arm/common/plat_arm.h>
 #include <platform_def.h>
 
 /*******************************************************************************
+ * Received from boot manifest and populated here
+ ******************************************************************************/
+extern uint32_t trp_boot_manifest_version;
+
+/*******************************************************************************
  * Initialize the UART
  ******************************************************************************/
 static console_t arm_trp_runtime_console;
 
+static int arm_trp_process_manifest(rmm_manifest_t *manifest)
+{
+	/* Verify the Boot Manifest Version. Only the Major is considered */
+	if (RMMD_MANIFEST_VERSION_MAJOR !=
+		RMMD_GET_MANIFEST_VERSION_MAJOR(manifest->version)) {
+		return E_RMM_BOOT_MANIFEST_VERSION_NOT_SUPPORTED;
+	}
+
-void arm_trp_early_platform_setup(void)
+	trp_boot_manifest_version = manifest->version;
+	flush_dcache_range((uintptr_t)manifest, sizeof(rmm_manifest_t));
+
+	return 0;
+}
+
+void arm_trp_early_platform_setup(rmm_manifest_t *manifest)
 {
+	int rc;
+
+	rc = arm_trp_process_manifest(manifest);
+	if (rc != 0) {
+		trp_boot_abort(rc);
+	}
+
 	/*
 	 * Initialize a different console than already in use to display
 	 * messages from trp
 	 */
-	int rc = console_pl011_register(PLAT_ARM_TRP_UART_BASE,
-					PLAT_ARM_TRP_UART_CLK_IN_HZ,
-					ARM_CONSOLE_BAUDRATE,
-					&arm_trp_runtime_console);
+	rc = console_pl011_register(PLAT_ARM_TRP_UART_BASE,
+				    PLAT_ARM_TRP_UART_CLK_IN_HZ,
+				    ARM_CONSOLE_BAUDRATE,
+				    &arm_trp_runtime_console);
 	if (rc == 0) {
 		panic();
 	}
 
 	console_set_scope(&arm_trp_runtime_console,
 			  CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
+
 }
 
-void trp_early_platform_setup(void)
+void trp_early_platform_setup(rmm_manifest_t *manifest)
 {
-	arm_trp_early_platform_setup();
+	arm_trp_early_platform_setup(manifest);
 }
diff --git a/services/std_svc/rmmd/rmmd_attest.c b/services/std_svc/rmmd/rmmd_attest.c
index 0432ec3..25adf50 100644
--- a/services/std_svc/rmmd/rmmd_attest.c
+++ b/services/std_svc/rmmd/rmmd_attest.c
@@ -5,6 +5,7 @@
  */
 #include <stdint.h>
 #include <string.h>
+
 #include <common/debug.h>
 #include <lib/spinlock.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
@@ -56,110 +57,96 @@
 }
 
 /*
- * TODO: Have different error codes for different errors so that the caller can
- * differentiate various error cases.
+ * Helper function to validate that the buffer base and length are
+ * within range.
  */
-int rmmd_attest_get_platform_token(uint64_t buf_pa, uint64_t *buf_len, uint64_t challenge_hash_len)
+static int validate_buffer_params(uint64_t buf_pa, uint64_t buf_len)
 {
-	int err;
-	uintptr_t va;
-	uint8_t temp_buf[SHA512_DIGEST_SIZE];
+	unsigned long shared_buf_page;
+	uintptr_t shared_buf_base;
 
-	/*
-	 * TODO: Currently we don't validate incoming buf_pa. This is a
-	 * prototype and we will need to allocate static buffer for EL3-RMM
-	 * communication.
-	 */
+	(void)plat_rmmd_get_el3_rmm_shared_mem(&shared_buf_base);
 
-	/* We need a page of buffer to pass data */
-	if (*buf_len != PAGE_SIZE) {
-		ERROR("Invalid buffer length\n");
-		return RMMD_ERR_INVAL;
+	shared_buf_page = shared_buf_base & ~PAGE_SIZE_MASK;
+
+	/* Validate the buffer pointer */
+	if ((buf_pa & ~PAGE_SIZE_MASK) != shared_buf_page) {
+		ERROR("Buffer PA out of range\n");
+		return E_RMM_BAD_ADDR;
 	}
 
-	if ((challenge_hash_len != SHA256_DIGEST_SIZE) &&
-	    (challenge_hash_len != SHA384_DIGEST_SIZE) &&
-	    (challenge_hash_len != SHA512_DIGEST_SIZE)) {
-		ERROR("Invalid hash size: %lu\n", challenge_hash_len);
-		return RMMD_ERR_INVAL;
+	/* Validate the size of the shared area */
+	if (((buf_pa + buf_len - 1UL) & ~PAGE_SIZE_MASK) != shared_buf_page) {
+		ERROR("Invalid buffer length\n");
+		return E_RMM_INVAL;
 	}
 
-	spin_lock(&lock);
+	return 0; /* No error */
+}
+
+int rmmd_attest_get_platform_token(uint64_t buf_pa, uint64_t *buf_size,
+				   uint64_t c_size)
+{
+	int err;
+	uint8_t temp_buf[SHA512_DIGEST_SIZE];
 
-	/* Map the buffer that was provided by the RMM. */
-	err = mmap_add_dynamic_region_alloc_va(buf_pa, &va, PAGE_SIZE,
-					       MT_RW_DATA | MT_REALM);
+	err = validate_buffer_params(buf_pa, *buf_size);
 	if (err != 0) {
-		ERROR("mmap_add_dynamic_region_alloc_va failed: %d (%p).\n"
-		      , err, (void *)buf_pa);
-		spin_unlock(&lock);
-		return RMMD_ERR_NOMEM;
+		return err;
+	}
+
+	if ((c_size != SHA256_DIGEST_SIZE) &&
+	    (c_size != SHA384_DIGEST_SIZE) &&
+	    (c_size != SHA512_DIGEST_SIZE)) {
+		ERROR("Invalid hash size: %lu\n", c_size);
+		return E_RMM_INVAL;
 	}
 
-	(void)memcpy(temp_buf, (void *)va, challenge_hash_len);
+	spin_lock(&lock);
 
-	print_challenge((uint8_t *)temp_buf, challenge_hash_len);
+	(void)memcpy(temp_buf, (void *)buf_pa, c_size);
+
+	print_challenge((uint8_t *)temp_buf, c_size);
 
 	/* Get the platform token. */
-	err = plat_get_cca_attest_token(va,
-		buf_len, (uintptr_t)temp_buf, challenge_hash_len);
+	err = plat_rmmd_get_cca_attest_token((uintptr_t)buf_pa,
+		buf_size, (uintptr_t)temp_buf, c_size);
 
 	if (err != 0) {
 		ERROR("Failed to get platform token: %d.\n", err);
-		err = RMMD_ERR_UNK;
+		err = E_RMM_UNK;
 	}
 
-	/* Unmap RMM memory. */
-	(void)mmap_remove_dynamic_region(va, PAGE_SIZE);
 	spin_unlock(&lock);
 
 	return err;
 }
 
-int rmmd_attest_get_signing_key(uint64_t buf_pa, uint64_t *buf_len,
+int rmmd_attest_get_signing_key(uint64_t buf_pa, uint64_t *buf_size,
 				uint64_t ecc_curve)
 {
 	int err;
-	uintptr_t va;
 
-	/*
-	 * TODO: Currently we don't validate incoming buf_pa. This is a
-	 * prototype and we will need to allocate static buffer for EL3-RMM
-	 * communication.
-	 */
-
-	/* We need a page of buffer to pass data */
-	if (*buf_len != PAGE_SIZE) {
-		ERROR("Invalid buffer length\n");
-		return RMMD_ERR_INVAL;
+	err = validate_buffer_params(buf_pa, *buf_size);
+	if (err != 0) {
+		return err;
 	}
 
 	if (ecc_curve != ATTEST_KEY_CURVE_ECC_SECP384R1) {
 		ERROR("Invalid ECC curve specified\n");
-		return RMMD_ERR_INVAL;
+		return E_RMM_INVAL;
 	}
 
 	spin_lock(&lock);
 
-	/* Map the buffer that was provided by the RMM. */
-	err = mmap_add_dynamic_region_alloc_va(buf_pa, &va, PAGE_SIZE,
-					       MT_RW_DATA | MT_REALM);
-	if (err != 0) {
-		ERROR("mmap_add_dynamic_region_alloc_va failed: %d (%p).\n"
-		      , err, (void *)buf_pa);
-		spin_unlock(&lock);
-		return RMMD_ERR_NOMEM;
-	}
-
 	/* Get the Realm attestation key. */
-	err = plat_get_cca_realm_attest_key(va, buf_len, (unsigned int)ecc_curve);
+	err = plat_rmmd_get_cca_realm_attest_key((uintptr_t)buf_pa, buf_size,
+						 (unsigned int)ecc_curve);
 	if (err != 0) {
 		ERROR("Failed to get attestation key: %d.\n", err);
-		err =  RMMD_ERR_UNK;
+		err =  E_RMM_UNK;
 	}
 
-	/* Unmap RMM memory. */
-	(void)mmap_remove_dynamic_region(va, PAGE_SIZE);
 	spin_unlock(&lock);
 
 	return err;
diff --git a/services/std_svc/rmmd/rmmd_main.c b/services/std_svc/rmmd/rmmd_main.c
index 746419e..322d9f2 100644
--- a/services/std_svc/rmmd/rmmd_main.c
+++ b/services/std_svc/rmmd/rmmd_main.c
@@ -33,6 +33,11 @@
 #include "rmmd_private.h"
 
 /*******************************************************************************
+ * RMM boot failure flag
+ ******************************************************************************/
+static bool rmm_boot_failed;
+
+/*******************************************************************************
  * RMM context information.
  ******************************************************************************/
 rmmd_rmm_context_t rmm_context[PLATFORM_CORE_COUNT];
@@ -132,13 +137,10 @@
  ******************************************************************************/
 static int32_t rmm_init(void)
 {
-
-	uint64_t rc;
-
+	long rc;
 	rmmd_rmm_context_t *ctx = &rmm_context[plat_my_core_pos()];
 
 	INFO("RMM init start.\n");
-	ctx->state = RMM_STATE_RESET;
 
 	/* Enable architecture extensions */
 	manage_extensions_realm(&ctx->cpu_ctx);
@@ -147,12 +149,13 @@
 	rmm_el2_context_init(&ctx->cpu_ctx.el2_sysregs_ctx);
 
 	rc = rmmd_rmm_sync_entry(ctx);
-	if (rc != 0ULL) {
-		ERROR("RMM initialisation failed 0x%" PRIx64 "\n", rc);
-		panic();
+	if (rc != E_RMM_BOOT_SUCCESS) {
+		ERROR("RMM init failed: %ld\n", rc);
+		/* Mark the boot as failed for all the CPUs */
+		rmm_boot_failed = true;
+		return 0;
 	}
 
-	ctx->state = RMM_STATE_IDLE;
 	INFO("RMM init end.\n");
 
 	return 1;
@@ -163,9 +166,13 @@
  ******************************************************************************/
 int rmmd_setup(void)
 {
+	size_t shared_buf_size __unused;
+	uintptr_t shared_buf_base;
 	uint32_t ep_attr;
 	unsigned int linear_id = plat_my_core_pos();
 	rmmd_rmm_context_t *rmm_ctx = &rmm_context[linear_id];
+	rmm_manifest_t *manifest;
+	int rc;
 
 	/* Make sure RME is supported. */
 	assert(get_armv9_2_feat_rme_support() != 0U);
@@ -192,6 +199,34 @@
 					MODE_SP_ELX,
 					DISABLE_ALL_EXCEPTIONS);
 
+	shared_buf_size =
+			plat_rmmd_get_el3_rmm_shared_mem(&shared_buf_base);
+
+	assert((shared_buf_size == SZ_4K) &&
+					((void *)shared_buf_base != NULL));
+
+	/* Load the boot manifest at the beginning of the shared area */
+	manifest = (rmm_manifest_t *)shared_buf_base;
+	rc = plat_rmmd_load_manifest(manifest);
+	if (rc != 0) {
+		ERROR("Error loading RMM Boot Manifest (%i)\n", rc);
+		return rc;
+	}
+	flush_dcache_range((uintptr_t)shared_buf_base, shared_buf_size);
+
+	/*
+	 * Prepare coldboot arguments for RMM:
+	 * arg0: This CPUID (primary processor).
+	 * arg1: Version for this Boot Interface.
+	 * arg2: PLATFORM_CORE_COUNT.
+	 * arg3: Base address for the EL3 <-> RMM shared area. The boot
+	 *       manifest will be stored at the beginning of this area.
+	 */
+	rmm_ep_info->args.arg0 = linear_id;
+	rmm_ep_info->args.arg1 = RMM_EL3_INTERFACE_VERSION;
+	rmm_ep_info->args.arg2 = PLATFORM_CORE_COUNT;
+	rmm_ep_info->args.arg3 = shared_buf_base;
+
 	/* Initialise RMM context with this entry point information */
 	cm_setup_context(&rmm_ctx->cpu_ctx, rmm_ep_info);
 
@@ -244,9 +279,14 @@
 				uint64_t x3, uint64_t x4, void *cookie,
 				void *handle, uint64_t flags)
 {
-	rmmd_rmm_context_t *ctx = &rmm_context[plat_my_core_pos()];
 	uint32_t src_sec_state;
 
+	/* If RMM failed to boot, treat any RMI SMC as unknown */
+	if (rmm_boot_failed) {
+		WARN("RMMD: Failed to boot up RMM. Ignoring RMI call\n");
+		SMC_RET1(handle, SMC_UNK);
+	}
+
 	/* Determine which security state this SMC originated from */
 	src_sec_state = caller_sec_state(flags);
 
@@ -272,11 +312,6 @@
 
 	switch (smc_fid) {
 	case RMMD_RMI_REQ_COMPLETE:
-		if (ctx->state == RMM_STATE_RESET) {
-			VERBOSE("RMMD: running rmmd_rmm_sync_exit\n");
-			rmmd_rmm_sync_exit(x1);
-		}
-
 		return rmmd_smc_forward(REALM, NON_SECURE, x1,
 					x2, x3, x4, 0, handle);
 
@@ -293,11 +328,26 @@
  ******************************************************************************/
 static void *rmmd_cpu_on_finish_handler(const void *arg)
 {
-	int32_t rc;
+	long rc;
 	uint32_t linear_id = plat_my_core_pos();
 	rmmd_rmm_context_t *ctx = &rmm_context[linear_id];
 
-	ctx->state = RMM_STATE_RESET;
+	if (rmm_boot_failed) {
+		/* RMM Boot failed on a previous CPU. Abort. */
+		ERROR("RMM Failed to initialize. Ignoring for CPU%d\n",
+								linear_id);
+		return NULL;
+	}
+
+	/*
+	 * Prepare warmboot arguments for RMM:
+	 * arg0: This CPUID.
+	 * arg1 to arg3: Not used.
+	 */
+	rmm_ep_info->args.arg0 = linear_id;
+	rmm_ep_info->args.arg1 = 0ULL;
+	rmm_ep_info->args.arg2 = 0ULL;
+	rmm_ep_info->args.arg3 = 0ULL;
 
 	/* Initialise RMM context with this entry point information */
 	cm_setup_context(&ctx->cpu_ctx, rmm_ep_info);
@@ -309,13 +359,13 @@
 	rmm_el2_context_init(&ctx->cpu_ctx.el2_sysregs_ctx);
 
 	rc = rmmd_rmm_sync_entry(ctx);
-	if (rc != 0) {
-		ERROR("RMM initialisation failed (%d) on CPU%d\n", rc,
-		      linear_id);
-		panic();
+
+	if (rc != E_RMM_BOOT_SUCCESS) {
+		ERROR("RMM init failed on CPU%d: %ld\n", linear_id, rc);
+		/* Mark the boot as failed for any other booting CPU */
+		rmm_boot_failed = true;
 	}
 
-	ctx->state = RMM_STATE_IDLE;
 	return NULL;
 }
 
@@ -328,15 +378,15 @@
 	int ret;
 
 	if (error == 0) {
-		return RMMD_OK;
+		return E_RMM_OK;
 	}
 
 	if (error == -EINVAL) {
-		ret = RMMD_ERR_BAD_ADDR;
+		ret = E_RMM_BAD_ADDR;
 	} else {
 		/* This is the only other error code we expect */
 		assert(error == -EPERM);
-		ret = RMMD_ERR_BAD_PAS;
+		ret = E_RMM_BAD_PAS;
 	}
 
 	ERROR("RMMD: PAS Transition failed. GPT ret = %d, PA: 0x%"PRIx64 ", FID = 0x%x\n",
@@ -354,6 +404,12 @@
 	uint32_t src_sec_state;
 	int ret;
 
+	/* If RMM failed to boot, treat any RMM-EL3 interface SMC as unknown */
+	if (rmm_boot_failed) {
+		WARN("RMMD: Failed to boot up RMM. Ignoring RMM-EL3 call\n");
+		SMC_RET1(handle, SMC_UNK);
+	}
+
 	/* Determine which security state this SMC originated from */
 	src_sec_state = caller_sec_state(flags);
 
@@ -375,6 +431,11 @@
 	case RMMD_ATTEST_GET_REALM_KEY:
 		ret = rmmd_attest_get_signing_key(x1, &x2, x3);
 		SMC_RET2(handle, ret, x2);
+
+	case RMM_BOOT_COMPLETE:
+		VERBOSE("RMMD: running rmmd_rmm_sync_exit\n");
+		rmmd_rmm_sync_exit(x1);
+
 	default:
 		WARN("RMMD: Unsupported RMM-EL3 call 0x%08x\n", smc_fid);
 		SMC_RET1(handle, SMC_UNK);
diff --git a/services/std_svc/rmmd/rmmd_private.h b/services/std_svc/rmmd/rmmd_private.h
index 73df2b8..4954a43 100644
--- a/services/std_svc/rmmd/rmmd_private.h
+++ b/services/std_svc/rmmd/rmmd_private.h
@@ -32,11 +32,6 @@
 #ifndef __ASSEMBLER__
 #include <stdint.h>
 
-typedef enum rmm_state {
-	RMM_STATE_RESET = 0,
-	RMM_STATE_IDLE
-} rmm_state_t;
-
 /*
  * Data structure used by the RMM dispatcher (RMMD) in EL3 to track context of
  * the RMM at R-EL2.
@@ -44,7 +39,6 @@
 typedef struct rmmd_rmm_context {
 	uint64_t c_rt_ctx;
 	cpu_context_t cpu_ctx;
-	rmm_state_t state;
 } rmmd_rmm_context_t;
 
 /* Functions used to enter/exit the RMM synchronously */
@@ -52,10 +46,10 @@
 __dead2 void rmmd_rmm_sync_exit(uint64_t rc);
 
 /* Functions implementing attestation utilities for RMM */
-int rmmd_attest_get_platform_token(uint64_t buf_pa, uint64_t *buf_len,
-				   uint64_t challenge_hash_len);
-int rmmd_attest_get_signing_key(uint64_t buf_pa, uint64_t *buf_len,
-				   uint64_t ecc_curve);
+int rmmd_attest_get_platform_token(uint64_t buf_pa, uint64_t *buf_size,
+				   uint64_t c_size);
+int rmmd_attest_get_signing_key(uint64_t buf_pa, uint64_t *buf_size,
+				uint64_t ecc_curve);
 
 /* Assembly helpers */
 uint64_t rmmd_rmm_enter(uint64_t *c_rt_ctx);
diff --git a/services/std_svc/rmmd/trp/trp.mk b/services/std_svc/rmmd/trp/trp.mk
index a4f6e03..44bbf22 100644
--- a/services/std_svc/rmmd/trp/trp.mk
+++ b/services/std_svc/rmmd/trp/trp.mk
@@ -1,11 +1,12 @@
 #
-# Copyright (c) 2021 Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2021-2022 Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
-RMM_SOURCES		+=	services/std_svc/rmmd/trp/trp_entry.S	\
-				services/std_svc/rmmd/trp/trp_main.c
+RMM_SOURCES		+=	services/std_svc/rmmd/trp/trp_entry.S \
+				services/std_svc/rmmd/trp/trp_main.c  \
+				services/std_svc/rmmd/trp/trp_helpers.c
 
 RMM_LINKERFILE		:=	services/std_svc/rmmd/trp/linker.lds
 
diff --git a/services/std_svc/rmmd/trp/trp_entry.S b/services/std_svc/rmmd/trp/trp_entry.S
index 1b03c9f..47c1df1 100644
--- a/services/std_svc/rmmd/trp/trp_entry.S
+++ b/services/std_svc/rmmd/trp/trp_entry.S
@@ -6,6 +6,8 @@
 
 #include <asm_macros.S>
 #include <services/rmmd_svc.h>
+
+#include <platform_def.h>
 #include "trp_private.h"
 
 .global trp_head
@@ -31,6 +33,28 @@
 	 * ---------------------------------------------
 	 */
 trp_head:
+	/*
+	 * Stash arguments from previous boot stage
+	 */
+	mov	x20, x0
+	mov	x21, x1
+	mov	x22, x2
+	mov	x23, x3
+
+	/*
+	 * Validate CPUId before allocating a stack.
+	 */
+	cmp	x20, #PLATFORM_CORE_COUNT
+	b.lo	1f
+
+	mov_imm	x0, RMM_BOOT_COMPLETE
+	mov_imm	x1, E_RMM_BOOT_CPU_ID_OUT_OF_RANGE
+	smc	#0
+
+	/* EL3 should never return back here, so panic if it does */
+	b	trp_panic
+
+1:
 	bl	plat_set_my_stack
 
 	/*
@@ -45,7 +69,6 @@
 	adr	x2, cold_boot_flag
 	str	xzr, [x2]
 
-
 	/* ---------------------------------------------
 	 * Zero out BSS section
 	 * ---------------------------------------------
@@ -54,15 +77,21 @@
 	ldr	x1, =__BSS_SIZE__
 	bl	zeromem
 
+	mov	x0, x20
+	mov	x1, x21
+	mov	x2, x22
+	mov	x3, x23
 	bl	trp_setup
-
 	bl	trp_main
 warm_boot:
-	mov_imm	x0, RMMD_RMI_REQ_COMPLETE
-	mov	x1, xzr
+	mov_imm	x0, RMM_BOOT_COMPLETE
+	mov	x1, xzr /* RMM_BOOT_SUCCESS */
 	smc	#0
 	b	trp_handler
 
+trp_panic:
+	no_ret plat_panic_handler
+
 	/*
 	 * Flag to mark if it is a cold boot.
 	 * 1: cold boot, 0: warmboot.
diff --git a/services/std_svc/rmmd/trp/trp_helpers.c b/services/std_svc/rmmd/trp/trp_helpers.c
new file mode 100644
index 0000000..159f3a5
--- /dev/null
+++ b/services/std_svc/rmmd/trp/trp_helpers.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+#include <plat/common/platform.h>
+#include <services/rmmd_svc.h>
+#include "trp_private.h"
+
+/*
+ * Per cpu data structure to populate parameters for an SMC in C code and use
+ * a pointer to this structure in assembler code to populate x0-x7
+ */
+static trp_args_t trp_smc_args[PLATFORM_CORE_COUNT];
+
+/*
+ * Set the arguments for SMC call
+ */
+trp_args_t *set_smc_args(uint64_t arg0,
+			uint64_t arg1,
+			uint64_t arg2,
+			uint64_t arg3,
+			uint64_t arg4,
+			uint64_t arg5,
+			uint64_t arg6,
+			uint64_t arg7)
+{
+	uint32_t linear_id;
+	trp_args_t *pcpu_smc_args;
+
+	/*
+	 * Return to Secure Monitor by raising an SMC. The results of the
+	 * service are passed as an arguments to the SMC
+	 */
+	linear_id = plat_my_core_pos();
+	pcpu_smc_args = &trp_smc_args[linear_id];
+	write_trp_arg(pcpu_smc_args, TRP_ARG0, arg0);
+	write_trp_arg(pcpu_smc_args, TRP_ARG1, arg1);
+	write_trp_arg(pcpu_smc_args, TRP_ARG2, arg2);
+	write_trp_arg(pcpu_smc_args, TRP_ARG3, arg3);
+	write_trp_arg(pcpu_smc_args, TRP_ARG4, arg4);
+	write_trp_arg(pcpu_smc_args, TRP_ARG5, arg5);
+	write_trp_arg(pcpu_smc_args, TRP_ARG6, arg6);
+	write_trp_arg(pcpu_smc_args, TRP_ARG7, arg7);
+
+	return pcpu_smc_args;
+}
+
+/*
+ * Abort the boot process with the reason given in err.
+ */
+__dead2 void trp_boot_abort(uint64_t err)
+{
+	(void)trp_smc(set_smc_args(RMM_BOOT_COMPLETE, err, 0, 0, 0, 0, 0, 0));
+	panic();
+}
diff --git a/services/std_svc/rmmd/trp/trp_main.c b/services/std_svc/rmmd/trp/trp_main.c
index 2e3f076..cf6ec7b 100644
--- a/services/std_svc/rmmd/trp/trp_main.c
+++ b/services/std_svc/rmmd/trp/trp_main.c
@@ -7,58 +7,63 @@
 
 #include <common/debug.h>
 #include <plat/common/platform.h>
+#include <services/rmm_core_manifest.h>
 #include <services/rmmd_svc.h>
 #include <services/trp/platform_trp.h>
+#include <trp_helpers.h>
+#include "trp_private.h"
 
 #include <platform_def.h>
-#include "trp_private.h"
 
-/*******************************************************************************
- * Per cpu data structure to populate parameters for an SMC in C code and use
- * a pointer to this structure in assembler code to populate x0-x7
- ******************************************************************************/
-static trp_args_t trp_smc_args[PLATFORM_CORE_COUNT];
+/* Parameters received from the previous image */
+static unsigned int trp_boot_abi_version;
+static uintptr_t trp_shared_region_start;
+
+/* Parameters received from boot manifest */
+uint32_t trp_boot_manifest_version;
 
 /*******************************************************************************
- * Set the arguments for SMC call
+ * Setup function for TRP.
  ******************************************************************************/
-static trp_args_t *set_smc_args(uint64_t arg0,
-				uint64_t arg1,
-				uint64_t arg2,
-				uint64_t arg3,
-				uint64_t arg4,
-				uint64_t arg5,
-				uint64_t arg6,
-				uint64_t arg7)
+void trp_setup(uint64_t x0,
+	       uint64_t x1,
+	       uint64_t x2,
+	       uint64_t x3)
 {
-	uint32_t linear_id;
-	trp_args_t *pcpu_smc_args;
-
 	/*
-	 * Return to Secure Monitor by raising an SMC. The results of the
-	 * service are passed as an arguments to the SMC
+	 * Validate boot parameters.
+	 *
+	 * According to the Boot Interface ABI v.0.1, the
+	 * parameters recived from EL3 are:
+	 * x0: CPUID (verified earlier so not used)
+	 * x1: Boot Interface version
+	 * x2: PLATFORM_CORE_COUNT
+	 * x3: Pointer to the shared memory area.
 	 */
-	linear_id = plat_my_core_pos();
-	pcpu_smc_args = &trp_smc_args[linear_id];
-	write_trp_arg(pcpu_smc_args, TRP_ARG0, arg0);
-	write_trp_arg(pcpu_smc_args, TRP_ARG1, arg1);
-	write_trp_arg(pcpu_smc_args, TRP_ARG2, arg2);
-	write_trp_arg(pcpu_smc_args, TRP_ARG3, arg3);
-	write_trp_arg(pcpu_smc_args, TRP_ARG4, arg4);
-	write_trp_arg(pcpu_smc_args, TRP_ARG5, arg5);
-	write_trp_arg(pcpu_smc_args, TRP_ARG6, arg6);
-	write_trp_arg(pcpu_smc_args, TRP_ARG7, arg7);
 
-	return pcpu_smc_args;
-}
+	(void)x0;
 
-/*******************************************************************************
- * Setup function for TRP.
- ******************************************************************************/
-void trp_setup(void)
-{
+	if (TRP_RMM_EL3_VERSION_GET_MAJOR(x1) != TRP_RMM_EL3_ABI_VERS_MAJOR) {
+		trp_boot_abort(E_RMM_BOOT_VERSION_MISMATCH);
+	}
+
+	if ((void *)x3 == NULL) {
+		trp_boot_abort(E_RMM_BOOT_INVALID_SHARED_BUFFER);
+	}
+
+	if (x2 > TRP_PLATFORM_CORE_COUNT) {
+		trp_boot_abort(E_RMM_BOOT_CPUS_OUT_OF_RANGE);
+	}
+
+	trp_boot_abi_version = x1;
+	trp_shared_region_start = x3;
+	flush_dcache_range((uintptr_t)&trp_boot_abi_version,
+			   sizeof(trp_boot_abi_version));
+	flush_dcache_range((uintptr_t)&trp_shared_region_start,
+			   sizeof(trp_shared_region_start));
+
 	/* Perform early platform-specific setup */
-	trp_early_platform_setup();
+	trp_early_platform_setup((rmm_manifest_t *)trp_shared_region_start);
 }
 
 /* Main function for TRP */
@@ -66,9 +71,19 @@
 {
 	NOTICE("TRP: %s\n", version_string);
 	NOTICE("TRP: %s\n", build_message);
+	NOTICE("TRP: Supported RMM-EL3 Interface ABI: v.%u.%u\n",
+		TRP_RMM_EL3_ABI_VERS_MAJOR, TRP_RMM_EL3_ABI_VERS_MINOR);
+	NOTICE("TRP: Boot Manifest Version : v.%u.%u\n",
+		RMMD_GET_MANIFEST_VERSION_MAJOR(trp_boot_manifest_version),
+		RMMD_GET_MANIFEST_VERSION_MINOR(trp_boot_manifest_version));
 	INFO("TRP: Memory base : 0x%lx\n", (unsigned long)RMM_BASE);
+	INFO("TRP: Base address for the shared region : 0x%lx\n",
+			(unsigned long)trp_shared_region_start);
 	INFO("TRP: Total size : 0x%lx bytes\n", (unsigned long)(RMM_END
 								- RMM_BASE));
+	INFO("TRP: RMM-EL3 Interface ABI reported by EL3: v.%u.%u\n",
+		TRP_RMM_EL3_VERSION_GET_MAJOR(trp_boot_abi_version),
+		TRP_RMM_EL3_VERSION_GET_MINOR(trp_boot_abi_version));
 }
 
 /*******************************************************************************
diff --git a/services/std_svc/rmmd/trp/trp_private.h b/services/std_svc/rmmd/trp/trp_private.h
index 4c5222e..945ae1c 100644
--- a/services/std_svc/rmmd/trp/trp_private.h
+++ b/services/std_svc/rmmd/trp/trp_private.h
@@ -7,27 +7,21 @@
 #ifndef TRP_PRIVATE_H
 #define TRP_PRIVATE_H
 
-/* Definitions to help the assembler access the SMC/ERET args structure */
-#define TRP_ARGS_SIZE		TRP_ARGS_END
-#define TRP_ARG0		0x0
-#define TRP_ARG1		0x8
-#define TRP_ARG2		0x10
-#define TRP_ARG3		0x18
-#define TRP_ARG4		0x20
-#define TRP_ARG5		0x28
-#define TRP_ARG6		0x30
-#define TRP_ARG7		0x38
-#define TRP_ARGS_END		0x40
+#include <services/rmmd_svc.h>
+#include <trp_helpers.h>
+
+/* Definitions for RMM-EL3 Interface ABI VERSION */
+#define TRP_RMM_EL3_ABI_VERS_MAJOR	RMM_EL3_IFC_VERSION_MAJOR
+#define TRP_RMM_EL3_ABI_VERS_MINOR	RMM_EL3_IFC_VERSION_MINOR
+#define TRP_RMM_EL3_ABI_VERS	(((TRP_RMM_EL3_ABI_VERS_MAJOR & 0x7FFF) << 16) | \
+				 (TRP_RMM_EL3_ABI_VERS_MINOR & 0xFFFF))
+
+#define TRP_PLATFORM_CORE_COUNT		PLATFORM_CORE_COUNT
 
 #ifndef __ASSEMBLER__
 
 #include <stdint.h>
 
-/* Data structure to hold SMC arguments */
-typedef struct trp_args {
-	uint64_t regs[TRP_ARGS_END >> 3];
-} __aligned(CACHE_WRITEBACK_GRANULE) trp_args_t;
-
 #define write_trp_arg(args, offset, val) (((args)->regs[offset >> 3])	\
 					 = val)
 /* RMI SMC64 FIDs handled by the TRP */
@@ -38,8 +32,14 @@
 /* Definitions for RMI VERSION */
 #define RMI_ABI_VERSION_MAJOR		U(0x0)
 #define RMI_ABI_VERSION_MINOR		U(0x0)
-#define RMI_ABI_VERSION			((RMI_ABI_VERSION_MAJOR << 16) | \
-					RMI_ABI_VERSION_MINOR)
+#define RMI_ABI_VERSION			(((RMI_ABI_VERSION_MAJOR & 0x7FFF) \
+								  << 16) | \
+					 (RMI_ABI_VERSION_MINOR & 0xFFFF))
+
+#define TRP_RMM_EL3_VERSION_GET_MAJOR(x)		\
+				RMM_EL3_IFC_VERSION_GET_MAJOR((x))
+#define TRP_RMM_EL3_VERSION_GET_MINOR(x)		\
+				RMM_EL3_IFC_VERSION_GET_MAJOR_MINOR((x))
 
 /* Helper to issue SMC calls to BL31 */
 uint64_t trp_smc(trp_args_t *);
@@ -48,7 +48,10 @@
 void trp_main(void);
 
 /* Setup TRP. Executed only by Primary CPU */
-void trp_setup(void);
+void trp_setup(uint64_t x0,
+	       uint64_t x1,
+	       uint64_t x2,
+	       uint64_t x3);
 
 #endif /* __ASSEMBLER__ */
 #endif /* TRP_PRIVATE_H */