feat(interrupts): add support for handling managed exit through vIRQ

An SP could specify, through its partition manifest, that the
preferred signaling mechanism for it to handle managed exit is
vIRQ instead of the default choice (vFIQ).

Hence, separate the vIRQ and vFIQ handlers and add support for
identifying the source of the direct message request for the current
endpoint to send the managed exit response.

Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
Change-Id: I06d6d81232de58779f81f40d4c6d2a96df0da27a
diff --git a/spm/cactus/cactus_interrupt.c b/spm/cactus/cactus_interrupt.c
index e08c4dd..35fdf30 100644
--- a/spm/cactus/cactus_interrupt.c
+++ b/spm/cactus/cactus_interrupt.c
@@ -21,6 +21,7 @@
 extern void notification_pending_interrupt_handler(void);
 
 extern ffa_id_t g_ffa_id;
+extern ffa_id_t g_dir_req_source_id;
 static uint32_t managed_exit_interrupt_id;
 
 /* Secure virtual interrupt that was last handled by Cactus SP. */
@@ -44,45 +45,10 @@
 	     managed_exit_interrupt_id);
 }
 
-void cactus_interrupt_handler(void)
+static void post_interrupt_handler(uint32_t intid)
 {
-	uint32_t intid = spm_interrupt_get();
 	unsigned int core_pos = get_current_core_id();
 
-	switch (intid) {
-	case MANAGED_EXIT_INTERRUPT_ID:
-		/*
-		 * A secure partition performs its housekeeping and sends a
-		 * direct response to signal interrupt completion.
-		 * This is a pure virtual interrupt, no need for deactivation.
-		 */
-		cactus_response(g_ffa_id, HYP_ID, MANAGED_EXIT_INTERRUPT_ID);
-		break;
-	case IRQ_TWDOG_INTID:
-		/*
-		 * Interrupt triggered due to Trusted watchdog timer expiry.
-		 * Clear the interrupt and stop the timer.
-		 */
-		VERBOSE("Trusted WatchDog timer stopped\n");
-		sp805_twdog_stop();
-
-		/* Perform secure interrupt de-activation. */
-		spm_interrupt_deactivate(intid);
-
-		break;
-	case NOTIFICATION_PENDING_INTERRUPT_INTID:
-		notification_pending_interrupt_handler();
-		break;
-	default:
-		/*
-		 * Currently the only source of secure interrupt is Trusted
-		 * Watchdog timer.
-		 */
-		ERROR("%s: Interrupt ID %x not handled!\n", __func__,
-			 intid);
-		panic();
-	}
-
 	last_serviced_interrupt[core_pos] = intid;
 
 	/* Invoke the tail end handler registered by the SP. */
@@ -92,3 +58,71 @@
 	}
 	spin_unlock(&sp_handler_lock[intid]);
 }
+
+void cactus_interrupt_handler_irq(void)
+{
+	uint32_t intid = spm_interrupt_get();
+
+	if (intid == managed_exit_interrupt_id) {
+		/*
+		 * A secure partition performs its housekeeping and
+		 * sends a direct response to signal interrupt
+		 * completion. This is a pure virtual interrupt, no
+		 * need for deactivation.
+		 */
+		VERBOSE("vIRQ: Sending ME response to %x\n",
+			g_dir_req_source_id);
+		cactus_response(g_ffa_id, g_dir_req_source_id,
+				managed_exit_interrupt_id);
+	} else {
+		switch (intid) {
+		case IRQ_TWDOG_INTID:
+			/*
+			 * Interrupt triggered due to Trusted watchdog timer expiry.
+			 * Clear the interrupt and stop the timer.
+			 */
+			VERBOSE("Trusted WatchDog timer stopped\n");
+			sp805_twdog_stop();
+
+			/* Perform secure interrupt de-activation. */
+			spm_interrupt_deactivate(intid);
+
+			break;
+		case NOTIFICATION_PENDING_INTERRUPT_INTID:
+			notification_pending_interrupt_handler();
+			break;
+		default:
+			ERROR("%s: Interrupt ID %x not handled!\n", __func__,
+				 intid);
+			panic();
+			break;
+		}
+	}
+	post_interrupt_handler(intid);
+}
+
+void cactus_interrupt_handler_fiq(void)
+{
+	uint32_t intid = spm_interrupt_get();
+
+	switch (intid) {
+	case MANAGED_EXIT_INTERRUPT_ID:
+		/*
+		 * A secure partition performs its housekeeping and sends a
+		 * direct response to signal interrupt completion.
+		 * This is a pure virtual interrupt, no need for deactivation.
+		 */
+		VERBOSE("vFIQ: Sending ME response to %x\n",
+			g_dir_req_source_id);
+		cactus_response(g_ffa_id, g_dir_req_source_id,
+				MANAGED_EXIT_INTERRUPT_ID);
+		break;
+	default:
+		/*
+		 * Currently only managed exit interrupt is supported by vFIQ.
+		 */
+		panic();
+		break;
+	}
+	post_interrupt_handler(intid);
+}