test: exercise secure espi interrupt handling

Hafnium/SPMC added support for enabling interrupts in the extended SPI
range. With the help of an SiP SMC call that can pend an interrupt,
this patch adds a test to trigger an espi interrupt when cactus is
running and ensure it is handled.

Additionally, a dummy device region node representing a fake
peripheral has been added to the Cactus SP manifest. It is used to
specify properties of the interrupt in the extended SPI range used
for the above test scenario.

Signed-off-by: Raghu Krishnamurthy <raghu.ncstate@gmail.com>
Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
Change-Id: Ief932c40e3abd33d619f2b144e61cae449147b27
diff --git a/spm/cactus/cactus_tests/cactus_test_interrupts.c b/spm/cactus/cactus_tests/cactus_test_interrupts.c
index efe2260..6a1092b 100644
--- a/spm/cactus/cactus_tests/cactus_test_interrupts.c
+++ b/spm/cactus/cactus_tests/cactus_test_interrupts.c
@@ -12,11 +12,13 @@
 #include "cactus_message_loop.h"
 #include "cactus_test_cmds.h"
 
+#include <mmio.h>
 #include <platform.h>
 
 /* Secure virtual interrupt that was last handled by Cactus SP. */
 extern uint32_t last_serviced_interrupt[PLATFORM_CORE_COUNT];
 static int flag_set;
+static volatile bool test_espi_handled;
 
 static void handle_sec_wdog_interrupt(void)
 {
@@ -227,3 +229,43 @@
 			       ffa_dir_msg_source(*args),
 			       last_serviced_interrupt[core_pos]);
 }
+
+static void sec_interrupt_test_espi_handled(void)
+{
+	expect(test_espi_handled, false);
+	test_espi_handled = true;
+	NOTICE("Interrupt handler for test espi interrupt called\n");
+
+	/* Perform secure interrupt de-activation. */
+	spm_interrupt_deactivate(IRQ_ESPI_TEST_INTID);
+}
+
+CACTUS_CMD_HANDLER(trigger_espi_cmd, CACTUS_TRIGGER_ESPI_CMD)
+{
+	uint32_t espi_id = cactus_get_espi_id(*args);
+
+	/*
+	 * The SiP function ID 0x82000100 must have been added to the SMC
+	 * whitelist of the Cactus SP that invokes it.
+	 */
+	smc_args plat_sip_call = {
+			.fid = 0x82000100,
+			.arg1 = espi_id,
+	};
+	smc_ret_values ret;
+
+	sp_register_interrupt_handler(sec_interrupt_test_espi_handled,
+				      espi_id);
+	ret = tftf_smc(&plat_sip_call);
+
+	if (ret.ret0 == SMC_UNKNOWN) {
+		ERROR("SiP SMC call not supported\n");
+		return cactus_error_resp(ffa_dir_msg_dest(*args),
+				ffa_dir_msg_source(*args),
+				CACTUS_ERROR_TEST);
+	}
+
+	return cactus_response(ffa_dir_msg_dest(*args),
+			       ffa_dir_msg_source(*args),
+			       test_espi_handled ? 1 : 0);
+}
diff --git a/spm/cactus/plat/arm/fvp/fdts/cactus.dts b/spm/cactus/plat/arm/fvp/fdts/cactus.dts
index 4d27c9c..ed4eb6d 100644
--- a/spm/cactus/plat/arm/fvp/fdts/cactus.dts
+++ b/spm/cactus/plat/arm/fvp/fdts/cactus.dts
@@ -120,5 +120,19 @@
 			attributes = <0x3>; /* read-write */
 			interrupts = <56 0x900>;
 		};
+
+		espi_test_node {
+			/*
+			 * A dummy device region node representing a fake
+			 * peripheral. Explicitly used to specify properties of
+			 * interrupt 5000, in the extended SPI range, used for
+			 * testing purposes. All the properties below except
+			 * `interrupts` are irrelevant.
+			 */
+			base-address = <0x00000000 0x1c130000>;
+			pages-count = <1>; /* One 4KB page */
+			attributes = <0x1>; /* read-only */
+			interrupts = <5000 0x900>;
+		};
 	};
 };
diff --git a/spm/common/sp_helpers.h b/spm/common/sp_helpers.h
index 629801e..a82924b 100644
--- a/spm/common/sp_helpers.h
+++ b/spm/common/sp_helpers.h
@@ -12,8 +12,11 @@
 #include <spm_common.h>
 #include <spinlock.h>
 
-/* Currently, Hafnium/SPM supports 1024 virtual interrupt IDs. */
-#define NUM_VINT_ID	1024
+/*
+ * Use extended SPI interrupt ID range, hafnium/SPMC maps virtual interrupts
+ * to physical interrupts 1 to 1.
+ */
+#define NUM_VINT_ID	5120
 
 typedef struct {
 	u_register_t fid;