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-all mailing list