FF-A: Direct Messaging from VMs to SPs

Hypervisor forward direct request from a VM, to the SWd if receiver is
 an SP.

Change-Id: Id2a2142ddc8c13c8e371347308c78c8a1ebc0b4a
Signed-off-by: J-Alves <joao.alves@arm.com>
diff --git a/src/api.c b/src/api.c
index 70df9f7..9510042 100644
--- a/src/api.c
+++ b/src/api.c
@@ -1757,7 +1757,7 @@
 					     struct vcpu *current,
 					     struct vcpu **next)
 {
-	struct ffa_value ret = (struct ffa_value){.func = FFA_INTERRUPT_32};
+	struct ffa_value ret;
 	struct vm *receiver_vm;
 	struct vcpu *receiver_vcpu;
 	struct two_vcpu_locked vcpus_locked;
@@ -1771,6 +1771,13 @@
 		return ffa_error(FFA_INVALID_PARAMETERS);
 	}
 
+	if (arch_other_world_direct_request_forward(receiver_vm_id, args,
+						    &ret)) {
+		return ret;
+	}
+
+	ret = (struct ffa_value){.func = FFA_INTERRUPT_32};
+
 	receiver_vm = vm_find(receiver_vm_id);
 	if (receiver_vm == NULL) {
 		return ffa_error(FFA_INVALID_PARAMETERS);
diff --git a/src/arch/aarch64/hypervisor/other_world.c b/src/arch/aarch64/hypervisor/other_world.c
index a3fa12b..2e1aebc 100644
--- a/src/arch/aarch64/hypervisor/other_world.c
+++ b/src/arch/aarch64/hypervisor/other_world.c
@@ -193,6 +193,31 @@
 	return false;
 }
 
+bool arch_other_world_direct_request_forward(ffa_vm_id_t receiver_vm_id,
+					     struct ffa_value args,
+					     struct ffa_value *ret)
+{
+#if SECURE_WORLD == 1
+	/*
+	 * SPs are not supposed to issue requests to VMs.
+	 */
+	(void)receiver_vm_id;
+	(void)args;
+	(void)ret;
+
+#else
+	/*
+	 * VM's requests should be forwarded to the SPMC, if receiver is an SP.
+	 */
+	if (!vm_id_is_current_world(receiver_vm_id)) {
+		*ret = arch_other_world_call(args);
+		return true;
+	}
+#endif
+
+	return false;
+}
+
 struct ffa_value arch_other_world_call(struct ffa_value args)
 {
 	return smc_ffa_call(args);
diff --git a/src/arch/fake/hypervisor/other_world.c b/src/arch/fake/hypervisor/other_world.c
index ebddb41..ddba66a 100644
--- a/src/arch/fake/hypervisor/other_world.c
+++ b/src/arch/fake/hypervisor/other_world.c
@@ -44,3 +44,13 @@
 
 	return true;
 }
+
+bool arch_other_world_direct_request_forward(ffa_vm_id_t receiver_vm_id,
+					     struct ffa_value args,
+					     struct ffa_value *ret)
+{
+	(void)receiver_vm_id;
+	(void)args;
+	(void)ret;
+	return false;
+}