test(interrupts): secure interrupt target in RUNNING state
This patch adds a new test to exercise secure interrupt targeted
for an SP in RUNNING state. The test is made part of a new test suite
named secure_interrupts.
All the tests in this test suite are run as part of two different
configurations: one where the target SP is a S-EL1 partition and
another where the target SP is a S-EL0 partition.
Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
Change-Id: Ibdea25bffa3c8285509e1c21a2ff93f2cc0acdda
diff --git a/test/vmapi/ffa_secure_partitions/BUILD.gn b/test/vmapi/ffa_secure_partitions/BUILD.gn
index 02394d7..c397ce2 100644
--- a/test/vmapi/ffa_secure_partitions/BUILD.gn
+++ b/test/vmapi/ffa_secure_partitions/BUILD.gn
@@ -43,6 +43,7 @@
"interrupts.c",
"notifications.c",
"power_mgt.c",
+ "secure_interrupts.c",
"setup_and_discovery.c",
]
diff --git a/test/vmapi/ffa_secure_partitions/secure_interrupts.c b/test/vmapi/ffa_secure_partitions/secure_interrupts.c
new file mode 100644
index 0000000..92776d3
--- /dev/null
+++ b/test/vmapi/ffa_secure_partitions/secure_interrupts.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2023 The Hafnium Authors.
+ *
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file or at
+ * https://opensource.org/licenses/BSD-3-Clause.
+ */
+
+#include "ffa_secure_partitions.h"
+#include "partition_services.h"
+#include "sp_helpers.h"
+
+#define SP_SLEEP_TIME 400U
+
+static void configure_trusted_wdog_interrupt(ffa_vm_id_t source,
+ ffa_vm_id_t dest, bool enable)
+{
+ struct ffa_value res;
+
+ res = sp_virtual_interrupt_cmd_send(source, dest, IRQ_TWDOG_INTID,
+ enable, 0);
+
+ EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
+ EXPECT_EQ(sp_resp(res), SP_SUCCESS);
+}
+
+static void enable_trusted_wdog_interrupt(ffa_vm_id_t source, ffa_vm_id_t dest)
+{
+ configure_trusted_wdog_interrupt(source, dest, true);
+}
+
+static void disable_trusted_wdog_interrupt(ffa_vm_id_t source, ffa_vm_id_t dest)
+{
+ configure_trusted_wdog_interrupt(source, dest, false);
+}
+
+static void enable_trigger_trusted_wdog_timer(ffa_vm_id_t own_id,
+ ffa_vm_id_t receiver_id,
+ uint32_t timer_ms)
+{
+ struct ffa_value res;
+
+ /* Enable trusted watchdog interrupt as vIRQ in the secure side. */
+ enable_trusted_wdog_interrupt(own_id, receiver_id);
+
+ res = sp_twdog_map_cmd_send(own_id, receiver_id);
+
+ EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
+ EXPECT_EQ(sp_resp(res), SP_SUCCESS);
+
+ /*
+ * Send a message to the SP through direct messaging requesting it to
+ * start the trusted watchdog timer.
+ */
+ res = sp_twdog_cmd_send(own_id, receiver_id, timer_ms);
+
+ EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
+ EXPECT_EQ(sp_resp(res), SP_SUCCESS);
+}
+
+static void check_and_disable_trusted_wdog_timer(ffa_vm_id_t own_id,
+ ffa_vm_id_t receiver_id)
+{
+ struct ffa_value res;
+
+ /* Check for the last serviced secure virtual interrupt. */
+ res = sp_get_last_interrupt_cmd_send(own_id, receiver_id);
+
+ EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
+ EXPECT_EQ(sp_resp(res), SP_SUCCESS);
+
+ /* Make sure Trusted Watchdog timer interrupt was serviced. */
+ EXPECT_EQ(sp_resp_value(res), IRQ_TWDOG_INTID);
+
+ /* Disable Trusted Watchdog interrupt. */
+ disable_trusted_wdog_interrupt(own_id, receiver_id);
+}
+
+/*
+ * Test secure interrupt handling while the Secure Partition is in RUNNING
+ * state.
+ */
+TEST(secure_interrupts, sp_running)
+{
+ struct ffa_value res;
+ ffa_vm_id_t own_id = hf_vm_get_id();
+ struct ffa_partition_info *service2_info = service2();
+ const ffa_vm_id_t receiver_id = service2_info->vm_id;
+
+ enable_trigger_trusted_wdog_timer(own_id, receiver_id, 400);
+
+ /* Send request to the SP to sleep. */
+ res = sp_sleep_cmd_send(own_id, receiver_id, SP_SLEEP_TIME);
+
+ /*
+ * Secure interrupt should trigger during this time, SP will handle the
+ * trusted watchdog timer interrupt.
+ */
+ EXPECT_EQ(res.func, FFA_MSG_SEND_DIRECT_RESP_32);
+ EXPECT_EQ(sp_resp(res), SP_SUCCESS);
+
+ /* Make sure elapsed time not less than sleep time. */
+ EXPECT_GE(sp_resp_value(res), SP_SLEEP_TIME);
+
+ check_and_disable_trusted_wdog_timer(own_id, receiver_id);
+}