fix: make the invocation of ffa_msg_wait v1.1 compliant

The invocation of FFA_MSG_WAIT at secure virtual FF-A instance is
made to be compliant with FF-A v1.1 EAC0 specification. It's
only use is to perform the state transition from RUNNING to WAITING
for the following Partition runtime models: RTM_FFA_RUN,
RTM_SEC_INTERRUPT, and RTM_SP_INIT.

However, the invocation of FFA_MSG_WAIT at non-secure virtual FF-A
instance is made to be compliant with the FF-A v1.0 spec for
legacy reasons.

Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
Change-Id: Ic63f07c9ce6e6c3be9df2a849900b30eb61fcf6d
diff --git a/src/api.c b/src/api.c
index 568d371..ae9bb68 100644
--- a/src/api.c
+++ b/src/api.c
@@ -692,7 +692,6 @@
 struct ffa_value api_ffa_msg_wait(struct vcpu *current, struct vcpu **next,
 				  struct ffa_value *args)
 {
-	struct ffa_value ret;
 	enum vcpu_state next_state = VCPU_STATE_WAITING;
 
 	if (args->arg1 != 0U || args->arg2 != 0U || args->arg3 != 0U ||
@@ -709,11 +708,7 @@
 
 	assert(next_state == VCPU_STATE_WAITING);
 
-	if (plat_ffa_msg_wait_prepare(current, next, &ret)) {
-		return ret;
-	}
-
-	return api_ffa_msg_recv(true, current, next);
+	return plat_ffa_msg_wait_prepare(current, next);
 }
 
 /**
diff --git a/src/arch/aarch64/plat/ffa/absent.c b/src/arch/aarch64/plat/ffa/absent.c
index bb8b9e8..43eb9b4 100644
--- a/src/arch/aarch64/plat/ffa/absent.c
+++ b/src/arch/aarch64/plat/ffa/absent.c
@@ -445,14 +445,13 @@
 	(void)ppool;
 }
 
-bool plat_ffa_msg_wait_prepare(struct vcpu *current, struct vcpu **next,
-			       struct ffa_value *ret_args)
+struct ffa_value plat_ffa_msg_wait_prepare(struct vcpu *current,
+					   struct vcpu **next)
 {
 	(void)current;
 	(void)next;
-	(void)ret_args;
 
-	return false;
+	return (struct ffa_value){.func = FFA_INTERRUPT_32};
 }
 
 bool plat_ffa_check_runtime_state_transition(struct vcpu *current,
diff --git a/src/arch/aarch64/plat/ffa/hypervisor.c b/src/arch/aarch64/plat/ffa/hypervisor.c
index 1668ac1..e7f9e94 100644
--- a/src/arch/aarch64/plat/ffa/hypervisor.c
+++ b/src/arch/aarch64/plat/ffa/hypervisor.c
@@ -11,6 +11,7 @@
 #include "hf/arch/other_world.h"
 #include "hf/arch/plat/ffa.h"
 
+#include "hf/api.h"
 #include "hf/dlog.h"
 #include "hf/ffa.h"
 #include "hf/ffa_internal.h"
@@ -933,14 +934,15 @@
 	return false;
 }
 
-bool plat_ffa_msg_wait_prepare(struct vcpu *current, struct vcpu **next,
-			       struct ffa_value *ret_args)
+/**
+ * The invocation of FFA_MSG_WAIT at non-secure virtual FF-A instance is made
+ * to be compliant with version v1.0 of the FF-A specification. It serves as
+ * a blocking call.
+ */
+struct ffa_value plat_ffa_msg_wait_prepare(struct vcpu *current,
+					   struct vcpu **next)
 {
-	(void)current;
-	(void)next;
-	(void)ret_args;
-
-	return false;
+	return api_ffa_msg_recv(true, current, next);
 }
 
 bool plat_ffa_check_runtime_state_transition(
diff --git a/src/arch/aarch64/plat/ffa/spmc.c b/src/arch/aarch64/plat/ffa/spmc.c
index 4a91e16..4747cf8 100644
--- a/src/arch/aarch64/plat/ffa/spmc.c
+++ b/src/arch/aarch64/plat/ffa/spmc.c
@@ -1937,19 +1937,29 @@
 	return ret;
 }
 
-bool plat_ffa_msg_wait_prepare(struct vcpu *current, struct vcpu **next,
-			       struct ffa_value *ret_args)
+/**
+ * The invocation of FFA_MSG_WAIT at secure virtual FF-A instance is compliant
+ * with FF-A v1.1 EAC0 specification. It only performs the  state transition
+ * from RUNNING to WAITING for the following Partition runtime models:
+ * RTM_FFA_RUN, RTM_SEC_INTERRUPT, RTM_SP_INIT.
+ */
+struct ffa_value plat_ffa_msg_wait_prepare(struct vcpu *current,
+					   struct vcpu **next)
 {
+	struct ffa_value ret_args =
+		(struct ffa_value){.func = FFA_INTERRUPT_32};
 	bool boot_order_complete = false;
 
 	if (sp_boot_next(current, next, &boot_order_complete)) {
-		*ret_args = (struct ffa_value){.func = FFA_INTERRUPT_32};
-		return true;
+		return ret_args;
 	}
 
 	/* All the SPs have been booted now. Return to NWd. */
 	if (boot_order_complete) {
-		return false;
+		*next = api_switch_to_other_world(
+			current, (struct ffa_value){.func = FFA_MSG_WAIT_32},
+			VCPU_STATE_WAITING);
+		return ret_args;
 	}
 
 	/* Refer FF-A v1.1 Beta0 section 7.4 bullet 2. */
@@ -1964,13 +1974,11 @@
 
 		/* Secure interrupt pre-empted normal world. */
 		if (current->preempted_vcpu->vm->id == HF_OTHER_WORLD_ID) {
-			*ret_args = plat_ffa_normal_world_resume(current, next);
-			return true;
+			return plat_ffa_normal_world_resume(current, next);
 		}
 
 		/* Secure interrupt pre-empted an SP. Resume it. */
-		*ret_args = plat_ffa_preempted_vcpu_resume(current, next);
-		return true;
+		return plat_ffa_preempted_vcpu_resume(current, next);
 	}
 
 	/*
@@ -1982,7 +1990,12 @@
 	current->rt_model = RTM_NONE;
 	sl_unlock(&current->lock);
 
-	return false;
+	/* Relinquish control back to the NWd. */
+	*next = api_switch_to_other_world(
+		current, (struct ffa_value){.func = FFA_MSG_WAIT_32},
+		VCPU_STATE_WAITING);
+
+	return ret_args;
 }
 
 struct vcpu *plat_ffa_unwind_nwd_call_chain_interrupt(struct vcpu *current_vcpu)
diff --git a/src/arch/fake/hypervisor/ffa.c b/src/arch/fake/hypervisor/ffa.c
index 0f45e3b..7515ebb 100644
--- a/src/arch/fake/hypervisor/ffa.c
+++ b/src/arch/fake/hypervisor/ffa.c
@@ -413,14 +413,14 @@
 {
 	return false;
 }
-bool plat_ffa_msg_wait_prepare(struct vcpu *current, struct vcpu **next,
-			       struct ffa_value *ret_args)
+
+struct ffa_value plat_ffa_msg_wait_prepare(struct vcpu *current,
+					   struct vcpu **next)
 {
 	(void)current;
 	(void)next;
-	(void)ret_args;
 
-	return false;
+	return (struct ffa_value){.func = FFA_INTERRUPT_32};
 }
 
 bool plat_ffa_check_runtime_state_transition(struct vcpu *current,