summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/sandbox/cpu/os.c17
-rw-r--r--configs/sandbox64_defconfig2
-rw-r--r--configs/sandbox_defconfig2
-rw-r--r--drivers/watchdog/Kconfig8
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/sandbox_alarm-wdt.c79
-rw-r--r--include/os.h17
7 files changed, 126 insertions, 0 deletions
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index d6170adaf5e..5e66304e2b9 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -130,6 +130,23 @@ void os_exit(int exit_code)
exit(exit_code);
}
+unsigned int os_alarm(unsigned int seconds)
+{
+ return alarm(seconds);
+}
+
+void os_set_alarm_handler(void (*handler)(int))
+{
+ if (!handler)
+ handler = SIG_DFL;
+ signal(SIGALRM, handler);
+}
+
+void os_raise_sigalrm(void)
+{
+ raise(SIGALRM);
+}
+
int os_write_file(const char *fname, const void *buf, int size)
{
int fd;
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index 48a7fd2bc22..04756729682 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -56,6 +56,7 @@ CONFIG_CMD_REMOTEPROC=y
CONFIG_CMD_SPI=y
CONFIG_CMD_USB=y
CONFIG_CMD_CAT=y
+CONFIG_CMD_WDT=y
CONFIG_BOOTP_DNS2=y
CONFIG_CMD_TFTPPUT=y
CONFIG_CMD_TFTPSRV=y
@@ -238,6 +239,7 @@ CONFIG_SPLASH_SCREEN_ALIGN=y
CONFIG_WDT=y
CONFIG_WDT_GPIO=y
CONFIG_WDT_SANDBOX=y
+CONFIG_WDT_ALARM_SANDBOX=y
CONFIG_FS_CBFS=y
CONFIG_FS_CRAMFS=y
CONFIG_CMD_DHRYSTONE=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index e18e666f126..34e90674eec 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -80,6 +80,7 @@ CONFIG_CMD_REMOTEPROC=y
CONFIG_CMD_SPI=y
CONFIG_CMD_TEMPERATURE=y
CONFIG_CMD_USB=y
+CONFIG_CMD_WDT=y
CONFIG_CMD_AXI=y
CONFIG_CMD_CAT=y
CONFIG_CMD_SETEXPR_FMT=y
@@ -314,6 +315,7 @@ CONFIG_W1_EEPROM_SANDBOX=y
CONFIG_WDT=y
CONFIG_WDT_GPIO=y
CONFIG_WDT_SANDBOX=y
+CONFIG_WDT_ALARM_SANDBOX=y
CONFIG_FS_CBFS=y
CONFIG_FS_CRAMFS=y
CONFIG_ADDR_MAP=y
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index e55deaf906b..29e375e1178 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -281,6 +281,14 @@ config WDT_SANDBOX
can be probed and supports all of the methods of WDT, but does not
really do anything.
+config WDT_ALARM_SANDBOX
+ bool "Enable SIGALRM-based Watchdog Timer support for Sandbox"
+ depends on SANDBOX && WDT
+ help
+ Enable support for a SIGALRM-based watchdog timer in Sandbox. This is
+ a watchdog device based on the host OS' alarm() function, which will
+ kill the sandbox with SIGALRM unless properly maintained.
+
config WDT_SBSA
bool "SBSA watchdog timer support"
depends on WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 0e2f582a5f9..446d961d7d2 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_DESIGNWARE_WATCHDOG) += designware_wdt.o
obj-$(CONFIG_ULP_WATCHDOG) += ulp_wdog.o
obj-$(CONFIG_$(SPL_TPL_)WDT) += wdt-uclass.o
obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.o
+obj-$(CONFIG_WDT_ALARM_SANDBOX) += sandbox_alarm-wdt.o
obj-$(CONFIG_WDT_APPLE) += apple_wdt.o
obj-$(CONFIG_WDT_ARMADA_37XX) += armada-37xx-wdt.o
obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o
diff --git a/drivers/watchdog/sandbox_alarm-wdt.c b/drivers/watchdog/sandbox_alarm-wdt.c
new file mode 100644
index 00000000000..71bb5d924ea
--- /dev/null
+++ b/drivers/watchdog/sandbox_alarm-wdt.c
@@ -0,0 +1,79 @@
+#include <common.h>
+#include <dm.h>
+#include <os.h>
+#include <wdt.h>
+
+struct alarm_wdt_priv {
+ unsigned int timeout_sec;
+};
+
+static void alarm_handler(int sig)
+{
+ const char *msg = "!!! ALARM !!!\n";
+
+ os_write(2, msg, strlen(msg));
+ os_fd_restore();
+ os_set_alarm_handler(NULL);
+ os_raise_sigalrm();
+}
+
+static int alarm_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+ struct alarm_wdt_priv *priv = dev_get_priv(dev);
+ unsigned int sec;
+
+ timeout = DIV_ROUND_UP(timeout, 1000);
+ sec = min_t(u64, UINT_MAX, timeout);
+ priv->timeout_sec = sec;
+
+ os_alarm(0);
+ os_set_alarm_handler(alarm_handler);
+ os_alarm(sec);
+
+ return 0;
+}
+
+static int alarm_wdt_stop(struct udevice *dev)
+{
+ os_alarm(0);
+ os_set_alarm_handler(NULL);
+
+ return 0;
+}
+
+static int alarm_wdt_reset(struct udevice *dev)
+{
+ struct alarm_wdt_priv *priv = dev_get_priv(dev);
+
+ os_alarm(priv->timeout_sec);
+
+ return 0;
+}
+
+static int alarm_wdt_expire_now(struct udevice *dev, ulong flags)
+{
+ alarm_handler(0);
+
+ return 0;
+}
+
+
+static const struct wdt_ops alarm_wdt_ops = {
+ .start = alarm_wdt_start,
+ .reset = alarm_wdt_reset,
+ .stop = alarm_wdt_stop,
+ .expire_now = alarm_wdt_expire_now,
+};
+
+static const struct udevice_id alarm_wdt_ids[] = {
+ { .compatible = "sandbox,alarm-wdt" },
+ {}
+};
+
+U_BOOT_DRIVER(alarm_wdt_sandbox) = {
+ .name = "alarm_wdt_sandbox",
+ .id = UCLASS_WDT,
+ .of_match = alarm_wdt_ids,
+ .ops = &alarm_wdt_ops,
+ .priv_auto = sizeof(struct alarm_wdt_priv),
+};
diff --git a/include/os.h b/include/os.h
index 5b353ae9d94..54874f5e0e8 100644
--- a/include/os.h
+++ b/include/os.h
@@ -109,6 +109,23 @@ int os_unlink(const char *pathname);
void os_exit(int exit_code) __attribute__((noreturn));
/**
+ * os_alarm() - access to the OS alarm() system call
+ */
+unsigned int os_alarm(unsigned int seconds);
+
+/**
+ * os_set_alarm_handler() - set handler for SIGALRM
+ *
+ * @handler: The handler function. Pass NULL for SIG_DFL.
+ */
+void os_set_alarm_handler(void (*handler)(int));
+
+/**
+ * os_raise_sigalrm() - do raise(SIGALRM)
+ */
+void os_raise_sigalrm(void);
+
+/**
* os_tty_raw() - put tty into raw mode to mimic serial console better
*
* @fd: File descriptor of stdin (normally 0)