summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Barnes <robbarnes@google.com>2022-11-29 20:54:29 +0000
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-02-14 16:28:36 +0000
commitb3f612ed2b5e7728e5c07f2b18772c4688a46370 (patch)
tree7dc241eee54b4268f47bec7469d4a0bb9e69ccd6
parent42d83017fb78371f1ded1af599089daedf3a9a4d (diff)
downloadchrome-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.c15
-rw-r--r--zephyr/test/system_safe_mode/src/system_safe_mode.c18
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);