sandbox: add SIGALRM-based watchdog device
In order to test that U-Boot actually maintains the watchdog device(s) during long-running busy-loops, such as those where we wait for the user to stop autoboot, we need a watchdog device that actually does something during those loops; we cannot test that behaviour via the DM test framework. So introduce a relatively simple watchdog device which is simply based on calling the host OS' alarm() function; that has the nice property that a new call to alarm() simply sets a new deadline, and alarm(0) cancels any existing alarm. These properties are precisely what we need to implement start/reset/stop. We install our own handler so that we get a known message printed if and when the watchdog fires, and by just invoking that handler directly, we get expire_now for free. The actual calls to the various OS functions (alarm, signal, raise) need to be done in os.c, and since the driver code cannot get access to the values of SIGALRM or SIG_DFL (that would require including a host header, and that's only os.c which can do that), we cannot simply do trivial wrappers for signal() and raise(), but instead create specialized functions just for use by this driver. Apart from enabling this driver for sandbox{,64}_defconfig, also enable the wdt command which was useful for hand-testing this new driver (especially with running u-boot under strace). Signed-off-by: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
This commit is contained in:
parent
2783670583
commit
10107efedd
@ -130,6 +130,23 @@ void os_exit(int exit_code)
|
|||||||
exit(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 os_write_file(const char *fname, const void *buf, int size)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
@ -56,6 +56,7 @@ CONFIG_CMD_REMOTEPROC=y
|
|||||||
CONFIG_CMD_SPI=y
|
CONFIG_CMD_SPI=y
|
||||||
CONFIG_CMD_USB=y
|
CONFIG_CMD_USB=y
|
||||||
CONFIG_CMD_CAT=y
|
CONFIG_CMD_CAT=y
|
||||||
|
CONFIG_CMD_WDT=y
|
||||||
CONFIG_BOOTP_DNS2=y
|
CONFIG_BOOTP_DNS2=y
|
||||||
CONFIG_CMD_TFTPPUT=y
|
CONFIG_CMD_TFTPPUT=y
|
||||||
CONFIG_CMD_TFTPSRV=y
|
CONFIG_CMD_TFTPSRV=y
|
||||||
@ -238,6 +239,7 @@ CONFIG_SPLASH_SCREEN_ALIGN=y
|
|||||||
CONFIG_WDT=y
|
CONFIG_WDT=y
|
||||||
CONFIG_WDT_GPIO=y
|
CONFIG_WDT_GPIO=y
|
||||||
CONFIG_WDT_SANDBOX=y
|
CONFIG_WDT_SANDBOX=y
|
||||||
|
CONFIG_WDT_ALARM_SANDBOX=y
|
||||||
CONFIG_FS_CBFS=y
|
CONFIG_FS_CBFS=y
|
||||||
CONFIG_FS_CRAMFS=y
|
CONFIG_FS_CRAMFS=y
|
||||||
CONFIG_CMD_DHRYSTONE=y
|
CONFIG_CMD_DHRYSTONE=y
|
||||||
|
@ -80,6 +80,7 @@ CONFIG_CMD_REMOTEPROC=y
|
|||||||
CONFIG_CMD_SPI=y
|
CONFIG_CMD_SPI=y
|
||||||
CONFIG_CMD_TEMPERATURE=y
|
CONFIG_CMD_TEMPERATURE=y
|
||||||
CONFIG_CMD_USB=y
|
CONFIG_CMD_USB=y
|
||||||
|
CONFIG_CMD_WDT=y
|
||||||
CONFIG_CMD_AXI=y
|
CONFIG_CMD_AXI=y
|
||||||
CONFIG_CMD_CAT=y
|
CONFIG_CMD_CAT=y
|
||||||
CONFIG_CMD_SETEXPR_FMT=y
|
CONFIG_CMD_SETEXPR_FMT=y
|
||||||
@ -314,6 +315,7 @@ CONFIG_W1_EEPROM_SANDBOX=y
|
|||||||
CONFIG_WDT=y
|
CONFIG_WDT=y
|
||||||
CONFIG_WDT_GPIO=y
|
CONFIG_WDT_GPIO=y
|
||||||
CONFIG_WDT_SANDBOX=y
|
CONFIG_WDT_SANDBOX=y
|
||||||
|
CONFIG_WDT_ALARM_SANDBOX=y
|
||||||
CONFIG_FS_CBFS=y
|
CONFIG_FS_CBFS=y
|
||||||
CONFIG_FS_CRAMFS=y
|
CONFIG_FS_CRAMFS=y
|
||||||
CONFIG_ADDR_MAP=y
|
CONFIG_ADDR_MAP=y
|
||||||
|
@ -281,6 +281,14 @@ config WDT_SANDBOX
|
|||||||
can be probed and supports all of the methods of WDT, but does not
|
can be probed and supports all of the methods of WDT, but does not
|
||||||
really do anything.
|
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
|
config WDT_SBSA
|
||||||
bool "SBSA watchdog timer support"
|
bool "SBSA watchdog timer support"
|
||||||
depends on WDT
|
depends on WDT
|
||||||
|
@ -16,6 +16,7 @@ obj-$(CONFIG_DESIGNWARE_WATCHDOG) += designware_wdt.o
|
|||||||
obj-$(CONFIG_ULP_WATCHDOG) += ulp_wdog.o
|
obj-$(CONFIG_ULP_WATCHDOG) += ulp_wdog.o
|
||||||
obj-$(CONFIG_$(SPL_TPL_)WDT) += wdt-uclass.o
|
obj-$(CONFIG_$(SPL_TPL_)WDT) += wdt-uclass.o
|
||||||
obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.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_APPLE) += apple_wdt.o
|
||||||
obj-$(CONFIG_WDT_ARMADA_37XX) += armada-37xx-wdt.o
|
obj-$(CONFIG_WDT_ARMADA_37XX) += armada-37xx-wdt.o
|
||||||
obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o
|
obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o
|
||||||
|
79
drivers/watchdog/sandbox_alarm-wdt.c
Normal file
79
drivers/watchdog/sandbox_alarm-wdt.c
Normal file
@ -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),
|
||||||
|
};
|
17
include/os.h
17
include/os.h
@ -108,6 +108,23 @@ int os_unlink(const char *pathname);
|
|||||||
*/
|
*/
|
||||||
void os_exit(int exit_code) __attribute__((noreturn));
|
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
|
* os_tty_raw() - put tty into raw mode to mimic serial console better
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user