refactor: unify interrupt handlers
With the recent refactors the differences
between both S-EL1 and S-EL0 partitions handling
are reduced.
As such, unifying in a single handler which can be
unit tested.
Signed-off-by: J-Alves <joao.alves@arm.com>
Change-Id: Ia92e757f52c61fd75e62ae72af7232afd3db7031
diff --git a/src/ffa/spmc/interrupts.c b/src/ffa/spmc/interrupts.c
index 6fee9df..77f586e 100644
--- a/src/ffa/spmc/interrupts.c
+++ b/src/ffa/spmc/interrupts.c
@@ -130,10 +130,11 @@
struct vcpu *target_vcpu = target_vcpu_locked.vcpu;
struct vcpu *preempted_vcpu = current_locked.vcpu;
- if (preempted_vcpu != NULL) {
- target_vcpu->preempted_vcpu = preempted_vcpu;
- preempted_vcpu->state = VCPU_STATE_PREEMPTED;
- }
+ assert(target_vcpu != NULL);
+ assert(preempted_vcpu != NULL);
+
+ target_vcpu->preempted_vcpu = preempted_vcpu;
+ preempted_vcpu->state = VCPU_STATE_PREEMPTED;
}
/**
@@ -232,53 +233,14 @@
}
/**
- * Handles the secure interrupt according to the target vCPU's state
- * in the case the owner of the interrupt is an S-EL0 partition.
+ * Handles the secure interrupt according to the target vCPU's state.
+ * Returns the next vCPU to resume accordingly.
+ * If it returns NULL, the current vCPU shall be resumed.
+ * This might be if the target vCPU is the current vCPU, or if the
+ * target vCPU is not in a state in which it can be resumed to handle
+ * the secure interrupt.
*/
-static struct vcpu *ffa_interrupts_signal_secure_interrupt_sel0(
- struct vcpu_locked current_locked,
- struct vcpu_locked target_vcpu_locked, uint32_t v_intid)
-{
- struct vcpu *target_vcpu = target_vcpu_locked.vcpu;
- struct vcpu *next;
-
- /* Secure interrupt signaling and queuing for S-EL0 SP. */
- switch (target_vcpu->state) {
- case VCPU_STATE_WAITING:
-
- /* FF-A v1.1 EAC0 Table 8.1 case 1 and Table 12.10. */
- dlog_verbose("S-EL0: Secure interrupt signaled: %x\n",
- target_vcpu->vm->id);
-
- next = interrupt_resume_waiting(current_locked,
- target_vcpu_locked, v_intid);
- break;
- case VCPU_STATE_BLOCKED:
- case VCPU_STATE_PREEMPTED:
- case VCPU_STATE_RUNNING:
- dlog_verbose("S-EL0: Secure interrupt queued: %x\n",
- target_vcpu->vm->id);
- /*
- * The target vCPU cannot be resumed, SPMC resumes current
- * vCPU.
- */
- next = NULL;
- ffa_interrupts_set_preempted_vcpu(
- target_vcpu_locked, (struct vcpu_locked){.vcpu = NULL});
- break;
- default:
- panic("Secure interrupt cannot be signaled to target SP\n");
- break;
- }
-
- return next;
-}
-
-/**
- * Handles the secure interrupt according to the target vCPU's state
- * in the case the owner of the interrupt is an S-EL1 partition.
- */
-static struct vcpu *ffa_interrupts_signal_secure_interrupt_sel1(
+static struct vcpu *ffa_interrupts_signal_secure_interrupt(
struct vcpu_locked current_locked,
struct vcpu_locked target_vcpu_locked, uint32_t v_intid)
{
@@ -295,15 +257,15 @@
assert(target_vcpu->vm->vcpu_count == 1);
}
- /* Secure interrupt signaling and queuing for S-EL1 SP. */
+ /* Secure interrupt signaling and queuing for SP. */
switch (target_vcpu->state) {
case VCPU_STATE_WAITING:
next = interrupt_resume_waiting(current_locked,
target_vcpu_locked, v_intid);
break;
case VCPU_STATE_BLOCKED:
-
- if (target_vcpu->cpu == current_locked.vcpu->cpu &&
+ if (!target_vcpu->vm->el0_partition &&
+ target_vcpu->cpu == current_locked.vcpu->cpu &&
ffa_direct_msg_precedes_in_call_chain(current_locked,
target_vcpu_locked)) {
struct ffa_value ret_interrupt =
@@ -336,23 +298,22 @@
ffa_interrupts_set_preempted_vcpu(target_vcpu_locked,
current_locked);
next = target_vcpu;
- } else {
- /*
- * Either:
- * - The target vCPU has migrated to a different
- * physical CPU. Hence, it cannot be resumed on this
- * CPU, SPMC resumes current vCPU.
- * - The target vCPU cannot be resumed now because it is
- * in BLOCKED state (it yielded CPU cycles using
- * FFA_YIELD). SPMC queues the virtual interrupt and
- * resumes the current vCPU which could belong to either
- * a VM or a SP.
- */
- next = NULL;
- ffa_interrupts_set_preempted_vcpu(
- target_vcpu_locked,
- (struct vcpu_locked){.vcpu = NULL});
+ break;
}
+
+ /*
+ * `next` is NULL.
+ * Either:
+ * - EL0 paritition can't be resumed when in blocked state.
+ * - The target vCPU has migrated to a different
+ * physical CPU. Hence, it cannot be resumed on this
+ * CPU, SPMC resumes current vCPU.
+ * - The target vCPU cannot be resumed now because it is
+ * in BLOCKED state (it yielded CPU cycles using
+ * FFA_YIELD). SPMC queues the virtual interrupt and
+ * resumes the current vCPU which could belong to either
+ * a VM or a SP.
+ */
break;
case VCPU_STATE_PREEMPTED:
/*
@@ -362,7 +323,8 @@
* resume current vCPU. Refer to section 8.3.2.1 bullet
* 3 in the FF-A v1.1 EAC0 spec.
*/
- if (target_vcpu->cpu == current_locked.vcpu->cpu &&
+ if (!target_vcpu->vm->el0_partition &&
+ target_vcpu->cpu == current_locked.vcpu->cpu &&
current->vm->id == HF_OTHER_WORLD_ID) {
/*
* The target vCPU must have been preempted by a
@@ -377,16 +339,11 @@
*/
CHECK(target_vcpu->scheduling_mode == NWD_MODE);
}
-
- next = NULL;
- ffa_interrupts_set_preempted_vcpu(
- target_vcpu_locked, (struct vcpu_locked){.vcpu = NULL});
-
break;
case VCPU_STATE_RUNNING:
- next = NULL;
- ffa_interrupts_set_preempted_vcpu(
- target_vcpu_locked, (struct vcpu_locked){.vcpu = NULL});
+ /*
+ * Interrupt has been injected in the vCPU state.
+ */
break;
case VCPU_STATE_BLOCKED_INTERRUPT:
/* WFI is no-op for SP. Fall through. */
@@ -495,13 +452,8 @@
* Either invoke the handler related to partitions from
* S-EL0 or from S-EL1.
*/
- *next = target_vcpu_locked.vcpu->vm->el0_partition
- ? ffa_interrupts_signal_secure_interrupt_sel0(
- current_locked,
- target_vcpu_locked, v_intid)
- : ffa_interrupts_signal_secure_interrupt_sel1(
- current_locked,
- target_vcpu_locked, v_intid);
+ *next = ffa_interrupts_signal_secure_interrupt(
+ current_locked, target_vcpu_locked, v_intid);
}
}