From 2897deab91e525e977c09a03624eda7990c81c71 Mon Sep 17 00:00:00 2001 From: Gatien Chevallier Date: Mon, 30 Oct 2023 14:26:35 +0100 Subject: [PATCH 1/3] core: panic: platform specific panic sequence Implement a new function plat_panic() for platform panic sequence. The default weak implementation traps CPU in an endless loop. Platforms can override the weak implementation for a specific panic sequence. Signed-off-by: Gatien Chevallier Signed-off-by: Etienne Carriere Reviewed-by: Jerome Forissier --- core/include/kernel/panic.h | 6 ++++++ core/kernel/panic.c | 15 +++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/core/include/kernel/panic.h b/core/include/kernel/panic.h index 3d4fa55b248..99ad715d967 100644 --- a/core/include/kernel/panic.h +++ b/core/include/kernel/panic.h @@ -8,6 +8,12 @@ #include +/* + * Platform can define a panic sequence to trap cpu/reset core or system + * after eventual debug trace. + */ +void plat_panic(void); + /* debug disabled => __FILE__, ... and panic message are not built. */ #if defined(CFG_TEE_CORE_DEBUG) #define __panic(str) __do_panic(__FILE__, __LINE__, __func__, str) diff --git a/core/kernel/panic.c b/core/kernel/panic.c index 18028fbfd3c..fc5bdf4f951 100644 --- a/core/kernel/panic.c +++ b/core/kernel/panic.c @@ -7,6 +7,7 @@ #include #include #include +#include #include void __do_panic(const char *file __maybe_unused, @@ -17,8 +18,6 @@ void __do_panic(const char *file __maybe_unused, /* disable prehemption */ (void)thread_mask_exceptions(THREAD_EXCP_ALL); - /* TODO: notify other cores */ - /* trace: Panic ['panic-string-message' ]at FILE:LINE []" */ if (!file && !func && !msg) EMSG_RAW("Panic"); @@ -29,11 +28,19 @@ void __do_panic(const char *file __maybe_unused, func ? "<" : "", func ? func : "", func ? ">" : ""); print_kernel_stack(); - /* abort current execution */ - while (1) + plat_panic(); + + EMSG("Platform failed to abort execution"); + while (true) cpu_idle(); } void __weak cpu_idle(void) { } + +void __weak __noreturn plat_panic(void) +{ + while (true) + cpu_idle(); +} From c8c62593ce590fc45a67bcc9629ad3d4cbca4e92 Mon Sep 17 00:00:00 2001 From: Gatien Chevallier Date: Thu, 2 Nov 2023 10:01:59 +0100 Subject: [PATCH 2/3] plat-stm32mp1: implement platform specific panic sequence Implement a platform specific sequence where the non-secure context can be dumped when a panic occurs, should the log level be sufficient. If there are two cores: raise an interrupt so that is can be stopped as well. Signed-off-by: Gatien Chevallier --- core/arch/arm/plat-stm32mp1/main.c | 126 +++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/core/arch/arm/plat-stm32mp1/main.c b/core/arch/arm/plat-stm32mp1/main.c index eebf0bd5e50..5a58233cefc 100644 --- a/core/arch/arm/plat-stm32mp1/main.c +++ b/core/arch/arm/plat-stm32mp1/main.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -584,3 +585,128 @@ early_init_late(init_debug); /* Some generic resources need to be unpaged */ DECLARE_KEEP_PAGER(pinctrl_apply_state); + +#if TRACE_LEVEL >= TRACE_DEBUG +static const char *const dump_table[] = { + "usr_sp", + "usr_lr", + "irq_spsr", + "irq_sp", + "irq_lr", + "fiq_spsr", + "fiq_sp", + "fiq_lr", + "svc_spsr", + "svc_sp", + "svc_lr", + "abt_spsr", + "abt_sp", + "abt_lr", + "und_spsr", + "und_sp", + "und_lr", +#ifdef CFG_SM_NO_CYCLE_COUNTING + "pmcr", +#endif +#ifdef CFG_FTRACE_SUPPORT + "cntkctl", + "pad" +#endif +}; + +static void stm32mp_dump_core_registers(bool panicking) +{ + struct sm_nsec_ctx *sm_nsec_ctx = sm_get_nsec_ctx(); + static unsigned int lock = SPINLOCK_UNLOCK; + bool display = false; + uint32_t *reg = NULL; + size_t i = U(0); + + cpu_spin_lock(&lock); + + if (panicking) + display = true; + + if (!display || !sm_nsec_ctx) + return; + + DMSG("CPU : %zu\n", get_core_pos()); + + reg = (uint32_t *)&sm_nsec_ctx->ub_regs.usr_sp; + + for (i = U(0); i < ARRAY_SIZE(dump_table); i++) + DMSG("%10s : %#8x\n", dump_table[i], reg[i]); + + cpu_spin_unlock(&lock); +} +DECLARE_KEEP_PAGER(stm32mp_dump_core_registers); +#else +static inline void stm32mp_dump_core_registers(bool panicking __unused) { } +#endif + +#define ARM_CNTXCTL_IMASK BIT(1) + +static void stm32mp_mask_timer(void) +{ + /* Mask timer interrupts */ + write_cntp_ctl(read_cntp_ctl() | ARM_CNTXCTL_IMASK); + write_cntv_ctl(read_cntv_ctl() | ARM_CNTXCTL_IMASK); +} + +/* SGI9 (secure SGI 1) informs targeted CPU it should abort execution */ +static enum itr_return sgi9_it_handler(struct itr_handler *hdl __unused) +{ + DMSG("Halting CPU %u", get_core_pos()); + + stm32mp_mask_timer(); + + stm32mp_dump_core_registers(true); + + while (true) + cpu_idle(); + + return ITRR_HANDLED; +} + +static struct itr_handler sgi9_reset_handler = { + .it = GIC_SEC_SGI_1, + .handler = sgi9_it_handler, +}; +DECLARE_KEEP_PAGER(sgi9_reset_handler); + +void __noreturn plat_panic(void) +{ + struct itr_chip *itr_chip = interrupt_get_main_chip(); + + stm32mp_mask_timer(); + + if (CFG_TEE_CORE_NB_CORE > 1) { + uint32_t target_mask = 0; + + if (get_core_pos() == 0) + target_mask = TARGET_CPU1_GIC_MASK; + else + target_mask = TARGET_CPU0_GIC_MASK; + + interrupt_raise_sgi(itr_chip, GIC_SEC_SGI_1, target_mask); + } + + stm32mp_dump_core_registers(true); + + while (true) + cpu_idle(); +} + +static TEE_Result setup_multi_core_panic(void) +{ + struct itr_chip *itr_chip = interrupt_get_main_chip(); + + if (CFG_TEE_CORE_NB_CORE < 2) + return TEE_SUCCESS; + + interrupt_add_handler_with_chip(itr_chip, &sgi9_reset_handler); + interrupt_enable(itr_chip, sgi9_reset_handler.it); + + return TEE_SUCCESS; +} +service_init(setup_multi_core_panic); From 49434ad099d1b8fe6be66590891cf0f0723d7987 Mon Sep 17 00:00:00 2001 From: Gatien Chevallier Date: Thu, 2 Nov 2023 16:54:08 +0100 Subject: [PATCH 3/3] [Review] plat-stm32mp1: implement platform specific panic sequence Add missing error code management Ass missing cpu_spin_unlock() Other minor fixes Signed-off-by: Gatien Chevallier --- core/arch/arm/plat-stm32mp1/main.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/core/arch/arm/plat-stm32mp1/main.c b/core/arch/arm/plat-stm32mp1/main.c index 5a58233cefc..a992c333ceb 100644 --- a/core/arch/arm/plat-stm32mp1/main.c +++ b/core/arch/arm/plat-stm32mp1/main.c @@ -627,28 +627,29 @@ static void stm32mp_dump_core_registers(bool panicking) if (panicking) display = true; - if (!display || !sm_nsec_ctx) + if (!display) { + cpu_spin_unlock(&lock); return; + } DMSG("CPU : %zu\n", get_core_pos()); reg = (uint32_t *)&sm_nsec_ctx->ub_regs.usr_sp; for (i = U(0); i < ARRAY_SIZE(dump_table); i++) - DMSG("%10s : %#8x\n", dump_table[i], reg[i]); + DMSG("%10s : %#8"PRIx32, dump_table[i], reg[i]); cpu_spin_unlock(&lock); } DECLARE_KEEP_PAGER(stm32mp_dump_core_registers); #else -static inline void stm32mp_dump_core_registers(bool panicking __unused) { } -#endif +static void stm32mp_dump_core_registers(bool panicking __unused) { } +#endif /* TRACE_LEVEL >= TRACE_DEBUG */ #define ARM_CNTXCTL_IMASK BIT(1) static void stm32mp_mask_timer(void) { - /* Mask timer interrupts */ write_cntp_ctl(read_cntp_ctl() | ARM_CNTXCTL_IMASK); write_cntv_ctl(read_cntv_ctl() | ARM_CNTXCTL_IMASK); } @@ -676,17 +677,16 @@ DECLARE_KEEP_PAGER(sgi9_reset_handler); void __noreturn plat_panic(void) { - struct itr_chip *itr_chip = interrupt_get_main_chip(); - stm32mp_mask_timer(); if (CFG_TEE_CORE_NB_CORE > 1) { + struct itr_chip *itr_chip = interrupt_get_main_chip(); uint32_t target_mask = 0; - if (get_core_pos() == 0) - target_mask = TARGET_CPU1_GIC_MASK; - else + if (get_core_pos()) target_mask = TARGET_CPU0_GIC_MASK; + else + target_mask = TARGET_CPU1_GIC_MASK; interrupt_raise_sgi(itr_chip, GIC_SEC_SGI_1, target_mask); } @@ -704,9 +704,12 @@ static TEE_Result setup_multi_core_panic(void) if (CFG_TEE_CORE_NB_CORE < 2) return TEE_SUCCESS; - interrupt_add_handler_with_chip(itr_chip, &sgi9_reset_handler); + if (interrupt_add_handler_with_chip(itr_chip, &sgi9_reset_handler)) + panic(); + interrupt_enable(itr_chip, sgi9_reset_handler.it); return TEE_SUCCESS; } + service_init(setup_multi_core_panic);