summaryrefslogtreecommitdiff
path: root/spm
diff options
context:
space:
mode:
authorOlivier Deprez <olivier.deprez@arm.com>2022-04-04 17:24:36 +0200
committerTrustedFirmware Code Review <review@review.trustedfirmware.org>2022-04-04 17:24:36 +0200
commitc394fcc734fd49221030564df51df58db25540f8 (patch)
tree0b75c952f0bf4406df0d7ea59d40a7734105e465 /spm
parent968a869e90b1f1dc8ddb70cd1f0cca657f885e27 (diff)
parentff33cd11268a91bf7fa88b10f08eaf9c74c24fc5 (diff)
Merge changes from topic "mp/sec_intr_management"
* changes: test(interrupts): check if last service interrupt is Trusted Wdog timer feat(interrupts): query last serviced interrupt test(interrupts): use custom handler for interrupt feat(interrupts): support for registering custom handler refactor(interrupts): enhance secure interrupt handling test
Diffstat (limited to 'spm')
-rw-r--r--spm/cactus/cactus_interrupt.c17
-rw-r--r--spm/cactus/cactus_main.c3
-rw-r--r--spm/cactus/cactus_tests/cactus_test_interrupts.c79
-rw-r--r--spm/common/sp_helpers.c38
-rw-r--r--spm/common/sp_helpers.h18
5 files changed, 151 insertions, 4 deletions
diff --git a/spm/cactus/cactus_interrupt.c b/spm/cactus/cactus_interrupt.c
index ef3d5cc..2305b01 100644
--- a/spm/cactus/cactus_interrupt.c
+++ b/spm/cactus/cactus_interrupt.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -22,9 +22,15 @@ extern void notification_pending_interrupt_handler(void);
extern ffa_id_t g_ffa_id;
+/* Secure virtual interrupt that was last handled by Cactus SP. */
+uint32_t last_serviced_interrupt[PLATFORM_CORE_COUNT];
+
+extern spinlock_t sp_handler_lock[NUM_VINT_ID];
+
void cactus_interrupt_handler(void)
{
uint32_t intid = spm_interrupt_get();
+ unsigned int core_pos = get_current_core_id();
switch (intid) {
case MANAGED_EXIT_INTERRUPT_ID:
@@ -59,4 +65,13 @@ void cactus_interrupt_handler(void)
intid);
panic();
}
+
+ last_serviced_interrupt[core_pos] = intid;
+
+ /* Invoke the tail end handler registered by the SP. */
+ spin_lock(&sp_handler_lock[intid]);
+ if (sp_interrupt_tail_end_handler[intid]) {
+ sp_interrupt_tail_end_handler[intid]();
+ }
+ spin_unlock(&sp_handler_lock[intid]);
}
diff --git a/spm/cactus/cactus_main.c b/spm/cactus/cactus_main.c
index 58186d1..dd15d97 100644
--- a/spm/cactus/cactus_main.c
+++ b/spm/cactus/cactus_main.c
@@ -206,6 +206,9 @@ void __dead2 cactus_main(bool primary_cold_boot)
/* Configure and enable Stage-1 MMU, enable D-Cache */
cactus_plat_configure_mmu(ffa_id);
+
+ /* Initialize locks for tail end interrupt handler */
+ sp_handler_spin_lock_init();
}
/*
diff --git a/spm/cactus/cactus_tests/cactus_test_interrupts.c b/spm/cactus/cactus_tests/cactus_test_interrupts.c
index ced5dca..dc64512 100644
--- a/spm/cactus/cactus_tests/cactus_test_interrupts.c
+++ b/spm/cactus/cactus_tests/cactus_test_interrupts.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -14,6 +14,16 @@
#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 void sec_wdog_interrupt_handled(void)
+{
+ expect(flag_set, 0);
+ flag_set = 1;
+}
+
CACTUS_CMD_HANDLER(sleep_cmd, CACTUS_SLEEP_CMD)
{
uint64_t time_lapsed;
@@ -101,3 +111,70 @@ CACTUS_CMD_HANDLER(twdog_cmd, CACTUS_TWDOG_START_CMD)
return cactus_success_resp(vm_id, source, time_ms);
}
+
+bool handle_twdog_interrupt_sp_sleep(uint32_t sleep_time, uint64_t *time_lapsed)
+{
+ sp_register_interrupt_tail_end_handler(sec_wdog_interrupt_handled,
+ IRQ_TWDOG_INTID);
+ *time_lapsed += sp_sleep_elapsed_time(sleep_time);
+
+ if (flag_set == 0) {
+ return false;
+ }
+
+ /* Reset the flag and unregister the handler. */
+ flag_set = 0;
+ sp_unregister_interrupt_tail_end_handler(IRQ_TWDOG_INTID);
+
+ return true;
+}
+
+CACTUS_CMD_HANDLER(sleep_twdog_cmd, CACTUS_SLEEP_TRIGGER_TWDOG_CMD)
+{
+ uint64_t time_lapsed = 0;
+ uint32_t sleep_time = cactus_get_sleep_time(*args) / 2;
+ uint64_t time_ms = cactus_get_wdog_trigger_duration(*args);
+
+ VERBOSE("Request to sleep %x for %ums.\n", ffa_dir_msg_dest(*args),
+ sleep_time);
+
+ if (!handle_twdog_interrupt_sp_sleep(sleep_time, &time_lapsed)) {
+ goto fail;
+ }
+
+ /* Lapsed time should be at least equal to sleep time. */
+ VERBOSE("Sleep complete: %llu\n", time_lapsed);
+
+ VERBOSE("Starting TWDOG: %llums\n", time_ms);
+ sp805_twdog_refresh();
+ sp805_twdog_start((time_ms * ARM_SP805_TWDG_CLK_HZ) / 1000);
+
+ VERBOSE("2nd Request to sleep %x for %ums.\n", ffa_dir_msg_dest(*args),
+ sleep_time);
+
+ if (!handle_twdog_interrupt_sp_sleep(sleep_time, &time_lapsed)) {
+ goto fail;
+ }
+
+ /* Lapsed time should be at least equal to sleep time. */
+ VERBOSE("2nd Sleep complete: %llu\n", time_lapsed);
+
+ return cactus_response(ffa_dir_msg_dest(*args),
+ ffa_dir_msg_source(*args),
+ time_lapsed);
+fail:
+ /* Test failed. */
+ ERROR("Watchdog interrupt not handled\n");
+ return cactus_error_resp(ffa_dir_msg_dest(*args),
+ ffa_dir_msg_source(*args),
+ CACTUS_ERROR_TEST);
+}
+
+CACTUS_CMD_HANDLER(interrupt_serviced_cmd, CACTUS_LAST_INTERRUPT_SERVICED_CMD)
+{
+ unsigned int core_pos = get_current_core_id();
+
+ return cactus_response(ffa_dir_msg_dest(*args),
+ ffa_dir_msg_source(*args),
+ last_serviced_interrupt[core_pos]);
+}
diff --git a/spm/common/sp_helpers.c b/spm/common/sp_helpers.c
index 77031f8..448084f 100644
--- a/spm/common/sp_helpers.c
+++ b/spm/common/sp_helpers.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -13,6 +13,10 @@
#include "sp_helpers.h"
+spinlock_t sp_handler_lock[NUM_VINT_ID];
+
+void (*sp_interrupt_tail_end_handler[NUM_VINT_ID])(void);
+
uintptr_t bound_rand(uintptr_t min, uintptr_t max)
{
/*
@@ -80,3 +84,35 @@ void sp_sleep(uint32_t ms)
{
(void)sp_sleep_elapsed_time(ms);
}
+
+void sp_handler_spin_lock_init(void)
+{
+ for (uint32_t i = 0; i < NUM_VINT_ID; i++) {
+ init_spinlock(&sp_handler_lock[i]);
+ }
+}
+
+void sp_register_interrupt_tail_end_handler(void (*handler)(void),
+ uint32_t interrupt_id)
+{
+ if (interrupt_id >= NUM_VINT_ID) {
+ ERROR("Cannot register handler for interrupt %u\n", interrupt_id);
+ panic();
+ }
+
+ spin_lock(&sp_handler_lock[interrupt_id]);
+ sp_interrupt_tail_end_handler[interrupt_id] = handler;
+ spin_unlock(&sp_handler_lock[interrupt_id]);
+}
+
+void sp_unregister_interrupt_tail_end_handler(uint32_t interrupt_id)
+{
+ if (interrupt_id >= NUM_VINT_ID) {
+ ERROR("Cannot unregister handler for interrupt %u\n", interrupt_id);
+ panic();
+ }
+
+ spin_lock(&sp_handler_lock[interrupt_id]);
+ sp_interrupt_tail_end_handler[interrupt_id] = NULL;
+ spin_unlock(&sp_handler_lock[interrupt_id]);
+}
diff --git a/spm/common/sp_helpers.h b/spm/common/sp_helpers.h
index 6fe8ec0..ef60221 100644
--- a/spm/common/sp_helpers.h
+++ b/spm/common/sp_helpers.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -10,6 +10,10 @@
#include <stdint.h>
#include <tftf_lib.h>
#include <spm_common.h>
+#include <spinlock.h>
+
+/* Currently, Hafnium/SPM supports only 64 virtual interrupt IDs. */
+#define NUM_VINT_ID 64
typedef struct {
u_register_t fid;
@@ -62,4 +66,16 @@ uint64_t sp_sleep_elapsed_time(uint32_t ms);
/* Sleep for at least 'ms' milliseconds. */
void sp_sleep(uint32_t ms);
+void sp_handler_spin_lock_init(void);
+
+/* Handler invoked at the tail end of interrupt processing by SP. */
+extern void (*sp_interrupt_tail_end_handler[NUM_VINT_ID])(void);
+
+/* Register the handler. */
+void sp_register_interrupt_tail_end_handler(void (*handler)(void),
+ uint32_t interrupt_id);
+
+/* Un-register the handler. */
+void sp_unregister_interrupt_tail_end_handler(uint32_t interrupt_id);
+
#endif /* SP_HELPERS_H */