svn commit: r327920 - in stable/11: share/man/man4 sys/conf sys/dev/watchdog sys/kern sys/sys
Mike Karels
karels at FreeBSD.org
Sat Jan 13 14:10:07 UTC 2018
Author: karels
Date: Sat Jan 13 14:10:05 2018
New Revision: 327920
URL: https://svnweb.freebsd.org/changeset/base/327920
Log:
MFC r327505:
make SW_WATCHDOG dynamic
Enable the hardclock-based watchdog previously conditional on the
SW_WATCHDOG option whenever hardware watchdogs are not found, and
watchdogd attempts to enable the watchdog. The SW_WATCHDOG option
still causes the sofware watchdog to be enabled even if there is a
hardware watchdog. This does not change the other software-based
watchdog enabled by the --softtimeout option to watchdogd.
Note that the code to reprime the watchdog during kernel core dumps is
no longer conditional on SW_WATCHDOG. I think this was previously a bug.
Reviewed by: imp alfred bjk
MFC after: 1 week
Relnotes: yes
Differential Revision: https://reviews.freebsd.org/D13713
Modified:
stable/11/share/man/man4/watchdog.4
stable/11/sys/conf/NOTES
stable/11/sys/dev/watchdog/watchdog.c
stable/11/sys/kern/kern_clock.c
stable/11/sys/kern/kern_dump.c
stable/11/sys/sys/watchdog.h
Modified: stable/11/share/man/man4/watchdog.4
==============================================================================
--- stable/11/share/man/man4/watchdog.4 Sat Jan 13 13:59:35 2018 (r327919)
+++ stable/11/share/man/man4/watchdog.4 Sat Jan 13 14:10:05 2018 (r327920)
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd December 21, 2009
+.Dd January 2, 2018
.Dt WATCHDOG 4
.Os
.Sh NAME
@@ -40,8 +40,11 @@ facility is used for controlling hardware and software
.Pp
The device
.Pa /dev/fido
-responds to a single
+supports several optional
.Xr ioctl 2
+calls for configuration, and
+responds to a single operational
+.Xr ioctl
call,
.Dv WDIOCPATPAT .
It takes a single argument which represents a timeout value specified as a
@@ -60,12 +63,16 @@ indicates that the
will be kept from timing out from the kernel.
.Pp
The
+.Dv WDIOCPATPAT
.Xr ioctl 2
call will return success if just one of the available
.Xr watchdog 9
implementations supports setting the timeout to the specified timeout.
This
means that at least one watchdog is armed.
+By default, this will be a hardware watchdog if one is present, but if
+no hardware watchdog is able to process the request, a default software
+watchdog is enabled.
If the call fails, for instance if
none of
.Xr watchdog 9
@@ -77,8 +84,53 @@ To disable the watchdogs pass
If disarming the watchdog(s) failed an error is returned.
The watchdog might
still be armed!
+.Pp
+The optional configuration
+.Xr ioctl
+commands are listed here, along with the type of the parameter used.
+Examples of their use can be found in
+.Xr watchdogd 8 .
+.Bl -tag -width "WDIOC_SETSOFTTIMEOUTACT int "
+.It Dv WDIOC_SETTIMEOUT Fa int
+set/reset the timer
+.It Dv WDIOC_GETTIMEOUT Fa int
+get total timeout
+.It Dv WDIOC_GETTIMELEFT Fa int
+get time left
+.It Dv WDIOC_GETPRETIMEOUT Fa int
+get the pre-timeout
+.It Dv WDIOC_SETPRETIMEOUT Fa int
+set the pre-timeout
+.It Dv WDIOC_SETPRETIMEOUTACT Fa int
+Set the action when a pre-timeout occurs (see
+.Li WD_SOFT_*
+below).
+.It Dv WDIOC_SETSOFT Fa int
+Use an internal software watchdog instead of hardware.
+There is also an external software watchdog, which is used by default
+if no hardware watchdog was attached.
+.It Dv WDIOC_SETSOFTTIMEOUTACT Fa int
+Set the action whan a soft timeout occurs.
+.El
+.Pp
+The actions that may be specified for the pre-timeout or the internal software
+watchdog are listed here.
+Multiple actions can be specified by ORing values together.
+.Bl -tag -width WD_SOFT_PRINT
+.It Dv WD_SOFT_PANIC
+panic
+.It Dv WD_SOFT_DDB
+enter debugger
+.It Dv WD_SOFT_LOG
+log(9)
+.It Dv WD_SOFT_PRINT
+printf(9)
+.El
.Sh RETURN VALUES
-The ioctl returns zero on success and non-zero on failure.
+The
+.Dv WDIOCPATPAT
+.Xr ioctl
+returns zero on success and non-zero on failure.
.Bl -tag -width Er
.It Bq Er EOPNOTSUPP
No watchdog present in the kernel or
@@ -89,6 +141,10 @@ Watchdog could not be disabled (timeout value of 0).
.It Bq Er EINVAL
Invalid flag combination passed.
.El
+.Pp
+The configuration
+.Xr ioctl
+operations return zero on success and non-zero on failure.
.Sh EXAMPLES
.Bd -literal -offset indent
#include <paths.h>
@@ -122,8 +178,10 @@ Enables a watchdog to recover from a potentially freez
.Pp
.Dl "options SW_WATCHDOG"
.Pp
-in your kernel config adds a software watchdog in the kernel, dropping to KDB
-or panic-ing when firing.
+in your kernel config forces a software watchdog in the kernel
+to be configured even if a hardware watchdog is configured,
+dropping to KDB or panicking when firing, depending
+on the KDB and KDB_UNATTENDED kernel configuration options.
.Sh SEE ALSO
.Xr watchdogd 8 ,
.Xr watchdog 9
Modified: stable/11/sys/conf/NOTES
==============================================================================
--- stable/11/sys/conf/NOTES Sat Jan 13 13:59:35 2018 (r327919)
+++ stable/11/sys/conf/NOTES Sat Jan 13 14:10:05 2018 (r327920)
@@ -2656,7 +2656,9 @@ options BOOTP_WIRED_TO=fxp0 # Use interface fxp0 for
options BOOTP_BLOCKSIZE=8192 # Override NFS block size
#
-# Add software watchdog routines.
+# Enable software watchdog routines, even if hardware watchdog is present.
+# By default, software watchdog timer is enabled only if no hardware watchdog
+# is present.
#
options SW_WATCHDOG
Modified: stable/11/sys/dev/watchdog/watchdog.c
==============================================================================
--- stable/11/sys/dev/watchdog/watchdog.c Sat Jan 13 13:59:35 2018 (r327919)
+++ stable/11/sys/dev/watchdog/watchdog.c Sat Jan 13 14:10:05 2018 (r327920)
@@ -76,6 +76,9 @@ SYSCTL_UINT(_hw_watchdog, OID_AUTO, wd_last_u_secs, CT
static int wd_lastpat_valid = 0;
static time_t wd_lastpat = 0; /* when the watchdog was last patted */
+/* Hook for external software watchdog to register for use if needed */
+void (*wdog_software_attach)(void);
+
static void
pow2ns_to_ts(int pow2ns, struct timespec *ts)
{
@@ -118,6 +121,7 @@ int
wdog_kern_pat(u_int utim)
{
int error;
+ static int first = 1;
if ((utim & WD_LASTVAL) != 0 && (utim & WD_INTERVAL) > 0)
return (EINVAL);
@@ -159,6 +163,17 @@ wdog_kern_pat(u_int utim)
} else {
EVENTHANDLER_INVOKE(watchdog_list, utim, &error);
}
+ /*
+ * If we no hardware watchdog responded, we have not tried to
+ * attach an external software watchdog, and one is available,
+ * attach it now and retry.
+ */
+ if (error == EOPNOTSUPP && first && *wdog_software_attach != NULL) {
+ (*wdog_software_attach)();
+ EVENTHANDLER_INVOKE(watchdog_list, utim, &error);
+ }
+ first = 0;
+
wd_set_pretimeout(wd_pretimeout, true);
/*
* If we were able to arm/strobe the watchdog, then
Modified: stable/11/sys/kern/kern_clock.c
==============================================================================
--- stable/11/sys/kern/kern_clock.c Sat Jan 13 13:59:35 2018 (r327919)
+++ stable/11/sys/kern/kern_clock.c Sat Jan 13 14:10:05 2018 (r327920)
@@ -333,15 +333,19 @@ read_cpu_time(long *cp_time)
}
}
-#ifdef SW_WATCHDOG
#include <sys/watchdog.h>
static int watchdog_ticks;
static int watchdog_enabled;
static void watchdog_fire(void);
static void watchdog_config(void *, u_int, int *);
-#endif /* SW_WATCHDOG */
+static void
+watchdog_attach(void)
+{
+ EVENTHANDLER_REGISTER(watchdog_list, watchdog_config, NULL, 0);
+}
+
/*
* Clock handling routines.
*
@@ -409,8 +413,14 @@ initclocks(dummy)
if (profhz == 0)
profhz = i;
psratio = profhz / i;
+
#ifdef SW_WATCHDOG
- EVENTHANDLER_REGISTER(watchdog_list, watchdog_config, NULL, 0);
+ /* Enable hardclock watchdog now, even if a hardware watchdog exists. */
+ watchdog_attach();
+#else
+ /* Volunteer to run a software watchdog. */
+ if (wdog_software_attach == NULL)
+ wdog_software_attach = watchdog_attach;
#endif
}
@@ -481,10 +491,8 @@ hardclock(int usermode, uintfptr_t pc)
#ifdef DEVICE_POLLING
hardclock_device_poll(); /* this is very short and quick */
#endif /* DEVICE_POLLING */
-#ifdef SW_WATCHDOG
if (watchdog_enabled > 0 && --watchdog_ticks <= 0)
watchdog_fire();
-#endif /* SW_WATCHDOG */
}
void
@@ -495,9 +503,7 @@ hardclock_cnt(int cnt, int usermode)
struct proc *p = td->td_proc;
int *t = DPCPU_PTR(pcputicks);
int flags, global, newticks;
-#ifdef SW_WATCHDOG
int i;
-#endif /* SW_WATCHDOG */
/*
* Update per-CPU and possibly global ticks values.
@@ -557,13 +563,11 @@ hardclock_cnt(int cnt, int usermode)
atomic_store_rel_int(&devpoll_run, 0);
}
#endif /* DEVICE_POLLING */
-#ifdef SW_WATCHDOG
if (watchdog_enabled > 0) {
i = atomic_fetchadd_int(&watchdog_ticks, -newticks);
if (i > 0 && i <= newticks)
watchdog_fire();
}
-#endif /* SW_WATCHDOG */
}
if (curcpu == CPU_FIRST())
cpu_tick_calibration();
@@ -841,8 +845,6 @@ SYSCTL_PROC(_kern, KERN_CLOCKRATE, clockrate,
0, 0, sysctl_kern_clockrate, "S,clockinfo",
"Rate and period of various kernel clocks");
-#ifdef SW_WATCHDOG
-
static void
watchdog_config(void *unused __unused, u_int cmd, int *error)
{
@@ -891,5 +893,3 @@ watchdog_fire(void)
panic("watchdog timeout");
#endif
}
-
-#endif /* SW_WATCHDOG */
Modified: stable/11/sys/kern/kern_dump.c
==============================================================================
--- stable/11/sys/kern/kern_dump.c Sat Jan 13 13:59:35 2018 (r327919)
+++ stable/11/sys/kern/kern_dump.c Sat Jan 13 14:10:05 2018 (r327920)
@@ -27,8 +27,6 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include "opt_watchdog.h"
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
@@ -36,9 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/kerneldump.h>
-#ifdef SW_WATCHDOG
#include <sys/watchdog.h>
-#endif
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/pmap.h>
@@ -195,9 +191,7 @@ dumpsys_cb_dumpdata(struct dump_pa *mdp, int seqnr, vo
}
dumpsys_map_chunk(pa, chunk, &va);
-#ifdef SW_WATCHDOG
wdog_kern_pat(WD_LASTVAL);
-#endif
error = dump_write(di, va, 0, dumplo, sz);
dumpsys_unmap_chunk(pa, chunk, va);
Modified: stable/11/sys/sys/watchdog.h
==============================================================================
--- stable/11/sys/sys/watchdog.h Sat Jan 13 13:59:35 2018 (r327919)
+++ stable/11/sys/sys/watchdog.h Sat Jan 13 14:10:05 2018 (r327920)
@@ -110,6 +110,14 @@ EVENTHANDLER_DECLARE(watchdog_list, watchdog_fn);
u_int wdog_kern_last_timeout(void);
int wdog_kern_pat(u_int utim);
+
+/*
+ * The following function pointer is used to attach a software watchdog
+ * if no hardware watchdog has been attached, and if the software module
+ * has initialized the function pointer.
+ */
+
+extern void (*wdog_software_attach)(void);
#endif
#endif /* _SYS_WATCHDOG_H */
More information about the svn-src-stable
mailing list