ia64/xen-unstable

changeset 4720:43be76d016ea

bitkeeper revision 1.1389.1.17 (427346c0aRp-AQNVyrLuVwZpeN01Sg)

crash.patch
FreeBSD calls domain_crash() on error so that its core is dumped.
Signed-off-by: Kip Macy <kmacy@fsmware.com>
author kaf24@firebug.cl.cam.ac.uk[kaf24]
date Sat Apr 30 08:50:08 2005 +0000 (2005-04-30)
parents 70c0c5349780
children 04c1feb7c674
files .rootkeys freebsd-5.3-xen-sparse/i386-xen/include/hypervisor.h freebsd-5.3-xen-sparse/kern/kern_shutdown.c
line diff
     1.1 --- a/.rootkeys	Sat Apr 30 08:45:02 2005 +0000
     1.2 +++ b/.rootkeys	Sat Apr 30 08:50:08 2005 +0000
     1.3 @@ -121,6 +121,7 @@ 423e7e8d4LBg7lzjHtssnxcZwezLJQ freebsd-5
     1.4  423e7e8dVX2QkuzWwB2rtZDxD5Y_-w freebsd-5.3-xen-sparse/i386-xen/xen/misc/npx.c
     1.5  423e7e8d_PdWXjQeRg75twh7TleJhQ freebsd-5.3-xen-sparse/i386-xen/xen/netfront/xn_netfront.c
     1.6  423e7e8dlsc1oCW_ul57w0AHY5jZjQ freebsd-5.3-xen-sparse/kern/kern_fork.c
     1.7 +427346bfHJQldVgD-acDy_2toKMhTA freebsd-5.3-xen-sparse/kern/kern_shutdown.c
     1.8  423e7e8dVDL1WLfbmQWuXMbetYk4jA freebsd-5.3-xen-sparse/mkbuildtree
     1.9  423e7e8dBrOrAbydK6h49bY0VvDgPw freebsd-5.3-xen-sparse/xenfbsd_kernel_build
    1.10  4187ca95_eQN62ugV1zliQcfzXrHnw install.sh
     2.1 --- a/freebsd-5.3-xen-sparse/i386-xen/include/hypervisor.h	Sat Apr 30 08:45:02 2005 +0000
     2.2 +++ b/freebsd-5.3-xen-sparse/i386-xen/include/hypervisor.h	Sat Apr 30 08:50:08 2005 +0000
     2.3 @@ -22,6 +22,7 @@ extern start_info_t *xen_start_info;
     2.4   * be MACHINE addresses.
     2.5   */
     2.6  
     2.7 +static inline void HYPERVISOR_crash(void) __dead2;
     2.8  
     2.9  void MULTICALL_flush_page_update_queue(void);
    2.10  
    2.11 @@ -201,6 +202,23 @@ HYPERVISOR_suspend(unsigned long srec)
    2.12      return ret;
    2.13  }
    2.14  
    2.15 +
    2.16 +static inline void
    2.17 +HYPERVISOR_crash(void) 
    2.18 +{
    2.19 +    int ret;
    2.20 +    unsigned long ign1;
    2.21 +    __asm__ __volatile__ (
    2.22 +        TRAP_INSTR
    2.23 +        : "=a" (ret), "=b" (ign1)
    2.24 +        : "0" (__HYPERVISOR_sched_op),
    2.25 +	"1" (SCHEDOP_shutdown | (SHUTDOWN_crash << SCHEDOP_reasonshift))
    2.26 +        : "memory" );
    2.27 +
    2.28 +	for (;;) ; /* eliminate noreturn error */ 
    2.29 +
    2.30 +}
    2.31 +
    2.32  static inline long 
    2.33  HYPERVISOR_set_timer_op(uint64_t timeout)
    2.34  {
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/freebsd-5.3-xen-sparse/kern/kern_shutdown.c	Sat Apr 30 08:50:08 2005 +0000
     3.3 @@ -0,0 +1,635 @@
     3.4 +/*-
     3.5 + * Copyright (c) 1986, 1988, 1991, 1993
     3.6 + *	The Regents of the University of California.  All rights reserved.
     3.7 + * (c) UNIX System Laboratories, Inc.
     3.8 + * All or some portions of this file are derived from material licensed
     3.9 + * to the University of California by American Telephone and Telegraph
    3.10 + * Co. or Unix System Laboratories, Inc. and are reproduced herein with
    3.11 + * the permission of UNIX System Laboratories, Inc.
    3.12 + *
    3.13 + * Redistribution and use in source and binary forms, with or without
    3.14 + * modification, are permitted provided that the following conditions
    3.15 + * are met:
    3.16 + * 1. Redistributions of source code must retain the above copyright
    3.17 + *    notice, this list of conditions and the following disclaimer.
    3.18 + * 2. Redistributions in binary form must reproduce the above copyright
    3.19 + *    notice, this list of conditions and the following disclaimer in the
    3.20 + *    documentation and/or other materials provided with the distribution.
    3.21 + * 4. Neither the name of the University nor the names of its contributors
    3.22 + *    may be used to endorse or promote products derived from this software
    3.23 + *    without specific prior written permission.
    3.24 + *
    3.25 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    3.26 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    3.27 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    3.28 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    3.29 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    3.30 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    3.31 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    3.32 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    3.33 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    3.34 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    3.35 + * SUCH DAMAGE.
    3.36 + *
    3.37 + *	@(#)kern_shutdown.c	8.3 (Berkeley) 1/21/94
    3.38 + */
    3.39 +
    3.40 +#include <sys/cdefs.h>
    3.41 +__FBSDID("$FreeBSD: src/sys/kern/kern_shutdown.c,v 1.163.2.2 2004/09/10 00:04:17 scottl Exp $");
    3.42 +
    3.43 +#include "opt_kdb.h"
    3.44 +#include "opt_hw_wdog.h"
    3.45 +#include "opt_mac.h"
    3.46 +#include "opt_panic.h"
    3.47 +#include "opt_show_busybufs.h"
    3.48 +#include "opt_sched.h"
    3.49 +
    3.50 +#include <sys/param.h>
    3.51 +#include <sys/systm.h>
    3.52 +#include <sys/bio.h>
    3.53 +#include <sys/buf.h>
    3.54 +#include <sys/conf.h>
    3.55 +#include <sys/cons.h>
    3.56 +#include <sys/eventhandler.h>
    3.57 +#include <sys/kdb.h>
    3.58 +#include <sys/kernel.h>
    3.59 +#include <sys/kthread.h>
    3.60 +#include <sys/mac.h>
    3.61 +#include <sys/malloc.h>
    3.62 +#include <sys/mount.h>
    3.63 +#include <sys/proc.h>
    3.64 +#include <sys/reboot.h>
    3.65 +#include <sys/resourcevar.h>
    3.66 +#include <sys/smp.h>		/* smp_active */
    3.67 +#include <sys/sysctl.h>
    3.68 +#include <sys/sysproto.h>
    3.69 +#include <sys/vnode.h>
    3.70 +
    3.71 +#include <machine/cpu.h>
    3.72 +#include <machine/pcb.h>
    3.73 +#include <machine/smp.h>
    3.74 +
    3.75 +#include <sys/signalvar.h>
    3.76 +
    3.77 +#ifndef PANIC_REBOOT_WAIT_TIME
    3.78 +#define PANIC_REBOOT_WAIT_TIME 15 /* default to 15 seconds */
    3.79 +#endif
    3.80 +
    3.81 +/*
    3.82 + * Note that stdarg.h and the ANSI style va_start macro is used for both
    3.83 + * ANSI and traditional C compilers.
    3.84 + */
    3.85 +#include <machine/stdarg.h>
    3.86 +
    3.87 +#ifdef KDB
    3.88 +#ifdef KDB_UNATTENDED
    3.89 +int debugger_on_panic = 0;
    3.90 +#else
    3.91 +int debugger_on_panic = 1;
    3.92 +#endif
    3.93 +SYSCTL_INT(_debug, OID_AUTO, debugger_on_panic, CTLFLAG_RW,
    3.94 +	&debugger_on_panic, 0, "Run debugger on kernel panic");
    3.95 +
    3.96 +#ifdef KDB_TRACE
    3.97 +int trace_on_panic = 1;
    3.98 +#else
    3.99 +int trace_on_panic = 0;
   3.100 +#endif
   3.101 +SYSCTL_INT(_debug, OID_AUTO, trace_on_panic, CTLFLAG_RW,
   3.102 +	&trace_on_panic, 0, "Print stack trace on kernel panic");
   3.103 +#endif /* KDB */
   3.104 +
   3.105 +int sync_on_panic = 0;
   3.106 +SYSCTL_INT(_kern, OID_AUTO, sync_on_panic, CTLFLAG_RW,
   3.107 +	&sync_on_panic, 0, "Do a sync before rebooting from a panic");
   3.108 +
   3.109 +SYSCTL_NODE(_kern, OID_AUTO, shutdown, CTLFLAG_RW, 0, "Shutdown environment");
   3.110 +
   3.111 +#ifdef	HW_WDOG
   3.112 +/*
   3.113 + * If there is a hardware watchdog, point this at the function needed to
   3.114 + * hold it off.
   3.115 + * It's needed when the kernel needs to do some lengthy operations.
   3.116 + * e.g. in wd.c when dumping core.. It's most annoying to have
   3.117 + * your precious core-dump only half written because the wdog kicked in.
   3.118 + */
   3.119 +watchdog_tickle_fn wdog_tickler = NULL;
   3.120 +#endif	/* HW_WDOG */
   3.121 +
   3.122 +/*
   3.123 + * Variable panicstr contains argument to first call to panic; used as flag
   3.124 + * to indicate that the kernel has already called panic.
   3.125 + */
   3.126 +const char *panicstr;
   3.127 +
   3.128 +int dumping;				/* system is dumping */
   3.129 +static struct dumperinfo dumper;	/* our selected dumper */
   3.130 +
   3.131 +/* Context information for dump-debuggers. */
   3.132 +static struct pcb dumppcb;		/* Registers. */
   3.133 +static lwpid_t dumptid;			/* Thread ID. */
   3.134 +
   3.135 +static void boot(int) __dead2;
   3.136 +static void poweroff_wait(void *, int);
   3.137 +static void shutdown_halt(void *junk, int howto);
   3.138 +static void shutdown_panic(void *junk, int howto);
   3.139 +static void shutdown_reset(void *junk, int howto);
   3.140 +
   3.141 +/* register various local shutdown events */
   3.142 +static void
   3.143 +shutdown_conf(void *unused)
   3.144 +{
   3.145 +
   3.146 +	EVENTHANDLER_REGISTER(shutdown_final, poweroff_wait, NULL,
   3.147 +	    SHUTDOWN_PRI_FIRST);
   3.148 +	EVENTHANDLER_REGISTER(shutdown_final, shutdown_halt, NULL,
   3.149 +	    SHUTDOWN_PRI_LAST + 100);
   3.150 +	EVENTHANDLER_REGISTER(shutdown_final, shutdown_panic, NULL,
   3.151 +	    SHUTDOWN_PRI_LAST + 100);
   3.152 +	EVENTHANDLER_REGISTER(shutdown_final, shutdown_reset, NULL,
   3.153 +	    SHUTDOWN_PRI_LAST + 200);
   3.154 +}
   3.155 +
   3.156 +SYSINIT(shutdown_conf, SI_SUB_INTRINSIC, SI_ORDER_ANY, shutdown_conf, NULL)
   3.157 +
   3.158 +/*
   3.159 + * The system call that results in a reboot
   3.160 + *
   3.161 + * MPSAFE
   3.162 + */
   3.163 +/* ARGSUSED */
   3.164 +int
   3.165 +reboot(struct thread *td, struct reboot_args *uap)
   3.166 +{
   3.167 +	int error;
   3.168 +
   3.169 +	error = 0;
   3.170 +#ifdef MAC
   3.171 +	error = mac_check_system_reboot(td->td_ucred, uap->opt);
   3.172 +#endif
   3.173 +	if (error == 0)
   3.174 +		error = suser(td);
   3.175 +	if (error == 0) {
   3.176 +		mtx_lock(&Giant);
   3.177 +		boot(uap->opt);
   3.178 +		mtx_unlock(&Giant);
   3.179 +	}
   3.180 +	return (error);
   3.181 +}
   3.182 +
   3.183 +/*
   3.184 + * Called by events that want to shut down.. e.g  <CTL><ALT><DEL> on a PC
   3.185 + */
   3.186 +static int shutdown_howto = 0;
   3.187 +
   3.188 +void
   3.189 +shutdown_nice(int howto)
   3.190 +{
   3.191 +
   3.192 +	shutdown_howto = howto;
   3.193 +
   3.194 +	/* Send a signal to init(8) and have it shutdown the world */
   3.195 +	if (initproc != NULL) {
   3.196 +		PROC_LOCK(initproc);
   3.197 +		psignal(initproc, SIGINT);
   3.198 +		PROC_UNLOCK(initproc);
   3.199 +	} else {
   3.200 +		/* No init(8) running, so simply reboot */
   3.201 +		boot(RB_NOSYNC);
   3.202 +	}
   3.203 +	return;
   3.204 +}
   3.205 +static int	waittime = -1;
   3.206 +
   3.207 +static void
   3.208 +print_uptime(void)
   3.209 +{
   3.210 +	int f;
   3.211 +	struct timespec ts;
   3.212 +
   3.213 +	getnanouptime(&ts);
   3.214 +	printf("Uptime: ");
   3.215 +	f = 0;
   3.216 +	if (ts.tv_sec >= 86400) {
   3.217 +		printf("%ldd", (long)ts.tv_sec / 86400);
   3.218 +		ts.tv_sec %= 86400;
   3.219 +		f = 1;
   3.220 +	}
   3.221 +	if (f || ts.tv_sec >= 3600) {
   3.222 +		printf("%ldh", (long)ts.tv_sec / 3600);
   3.223 +		ts.tv_sec %= 3600;
   3.224 +		f = 1;
   3.225 +	}
   3.226 +	if (f || ts.tv_sec >= 60) {
   3.227 +		printf("%ldm", (long)ts.tv_sec / 60);
   3.228 +		ts.tv_sec %= 60;
   3.229 +		f = 1;
   3.230 +	}
   3.231 +	printf("%lds\n", (long)ts.tv_sec);
   3.232 +}
   3.233 +
   3.234 +static void
   3.235 +doadump(void)
   3.236 +{
   3.237 +
   3.238 +	/*
   3.239 +	 * Sometimes people have to call this from the kernel debugger. 
   3.240 +	 * (if 'panic' can not dump)
   3.241 +	 * Give them a clue as to why they can't dump.
   3.242 +	 */
   3.243 +	if (dumper.dumper == NULL) {
   3.244 +		printf("Cannot dump. No dump device defined.\n");
   3.245 +		return;
   3.246 +	}
   3.247 +
   3.248 +	savectx(&dumppcb);
   3.249 +	dumptid = curthread->td_tid;
   3.250 +	dumping++;
   3.251 +	dumpsys(&dumper);
   3.252 +}
   3.253 +
   3.254 +/*
   3.255 + *  Go through the rigmarole of shutting down..
   3.256 + * this used to be in machdep.c but I'll be dammned if I could see
   3.257 + * anything machine dependant in it.
   3.258 + */
   3.259 +static void
   3.260 +boot(int howto)
   3.261 +{
   3.262 +	static int first_buf_printf = 1;
   3.263 +
   3.264 +	/* collect extra flags that shutdown_nice might have set */
   3.265 +	howto |= shutdown_howto;
   3.266 +
   3.267 +	/* We are out of the debugger now. */
   3.268 +	kdb_active = 0;
   3.269 +
   3.270 +#ifdef SMP
   3.271 +	if (smp_active)
   3.272 +		printf("boot() called on cpu#%d\n", PCPU_GET(cpuid));
   3.273 +#endif
   3.274 +	/*
   3.275 +	 * Do any callouts that should be done BEFORE syncing the filesystems.
   3.276 +	 */
   3.277 +	EVENTHANDLER_INVOKE(shutdown_pre_sync, howto);
   3.278 +
   3.279 +	/* 
   3.280 +	 * Now sync filesystems
   3.281 +	 */
   3.282 +	if (!cold && (howto & RB_NOSYNC) == 0 && waittime < 0) {
   3.283 +		register struct buf *bp;
   3.284 +		int iter, nbusy, pbusy;
   3.285 +#ifndef PREEMPTION
   3.286 +		int subiter;
   3.287 +#endif
   3.288 +
   3.289 +		waittime = 0;
   3.290 +
   3.291 +		sync(&thread0, NULL);
   3.292 +
   3.293 +		/*
   3.294 +		 * With soft updates, some buffers that are
   3.295 +		 * written will be remarked as dirty until other
   3.296 +		 * buffers are written.
   3.297 +		 */
   3.298 +		for (iter = pbusy = 0; iter < 20; iter++) {
   3.299 +			nbusy = 0;
   3.300 +			for (bp = &buf[nbuf]; --bp >= buf; ) {
   3.301 +				if ((bp->b_flags & B_INVAL) == 0 &&
   3.302 +				    BUF_REFCNT(bp) > 0) {
   3.303 +					nbusy++;
   3.304 +				} else if ((bp->b_flags & (B_DELWRI | B_INVAL))
   3.305 +						== B_DELWRI) {
   3.306 +					/* bawrite(bp);*/
   3.307 +					nbusy++;
   3.308 +				}
   3.309 +			}
   3.310 +			if (nbusy == 0) {
   3.311 +				if (first_buf_printf)
   3.312 +					printf("No buffers busy after final sync");
   3.313 +				break;
   3.314 +			}
   3.315 +			if (first_buf_printf) {
   3.316 +				printf("Syncing disks, buffers remaining... ");
   3.317 +				first_buf_printf = 0;
   3.318 +			}
   3.319 +			printf("%d ", nbusy);
   3.320 +			if (nbusy < pbusy)
   3.321 +				iter = 0;
   3.322 +			pbusy = nbusy;
   3.323 +			sync(&thread0, NULL);
   3.324 +
   3.325 +#ifdef PREEMPTION
   3.326 +			/*
   3.327 +			 * Drop Giant and spin for a while to allow
   3.328 +			 * interrupt threads to run.
   3.329 +			 */
   3.330 +			DROP_GIANT();
   3.331 +			DELAY(50000 * iter);
   3.332 +			PICKUP_GIANT();
   3.333 +#else
   3.334 +			/*
   3.335 +			 * Drop Giant and context switch several times to
   3.336 +			 * allow interrupt threads to run.
   3.337 +			 */
   3.338 +			DROP_GIANT();
   3.339 +			for (subiter = 0; subiter < 50 * iter; subiter++) {
   3.340 +				mtx_lock_spin(&sched_lock);
   3.341 +				mi_switch(SW_VOL, NULL);
   3.342 +				mtx_unlock_spin(&sched_lock);
   3.343 +				DELAY(1000);
   3.344 +			}
   3.345 +			PICKUP_GIANT();
   3.346 +#endif
   3.347 +		}
   3.348 +		printf("\n");
   3.349 +		/*
   3.350 +		 * Count only busy local buffers to prevent forcing 
   3.351 +		 * a fsck if we're just a client of a wedged NFS server
   3.352 +		 */
   3.353 +		nbusy = 0;
   3.354 +		for (bp = &buf[nbuf]; --bp >= buf; ) {
   3.355 +			if (((bp->b_flags&B_INVAL) == 0 && BUF_REFCNT(bp)) ||
   3.356 +			    ((bp->b_flags & (B_DELWRI|B_INVAL)) == B_DELWRI)) {
   3.357 +				if (bp->b_dev == NULL) {
   3.358 +					TAILQ_REMOVE(&mountlist,
   3.359 +					    bp->b_vp->v_mount, mnt_list);
   3.360 +					continue;
   3.361 +				}
   3.362 +				nbusy++;
   3.363 +#if defined(SHOW_BUSYBUFS) || defined(DIAGNOSTIC)
   3.364 +				printf(
   3.365 +			    "%d: dev:%s, flags:%0x, blkno:%ld, lblkno:%ld\n",
   3.366 +				    nbusy, devtoname(bp->b_dev),
   3.367 +				    bp->b_flags, (long)bp->b_blkno,
   3.368 +				    (long)bp->b_lblkno);
   3.369 +#endif
   3.370 +			}
   3.371 +		}
   3.372 +		if (nbusy) {
   3.373 +			/*
   3.374 +			 * Failed to sync all blocks. Indicate this and don't
   3.375 +			 * unmount filesystems (thus forcing an fsck on reboot).
   3.376 +			 */
   3.377 +			printf("Giving up on %d buffers\n", nbusy);
   3.378 +			DELAY(5000000);	/* 5 seconds */
   3.379 +		} else {
   3.380 +			if (!first_buf_printf)
   3.381 +				printf("Final sync complete\n");
   3.382 +			/*
   3.383 +			 * Unmount filesystems
   3.384 +			 */
   3.385 +			if (panicstr == 0)
   3.386 +				vfs_unmountall();
   3.387 +		}
   3.388 +		DELAY(100000);		/* wait for console output to finish */
   3.389 +	}
   3.390 +
   3.391 +	print_uptime();
   3.392 +
   3.393 +	/*
   3.394 +	 * Ok, now do things that assume all filesystem activity has
   3.395 +	 * been completed.
   3.396 +	 */
   3.397 +	EVENTHANDLER_INVOKE(shutdown_post_sync, howto);
   3.398 +	splhigh();
   3.399 +	if ((howto & (RB_HALT|RB_DUMP)) == RB_DUMP && !cold && !dumping) 
   3.400 +		doadump();
   3.401 +
   3.402 +	/* Now that we're going to really halt the system... */
   3.403 +	EVENTHANDLER_INVOKE(shutdown_final, howto);
   3.404 +
   3.405 +	for(;;) ;	/* safety against shutdown_reset not working */
   3.406 +	/* NOTREACHED */
   3.407 +}
   3.408 +
   3.409 +/*
   3.410 + * If the shutdown was a clean halt, behave accordingly.
   3.411 + */
   3.412 +static void
   3.413 +shutdown_halt(void *junk, int howto)
   3.414 +{
   3.415 +
   3.416 +	if (howto & RB_HALT) {
   3.417 +		printf("\n");
   3.418 +		printf("The operating system has halted.\n");
   3.419 +		printf("Please press any key to reboot.\n\n");
   3.420 +		switch (cngetc()) {
   3.421 +		case -1:		/* No console, just die */
   3.422 +			cpu_halt();
   3.423 +			/* NOTREACHED */
   3.424 +		default:
   3.425 +			howto &= ~RB_HALT;
   3.426 +			break;
   3.427 +		}
   3.428 +	}
   3.429 +}
   3.430 +
   3.431 +/*
   3.432 + * Check to see if the system paniced, pause and then reboot
   3.433 + * according to the specified delay.
   3.434 + */
   3.435 +static void
   3.436 +shutdown_panic(void *junk, int howto)
   3.437 +{
   3.438 +	int loop;
   3.439 +
   3.440 +	if (howto & RB_DUMP) {
   3.441 +		if (PANIC_REBOOT_WAIT_TIME != 0) {
   3.442 +			if (PANIC_REBOOT_WAIT_TIME != -1) {
   3.443 +				printf("Automatic reboot in %d seconds - "
   3.444 +				       "press a key on the console to abort\n",
   3.445 +					PANIC_REBOOT_WAIT_TIME);
   3.446 +				for (loop = PANIC_REBOOT_WAIT_TIME * 10;
   3.447 +				     loop > 0; --loop) {
   3.448 +					DELAY(1000 * 100); /* 1/10th second */
   3.449 +					/* Did user type a key? */
   3.450 +					if (cncheckc() != -1)
   3.451 +						break;
   3.452 +				}
   3.453 +				if (!loop)
   3.454 +					return;
   3.455 +			}
   3.456 +		} else { /* zero time specified - reboot NOW */
   3.457 +			return;
   3.458 +		}
   3.459 +		printf("--> Press a key on the console to reboot,\n");
   3.460 +		printf("--> or switch off the system now.\n");
   3.461 +		cngetc();
   3.462 +	}
   3.463 +}
   3.464 +
   3.465 +/*
   3.466 + * Everything done, now reset
   3.467 + */
   3.468 +static void
   3.469 +shutdown_reset(void *junk, int howto)
   3.470 +{
   3.471 +
   3.472 +	printf("Rebooting...\n");
   3.473 +	DELAY(1000000);	/* wait 1 sec for printf's to complete and be read */
   3.474 +	/* cpu_boot(howto); */ /* doesn't do anything at the moment */
   3.475 +	cpu_reset();
   3.476 +	/* NOTREACHED */ /* assuming reset worked */
   3.477 +}
   3.478 +
   3.479 +#ifdef SMP
   3.480 +static u_int panic_cpu = NOCPU;
   3.481 +#endif
   3.482 +
   3.483 +/*
   3.484 + * Panic is called on unresolvable fatal errors.  It prints "panic: mesg",
   3.485 + * and then reboots.  If we are called twice, then we avoid trying to sync
   3.486 + * the disks as this often leads to recursive panics.
   3.487 + *
   3.488 + * MPSAFE
   3.489 + */
   3.490 +void
   3.491 +panic(const char *fmt, ...)
   3.492 +{
   3.493 +	struct thread *td = curthread;
   3.494 +	int bootopt, newpanic;
   3.495 +	va_list ap;
   3.496 +	static char buf[256];
   3.497 +
   3.498 +#ifdef SMP
   3.499 +	/*
   3.500 +	 * We don't want multiple CPU's to panic at the same time, so we
   3.501 +	 * use panic_cpu as a simple spinlock.  We have to keep checking
   3.502 +	 * panic_cpu if we are spinning in case the panic on the first
   3.503 +	 * CPU is canceled.
   3.504 +	 */
   3.505 +	if (panic_cpu != PCPU_GET(cpuid))
   3.506 +		while (atomic_cmpset_int(&panic_cpu, NOCPU,
   3.507 +		    PCPU_GET(cpuid)) == 0)
   3.508 +			while (panic_cpu != NOCPU)
   3.509 +				; /* nothing */
   3.510 +#endif
   3.511 +
   3.512 +	bootopt = RB_AUTOBOOT | RB_DUMP;
   3.513 +	newpanic = 0;
   3.514 +	if (panicstr)
   3.515 +		bootopt |= RB_NOSYNC;
   3.516 +	else {
   3.517 +		panicstr = fmt;
   3.518 +		newpanic = 1;
   3.519 +	}
   3.520 +
   3.521 +	va_start(ap, fmt);
   3.522 +	if (newpanic) {
   3.523 +		(void)vsnprintf(buf, sizeof(buf), fmt, ap);
   3.524 +		panicstr = buf;
   3.525 +		printf("panic: %s\n", buf);
   3.526 +	} else {
   3.527 +		printf("panic: ");
   3.528 +		vprintf(fmt, ap);
   3.529 +		printf("\n");
   3.530 +	}
   3.531 +	va_end(ap);
   3.532 +#ifdef SMP
   3.533 +	printf("cpuid = %d\n", PCPU_GET(cpuid));
   3.534 +#endif
   3.535 +
   3.536 +#ifdef KDB
   3.537 +	if (newpanic && trace_on_panic)
   3.538 +		kdb_backtrace();
   3.539 +	if (debugger_on_panic)
   3.540 +		kdb_enter("panic");
   3.541 +#ifdef RESTARTABLE_PANICS
   3.542 +	/* See if the user aborted the panic, in which case we continue. */
   3.543 +	if (panicstr == NULL) {
   3.544 +#ifdef SMP
   3.545 +		atomic_store_rel_int(&panic_cpu, NOCPU);
   3.546 +#endif
   3.547 +		return;
   3.548 +	}
   3.549 +#endif
   3.550 +#endif
   3.551 +	mtx_lock_spin(&sched_lock);
   3.552 +	td->td_flags |= TDF_INPANIC;
   3.553 +	mtx_unlock_spin(&sched_lock);
   3.554 +	if (!sync_on_panic)
   3.555 +		bootopt |= RB_NOSYNC;
   3.556 +#ifdef XEN
   3.557 +	HYPERVISOR_crash();
   3.558 +#else
   3.559 +	boot(bootopt);
   3.560 +#endif
   3.561 +}
   3.562 +
   3.563 +/*
   3.564 + * Support for poweroff delay.
   3.565 + */
   3.566 +#ifndef POWEROFF_DELAY
   3.567 +# define POWEROFF_DELAY 5000
   3.568 +#endif
   3.569 +static int poweroff_delay = POWEROFF_DELAY;
   3.570 +
   3.571 +SYSCTL_INT(_kern_shutdown, OID_AUTO, poweroff_delay, CTLFLAG_RW,
   3.572 +	&poweroff_delay, 0, "");
   3.573 +
   3.574 +static void
   3.575 +poweroff_wait(void *junk, int howto)
   3.576 +{
   3.577 +
   3.578 +	if (!(howto & RB_POWEROFF) || poweroff_delay <= 0)
   3.579 +		return;
   3.580 +	DELAY(poweroff_delay * 1000);
   3.581 +}
   3.582 +
   3.583 +/*
   3.584 + * Some system processes (e.g. syncer) need to be stopped at appropriate
   3.585 + * points in their main loops prior to a system shutdown, so that they
   3.586 + * won't interfere with the shutdown process (e.g. by holding a disk buf
   3.587 + * to cause sync to fail).  For each of these system processes, register
   3.588 + * shutdown_kproc() as a handler for one of shutdown events.
   3.589 + */
   3.590 +static int kproc_shutdown_wait = 60;
   3.591 +SYSCTL_INT(_kern_shutdown, OID_AUTO, kproc_shutdown_wait, CTLFLAG_RW,
   3.592 +    &kproc_shutdown_wait, 0, "");
   3.593 +
   3.594 +void
   3.595 +kproc_shutdown(void *arg, int howto)
   3.596 +{
   3.597 +	struct proc *p;
   3.598 +	char procname[MAXCOMLEN + 1];
   3.599 +	int error;
   3.600 +
   3.601 +	if (panicstr)
   3.602 +		return;
   3.603 +
   3.604 +	p = (struct proc *)arg;
   3.605 +	strlcpy(procname, p->p_comm, sizeof(procname));
   3.606 +	printf("Waiting (max %d seconds) for system process `%s' to stop...",
   3.607 +	    kproc_shutdown_wait, procname);
   3.608 +	error = kthread_suspend(p, kproc_shutdown_wait * hz);
   3.609 +
   3.610 +	if (error == EWOULDBLOCK)
   3.611 +		printf("timed out\n");
   3.612 +	else
   3.613 +		printf("done\n");
   3.614 +}
   3.615 +
   3.616 +/* Registration of dumpers */
   3.617 +int
   3.618 +set_dumper(struct dumperinfo *di)
   3.619 +{
   3.620 +
   3.621 +	if (di == NULL) {
   3.622 +		bzero(&dumper, sizeof dumper);
   3.623 +		return (0);
   3.624 +	}
   3.625 +	if (dumper.dumper != NULL)
   3.626 +		return (EBUSY);
   3.627 +	dumper = *di;
   3.628 +	return (0);
   3.629 +}
   3.630 +
   3.631 +#if defined(__powerpc__)
   3.632 +void
   3.633 +dumpsys(struct dumperinfo *di __unused)
   3.634 +{
   3.635 +
   3.636 +	printf("Kernel dumps not implemented on this architecture\n");
   3.637 +}
   3.638 +#endif