Home | History | Annotate | Line # | Download | only in sysmon
swwdog.c revision 1.2
      1 /*	$NetBSD: swwdog.c,v 1.2 2005/02/27 00:27:49 perry Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2004, 2005 Steven M. Bellovin
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *      This product includes software developed by Steven M. Bellovin
     18  * 4. The name of the author contributors may not be used to endorse or
     19  *    promote products derived from this software without specific prior
     20  *    written permission.
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS
     23  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     25  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
     26  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     32  * POSSIBILITY OF SUCH DAMAGE.
     33  */
     34 
     35 #include <sys/cdefs.h>
     36 __KERNEL_RCSID(0, "$NetBSD: swwdog.c,v 1.2 2005/02/27 00:27:49 perry Exp $");
     37 
     38 /*
     39  *
     40  * Software watchdog timer
     41  *
     42  */
     43 #include <sys/param.h>
     44 #include <sys/callout.h>
     45 #include <sys/cdefs.h>
     46 #include <sys/device.h>
     47 #include <sys/kernel.h>
     48 #include <sys/reboot.h>
     49 #include <sys/systm.h>
     50 #include <sys/wdog.h>
     51 #include <dev/sysmon/sysmonvar.h>
     52 
     53 #include "swwdog.h"
     54 
     55 struct swwdog_softc {
     56 	struct sysmon_wdog sc_smw;
     57 	struct callout sc_c;
     58 	char sc_name[20];
     59 	int sc_wdog_armed;
     60 } sc_wdog[NSWWDOG];
     61 
     62 void	swwdogattach(int);
     63 
     64 static int swwdog_setmode(struct sysmon_wdog *);
     65 static int swwdog_tickle(struct sysmon_wdog *);
     66 
     67 static int swwdog_arm(struct swwdog_softc *);
     68 static int swwdog_disarm(struct swwdog_softc *);
     69 
     70 static void swwdog_panic(void *);
     71 
     72 int swwdog_reboot = 0;		/* set for panic instead of reboot */
     73 
     74 #define	SWDOG_DEFAULT	60		/* 60-second default period */
     75 
     76 void
     77 swwdogattach(int count)
     78 {
     79 	int i;
     80 
     81 	for (i = 0; i < NSWWDOG; i++) {
     82 		struct swwdog_softc *sc = &sc_wdog[i];
     83 
     84 		snprintf(sc->sc_name, sizeof sc->sc_name, "swwdog%d", i);
     85 		printf("%s: ", sc->sc_name);
     86 		sc->sc_smw.smw_name = sc->sc_name;
     87 		sc->sc_smw.smw_cookie = sc;
     88 		sc->sc_smw.smw_setmode = swwdog_setmode;
     89 		sc->sc_smw.smw_tickle = swwdog_tickle;
     90 		sc->sc_smw.smw_period = SWDOG_DEFAULT;
     91 		callout_init(&sc->sc_c);
     92 		callout_setfunc(&sc->sc_c, swwdog_panic, sc);
     93 
     94 		if (sysmon_wdog_register(&sc->sc_smw) == 0)
     95 			printf("software watchdog initialized\n");
     96 		else printf("unable to register software watchdog "
     97 				"with sysmon\n");
     98 	}
     99 }
    100 
    101 static int
    102 swwdog_setmode(struct sysmon_wdog *smw)
    103 {
    104 	struct swwdog_softc *sc = smw->smw_cookie;
    105 	int error = 0;
    106 
    107 	if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) {
    108 		error = swwdog_disarm(sc);
    109 	} else {
    110 		if (smw->smw_period == 0)
    111 			return EINVAL;
    112 		else if (smw->smw_period == WDOG_PERIOD_DEFAULT)
    113 			sc->sc_smw.smw_period = SWDOG_DEFAULT;
    114 		else sc->sc_smw.smw_period = smw->smw_period;
    115 		error = swwdog_arm(sc);
    116 	}
    117 	return error;
    118 }
    119 
    120 static int
    121 swwdog_tickle(struct sysmon_wdog *smw)
    122 {
    123 
    124 	return swwdog_arm(smw->smw_cookie);
    125 }
    126 
    127 static int
    128 swwdog_arm(struct swwdog_softc *sc)
    129 {
    130 
    131 	callout_schedule(&sc->sc_c, sc->sc_smw.smw_period * hz);
    132 	return 0;
    133 }
    134 
    135 static int
    136 swwdog_disarm(struct swwdog_softc *sc)
    137 {
    138 
    139 	callout_stop(&sc->sc_c);
    140 	return 0;
    141 }
    142 
    143 static void
    144 swwdog_panic(void *vsc)
    145 {
    146 	struct swwdog_softc *sc = vsc;
    147 	int do_panic;
    148 
    149 	do_panic = swwdog_reboot;
    150 	swwdog_reboot = 1;
    151 	callout_schedule(&sc->sc_c, 60 * hz);	/* deliberate double-panic */
    152 
    153 	printf("%s: %d second timer expired", sc->sc_name,
    154 	    sc->sc_smw.smw_period);
    155 
    156 	if (do_panic)
    157 		panic("watchdog timer expired");
    158 	else cpu_reboot(0, NULL);
    159 }
    160