diff options
author | Rob Barnes <robbarnes@google.com> | 2022-11-29 20:54:29 +0000 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-02-14 16:28:36 +0000 |
commit | b3f612ed2b5e7728e5c07f2b18772c4688a46370 (patch) | |
tree | 7dc241eee54b4268f47bec7469d4a0bb9e69ccd6 | |
parent | 42d83017fb78371f1ded1af599089daedf3a9a4d (diff) | |
download | chrome-ec-b3f612ed2b5e7728e5c07f2b18772c4688a46370.tar.gz |
system_safe_mode: Publish EC_HOST_EVENT_PANIC when safe mode starts
Publish EC_HOST_EVENT_PANIC when safe mode starts.
The event is published from a deferred function since publishing events
from an ISR is not compatible with some systems.
The kernel may use this event to clean up before the system is reset
(e.g. sync the drive). This will be a no-op if the kernel doesn't handle
it.
This is a refactor of CL:4063818, which was reverted in CL:4225911.
The original implementation triggered the event in the panic handler.
This version triggers the event after safe mode starts. Since the system
reboots immediately when safe mode isn't started, triggering the event
outside of safe mode doesn't have any effect.
BUG=b:258195448
BRANCH=None
TEST=Observe event in kernel. Pass system_safe_mode unit test.
Change-Id: I62c48590029bf2bf8f1e0bb7271f29499a8a28d7
Signed-off-by: Rob Barnes <robbarnes@google.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4226407
Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
-rw-r--r-- | common/system_safe_mode.c | 15 | ||||
-rw-r--r-- | zephyr/test/system_safe_mode/src/system_safe_mode.c | 18 |
2 files changed, 33 insertions, 0 deletions
diff --git a/common/system_safe_mode.c b/common/system_safe_mode.c index 539bbb626d..e86aa5216f 100644 --- a/common/system_safe_mode.c +++ b/common/system_safe_mode.c @@ -8,6 +8,7 @@ #include "cpu.h" #include "ec_commands.h" #include "hooks.h" +#include "host_command.h" #include "panic.h" #include "stddef.h" #include "system.h" @@ -88,6 +89,13 @@ bool command_is_allowed_in_safe_mode(int command) return false; } +static void system_safe_mode_start(void) +{ + if (IS_ENABLED(CONFIG_HOSTCMD_EVENTS)) + host_set_single_event(EC_HOST_EVENT_PANIC); +} +DECLARE_DEFERRED(system_safe_mode_start); + int start_system_safe_mode(void) { if (!system_is_in_rw()) { @@ -111,6 +119,13 @@ int start_system_safe_mode(void) schedule_system_safe_mode_timeout(); + /* + * Schedule a deferred function to run immediately + * after returning from fault handler. Defer operations that + * must not run in an ISR to this function. + */ + hook_call_deferred(&system_safe_mode_start_data, 0); + in_safe_mode = true; panic_printf("\nStarting system safe mode\n"); diff --git a/zephyr/test/system_safe_mode/src/system_safe_mode.c b/zephyr/test/system_safe_mode/src/system_safe_mode.c index 2b861f2e5b..f286a45124 100644 --- a/zephyr/test/system_safe_mode/src/system_safe_mode.c +++ b/zephyr/test/system_safe_mode/src/system_safe_mode.c @@ -140,4 +140,22 @@ ZTEST_USER(system_safe_mode, test_blocked_command_in_safe_mode) zassert_true(host_command_process(&args)); } +ZTEST_USER(system_safe_mode, test_panic_event_notify) +{ +#ifdef CONFIG_HOSTCMD_X86 + /* Enable the EC_HOST_EVENT_PANIC event in the lpc mask */ + host_event_t lpc_event_mask; + host_event_t mask = EC_HOST_EVENT_MASK(EC_HOST_EVENT_PANIC); + + lpc_event_mask = lpc_get_host_event_mask(LPC_HOST_EVENT_SCI); + lpc_set_host_event_mask(LPC_HOST_EVENT_SCI, lpc_event_mask | mask); +#endif + + zassert_false(host_is_event_set(EC_HOST_EVENT_PANIC)); + k_sys_fatal_error_handler(K_ERR_CPU_EXCEPTION, NULL); + /* Short sleep to allow hook task to run */ + k_msleep(1); + zassert_true(host_is_event_set(EC_HOST_EVENT_PANIC)); +} + ZTEST_SUITE(system_safe_mode, NULL, NULL, system_before, NULL, NULL); |