diff options
-rw-r--r-- | chip/ish/watchdog.c | 27 | ||||
-rw-r--r-- | core/minute-ia/interrupts.c | 33 | ||||
-rw-r--r-- | core/minute-ia/panic.c | 7 |
3 files changed, 30 insertions, 37 deletions
diff --git a/chip/ish/watchdog.c b/chip/ish/watchdog.c index fd0ebcf247..79f6e788df 100644 --- a/chip/ish/watchdog.c +++ b/chip/ish/watchdog.c @@ -20,7 +20,6 @@ */ #include "common.h" -#include "console.h" #include "hooks.h" #include "task.h" #include "registers.h" @@ -46,32 +45,6 @@ int watchdog_init(void) return EC_SUCCESS; } -/* Parameters are pushed by hardware, we only care about %EIP */ -__attribute__ ((noreturn)) -void watchdog_warning(uint32_t errorcode, - uint32_t eip, - uint32_t cs, - uint32_t eflags) -{ - ccprintf("\nWDT Expired. EIP was 0x%08X. Resetting...\n", eip); - cflush(); - - system_reset(SYSTEM_RESET_AP_WATCHDOG); - __builtin_unreachable(); -} - -__attribute__ ((noreturn)) -void watchdog_warning_irq(void) -{ - /* - * Parameters to watchdog_warning were pushed by hardware, use - * asm here to re-use these parameters in the call. - */ - __asm__ ("call watchdog_warning\n"); - __builtin_unreachable(); -} -DECLARE_IRQ(ISH_WDT_IRQ, watchdog_warning_irq); - void watchdog_reload(void) { /* diff --git a/core/minute-ia/interrupts.c b/core/minute-ia/interrupts.c index efa07ef062..5e69b9c199 100644 --- a/core/minute-ia/interrupts.c +++ b/core/minute-ia/interrupts.c @@ -169,15 +169,19 @@ static const irq_desc_t system_irqs[] = { * and go directly to the CPU core, so get_current_interrupt_vector * cannot be used. */ -#define DEFINE_EXN_HANDLER(vector) \ - void __keep exception_panic_##vector(void); \ - __attribute__ ((noreturn)) void exception_panic_##vector(void) \ - { \ - __asm__ ( \ - "push $" #vector "\n" \ - "call exception_panic\n"); \ - while (1) \ - continue; \ +#define DEFINE_EXN_HANDLER(vector) \ + _DEFINE_EXN_HANDLER(vector, exception_panic_##vector) +#define _DEFINE_EXN_HANDLER(vector, name) \ + __DEFINE_EXN_HANDLER(vector, name) +#define __DEFINE_EXN_HANDLER(vector, name) \ + void __keep name(void); \ + __attribute__ ((noreturn)) void name(void) \ + { \ + __asm__ ( \ + "push $" #vector "\n" \ + "call exception_panic\n"); \ + while (1) \ + continue; \ } DEFINE_EXN_HANDLER(0); @@ -200,6 +204,7 @@ DEFINE_EXN_HANDLER(17); DEFINE_EXN_HANDLER(18); DEFINE_EXN_HANDLER(19); DEFINE_EXN_HANDLER(20); +_DEFINE_EXN_HANDLER(ISH_WDT_VEC, exception_panic_wdt); void set_interrupt_gate(uint8_t num, isr_handler_t func, uint8_t flags) { @@ -457,6 +462,16 @@ void init_interrupts(void) set_interrupt_gate(19, exception_panic_19, IDT_DESC_FLAGS); set_interrupt_gate(20, exception_panic_20, IDT_DESC_FLAGS); + /* + * Set up watchdog expiration like a panic, that way we can + * use the common panic handling code, and also properly + * retrieve EIP. + */ + if (IS_ENABLED(CONFIG_WATCHDOG)) + set_interrupt_gate(ISH_WDT_VEC, + exception_panic_wdt, + IDT_DESC_FLAGS); + /* Note: At reset, ID field is already set to 0 in APIC ID register */ /* Enable the APIC, mapping the spurious interrupt at the same time. */ diff --git a/core/minute-ia/panic.c b/core/minute-ia/panic.c index 40e8ee1cf0..0898e4e717 100644 --- a/core/minute-ia/panic.c +++ b/core/minute-ia/panic.c @@ -50,7 +50,9 @@ const static char *panic_reason[] = { */ void panic_data_print(const struct panic_data *pdata) { - if (pdata->x86.vector <= 20) + if (pdata->x86.vector == ISH_WDT_VEC) + panic_printf("Reason: Watchdog Expiration\n"); + else if (pdata->x86.vector <= 20) panic_printf("Reason: %s\n", panic_reason[pdata->x86.vector]); else panic_printf("Interrupt vector number: 0x%08X (unknown)\n", @@ -134,6 +136,9 @@ __attribute__ ((noreturn)) void __keep exception_panic( if (panic_once) { system_reset(SYSTEM_RESET_HARD); + } else if (vector == ISH_WDT_VEC) { + panic_once = 1; + system_reset(SYSTEM_RESET_AP_WATCHDOG); } else { panic_once = 1; system_reset(0); |