refactor(interrupts): cleanup secure interrupt handling code

This patch ensures most of the secure interrupt handling is limited
to the plat/ffa/spmc.c module.

Change-Id: I0a58c709bca56e5fa9c97983e2f5270052be3a8f
Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
diff --git a/src/api.c b/src/api.c
index b1ae667..b232a1a 100644
--- a/src/api.c
+++ b/src/api.c
@@ -684,6 +684,24 @@
 	}
 }
 
+struct ffa_value api_ffa_msg_wait(struct vcpu *current, struct vcpu **next,
+				  struct ffa_value *args)
+{
+	struct ffa_value ret;
+
+	if (args->arg1 != 0U || args->arg2 != 0U || args->arg3 != 0U ||
+	    args->arg4 != 0U || args->arg5 != 0U || args->arg6 != 0U ||
+	    args->arg7 != 0U) {
+		return ffa_error(FFA_INVALID_PARAMETERS);
+	}
+
+	if (plat_ffa_msg_wait_prepare(current, next, &ret)) {
+		return ret;
+	}
+
+	return api_ffa_msg_recv(true, current, next);
+}
+
 /**
  * Prepares the vCPU to run by updating its state and fetching whether a return
  * value needs to be forced onto the vCPU.
diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
index c71894d..cd64d68 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -322,54 +322,6 @@
 
 #if SECURE_WORLD == 1
 
-static bool sp_boot_next(struct vcpu *current, struct vcpu **next,
-			 struct ffa_value *ffa_ret)
-{
-	struct vm_locked current_vm_locked;
-	struct vm *vm_next = NULL;
-	bool ret = false;
-
-	/*
-	 * If VM hasn't been initialized, initialize it and traverse
-	 * booting list following "next_boot" field in the VM structure.
-	 * Once all the SPs have been booted (when "next_boot" is NULL),
-	 * return execution to the NWd.
-	 */
-	current_vm_locked = vm_lock(current->vm);
-	if (current_vm_locked.vm->initialized == false) {
-		current_vm_locked.vm->initialized = true;
-		current->is_bootstrapped = true;
-		dlog_verbose("Initialized VM: %#x, boot_order: %u\n",
-			     current_vm_locked.vm->id,
-			     current_vm_locked.vm->boot_order);
-
-		if (current_vm_locked.vm->next_boot != NULL) {
-			/* Refer FF-A v1.1 Beta0 section 7.5 Rule 2. */
-			current->state = VCPU_STATE_WAITING;
-			vm_next = current_vm_locked.vm->next_boot;
-			CHECK(vm_next->initialized == false);
-			*next = vm_get_vcpu(vm_next, vcpu_index(current));
-			arch_regs_reset(*next);
-			(*next)->cpu = current->cpu;
-			(*next)->state = VCPU_STATE_RUNNING;
-			(*next)->regs_available = false;
-
-			/* Set the designated GP register with the vCPU ID. */
-			vcpu_set_phys_core_idx(*next);
-
-			*ffa_ret = (struct ffa_value){.func = FFA_INTERRUPT_32};
-			ret = true;
-			goto out;
-		}
-
-		dlog_verbose("Finished initializing all VMs.\n");
-	}
-
-out:
-	vm_unlock(&current_vm_locked);
-	return ret;
-}
-
 /**
  * Handle special direct messages from SPMD to SPMC. For now related to power
  * management only.
@@ -565,45 +517,7 @@
 					 current, next);
 		return true;
 	case FFA_MSG_WAIT_32:
-		if (args->arg1 != 0U || args->arg2 != 0U || args->arg3 != 0U ||
-		    args->arg4 != 0U || args->arg5 != 0U || args->arg6 != 0U ||
-		    args->arg7 != 0U) {
-			*args = ffa_error(FFA_INVALID_PARAMETERS);
-			return true;
-		}
-#if SECURE_WORLD == 1
-		if (sp_boot_next(current, next, args)) {
-			return true;
-		}
-
-		/* Refer FF-A v1.1 Beta0 section 7.4 bullet 2. */
-		if (current->processing_secure_interrupt) {
-			CHECK(current->state == VCPU_STATE_WAITING);
-
-			/*
-			 * This flag should not have been set by SPMC when it
-			 * signaled the virtual interrupt to the SP while SP was
-			 * in WAITING or BLOCKED states. Refer the embedded
-			 * comment in vcpu.h file for further description.
-			 */
-			assert(!current->implicit_completion_signal);
-
-			/* Secure interrupt pre-empted normal world. */
-			if (current->preempted_vcpu->vm->id ==
-			    HF_OTHER_WORLD_ID) {
-				*args = plat_ffa_normal_world_resume(current,
-								     next);
-			} else {
-				/*
-				 * Secure interrupt pre-empted an SP. Resume it.
-				 */
-				*args = plat_ffa_preempted_vcpu_resume(current,
-								       next);
-			}
-			return true;
-		}
-#endif
-		*args = api_ffa_msg_recv(true, current, next);
+		*args = api_ffa_msg_wait(current, next, args);
 		return true;
 	case FFA_MSG_POLL_32:
 		*args = api_ffa_msg_recv(false, current, next);
diff --git a/src/arch/aarch64/plat/ffa/absent.c b/src/arch/aarch64/plat/ffa/absent.c
index fe053d1..8c0c27b 100644
--- a/src/arch/aarch64/plat/ffa/absent.c
+++ b/src/arch/aarch64/plat/ffa/absent.c
@@ -358,3 +358,13 @@
 	(void)manifest_vm;
 	(void)ppool;
 }
+
+bool plat_ffa_msg_wait_prepare(struct vcpu *current, struct vcpu **next,
+			       struct ffa_value *ret_args)
+{
+	(void)current;
+	(void)next;
+	(void)ret_args;
+
+	return false;
+}
diff --git a/src/arch/aarch64/plat/ffa/hypervisor.c b/src/arch/aarch64/plat/ffa/hypervisor.c
index f8dccfd..1e6cdf1 100644
--- a/src/arch/aarch64/plat/ffa/hypervisor.c
+++ b/src/arch/aarch64/plat/ffa/hypervisor.c
@@ -726,3 +726,13 @@
 {
 	return false;
 }
+
+bool plat_ffa_msg_wait_prepare(struct vcpu *current, struct vcpu **next,
+			       struct ffa_value *ret_args)
+{
+	(void)current;
+	(void)next;
+	(void)ret_args;
+
+	return false;
+}
diff --git a/src/arch/aarch64/plat/ffa/spmc.c b/src/arch/aarch64/plat/ffa/spmc.c
index 07f3266..e93e401 100644
--- a/src/arch/aarch64/plat/ffa/spmc.c
+++ b/src/arch/aarch64/plat/ffa/spmc.c
@@ -1389,3 +1389,80 @@
 {
 	return true;
 }
+
+static bool sp_boot_next(struct vcpu *current, struct vcpu **next)
+{
+	struct vm_locked current_vm_locked;
+	struct vm *vm_next = NULL;
+	bool ret = false;
+
+	/*
+	 * If VM hasn't been initialized, initialize it and traverse
+	 * booting list following "next_boot" field in the VM structure.
+	 * Once all the SPs have been booted (when "next_boot" is NULL),
+	 * return execution to the NWd.
+	 */
+	current_vm_locked = vm_lock(current->vm);
+	if (current_vm_locked.vm->initialized == false) {
+		current_vm_locked.vm->initialized = true;
+		current->is_bootstrapped = true;
+		dlog_verbose("Initialized VM: %#x, boot_order: %u\n",
+			     current_vm_locked.vm->id,
+			     current_vm_locked.vm->boot_order);
+
+		if (current_vm_locked.vm->next_boot != NULL) {
+			/* Refer FF-A v1.1 Beta0 section 7.5 Rule 2. */
+			current->state = VCPU_STATE_WAITING;
+			vm_next = current_vm_locked.vm->next_boot;
+			CHECK(vm_next->initialized == false);
+			*next = vm_get_vcpu(vm_next, vcpu_index(current));
+			arch_regs_reset(*next);
+			(*next)->cpu = current->cpu;
+			(*next)->state = VCPU_STATE_RUNNING;
+			(*next)->regs_available = false;
+
+			ret = true;
+			goto out;
+		}
+
+		dlog_verbose("Finished initializing all VMs.\n");
+	}
+
+out:
+	vm_unlock(&current_vm_locked);
+	return ret;
+}
+
+bool plat_ffa_msg_wait_prepare(struct vcpu *current, struct vcpu **next,
+			       struct ffa_value *ret_args)
+{
+	if (sp_boot_next(current, next)) {
+		*ret_args = (struct ffa_value){.func = FFA_INTERRUPT_32};
+		return true;
+	}
+
+	/* Refer FF-A v1.1 Beta0 section 7.4 bullet 2. */
+	if (current->processing_secure_interrupt) {
+		CHECK(current->state == VCPU_STATE_WAITING);
+
+		/*
+		 * This flag should not have been set by SPMC when it signaled
+		 * the virtual interrupt to the SP while SP was in WAITING or
+		 * BLOCKED states. Refer the embedded comment in vcpu.h file
+		 * for further description.
+		 */
+		assert(!current->implicit_completion_signal);
+
+		/* 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;
+		}
+
+		/* Secure interrupt pre-empted an SP. Resume it. */
+		*ret_args = plat_ffa_preempted_vcpu_resume(current, next);
+		return true;
+	}
+
+	return false;
+}
diff --git a/src/arch/fake/hypervisor/ffa.c b/src/arch/fake/hypervisor/ffa.c
index 9300963..efd270b 100644
--- a/src/arch/fake/hypervisor/ffa.c
+++ b/src/arch/fake/hypervisor/ffa.c
@@ -333,3 +333,12 @@
 {
 	return false;
 }
+bool plat_ffa_msg_wait_prepare(struct vcpu *current, struct vcpu **next,
+			       struct ffa_value *ret_args)
+{
+	(void)current;
+	(void)next;
+	(void)ret_args;
+
+	return false;
+}