Merge "test: exercise secure espi interrupt handling"
diff --git a/include/runtime_services/cactus_test_cmds.h b/include/runtime_services/cactus_test_cmds.h
index a12a588..5f3d0d2 100644
--- a/include/runtime_services/cactus_test_cmds.h
+++ b/include/runtime_services/cactus_test_cmds.h
@@ -604,4 +604,23 @@
return cactus_send_cmd(source, dest, CACTUS_RESUME_AFTER_MANAGED_EXIT,
0, 0, 0, 0);
}
+
+/**
+ * Request SP to pend an interrupt in the extended SPI range.
+ *
+ * The command is the hex representation of the string "espi".
+ */
+#define CACTUS_TRIGGER_ESPI_CMD U(0x65737069)
+static inline struct ffa_value cactus_trigger_espi_cmd(
+ ffa_id_t source, ffa_id_t dest, uint32_t espi_id)
+{
+ return cactus_send_cmd(source, dest, CACTUS_TRIGGER_ESPI_CMD,
+ espi_id, 0, 0, 0);
+}
+
+static inline uint32_t cactus_get_espi_id(struct ffa_value ret)
+{
+ return (uint32_t)ret.arg4;
+}
+
#endif
diff --git a/include/runtime_services/spm_common.h b/include/runtime_services/spm_common.h
index 9e7f1e6..48471bc 100644
--- a/include/runtime_services/spm_common.h
+++ b/include/runtime_services/spm_common.h
@@ -30,6 +30,9 @@
/* INTID for the notification pending interrupt. */
#define NOTIFICATION_PENDING_INTERRUPT_INTID 5
+/* Interrupt used for testing extended SPI handling. */
+#define IRQ_ESPI_TEST_INTID 5000
+
/** IRQ/FIQ pin used for signaling a virtual interrupt. */
enum interrupt_pin {
INTERRUPT_TYPE_IRQ,
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;
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_secure_interrupts.c b/tftf/tests/runtime_services/secure_service/test_ffa_secure_interrupts.c
index 336faf9..3f746f4 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_secure_interrupts.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_secure_interrupts.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,6 +7,8 @@
#include <cactus_test_cmds.h>
#include <ffa_endpoints.h>
#include <ffa_helpers.h>
+#include <mmio.h>
+#include <spm_common.h>
#include <spm_test_helpers.h>
#include <test_helpers.h>
#include <timer.h>
@@ -424,3 +426,86 @@
return TEST_RESULT_SUCCESS;
}
+
+/*
+ * @Test_Aim@ Test handling of interrupt belonging to the extended SPI range
+ * while first Secure Partition is in RUNNING state.
+ *
+ * 1. Send a direct message request command to first Cactus SP to trigger the
+ * eSPI interrupt.
+ *
+ * 2. The Cactus SP either successfully handles the interrupt or fails to do
+ * so. It sends a value through direct message response indicating if the
+ * interrupt was handled.
+ *
+ * 3. TFTF sends a direct request message to SP to query the ID of last serviced
+ * secure virtual interrupt.
+ *
+ * 4. Further, TFTF expects SP to return the appropriate interrupt id through a
+ * direct response message.
+ */
+test_result_t test_ffa_espi_sec_interrupt(void)
+{
+ struct ffa_value ret_values;
+
+ CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids);
+
+ /* Enable ESPI. */
+ ret_values = cactus_interrupt_cmd(SENDER, RECEIVER, IRQ_ESPI_TEST_INTID,
+ true, INTERRUPT_TYPE_IRQ);
+
+ if (!is_ffa_direct_response(ret_values)) {
+ ERROR("Expected a direct response message while configuring"
+ " interrupt ESPI %u\n", IRQ_ESPI_TEST_INTID);
+ return TEST_RESULT_FAIL;
+ }
+
+ if (cactus_get_response(ret_values) != CACTUS_SUCCESS) {
+ ERROR("Failed to configure ESPI interrupt\n");
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Trigger ESPI while running. */
+ ret_values = cactus_trigger_espi_cmd(SENDER, RECEIVER, IRQ_ESPI_TEST_INTID);
+ if (!is_ffa_direct_response(ret_values)) {
+ ERROR("Expected a direct response message while triggering"
+ " interrupt ESPI %u\n", IRQ_ESPI_TEST_INTID);
+ return TEST_RESULT_FAIL;
+ }
+
+ if (cactus_get_response(ret_values) != 1) {
+ ERROR("Interrupt %u not serviced by SP\n", IRQ_ESPI_TEST_INTID);
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Disable ESPI. */
+ ret_values = cactus_interrupt_cmd(SENDER, RECEIVER, IRQ_ESPI_TEST_INTID,
+ false, INTERRUPT_TYPE_IRQ);
+
+ if (!is_ffa_direct_response(ret_values)) {
+ ERROR("Expected a direct response message while configuring"
+ " interrupt ESPI %u\n", IRQ_ESPI_TEST_INTID);
+ return TEST_RESULT_FAIL;
+ }
+
+ if (cactus_get_response(ret_values) != CACTUS_SUCCESS) {
+ ERROR("Failed to configure ESPI interrupt %u\n", IRQ_ESPI_TEST_INTID);
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Check for the last serviced secure virtual interrupt. */
+ ret_values = cactus_get_last_interrupt_cmd(SENDER, RECEIVER);
+
+ if (!is_ffa_direct_response(ret_values)) {
+ ERROR("Expected a direct response for last serviced interrupt"
+ " command\n");
+ return TEST_RESULT_FAIL;
+ }
+
+ /* Make sure Trusted Watchdog timer interrupt was serviced*/
+ if (cactus_get_response(ret_values) != IRQ_ESPI_TEST_INTID) {
+ ERROR("ESPI interrupt %u not serviced by SP\n", IRQ_ESPI_TEST_INTID);
+ return TEST_RESULT_FAIL;
+ }
+ return TEST_RESULT_SUCCESS;
+}
diff --git a/tftf/tests/tests-spm.xml b/tftf/tests/tests-spm.xml
index 6285a97..8ec2812 100644
--- a/tftf/tests/tests-spm.xml
+++ b/tftf/tests/tests-spm.xml
@@ -140,6 +140,8 @@
function="test_ffa_sec_interrupt_sp_blocked" />
<testcase name="Test Secure interrupt handling while SP1 waiting SP2 running"
function="test_ffa_sec_interrupt_sp1_waiting_sp2_running" />
+ <testcase name="Test ESPI Secure interrupt handling"
+ function="test_ffa_espi_sec_interrupt" />
</testsuite>
<testsuite name="SMMUv3 tests"