diff options
author | Bill Richardson <wfrichar@chromium.org> | 2015-11-06 09:58:45 -0800 |
---|---|---|
committer | Bill Richardson <wfrichar@chromium.org> | 2015-11-10 22:39:14 +0000 |
commit | 576444aa1364d548ff6d29b3f5e7224975bffda6 (patch) | |
tree | a34a20d138c8ae8d6d0d136b20335119510e4b4c /chip/g | |
parent | 957a84277bb9ea57cdd63094cfce8a5362ee1fe6 (diff) | |
download | chrome-ec-576444aa1364d548ff6d29b3f5e7224975bffda6.tar.gz |
Cr50: Workaround for watchdog permission problems
When we lower the runlevel for security purposes, the standard
ARM watchdog interrupt is no longer enough to cause a full
reboot. We'll manually trigger a system reset instead. For now,
it's a soft reset. Should it be hard?
BUG=chrome-os-partner:47289
BRANCH=none
CQ-DEPEND=CL:310975
TEST=make buildall, manual
From the console, run "crash watchdog". After a second or to,
the watchdog trace dump appears and the system reboots.
Change-Id: I99fcaf19b32728563e3b051755d65267cc11156c
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/311298
Reviewed-by: Nagendra Modadugu <ngm@google.com>
Diffstat (limited to 'chip/g')
-rw-r--r-- | chip/g/system.c | 2 | ||||
-rw-r--r-- | chip/g/watchdog.c | 27 |
2 files changed, 20 insertions, 9 deletions
diff --git a/chip/g/system.c b/chip/g/system.c index 0fc3334a4e..4d935bcf37 100644 --- a/chip/g/system.c +++ b/chip/g/system.c @@ -45,6 +45,8 @@ void system_pre_init(void) void system_reset(int flags) { + /* TODO: if (flags & SYSTEM_RESET_PRESERVE_FLAGS), do so. */ + /* Disable interrupts to avoid task swaps during reboot */ interrupt_disable(); diff --git a/chip/g/watchdog.c b/chip/g/watchdog.c index 2a827b09a8..0568e27161 100644 --- a/chip/g/watchdog.c +++ b/chip/g/watchdog.c @@ -10,6 +10,7 @@ #include "registers.h" #include "task.h" #include "util.h" +#include "system.h" #include "watchdog.h" /* magic value to unlock the watchdog registers */ @@ -18,6 +19,12 @@ /* Watchdog expiration : assume 30 Mhz clock for now */ #define WATCHDOG_PERIOD (CONFIG_WATCHDOG_PERIOD_MS * (30000000 / 1000)) +void trace_and_reset(uint32_t excep_lr, uint32_t excep_sp) +{ + watchdog_trace(excep_lr, excep_sp); + system_reset(RESET_FLAG_WATCHDOG); +} + /* Warning interrupt at the middle of the watchdog period */ void IRQ_HANDLER(GC_IRQNUM_WATCHDOG0_WDOGINT)(void) __attribute__((naked)); void IRQ_HANDLER(GC_IRQNUM_WATCHDOG0_WDOGINT)(void) @@ -29,19 +36,21 @@ void IRQ_HANDLER(GC_IRQNUM_WATCHDOG0_WDOGINT)(void) * stack for ARM EABI. This also conveninently saves * R0=LR so we can pass it to task_resched_if_needed. */ "push {r0, lr}\n" - "bl watchdog_trace\n" - /* Do NOT reset the watchdog interrupt here; it will - * be done in watchdog_reload(), or reset will be - * triggered if we don't call that by the next watchdog - * period. Instead, de-activate the interrupt in the - * NVIC, so the watchdog trace will only be printed - * once. - */ + /* We've lowered our runlevel, so just rebooting the ARM + * core doesn't work. */ + "bl trace_and_reset\n" + /* Do NOT reset the watchdog interrupt here; it will + * be done in watchdog_reload(), or reset will be + * triggered if we don't call that by the next watchdog + * period. Instead, de-activate the interrupt in the + * NVIC, so the watchdog trace will only be printed + * once. + */ "mov r0, %[irq]\n" "bl task_disable_irq\n" "pop {r0, lr}\n" "b task_resched_if_needed\n" - : : [irq] "i" (GC_IRQNUM_WATCHDOG0_WDOGINT)); + : : [irq] "i" (GC_IRQNUM_WATCHDOG0_WDOGINT)); } const struct irq_priority IRQ_PRIORITY(GC_IRQNUM_WATCHDOG0_WDOGINT) __attribute__((section(".rodata.irqprio"))) |