kern_shutdown.c revision 107036
117658Sjulian/*-
217658Sjulian * Copyright (c) 1986, 1988, 1991, 1993
317658Sjulian *	The Regents of the University of California.  All rights reserved.
417658Sjulian * (c) UNIX System Laboratories, Inc.
517658Sjulian * All or some portions of this file are derived from material licensed
617658Sjulian * to the University of California by American Telephone and Telegraph
717658Sjulian * Co. or Unix System Laboratories, Inc. and are reproduced herein with
817658Sjulian * the permission of UNIX System Laboratories, Inc.
917658Sjulian *
1017658Sjulian * Redistribution and use in source and binary forms, with or without
1117658Sjulian * modification, are permitted provided that the following conditions
1217658Sjulian * are met:
1317658Sjulian * 1. Redistributions of source code must retain the above copyright
1417658Sjulian *    notice, this list of conditions and the following disclaimer.
1517658Sjulian * 2. Redistributions in binary form must reproduce the above copyright
1617658Sjulian *    notice, this list of conditions and the following disclaimer in the
1717658Sjulian *    documentation and/or other materials provided with the distribution.
1817658Sjulian * 3. All advertising materials mentioning features or use of this software
1917658Sjulian *    must display the following acknowledgement:
2017658Sjulian *	This product includes software developed by the University of
2117658Sjulian *	California, Berkeley and its contributors.
2217658Sjulian * 4. Neither the name of the University nor the names of its contributors
2317658Sjulian *    may be used to endorse or promote products derived from this software
2417658Sjulian *    without specific prior written permission.
2517658Sjulian *
2617658Sjulian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2717658Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2817658Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2917658Sjulian * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3017658Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3117658Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3217658Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3317658Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3417658Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3517658Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3617658Sjulian * SUCH DAMAGE.
3717658Sjulian *
3817658Sjulian *	@(#)kern_shutdown.c	8.3 (Berkeley) 1/21/94
3950477Speter * $FreeBSD: head/sys/kern/kern_shutdown.c 107036 2002-11-18 02:41:03Z alfred $
4017658Sjulian */
4117658Sjulian
4217658Sjulian#include "opt_ddb.h"
43103647Sjhb#include "opt_ddb_trace.h"
44103647Sjhb#include "opt_ddb_unattended.h"
4533445Seivind#include "opt_hw_wdog.h"
46106024Srwatson#include "opt_mac.h"
4728976Sbde#include "opt_panic.h"
4828976Sbde#include "opt_show_busybufs.h"
4917658Sjulian
5017658Sjulian#include <sys/param.h>
5117658Sjulian#include <sys/systm.h>
5260041Sphk#include <sys/bio.h>
5331275Sbde#include <sys/buf.h>
5478767Sjhb#include <sys/conf.h>
5578767Sjhb#include <sys/cons.h>
5681688Sbde#include <sys/disklabel.h>
5778767Sjhb#include <sys/eventhandler.h>
5817658Sjulian#include <sys/kernel.h>
5955539Sluoqi#include <sys/kthread.h>
60106024Srwatson#include <sys/mac.h>
6189601Ssobomax#include <sys/malloc.h>
6221776Sbde#include <sys/mount.h>
6378767Sjhb#include <sys/proc.h>
6478767Sjhb#include <sys/reboot.h>
6578767Sjhb#include <sys/resourcevar.h>
6678767Sjhb#include <sys/smp.h>		/* smp_active */
6717658Sjulian#include <sys/sysctl.h>
6817658Sjulian#include <sys/sysproto.h>
6978767Sjhb#include <sys/vnode.h>
7017658Sjulian
7194169Sphk#include <machine/pcb.h>
7217658Sjulian#include <machine/md_var.h>
7391778Sjake#include <machine/smp.h>
7417658Sjulian
7517658Sjulian#include <sys/signalvar.h>
7682119Sjhb#ifdef DDB
7782119Sjhb#include <ddb/ddb.h>
7882119Sjhb#endif
7917658Sjulian
8017658Sjulian#ifndef PANIC_REBOOT_WAIT_TIME
8117658Sjulian#define PANIC_REBOOT_WAIT_TIME 15 /* default to 15 seconds */
8217658Sjulian#endif
8317658Sjulian
8417658Sjulian/*
8517658Sjulian * Note that stdarg.h and the ANSI style va_start macro is used for both
8617658Sjulian * ANSI and traditional C compilers.
8717658Sjulian */
8817658Sjulian#include <machine/stdarg.h>
8917658Sjulian
9028769Sbde#ifdef DDB
9117658Sjulian#ifdef DDB_UNATTENDED
9242135Smsmithint debugger_on_panic = 0;
9317658Sjulian#else
9442135Smsmithint debugger_on_panic = 1;
9517658Sjulian#endif
9617658SjulianSYSCTL_INT(_debug, OID_AUTO, debugger_on_panic, CTLFLAG_RW,
9746381Sbillf	&debugger_on_panic, 0, "Run debugger on kernel panic");
98103647Sjhb
99103647Sjhb#ifdef DDB_TRACE
100103647Sjhbint trace_on_panic = 1;
101103647Sjhb#else
102103647Sjhbint trace_on_panic = 0;
10317658Sjulian#endif
104103647SjhbSYSCTL_INT(_debug, OID_AUTO, trace_on_panic, CTLFLAG_RW,
105103647Sjhb	&trace_on_panic, 0, "Print stack trace on kernel panic");
106103647Sjhb#endif
10717658Sjulian
10885202Speterint sync_on_panic = 1;
10985202SpeterSYSCTL_INT(_kern, OID_AUTO, sync_on_panic, CTLFLAG_RW,
11085202Speter	&sync_on_panic, 0, "Do a sync before rebooting from a panic");
11185202Speter
11243436SmsmithSYSCTL_NODE(_kern, OID_AUTO, shutdown, CTLFLAG_RW, 0, "Shutdown environment");
11343436Smsmith
11428000Sjulian#ifdef	HW_WDOG
11517658Sjulian/*
11627997Sjulian * If there is a hardware watchdog, point this at the function needed to
11727997Sjulian * hold it off.
11827997Sjulian * It's needed when the kernel needs to do some lengthy operations.
11927997Sjulian * e.g. in wd.c when dumping core.. It's most annoying to have
12027997Sjulian * your precious core-dump only half written because the wdog kicked in.
12127997Sjulian */
12227997Sjulianwatchdog_tickle_fn wdog_tickler = NULL;
12328000Sjulian#endif	/* HW_WDOG */
12427997Sjulian
12527997Sjulian/*
12617658Sjulian * Variable panicstr contains argument to first call to panic; used as flag
12717658Sjulian * to indicate that the kernel has already called panic.
12817658Sjulian */
12917658Sjulianconst char *panicstr;
13017658Sjulian
13193496Sphkint dumping;				/* system is dumping */
13293496Sphkstatic struct dumperinfo dumper;	/* our selected dumper */
13394169Sphkstatic struct pcb dumppcb;		/* "You Are Here" sign for dump-debuggers */
13467093Sps
13565395Speterstatic void boot(int) __dead2;
13665395Speterstatic void poweroff_wait(void *, int);
13765395Speterstatic void shutdown_halt(void *junk, int howto);
13865395Speterstatic void shutdown_panic(void *junk, int howto);
13965395Speterstatic void shutdown_reset(void *junk, int howto);
14017658Sjulian
14150107Smsmith/* register various local shutdown events */
14250107Smsmithstatic void
14350107Smsmithshutdown_conf(void *unused)
14450107Smsmith{
14550107Smsmith	EVENTHANDLER_REGISTER(shutdown_final, poweroff_wait, NULL, SHUTDOWN_PRI_FIRST);
14650107Smsmith	EVENTHANDLER_REGISTER(shutdown_final, shutdown_halt, NULL, SHUTDOWN_PRI_LAST + 100);
14750107Smsmith	EVENTHANDLER_REGISTER(shutdown_final, shutdown_panic, NULL, SHUTDOWN_PRI_LAST + 100);
14850107Smsmith	EVENTHANDLER_REGISTER(shutdown_final, shutdown_reset, NULL, SHUTDOWN_PRI_LAST + 200);
14950107Smsmith}
15048868Sphk
15150107SmsmithSYSINIT(shutdown_conf, SI_SUB_INTRINSIC, SI_ORDER_ANY, shutdown_conf, NULL)
15250107Smsmith
15317658Sjulian/*
15417658Sjulian * The system call that results in a reboot
15582749Sdillon *
15682749Sdillon * MPSAFE
15717658Sjulian */
15882749Sdillon/* ARGSUSED */
15917658Sjulianint
16083366Sjulianreboot(struct thread *td, struct reboot_args *uap)
16117658Sjulian{
16217658Sjulian	int error;
16317658Sjulian
164106024Srwatson	error = 0;
165106024Srwatson#ifdef MAC
166106024Srwatson	error = mac_check_system_reboot(td->td_ucred, uap->opt);
167106024Srwatson#endif
168106024Srwatson	if (error == 0)
169106024Srwatson		error = suser(td);
170106024Srwatson	if (error == 0) {
171106024Srwatson		mtx_lock(&Giant);
17282749Sdillon		boot(uap->opt);
173106024Srwatson		mtx_unlock(&Giant);
174106024Srwatson	}
17582749Sdillon	return (error);
17617658Sjulian}
17717658Sjulian
17817658Sjulian/*
17917658Sjulian * Called by events that want to shut down.. e.g  <CTL><ALT><DEL> on a PC
18017658Sjulian */
18165268Smsmithstatic int shutdown_howto = 0;
18265268Smsmith
18317658Sjulianvoid
18465268Smsmithshutdown_nice(int howto)
18517658Sjulian{
18665268Smsmith	shutdown_howto = howto;
18765268Smsmith
18817658Sjulian	/* Send a signal to init(8) and have it shutdown the world */
18917658Sjulian	if (initproc != NULL) {
19073913Sjhb		PROC_LOCK(initproc);
19117658Sjulian		psignal(initproc, SIGINT);
19273913Sjhb		PROC_UNLOCK(initproc);
19317658Sjulian	} else {
19417658Sjulian		/* No init(8) running, so simply reboot */
19517658Sjulian		boot(RB_NOSYNC);
19617658Sjulian	}
19717658Sjulian	return;
19817658Sjulian}
19917658Sjulianstatic int	waittime = -1;
20017658Sjulian
20154233Sphkstatic void
20265395Speterprint_uptime(void)
20354233Sphk{
20454233Sphk	int f;
20554233Sphk	struct timespec ts;
20654233Sphk
20754233Sphk	getnanouptime(&ts);
20854233Sphk	printf("Uptime: ");
20954233Sphk	f = 0;
21054233Sphk	if (ts.tv_sec >= 86400) {
21165764Sjhb		printf("%ldd", (long)ts.tv_sec / 86400);
21254233Sphk		ts.tv_sec %= 86400;
21354233Sphk		f = 1;
21454233Sphk	}
21554233Sphk	if (f || ts.tv_sec >= 3600) {
21665764Sjhb		printf("%ldh", (long)ts.tv_sec / 3600);
21754233Sphk		ts.tv_sec %= 3600;
21854233Sphk		f = 1;
21954233Sphk	}
22054233Sphk	if (f || ts.tv_sec >= 60) {
22165764Sjhb		printf("%ldm", (long)ts.tv_sec / 60);
22254233Sphk		ts.tv_sec %= 60;
22354233Sphk		f = 1;
22454233Sphk	}
22565764Sjhb	printf("%lds\n", (long)ts.tv_sec);
22654233Sphk}
22754233Sphk
22894169Sphkstatic void
22994169Sphkdoadump(void)
23094169Sphk{
23194169Sphk	savectx(&dumppcb);
23294169Sphk	dumping++;
23394169Sphk	dumpsys(&dumper);
23494169Sphk}
23594169Sphk
23617658Sjulian/*
23717658Sjulian *  Go through the rigmarole of shutting down..
23817658Sjulian * this used to be in machdep.c but I'll be dammned if I could see
23917658Sjulian * anything machine dependant in it.
24017658Sjulian */
24131275Sbdestatic void
24265395Speterboot(int howto)
24317658Sjulian{
24417658Sjulian
24565268Smsmith	/* collect extra flags that shutdown_nice might have set */
24665268Smsmith	howto |= shutdown_howto;
24765268Smsmith
24882119Sjhb#ifdef DDB
24982119Sjhb	/* We are out of the debugger now. */
25082119Sjhb	db_active = 0;
25182119Sjhb#endif
25282119Sjhb
25325164Speter#ifdef SMP
25465395Speter	if (smp_active)
25570861Sjake		printf("boot() called on cpu#%d\n", PCPU_GET(cpuid));
25625164Speter#endif
25727997Sjulian	/*
25827997Sjulian	 * Do any callouts that should be done BEFORE syncing the filesystems.
25927997Sjulian	 */
26050107Smsmith	EVENTHANDLER_INVOKE(shutdown_pre_sync, howto);
26127997Sjulian
26227997Sjulian	/*
26327997Sjulian	 * Now sync filesystems
26427997Sjulian	 */
26517658Sjulian	if (!cold && (howto & RB_NOSYNC) == 0 && waittime < 0) {
26617658Sjulian		register struct buf *bp;
26765707Sjasone		int iter, nbusy, pbusy;
26865707Sjasone		int subiter;
26917658Sjulian
27017658Sjulian		waittime = 0;
271107036Salfred		printf("\nsyncing disks, buffers remaining... ");
27217658Sjulian
27390361Sjulian		sync(&thread0, NULL);
27417658Sjulian
27534266Sjulian		/*
27634266Sjulian		 * With soft updates, some buffers that are
27734266Sjulian		 * written will be remarked as dirty until other
27834266Sjulian		 * buffers are written.
27934266Sjulian		 */
28065707Sjasone		for (iter = pbusy = 0; iter < 20; iter++) {
28117658Sjulian			nbusy = 0;
28217658Sjulian			for (bp = &buf[nbuf]; --bp >= buf; ) {
28348225Smckusick				if ((bp->b_flags & B_INVAL) == 0 &&
28448225Smckusick				    BUF_REFCNT(bp) > 0) {
28517658Sjulian					nbusy++;
28634266Sjulian				} else if ((bp->b_flags & (B_DELWRI | B_INVAL))
28734266Sjulian						== B_DELWRI) {
28834266Sjulian					/* bawrite(bp);*/
28934266Sjulian					nbusy++;
29017658Sjulian				}
29117658Sjulian			}
29217658Sjulian			if (nbusy == 0)
29317658Sjulian				break;
29417658Sjulian			printf("%d ", nbusy);
29565707Sjasone			if (nbusy < pbusy)
29665707Sjasone				iter = 0;
29765707Sjasone			pbusy = nbusy;
29890361Sjulian			sync(&thread0, NULL);
29983366Sjulian 			if (curthread != NULL) {
30088900Sjhb				DROP_GIANT();
30165707Sjasone   				for (subiter = 0; subiter < 50 * iter; subiter++) {
30272200Sbmilekic     					mtx_lock_spin(&sched_lock);
30383366Sjulian					curthread->td_proc->p_stats->p_ru.ru_nvcsw++;
30465707Sjasone     					mi_switch(); /* Allow interrupt threads to run */
30572200Sbmilekic     					mtx_unlock_spin(&sched_lock);
30665707Sjasone     					DELAY(1000);
30765707Sjasone   				}
30868808Sjhb				PICKUP_GIANT();
30965707Sjasone 			} else
31034266Sjulian			DELAY(50000 * iter);
31117658Sjulian		}
31253023Sphk		printf("\n");
31341137Smsmith		/*
31441137Smsmith		 * Count only busy local buffers to prevent forcing
31541137Smsmith		 * a fsck if we're just a client of a wedged NFS server
31641137Smsmith		 */
31741137Smsmith		nbusy = 0;
31841137Smsmith		for (bp = &buf[nbuf]; --bp >= buf; ) {
31948225Smckusick			if (((bp->b_flags&B_INVAL) == 0 && BUF_REFCNT(bp)) ||
32048225Smckusick			    ((bp->b_flags & (B_DELWRI|B_INVAL)) == B_DELWRI)) {
32153023Sphk				if (bp->b_dev == NODEV) {
32253452Sphk					TAILQ_REMOVE(&mountlist,
32348225Smckusick					    bp->b_vp->v_mount, mnt_list);
32453023Sphk					continue;
32553023Sphk				}
32653023Sphk				nbusy++;
32753023Sphk#if defined(SHOW_BUSYBUFS) || defined(DIAGNOSTIC)
32853023Sphk				printf(
32953023Sphk			    "%d: dev:%s, flags:%08lx, blkno:%ld, lblkno:%ld\n",
33053023Sphk				    nbusy, devtoname(bp->b_dev),
33153023Sphk				    bp->b_flags, (long)bp->b_blkno,
33253023Sphk				    (long)bp->b_lblkno);
33353023Sphk#endif
33446568Speter			}
33541137Smsmith		}
33617658Sjulian		if (nbusy) {
33717658Sjulian			/*
33817658Sjulian			 * Failed to sync all blocks. Indicate this and don't
33917658Sjulian			 * unmount filesystems (thus forcing an fsck on reboot).
34017658Sjulian			 */
34153023Sphk			printf("giving up on %d buffers\n", nbusy);
34217658Sjulian			DELAY(5000000);	/* 5 seconds */
34317658Sjulian		} else {
34417658Sjulian			printf("done\n");
34517658Sjulian			/*
34617658Sjulian			 * Unmount filesystems
34717658Sjulian			 */
34817658Sjulian			if (panicstr == 0)
34917658Sjulian				vfs_unmountall();
35017658Sjulian		}
35139237Sgibbs		DELAY(100000);		/* wait for console output to finish */
35217658Sjulian	}
35327997Sjulian
35454233Sphk	print_uptime();
35554233Sphk
35627997Sjulian	/*
35727997Sjulian	 * Ok, now do things that assume all filesystem activity has
35827997Sjulian	 * been completed.
35927997Sjulian	 */
36050107Smsmith	EVENTHANDLER_INVOKE(shutdown_post_sync, howto);
36139237Sgibbs	splhigh();
36293496Sphk	if ((howto & (RB_HALT|RB_DUMP)) == RB_DUMP &&
36394169Sphk	    !cold && dumper.dumper != NULL && !dumping)
36494169Sphk		doadump();
36539237Sgibbs
36639237Sgibbs	/* Now that we're going to really halt the system... */
36750107Smsmith	EVENTHANDLER_INVOKE(shutdown_final, howto);
36839237Sgibbs
36950107Smsmith	for(;;) ;	/* safety against shutdown_reset not working */
37050107Smsmith	/* NOTREACHED */
37150107Smsmith}
37250107Smsmith
37350107Smsmith/*
37450107Smsmith * If the shutdown was a clean halt, behave accordingly.
37550107Smsmith */
37650107Smsmithstatic void
37750107Smsmithshutdown_halt(void *junk, int howto)
37850107Smsmith{
37917658Sjulian	if (howto & RB_HALT) {
38017658Sjulian		printf("\n");
38117658Sjulian		printf("The operating system has halted.\n");
38217658Sjulian		printf("Please press any key to reboot.\n\n");
38319274Sjulian		switch (cngetc()) {
38419274Sjulian		case -1:		/* No console, just die */
38519274Sjulian			cpu_halt();
38619274Sjulian			/* NOTREACHED */
38719274Sjulian		default:
38839237Sgibbs			howto &= ~RB_HALT;
38919274Sjulian			break;
39019274Sjulian		}
39150107Smsmith	}
39250107Smsmith}
39317658Sjulian
39450107Smsmith/*
39550107Smsmith * Check to see if the system paniced, pause and then reboot
39650107Smsmith * according to the specified delay.
39750107Smsmith */
39850107Smsmithstatic void
39950107Smsmithshutdown_panic(void *junk, int howto)
40050107Smsmith{
40150107Smsmith	int loop;
40250107Smsmith
40350107Smsmith	if (howto & RB_DUMP) {
40439237Sgibbs		if (PANIC_REBOOT_WAIT_TIME != 0) {
40539237Sgibbs			if (PANIC_REBOOT_WAIT_TIME != -1) {
40639237Sgibbs				printf("Automatic reboot in %d seconds - "
40739237Sgibbs				       "press a key on the console to abort\n",
40839237Sgibbs					PANIC_REBOOT_WAIT_TIME);
40939237Sgibbs				for (loop = PANIC_REBOOT_WAIT_TIME * 10;
41039237Sgibbs				     loop > 0; --loop) {
41139237Sgibbs					DELAY(1000 * 100); /* 1/10th second */
41239237Sgibbs					/* Did user type a key? */
41339237Sgibbs					if (cncheckc() != -1)
41439237Sgibbs						break;
41517658Sjulian				}
41639237Sgibbs				if (!loop)
41750107Smsmith					return;
41817658Sjulian			}
41939237Sgibbs		} else { /* zero time specified - reboot NOW */
42050107Smsmith			return;
42117658Sjulian		}
42289522Snik		printf("--> Press a key on the console to reboot,\n");
42389522Snik		printf("--> or switch off the system now.\n");
42439237Sgibbs		cngetc();
42517658Sjulian	}
42650107Smsmith}
42750107Smsmith
42850107Smsmith/*
42950107Smsmith * Everything done, now reset
43050107Smsmith */
43150107Smsmithstatic void
43250107Smsmithshutdown_reset(void *junk, int howto)
43350107Smsmith{
43417658Sjulian	printf("Rebooting...\n");
43517658Sjulian	DELAY(1000000);	/* wait 1 sec for printf's to complete and be read */
43617677Sjulian	/* cpu_boot(howto); */ /* doesn't do anything at the moment */
43717658Sjulian	cpu_reset();
43850107Smsmith	/* NOTREACHED */ /* assuming reset worked */
43917658Sjulian}
44017658Sjulian
44175570Sjhb#ifdef SMP
442101155Sjhbstatic u_int panic_cpu = NOCPU;
44375570Sjhb#endif
44475570Sjhb
44517658Sjulian/*
44617658Sjulian * Panic is called on unresolvable fatal errors.  It prints "panic: mesg",
44717658Sjulian * and then reboots.  If we are called twice, then we avoid trying to sync
44817658Sjulian * the disks as this often leads to recursive panics.
44982749Sdillon *
45082749Sdillon * MPSAFE
45117658Sjulian */
45217658Sjulianvoid
45317658Sjulianpanic(const char *fmt, ...)
45417658Sjulian{
455100209Sgallatin	struct thread *td = curthread;
456103647Sjhb	int bootopt, newpanic;
45717658Sjulian	va_list ap;
45838874Sache	static char buf[256];
45917658Sjulian
46065557Sjasone#ifdef SMP
46182115Sjhb	/*
46282115Sjhb	 * We don't want multiple CPU's to panic at the same time, so we
463101155Sjhb	 * use panic_cpu as a simple spinlock.  We have to keep checking
464101155Sjhb	 * panic_cpu if we are spinning in case the panic on the first
46582115Sjhb	 * CPU is canceled.
46682115Sjhb	 */
467101155Sjhb	if (panic_cpu != PCPU_GET(cpuid))
468101155Sjhb		while (atomic_cmpset_int(&panic_cpu, NOCPU,
469101155Sjhb		    PCPU_GET(cpuid)) == 0)
470101155Sjhb			while (panic_cpu != NOCPU)
471101155Sjhb				; /* nothing */
47265557Sjasone#endif
47365557Sjasone
47417658Sjulian	bootopt = RB_AUTOBOOT | RB_DUMP;
475103647Sjhb	newpanic = 0;
47617658Sjulian	if (panicstr)
47717658Sjulian		bootopt |= RB_NOSYNC;
478103647Sjhb	else {
47917658Sjulian		panicstr = fmt;
480103647Sjhb		newpanic = 1;
481103647Sjhb	}
48217658Sjulian
48317658Sjulian	va_start(ap, fmt);
48441514Sarchie	(void)vsnprintf(buf, sizeof(buf), fmt, ap);
48538874Sache	if (panicstr == fmt)
48638874Sache		panicstr = buf;
48717658Sjulian	va_end(ap);
48838874Sache	printf("panic: %s\n", buf);
48926100Sfsmp#ifdef SMP
49072091Sasmodai	/* two separate prints in case of an unmapped page and trap */
49170861Sjake	printf("cpuid = %d; ", PCPU_GET(cpuid));
49269335Sjhb#ifdef APIC_IO
49329128Speter	printf("lapic.id = %08x\n", lapic.id);
49499828Sjhb#else
49599828Sjhb	printf("\n");
49626100Sfsmp#endif
49769335Sjhb#endif
49817658Sjulian
49917658Sjulian#if defined(DDB)
500103647Sjhb	if (newpanic && trace_on_panic)
501103647Sjhb		db_print_backtrace();
50217658Sjulian	if (debugger_on_panic)
50317658Sjulian		Debugger ("panic");
50482223Sjhb#ifdef RESTARTABLE_PANICS
50582115Sjhb	/* See if the user aborted the panic, in which case we continue. */
50682115Sjhb	if (panicstr == NULL) {
50782115Sjhb#ifdef SMP
508101155Sjhb		atomic_store_rel_int(&panic_cpu, NOCPU);
50917658Sjulian#endif
51082115Sjhb		return;
51182115Sjhb	}
51282115Sjhb#endif
51382223Sjhb#endif
514100209Sgallatin	td->td_flags |= TDF_INPANIC;
51585202Speter	if (!sync_on_panic)
51685202Speter		bootopt |= RB_NOSYNC;
51717658Sjulian	boot(bootopt);
51817658Sjulian}
51917658Sjulian
52017768Sjulian/*
52143436Smsmith * Support for poweroff delay.
52243436Smsmith */
52354248Smsmith#ifndef POWEROFF_DELAY
52454248Smsmith# define POWEROFF_DELAY 5000
52554248Smsmith#endif
52654248Smsmithstatic int poweroff_delay = POWEROFF_DELAY;
52754248Smsmith
52843436SmsmithSYSCTL_INT(_kern_shutdown, OID_AUTO, poweroff_delay, CTLFLAG_RW,
52943436Smsmith	&poweroff_delay, 0, "");
53043436Smsmith
53150107Smsmithstatic void
53250107Smsmithpoweroff_wait(void *junk, int howto)
53343436Smsmith{
53443436Smsmith	if(!(howto & RB_POWEROFF) || poweroff_delay <= 0)
53543436Smsmith		return;
53643436Smsmith	DELAY(poweroff_delay * 1000);
53743436Smsmith}
53855539Sluoqi
53955539Sluoqi/*
54055539Sluoqi * Some system processes (e.g. syncer) need to be stopped at appropriate
54155539Sluoqi * points in their main loops prior to a system shutdown, so that they
54255539Sluoqi * won't interfere with the shutdown process (e.g. by holding a disk buf
54355539Sluoqi * to cause sync to fail).  For each of these system processes, register
54455539Sluoqi * shutdown_kproc() as a handler for one of shutdown events.
54555539Sluoqi */
54655539Sluoqistatic int kproc_shutdown_wait = 60;
54755539SluoqiSYSCTL_INT(_kern_shutdown, OID_AUTO, kproc_shutdown_wait, CTLFLAG_RW,
54855539Sluoqi    &kproc_shutdown_wait, 0, "");
54955539Sluoqi
55055539Sluoqivoid
55170063Sjhbkproc_shutdown(void *arg, int howto)
55255539Sluoqi{
55355539Sluoqi	struct proc *p;
55455539Sluoqi	int error;
55555539Sluoqi
55655539Sluoqi	if (panicstr)
55755539Sluoqi		return;
55855539Sluoqi
55955539Sluoqi	p = (struct proc *)arg;
56055539Sluoqi	printf("Waiting (max %d seconds) for system process `%s' to stop...",
56155862Sluoqi	    kproc_shutdown_wait, p->p_comm);
56270063Sjhb	error = kthread_suspend(p, kproc_shutdown_wait * hz);
56355539Sluoqi
56455539Sluoqi	if (error == EWOULDBLOCK)
56555539Sluoqi		printf("timed out\n");
56655539Sluoqi	else
56755539Sluoqi		printf("stopped\n");
56855539Sluoqi}
56993496Sphk
57093496Sphk/* Registration of dumpers */
57193496Sphkint
57293496Sphkset_dumper(struct dumperinfo *di)
57393496Sphk{
57493496Sphk	if (di == NULL) {
57593496Sphk		bzero(&dumper, sizeof dumper);
57693496Sphk		return (0);
57793496Sphk	}
57893496Sphk	if (dumper.dumper != NULL)
57993496Sphk		return (EBUSY);
58093496Sphk	dumper = *di;
58193496Sphk	return (0);
58293496Sphk}
58393496Sphk
584105531Stmm#if defined(__powerpc__)
58593496Sphkvoid
58693496Sphkdumpsys(struct dumperinfo *di __unused)
58793496Sphk{
58893496Sphk
58993496Sphk	printf("Kernel dumps not implemented on this architecture\n");
59093496Sphk}
59193496Sphk#endif
592