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(¤t_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(¤t_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;
+}