summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2015-11-06 09:58:45 -0800
committerBill Richardson <wfrichar@chromium.org>2015-11-10 22:39:14 +0000
commit576444aa1364d548ff6d29b3f5e7224975bffda6 (patch)
treea34a20d138c8ae8d6d0d136b20335119510e4b4c
parent957a84277bb9ea57cdd63094cfce8a5362ee1fe6 (diff)
downloadchrome-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>
-rw-r--r--chip/g/system.c2
-rw-r--r--chip/g/watchdog.c27
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")))