Merge "test(spm): test FFA_FEATURES with NPI, SRI, MEI"
diff --git a/include/runtime_services/cactus_test_cmds.h b/include/runtime_services/cactus_test_cmds.h
index 3938c2f..0630753 100644
--- a/include/runtime_services/cactus_test_cmds.h
+++ b/include/runtime_services/cactus_test_cmds.h
@@ -654,4 +654,34 @@
 	return (uint64_t)ret.arg4;
 }
 
+/**
+ * Request SP to send indirect message to FF-A endpoint.
+ *
+ * Command ID is string: MSGREQ.
+ */
+#define CACTUS_REQ_MSG_SEND_CMD U(0x4d5347524551a)
+
+static inline struct ffa_value cactus_req_ind_msg_send_cmd(
+	ffa_id_t source, ffa_id_t dest, ffa_id_t receiver,
+	ffa_id_t sender, uint32_t flags)
+{
+	return cactus_send_cmd(source, dest, CACTUS_REQ_MSG_SEND_CMD,
+			       flags, receiver, sender, 0);
+}
+
+static inline ffa_id_t cactus_msg_send_receiver(struct ffa_value ret)
+{
+	return (ffa_id_t)ret.arg5;
+}
+
+static inline ffa_id_t cactus_msg_send_sender(struct ffa_value ret)
+{
+	return (ffa_id_t)ret.arg6;
+}
+
+static inline uint64_t cactus_msg_send_flags(struct ffa_value ret)
+{
+	return (uint64_t)ret.arg4;
+}
+
 #endif
diff --git a/include/runtime_services/ffa_helpers.h b/include/runtime_services/ffa_helpers.h
index 3ae43d2..08befd0 100644
--- a/include/runtime_services/ffa_helpers.h
+++ b/include/runtime_services/ffa_helpers.h
@@ -11,6 +11,8 @@
 #include <tftf_lib.h>
 #include <utils_def.h>
 
+#include <xlat_tables_defs.h>
+
 /* This error code must be different to the ones used by FFA */
 #define FFA_TFTF_ERROR		-42
 
@@ -132,6 +134,10 @@
 /** Query interrupt ID of the Managed Exit Interrupt. */
 #define FFA_FEATURE_MEI 0x3U
 
+/** Minimum and maximum buffer size reported by FFA_FEATURES(FFA_RXTX_MAP) */
+#define FFA_RXTX_MAP_MIN_BUF_4K 0
+#define FFA_RXTX_MAP_MAX_BUF_PAGE_COUNT 1
+
 /** Partition property: partition supports receipt of direct requests. */
 #define FFA_PARTITION_DIRECT_REQ_RECV (UINT32_C(1) << 0)
 
@@ -290,6 +296,48 @@
 
 typedef uint64_t ffa_notification_bitmap_t;
 
+/**
+ * Partition message header as specified by table 6.2 from FF-A v1.1 EAC0
+ * specification.
+ */
+struct ffa_partition_rxtx_header {
+	uint32_t flags;
+	/* MBZ */
+	uint32_t reserved;
+	/* Offset from the beginning of the buffer to the message payload. */
+	uint32_t offset;
+	/* Sender(Bits[31:16]) and Receiver(Bits[15:0]) endpoint IDs. */
+	ffa_id_t receiver;
+	ffa_id_t sender;
+	/* Size of message in buffer. */
+	uint32_t size;
+};
+
+#define FFA_RXTX_HEADER_SIZE sizeof(struct ffa_partition_rxtx_header)
+
+static inline void ffa_rxtx_header_init(
+	ffa_id_t sender, ffa_id_t receiver, uint32_t size,
+	struct ffa_partition_rxtx_header *header)
+{
+	header->flags = 0;
+	header->reserved = 0;
+	header->offset = FFA_RXTX_HEADER_SIZE;
+	header->sender = sender;
+	header->receiver = receiver;
+	header->size = size;
+}
+
+/* The maximum length possible for a single message. */
+#define FFA_PARTITION_MSG_PAYLOAD_MAX (PAGE_SIZE - FFA_RXTX_HEADER_SIZE)
+
+struct ffa_partition_msg {
+	struct ffa_partition_rxtx_header header;
+	char payload[FFA_PARTITION_MSG_PAYLOAD_MAX];
+};
+
+/* The maximum length possible for a single message. */
+#define FFA_MSG_PAYLOAD_MAX PAGE_SIZE
+
 #define FFA_NOTIFICATION(ID)		(UINT64_C(1) << ID)
 
 #define MAX_FFA_NOTIFICATIONS		UINT32_C(64)
@@ -306,30 +354,64 @@
 #define FFA_NOTIFICATIONS_FLAG_BITMAP_SPM	UINT32_C(0x1 << 2)
 #define FFA_NOTIFICATIONS_FLAG_BITMAP_HYP	UINT32_C(0x1 << 3)
 
+#define FFA_NOTIFICATION_SPM_BUFFER_FULL_MASK FFA_NOTIFICATION(0)
+#define FFA_NOTIFICATION_HYP_BUFFER_FULL_MASK FFA_NOTIFICATION(32)
+
 /**
  * The following is an SGI ID, that the SPMC configures as non-secure, as
  * suggested by the FF-A v1.1 specification, in section 9.4.1.
  */
 #define FFA_SCHEDULE_RECEIVER_INTERRUPT_ID 8
 
-#define FFA_NOTIFICATIONS_BITMAP(lo, hi)	\
-	(ffa_notification_bitmap_t)(lo) | 	\
-	(((ffa_notification_bitmap_t)hi << 32) & 0xFFFFFFFF00000000ULL)
-
-#define FFA_NOTIFICATIONS_FLAGS_VCPU_ID(id) UINT32_C((id & 0xFFFF) << 16)
-
-static inline ffa_notification_bitmap_t ffa_notifications_get_from_sp(
-       struct ffa_value val)
+/**
+ * Helper function to assemble a 64-bit sized bitmap, from the 32-bit sized lo
+ * and hi.
+ * Helpful as FF-A specification defines that the notifications interfaces
+ * arguments are 32-bit registers.
+ */
+static inline ffa_notification_bitmap_t ffa_notification_bitmap(uint32_t lo,
+								uint32_t hi)
 {
-	return FFA_NOTIFICATIONS_BITMAP(val.arg2, val.arg3);
+	return (ffa_notification_bitmap_t)hi << 32U | lo;
 }
 
-static inline ffa_notification_bitmap_t ffa_notifications_get_from_vm(
+static inline ffa_notification_bitmap_t ffa_notification_get_from_sp(
        struct ffa_value val)
 {
-	return FFA_NOTIFICATIONS_BITMAP(val.arg4, val.arg5);
+	return ffa_notification_bitmap((uint32_t)val.arg2,
+				       (uint32_t)val.arg3);
 }
 
+static inline ffa_notification_bitmap_t ffa_notification_get_from_vm(
+       struct ffa_value val)
+{
+	return ffa_notification_bitmap((uint32_t)val.arg4,
+				       (uint32_t)val.arg5);
+}
+
+static inline ffa_notification_bitmap_t ffa_notification_get_from_framework(
+	struct ffa_value val)
+{
+	return ffa_notification_bitmap((uint32_t)val.arg6,
+				       (uint32_t)val.arg7);
+}
+
+ /**
+ * Helper functions to check for buffer full notification.
+ */
+static inline bool is_ffa_hyp_buffer_full_notification(
+	ffa_notification_bitmap_t framework)
+{
+	return (framework & FFA_NOTIFICATION_HYP_BUFFER_FULL_MASK) != 0U;
+}
+
+static inline bool is_ffa_spm_buffer_full_notification(
+	ffa_notification_bitmap_t framework)
+{
+	return (framework & FFA_NOTIFICATION_SPM_BUFFER_FULL_MASK) != 0U;
+}
+
+
 /*
  * FFA_NOTIFICATION_INFO_GET is a SMC64 interface.
  * The following macros are defined for SMC64 implementation.
@@ -343,21 +425,21 @@
 #define FFA_NOTIFICATIONS_LIST_SHIFT(l) 		(2 * (l - 1) + 12)
 #define FFA_NOTIFICATIONS_LIST_SIZE_MASK 		0x3U
 
-static inline uint32_t ffa_notifications_info_get_lists_count(
+static inline uint32_t ffa_notification_info_get_lists_count(
 	struct ffa_value ret)
 {
 	return (uint32_t)(ret.arg2 >> FFA_NOTIFICATIONS_LISTS_COUNT_SHIFT)
 	       & FFA_NOTIFICATIONS_LISTS_COUNT_MASK;
 }
 
-static inline uint32_t ffa_notifications_info_get_list_size(
+static inline uint32_t ffa_notification_info_get_list_size(
 	struct ffa_value ret, uint32_t list)
 {
 	return (uint32_t)(ret.arg2 >> FFA_NOTIFICATIONS_LIST_SHIFT(list)) &
 	       FFA_NOTIFICATIONS_LIST_SIZE_MASK;
 }
 
-static inline bool ffa_notifications_info_get_more_pending(struct ffa_value ret)
+static inline bool ffa_notification_info_get_more_pending(struct ffa_value ret)
 {
 	return (ret.arg2 & FFA_NOTIFICATIONS_INFO_GET_FLAG_MORE_PENDING) != 0U;
 }
@@ -785,10 +867,13 @@
 struct ffa_value ffa_features_with_input_property(uint32_t feature,
                                                   uint32_t param);
 struct ffa_value ffa_partition_info_get(const struct ffa_uuid uuid);
+struct ffa_value ffa_rx_release_with_id(ffa_id_t vm_id);
 struct ffa_value ffa_rx_release(void);
 struct ffa_value ffa_rxtx_map(uintptr_t send, uintptr_t recv, uint32_t pages);
 struct ffa_value ffa_rxtx_unmap_with_id(uint32_t id);
 struct ffa_value ffa_rxtx_unmap(void);
+struct ffa_value ffa_msg_send2_with_id(uint32_t flags, ffa_id_t sender);
+struct ffa_value ffa_msg_send2(uint32_t flags);
 struct ffa_value ffa_mem_donate(uint32_t descriptor_length,
 				uint32_t fragment_length);
 struct ffa_value ffa_mem_lend(uint32_t descriptor_length,
diff --git a/include/runtime_services/ffa_svc.h b/include/runtime_services/ffa_svc.h
index 0e6081e..577e8cf 100644
--- a/include/runtime_services/ffa_svc.h
+++ b/include/runtime_services/ffa_svc.h
@@ -150,6 +150,7 @@
 #define FFA_RX_RELEASE		FFA_FID(SMC_32, FFA_FNUM_RX_RELEASE)
 #define FFA_RXTX_MAP_SMC32	FFA_FID(SMC_32, FFA_FNUM_RXTX_MAP)
 #define FFA_RXTX_UNMAP		FFA_FID(SMC_32, FFA_FNUM_RXTX_UNMAP)
+#define FFA_MSG_SEND2		FFA_FID(SMC_32, FFA_FNUM_MSG_SEND2)
 #define FFA_PARTITION_INFO_GET	FFA_FID(SMC_32, FFA_FNUM_PARTITION_INFO_GET)
 #define FFA_ID_GET		FFA_FID(SMC_32, FFA_FNUM_ID_GET)
 #define FFA_MSG_POLL		FFA_FID(SMC_32, FFA_FNUM_MSG_POLL)
diff --git a/include/runtime_services/pmf.h b/include/runtime_services/pmf.h
index d2ed412..5192999 100644
--- a/include/runtime_services/pmf.h
+++ b/include/runtime_services/pmf.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -24,17 +24,18 @@
 #define PMF_CACHE_MAINT		(1 << 0)
 #define PMF_NO_CACHE_MAINT	0
 
+#define PMF_SMC_VERSION		U(0x00000001)
 /*
  * Defines for PMF SMC function ids.
  */
 #ifndef __aarch64__
-#define PMF_SMC_GET_TIMESTAMP	0x82000010
+#define PMF_SMC_GET_TIMESTAMP	0x87000020
+#define PMF_SMC_GET_VERSION	0x87000021
 #else
-#define PMF_SMC_GET_TIMESTAMP	0xC2000010
+#define PMF_SMC_GET_TIMESTAMP	0xC7000020
+#define PMF_SMC_GET_VERSION	0xC7000021
 #endif
 
-#define PMF_NUM_SMC_CALLS		2
-
 /* Following are the supported PMF service IDs */
 #define PMF_PSCI_STAT_SVC_ID	0
 #define PMF_RT_INSTR_SVC_ID	1
diff --git a/include/runtime_services/spm_common.h b/include/runtime_services/spm_common.h
index ad2ba08..fb1f61e 100644
--- a/include/runtime_services/spm_common.h
+++ b/include/runtime_services/spm_common.h
@@ -150,4 +150,10 @@
 	ffa_id_t receiver_id,
 	uint32_t mem_func);
 
+bool receive_indirect_message(void *buffer, size_t buffer_size, void *recv,
+			      ffa_id_t *sender, ffa_id_t receiver,
+			      ffa_id_t own_id);
+struct ffa_value send_indirect_message(
+		ffa_id_t from, ffa_id_t to, void *send, const void *payload,
+		size_t payload_size, uint32_t send_flags);
 #endif /* SPM_COMMON_H */
diff --git a/include/runtime_services/ven_el3_svc.h b/include/runtime_services/ven_el3_svc.h
new file mode 100644
index 0000000..3a61ecd
--- /dev/null
+++ b/include/runtime_services/ven_el3_svc.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef VEN_EL3_SVC_H
+#define VEN_EL3_SVC_H
+
+/*
+ * Definitions related to the Vendor-Specific El3 as per the SMC Calling Convention.
+ */
+
+/* VEN_EL3_SMC_32		0x87000000U */
+/* VEN_EL3_SMC_64		0xC7000000U */
+
+#define VEN_EL3_SVC_UID		0x8700ff01
+/*				0x8700ff02 is reserved */
+#define VEN_EL3_SVC_VERSION	0x8700ff03
+
+#define VEN_EL3_SVC_VERSION_MAJOR	1
+#define VEN_EL3_SVC_VERSION_MINOR	0
+
+#endif /* VEN_EL3_SVC_H */
diff --git a/lib/power_management/suspend/aarch64/asm_tftf_suspend.S b/lib/power_management/suspend/aarch64/asm_tftf_suspend.S
index e715e49..c643475 100644
--- a/lib/power_management/suspend/aarch64/asm_tftf_suspend.S
+++ b/lib/power_management/suspend/aarch64/asm_tftf_suspend.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -81,8 +81,18 @@
 	stp	x3, x4, [x0, #SUSPEND_CTX_TTBR0_OFFSET]
 	stp	x5, x6, [x0, #SUSPEND_CTX_VBAR_OFFSET]
 	mrs	x1, hcr_el2
+	/*
+	 * Check if the processor supports SME
+	 */
+	mrs	x2, id_aa64pfr1_el1
+	tst	x2, #(1 << 25)
+	bne	3f
 	str	x1, [x0, #SUSPEND_CTX_HCR_OFFSET]
 	ret
+
+3:	mrs	x2, SMCR_EL2
+	stp	x1, x2, [x0, #SUSPEND_CTX_HCR_OFFSET]
+	ret
 endfunc __tftf_save_arch_context
 
 /*
@@ -120,13 +130,24 @@
 	msr	ttbr0_el2, x3
 	msr	tcr_el2, x4
 	msr	vbar_el2, x5
+        /*
+	 * Check if the processor supports SME
+	 */
+	mrs	x2, id_aa64pfr1_el1
+	tst	x2, #(1 << 25)
+	bne	3f
 	ldr	x1, [x0, #SUSPEND_CTX_HCR_OFFSET]
 	msr	hcr_el2, x1
+	b	4f
+
+3:	ldp	x1, x2, [x0, #SUSPEND_CTX_HCR_OFFSET]
+	msr     hcr_el2, x1
+	msr	SMCR_EL2, x2
 
 	/*
 	 * TLB invalidations need to be completed before enabling MMU
 	 */
-	dsb	nsh
+4:	dsb	nsh
 	msr	sctlr_el2, x6
 	/* Ensure the MMU enable takes effect immediately */
 	isb
diff --git a/lib/power_management/suspend/suspend_private.h b/lib/power_management/suspend/suspend_private.h
index 2ccf7a3..debd84f 100644
--- a/lib/power_management/suspend/suspend_private.h
+++ b/lib/power_management/suspend/suspend_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,8 +10,9 @@
 /*
  * Number of system registers we need to save/restore across a CPU suspend:
  * EL1: MAIR, CPACR, TTBR0, TCR, VBAR, SCTLR
- * EL2: MAIR, CPTR, TTBR0, TCR, VBAR, SCTLR, HCR
+ * EL2: MAIR, CPTR, TTBR0, TCR, VBAR, SCTLR, HCR, SMCR
  * APIAKeyLo_EL1 and APIAKeyHi_EL1 (if enabled).
+ * On need basis other registers can be included in tftf_suspend_context.
  */
 #if ENABLE_PAUTH
 #define NR_CTX_REGS 10
diff --git a/spm/cactus/cactus.mk b/spm/cactus/cactus.mk
index 4e86e3d..0755749 100644
--- a/spm/cactus/cactus.mk
+++ b/spm/cactus/cactus.mk
@@ -51,6 +51,7 @@
 		cactus_message_loop.c			\
 		cactus_test_simd.c		\
 		cactus_test_direct_messaging.c		\
+		cactus_test_indirect_message.c	\
 		cactus_test_interrupts.c		\
 		cactus_test_memory_sharing.c		\
 		cactus_tests_smmuv3.c			\
diff --git a/spm/cactus/cactus_tests/cactus_test_indirect_message.c b/spm/cactus/cactus_tests/cactus_test_indirect_message.c
new file mode 100644
index 0000000..085d72f
--- /dev/null
+++ b/spm/cactus/cactus_tests/cactus_test_indirect_message.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "cactus_message_loop.h"
+#include <cactus_test_cmds.h>
+#include "debug.h"
+#include "ffa_helpers.h"
+#include "utils_def.h"
+#include <ffa_endpoints.h>
+#include <spm_common.h>
+
+CACTUS_CMD_HANDLER(req_msg_send, CACTUS_REQ_MSG_SEND_CMD)
+{
+	struct ffa_value ret;
+	const ffa_id_t vm_id = ffa_dir_msg_dest(*args);
+	const ffa_id_t source = ffa_dir_msg_source(*args);
+	const ffa_id_t receiver = cactus_msg_send_receiver(*args);
+	const ffa_id_t sender = cactus_msg_send_sender(*args);
+	const char message[] = "Testing FF-A message.";
+
+	VERBOSE("%x requested to send indirect message to %x as %x(own %x)\n",
+		ffa_dir_msg_source(*args), receiver, sender, vm_id);
+
+	ret = send_indirect_message(sender, receiver, mb->send, message,
+				    ARRAY_SIZE(message), 0);
+
+	if (is_ffa_call_error(ret)) {
+		ERROR("Failed to send indirect message.\n");
+		return cactus_error_resp(vm_id,
+					 source,
+					 ffa_error_code(ret));
+	}
+
+	return cactus_success_resp(vm_id, source, 0);
+}
diff --git a/spm/cactus/cactus_tests/cactus_test_notifications.c b/spm/cactus/cactus_tests/cactus_test_notifications.c
index 6d7b41b..420f942 100644
--- a/spm/cactus/cactus_tests/cactus_test_notifications.c
+++ b/spm/cactus/cactus_tests/cactus_test_notifications.c
@@ -109,8 +109,8 @@
 	VERBOSE("Notifications returned:\n"
 			"   from sp: %llx\n"
 			"   from vm: %llx\n",
-		ffa_notifications_get_from_sp(ret),
-		ffa_notifications_get_from_vm(ret));
+		ffa_notification_get_from_sp(ret),
+		ffa_notification_get_from_vm(ret));
 
 	/* If requested to check the status of NPI, for the respective CPU. */
 	if (cactus_notifications_check_npi_handled(*args)) {
@@ -126,8 +126,8 @@
 	}
 
 	return cactus_notifications_get_success_resp(
-		vm_id, source, ffa_notifications_get_from_sp(ret),
-		ffa_notifications_get_from_vm(ret));
+		vm_id, source, ffa_notification_get_from_sp(ret),
+		ffa_notification_get_from_vm(ret));
 }
 
 CACTUS_CMD_HANDLER(notifications_set, CACTUS_NOTIFICATIONS_SET_CMD)
diff --git a/spm/cactus/plat/arm/fvp/fdts/cactus.dts b/spm/cactus/plat/arm/fvp/fdts/cactus.dts
index 3effb39..4d95069 100644
--- a/spm/cactus/plat/arm/fvp/fdts/cactus.dts
+++ b/spm/cactus/plat/arm/fvp/fdts/cactus.dts
@@ -27,7 +27,7 @@
 	entrypoint-offset = <0x00002000>;
 	xlat-granule = <0>; /* 4KiB */
 	boot-order = <0>;
-	messaging-method = <3>; /* Direct messaging only */
+	messaging-method = <7>; /* Indirect Messaging and direct messaging. */
 	ns-interrupts-action = <1>; /* Managed exit is supported */
 	notification-support; /* Support receipt of notifications. */
 
diff --git a/spm/cactus/plat/arm/tc/fdts/cactus.dts b/spm/cactus/plat/arm/tc/fdts/cactus.dts
index 31b9e8e..a4c71fe 100644
--- a/spm/cactus/plat/arm/tc/fdts/cactus.dts
+++ b/spm/cactus/plat/arm/tc/fdts/cactus.dts
@@ -25,7 +25,7 @@
 	entrypoint-offset = <0x00002000>;
 	xlat-granule = <0>; /* 4KiB */
 	boot-order = <0>;
-	messaging-method = <3>; /* Direct messaging only */
+	messaging-method = <7>; /* Indirect messaging and direct messaging. */
 	notification-support; /* Support receipt of notifications. */
 	managed-exit; /* Managed exit supported */
 	run-time-model = <1>; /* Run to completion */
diff --git a/tftf/tests/aarch32_tests_to_skip.txt b/tftf/tests/aarch32_tests_to_skip.txt
index 210d465..6913cb1 100644
--- a/tftf/tests/aarch32_tests_to_skip.txt
+++ b/tftf/tests/aarch32_tests_to_skip.txt
@@ -18,3 +18,4 @@
 FF-A Notifications
 RMI and SPM tests
 FF-A SMCCC compliance
+FF-A Indirect Messaging
diff --git a/tftf/tests/runtime_services/el3/query_ven_el3_svc.c b/tftf/tests/runtime_services/el3/query_ven_el3_svc.c
new file mode 100644
index 0000000..0b3b6e3
--- /dev/null
+++ b/tftf/tests/runtime_services/el3/query_ven_el3_svc.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <psci.h>
+#include <smccc.h>
+#include <ven_el3_svc.h>
+#include <tftf_lib.h>
+#include <uuid_utils.h>
+
+/*
+ * Vendor-Specific EL3 UUID as returned by the implementation in the Trusted
+ * Firmware.
+ */
+static const uuid_t armtf_ven_el3_svc_uuid = {
+	{0xb6, 0x01, 0x1d, 0xca},
+	{0x57, 0xc4},
+	{0x40, 0x7e},
+	0x83, 0xf0,
+	{0xa7, 0xed, 0xda, 0xf0, 0xdf, 0x6c}
+};
+
+/**
+ * @Test_Aim@ Query the Vendor-Specific El3 Service
+ *
+ * This test targets the implementation of the vendor-specific el3 in the Trusted
+ * Firmware. If it is interfaced with a different implementation then this test
+ * will most likely fail because the values returned by the service won't be the
+ * ones expected.
+ *
+ * The following queries are performed:
+ * 1) Call UID
+ * 2) Call count - is reserved and is expected to fail
+ * 3) Call revision details
+ */
+test_result_t test_query_ven_el3_svc(void)
+{
+	smc_args ven_el3_svc_args;
+	smc_ret_values ret;
+	uuid_t ven_el3_svc_uuid;
+	char uuid_str[UUID_STR_SIZE];
+	test_result_t test_result = TEST_RESULT_SUCCESS;
+
+	/* Standard Service Call UID */
+	ven_el3_svc_args.fid = VEN_EL3_SVC_UID;
+	ret = tftf_smc(&ven_el3_svc_args);
+
+	make_uuid_from_4words(&ven_el3_svc_uuid,
+			ret.ret0, ret.ret1, ret.ret2, ret.ret3);
+	if (!uuid_equal(&ven_el3_svc_uuid, &armtf_ven_el3_svc_uuid)) {
+		tftf_testcase_printf("Wrong UUID: expected %s,\n",
+				uuid_to_str(&armtf_ven_el3_svc_uuid, uuid_str));
+		tftf_testcase_printf("                 got %s\n",
+				uuid_to_str(&ven_el3_svc_uuid, uuid_str));
+		test_result = TEST_RESULT_FAIL;
+	}
+
+	/*
+	 * Standard Service Call Count which is reserved for vendor-specific el3
+	 * This will return an unkown smc.
+	 */
+	ven_el3_svc_args.fid = VEN_EL3_SVC_UID + 1;
+	ret = tftf_smc(&ven_el3_svc_args);
+
+	if (ret.ret0 != SMC_UNKNOWN) {
+		tftf_testcase_printf("Querying Vendor-Specific el3 service call count"
+				" which is reserved failed\n");
+		test_result = TEST_RESULT_FAIL;
+	}
+
+	/* Vendor-Specific El3 Service Call for version details */
+	ven_el3_svc_args.fid = VEN_EL3_SVC_VERSION;
+	ret = tftf_smc(&ven_el3_svc_args);
+
+	if ((ret.ret0 != VEN_EL3_SVC_VERSION_MAJOR) ||
+	    (ret.ret1 != VEN_EL3_SVC_VERSION_MINOR)) {
+		tftf_testcase_printf(
+			"Vendor Specific El3 service reported wrong version: expected {%u.%u}, got {%llu.%llu}\n",
+			VEN_EL3_SVC_VERSION_MAJOR, VEN_EL3_SVC_VERSION_MINOR,
+			(unsigned long long)ret.ret0,
+			(unsigned long long)ret.ret1);
+		test_result = TEST_RESULT_FAIL;
+	}
+
+	return test_result;
+}
diff --git a/tftf/tests/runtime_services/secure_service/ffa_helpers.c b/tftf/tests/runtime_services/secure_service/ffa_helpers.c
index 6db193c..b5bb091 100644
--- a/tftf/tests/runtime_services/secure_service/ffa_helpers.c
+++ b/tftf/tests/runtime_services/secure_service/ffa_helpers.c
@@ -465,16 +465,23 @@
 	return ffa_service_call(&args);
 }
 
-/* Query SPMD that the rx buffer of the partition can be released */
-struct ffa_value ffa_rx_release(void)
+/* Querying the SPMC to release the rx buffers of the VM ID. */
+struct ffa_value ffa_rx_release_with_id(ffa_id_t vm_id)
 {
 	struct ffa_value args = {
-		.fid = FFA_RX_RELEASE
+		.fid = FFA_RX_RELEASE,
+		.arg1 = (uint64_t)vm_id,
 	};
 
 	return ffa_service_call(&args);
 }
 
+/* Query SPMC that the rx buffer of the partition can be released */
+struct ffa_value ffa_rx_release(void)
+{
+	return ffa_rx_release_with_id(0);
+}
+
 /* Map the RXTX buffer */
 struct ffa_value ffa_rxtx_map(uintptr_t send, uintptr_t recv, uint32_t pages)
 {
@@ -514,6 +521,39 @@
 	return ffa_service_call(&args);
 }
 
+/**
+ * Copies data from the sender's send buffer to the recipient's receive buffer
+ * and notifies the receiver.
+ *
+ * `flags` may include a 'Delay Schedule Receiver interrupt'.
+ *
+ * Returns FFA_SUCCESS if the message is sent, or an error code otherwise:
+ *  - INVALID_PARAMETERS: one or more of the parameters do not conform.
+ *  - BUSY: receiver's mailbox was full.
+ *  - DENIED: receiver is not in a state to handle the request or doesn't
+ *    support indirect messages.
+ */
+struct ffa_value ffa_msg_send2_with_id(uint32_t flags, ffa_id_t sender)
+{
+	struct ffa_value args = {
+		.fid = FFA_MSG_SEND2,
+		.arg1 = sender << 16,
+		.arg2 = flags,
+		.arg3 = FFA_PARAM_MBZ,
+		.arg4 = FFA_PARAM_MBZ,
+		.arg5 = FFA_PARAM_MBZ,
+		.arg6 = FFA_PARAM_MBZ,
+		.arg7 = FFA_PARAM_MBZ
+	};
+
+	return ffa_service_call(&args);
+}
+
+struct ffa_value ffa_msg_send2(uint32_t flags)
+{
+	return ffa_msg_send2_with_id(flags, 0);
+}
+
 /* Donate memory to another partition */
 struct ffa_value ffa_mem_donate(uint32_t descriptor_length,
 				uint32_t fragment_length)
diff --git a/tftf/tests/runtime_services/secure_service/spm_common.c b/tftf/tests/runtime_services/secure_service/spm_common.c
index a65fdb8..8fb3a72 100644
--- a/tftf/tests/runtime_services/secure_service/spm_common.c
+++ b/tftf/tests/runtime_services/secure_service/spm_common.c
@@ -10,6 +10,7 @@
 #include <cactus_test_cmds.h>
 #include <debug.h>
 #include <ffa_endpoints.h>
+#include <assert.h>
 #include <ffa_svc.h>
 #include <lib/extensions/sve.h>
 #include <spm_common.h>
@@ -844,3 +845,107 @@
 	return ffa_memory_access_init(receiver_id, data_access,
 				      instruction_access, 0, NULL);
 }
+
+/**
+ * Receives message from the mailbox, copies it into the 'buffer', gets the
+ * pending framework notifications and releases the RX buffer.
+ * Returns false if it fails to copy the message to `buffer`, or true
+ * otherwise.
+ */
+bool receive_indirect_message(void *buffer, size_t buffer_size, void *recv,
+			      ffa_id_t *sender, ffa_id_t receiver, ffa_id_t own_id)
+{
+	const struct ffa_partition_msg *message;
+	struct ffa_partition_rxtx_header header;
+	ffa_id_t source_vm_id;
+	const uint32_t *payload;
+	struct ffa_value ret;
+	ffa_notification_bitmap_t fwk_notif;
+
+	if (buffer_size > FFA_MSG_PAYLOAD_MAX) {
+		return false;
+	}
+
+	ret = ffa_notification_get(receiver, 0,
+				   FFA_NOTIFICATIONS_FLAG_BITMAP_SPM);
+	if (is_ffa_call_error(ret)) {
+		return false;
+	}
+
+	fwk_notif = ffa_notification_get_from_framework(ret);
+
+	if (fwk_notif == 0U) {
+		ERROR("Expected Rx buffer full notification.");
+		return false;
+	}
+
+	message = (const struct ffa_partition_msg *)recv;
+	memcpy(&header, message, sizeof(struct ffa_partition_rxtx_header));
+
+	source_vm_id = header.sender;
+
+	if (is_ffa_spm_buffer_full_notification(fwk_notif)) {
+		/*
+		 * Expect the sender to always have been an SP.
+		 */
+		assert(IS_SP_ID(source_vm_id));
+	}
+
+	if (header.size > buffer_size) {
+		ERROR("Error in rxtx header. Message size: %#x; "
+		      "buffer size: %lu\n",
+		      header.size, buffer_size);
+		return false;
+	}
+
+	payload = (const uint32_t *)message->payload;
+
+	/* Get message to free the RX buffer. */
+	memcpy(buffer, payload, header.size);
+
+	/* Check receiver ID against own ID. */
+	if (receiver != own_id) {
+		ret = ffa_rx_release_with_id(receiver);
+	} else {
+		ret = ffa_rx_release();
+	}
+
+	if (is_ffa_call_error(ret)) {
+		ERROR("Failed to release the rx buffer\n");
+		return false;
+	}
+
+	if (receiver != header.receiver) {
+		ERROR("Header receiver: %x different than expected receiver: %x\n",
+		      header.receiver, receiver);
+		return false;
+	}
+
+
+	if (sender != NULL) {
+		*sender = source_vm_id;
+	}
+
+	return true;
+}
+
+/**
+ * Sends an indirect message: initializes the `ffa_rxtx_header`, copies the
+ * payload to the TX buffer.
+ * Uses the `send_flags` if any are provided in the call to FFA_MSG_SEND2.
+ */
+struct ffa_value send_indirect_message(
+		ffa_id_t from, ffa_id_t to, void *send, const void *payload,
+		size_t payload_size, uint32_t send_flags)
+{
+	struct ffa_partition_msg *message = (struct ffa_partition_msg *)send;
+
+	/* Initialize message header. */
+	ffa_rxtx_header_init(from, to, payload_size, &message->header);
+
+	/* Fill TX buffer with payload. */
+	memcpy(message->payload, payload, payload_size);
+
+	/* Send the message. */
+	return ffa_msg_send2(send_flags);
+}
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_exceptions.c b/tftf/tests/runtime_services/secure_service/test_ffa_exceptions.c
index 0a345d4..bd0df07 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_exceptions.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_exceptions.c
@@ -7,6 +7,7 @@
 #include <arch_helpers.h>
 #include <cactus_test_cmds.h>
 #include "ffa_helpers.h"
+#include "tftf_lib.h"
 #include <debug.h>
 #include <ffa_endpoints.h>
 #include <ffa_svc.h>
@@ -115,3 +116,55 @@
 
 	return host_cmp_result();
 }
+
+/**
+ * Map the NS RXTX buffers to the SPM, invoke the TRP delegation
+ * service to change the RX buffer PAS to realm, invoke the
+ * FFA_PARTITON_INFO_GET interface, such that SPM does NS access
+ * to realm region and triggers GPF.
+ */
+test_result_t test_ffa_rxtx_to_realm_pas(void)
+{
+	struct mailbox_buffers mb;
+	u_register_t retmm;
+	struct ffa_value ret;
+
+	GET_TFTF_MAILBOX(mb);
+
+	if (get_armv9_2_feat_rme_support() == 0U) {
+		return TEST_RESULT_SKIPPED;
+	}
+
+	/* Delegate the shared page to Realm. */
+	retmm = host_rmi_granule_delegate((u_register_t)mb.recv);
+	if (retmm != 0UL) {
+		ERROR("Granule delegate failed, ret=0x%lx\n", retmm);
+		return TEST_RESULT_FAIL;
+	}
+
+	ret = ffa_partition_info_get((struct ffa_uuid){{0}});
+
+	if (!is_expected_ffa_error(ret, FFA_ERROR_ABORTED)) {
+		ERROR("FFA_PARTITON_INFO_GET should terminate with"
+		       "FFA_ERROR_ABORTED\n");
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Undelegate the shared page. */
+	retmm = host_rmi_granule_undelegate((u_register_t)mb.recv);
+	if (retmm != 0UL) {
+		ERROR("Granule undelegate failed, ret=0x%lx\n", retmm);
+		return TEST_RESULT_FAIL;
+	}
+
+	ret = ffa_partition_info_get((struct ffa_uuid){{0}});
+
+	if (is_ffa_call_error(ret)) {
+		ERROR("FFA_PARTITON_INFO_GET should succeed.\n");
+		return TEST_RESULT_FAIL;
+	}
+
+	ffa_rx_release();
+
+	return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_indirect_messaging.c b/tftf/tests/runtime_services/secure_service/test_ffa_indirect_messaging.c
new file mode 100644
index 0000000..5a60a21
--- /dev/null
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_indirect_messaging.c
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2024 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include "ffa_helpers.h"
+#include "spm_common.h"
+#include "tftf_lib.h"
+#include <debug.h>
+#include <smccc.h>
+
+#include <arch_helpers.h>
+#include <cactus_test_cmds.h>
+#include <ffa_endpoints.h>
+#include <ffa_svc.h>
+#include <host_realm_helper.h>
+#include <platform.h>
+#include <spm_test_helpers.h>
+#include <test_helpers.h>
+
+static const struct ffa_uuid expected_sp_uuids[] = {
+		{PRIMARY_UUID},
+	};
+
+const char expected_msg[] = "Testing FF-A message.";
+
+/*
+ *
+ * Used as the RX/TX buffers belonging to VM 1 in the forwarding FFA_RXTX_MAP
+ * tests.
+ */
+static __aligned(PAGE_SIZE) uint8_t vm1_rx_buffer[PAGE_SIZE];
+static __aligned(PAGE_SIZE) uint8_t vm1_tx_buffer[PAGE_SIZE];
+
+test_result_t test_ffa_indirect_message_sp_to_vm(void)
+{
+	struct ffa_value ret;
+	struct mailbox_buffers mb;
+	ffa_id_t header_sender;
+	const ffa_id_t vm_id = 1;
+	const ffa_id_t sender = SP_ID(1);
+	char msg[300];
+
+	/**********************************************************************
+	 * Check SPMC has ffa_version and expected FF-A endpoints are deployed.
+	 **********************************************************************/
+	CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
+
+	GET_TFTF_MAILBOX(mb);
+
+	ret = ffa_rxtx_map_forward(mb.send, vm_id, vm1_rx_buffer,
+				   vm1_tx_buffer);
+
+	if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
+		ERROR("Failed to map buffers RX %p TX %p for VM %x\n",
+		      vm1_tx_buffer, vm1_tx_buffer, vm_id);
+		return TEST_RESULT_FAIL;
+	}
+
+	ret = ffa_notification_bitmap_create(vm_id, PLATFORM_CORE_COUNT);
+
+	if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
+		ERROR("Failed to create bitmap for vm %x\n", vm_id);
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Request SP to send message. */
+	ret = cactus_req_ind_msg_send_cmd(
+			HYP_ID, sender, vm_id, sender, 0);
+
+	if (!is_ffa_direct_response(ret) &&
+	    cactus_get_response(ret) != CACTUS_SUCCESS) {
+		return TEST_RESULT_FAIL;
+	}
+
+	if (!receive_indirect_message(&msg, ARRAY_SIZE(msg), (void *)vm1_rx_buffer,
+				      &header_sender, vm_id, 0)) {
+		return TEST_RESULT_FAIL;
+	}
+
+	if (strncmp(msg, expected_msg, ARRAY_SIZE(expected_msg)) != 0) {
+		ERROR("Unexpected message: %s, expected: %s\n", msg, expected_msg);
+		return TEST_RESULT_FAIL;
+	}
+
+	if (header_sender != sender) {
+		ERROR("Unexpected endpoints. Sender: %x Expected: %x\n",
+		      header_sender, sender);
+		return TEST_RESULT_FAIL;
+	}
+
+	ret = ffa_notification_bitmap_destroy(vm_id);
+	if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
+		return TEST_RESULT_FAIL;
+	}
+
+	ret = ffa_rxtx_unmap_with_id(vm_id);
+	if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
+
+/**
+ * Test message sent from SP to VM when VM's RX is realm, the operation fails
+ * smoothly.
+ */
+test_result_t test_ffa_indirect_message_sp_to_vm_rx_realm_fail(void)
+{
+	struct ffa_value ret;
+	struct mailbox_buffers mb;
+	const ffa_id_t vm_id = 1;
+	const ffa_id_t sender = SP_ID(1);
+	ffa_id_t header_sender;
+	u_register_t ret_rmm;
+	char msg[300];
+
+	if (get_armv9_2_feat_rme_support() == 0U) {
+		return TEST_RESULT_SKIPPED;
+	}
+
+	/**********************************************************************
+	 * Check SPMC has ffa_version and expected FF-A endpoints are deployed.
+	 **********************************************************************/
+	CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
+
+	GET_TFTF_MAILBOX(mb);
+
+	/* Map RXTX buffers into SPMC translation. */
+	ret = ffa_rxtx_map_forward(mb.send, vm_id, vm1_rx_buffer,
+				   vm1_tx_buffer);
+
+	if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
+		ERROR("Failed to map buffers RX %p TX %p for VM %x\n",
+		      vm1_rx_buffer, vm1_tx_buffer, vm_id);
+		return TEST_RESULT_FAIL;
+	}
+
+	/*
+	 * Create bitmap only to then demonstrate that the message can't
+	 * be sent, as there are no pending notifications to the VM.
+	 */
+	ret = ffa_notification_bitmap_create(vm_id, PLATFORM_CORE_COUNT);
+
+	if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
+		ERROR("Failed to create bitmap for vm %x\n", vm_id);
+		return TEST_RESULT_FAIL;
+	}
+
+	/*
+	 * Delegate RX buffer of VM to realm.
+	 */
+	ret_rmm = host_rmi_granule_delegate((u_register_t)vm1_rx_buffer);
+
+	if (ret_rmm != 0UL) {
+		INFO("Delegate operation returns %#lx for address %p\n",
+		     ret_rmm, mb.send);
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Request SP to send message. */
+	ret = cactus_req_ind_msg_send_cmd(
+			HYP_ID, sender, vm_id, sender, 0);
+
+	if (!is_ffa_direct_response(ret) &&
+	    cactus_get_response(ret) != FFA_ERROR_ABORTED) {
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Undelegate to reestablish the same security state for PAS. */
+	ret_rmm = host_rmi_granule_undelegate((u_register_t)vm1_rx_buffer);
+
+	if (ret_rmm != 0UL) {
+		INFO("Undelegate operation returns %#lx for address %p\n",
+		     ret_rmm, mb.send);
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Expect that attempting to receive message shall fail. */
+	if (receive_indirect_message(&msg, ARRAY_SIZE(msg), (void *)vm1_rx_buffer,
+				     NULL, vm_id, 0)) {
+		return TEST_RESULT_FAIL;
+	}
+
+	/*
+	 * Redo the test so we check after undelegating the memory.
+	 * After undelegating, the SPMC should be able to complete the
+	 * operation.
+	 */
+	ret = cactus_req_ind_msg_send_cmd(
+			HYP_ID, sender, vm_id, sender, 0);
+
+	if (!is_ffa_direct_response(ret) &&
+	    cactus_get_response(ret) != CACTUS_SUCCESS) {
+		return TEST_RESULT_FAIL;
+	}
+
+	if (!receive_indirect_message(&msg, ARRAY_SIZE(msg), (void *)vm1_rx_buffer,
+				      &header_sender, vm_id, 0)) {
+		return TEST_RESULT_FAIL;
+	}
+
+	if (strncmp(msg, expected_msg, ARRAY_SIZE(expected_msg)) != 0) {
+		ERROR("Unexpected message: %s, expected: %s\n", msg, expected_msg);
+		return TEST_RESULT_FAIL;
+	}
+
+	if (header_sender != sender) {
+		ERROR("Unexpected endpoints. Sender: %x Expected: %x\n",
+		      header_sender, sender);
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Cleaning up after the test: */
+
+	/* Destroy bitmap of VM. */
+	ret = ffa_notification_bitmap_destroy(vm_id);
+
+	if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
+		ERROR("Failed to destroy bitmap for vm %x\n", vm_id);
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Unmap RXTX buffers into SPMC translation. */
+	ret = ffa_rxtx_unmap_with_id(vm_id);
+
+	if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
+		ERROR("Failed to unmap RXTX for vm %x\n", vm_id);
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
+
+/**
+ * Test message sent from VM to SP, when VM TX is in realm PAS, the operation
+ * fails smoothly.
+ */
+test_result_t test_ffa_indirect_message_vm_to_sp_tx_realm_fail(void)
+{
+	struct ffa_value ret;
+	struct mailbox_buffers mb;
+	const ffa_id_t vm_id = 1;
+	const ffa_id_t receiver = SP_ID(1);
+	u_register_t ret_rmm;
+	char payload[] = "Poisonous...";
+	struct ffa_partition_msg *message = (struct ffa_partition_msg *)vm1_tx_buffer;
+
+	if (get_armv9_2_feat_rme_support() == 0U) {
+		return TEST_RESULT_SKIPPED;
+	}
+
+	/**********************************************************************
+	 * Check SPMC has ffa_version and expected FF-A endpoints are deployed.
+	 **********************************************************************/
+	CHECK_SPMC_TESTING_SETUP(1, 2, expected_sp_uuids);
+
+	GET_TFTF_MAILBOX(mb);
+
+	/* Map RXTX buffers into SPMC translation. */
+	ret = ffa_rxtx_map_forward(mb.send, vm_id, vm1_rx_buffer,
+				   vm1_tx_buffer);
+
+	if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
+		ERROR("Failed to map buffers RX %p TX %p for VM %x\n",
+		      vm1_rx_buffer, vm1_tx_buffer, vm_id);
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Initialize message header. */
+	ffa_rxtx_header_init(vm_id, receiver, ARRAY_SIZE(payload), &message->header);
+
+	/* Fill TX buffer with payload. */
+	memcpy(message->payload, payload, ARRAY_SIZE(payload));
+
+	/* Delegate TX buffer of VM to realm PAS. */
+	ret_rmm = host_rmi_granule_delegate((u_register_t)vm1_tx_buffer);
+
+	if (ret_rmm != 0UL) {
+		INFO("Delegate operation returns %#lx for address %p\n",
+		     ret_rmm, mb.send);
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Expect that attempting to send message shall fail. */
+	ret = ffa_msg_send2_with_id(0, vm_id);
+
+	if (!is_expected_ffa_error(ret, FFA_ERROR_ABORTED)) {
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Undelegate to reestablish the same security state for PAS. */
+	ret_rmm = host_rmi_granule_undelegate((u_register_t)vm1_tx_buffer);
+
+	if (ret_rmm != 0UL) {
+		INFO("Undelegate operation returns %#lx for address %p\n",
+		     ret_rmm, mb.send);
+		return TEST_RESULT_FAIL;
+	}
+
+	/* Unmap RXTX buffers into SPMC translation. */
+	ret = ffa_rxtx_unmap_with_id(vm_id);
+
+	if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
+		ERROR("Failed to unmap RXTX for vm %x\n", vm_id);
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c b/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c
index f2c2634..ca6c75a 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_notifications.c
@@ -536,8 +536,8 @@
 		 * ffa_notification_get.
 		 */
 		success_ret = (ffa_func_id(*ret) == FFA_SUCCESS_SMC32);
-		from_sp = ffa_notifications_get_from_sp(*ret);
-		from_vm = ffa_notifications_get_from_vm(*ret);
+		from_sp = ffa_notification_get_from_sp(*ret);
+		from_vm = ffa_notification_get_from_vm(*ret);
 	}
 
 	if (success_ret != true ||
@@ -557,19 +557,19 @@
 	struct ffa_value *ret, uint16_t *ids, uint32_t *lists_sizes,
 	const uint32_t max_ids_count, uint32_t lists_count, bool more_pending)
 {
-	if (lists_count != ffa_notifications_info_get_lists_count(*ret) ||
-	    more_pending != ffa_notifications_info_get_more_pending(*ret)) {
+	if (lists_count != ffa_notification_info_get_lists_count(*ret) ||
+	    more_pending != ffa_notification_info_get_more_pending(*ret)) {
 		ERROR("Notification info get not as expected.\n"
 		      "    Lists counts: %u; more pending %u\n",
-		      ffa_notifications_info_get_lists_count(*ret),
-		      ffa_notifications_info_get_more_pending(*ret));
+		      ffa_notification_info_get_lists_count(*ret),
+		      ffa_notification_info_get_more_pending(*ret));
 		dump_ffa_value(*ret);
 		return false;
 	}
 
 	for (uint32_t i = 0; i < lists_count; i++) {
 		uint32_t cur_size =
-				ffa_notifications_info_get_list_size(*ret,
+				ffa_notification_info_get_list_size(*ret,
 								     i + 1);
 
 		if (lists_sizes[i] != cur_size) {
@@ -1268,6 +1268,10 @@
 		result = TEST_RESULT_FAIL;
 	}
 
+	if (!notifications_bitmap_destroy(per_vcpu_receiver)) {
+		result = TEST_RESULT_FAIL;
+	}
+
 	return result;
 }
 
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
index 3c03d5f..621fc69 100644
--- 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
@@ -129,6 +129,41 @@
 	return TEST_RESULT_SUCCESS;
 }
 
+/**
+ * Test that `FFA_FEATURES(FFA_RXTX_MAP_SMC64)` returns a parameter explaining
+ * the maximum and minimum buffer size on v1.2 or greater.
+ */
+test_result_t test_ffa_features_rxtx_map(void)
+{
+
+	struct ffa_value args = {
+		.fid = FFA_FEATURES,
+		.arg1 = FFA_RXTX_MAP_SMC64,
+	};
+	struct ffa_value ret;
+	uint32_t param;
+	const uint32_t expected_param = (FFA_RXTX_MAP_MIN_BUF_4K << 0) |
+					(FFA_RXTX_MAP_MAX_BUF_PAGE_COUNT << 16);
+
+	SKIP_TEST_IF_FFA_VERSION_LESS_THAN(1, 2);
+
+	ret = ffa_service_call(&args);
+	if (ffa_func_id(ret) != FFA_SUCCESS_SMC32) {
+		ERROR("FFA_FEATURES failed: %d(%d)\n", ffa_func_id(ret),
+		      ffa_error_code(ret));
+		return TEST_RESULT_FAIL;
+	}
+
+	param = ret.arg2;
+	if (param != expected_param) {
+		ERROR("Unexpected param (expected %d, got %d)\n",
+		      expected_param, param);
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
+
 /******************************************************************************
  * FF-A Version ABI Tests
  ******************************************************************************/
@@ -384,16 +419,20 @@
 
 	ret = ffa_rxtx_map_forward(mb.send, VM_ID(1), vm1_rx_buffer,
 				   vm1_tx_buffer);
-	if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32))
+
+	if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
 		return TEST_RESULT_FAIL;
+	}
 
 	ret = ffa_rxtx_unmap_with_id(VM_ID(1));
-	if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32))
+	if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
 		return TEST_RESULT_FAIL;
+	}
 
 	ret = ffa_rxtx_unmap();
-	if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32))
+	if (!is_expected_ffa_return(ret, FFA_SUCCESS_SMC32)) {
 		return TEST_RESULT_FAIL;
+	}
 
 	return TEST_RESULT_SUCCESS;
 }
diff --git a/tftf/tests/runtime_services/sip_service/test_debugfs.c b/tftf/tests/runtime_services/sip_service/test_debugfs.c
index 6c626e9..39a1bf9 100644
--- a/tftf/tests/runtime_services/sip_service/test_debugfs.c
+++ b/tftf/tests/runtime_services/sip_service/test_debugfs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,9 +13,15 @@
 #define SMC_OK			(0)
 
 #define DEBUGFS_VERSION		(0x00000001)
-#define DEBUGFS_SMC_64		(0xC2000030)
 #define MAX_PATH_LEN		(256)
 
+#ifndef __aarch64__
+#define DEBUGFS_SMC   0x87000010
+#else
+#define DEBUGFS_SMC   0xC7000010
+#endif
+
+
 /* DebugFS shared buffer area */
 #ifndef PLAT_ARM_DEBUGFS_BASE
 #define PLAT_ARM_DEBUGFS_BASE		(0x81000000)
@@ -64,7 +70,7 @@
 	smc_ret_values ret;
 	smc_args args;
 
-	args.fid  = DEBUGFS_SMC_64;
+	args.fid  = DEBUGFS_SMC;
 	args.arg1 = INIT;
 	args.arg2 = phys_addr;
 	ret = tftf_smc(&args);
@@ -77,7 +83,7 @@
 	smc_ret_values ret;
 	smc_args args;
 
-	args.fid  = DEBUGFS_SMC_64;
+	args.fid  = DEBUGFS_SMC;
 	args.arg1 = VERSION;
 	ret = tftf_smc(&args);
 
@@ -92,7 +98,7 @@
 
 	strlcpy(parms->open.fname, name, MAX_PATH_LEN);
 
-	args.fid  = DEBUGFS_SMC_64;
+	args.fid  = DEBUGFS_SMC;
 	args.arg1 = OPEN;
 	args.arg2 = (u_register_t) flags;
 	ret = tftf_smc(&args);
@@ -105,7 +111,7 @@
 	smc_ret_values ret;
 	smc_args args;
 
-	args.fid  = DEBUGFS_SMC_64;
+	args.fid  = DEBUGFS_SMC;
 	args.arg1 = READ;
 	args.arg2 = (u_register_t) fd;
 	args.arg3 = (u_register_t) size;
@@ -125,7 +131,7 @@
 	smc_ret_values ret;
 	smc_args args;
 
-	args.fid  = DEBUGFS_SMC_64;
+	args.fid  = DEBUGFS_SMC;
 	args.arg1 = CLOSE;
 	args.arg2 = (u_register_t) fd;
 
@@ -144,7 +150,7 @@
 	strlcpy(parms->mount.where, where, MAX_PATH_LEN);
 	strlcpy(parms->mount.spec, spec, MAX_PATH_LEN);
 
-	args.fid  = DEBUGFS_SMC_64;
+	args.fid  = DEBUGFS_SMC;
 	args.arg1 = MOUNT;
 
 	ret = tftf_smc(&args);
@@ -160,7 +166,7 @@
 
 	strlcpy(parms->stat.path, name, MAX_PATH_LEN);
 
-	args.fid  = DEBUGFS_SMC_64;
+	args.fid  = DEBUGFS_SMC;
 	args.arg1 = STAT;
 
 	ret = tftf_smc(&args);
@@ -178,7 +184,7 @@
 	smc_ret_values ret;
 	smc_args args;
 
-	args.fid  = DEBUGFS_SMC_64;
+	args.fid  = DEBUGFS_SMC;
 	args.arg1 = SEEK;
 	args.arg2 = (u_register_t) fd;
 	args.arg3 = (u_register_t) offset;
diff --git a/tftf/tests/runtime_services/standard_service/pmf/api_tests/runtime_instr/test_pmf_rt_instr.c b/tftf/tests/runtime_services/standard_service/pmf/api_tests/runtime_instr/test_pmf_rt_instr.c
index 3c1fdaf..43685e4 100644
--- a/tftf/tests/runtime_services/standard_service/pmf/api_tests/runtime_instr/test_pmf_rt_instr.c
+++ b/tftf/tests/runtime_services/standard_service/pmf/api_tests/runtime_instr/test_pmf_rt_instr.c
@@ -63,6 +63,26 @@
 	return ret.ret0;
 }
 
+/*
+ * Simple check to see if we are able to probe
+ * pmf versioning under vendor specific el3.
+ */
+test_result_t test_check_pmf_version(void)
+{
+	smc_args args = { 0 };
+	smc_ret_values ret;
+
+	args.fid = PMF_SMC_GET_VERSION;
+	ret = tftf_smc(&args);
+
+	if (ret.ret1 != PMF_SMC_VERSION)
+	{
+		return TEST_RESULT_FAIL;
+	}
+
+	return TEST_RESULT_SUCCESS;
+}
+
 static int cycles_to_ns(uint64_t cycles, uint64_t freq, uint64_t *ns)
 {
 	if (cycles > UINT64_MAX / 1000000000 || freq == 0)
diff --git a/tftf/tests/tests-memory-access.mk b/tftf/tests/tests-memory-access.mk
index 13b2241..5c71b2e 100644
--- a/tftf/tests/tests-memory-access.mk
+++ b/tftf/tests/tests-memory-access.mk
@@ -27,4 +27,6 @@
 		test_ffa_memory_sharing.c				\
 		test_ffa_setup_and_discovery.c				\
 		spm_test_helpers.c					\
+		test_ffa_exceptions.c					\
+		test_ffa_indirect_messaging.c				\
 )
diff --git a/tftf/tests/tests-memory-access.xml b/tftf/tests/tests-memory-access.xml
index 4318cc9..f1d96e2 100644
--- a/tftf/tests/tests-memory-access.xml
+++ b/tftf/tests/tests-memory-access.xml
@@ -43,6 +43,12 @@
                 function="s_memory_cannot_be_accessed_in_ns" />
   </testsuite>
 
+  <testsuite name="SP exceptions"
+             description="SP exceptions" >
+     <testcase name="Access from a SP to a Realm region"
+               function="rl_memory_cannot_be_accessed_in_s" />
+  </testsuite>
+
   <testsuite name="Invalid memory access with RME extension"
     description="Invalid memory access with RME extension">
       <testcase name="Access Realm memory from NS world"
@@ -57,6 +63,12 @@
                 function="test_ffa_mem_send_sp_realm_memory" />
       <testcase name="FF-A memory share fail realm memory other constituent"
                 function="test_ffa_mem_lend_sp_realm_memory_separate_constituent" />
+      <testcase name="FF-A partition info get after NWd RX is in realm PAS"
+                function="test_ffa_rxtx_to_realm_pas" />
+      <testcase name="FF-A Indirect message fails if VM RX is realm"
+                function="test_ffa_indirect_message_sp_to_vm_rx_realm_fail" />
+      <testcase name="FF-A Indirect message fails if VM TX is realm"
+                function="test_ffa_indirect_message_vm_to_sp_tx_realm_fail" />
   </testsuite>
 
 </testsuites>
diff --git a/tftf/tests/tests-psci.mk b/tftf/tests/tests-psci.mk
index 0be0cef..597ee8c 100644
--- a/tftf/tests/tests-psci.mk
+++ b/tftf/tests/tests-psci.mk
@@ -1,15 +1,9 @@
 #
-# Copyright (c) 2018, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2024, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
-TESTS_SOURCES	+=								\
-	$(addprefix tftf/tests/runtime_services/standard_service/,		\
-		query_std_svc.c 						\
-		unknown_smc.c 							\
-	)
-
 TESTS_SOURCES	+=						\
 	$(addprefix tftf/tests/runtime_services/standard_service/psci/api_tests/, \
 		affinity_info/test_psci_affinity_info.c		\
diff --git a/tftf/tests/tests-psci.xml b/tftf/tests/tests-psci.xml
index e9c612b..918d9a7 100644
--- a/tftf/tests/tests-psci.xml
+++ b/tftf/tests/tests-psci.xml
@@ -1,24 +1,15 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-  Copyright (c) 2018, Arm Limited. All rights reserved.
+  Copyright (c) 2018-2024, Arm Limited. All rights reserved.
 
   SPDX-License-Identifier: BSD-3-Clause
 -->
 
 <testsuites>
 
-  <!--
-      Strictly speaking, this testsuite is not testing PSCI but we put it here
-      nonetheless to avoid having it alone in a separate XML file.
-  -->
-  <testsuite name="Query runtime services" description="Generic queries as defined by the SMCCC">
-    <testcase name="Unknown SMC" function="test_unknown_smc" />
-    <testcase name="Query Standard Service" function="test_query_std_svc" />
-  </testsuite>
-
   <testsuite name="PSCI Version" description="Check the version of PSCI implemented">
-    <testcase name="PSCI Version" function="test_psci_version" />
+     <testcase name="PSCI Version" function="test_psci_version" />
   </testsuite>
 
   <testsuite name="PSCI Affinity Info" description="Test PSCI AFFINITY_INFO support">
diff --git a/tftf/tests/tests-smc.mk b/tftf/tests/tests-smc.mk
index 8496cd1..5d86bf6 100644
--- a/tftf/tests/tests-smc.mk
+++ b/tftf/tests/tests-smc.mk
@@ -1,7 +1,14 @@
 #
-# Copyright (c) 2018, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2024, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
-TESTS_SOURCES += tftf/tests/runtime_services/generic/generic_smc.c
+TESTS_SOURCES	+=						\
+	$(addprefix tftf/tests/runtime_services/,		\
+		generic/generic_smc.c				\
+		standard_service/query_std_svc.c		\
+		standard_service/unknown_smc.c 			\
+		el3/query_ven_el3_svc.c				\
+	)
+
diff --git a/tftf/tests/tests-smc.xml b/tftf/tests/tests-smc.xml
index 56f987d..d63cfc3 100644
--- a/tftf/tests/tests-smc.xml
+++ b/tftf/tests/tests-smc.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-  Copyright (c) 2018, Arm Limited. All rights reserved.
+  Copyright (c) 2018-2024, Arm Limited. All rights reserved.
 
   SPDX-License-Identifier: BSD-3-Clause
 -->
@@ -16,4 +16,11 @@
      <testcase name="Yielding SMC64"	function="smc64_yielding" />
   </testsuite>
 
+  <testsuite name="Query runtime services" description="Generic queries as defined by the SMCCC">
+     <testcase name="Unknown SMC" function="test_unknown_smc" />
+     <testcase name="Query Standard Service" function="test_query_std_svc" />
+     <testcase name="Query Vendor-Specific Service" function="test_query_ven_el3_svc" />
+     <testcase name="Probe PMF Version" function="test_check_pmf_version" />
+  </testsuite>
+
 </testsuites>
diff --git a/tftf/tests/tests-spm.mk b/tftf/tests/tests-spm.mk
index b094e87..1ac5e84 100644
--- a/tftf/tests/tests-spm.mk
+++ b/tftf/tests/tests-spm.mk
@@ -14,6 +14,7 @@
 		spm_common.c						\
 		spm_test_helpers.c					\
 		test_ffa_direct_messaging.c				\
+		test_ffa_indirect_messaging.c				\
 		test_ffa_interrupts.c					\
 		test_ffa_secure_interrupts.c				\
 		test_ffa_memory_sharing.c				\
diff --git a/tftf/tests/tests-spm.xml b/tftf/tests/tests-spm.xml
index 21d4631..cbddb98 100644
--- a/tftf/tests/tests-spm.xml
+++ b/tftf/tests/tests-spm.xml
@@ -11,6 +11,8 @@
              description="Test FF-A Setup and Discovery interfaces" >
      <testcase name="Test FFA_FEATURES"
                function="test_ffa_features" />
+     <testcase name="Test FFA_FEATURES (FFA_RXTX_MAP)"
+               function="test_ffa_features_rxtx_map" />
 
      <testcase name="Same FFA version as SPM"
                function="test_ffa_version_equal" />
@@ -68,14 +70,6 @@
                function="test_smccc_ext_callee_preserved" />
   </testsuite>
 
-  <testsuite name="SP exceptions"
-             description="SP exceptions" >
-
-     <testcase name="Access from a SP to a Realm region"
-               function="rl_memory_cannot_be_accessed_in_s" />
-
-  </testsuite>
-
   <testsuite name="FF-A Direct messaging"
              description="Test FF-A Direct messaging" >
 
@@ -241,4 +235,10 @@
                function="test_ffa_notifications_sp_signals_vm_per_vcpu" />
   </testsuite>
 
+  <testsuite name="FF-A Indirect Messaging"
+             description="Test FF-A Indirect messaging" >
+  <testcase name="FF-A Indirect Message from SP to VM"
+               function="test_ffa_indirect_message_sp_to_vm" />
+  </testsuite>
+
 </testsuites>