Merge "fix(TFTF): ensure robustness of SError inject test"
diff --git a/Makefile b/Makefile
index a758b8a..8eba940 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@
 
 # TFTF Version
 VERSION_MAJOR		:= 2
-VERSION_MINOR		:= 4
+VERSION_MINOR		:= 5
 
 MAKE_HELPERS_DIRECTORY := make_helpers/
 include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
diff --git a/docs/change-log.rst b/docs/change-log.rst
index 91f3fde..136bbd4 100644
--- a/docs/change-log.rst
+++ b/docs/change-log.rst
@@ -7,6 +7,184 @@
 Tests are not guaranteed to be compatible. This also means that a version
 upgrade on the TF-A-Tests side might not necessarily introduce any new feature.
 
+Version 2.5
+-----------
+
+New features
+^^^^^^^^^^^^
+-  More tests are made available in this release to help validate the
+   functionalities in the following areas:
+    -  True Random Number Generator (TRNG) test scenarios.
+    -  Multicore / Power State Controller Interface (PSCI) tests.
+    -  v8.6 Activity Monitors Unit (AMU) enhancements test scenarios.
+    -  Secure Partition Manager (SPM) / Firmware Framework (FF-A) v1.0 testing.
+        -  Interrupt Handling between Non-secure and Secure world.
+        -  Direct messages and memory sharing between Secure Partitions(SP).
+        -  Many tests to exercise FF-A v1.0 ABIs.
+        -  SPM saving/restoring the NS SIMD context enabling a normal world FF-A
+           endpoint (TFTF) and a secure partition to use SIMD vectors and
+           instructions independently.
+
+TFTF
+~~~~
+
+-  SPM / FF-A v1.0 testing.
+    -  Refactor FF-A memory sharing tests
+        -  Created helper functions to initialize ffa_memory_region and to send
+           the respective memory region to the SP, making it possible to reuse
+           the logic in SP-to-SP memory share tests.
+        -  Added comments to document relevant aspects about memory sharing.
+
+    -  Trigger direct messaging between SPs.
+        -  Use cactus command 'CACTUS_REQ_ECHO_SEND_CMD' to make cactus SPs
+           communicate with each other using direct message interfaces.
+
+    -  Added helpers for SPM tests.
+        -  Checking SPMC has expected FFA_VERSION.
+        -  Checking that expected FF-A endpoints are deployed in the system.
+        -  Getting global TFTF mailbox.
+
+-  Replace '.inst' AArch64 machine directives with CPU Memory Tagging Extension
+   instructions in 'test_mte_instructions' function.
+
+-  Add build option for Arm Feature Modifiers.
+    -  This patch adds a new ARM_ARCH_FEATURE build option to add support
+       for compiler's feature modifiers.
+
+-  Enable 8 cores support for Theodul DSU(DynamIQ Shared Unit) for the
+   Total Compute (TC0) platform.
+
+-  New tests:
+
+    -  Remove redundant code and add better tests for TRNG SMCs.
+         -  Tests that the Version, Features, and RND calls conform to the spec.
+
+    -  New tests for v8.6 AMU enhancements (FEAT_AMUv1p1)
+         -  Make sure AMU offsets are being saved and restored properly.
+
+    -  Tests to request SP-to-SP memory share.
+
+    -  SP-to-SP direct messaging deadlock test.
+         -  TFTF sends CACTUS_REQ_DEADLOCK_CMD to cactus SP.
+
+Cactus(Secure-EL1 test partition)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+-  Enable managed exit for primary cactus secure partition.
+
+-  Helper commands needed for interrupt testing.
+
+-  Add handler from managed exit FIQ interrupt.
+
+-  Make ffa_id global.
+
+-  Implement HF_INTERRUPT_ENABLE Hafnium hypervisor call wrapper. With this
+   service, a secure partition calls into the SPMC to enable/disable a
+   particular virtual interrupt.
+
+-  Invalidate the data cache for the cactus image.
+
+-  Helper commands needed for interrupt testing.
+     -  CACTUS_SLEEP_CMD & CACTUS_INTERRUPT_CMD added.
+
+-  Decouple exception handling from tftf framework.
+    -  With new interrupt related tests coming up in Cactus, added separate
+       exception handler code for irq/fiq in Cactus.
+
+-  Hypervisor calls moved to a separate module.
+
+-  Add secondary entry point register function.
+
+-  Declare third SP instance as UP SP.
+
+-  Provision a cold boot path for secondary cores (or secondary pinned
+   execution contexts).
+
+-  Tidy message loop, commands definitions, direct messaging API definitions.
+
+-  Helpers for error logging after FF-A calls.
+
+-  Properly placing Cactus test files.
+
+-  Tidying FF-A Memory Sharing tests.
+
+-  Use CACTUS_ECHO_CMD in direct message tests.
+
+-  Refactor handling of commands.
+    -  Added helper macros to define a command handler, build a command table
+       in which each element is a pair of the handler and respective command
+       ID. Available tests have been moved to their own command handler.
+
+-  Extend arguments in commands responses.
+    -  In the test commands framework, added template to extend number of
+       values to include in a command response.
+
+-  Check FF-A return is a valid direct response.
+    -  Added a helper function to check if return of FFA_MSG_SEND_DIRECT_REQ
+       is FFA_MSG_SEND_DIRECT_RESP.
+
+-  FFA_MSG_DIRECT_RESP call extended to use 5 registers.
+
+-  Added accessors for arguments from FF-A calls.
+    -  Some accessors for arguments from FF-A calls, namely for func id, error
+       code, and direct message destination/source.
+
+-  Use virtual counter for sp_sleep.
+    -  Changes sp_sleep() to use virtual counter instead of physical counter.
+
+-  Checks if SIMD vectors are preserved in the normal world while transitioning
+   from normal world to secure world and back to normal world.
+
+-  Tidying common code to tftf and cactus.
+
+-  Refactor cactus_test_cmds.h to incorporate static inline functions instead
+   of macros to enforce type checking.
+
+-  Removed reference to Hafnium in name from helper function and macro to
+   make them generic.
+
+-  For consistency added the cmd id 'CACTUS_MEM_SEND_CMD'.
+
+-  Add command to request memory sharing between SPs.
+
+-  Add & handle commands 'CACTUS_REQ_ECHO_CMD' and 'CACTUS_ECHO_CMD'.
+
+-  Update README with list of sample partitions.
+
+-  Remove reference to PSA from xml test file.
+
+-  Reduce tests verbosity in release mode.
+    -  Update few NOTICE messages to VERBOSE/INFO.
+
+-  Fix conversion issues on cactus responses.
+
+-  Create RXTX map/configure helper macros and use them.
+
+-  Update OP-TEE version used for testing to 3.10.
+    -  SPMC as S-EL1 tests using OP-TEE depend on a static binary stored as
+       a CI file. This binary corresponds to a build of OP-TEE v3.10.
+
+-  Add uart2 to device-regions node.
+    -  First SP no longer has an open access to the full system peripheral
+       range and devices must be explicitly declared in the SP manifest.
+
+-  New tests:
+
+    -  Test for exercising SMMUv3 driver to perform stage2 translation.
+
+    -  Test handling of non-secure interrupt while running SP.
+
+    -  Add secondary cores direct messaging test for SPM.
+
+    -  Testing deadlock by FF-A direct message.
+         -  Added command CACTUS_DEADLOCK_CMD to file cactus_test_cmds.h to create
+            a deadlock scenario using FF-A direct message interfaces.
+
+    -  Test SP-to-SP memory share operations
+         -  Handle 'CACTUS_REQ_MEM_SEND_CMD' by sending memory to the receiver SP.
+
+    -  Implemented test to validate FFA_RXTX_MAP ABI.
+
 Version 2.4
 -----------
 
diff --git a/docs/getting_started/build.rst b/docs/getting_started/build.rst
index 27ad580..d0147f9 100644
--- a/docs/getting_started/build.rst
+++ b/docs/getting_started/build.rst
@@ -206,24 +206,11 @@
 SPM test images
 ```````````````
 
-This repository contains 3 Secure Partitions that exercise the Secure Partition
-Manager (SPM) in TF-A [#]_. Cactus-MM is designed to test the SPM
-implementation based on the `ARM Management Mode Interface`_ (MM), while Cactus
-and Ivy can test the SPM implementation based on the SPCI and SPRT draft
-specifications. Note that it isn't possible to use both communication mechanisms
-at once: If Cactus-MM is used Cactus and Ivy can't be used.
+This repository contains three sample Secure Partitions (SP) meant to be used
+with one implementation of a Secure Partition Manager (SPM):
 
-They run in Secure-EL0 and perform the following tasks:
-
--  Test that TF-A has correctly setup the secure partition environment: They
-   should be allowed to perform cache maintenance operations, access floating
-   point registers, etc.
-
--  Test that TF-A accepts to change data access permissions and instruction
-   permissions on behalf of the Secure Partitions for memory regions the latter
-   owns.
-
--  Test communication with SPM through either MM, or both SPCI and SPRT.
+- Cactus-MM
+- Cactus and Ivy
 
 They are only supported on AArch64 FVP. They can be built independently of the
 other test images using the following command:
@@ -232,16 +219,35 @@
 
    make PLAT=fvp cactus ivy cactus_mm
 
-In the TF-A boot flow, the partitions replace the ``BL32`` image and should be
-injected in the FIP image. To test SPM-MM with Cactus-MM, it is enough to use
-``cactus_mm.bin`` as BL32 image. To test the SPM based on SPCI and SPRT, it is
-needed to use ``sp_tool`` to build a Secure Partition package that can be used
-as BL32 image.
-
 To run the full set of tests in the Secure Partitions, they should be used in
 conjunction with the TFTF image.
 
-For SPM-MM, build TF-A following the `TF-A SPM User Guide`_ and the following
+Please refer to the `TF-A documentation`_ for further details.
+
+Cactus-MM
+'''''''''
+
+Cactus-MM is designed to test the TF-A EL3 SPM implementation
+(`TF-A Secure Partition Manager (MM)`_) based on the
+`Arm Management Mode Interface`_ (MM)
+
+This SP runs in Secure-EL0 and performs the following tasks:
+
+-  Test that TF-A has correctly setup the secure partition environment: it
+   should be allowed to perform cache maintenance operations, access floating
+   point registers, etc.
+
+-  Test that TF-A accepts to change data access permissions and instruction
+   permissions on behalf of the Secure Partition for memory regions the latter
+   owns.
+
+-  Test communication with SPM through MM interface.
+
+In the TF-A boot flow, the partition replaces the ``BL32`` image and should be
+injected in the FIP image. To test SPM-MM with Cactus-MM, it is enough to use
+``cactus_mm.bin`` as BL32 image.
+
+For SPM-MM, build TF-A following `Building TF-A Secure Partition Manager (MM)`_ and the following
 commands can be used to build the tests:
 
 ::
@@ -250,8 +256,40 @@
 
     make PLAT=fvp TESTS=spm-mm tftf cactus_mm
 
-For SPM based on SPCI and SPRT, build TF-A following the `TF-A SPM User Guide`_
-and the following commands can be used to build the tests:
+Cactus and Ivy
+''''''''''''''
+
+Cactus and Ivy are designed to test the FF-A based SPM implementation with
+secure virtualization enabled. Refer to `Arm Firmware Framework for Armv8-A`_
+
+In the TF-A reference code base, BL31 implements the SPMD and BL32 the SPMC.
+The SPMC runs at S-EL2 and acts as a partition manager for multiple secure
+partitions (`TF-A Secure Partition Manager (FF-A)`_):
+
+- Cactus is a sample FF-A compliant S-EL1 partition. As a matter of providing
+  a realistic test harness, three instances of the same partition binary are
+  launched as separate SPs (hence assigned three different FF-A IDs
+  corresponding each to a different secure partition). Each secure partition
+  instance has a separate manifest (`Cactus sample manifest`_,
+  `Cactus secondary manifest`_, `Cactus tertiary manifest`_ ). First two
+  instances are MP SPs. Third instance is a UP SP. Each instance runs a set
+  of built-in tests at boot time. They exercise SP to SPMC FF-A interfaces
+  contained in the secure world. The partition interacts with the SPMC through
+  SMC. Once the NWd and TFTF are started, another set of run-time tests
+  exercise the normal world to secure world primitives.
+- Ivy is a specific kind of S-EL1 UP partition, where the S-EL1 exception level
+  consists of a thin shim layer. The applicative part of the partition is held
+  at S-EL0. The shim provides early bootstrap code, MMU configuration and a
+  vector table trapping S-EL0 requests. The application interacts with the shim
+  through FF-A protocol by the use of SVC instruction. The shim relays the
+  request to the SPMC by an SMC. The S-EL0 application doesn't require knowledge
+  of the shim, and can be self contained.
+
+This picture illustrates the test setup:
+
+.. image:: ../resources/tftf-cactus.png
+
+To build TFTF with SPM tests, Cactus and Ivy use:
 
 ::
 
@@ -259,31 +297,23 @@
 
     make PLAT=fvp TESTS=spm tftf cactus ivy
 
-    # TF-A repository:
-
-    make sptool
-
-    tools/sptool/sptool -o sp_package.bin \
-        -i path/to/cactus.bin:path/to/cactus.dtb \
-        -i path/to/ivy.bin:path/to/ivy.dtb
-
-Please refer to the `TF-A documentation`_ for further details.
-
 --------------
 
 .. [#] Therefore, the Trusted Board Boot feature must be enabled in TF-A for
        the FWU test images to work. Please refer the `TF-A documentation`_ for
        further details.
 
-.. [#] Therefore, the Secure Partition Manager must be enabled in TF-A for
-       any of the test Secure Partitions to work. Please refer to the
-       `TF-A documentation`_ for further details.
-
 --------------
 
-*Copyright (c) 2019, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2021, Arm Limited. All rights reserved.*
 
 .. _EL3 test payload README file: https://git.trustedfirmware.org/TF-A/tf-a-tests.git/tree/el3_payload/README
-.. _ARM Management Mode Interface: http://infocenter.arm.com/help/topic/com.arm.doc.den0060a/DEN0060A_ARM_MM_Interface_Specification.pdf
+.. _Arm Management Mode Interface: https://developer.arm.com/documentation/den0060/a/
+.. _Arm Firmware Framework for Armv8-A: https://developer.arm.com/docs/den0077/latest
 .. _TF-A documentation: https://trustedfirmware-a.readthedocs.org
-.. _TF-A SPM User Guide: https://trustedfirmware-a.readthedocs.io/en/latest/components/secure-partition-manager-design.html#building-tf-a-with-secure-partition-support
+.. _TF-A Secure Partition Manager (FF-A): https://trustedfirmware-a.readthedocs.io/en/latest/components/secure-partition-manager.html
+.. _TF-A Secure Partition Manager (MM): https://trustedfirmware-a.readthedocs.io/en/latest/components/secure-partition-manager-mm.html
+.. _Building TF-A Secure Partition Manager (MM): https://trustedfirmware-a.readthedocs.io/en/latest/components/secure-partition-manager-mm.html#building-tf-a-with-secure-partition-support
+.. _Cactus sample manifest: https://git.trustedfirmware.org/TF-A/tf-a-tests.git/tree/spm/cactus/plat/arm/fvp/fdts/cactus.dts?h=v2.5-rc1
+.. _Cactus secondary manifest: https://git.trustedfirmware.org/TF-A/tf-a-tests.git/tree/spm/cactus/plat/arm/fvp/fdts/cactus-secondary.dts?h=v2.5-rc1
+.. _Cactus tertiary manifest: https://git.trustedfirmware.org/TF-A/tf-a-tests.git/tree/spm/cactus/plat/arm/fvp/fdts/cactus-tertiary.dts?h=v2.5-rc1
diff --git a/docs/resources/tftf-cactus.png b/docs/resources/tftf-cactus.png
new file mode 100644
index 0000000..29539f7
--- /dev/null
+++ b/docs/resources/tftf-cactus.png
Binary files differ
diff --git a/include/lib/mmio.h b/include/lib/mmio.h
index e8a7df0..c788af3 100644
--- a/include/lib/mmio.h
+++ b/include/lib/mmio.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -24,16 +24,33 @@
 	*(volatile uint32_t*)addr = value;
 }
 
+static inline void mmio_write32_offset(uintptr_t addr, uint32_t byte_off,
+					uint32_t data)
+{
+	mmio_write_32((uintptr_t)((uint8_t *)addr + byte_off), data);
+}
+
 static inline uint32_t mmio_read_32(uintptr_t addr)
 {
 	return *(volatile uint32_t*)addr;
 }
 
+static inline uint32_t mmio_read32_offset(uintptr_t addr, uint32_t byte_off)
+{
+	return mmio_read_32((uintptr_t)((uint8_t *)addr + byte_off));
+}
+
 static inline void mmio_write_64(uintptr_t addr, uint64_t value)
 {
 	*(volatile uint64_t*)addr = value;
 }
 
+static inline void mmio_write64_offset(uintptr_t addr, uint32_t byte_off,
+					uint64_t data)
+{
+	mmio_write_64((uintptr_t)((uint8_t *)addr + byte_off), data);
+}
+
 static inline uint64_t mmio_read_64(uintptr_t addr)
 {
 	return *(volatile uint64_t*)addr;
diff --git a/include/runtime_services/cactus_test_cmds.h b/include/runtime_services/cactus_test_cmds.h
index d03a97f..0970968 100644
--- a/include/runtime_services/cactus_test_cmds.h
+++ b/include/runtime_services/cactus_test_cmds.h
@@ -37,7 +37,7 @@
  * messages interfaces.
  */
 static inline smc_ret_values cactus_send_cmd(
-	ffa_vm_id_t source, ffa_vm_id_t dest, uint64_t cmd, uint64_t val0,
+	ffa_id_t source, ffa_id_t dest, uint64_t cmd, uint64_t val0,
 	uint64_t val1, uint64_t val2, uint64_t val3)
 {
 	return 	ffa_msg_send_direct_req64(source, dest, cmd, val0, val1, val2,
@@ -50,7 +50,7 @@
  * a need to propagate more than one value in the response of a command.
  */
 static inline smc_ret_values cactus_send_response(
-	ffa_vm_id_t source, ffa_vm_id_t dest, uint32_t resp, uint32_t val0,
+	ffa_id_t source, ffa_id_t dest, uint32_t resp, uint32_t val0,
 	uint64_t val1, uint64_t val2, uint64_t val3)
 {
 	return ffa_msg_send_direct_resp64(source, dest, resp, val0, val1,
@@ -61,7 +61,7 @@
  * For responses of one value only.
  */
 static inline smc_ret_values cactus_response(
-	ffa_vm_id_t source, ffa_vm_id_t dest, uint32_t response)
+	ffa_id_t source, ffa_id_t dest, uint32_t response)
 {
 	return ffa_msg_send_direct_resp64(source, dest, response, 0, 0, 0, 0);
 }
@@ -78,7 +78,7 @@
  * specific test.
  */
 static inline smc_ret_values cactus_success_resp(
-		ffa_vm_id_t source, ffa_vm_id_t dest, uint64_t value)
+		ffa_id_t source, ffa_id_t dest, uint64_t value)
 {
 	return cactus_send_response(source, dest, CACTUS_SUCCESS, value,
 				    0, 0, 0);
@@ -90,7 +90,7 @@
  * in the error code list.
  */
 static inline smc_ret_values cactus_error_resp(
-		ffa_vm_id_t source, ffa_vm_id_t dest, uint32_t error_code)
+		ffa_id_t source, ffa_id_t dest, uint32_t error_code)
 {
 	return cactus_send_response(source, dest, CACTUS_ERROR, error_code,
 				    0, 0, 0);
@@ -110,7 +110,7 @@
 #define CACTUS_ECHO_CMD U(0x6563686f)
 
 static inline smc_ret_values cactus_echo_send_cmd(
-	ffa_vm_id_t source, ffa_vm_id_t dest, uint64_t echo_val)
+	ffa_id_t source, ffa_id_t dest, uint64_t echo_val)
 {
 	return cactus_send_cmd(source, dest, CACTUS_ECHO_CMD, echo_val, 0, 0,
 			       0);
@@ -131,16 +131,16 @@
 #define CACTUS_REQ_ECHO_CMD (CACTUS_ECHO_CMD + 1)
 
 static inline smc_ret_values cactus_req_echo_send_cmd(
-	ffa_vm_id_t source, ffa_vm_id_t dest, ffa_vm_id_t echo_dest,
+	ffa_id_t source, ffa_id_t dest, ffa_id_t echo_dest,
 	uint64_t echo_val)
 {
 	return cactus_send_cmd(source, dest, CACTUS_REQ_ECHO_CMD, echo_val,
 			       echo_dest, 0, 0);
 }
 
-static inline ffa_vm_id_t cactus_req_echo_get_echo_dest(smc_ret_values ret)
+static inline ffa_id_t cactus_req_echo_get_echo_dest(smc_ret_values ret)
 {
-	return (ffa_vm_id_t)ret.ret5;
+	return (ffa_id_t)ret.ret5;
 }
 
 /**
@@ -155,15 +155,15 @@
 #define CACTUS_DEADLOCK_CMD U(0x64656164)
 
 static inline smc_ret_values cactus_deadlock_send_cmd(
-	ffa_vm_id_t source, ffa_vm_id_t dest, ffa_vm_id_t next_dest)
+	ffa_id_t source, ffa_id_t dest, ffa_id_t next_dest)
 {
 	return cactus_send_cmd(source, dest, CACTUS_DEADLOCK_CMD, next_dest, 0,
 			       0, 0);
 }
 
-static inline ffa_vm_id_t cactus_deadlock_get_next_dest(smc_ret_values ret)
+static inline ffa_id_t cactus_deadlock_get_next_dest(smc_ret_values ret)
 {
-	return (ffa_vm_id_t)ret.ret4;
+	return (ffa_id_t)ret.ret4;
 }
 
 /**
@@ -173,17 +173,17 @@
 #define CACTUS_REQ_DEADLOCK_CMD (CACTUS_DEADLOCK_CMD + 1)
 
 static inline smc_ret_values cactus_req_deadlock_send_cmd(
-	ffa_vm_id_t source, ffa_vm_id_t dest, ffa_vm_id_t next_dest1,
-	ffa_vm_id_t next_dest2)
+	ffa_id_t source, ffa_id_t dest, ffa_id_t next_dest1,
+	ffa_id_t next_dest2)
 {
 	return cactus_send_cmd(source, dest, CACTUS_REQ_DEADLOCK_CMD,
 			       next_dest1, next_dest2, 0, 0);
 }
 
 /* To get next_dest1 use CACTUS_DEADLOCK_GET_NEXT_DEST */
-static inline ffa_vm_id_t cactus_deadlock_get_next_dest2(smc_ret_values ret)
+static inline ffa_id_t cactus_deadlock_get_next_dest2(smc_ret_values ret)
 {
-	return (ffa_vm_id_t)ret.ret5;
+	return (ffa_id_t)ret.ret5;
 }
 
 /**
@@ -195,7 +195,7 @@
 #define CACTUS_MEM_SEND_CMD U(0x6d656d)
 
 static inline smc_ret_values cactus_mem_send_cmd(
-	ffa_vm_id_t source, ffa_vm_id_t dest, uint32_t mem_func,
+	ffa_id_t source, ffa_id_t dest, uint32_t mem_func,
 	ffa_memory_handle_t handle)
 {
 	return cactus_send_cmd(source, dest, CACTUS_MEM_SEND_CMD, mem_func,
@@ -217,8 +217,8 @@
 #define CACTUS_REQ_MEM_SEND_CMD U(0x6d656d6f7279)
 
 static inline smc_ret_values cactus_req_mem_send_send_cmd(
-	ffa_vm_id_t source, ffa_vm_id_t dest, uint32_t mem_func,
-	ffa_vm_id_t receiver)
+	ffa_id_t source, ffa_id_t dest, uint32_t mem_func,
+	ffa_id_t receiver)
 {
 	return cactus_send_cmd(source, dest, CACTUS_REQ_MEM_SEND_CMD, mem_func,
 			       receiver, 0, 0);
@@ -229,9 +229,9 @@
 	return (uint32_t)ret.ret4;
 }
 
-static inline ffa_vm_id_t cactus_req_mem_send_get_receiver(smc_ret_values ret)
+static inline ffa_id_t cactus_req_mem_send_get_receiver(smc_ret_values ret)
 {
-	return (ffa_vm_id_t)ret.ret5;
+	return (ffa_id_t)ret.ret5;
 }
 
 /**
@@ -244,7 +244,7 @@
 #define CACTUS_REQ_SIMD_FILL_CMD U(0x53494d44)
 
 static inline smc_ret_values cactus_req_simd_fill_send_cmd(
-	ffa_vm_id_t source, ffa_vm_id_t dest)
+	ffa_id_t source, ffa_id_t dest)
 {
 	return cactus_send_cmd(source, dest, CACTUS_REQ_SIMD_FILL_CMD, 0, 0, 0,
 			       0);
@@ -258,7 +258,7 @@
 #define CACTUS_SLEEP_CMD U(0x736c656570)
 
 static inline smc_ret_values cactus_sleep_cmd(
-	ffa_vm_id_t source, ffa_vm_id_t dest, uint32_t sleep_time)
+	ffa_id_t source, ffa_id_t dest, uint32_t sleep_time)
 {
 	return cactus_send_cmd(source, dest, CACTUS_SLEEP_CMD, sleep_time, 0, 0,
 			       0);
@@ -277,7 +277,7 @@
 #define CACTUS_INTERRUPT_CMD U(0x696e7472)
 
 static inline smc_ret_values cactus_interrupt_cmd(
-	ffa_vm_id_t source, ffa_vm_id_t dest, uint32_t interrupt_id,
+	ffa_id_t source, ffa_id_t dest, uint32_t interrupt_id,
 	bool enable, uint32_t pin)
 {
 	return cactus_send_cmd(source, dest, CACTUS_INTERRUPT_CMD, interrupt_id,
@@ -299,4 +299,17 @@
 	return (enum interrupt_pin)ret.ret6;
 }
 
+/**
+ * Request to initiate DMA transaction by upstream peripheral.
+ *
+ * The command id is the hex representation of the string "SMMU"
+ */
+#define CACTUS_DMA_SMMUv3_CMD           (0x534d4d55)
+
+static inline smc_ret_values cactus_send_dma_cmd(
+	ffa_id_t source, ffa_id_t dest)
+{
+	return cactus_send_cmd(source, dest, CACTUS_DMA_SMMUv3_CMD, 0, 0, 0,
+			       0);
+}
 #endif
diff --git a/include/runtime_services/ffa_helpers.h b/include/runtime_services/ffa_helpers.h
index 592327a..3ca9c82 100644
--- a/include/runtime_services/ffa_helpers.h
+++ b/include/runtime_services/ffa_helpers.h
@@ -14,7 +14,7 @@
 /* This error code must be different to the ones used by FFA */
 #define FFA_TFTF_ERROR		-42
 
-typedef unsigned short ffa_vm_id_t;
+typedef unsigned short ffa_id_t;
 typedef unsigned short ffa_vm_count_t;
 typedef unsigned short ffa_vcpu_count_t;
 typedef uint64_t ffa_memory_handle_t;
@@ -31,7 +31,7 @@
 
 struct ffa_partition_info {
 	/** The ID of the VM the information is about */
-	ffa_vm_id_t id;
+	ffa_id_t id;
 	/** The number of execution contexts implemented by the partition */
 	uint16_t exec_context;
 	/** The Partition's properties, e.g. supported messaging methods */
@@ -46,6 +46,10 @@
 	return (int32_t) val.ret2;
 }
 
+static inline ffa_id_t ffa_endpoint_id(smc_ret_values val) {
+	return (ffa_id_t) val.ret2 & 0xffff;
+}
+
 enum ffa_data_access {
 	FFA_DATA_ACCESS_NOT_SPECIFIED,
 	FFA_DATA_ACCESS_RO,
@@ -196,7 +200,7 @@
  */
 struct ffa_memory_region_attributes {
 	/** The ID of the VM to which the memory is being given or shared. */
-	ffa_vm_id_t receiver;
+	ffa_id_t receiver;
 	/**
 	 * The permissions with which the memory region should be mapped in the
 	 * receiver's page table.
@@ -264,7 +268,7 @@
 	 * The ID of the VM which originally sent the memory region, i.e. the
 	 * owner.
 	 */
-	ffa_vm_id_t sender;
+	ffa_id_t sender;
 	ffa_memory_attributes_t attributes;
 	/** Reserved field, must be 0. */
 	uint8_t reserved_0;
@@ -300,7 +304,7 @@
 	ffa_memory_handle_t handle;
 	ffa_memory_region_flags_t flags;
 	uint32_t endpoint_count;
-	ffa_vm_id_t endpoints[];
+	ffa_id_t endpoints[];
 };
 
 static inline ffa_memory_handle_t ffa_assemble_handle(uint32_t h1, uint32_t h2)
@@ -335,18 +339,18 @@
 static inline uint32_t ffa_mem_relinquish_init(
 	struct ffa_mem_relinquish *relinquish_request,
 	ffa_memory_handle_t handle, ffa_memory_region_flags_t flags,
-	ffa_vm_id_t sender)
+	ffa_id_t sender)
 {
 	relinquish_request->handle = handle;
 	relinquish_request->flags = flags;
 	relinquish_request->endpoint_count = 1;
 	relinquish_request->endpoints[0] = sender;
-	return sizeof(struct ffa_mem_relinquish) + sizeof(ffa_vm_id_t);
+	return sizeof(struct ffa_mem_relinquish) + sizeof(ffa_id_t);
 }
 
 uint32_t ffa_memory_retrieve_request_init(
 	struct ffa_memory_region *memory_region, ffa_memory_handle_t handle,
-	ffa_vm_id_t sender, ffa_vm_id_t receiver, uint32_t tag,
+	ffa_id_t sender, ffa_id_t receiver, uint32_t tag,
 	ffa_memory_region_flags_t flags, enum ffa_data_access data_access,
 	enum ffa_instruction_access instruction_access,
 	enum ffa_memory_type type, enum ffa_memory_cacheability cacheability,
@@ -354,7 +358,7 @@
 
 uint32_t ffa_memory_region_init(
 	struct ffa_memory_region *memory_region, size_t memory_region_max_size,
-	ffa_vm_id_t sender, ffa_vm_id_t receiver,
+	ffa_id_t sender, ffa_id_t receiver,
 	const struct ffa_memory_region_constituent constituents[],
 	uint32_t constituent_count, uint32_t tag,
 	ffa_memory_region_flags_t flags, enum ffa_data_access data_access,
@@ -363,37 +367,38 @@
 	enum ffa_memory_shareability shareability, uint32_t *total_length,
 	uint32_t *fragment_length);
 
-static inline ffa_vm_id_t ffa_dir_msg_dest(smc_ret_values val) {
-	return (ffa_vm_id_t)val.ret1 & U(0xFFFF);
+static inline ffa_id_t ffa_dir_msg_dest(smc_ret_values val) {
+	return (ffa_id_t)val.ret1 & U(0xFFFF);
 }
 
-static inline ffa_vm_id_t ffa_dir_msg_source(smc_ret_values val) {
-	return (ffa_vm_id_t)(val.ret1 >> 16U);
+static inline ffa_id_t ffa_dir_msg_source(smc_ret_values val) {
+	return (ffa_id_t)(val.ret1 >> 16U);
 }
 
-smc_ret_values ffa_msg_send_direct_req64(ffa_vm_id_t source_id,
-					 ffa_vm_id_t dest_id, uint64_t arg0,
+smc_ret_values ffa_msg_send_direct_req64(ffa_id_t source_id,
+					 ffa_id_t dest_id, uint64_t arg0,
 					 uint64_t arg1, uint64_t arg2,
 					 uint64_t arg3, uint64_t arg4);
 
-smc_ret_values ffa_msg_send_direct_req32(ffa_vm_id_t source_id,
-					 ffa_vm_id_t dest_id, uint32_t arg0,
+smc_ret_values ffa_msg_send_direct_req32(ffa_id_t source_id,
+					 ffa_id_t dest_id, uint32_t arg0,
 					 uint32_t arg1, uint32_t arg2,
 					 uint32_t arg3, uint32_t arg4);
 
-smc_ret_values ffa_msg_send_direct_resp64(ffa_vm_id_t source_id,
-					  ffa_vm_id_t dest_id, uint64_t arg0,
+smc_ret_values ffa_msg_send_direct_resp64(ffa_id_t source_id,
+					  ffa_id_t dest_id, uint64_t arg0,
 					  uint64_t arg1, uint64_t arg2,
 					  uint64_t arg3, uint64_t arg4);
 
-smc_ret_values ffa_msg_send_direct_resp32(ffa_vm_id_t source_id,
-					  ffa_vm_id_t dest_id, uint32_t arg0,
+smc_ret_values ffa_msg_send_direct_resp32(ffa_id_t source_id,
+					  ffa_id_t dest_id, uint32_t arg0,
 					  uint32_t arg1, uint32_t arg2,
 					  uint32_t arg3, uint32_t arg4);
 
 smc_ret_values ffa_run(uint32_t dest_id, uint32_t vcpu_id);
 smc_ret_values ffa_version(uint32_t input_version);
 smc_ret_values ffa_id_get(void);
+smc_ret_values ffa_spm_id_get(void);
 smc_ret_values ffa_msg_wait(void);
 smc_ret_values ffa_error(int32_t error_code);
 smc_ret_values ffa_features(uint32_t feature);
diff --git a/include/runtime_services/ffa_svc.h b/include/runtime_services/ffa_svc.h
index c970265..3a474e7 100644
--- a/include/runtime_services/ffa_svc.h
+++ b/include/runtime_services/ffa_svc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -22,7 +22,7 @@
 
 /* The macros below are used to identify FFA calls from the SMC function ID */
 #define FFA_FNUM_MIN_VALUE	U(0x60)
-#define FFA_FNUM_MAX_VALUE	U(0x84)
+#define FFA_FNUM_MAX_VALUE	U(0x85)
 #define is_ffa_fid(fid) __extension__ ({		\
 	__typeof__(fid) _fid = (fid);			\
 	((GET_SMC_NUM(_fid) >= FFA_FNUM_MIN_VALUE) &&	\
@@ -85,6 +85,7 @@
 #define FFA_FNUM_MEM_RELINQUISH	U(0x76)
 #define FFA_FNUM_MEM_RECLAIM		U(0x77)
 #define FFA_FNUM_SECONDARY_EP_REGISTER	U(0x84)
+#define FFA_FNUM_SPM_ID_GET		U(0x85)
 
 /* FFA SMC32 FIDs */
 #define FFA_ERROR		FFA_FID(SMC_32, FFA_FNUM_ERROR)
@@ -114,6 +115,7 @@
 #define FFA_MEM_RETRIEVE_RESP	FFA_FID(SMC_32, FFA_FNUM_MEM_RETRIEVE_RESP)
 #define FFA_MEM_RELINQUISH	FFA_FID(SMC_32, FFA_FNUM_MEM_RELINQUISH)
 #define FFA_MEM_RECLAIM	FFA_FID(SMC_32, FFA_FNUM_MEM_RECLAIM)
+#define FFA_SPM_ID_GET		FFA_FID(SMC_32, FFA_FNUM_SPM_ID_GET)
 
 /* FFA SMC64 FIDs */
 #define FFA_SUCCESS_SMC64	FFA_FID(SMC_64, FFA_FNUM_SUCCESS)
diff --git a/include/runtime_services/spm_common.h b/include/runtime_services/spm_common.h
index 50159ec..685e732 100644
--- a/include/runtime_services/spm_common.h
+++ b/include/runtime_services/spm_common.h
@@ -13,6 +13,8 @@
 
 /* Hypervisor ID at physical FFA instance */
 #define HYP_ID          (0)
+/* SPMC ID */
+#define SPMC_ID		U(0x8000)
 
 /* ID for the first Secure Partition. */
 #define SPM_VM_ID_FIRST                 SP_ID(1)
@@ -42,6 +44,7 @@
 	const char *test_name;
 	unsigned int feature;
 	unsigned int expected_ret;
+	unsigned int version_added;
 };
 
 struct mailbox_buffers {
@@ -107,7 +110,7 @@
  */
 bool memory_retrieve(struct mailbox_buffers *mb,
 		     struct ffa_memory_region **retrieved, uint64_t handle,
-		     ffa_vm_id_t sender, ffa_vm_id_t receiver,
+		     ffa_id_t sender, ffa_id_t receiver,
 		     uint32_t mem_func);
 
 /**
@@ -115,7 +118,7 @@
  * after it being done with the memory shared, identified by the 'handle'.
  */
 bool memory_relinquish(struct ffa_mem_relinquish *m, uint64_t handle,
-		       ffa_vm_id_t id);
+		       ffa_id_t id);
 
 ffa_memory_handle_t memory_send(
 	struct ffa_memory_region *memory_region, uint32_t mem_func,
@@ -123,7 +126,7 @@
 
 ffa_memory_handle_t memory_init_and_send(
 	struct ffa_memory_region *memory_region, size_t memory_region_max_size,
-	ffa_vm_id_t sender, ffa_vm_id_t receiver,
+	ffa_id_t sender, ffa_id_t receiver,
 	const struct ffa_memory_region_constituent* constituents,
 	uint32_t constituents_count, uint32_t mem_func);
 
diff --git a/plat/arm/fvp/include/platform_def.h b/plat/arm/fvp/include/platform_def.h
index ed45642..3afc9b8 100644
--- a/plat/arm/fvp/include/platform_def.h
+++ b/plat/arm/fvp/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -217,7 +217,11 @@
 #define MAX_XLAT_TABLES			20
 #define MAX_MMAP_REGIONS		50
 #else
+#if IMAGE_CACTUS
+#define MAX_XLAT_TABLES			6
+#else
 #define MAX_XLAT_TABLES			5
+#endif
 #define MAX_MMAP_REGIONS		16
 #endif
 
diff --git a/spm/cactus/cactus.mk b/spm/cactus/cactus.mk
index a52120f..ae66c1d 100644
--- a/spm/cactus/cactus.mk
+++ b/spm/cactus/cactus.mk
@@ -49,6 +49,7 @@
 		cactus_test_ffa.c 			\
 		cactus_test_interrupts.c		\
 		cactus_test_memory_sharing.c		\
+		cactus_tests_smmuv3.c			\
 	)
 
 # TODO: Remove dependency on TFTF files.
diff --git a/spm/cactus/cactus_interrupt.c b/spm/cactus/cactus_interrupt.c
index 7de36cf..f61df94 100644
--- a/spm/cactus/cactus_interrupt.c
+++ b/spm/cactus/cactus_interrupt.c
@@ -13,7 +13,7 @@
 #include "cactus_test_cmds.h"
 #include "spm_common.h"
 
-extern ffa_vm_id_t g_ffa_id;
+extern ffa_id_t g_ffa_id;
 
 static void managed_exit_handler(void)
 {
diff --git a/spm/cactus/cactus_main.c b/spm/cactus/cactus_main.c
index 45d2db0..73606bd 100644
--- a/spm/cactus/cactus_main.c
+++ b/spm/cactus/cactus_main.c
@@ -34,7 +34,7 @@
 extern void secondary_cold_entry(void);
 
 /* Global ffa_id */
-ffa_vm_id_t g_ffa_id;
+ffa_id_t g_ffa_id;
 
 /*
  *
@@ -45,10 +45,10 @@
  *
  */
 
-static void __dead2 message_loop(ffa_vm_id_t vm_id, struct mailbox_buffers *mb)
+static void __dead2 message_loop(ffa_id_t vm_id, struct mailbox_buffers *mb)
 {
 	smc_ret_values ffa_ret;
-	ffa_vm_id_t destination;
+	ffa_id_t destination;
 
 	/*
 	* This initial wait call is necessary to inform SPMD that
@@ -93,6 +93,9 @@
 	/* PLAT_ARM_DEVICE0 area includes UART2 necessary to console */
 	MAP_REGION_FLAT(PLAT_ARM_DEVICE0_BASE, PLAT_ARM_DEVICE0_SIZE,
 			MT_DEVICE | MT_RW),
+	/* scratch memory allocated to be used for running SMMU tests */
+	MAP_REGION_FLAT(PLAT_CACTUS_MEMCPY_BASE, PLAT_CACTUS_MEMCPY_RANGE,
+			MT_MEMORY | MT_RW),
 	{0}
 };
 
@@ -179,7 +182,7 @@
 
 	/* Get current FFA id */
 	smc_ret_values ffa_id_ret = ffa_id_get();
-	ffa_vm_id_t ffa_id = (ffa_vm_id_t)(ffa_id_ret.ret2 & 0xffff);
+	ffa_id_t ffa_id = ffa_endpoint_id(ffa_id_ret);
 	if (ffa_func_id(ffa_id_ret) != FFA_SUCCESS_SMC32) {
 		ERROR("FFA_ID_GET failed.\n");
 		panic();
diff --git a/spm/cactus/cactus_tests/cactus_message_loop.c b/spm/cactus/cactus_tests/cactus_message_loop.c
index 11207dc..fde7074 100644
--- a/spm/cactus/cactus_tests/cactus_message_loop.c
+++ b/spm/cactus/cactus_tests/cactus_message_loop.c
@@ -49,7 +49,6 @@
 		}
 	}
 
-	ERROR("Unhandled test command!\n");
 	*ret = cactus_error_resp(ffa_dir_msg_dest(*cmd_args),
 				 ffa_dir_msg_source(*cmd_args),
 				 CACTUS_ERROR_UNHANDLED);
diff --git a/spm/cactus/cactus_tests/cactus_test_direct_messaging.c b/spm/cactus/cactus_tests/cactus_test_direct_messaging.c
index a59cfa2..9b9d1aa 100644
--- a/spm/cactus/cactus_tests/cactus_test_direct_messaging.c
+++ b/spm/cactus/cactus_tests/cactus_test_direct_messaging.c
@@ -24,8 +24,8 @@
 CACTUS_CMD_HANDLER(req_echo_cmd, CACTUS_REQ_ECHO_CMD)
 {
 	smc_ret_values ffa_ret;
-	ffa_vm_id_t vm_id = ffa_dir_msg_dest(*args);
-	ffa_vm_id_t echo_dest = cactus_req_echo_get_echo_dest(*args);
+	ffa_id_t vm_id = ffa_dir_msg_dest(*args);
+	ffa_id_t echo_dest = cactus_req_echo_get_echo_dest(*args);
 	uint64_t echo_val = cactus_echo_get_val(*args);
 
 	VERBOSE("%x requested to send echo to %x, value %llx\n",
@@ -48,10 +48,10 @@
 	return cactus_success_resp(vm_id, ffa_dir_msg_source(*args), 0);
 }
 
-static smc_ret_values base_deadlock_handler(ffa_vm_id_t vm_id,
-					    ffa_vm_id_t source,
-					    ffa_vm_id_t deadlock_dest,
-					    ffa_vm_id_t deadlock_next_dest)
+static smc_ret_values base_deadlock_handler(ffa_id_t vm_id,
+					    ffa_id_t source,
+					    ffa_id_t deadlock_dest,
+					    ffa_id_t deadlock_next_dest)
 {
 	smc_ret_values ffa_ret;
 
@@ -92,9 +92,9 @@
 
 CACTUS_CMD_HANDLER(deadlock_cmd, CACTUS_DEADLOCK_CMD)
 {
-	ffa_vm_id_t source = ffa_dir_msg_source(*args);
-	ffa_vm_id_t deadlock_dest = cactus_deadlock_get_next_dest(*args);
-	ffa_vm_id_t deadlock_next_dest = source;
+	ffa_id_t source = ffa_dir_msg_source(*args);
+	ffa_id_t deadlock_dest = cactus_deadlock_get_next_dest(*args);
+	ffa_id_t deadlock_next_dest = source;
 
 	VERBOSE("%x is creating deadlock. next: %x\n", source, deadlock_dest);
 
@@ -104,10 +104,10 @@
 
 CACTUS_CMD_HANDLER(req_deadlock_cmd, CACTUS_REQ_DEADLOCK_CMD)
 {
-	ffa_vm_id_t vm_id = ffa_dir_msg_dest(*args);
-	ffa_vm_id_t source = ffa_dir_msg_source(*args);
-	ffa_vm_id_t deadlock_dest = cactus_deadlock_get_next_dest(*args);
-	ffa_vm_id_t deadlock_next_dest = cactus_deadlock_get_next_dest2(*args);
+	ffa_id_t vm_id = ffa_dir_msg_dest(*args);
+	ffa_id_t source = ffa_dir_msg_source(*args);
+	ffa_id_t deadlock_dest = cactus_deadlock_get_next_dest(*args);
+	ffa_id_t deadlock_next_dest = cactus_deadlock_get_next_dest2(*args);
 
 	VERBOSE("%x requested deadlock with %x and %x\n",
 		ffa_dir_msg_source(*args), deadlock_dest, deadlock_next_dest);
diff --git a/spm/cactus/cactus_tests/cactus_test_ffa.c b/spm/cactus/cactus_tests/cactus_test_ffa.c
index 2ade7bd..93f0403 100644
--- a/spm/cactus/cactus_tests/cactus_test_ffa.c
+++ b/spm/cactus/cactus_tests/cactus_test_ffa.c
@@ -20,6 +20,8 @@
 #define FFA_MAJOR 1U
 #define FFA_MINOR 0U
 
+static uint32_t spm_version;
+
 static const uint32_t primary_uuid[4] = PRIMARY_UUID;
 static const uint32_t secondary_uuid[4] = SECONDARY_UUID;
 static const uint32_t tertiary_uuid[4] = TERTIARY_UUID;
@@ -32,23 +34,31 @@
 {
 	const char *test_features = "FFA Features interface";
 	smc_ret_values ffa_ret;
+	unsigned int expected_ret;
 	const struct ffa_features_test *ffa_feature_test_target;
 	unsigned int i, test_target_size =
 		get_ffa_feature_test_target(&ffa_feature_test_target);
+	struct ffa_features_test test_target;
 
 
 	announce_test_section_start(test_features);
 
 	for (i = 0U; i < test_target_size; i++) {
-		announce_test_start(ffa_feature_test_target[i].test_name);
+		test_target = ffa_feature_test_target[i];
 
-		ffa_ret = ffa_features(ffa_feature_test_target[i].feature);
-		expect(ffa_func_id(ffa_ret), ffa_feature_test_target[i].expected_ret);
-		if (ffa_feature_test_target[i].expected_ret == FFA_ERROR) {
+		announce_test_start(test_target.test_name);
+
+		ffa_ret = ffa_features(test_target.feature);
+		expected_ret = FFA_VERSION_COMPILED
+				>= test_target.version_added ?
+				test_target.expected_ret : FFA_ERROR;
+
+		expect(ffa_func_id(ffa_ret), expected_ret);
+		if (expected_ret == FFA_ERROR) {
 			expect(ffa_error_code(ffa_ret), FFA_ERROR_NOT_SUPPORTED);
 		}
 
-		announce_test_end(ffa_feature_test_target[i].test_name);
+		announce_test_end(test_target.test_name);
 	}
 
 	announce_test_section_end(test_features);
@@ -147,7 +157,7 @@
 	announce_test_start(test_ffa_version);
 
 	smc_ret_values ret = ffa_version(MAKE_FFA_VERSION(FFA_MAJOR, FFA_MINOR));
-	uint32_t spm_version = (uint32_t)ret.ret0;
+	spm_version = (uint32_t)ret.ret0;
 
 	bool ffa_version_compatible =
 		((spm_version >> FFA_VERSION_MAJOR_SHIFT) == FFA_MAJOR &&
@@ -163,6 +173,32 @@
 	announce_test_end(test_ffa_version);
 }
 
+void ffa_spm_id_get_test(void)
+{
+	const char *test_spm_id_get = "FFA_SPM_ID_GET SMC Function";
+
+	announce_test_start(test_spm_id_get);
+
+	if (spm_version >= MAKE_FFA_VERSION(1, 1)) {
+		smc_ret_values ret = ffa_spm_id_get();
+
+		expect(ffa_func_id(ret), FFA_SUCCESS_SMC32);
+
+		ffa_id_t spm_id = ffa_endpoint_id(ret);
+
+		VERBOSE("SPM ID = 0x%x\n", spm_id);
+		/*
+		 * Check the SPMC value given in the fvp_spmc_manifest
+		 * is returned.
+		 */
+		expect(spm_id, SPMC_ID);
+	} else {
+		NOTICE("FFA_SPM_ID_GET not supported in this version of FF-A."
+			" Test skipped.\n");
+	}
+	announce_test_end(test_spm_id_get);
+}
+
 void ffa_tests(struct mailbox_buffers *mb)
 {
 	const char *test_ffa = "FFA Interfaces";
@@ -171,6 +207,7 @@
 
 	ffa_features_test();
 	ffa_version_test();
+	ffa_spm_id_get_test();
 	ffa_partition_info_get_test(mb);
 
 	announce_test_section_end(test_ffa);
diff --git a/spm/cactus/cactus_tests/cactus_test_memory_sharing.c b/spm/cactus/cactus_tests/cactus_test_memory_sharing.c
index e7bce50..604058a 100644
--- a/spm/cactus/cactus_tests/cactus_test_memory_sharing.c
+++ b/spm/cactus/cactus_tests/cactus_test_memory_sharing.c
@@ -24,8 +24,8 @@
 	int ret;
 	unsigned int mem_attrs;
 	uint32_t *ptr;
-	ffa_vm_id_t source = ffa_dir_msg_source(*args);
-	ffa_vm_id_t vm_id = ffa_dir_msg_dest(*args);
+	ffa_id_t source = ffa_dir_msg_source(*args);
+	ffa_id_t vm_id = ffa_dir_msg_dest(*args);
 	uint32_t mem_func = cactus_req_mem_send_get_mem_func(*args);
 	uint64_t handle = cactus_mem_send_get_handle(*args);
 
@@ -107,10 +107,10 @@
 {
 	smc_ret_values ffa_ret;
 	uint32_t mem_func = cactus_req_mem_send_get_mem_func(*args);
-	ffa_vm_id_t receiver = cactus_req_mem_send_get_receiver(*args);
+	ffa_id_t receiver = cactus_req_mem_send_get_receiver(*args);
 	ffa_memory_handle_t handle;
-	ffa_vm_id_t vm_id = ffa_dir_msg_dest(*args);
-	ffa_vm_id_t source = ffa_dir_msg_source(*args);
+	ffa_id_t vm_id = ffa_dir_msg_dest(*args);
+	ffa_id_t source = ffa_dir_msg_source(*args);
 
 	VERBOSE("%x requested to send memory to %x (func: %x)\n",
 		source, receiver, mem_func);
diff --git a/spm/cactus/cactus_tests/cactus_tests_smmuv3.c b/spm/cactus/cactus_tests/cactus_tests_smmuv3.c
new file mode 100644
index 0000000..fbf46c8
--- /dev/null
+++ b/spm/cactus/cactus_tests/cactus_tests_smmuv3.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include "cactus.h"
+#include "cactus_message_loop.h"
+#include <cactus_platform_def.h>
+#include "cactus_test_cmds.h"
+#include "cactus_tests.h"
+#include <debug.h>
+#include <ffa_helpers.h>
+#include <mmio.h>
+#include "smmuv3_test_engine.h"
+#include <sp_helpers.h>
+#include <spm_common.h>
+
+/* Source and target address for memcopy operation */
+#define MEMCPY_SOURCE_BASE	PLAT_CACTUS_MEMCPY_BASE
+#define MEMPCY_TOTAL_SIZE	(PLAT_CACTUS_MEMCPY_RANGE / 2)
+#define MEMCPY_TARGET_BASE	(MEMCPY_SOURCE_BASE + MEMPCY_TOTAL_SIZE)
+
+/* Miscellaneous */
+#define NO_SUBSTREAMID	(0xFFFFFFFFU)
+#define TRANSFER_SIZE	(MEMPCY_TOTAL_SIZE / FRAME_COUNT)
+#define LOOP_COUNT	(5000U)
+
+static bool run_smmuv3_test(void)
+{
+	uint64_t source_addr, cpy_range, target_addr;
+	uint64_t begin_addr, end_addr, dest_addr;
+	uint32_t status;
+	unsigned int i, f, attempts;
+
+	/*
+	 * The test engine's MEMCPY command copies data from the region in
+	 * range [begin, end_incl] to the region with base address as udata.
+	 * In this test, we configure the test engine to initiate memcpy from
+	 * scratch page located at MEMCPY_SOURCE_BASE to the page located at
+	 * address MEMCPY_TARGET_BASE
+	 */
+
+	VERBOSE("CACTUS: Running SMMUv3 test\n");
+
+	source_addr = MEMCPY_SOURCE_BASE;
+	cpy_range = MEMPCY_TOTAL_SIZE;
+	target_addr = MEMCPY_TARGET_BASE;
+	uint32_t streamID_list[] = { 0U, 1U };
+
+	uint64_t data[] = {
+		ULL(0xBAADFEEDCEEBDAAF),
+		ULL(0x0123456776543210)
+	};
+
+	/* Write pre-determined content to source pages */
+	for (i = 0U; i < (cpy_range / 8U); i++) {
+		mmio_write64_offset(source_addr, i * 8, data[i%2]);
+	}
+
+	/* Clean the data caches */
+	clean_dcache_range(source_addr, cpy_range);
+
+	/*
+	 * Make sure above load, store and cache maintenance instructions
+	 * complete before we start writing to TestEngine frame configuration
+	 * fields
+	 */
+	dsbsy();
+
+	for (f = 0U; f < FRAME_COUNT; f++) {
+		attempts = 0U;
+		begin_addr = source_addr + (TRANSFER_SIZE * f);
+		end_addr = begin_addr + TRANSFER_SIZE - 1U;
+		dest_addr = target_addr + (TRANSFER_SIZE * f);
+
+		/* Initiate DMA sequence */
+		mmio_write32_offset(PRIV_BASE_FRAME + F_IDX(f), PCTRL_OFF, 0);
+		mmio_write32_offset(PRIV_BASE_FRAME + F_IDX(f), DOWNSTREAM_PORT_OFF, 0);
+		mmio_write32_offset(PRIV_BASE_FRAME + F_IDX(f), STREAM_ID_OFF, streamID_list[f%2]);
+		mmio_write32_offset(PRIV_BASE_FRAME + F_IDX(f), SUBSTREAM_ID_OFF, NO_SUBSTREAMID);
+
+		mmio_write32_offset(USR_BASE_FRAME + F_IDX(f), UCTRL_OFF, 0);
+		mmio_write32_offset(USR_BASE_FRAME + F_IDX(f), SEED_OFF, 0);
+		mmio_write64_offset(USR_BASE_FRAME + F_IDX(f), BEGIN_OFF, begin_addr);
+		mmio_write64_offset(USR_BASE_FRAME + F_IDX(f), END_CTRL_OFF, end_addr);
+
+		/* Legal values for stride: 1 and any multiples of 8 */
+		mmio_write64_offset(USR_BASE_FRAME + F_IDX(f), STRIDE_OFF, 1);
+		mmio_write64_offset(USR_BASE_FRAME + F_IDX(f), UDATA_OFF, dest_addr);
+
+		mmio_write32_offset(USR_BASE_FRAME + F_IDX(f), CMD_OFF, ENGINE_MEMCPY);
+		VERBOSE("SMMUv3TestEngine: Waiting for MEMCPY completion for frame: %u\n", f);
+
+		/*
+		 * It is guaranteed that a read of "cmd" fields after writing to it will
+		 * immediately return ENGINE_FRAME_MISCONFIGURED if the command was
+		 * invalid.
+		 */
+		if (mmio_read32_offset(USR_BASE_FRAME + F_IDX(f), CMD_OFF) == ENGINE_MIS_CFG) {
+			ERROR("SMMUv3TestEngine: Misconfigured for frame: %u\n", f);
+			return false;
+		}
+
+		/* Wait for mem copy to be complete */
+		while (attempts++ < LOOP_COUNT) {
+			status = mmio_read32_offset(USR_BASE_FRAME + F_IDX(f), CMD_OFF);
+			if (status == ENGINE_HALTED) {
+				break;
+			} else if (status == ENGINE_ERROR) {
+				ERROR("SMMUv3: Test failed\n");
+				return false;
+			}
+
+			/*
+			 * TODO: Introduce a small delay here to make sure the
+			 * CPU memory accesses do not starve the interconnect
+			 * due to continuous polling.
+			 */
+		}
+
+		if (attempts == LOOP_COUNT) {
+			ERROR("SMMUv3: Test failed\n");
+			return false;
+		}
+
+		dsbsy();
+	}
+
+	/*
+	 * Invalidate cached entries to force the CPU to fetch the data from
+	 * Main memory
+	 */
+	inv_dcache_range(source_addr, cpy_range);
+	inv_dcache_range(target_addr, cpy_range);
+
+	/* Compare source and destination memory locations for data */
+	for (i = 0U; i < (cpy_range / 8U); i++) {
+		if (mmio_read_64(source_addr + 8 * i) != mmio_read_64(target_addr + 8 * i)) {
+			ERROR("SMMUv3: Mem copy failed: %llx\n", target_addr + 8 * i);
+			return false;
+		}
+	}
+
+	return true;
+}
+
+CACTUS_CMD_HANDLER(smmuv3_cmd, CACTUS_DMA_SMMUv3_CMD)
+{
+	smc_ret_values ffa_ret;
+	ffa_id_t vm_id = ffa_dir_msg_dest(*args);
+	ffa_id_t source = ffa_dir_msg_source(*args);
+
+	VERBOSE("Received request through direct message for DMA service\n");
+
+	/*
+	 * At present, the test cannot be run concurrently on multiple SPs as
+	 * there is only one SMMUv3TestEngine IP in the FVP model. Hence, run
+	 * the test only on the first SP.
+	 */
+	if (vm_id != SPM_VM_ID_FIRST) {
+		return cactus_error_resp(vm_id, source, 0);
+	}
+
+	if (run_smmuv3_test()) {
+		ffa_ret = cactus_success_resp(vm_id, source, 0);
+	} else {
+		ffa_ret = cactus_error_resp(vm_id, source, 0);
+	}
+
+	return ffa_ret;
+}
diff --git a/spm/cactus/cactus_tests/smmuv3_test_engine.h b/spm/cactus/cactus_tests/smmuv3_test_engine.h
new file mode 100644
index 0000000..32d86ac
--- /dev/null
+++ b/spm/cactus/cactus_tests/smmuv3_test_engine.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* The test engine supports numerous frames but we only use a few */
+#define FRAME_COUNT	(2U)
+#define FRAME_SIZE	(0x80U) /* 128 bytes */
+#define F_IDX(n)	(n * FRAME_SIZE)
+
+/* Commands supported by SMMUv3TestEngine built into the AEM */
+#define ENGINE_NO_FRAME	(0U)
+#define ENGINE_HALTED	(1U)
+
+/*
+ * ENGINE_MEMCPY: Read and Write transactions
+ * ENGINE_RAND48: Only Write transactions: Source address not required
+ * ENGINE_SUM64: Only read transactions: Target address not required
+ */
+#define ENGINE_MEMCPY	(2U)
+#define ENGINE_RAND48	(3U)
+#define ENGINE_SUM64	(4U)
+#define ENGINE_ERROR	(0xFFFFFFFFU)
+#define ENGINE_MIS_CFG	(ENGINE_ERROR - 1)
+
+/*
+ * Refer to:
+ * https://developer.arm.com/documentation/100964/1111-00/Trace-components/SMMUv3TestEngine---trace
+ */
+
+/* Offset of various control fields belonging to User Frame */
+#define CMD_OFF		(0x0U)
+#define UCTRL_OFF	(0x4U)
+#define SEED_OFF	(0x24U)
+#define BEGIN_OFF	(0x28U)
+#define END_CTRL_OFF	(0x30U)
+#define STRIDE_OFF	(0x38U)
+#define UDATA_OFF	(0x40U)
+
+/* Offset of various control fields belonging to PRIV Frame */
+#define PCTRL_OFF		(0x0U)
+#define DOWNSTREAM_PORT_OFF	(0x4U)
+#define STREAM_ID_OFF		(0x8U)
+#define SUBSTREAM_ID_OFF	(0xCU)
diff --git a/spm/cactus/plat/arm/fvp/fdts/cactus.dts b/spm/cactus/plat/arm/fvp/fdts/cactus.dts
index eb569f7..1c28fde 100644
--- a/spm/cactus/plat/arm/fvp/fdts/cactus.dts
+++ b/spm/cactus/plat/arm/fvp/fdts/cactus.dts
@@ -62,6 +62,24 @@
 			pages-count = <4>;
 			attributes = <0x7>; /* read-write-execute */
 		};
+
+		/*
+		 * Scratch memory used for the purpose of testing SMMUv3 driver
+		 * through Cactus SP
+		 */
+		smmuv3-memcpy-src {
+			description = "smmuv3-memcpy-source";
+			pages-count = <4>;
+			base-address = <0x00000000 0x7400000>;
+			attributes = <0x3>; /* read-write */
+		};
+
+		smmuv3-memcpy-dst {
+			description = "smmuv3-memcpy-destination";
+			pages-count = <4>;
+			base-address = <0x00000000 0x7404000>;
+			attributes = <0x3>; /* read-write */
+		};
 	};
 
 	device-regions {
@@ -73,6 +91,20 @@
 			attributes = <0x3>; /* read-write */
 		};
 
+		smmuv3-testengine {
+			/*
+			 * SMMUv3TestEngine is a DMA IP modeled in the
+			 * Base-RevC FVP Model.
+			 * User Frame: 0x2bfe0000
+			 * Privileged Frame: 0x2bff0000
+			 */
+			base-address = <0x00000000 0x2bfe0000>;
+			pages-count = <32>; /* Two 64KB pages */
+			attributes = <0x3>; /* read-write */
+			smmu-id = <0>;
+			stream-ids = <0x0 0x1>;
+		};
+
 		test-reg {
 			/* Dummy Values */
 			base-address = <0x00000000 0x22000000>;
diff --git a/spm/cactus/plat/arm/fvp/include/cactus_platform_def.h b/spm/cactus/plat/arm/fvp/include/cactus_platform_def.h
index b4c57ef..8940c83 100644
--- a/spm/cactus/plat/arm/fvp/include/cactus_platform_def.h
+++ b/spm/cactus/plat/arm/fvp/include/cactus_platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -18,8 +18,16 @@
 #define PLAT_CACTUS_RX_BASE		ULL(0x7300000)
 #define PLAT_CACTUS_CORE_COUNT		(8U)
 
+/* Scratch memory used for SMMUv3 driver testing purposes in Cactus SP */
+#define PLAT_CACTUS_MEMCPY_BASE		ULL(0x7400000)
+#define PLAT_CACTUS_MEMCPY_RANGE	ULL(0x8000)
+
 #define CACTUS_PRIMARY_EC_COUNT		(8U)
 #define CACTUS_SECONDARY_EC_COUNT	(8U)
 #define CACTUS_TERTIARY_EC_COUNT	(1U)
 
+/* Base address of user and PRIV frames in SMMUv3TestEngine */
+#define USR_BASE_FRAME			ULL(0x2BFE0000)
+#define PRIV_BASE_FRAME			ULL(0x2BFF0000)
+
 #endif /* CACTUS_PLATFORM_DEF_H */
diff --git a/tftf/tests/runtime_services/secure_service/ffa_helpers.c b/tftf/tests/runtime_services/secure_service/ffa_helpers.c
index 8e7b58c..4c69eb1 100644
--- a/tftf/tests/runtime_services/secure_service/ffa_helpers.c
+++ b/tftf/tests/runtime_services/secure_service/ffa_helpers.c
@@ -55,8 +55,8 @@
  *     -BUSY: Message target is busy
  *     -ABORTED: Message target ran into an unexpected error and has aborted
  */
-smc_ret_values ffa_msg_send_direct_req64(ffa_vm_id_t source_id,
-					 ffa_vm_id_t dest_id, uint64_t arg0,
+smc_ret_values ffa_msg_send_direct_req64(ffa_id_t source_id,
+					 ffa_id_t dest_id, uint64_t arg0,
 					 uint64_t arg1, uint64_t arg2,
 					 uint64_t arg3, uint64_t arg4)
 {
@@ -74,8 +74,8 @@
 	return tftf_smc(&args);
 }
 
-smc_ret_values ffa_msg_send_direct_req32(ffa_vm_id_t source_id,
-					 ffa_vm_id_t dest_id, uint32_t arg0,
+smc_ret_values ffa_msg_send_direct_req32(ffa_id_t source_id,
+					 ffa_id_t dest_id, uint32_t arg0,
 					 uint32_t arg1, uint32_t arg2,
 					 uint32_t arg3, uint32_t arg4)
 {
@@ -93,8 +93,8 @@
 	return tftf_smc(&args);
 }
 
-smc_ret_values ffa_msg_send_direct_resp64(ffa_vm_id_t source_id,
-					  ffa_vm_id_t dest_id, uint64_t arg0,
+smc_ret_values ffa_msg_send_direct_resp64(ffa_id_t source_id,
+					  ffa_id_t dest_id, uint64_t arg0,
 					  uint64_t arg1, uint64_t arg2,
 					  uint64_t arg3, uint64_t arg4)
 {
@@ -112,8 +112,8 @@
 	return tftf_smc(&args);
 }
 
-smc_ret_values ffa_msg_send_direct_resp32(ffa_vm_id_t source_id,
-					  ffa_vm_id_t dest_id, uint32_t arg0,
+smc_ret_values ffa_msg_send_direct_resp32(ffa_id_t source_id,
+					  ffa_id_t dest_id, uint32_t arg0,
 					  uint32_t arg1, uint32_t arg2,
 					  uint32_t arg3, uint32_t arg4)
 {
@@ -137,9 +137,9 @@
  * composite memory region offset.
  */
 static void ffa_memory_region_init_header(
-	struct ffa_memory_region *memory_region, ffa_vm_id_t sender,
+	struct ffa_memory_region *memory_region, ffa_id_t sender,
 	ffa_memory_attributes_t attributes, ffa_memory_region_flags_t flags,
-	ffa_memory_handle_t handle, uint32_t tag, ffa_vm_id_t receiver,
+	ffa_memory_handle_t handle, uint32_t tag, ffa_id_t receiver,
 	ffa_memory_access_permissions_t permissions)
 {
 	memory_region->sender = sender;
@@ -168,7 +168,7 @@
  */
 uint32_t ffa_memory_region_init(
 	struct ffa_memory_region *memory_region, size_t memory_region_max_size,
-	ffa_vm_id_t sender, ffa_vm_id_t receiver,
+	ffa_id_t sender, ffa_id_t receiver,
 	const struct ffa_memory_region_constituent constituents[],
 	uint32_t constituent_count, uint32_t tag,
 	ffa_memory_region_flags_t flags, enum ffa_data_access data_access,
@@ -259,7 +259,7 @@
  */
 uint32_t ffa_memory_retrieve_request_init(
 	struct ffa_memory_region *memory_region, ffa_memory_handle_t handle,
-	ffa_vm_id_t sender, ffa_vm_id_t receiver, uint32_t tag,
+	ffa_id_t sender, ffa_id_t receiver, uint32_t tag,
 	ffa_memory_region_flags_t flags, enum ffa_data_access data_access,
 	enum ffa_instruction_access instruction_access,
 	enum ffa_memory_type type, enum ffa_memory_cacheability cacheability,
@@ -291,7 +291,6 @@
 	       memory_region->receiver_count * sizeof(struct ffa_memory_access);
 }
 
-
 /*
  * FFA Version ABI helper.
  * Version fields:
@@ -317,6 +316,15 @@
 	return tftf_smc(&args);
 }
 
+smc_ret_values ffa_spm_id_get(void)
+{
+	smc_args args = {
+		.fid = FFA_SPM_ID_GET
+	};
+
+	return tftf_smc(&args);
+}
+
 smc_ret_values ffa_msg_wait(void)
 {
 	smc_args args = {
diff --git a/tftf/tests/runtime_services/secure_service/spm_common.c b/tftf/tests/runtime_services/secure_service/spm_common.c
index 12b70a9..e2d3392 100644
--- a/tftf/tests/runtime_services/secure_service/spm_common.c
+++ b/tftf/tests/runtime_services/secure_service/spm_common.c
@@ -6,6 +6,7 @@
 
 #include <debug.h>
 #include <ffa_endpoints.h>
+#include <ffa_svc.h>
 #include <spm_common.h>
 #include <xlat_tables_v2.h>
 
@@ -19,7 +20,7 @@
 bool is_ffa_call_error(smc_ret_values ret)
 {
 	if (ffa_func_id(ret) == FFA_ERROR) {
-		ERROR("FF-A call returned error (%x): %d\n",
+		VERBOSE("FF-A call returned error (%x): %d\n",
 		      ffa_func_id(ret), ffa_error_code(ret));
 		return true;
 	}
@@ -38,7 +39,7 @@
 		return true;
 	}
 
-	ERROR("%x is not FF-A response.\n", ffa_func_id(ret));
+	VERBOSE("%x is not FF-A response.\n", ffa_func_id(ret));
 	/* To log error in case it is FFA_ERROR*/
 	is_ffa_call_error(ret);
 
@@ -54,7 +55,7 @@
 		return true;
 	}
 
-	ERROR("Expecting %x, FF-A return was %x\n", func_id, ffa_func_id(ret));
+	VERBOSE("Expecting %x, FF-A return was %x\n", func_id, ffa_func_id(ret));
 
 	return false;
 }
@@ -166,6 +167,8 @@
 	{"FFA_RXTX_UNMAP_32 check", FFA_RXTX_UNMAP, FFA_ERROR},
 	{"FFA_PARTITION_INFO_GET_32 check", FFA_PARTITION_INFO_GET, FFA_SUCCESS_SMC32},
 	{"FFA_ID_GET_32 check", FFA_ID_GET, FFA_SUCCESS_SMC32},
+	{"FFA_SPM_ID_GET_32 check", FFA_SPM_ID_GET, FFA_SUCCESS_SMC32,
+		MAKE_FFA_VERSION(1, 1)},
 	{"FFA_MSG_POLL_32 check", FFA_MSG_POLL, FFA_SUCCESS_SMC32},
 	{"FFA_MSG_WAIT_32 check", FFA_MSG_WAIT, FFA_SUCCESS_SMC32},
 	{"FFA_YIELD_32 check", FFA_MSG_YIELD, FFA_SUCCESS_SMC32},
@@ -199,7 +202,7 @@
 
 bool memory_retrieve(struct mailbox_buffers *mb,
 		     struct ffa_memory_region **retrieved, uint64_t handle,
-		     ffa_vm_id_t sender, ffa_vm_id_t receiver,
+		     ffa_id_t sender, ffa_id_t receiver,
 		     uint32_t mem_func)
 {
 	smc_ret_values ret;
@@ -269,7 +272,7 @@
 }
 
 bool memory_relinquish(struct ffa_mem_relinquish *m, uint64_t handle,
-		       ffa_vm_id_t id)
+		       ffa_id_t id)
 {
 	smc_ret_values ret;
 
@@ -297,7 +300,7 @@
 	uint32_t fragment_length, uint32_t total_length)
 {
 	smc_ret_values ret;
-	ffa_vm_id_t receiver =
+	ffa_id_t receiver =
 		memory_region->receivers[0].receiver_permissions.receiver;
 
 	if (fragment_length != total_length) {
@@ -336,7 +339,7 @@
  */
 ffa_memory_handle_t memory_init_and_send(
 	struct ffa_memory_region *memory_region, size_t memory_region_max_size,
-	ffa_vm_id_t sender, ffa_vm_id_t receiver,
+	ffa_id_t sender, ffa_id_t receiver,
 	const struct ffa_memory_region_constituent *constituents,
 	uint32_t constituents_count, uint32_t mem_func)
 {
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c b/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c
index 0a722e4..1b9abe9 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c
@@ -27,8 +27,8 @@
 
 static event_t cpu_booted[PLATFORM_CORE_COUNT];
 
-static test_result_t send_cactus_echo_cmd(ffa_vm_id_t sender,
-					  ffa_vm_id_t dest,
+static test_result_t send_cactus_echo_cmd(ffa_id_t sender,
+					  ffa_id_t dest,
 					  uint64_t value)
 {
 	smc_ret_values ret;
@@ -92,9 +92,9 @@
  * otherwise.
  * For the CACTUS_SUCCESS response, the test returns TEST_RESULT_SUCCESS.
  */
-static test_result_t send_cactus_req_echo_cmd(ffa_vm_id_t sender,
-					      ffa_vm_id_t dest,
-					      ffa_vm_id_t echo_dest,
+static test_result_t send_cactus_req_echo_cmd(ffa_id_t sender,
+					      ffa_id_t dest,
+					      ffa_id_t echo_dest,
 					      uint64_t value)
 {
 	smc_ret_values ret;
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_features.c b/tftf/tests/runtime_services/secure_service/test_ffa_features.c
deleted file mode 100644
index e4cd845..0000000
--- a/tftf/tests/runtime_services/secure_service/test_ffa_features.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <spm_common.h>
-#include <test_helpers.h>
-#include <tftf_lib.h>
-
-test_result_t test_ffa_features(void)
-{
-	SKIP_TEST_IF_FFA_VERSION_LESS_THAN(1, 0);
-
-	/* Check if SPMC is OP-TEE at S-EL1 */
-	if (check_spmc_execution_level()) {
-		/* FFA_FEATURES is not yet supported in OP-TEE */
-		return TEST_RESULT_SUCCESS;
-	}
-
-	smc_ret_values ffa_ret;
-	const struct ffa_features_test *ffa_feature_test_target;
-	unsigned int i, test_target_size =
-		get_ffa_feature_test_target(&ffa_feature_test_target);
-
-	for (i = 0U; i < test_target_size; i++) {
-		ffa_ret = ffa_features(ffa_feature_test_target[i].feature);
-		if (ffa_func_id(ffa_ret) != ffa_feature_test_target[i].expected_ret) {
-			tftf_testcase_printf("%s returned %x, expected %x\n",
-					     ffa_feature_test_target[i].test_name,
-					     ffa_func_id(ffa_ret),
-					     ffa_feature_test_target[i].expected_ret);
-			return TEST_RESULT_FAIL;
-		}
-		if ((ffa_feature_test_target[i].expected_ret == FFA_ERROR) &&
-		    (ffa_error_code(ffa_ret) != FFA_ERROR_NOT_SUPPORTED)) {
-			tftf_testcase_printf("%s failed for the wrong reason: "
-					     "returned %x, expected %x\n",
-					     ffa_feature_test_target[i].test_name,
-					     ffa_error_code(ffa_ret),
-					     FFA_ERROR_NOT_SUPPORTED);
-			return TEST_RESULT_FAIL;
-		}
-	}
-
-	return TEST_RESULT_SUCCESS;
-}
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c b/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c
index f126c57..46a7349 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_memory_sharing.c
@@ -130,8 +130,8 @@
  * Cactus SP should reply to TFTF on whether the test succeeded or not.
  */
 static test_result_t test_req_mem_send_sp_to_sp(uint32_t mem_func,
-						ffa_vm_id_t sender_sp,
-						ffa_vm_id_t receiver_sp)
+						ffa_id_t sender_sp,
+						ffa_id_t receiver_sp)
 {
 	smc_ret_values ret;
 
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_rxtx_map.c b/tftf/tests/runtime_services/secure_service/test_ffa_rxtx_map.c
deleted file mode 100644
index 1b47c5f..0000000
--- a/tftf/tests/runtime_services/secure_service/test_ffa_rxtx_map.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <debug.h>
-
-#include <test_helpers.h>
-#include <xlat_tables_defs.h>
-
-static struct mailbox_buffers mb;
-
-static test_result_t test_ffa_rxtx_map(uint32_t expected_return)
-{
-	smc_ret_values ret;
-
-	/**********************************************************************
-	 * Verify that FFA is there and that it has the correct version.
-	 **********************************************************************/
-	SKIP_TEST_IF_FFA_VERSION_LESS_THAN(1, 0);
-
-	/**********************************************************************
-	 * If OP-TEE is SPMC skip this test.
-	 **********************************************************************/
-	if (check_spmc_execution_level()) {
-		VERBOSE("OP-TEE as SPMC at S-EL1. Skipping test!\n");
-		return TEST_RESULT_SKIPPED;
-	}
-
-	/*
-	 * Declare RXTX buffers, assign them to the mailbox and call
-	 * FFA_RXTX_MAP.
-	 */
-	CONFIGURE_AND_MAP_MAILBOX(mb, PAGE_SIZE, ret);
-	if (ffa_func_id(ret) != expected_return) {
-		ERROR("Failed to map RXTX buffers %x!\n", ffa_error_code(ret));
-		return TEST_RESULT_FAIL;
-	}
-
-	return TEST_RESULT_SUCCESS;
-}
-
-/**
- * Test mapping RXTX buffers from NWd.
- * This test also sets the Mailbox for other SPM related tests that need to use
- * RXTX buffers.
- */
-test_result_t test_ffa_rxtx_map_success(void)
-{
-	test_result_t ret = test_ffa_rxtx_map(FFA_SUCCESS_SMC32);
-
-	if (ret == TEST_RESULT_SUCCESS) {
-		INFO("Set RXTX Mailbox for remaining spm tests!\n");
-		set_tftf_mailbox(&mb);
-	}
-	return ret;
-}
-
-/**
- * Test to verify that 2nd call to FFA_RXTX_MAP should fail.
- */
-test_result_t test_ffa_rxtx_map_fail(void)
-{
-	INFO("This test expects error log.\n");
-	return test_ffa_rxtx_map(FFA_ERROR);
-}
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_setup_and_discovery.c b/tftf/tests/runtime_services/secure_service/test_ffa_setup_and_discovery.c
new file mode 100644
index 0000000..f8a5ace
--- /dev/null
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_setup_and_discovery.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+
+#include <ffa_svc.h>
+#include <ffa_helpers.h>
+#include <spm_common.h>
+#include <test_helpers.h>
+#include <tftf_lib.h>
+#include <xlat_tables_defs.h>
+
+static bool should_skip_version_test;
+
+static struct mailbox_buffers mb;
+
+/*
+ * Using FFA version expected for SPM.
+ */
+#define SPM_VERSION MAKE_FFA_VERSION(FFA_VERSION_MAJOR, FFA_VERSION_MINOR)
+
+/******************************************************************************
+ * FF-A Features ABI Tests
+ ******************************************************************************/
+
+test_result_t test_ffa_features(void)
+{
+	SKIP_TEST_IF_FFA_VERSION_LESS_THAN(1, 0);
+
+	/* Check if SPMC is OP-TEE at S-EL1 */
+	if (check_spmc_execution_level()) {
+		/* FFA_FEATURES is not yet supported in OP-TEE */
+		return TEST_RESULT_SUCCESS;
+	}
+
+	smc_ret_values ffa_ret;
+	unsigned int expected_ret;
+	const struct ffa_features_test *ffa_feature_test_target;
+	unsigned int i, test_target_size =
+		get_ffa_feature_test_target(&ffa_feature_test_target);
+	struct ffa_features_test test_target;
+
+	for (i = 0U; i < test_target_size; i++) {
+		test_target = ffa_feature_test_target[i];
+		ffa_ret = ffa_features(test_target.feature);
+		expected_ret = FFA_VERSION_COMPILED
+			>= test_target.version_added ?
+			test_target.expected_ret : FFA_ERROR;
+		if (ffa_func_id(ffa_ret) != expected_ret) {
+			tftf_testcase_printf("%s returned %x, expected %x\n",
+					test_target.test_name,
+					ffa_func_id(ffa_ret),
+					expected_ret);
+			return TEST_RESULT_FAIL;
+		}
+		if ((expected_ret == FFA_ERROR) &&
+				(ffa_error_code(ffa_ret) != FFA_ERROR_NOT_SUPPORTED)) {
+			tftf_testcase_printf("%s failed for the wrong reason: "
+					"returned %x, expected %x\n",
+					test_target.test_name,
+					ffa_error_code(ffa_ret),
+					FFA_ERROR_NOT_SUPPORTED);
+			return TEST_RESULT_FAIL;
+		}
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
+
+/******************************************************************************
+ * FF-A Version ABI Tests
+ ******************************************************************************/
+
+/*
+ * Calls FFA Version ABI, and checks if the result as expected.
+ */
+static test_result_t test_ffa_version(uint32_t input_version,
+					uint32_t expected_return)
+{
+	if (should_skip_version_test) {
+		return TEST_RESULT_SKIPPED;
+	}
+
+	smc_ret_values ret_values = ffa_version(input_version);
+
+	uint32_t spm_version = (uint32_t)(0xFFFFFFFF & ret_values.ret0);
+
+	if (spm_version == expected_return) {
+		return TEST_RESULT_SUCCESS;
+	}
+
+	tftf_testcase_printf("Input Version: 0x%x\n"
+			     "Return: 0x%x\nExpected: 0x%x\n",
+			      input_version, spm_version, expected_return);
+
+	return TEST_RESULT_FAIL;
+}
+
+/*
+ * @Test_Aim@ Validate what happens when using same version as SPM.
+ */
+test_result_t test_ffa_version_equal(void)
+{
+	/*
+	 * FFA_VERSION interface is used to check that SPM functionality is
+	 * supported. On FFA_VERSION invocation from TFTF, the SPMD returns
+	 * either NOT_SUPPORTED or the SPMC version value provided in the SPMC
+	 * manifest. The variable "should_skip_test" is set to true when the
+	 * SPMD returns NOT_SUPPORTED or a mismatched version, which means that
+	 * a TFTF physical FF-A endpoint version (SPM_VERSION) does not match
+	 * the SPMC's physical FF-A endpoint version. This prevents running the
+	 * subsequent FF-A version tests (and break the test flow), as they're
+	 * not relevant when the SPMD is not present within BL31
+	 * (FFA_VERSION returns NOT_SUPPORTED).
+	 */
+	test_result_t ret = test_ffa_version(SPM_VERSION, SPM_VERSION);
+
+	if (ret != TEST_RESULT_SUCCESS) {
+		should_skip_version_test = true;
+		ret = TEST_RESULT_SKIPPED;
+	}
+	return ret;
+}
+
+/*
+ * @Test_Aim@ Validate what happens when setting bit 31 in
+ * 'input_version'. As per spec, FFA version is 31 bits long.
+ * Bit 31 set is an invalid input.
+ */
+test_result_t test_ffa_version_bit31(void)
+{
+	return test_ffa_version(FFA_VERSION_BIT31_MASK | SPM_VERSION,
+				FFA_ERROR_NOT_SUPPORTED);
+}
+
+/*
+ * @Test_Aim@ Validate what happens for bigger version than SPM's.
+ */
+test_result_t test_ffa_version_bigger(void)
+{
+	return test_ffa_version(MAKE_FFA_VERSION(FFA_VERSION_MAJOR + 1, 0),
+				SPM_VERSION);
+}
+
+/*
+ * @Test_Aim@ Validate what happens for smaller version than SPM's.
+ */
+test_result_t test_ffa_version_smaller(void)
+{
+	return test_ffa_version(MAKE_FFA_VERSION(0, 9), SPM_VERSION);
+}
+
+/******************************************************************************
+ * FF-A RXTX ABI Tests
+ ******************************************************************************/
+
+static test_result_t test_ffa_rxtx_map(uint32_t expected_return)
+{
+	smc_ret_values ret;
+
+	/**********************************************************************
+	 * Verify that FFA is there and that it has the correct version.
+	 **********************************************************************/
+	SKIP_TEST_IF_FFA_VERSION_LESS_THAN(1, 0);
+
+	/**********************************************************************
+	 * If OP-TEE is SPMC skip this test.
+	 **********************************************************************/
+	if (check_spmc_execution_level()) {
+		VERBOSE("OP-TEE as SPMC at S-EL1. Skipping test!\n");
+		return TEST_RESULT_SKIPPED;
+	}
+
+	/*
+	 * Declare RXTX buffers, assign them to the mailbox and call
+	 * FFA_RXTX_MAP.
+	 */
+	CONFIGURE_AND_MAP_MAILBOX(mb, PAGE_SIZE, ret);
+	if (ffa_func_id(ret) != expected_return) {
+		ERROR("Failed to map RXTX buffers %x!\n", ffa_error_code(ret));
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
+
+/**
+ * Test mapping RXTX buffers from NWd.
+ * This test also sets the Mailbox for other SPM related tests that need to use
+ * RXTX buffers.
+ */
+test_result_t test_ffa_rxtx_map_success(void)
+{
+	test_result_t ret = test_ffa_rxtx_map(FFA_SUCCESS_SMC32);
+
+	if (ret == TEST_RESULT_SUCCESS) {
+		INFO("Set RXTX Mailbox for remaining spm tests!\n");
+		set_tftf_mailbox(&mb);
+	}
+	return ret;
+}
+
+/**
+ * Test to verify that 2nd call to FFA_RXTX_MAP should fail.
+ */
+test_result_t test_ffa_rxtx_map_fail(void)
+{
+	INFO("This test expects error log.\n");
+	return test_ffa_rxtx_map(FFA_ERROR);
+}
+
+/******************************************************************************
+ * FF-A SPM_ID_GET ABI Tests
+ ******************************************************************************/
+
+test_result_t test_ffa_spm_id_get(void)
+{
+	SKIP_TEST_IF_FFA_VERSION_LESS_THAN(1, 1);
+
+	smc_ret_values ffa_ret = ffa_spm_id_get();
+
+	if (is_ffa_call_error(ffa_ret)) {
+		ERROR("FFA_SPM_ID_GET call failed! Error code: 0x%x\n",
+			ffa_error_code(ffa_ret));
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Check the SPMC value given in the fvp_spmc_manifest is returned */
+	ffa_id_t spm_id = ffa_endpoint_id(ffa_ret);
+
+	if (spm_id != SPMC_ID) {
+		ERROR("Expected SPMC_ID of 0x%x\n received: 0x%x\n",
+			SPMC_ID, spm_id);
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_version.c b/tftf/tests/runtime_services/secure_service/test_ffa_version.c
deleted file mode 100644
index 41eca5a..0000000
--- a/tftf/tests/runtime_services/secure_service/test_ffa_version.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <ffa_svc.h>
-#include <test_helpers.h>
-#include <tftf_lib.h>
-
-/*
- * Using FFA version expected for SPM.
- */
-#define SPM_VERSION MAKE_FFA_VERSION(FFA_VERSION_MAJOR, FFA_VERSION_MINOR)
-
-static bool should_skip_test;
-
-/*
- * Calls FFA Version ABI, and checks if the result as expected.
- */
-static test_result_t test_ffa_version(uint32_t input_version, uint32_t expected_return)
-{
-	if (should_skip_test) {
-		return TEST_RESULT_SKIPPED;
-	}
-
-	smc_ret_values ret_values = ffa_version(input_version);
-
-	uint32_t spm_version = (uint32_t)(0xFFFFFFFF & ret_values.ret0);
-
-	if (spm_version == expected_return) {
-		return TEST_RESULT_SUCCESS;
-	}
-
-	tftf_testcase_printf("Input Version: 0x%x\nReturn: 0x%x\nExpected: 0x%x\n",
-			      input_version, spm_version, expected_return);
-
-	return TEST_RESULT_FAIL;
-}
-
-/*
- * @Test_Aim@ Validate what happens when using same version as SPM.
- */
-test_result_t test_ffa_version_equal(void)
-{
-	/*
-	 * FFA_VERSION interface is used to check that SPM functionality is supported.
-	 * On FFA_VERSION invocation from TFTF, the SPMD returns either NOT_SUPPORTED or
-	 * the SPMC version value provided in the SPMC manifest. The variable "should_skip_test"
-	 * is set to true when the SPMD returns NOT_SUPPORTED or a mismatched version, which
-	 * means that a TFTF physical FF-A endpoint version (SPM_VERSION) does not match the
-	 * SPMC's physical FF-A endpoint version. This prevents running the subsequent FF-A
-	 * version tests (and break the test flow), as they're not relevant when the SPMD is
-	 * not present within BL31 (FFA_VERSION returns NOT_SUPPORTED).
-	 */
-	test_result_t ret = test_ffa_version(SPM_VERSION, SPM_VERSION);
-	if (ret != TEST_RESULT_SUCCESS) {
-		should_skip_test = true;
-		ret = TEST_RESULT_SKIPPED;
-	}
-	return ret;
-}
-
-/*
- * @Test_Aim@ Validate what happens when setting bit 31 in
- * 'input_version'. As per spec, FFA version is 31 bits long.
- * Bit 31 set is an invalid input.
- */
-test_result_t test_ffa_version_bit31(void)
-{
-	return test_ffa_version(FFA_VERSION_BIT31_MASK | SPM_VERSION, FFA_ERROR_NOT_SUPPORTED);
-}
-
-/*
- * @Test_Aim@ Validate what happens for bigger version than SPM's.
- */
-test_result_t test_ffa_version_bigger(void)
-{
-	return test_ffa_version(MAKE_FFA_VERSION(FFA_VERSION_MAJOR + 1, 0), SPM_VERSION);
-}
-
-/*
- * @Test_Aim@ Validate what happens for smaller version than SPM's.
- */
-test_result_t test_ffa_version_smaller(void)
-{
-	return test_ffa_version(MAKE_FFA_VERSION(0, 9), SPM_VERSION);
-}
diff --git a/tftf/tests/runtime_services/secure_service/test_spm_smmu.c b/tftf/tests/runtime_services/secure_service/test_spm_smmu.c
new file mode 100644
index 0000000..b041a97
--- /dev/null
+++ b/tftf/tests/runtime_services/secure_service/test_spm_smmu.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <cactus_test_cmds.h>
+#include <debug.h>
+#include <ffa_endpoints.h>
+#include <smccc.h>
+#include <test_helpers.h>
+
+static const struct ffa_uuid expected_sp_uuids[] = { {PRIMARY_UUID} };
+
+/**************************************************************************
+ * Send a command to SP1 initiate DMA service with the help of a peripheral
+ * device upstream of an SMMUv3 IP
+ **************************************************************************/
+test_result_t test_smmu_spm(void)
+{
+	smc_ret_values ret;
+
+	/**********************************************************************
+	 * Check SPMC has ffa_version and expected FFA endpoints are deployed.
+	 **********************************************************************/
+	CHECK_SPMC_TESTING_SETUP(1, 0, expected_sp_uuids);
+
+	VERBOSE("Sending command to SP %x for initiating DMA transfer\n",
+			SP_ID(1));
+	ret = cactus_send_dma_cmd(HYP_ID, SP_ID(1));
+
+	if (cactus_get_response(ret) != CACTUS_SUCCESS) {
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
+
diff --git a/tftf/tests/tests-spm.mk b/tftf/tests/tests-spm.mk
index 9364052..dc99337 100644
--- a/tftf/tests/tests-spm.mk
+++ b/tftf/tests/tests-spm.mk
@@ -9,10 +9,9 @@
 		ffa_helpers.c						\
 		spm_common.c						\
 		test_ffa_direct_messaging.c				\
-		test_ffa_features.c					\
 		test_ffa_interrupts.c					\
 		test_ffa_memory_sharing.c				\
-		test_ffa_rxtx_map.c					\
-		test_ffa_version.c					\
+		test_ffa_setup_and_discovery.c				\
 		test_spm_cpu_features.c					\
+		test_spm_smmu.c						\
 	)
diff --git a/tftf/tests/tests-spm.xml b/tftf/tests/tests-spm.xml
index 01ebcea..cafbc46 100644
--- a/tftf/tests/tests-spm.xml
+++ b/tftf/tests/tests-spm.xml
@@ -7,27 +7,27 @@
 -->
 
 <testsuites>
+  <testsuite name="FF-A Setup and Discovery"
+             description="Test FF-A Setup and Discovery interfaces" >
+     <testcase name="Test FFA_FEATURES"
+               function="test_ffa_features" />
 
-  <testsuite name="FF-A Version"
-             description="Test FF-A Version ABI" >
+     <testcase name="Same FFA version as SPM"
+               function="test_ffa_version_equal" />
+     <testcase name="Setting bit 31 in input version"
+               function="test_ffa_version_bit31"/>
+     <testcase name="Bigger FFA version than SPM"
+               function="test_ffa_version_bigger" />
+     <testcase name="Smaller FFA version than SPM"
+               function="test_ffa_version_smaller" />
 
-    <testcase name="Same FFA version as SPM"
-              function="test_ffa_version_equal" />
-    <testcase name="Setting bit 31 in input version"
-              function="test_ffa_version_bit31"/>
-    <testcase name="Bigger FFA version than SPM"
-              function="test_ffa_version_bigger" />
-    <testcase name="Smaller FFA version than SPM"
-              function="test_ffa_version_smaller" />
-
-  </testsuite>
-
-  <testsuite name="FF-A RXTX Mapping"
-             description="Test to FF-A RXTX mapping ABI" >
      <testcase name="FF-A RXTX Map API success"
                function="test_ffa_rxtx_map_success" />
      <testcase name="FF-A RXTX Map API consecutive"
                function="test_ffa_rxtx_map_fail" />
+
+     <testcase name="Test FFA_SPM_ID_GET"
+               function="test_ffa_spm_id_get" />
   </testsuite>
 
   <testsuite name="FF-A Direct messaging"
@@ -66,12 +66,6 @@
                function="test_req_mem_donate_sp_to_sp" />
   </testsuite>
 
-  <testsuite name="FF-A features"
-             description="Test FFA_FEATURES ABI" >
-     <testcase name="Test FFA_FEATURES"
-               function="test_ffa_features" />
-  </testsuite>
-
   <testsuite name="SIMD,SVE Registers context"
              description="Validate context switch between NWd and SWd" >
      <testcase name="Check that SIMD registers context is preserved"
@@ -84,4 +78,10 @@
                function="test_ffa_ns_interrupt" />
   </testsuite>
 
+  <testsuite name="SMMUv3 tests"
+             description="Initiate stage2 translation for streams from upstream peripherals" >
+     <testcase name="Check DMA command by SMMUv3TestEngine completes"
+               function="test_smmu_spm" />
+  </testsuite>
+
 </testsuites>