From 2ece52589486990cca666dc3ebc4164d5f2c0aed Mon Sep 17 00:00:00 2001 From: Jack Rosenthal Date: Mon, 22 Apr 2019 10:56:10 -0600 Subject: minute-ia: hard reset if we panic while handling a panic ish_pm_reset is a rather complex procedure, and encountering a panic while it is happening could lead to an infinte loop of handling panics. This will preform a reset of the Minute-IA core if a panic occurs and the system is already resetting from panic. BUG=b:130752748,b:130587334 BRANCH=none TEST=copied some invalid opcodes into switch_to_aontask procedure, observed the hard reset after forcing a panic Change-Id: I43459d78da9b67297f84e3a736d3f92da42a814c Signed-off-by: Jack Rosenthal Reviewed-on: https://chromium-review.googlesource.com/1576835 Reviewed-by: Jett Rink --- chip/ish/system.c | 22 +++++++++------------- core/minute-ia/panic.c | 22 +++++++++++++++++++--- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/chip/ish/system.c b/chip/ish/system.c index 22e6d60a06..74b6c8e17e 100644 --- a/chip/ish/system.c +++ b/chip/ish/system.c @@ -50,22 +50,18 @@ uint32_t chip_read_reset_flags(void) return 0; } -void _system_reset(int flags, int wake_from_hibernate) +void system_reset(int flags) { -#ifdef CONFIG_LOW_POWER_IDLE - /** - * ish_pm_reset() do more (poweroff main SRAM etc) than - * ish_mia_reset() which just reset the ISH minute-ia cpu core + /* + * ish_pm_reset() does more (poweroff main SRAM, etc) than + * ish_mia_reset() which just resets the ISH minute-ia cpu core */ - ish_pm_reset(); -#else - ish_mia_reset(); -#endif -} -void system_reset(int flags) -{ - _system_reset(flags, 0); + if (!IS_ENABLED(CONFIG_LOW_POWER_IDLE) || flags & SYSTEM_RESET_HARD) + ish_mia_reset(); + else + ish_pm_reset(); + while(1) ; } diff --git a/core/minute-ia/panic.c b/core/minute-ia/panic.c index eda38abc7f..06c903be0c 100644 --- a/core/minute-ia/panic.c +++ b/core/minute-ia/panic.c @@ -93,6 +93,14 @@ __attribute__ ((noreturn)) void __keep exception_panic( uint32_t cs, uint32_t eflags) { + /* + * If a panic were to occur during the reset procedure, we want + * to make sure that this panic will certainly cause a hard + * reset, rather than aontaskfw reset. Track if paniced once + * already. + */ + static int panic_once; + register uint32_t eax asm("eax"); register uint32_t ebx asm("ebx"); register uint32_t ecx asm("ecx"); @@ -121,10 +129,18 @@ __attribute__ ((noreturn)) void __keep exception_panic( PANIC_DATA_PTR->magic = PANIC_DATA_MAGIC; /* Display the panic and reset */ + if (panic_once) + panic_printf("\nWhile resetting from a panic, another panic" + " occurred!"); panic_data_print(PANIC_DATA_PTR); - system_reset(SYSTEM_RESET_HARD); - while (1) - continue; + if (panic_once) { + system_reset(SYSTEM_RESET_HARD); + } else { + panic_once = 1; + system_reset(0); + } + + __builtin_unreachable(); } #ifdef CONFIG_SOFTWARE_PANIC -- cgit v1.2.1