feat(ff-a): allow ffa_run forwarding to secure world.

An ffa_run is needed when there are secondary secure parititions with
multiple execution contexts. Power management does not wake up those
execution contexts into their wait loops, so an ffa_run is necessary.
This is similar to the infrastructure tf-a-tests has to enable running
multiple secure partitions.

Signed-off-by: Raghu Krishnamurthy <raghu.ncstate@gmail.com>
Change-Id: I95e13040a42ab2833ec9267520cb1c099a7d41a1
diff --git a/src/api.c b/src/api.c
index 9d0a37b..d08e3f8 100644
--- a/src/api.c
+++ b/src/api.c
@@ -760,6 +760,10 @@
 		goto out;
 	}
 
+	if (plat_ffa_run_forward(vm_id, vcpu_idx, &ret)) {
+		return ret;
+	}
+
 	/* The requested VM must exist. */
 	vm = vm_find(vm_id);
 	if (vm == NULL) {
diff --git a/src/arch/aarch64/plat/ffa/absent.c b/src/arch/aarch64/plat/ffa/absent.c
index 9a43f72..999e169 100644
--- a/src/arch/aarch64/plat/ffa/absent.c
+++ b/src/arch/aarch64/plat/ffa/absent.c
@@ -132,3 +132,13 @@
 	(void)vm_id;
 	return false;
 }
+
+bool plat_ffa_run_forward(ffa_vm_id_t vm_id, ffa_vcpu_index_t vcpu_idx,
+			  struct ffa_value *ret)
+{
+	(void)vm_id;
+	(void)vcpu_idx;
+	(void)ret;
+
+	return false;
+}
diff --git a/src/arch/aarch64/plat/ffa/hypervisor.c b/src/arch/aarch64/plat/ffa/hypervisor.c
index de23811..2625954 100644
--- a/src/arch/aarch64/plat/ffa/hypervisor.c
+++ b/src/arch/aarch64/plat/ffa/hypervisor.c
@@ -90,6 +90,21 @@
 	dlog_verbose("TEE finished setting up buffers.\n");
 }
 
+bool plat_ffa_run_forward(ffa_vm_id_t vm_id, ffa_vcpu_index_t vcpu_idx,
+			  struct ffa_value *ret)
+{
+	/*
+	 * VM's requests should be forwarded to the SPMC, if target is an SP.
+	 */
+	if (!vm_id_is_current_world(vm_id)) {
+		*ret = arch_other_world_call((struct ffa_value){
+			.func = FFA_RUN_32, ffa_vm_vcpu(vm_id, vcpu_idx)});
+		return true;
+	}
+
+	return false;
+}
+
 /**
  * Check validity of a FF-A direct message request.
  */
diff --git a/src/arch/aarch64/plat/ffa/spmc.c b/src/arch/aarch64/plat/ffa/spmc.c
index 6358797..f382399 100644
--- a/src/arch/aarch64/plat/ffa/spmc.c
+++ b/src/arch/aarch64/plat/ffa/spmc.c
@@ -96,6 +96,16 @@
 	plat_ffa_vm_init();
 }
 
+bool plat_ffa_run_forward(ffa_vm_id_t vm_id, ffa_vcpu_index_t vcpu_idx,
+			  struct ffa_value *ret)
+{
+	(void)vm_id;
+	(void)vcpu_idx;
+	(void)ret;
+
+	return false;
+}
+
 /**
  * Check validity of a FF-A direct message request.
  */
diff --git a/src/arch/fake/hypervisor/ffa.c b/src/arch/fake/hypervisor/ffa.c
index 7b61f0b..d372636 100644
--- a/src/arch/fake/hypervisor/ffa.c
+++ b/src/arch/fake/hypervisor/ffa.c
@@ -43,6 +43,16 @@
 	return true;
 }
 
+bool plat_ffa_run_forward(ffa_vm_id_t vm_id, ffa_vcpu_index_t vcpu_idx,
+			  struct ffa_value *ret)
+{
+	(void)vm_id;
+	(void)vcpu_idx;
+	(void)ret;
+
+	return false;
+}
+
 bool plat_ffa_direct_request_forward(ffa_vm_id_t receiver_vm_id,
 				     struct ffa_value args,
 				     struct ffa_value *ret)