From 576444aa1364d548ff6d29b3f5e7224975bffda6 Mon Sep 17 00:00:00 2001 From: Bill Richardson Date: Fri, 6 Nov 2015 09:58:45 -0800 Subject: 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 Reviewed-on: https://chromium-review.googlesource.com/311298 Reviewed-by: Nagendra Modadugu --- chip/g/system.c | 2 ++ chip/g/watchdog.c | 27 ++++++++++++++++++--------- 2 files changed, 20 insertions(+), 9 deletions(-) (limited to 'chip') 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"))) -- cgit v1.2.1