diff options
author | Olivier Deprez <olivier.deprez@arm.com> | 2022-04-04 17:24:36 +0200 |
---|---|---|
committer | TrustedFirmware Code Review <review@review.trustedfirmware.org> | 2022-04-04 17:24:36 +0200 |
commit | c394fcc734fd49221030564df51df58db25540f8 (patch) | |
tree | 0b75c952f0bf4406df0d7ea59d40a7734105e465 /spm/cactus | |
parent | 968a869e90b1f1dc8ddb70cd1f0cca657f885e27 (diff) | |
parent | ff33cd11268a91bf7fa88b10f08eaf9c74c24fc5 (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/cactus')
-rw-r--r-- | spm/cactus/cactus_interrupt.c | 17 | ||||
-rw-r--r-- | spm/cactus/cactus_main.c | 3 | ||||
-rw-r--r-- | spm/cactus/cactus_tests/cactus_test_interrupts.c | 79 |
3 files changed, 97 insertions, 2 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]); +} |