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;
 }