refactor(plat/ffa): extract direct messaging

Extract the direct messaging interface from `plat/ffa.h` to
`plat/ffa/direct_messaging.h`.

Change-Id: Idab65bcea7b3e9975a293fa4d83b2b9a6c90b5e8
Signed-off-by: Karl Meakin <karl.meakin@arm.com>
diff --git a/inc/hf/arch/plat/ffa.h b/inc/hf/arch/plat/ffa.h
index d5367fd..7cca81c 100644
--- a/inc/hf/arch/plat/ffa.h
+++ b/inc/hf/arch/plat/ffa.h
@@ -10,7 +10,6 @@
 
 #include "hf/addr.h"
 #include "hf/ffa.h"
-#include "hf/ffa_memory_internal.h"
 #include "hf/manifest.h"
 #include "hf/vcpu.h"
 #include "hf/vm.h"
@@ -24,19 +23,6 @@
 bool plat_ffa_is_memory_send_valid(ffa_id_t receiver, ffa_id_t sender,
 				   uint32_t share_func, bool multiple_borrower);
 
-bool plat_ffa_is_direct_request_valid(struct vcpu *current,
-				      ffa_id_t sender_vm_id,
-				      ffa_id_t receiver_vm_id);
-bool plat_ffa_is_direct_response_valid(struct vcpu *current,
-				       ffa_id_t sender_vm_id,
-				       ffa_id_t receiver_vm_id);
-bool plat_ffa_is_direct_request_supported(struct vm *sender_vm,
-					  struct vm *receiver_vm,
-					  uint32_t func);
-bool plat_ffa_direct_request_forward(ffa_id_t receiver_vm_id,
-				     struct ffa_value args,
-				     struct ffa_value *ret);
-
 bool plat_ffa_rx_release_forward(struct vm_locked vm_locked,
 				 struct ffa_value *ret);
 
@@ -255,13 +241,6 @@
 void plat_ffa_init_schedule_mode_ffa_run(struct vcpu_locked current_locked,
 					 struct vcpu_locked target_locked);
 
-void plat_ffa_wind_call_chain_ffa_direct_req(
-	struct vcpu_locked current_locked,
-	struct vcpu_locked receiver_vcpu_locked, ffa_id_t sender_vm_id);
-
-void plat_ffa_unwind_call_chain_ffa_direct_resp(
-	struct vcpu_locked current_locked, struct vcpu_locked next_locked);
-
 void plat_ffa_enable_virtual_interrupts(struct vcpu_locked current_locked,
 					struct vm_locked vm_locked);
 
diff --git a/inc/hf/arch/plat/ffa/direct_messaging.h b/inc/hf/arch/plat/ffa/direct_messaging.h
new file mode 100644
index 0000000..d19e758
--- /dev/null
+++ b/inc/hf/arch/plat/ffa/direct_messaging.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2024 The Hafnium Authors.
+ *
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file or at
+ * https://opensource.org/licenses/BSD-3-Clause.
+ */
+
+#pragma once
+
+#include "hf/vcpu.h"
+#include "hf/vm.h"
+
+/** Check validity of a FF-A direct message request. */
+bool plat_ffa_is_direct_request_valid(struct vcpu *current,
+				      ffa_id_t sender_vm_id,
+				      ffa_id_t receiver_vm_id);
+
+/** Check validity of a FF-A direct message response. */
+bool plat_ffa_is_direct_response_valid(struct vcpu *current,
+				       ffa_id_t sender_vm_id,
+				       ffa_id_t receiver_vm_id);
+
+bool plat_ffa_is_direct_request_supported(struct vm *sender_vm,
+					  struct vm *receiver_vm,
+					  uint32_t func);
+
+bool plat_ffa_direct_request_forward(ffa_id_t receiver_vm_id,
+				     struct ffa_value args,
+				     struct ffa_value *ret);
+
+void plat_ffa_wind_call_chain_ffa_direct_req(
+	struct vcpu_locked current_locked,
+	struct vcpu_locked receiver_vcpu_locked, ffa_id_t sender_vm_id);
+
+void plat_ffa_unwind_call_chain_ffa_direct_resp(
+	struct vcpu_locked current_locked, struct vcpu_locked next_locked);
diff --git a/src/api.c b/src/api.c
index 957cabe..bc7ad48 100644
--- a/src/api.c
+++ b/src/api.c
@@ -14,6 +14,7 @@
 #include "hf/arch/mm.h"
 #include "hf/arch/other_world.h"
 #include "hf/arch/plat/ffa.h"
+#include "hf/arch/plat/ffa/direct_messaging.h"
 #include "hf/arch/timer.h"
 #include "hf/arch/vm.h"
 
diff --git a/src/arch/aarch64/plat/ffa/BUILD.gn b/src/arch/aarch64/plat/ffa/BUILD.gn
index 5b57f52..a90bc9e 100644
--- a/src/arch/aarch64/plat/ffa/BUILD.gn
+++ b/src/arch/aarch64/plat/ffa/BUILD.gn
@@ -22,7 +22,10 @@
     ":hypervisor_config",
   ]
   deps = [ "//vmlib/${plat_arch}:smc_call" ]
-  sources = [ "hypervisor.c" ]
+  sources = [
+    "hypervisor.c",
+    "hypervisor/direct_messaging.c",
+  ]
 }
 
 source_set("spmc") {
@@ -36,5 +39,6 @@
   sources = [
     "//src/arch/aarch64/hypervisor/simd.c",
     "spmc.c",
+    "spmc/direct_messaging.c",
   ]
 }
diff --git a/src/arch/aarch64/plat/ffa/hypervisor.c b/src/arch/aarch64/plat/ffa/hypervisor.c
index 2d23e7d..beeb9e7 100644
--- a/src/arch/aarch64/plat/ffa/hypervisor.c
+++ b/src/arch/aarch64/plat/ffa/hypervisor.c
@@ -6,7 +6,6 @@
  * https://opensource.org/licenses/BSD-3-Clause.
  */
 
-#include "hf/arch/barriers.h"
 #include "hf/arch/ffa.h"
 #include "hf/arch/other_world.h"
 #include "hf/arch/plat/ffa.h"
@@ -15,14 +14,11 @@
 #include "hf/dlog.h"
 #include "hf/ffa.h"
 #include "hf/ffa_internal.h"
-#include "hf/ffa_memory.h"
 #include "hf/ffa_memory_internal.h"
-#include "hf/std.h"
 #include "hf/vcpu.h"
 #include "hf/vm.h"
 #include "hf/vm_ids.h"
 
-#include "msr.h"
 #include "smc.h"
 #include "sysregs.h"
 
@@ -198,24 +194,6 @@
 }
 
 /**
- * Check validity of a FF-A direct message request.
- */
-bool plat_ffa_is_direct_request_valid(struct vcpu *current,
-				      ffa_id_t sender_vm_id,
-				      ffa_id_t receiver_vm_id)
-{
-	ffa_id_t current_vm_id = current->vm->id;
-
-	/*
-	 * The primary VM can send direct message request to
-	 * any other VM (but itself) or SP, but can't spoof
-	 * a different sender.
-	 */
-	return sender_vm_id != receiver_vm_id &&
-	       sender_vm_id == current_vm_id && vm_is_primary(current->vm);
-}
-
-/**
  * Check validity of the calls:
  * FFA_NOTIFICATION_BITMAP_CREATE/FFA_NOTIFICATION_BITMAP_DESTROY.
  */
@@ -232,74 +210,6 @@
 	return ffa_error(FFA_NOT_SUPPORTED);
 }
 
-bool plat_ffa_is_direct_request_supported(struct vm *sender_vm,
-					  struct vm *receiver_vm, uint32_t func)
-{
-	(void)sender_vm;
-	(void)receiver_vm;
-	(void)func;
-
-	/*
-	 * As Hypervisor is only meant to be used as a test artifact, allow
-	 * direct messaging for all VMs.
-	 */
-	return true;
-}
-
-/**
- * Check validity of a FF-A direct message response.
- */
-bool plat_ffa_is_direct_response_valid(struct vcpu *current,
-				       ffa_id_t sender_vm_id,
-				       ffa_id_t receiver_vm_id)
-{
-	ffa_id_t current_vm_id = current->vm->id;
-
-	/*
-	 * Secondary VMs can send direct message responses to
-	 * the PVM, but can't spoof a different sender.
-	 */
-	return sender_vm_id != receiver_vm_id &&
-	       sender_vm_id == current_vm_id &&
-	       receiver_vm_id == HF_PRIMARY_VM_ID;
-}
-
-bool plat_ffa_direct_request_forward(ffa_id_t receiver_vm_id,
-				     struct ffa_value args,
-				     struct ffa_value *ret)
-{
-	if (!ffa_tee_enabled) {
-		dlog_verbose("Not forwarding: ffa_tee_enabled is false\n");
-		return false;
-	}
-
-	/*
-	 * VM's requests should be forwarded to the SPMC, if receiver is an SP.
-	 */
-	if (vm_id_is_current_world(receiver_vm_id)) {
-		dlog_verbose(
-			"Not forwarding: receiver VM %#x is in the same "
-			"world\n",
-			receiver_vm_id);
-		return false;
-	}
-
-	switch (args.func) {
-	case FFA_MSG_SEND_DIRECT_REQ_32:
-	case FFA_MSG_SEND_DIRECT_REQ_64:
-		*ret = arch_other_world_call(args);
-		break;
-	case FFA_MSG_SEND_DIRECT_REQ2_64:
-		*ret = arch_other_world_call_ext(args);
-		break;
-	default:
-		panic("Invalid direct message function %#x\n", args.func);
-		break;
-	}
-
-	return true;
-}
-
 bool plat_ffa_rx_release_forward(struct vm_locked vm_locked,
 				 struct ffa_value *ret)
 {
@@ -1174,30 +1084,12 @@
 	(void)target_locked;
 }
 
-void plat_ffa_wind_call_chain_ffa_direct_req(
-	struct vcpu_locked current_locked,
-	struct vcpu_locked receiver_vcpu_locked, ffa_id_t sender_vm_id)
-{
-	/* Calls chains not supported in the Hypervisor/VMs. */
-	(void)current_locked;
-	(void)receiver_vcpu_locked;
-	(void)sender_vm_id;
-}
-
 bool plat_ffa_is_spmd_lp_id(ffa_id_t vm_id)
 {
 	(void)vm_id;
 	return false;
 }
 
-void plat_ffa_unwind_call_chain_ffa_direct_resp(
-	struct vcpu_locked current_locked, struct vcpu_locked next_locked)
-{
-	/* Calls chains not supported in the Hypervisor/VMs. */
-	(void)current_locked;
-	(void)next_locked;
-}
-
 /**
  * Enable relevant virtual interrupts for VMs.
  */
diff --git a/src/arch/aarch64/plat/ffa/hypervisor/direct_messaging.c b/src/arch/aarch64/plat/ffa/hypervisor/direct_messaging.c
new file mode 100644
index 0000000..e9c0562
--- /dev/null
+++ b/src/arch/aarch64/plat/ffa/hypervisor/direct_messaging.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2024 The Hafnium Authors.
+ *
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file or at
+ * https://opensource.org/licenses/BSD-3-Clause.
+ */
+
+#include "hf/arch/plat/ffa/direct_messaging.h"
+
+#include "hf/arch/other_world.h"
+
+#include "hf/vcpu.h"
+#include "hf/vm.h"
+
+#include "hypervisor.h"
+
+/**
+ * Check validity of a FF-A direct message request.
+ */
+bool plat_ffa_is_direct_request_valid(struct vcpu *current,
+				      ffa_id_t sender_vm_id,
+				      ffa_id_t receiver_vm_id)
+{
+	ffa_id_t current_vm_id = current->vm->id;
+
+	/*
+	 * The primary VM can send direct message request to
+	 * any other VM (but itself) or SP, but can't spoof
+	 * a different sender.
+	 */
+	return sender_vm_id != receiver_vm_id &&
+	       sender_vm_id == current_vm_id && vm_is_primary(current->vm);
+}
+
+bool plat_ffa_is_direct_request_supported(struct vm *sender_vm,
+					  struct vm *receiver_vm, uint32_t func)
+{
+	(void)sender_vm;
+	(void)receiver_vm;
+	(void)func;
+
+	/*
+	 * As Hypervisor is only meant to be used as a test artifact, allow
+	 * direct messaging for all VMs.
+	 */
+	return true;
+}
+
+/**
+ * Check validity of a FF-A direct message response.
+ */
+bool plat_ffa_is_direct_response_valid(struct vcpu *current,
+				       ffa_id_t sender_vm_id,
+				       ffa_id_t receiver_vm_id)
+{
+	ffa_id_t current_vm_id = current->vm->id;
+
+	/*
+	 * Secondary VMs can send direct message responses to
+	 * the PVM, but can't spoof a different sender.
+	 */
+	return sender_vm_id != receiver_vm_id &&
+	       sender_vm_id == current_vm_id &&
+	       receiver_vm_id == HF_PRIMARY_VM_ID;
+}
+
+bool plat_ffa_direct_request_forward(ffa_id_t receiver_vm_id,
+				     struct ffa_value args,
+				     struct ffa_value *ret)
+{
+	if (!plat_ffa_is_tee_enabled()) {
+		dlog_verbose("Not forwarding: ffa_tee_enabled is false\n");
+		return false;
+	}
+
+	/*
+	 * VM's requests should be forwarded to the SPMC, if receiver is an SP.
+	 */
+	if (vm_id_is_current_world(receiver_vm_id)) {
+		dlog_verbose(
+			"Not forwarding: receiver VM %#x is in the same "
+			"world\n",
+			receiver_vm_id);
+		return false;
+	}
+
+	switch (args.func) {
+	case FFA_MSG_SEND_DIRECT_REQ_32:
+	case FFA_MSG_SEND_DIRECT_REQ_64:
+		*ret = arch_other_world_call(args);
+		break;
+	case FFA_MSG_SEND_DIRECT_REQ2_64:
+		*ret = arch_other_world_call_ext(args);
+		break;
+	default:
+		panic("Invalid direct message function %#x\n", args.func);
+		break;
+	}
+
+	return true;
+}
+
+void plat_ffa_wind_call_chain_ffa_direct_req(
+	struct vcpu_locked current_locked,
+	struct vcpu_locked receiver_vcpu_locked, ffa_id_t sender_vm_id)
+{
+	/* Calls chains not supported in the Hypervisor/VMs. */
+	(void)current_locked;
+	(void)receiver_vcpu_locked;
+	(void)sender_vm_id;
+}
+
+void plat_ffa_unwind_call_chain_ffa_direct_resp(
+	struct vcpu_locked current_locked, struct vcpu_locked next_locked)
+{
+	/* Calls chains not supported in the Hypervisor/VMs. */
+	(void)current_locked;
+	(void)next_locked;
+}
diff --git a/src/arch/aarch64/plat/ffa/spmc.c b/src/arch/aarch64/plat/ffa/spmc.c
index 41abf27..f381332 100644
--- a/src/arch/aarch64/plat/ffa/spmc.c
+++ b/src/arch/aarch64/plat/ffa/spmc.c
@@ -10,8 +10,8 @@
 #include "hf/arch/gicv3.h"
 #include "hf/arch/host_timer.h"
 #include "hf/arch/mmu.h"
-#include "hf/arch/other_world.h"
 #include "hf/arch/plat/ffa.h"
+#include "hf/arch/std.h"
 #include "hf/arch/sve.h"
 #include "hf/arch/vmid_base.h"
 
@@ -25,15 +25,12 @@
 #include "hf/hf_ipi.h"
 #include "hf/interrupt_desc.h"
 #include "hf/plat/interrupts.h"
-#include "hf/std.h"
 #include "hf/timer_mgmt.h"
 #include "hf/vcpu.h"
 #include "hf/vm.h"
 
-#include "vmapi/hf/call.h"
 #include "vmapi/hf/ffa.h"
 
-#include "msr.h"
 #include "smc.h"
 #include "sysregs.h"
 
@@ -515,123 +512,6 @@
 	return (vm_id >= EL3_SPMD_LP_ID_START && vm_id <= EL3_SPMD_LP_ID_END);
 }
 
-/**
- * Check validity of a FF-A direct message request.
- */
-bool plat_ffa_is_direct_request_valid(struct vcpu *current,
-				      ffa_id_t sender_vm_id,
-				      ffa_id_t receiver_vm_id)
-{
-	ffa_id_t current_vm_id = current->vm->id;
-
-	/*
-	 * The normal world can send direct message requests
-	 * via the Hypervisor to any SP. Currently SPs can only send
-	 * direct messages to each other and not to the NWd.
-	 * SPMD Logical partitions can also send direct messages.
-	 */
-	return sender_vm_id != receiver_vm_id &&
-	       vm_id_is_current_world(receiver_vm_id) &&
-	       (sender_vm_id == current_vm_id ||
-		(current_vm_id == HF_HYPERVISOR_VM_ID &&
-		 (plat_ffa_is_spmd_lp_id(sender_vm_id) ||
-		  !vm_id_is_current_world(sender_vm_id))));
-}
-
-/**
- * Check that the receiver supports receipt of direct requests, and that the
- * sender supports sending direct messaging requests, in accordance to their
- * respective configurations at the partition's FF-A manifest.
- */
-bool plat_ffa_is_direct_request_supported(struct vm *sender_vm,
-					  struct vm *receiver_vm, uint32_t func)
-{
-	uint16_t sender_method;
-	uint16_t receiver_method;
-	enum ffa_version sender_ffa_version = sender_vm->ffa_version;
-	enum ffa_version receiver_ffa_version = receiver_vm->ffa_version;
-
-	/* Check if version supports messaging function. */
-	if (func == FFA_MSG_SEND_DIRECT_REQ2_64 &&
-	    sender_ffa_version < FFA_VERSION_1_2) {
-		dlog_verbose(
-			"Sender version does not allow usage of func id "
-			"0x%x.\n",
-			func);
-		return false;
-	}
-
-	if (func == FFA_MSG_SEND_DIRECT_REQ2_64 &&
-	    receiver_ffa_version < FFA_VERSION_1_2) {
-		dlog_verbose(
-			"Receiver version does not allow usage of func id "
-			"0x%x.\n",
-			func);
-		return false;
-	}
-
-	/*
-	 * Check if endpoint is configured to accept direct requests via given
-	 * method.
-	 */
-	sender_method = (func == FFA_MSG_SEND_DIRECT_REQ2_64)
-				? FFA_PARTITION_DIRECT_REQ2_SEND
-				: FFA_PARTITION_DIRECT_REQ_SEND;
-	receiver_method = (func == FFA_MSG_SEND_DIRECT_REQ2_64)
-				  ? FFA_PARTITION_DIRECT_REQ2_RECV
-				  : FFA_PARTITION_DIRECT_REQ_RECV;
-
-	if (!vm_supports_messaging_method(sender_vm, sender_method)) {
-		dlog_verbose(
-			"Sender can't send direct message requests via func id "
-			"0x%x.\n",
-			func);
-		return false;
-	}
-
-	if (!vm_supports_messaging_method(receiver_vm, receiver_method)) {
-		dlog_verbose(
-			"Receiver can't receive direct message requests via "
-			"func id 0x%x.\n",
-			func);
-		return false;
-	}
-
-	return true;
-}
-
-/**
- * Check validity of a FF-A direct message response.
- */
-bool plat_ffa_is_direct_response_valid(struct vcpu *current,
-				       ffa_id_t sender_vm_id,
-				       ffa_id_t receiver_vm_id)
-{
-	ffa_id_t current_vm_id = current->vm->id;
-
-	/*
-	 * Direct message responses emitted from a SP target either the NWd,
-	 * or EL3 SPMD logical partition or another SP.
-	 */
-	return sender_vm_id != receiver_vm_id &&
-	       sender_vm_id == current_vm_id &&
-	       vm_id_is_current_world(sender_vm_id);
-}
-
-bool plat_ffa_direct_request_forward(ffa_id_t receiver_vm_id,
-				     struct ffa_value args,
-				     struct ffa_value *ret)
-{
-	/*
-	 * SPs are not supposed to issue requests to VMs.
-	 */
-	(void)receiver_vm_id;
-	(void)args;
-	(void)ret;
-
-	return false;
-}
-
 bool plat_ffa_rx_release_forward(struct vm_locked vm_locked,
 				 struct ffa_value *ret)
 {
diff --git a/src/arch/aarch64/plat/ffa/spmc/direct_messaging.c b/src/arch/aarch64/plat/ffa/spmc/direct_messaging.c
new file mode 100644
index 0000000..d0a74f9
--- /dev/null
+++ b/src/arch/aarch64/plat/ffa/spmc/direct_messaging.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2024 The Hafnium Authors.
+ *
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file or at
+ * https://opensource.org/licenses/BSD-3-Clause.
+ */
+
+#include "hf/arch/plat/ffa/direct_messaging.h"
+
+#include "hf/arch/plat/ffa.h"
+
+#include "hf/vm.h"
+
+bool plat_ffa_is_direct_request_valid(struct vcpu *current,
+				      ffa_id_t sender_vm_id,
+				      ffa_id_t receiver_vm_id)
+{
+	ffa_id_t current_vm_id = current->vm->id;
+
+	/*
+	 * The normal world can send direct message requests
+	 * via the Hypervisor to any SP. Currently SPs can only send
+	 * direct messages to each other and not to the NWd.
+	 * SPMD Logical partitions can also send direct messages.
+	 */
+	return sender_vm_id != receiver_vm_id &&
+	       vm_id_is_current_world(receiver_vm_id) &&
+	       (sender_vm_id == current_vm_id ||
+		(current_vm_id == HF_HYPERVISOR_VM_ID &&
+		 (plat_ffa_is_spmd_lp_id(sender_vm_id) ||
+		  !vm_id_is_current_world(sender_vm_id))));
+}
+
+/**
+ * Check that the receiver supports receipt of direct requests, and that the
+ * sender supports sending direct messaging requests, in accordance to their
+ * respective configurations at the partition's FF-A manifest.
+ */
+bool plat_ffa_is_direct_request_supported(struct vm *sender_vm,
+					  struct vm *receiver_vm, uint32_t func)
+{
+	uint16_t sender_method;
+	uint16_t receiver_method;
+	enum ffa_version sender_ffa_version = sender_vm->ffa_version;
+	enum ffa_version receiver_ffa_version = receiver_vm->ffa_version;
+
+	/* Check if version supports messaging function. */
+	if (func == FFA_MSG_SEND_DIRECT_REQ2_64 &&
+	    sender_ffa_version < FFA_VERSION_1_2) {
+		dlog_verbose(
+			"Sender version does not allow usage of func id "
+			"0x%x.\n",
+			func);
+		return false;
+	}
+
+	if (func == FFA_MSG_SEND_DIRECT_REQ2_64 &&
+	    receiver_ffa_version < FFA_VERSION_1_2) {
+		dlog_verbose(
+			"Receiver version does not allow usage of func id "
+			"0x%x.\n",
+			func);
+		return false;
+	}
+
+	/*
+	 * Check if endpoint is configured to accept direct requests via given
+	 * method.
+	 */
+	sender_method = (func == FFA_MSG_SEND_DIRECT_REQ2_64)
+				? FFA_PARTITION_DIRECT_REQ2_SEND
+				: FFA_PARTITION_DIRECT_REQ_SEND;
+	receiver_method = (func == FFA_MSG_SEND_DIRECT_REQ2_64)
+				  ? FFA_PARTITION_DIRECT_REQ2_RECV
+				  : FFA_PARTITION_DIRECT_REQ_RECV;
+
+	if (!vm_supports_messaging_method(sender_vm, sender_method)) {
+		dlog_verbose(
+			"Sender can't send direct message requests via func id "
+			"0x%x.\n",
+			func);
+		return false;
+	}
+
+	if (!vm_supports_messaging_method(receiver_vm, receiver_method)) {
+		dlog_verbose(
+			"Receiver can't receive direct message requests via "
+			"func id 0x%x.\n",
+			func);
+		return false;
+	}
+
+	return true;
+}
+
+/** Check validity of a FF-A direct message response. */
+bool plat_ffa_is_direct_response_valid(struct vcpu *current,
+				       ffa_id_t sender_vm_id,
+				       ffa_id_t receiver_vm_id)
+{
+	ffa_id_t current_vm_id = current->vm->id;
+
+	/*
+	 * Direct message responses emitted from a SP target either the NWd,
+	 * or EL3 SPMD logical partition or another SP.
+	 */
+	return sender_vm_id != receiver_vm_id &&
+	       sender_vm_id == current_vm_id &&
+	       vm_id_is_current_world(sender_vm_id);
+}
+
+bool plat_ffa_direct_request_forward(ffa_id_t receiver_vm_id,
+				     struct ffa_value args,
+				     struct ffa_value *ret)
+{
+	/*
+	 * SPs are not supposed to issue requests to VMs.
+	 */
+	(void)receiver_vm_id;
+	(void)args;
+	(void)ret;
+
+	return false;
+}
diff --git a/src/load.c b/src/load.c
index 9968eb7..fc9007f 100644
--- a/src/load.c
+++ b/src/load.c
@@ -13,6 +13,7 @@
 #include "hf/arch/init.h"
 #include "hf/arch/other_world.h"
 #include "hf/arch/plat/ffa.h"
+#include "hf/arch/plat/ffa/direct_messaging.h"
 #include "hf/arch/vm.h"
 
 #include "hf/api.h"