feat(interrupts): SRI triggered when SP back to wait
Implement the action to trigger SRI when SP goes into
waiting state while there are pending interrupts.
Signed-off-by: J-Alves <joao.alves@arm.com>
Change-Id: Ie983e8d22355a51e55dde0089ac6330982bb89a1
diff --git a/src/api.c b/src/api.c
index 494cfef..c39e3fb 100644
--- a/src/api.c
+++ b/src/api.c
@@ -3161,9 +3161,10 @@
next_locked);
/*
- * Check if there is a pending secure interrupt.
- * If there is, return back to the caller with FFA_INTERRUPT,
- * and set the `next` vcpu in a preempted state.
+ * Check if there is a pending interrupt, and if the partition
+ * is expects to notify the scheduler or resume straight away.
+ * Either trigger SRI for later donation of CPU cycles, or
+ * eret `FFA_INTERRUPT` back to the caller.
*/
if (ffa_interrupts_intercept_call(current_locked, next_locked,
&signal_interrupt)) {
diff --git a/src/ffa/spmc/cpu_cycles.c b/src/ffa/spmc/cpu_cycles.c
index 0780260..13e8555 100644
--- a/src/ffa/spmc/cpu_cycles.c
+++ b/src/ffa/spmc/cpu_cycles.c
@@ -265,10 +265,10 @@
both_vcpu_locks = vcpu_lock_both(current, *next);
/*
- * Check if there are any pending secure virtual interrupts to
- * be handled. The `next` should have a pointer to the current
- * vCPU. Intercept call will set `ret` to FFA_INTERRUPT and the
- * respective interrupt id.
+ * Check if there is a pending interrupt, and if the partition
+ * is expects to notify the scheduler or resume straight away.
+ * Either trigger SRI for later donation of CPU cycles, or
+ * eret `FFA_INTERRUPT` back to the caller.
*/
if (ffa_interrupts_intercept_call(both_vcpu_locks.vcpu1,
both_vcpu_locks.vcpu2, ffa_ret)) {
diff --git a/src/ffa/spmc/interrupts.c b/src/ffa/spmc/interrupts.c
index 724ed53..ded866a 100644
--- a/src/ffa/spmc/interrupts.c
+++ b/src/ffa/spmc/interrupts.c
@@ -752,45 +752,60 @@
struct vcpu_locked next_locked,
struct ffa_value *signal_interrupt)
{
+ uint32_t intid;
+ struct vm *current_vm = current_locked.vcpu->vm;
+
+ /* No pending interrupts, no need to intercept or trigger SRI. */
+ if (vcpu_virt_interrupt_count_get(current_locked) == 0U) {
+ return false;
+ }
+
+ /*
+ * Do not intercept the call.
+ * Let the partition go into waiting state as planned.
+ * Pend the SRI on the next world switch to the NWd.
+ */
+ if (current_vm->sri_policy.intr_pending_entry_wait) {
+ dlog_verbose(
+ "Partition entry to wait. Interrupts pending. Send "
+ "SRI.\n");
+ ffa_notifications_sri_set_delayed(current_locked.vcpu->cpu);
+ return false;
+ }
+
/*
* Since S-EL0 partitions will not receive the interrupt through a vIRQ
* signal in addition to the FFA_INTERRUPT ERET, make the interrupt no
* longer pending at this point. Otherwise keep it as pending for
* when the S-EL1 parition calls hf_interrupt_get.
*/
- uint32_t intid = current_locked.vcpu->vm->el0_partition
- ? vcpu_virt_interrupt_get_pending_and_enabled(
- current_locked)
- : vcpu_virt_interrupt_peek_pending_and_enabled(
- current_locked);
+ intid = current_locked.vcpu->vm->el0_partition
+ ? vcpu_virt_interrupt_get_pending_and_enabled(
+ current_locked)
+ : vcpu_virt_interrupt_peek_pending_and_enabled(
+ current_locked);
/*
- * Check if there are any pending virtual secure interrupts to be
- * handled.
+ * At this point there are interrupts pending, and the partition
+ * didn't configure an SRI policy for handling interrupts.
+ *
+ * Prepare to signal virtual secure interrupt to S-EL0/S-EL1 SP
+ * in WAITING state. Refer to FF-A v1.2 Table 9.1 and Table 9.2
+ * case 1.
*/
- if (intid != HF_INVALID_INTID) {
- /*
- * Prepare to signal virtual secure interrupt to S-EL0/S-EL1 SP
- * in WAITING state. Refer to FF-A v1.2 Table 9.1 and Table 9.2
- * case 1.
- */
- *signal_interrupt = api_ffa_interrupt_return(intid);
+ *signal_interrupt = api_ffa_interrupt_return(intid);
- /*
- * Prepare to resume this partition's vCPU in SPMC
- * schedule mode to handle virtual secure interrupt.
- */
- ffa_interrupts_run_in_sec_interrupt_rtm(current_locked);
+ /*
+ * Prepare to resume this partition's vCPU in SPMC
+ * schedule mode to handle virtual secure interrupt.
+ */
+ ffa_interrupts_run_in_sec_interrupt_rtm(current_locked);
- current_locked.vcpu->preempted_vcpu = next_locked.vcpu;
- next_locked.vcpu->state = VCPU_STATE_PREEMPTED;
+ current_locked.vcpu->preempted_vcpu = next_locked.vcpu;
+ next_locked.vcpu->state = VCPU_STATE_PREEMPTED;
- dlog_verbose(
- "%s: Pending interrupt %d, intercepting FF-A call.\n",
- __func__, intid);
+ dlog_verbose("%s: Pending interrupt %d, intercepting FF-A call.\n",
+ __func__, intid);
- return true;
- }
-
- return false;
+ return true;
}