summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Barnes <robbarnes@google.com>2023-04-11 14:41:18 -0600
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-04-18 14:19:05 +0000
commit5395914606d26ddc137a2d33e795655959f559d4 (patch)
tree53d6ab1aaa0c0d84fd3102386d8b31c4c2f18e2b
parent2c338a7e8a7f33b94a9b5164be85e0c62b6dae3e (diff)
downloadchrome-ec-5395914606d26ddc137a2d33e795655959f559d4.tar.gz
panic: Set watchdog panic reason if old watchdog panic
The watchdog panic info may be set in watchdog handler or during system pre init after the watchdog reset. It depends on the chip implementation. For cortex-m on Zephyr, the watchdog panic reason is not set in the watchdog handler. The current logic in system pre init only sets the watchdog panic reason when the current reason is not a watchdog. This means only the first watchdog is reported. Successive watchdogs are ignored because the panic flags are never reset. The panic flags will only be reset if a non-watchdog panic occurs or EC memory cleared (FW update or 0 battery). This change checks if the current watchdog panic is old. This is inferred by checking for the PANIC_DATA_FLAG_OLD_HOSTCMD flag, which is set when the host reads the panic info. BUG=b:273516527 BRANCH=Zephyer NPCX boards TEST=Succesive watchdogs are correctly reported in elog TEST=drivers.system unit test Change-Id: I91ec1bf75a85ea7fed978895a262ff74e6ac16c7 Signed-off-by: Rob Barnes <robbarnes@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4415329 Commit-Queue: Aaron Massey <aaronmassey@google.com> Reviewed-by: Aaron Massey <aaronmassey@google.com>
-rw-r--r--common/system.c10
-rw-r--r--zephyr/test/drivers/system/src/system.c50
2 files changed, 59 insertions, 1 deletions
diff --git a/common/system.c b/common/system.c
index f7bdd5d402..adb8c665c3 100644
--- a/common/system.c
+++ b/common/system.c
@@ -903,9 +903,17 @@ void system_common_pre_init(void)
uint32_t reason;
uint32_t info;
uint8_t exception;
+ struct panic_data *pdata;
panic_get_reason(&reason, &info, &exception);
- if (reason != PANIC_SW_WATCHDOG)
+ pdata = panic_get_data();
+ /* The watchdog panic info may have already been initialized by
+ * the watchdog handler, so only set it here if the panic reason
+ * is not a watchdog or the panic info has already been read,
+ * i.e. an old watchdog panic.
+ */
+ if (reason != PANIC_SW_WATCHDOG || !pdata ||
+ pdata->flags & PANIC_DATA_FLAG_OLD_HOSTCMD)
panic_set_reason(PANIC_SW_WATCHDOG, 0, 0);
}
diff --git a/zephyr/test/drivers/system/src/system.c b/zephyr/test/drivers/system/src/system.c
index 2bd8554994..051723f194 100644
--- a/zephyr/test/drivers/system/src/system.c
+++ b/zephyr/test/drivers/system/src/system.c
@@ -98,11 +98,61 @@ ZTEST(system, test_system_common_pre_init__watch_dog_panic)
uint32_t info;
uint8_t exception;
+ /* Watchdog reset should result in any existing panic data being
+ * overwritten
+ */
+ panic_set_reason(PANIC_SW_DIV_ZERO, 0x12, 0x34);
+
+ /* Clear all reset flags and set them arbitrarily */
+ system_set_reset_flags(EC_RESET_FLAG_WATCHDOG);
+ system_common_pre_init();
+ panic_get_reason(&reason, &info, &exception);
+ zassert_equal(reason, PANIC_SW_WATCHDOG);
+ zassert_equal(info, 0);
+ zassert_equal(exception, 0);
+}
+
+ZTEST(system, test_system_common_pre_init__watch_dog_panic_already_initialized)
+{
+ uint32_t reason;
+ uint32_t info;
+ uint8_t exception;
+
+ /* Watchdog reset should not overwrite panic info if already filled
+ * in with watchdog panic info that HAS NOT been read by host
+ */
+ panic_set_reason(PANIC_SW_WATCHDOG, 0x12, 0x34);
+
+ /* Clear all reset flags and set them arbitrarily */
+ system_set_reset_flags(EC_RESET_FLAG_WATCHDOG);
+ system_common_pre_init();
+ panic_get_reason(&reason, &info, &exception);
+ zassert_equal(reason, PANIC_SW_WATCHDOG);
+ zassert_equal(info, 0x12);
+ zassert_equal(exception, 0x34);
+}
+
+ZTEST(system, test_system_common_pre_init__watch_dog_panic_already_read)
+{
+ uint32_t reason;
+ uint32_t info;
+ uint8_t exception;
+ struct panic_data *pdata;
+
+ /* Watchdog reset should overwrite panic info if already filled
+ * in with watchdog panic info that HAS been read by host
+ */
+ panic_set_reason(PANIC_SW_WATCHDOG, 0x12, 0x34);
+ pdata = get_panic_data_write();
+ pdata->flags |= PANIC_DATA_FLAG_OLD_HOSTCMD;
+
/* Clear all reset flags and set them arbitrarily */
system_set_reset_flags(EC_RESET_FLAG_WATCHDOG);
system_common_pre_init();
panic_get_reason(&reason, &info, &exception);
zassert_equal(reason, PANIC_SW_WATCHDOG);
+ zassert_equal(info, 0);
+ zassert_equal(exception, 0);
}
ZTEST(system, test_system_encode_save_flags)