kern_shutdown.c revision 113633
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 113633 2003-04-17 22:29:23Z jhb $
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>
5678767Sjhb#include <sys/eventhandler.h>
5717658Sjulian#include <sys/kernel.h>
5855539Sluoqi#include <sys/kthread.h>
59106024Srwatson#include <sys/mac.h>
6089601Ssobomax#include <sys/malloc.h>
6121776Sbde#include <sys/mount.h>
6278767Sjhb#include <sys/proc.h>
6378767Sjhb#include <sys/reboot.h>
6478767Sjhb#include <sys/resourcevar.h>
6578767Sjhb#include <sys/smp.h>		/* smp_active */
6617658Sjulian#include <sys/sysctl.h>
6717658Sjulian#include <sys/sysproto.h>
6878767Sjhb#include <sys/vnode.h>
6917658Sjulian
7094169Sphk#include <machine/pcb.h>
7117658Sjulian#include <machine/md_var.h>
7291778Sjake#include <machine/smp.h>
7317658Sjulian
7417658Sjulian#include <sys/signalvar.h>
7582119Sjhb#ifdef DDB
7682119Sjhb#include <ddb/ddb.h>
7782119Sjhb#endif
7817658Sjulian
7917658Sjulian#ifndef PANIC_REBOOT_WAIT_TIME
8017658Sjulian#define PANIC_REBOOT_WAIT_TIME 15 /* default to 15 seconds */
8117658Sjulian#endif
8217658Sjulian
8317658Sjulian/*
8417658Sjulian * Note that stdarg.h and the ANSI style va_start macro is used for both
8517658Sjulian * ANSI and traditional C compilers.
8617658Sjulian */
8717658Sjulian#include <machine/stdarg.h>
8817658Sjulian
8928769Sbde#ifdef DDB
9017658Sjulian#ifdef DDB_UNATTENDED
9142135Smsmithint debugger_on_panic = 0;
9217658Sjulian#else
9342135Smsmithint debugger_on_panic = 1;
9417658Sjulian#endif
9517658SjulianSYSCTL_INT(_debug, OID_AUTO, debugger_on_panic, CTLFLAG_RW,
9646381Sbillf	&debugger_on_panic, 0, "Run debugger on kernel panic");
97103647Sjhb
98103647Sjhb#ifdef DDB_TRACE
99103647Sjhbint trace_on_panic = 1;
100103647Sjhb#else
101103647Sjhbint trace_on_panic = 0;
10217658Sjulian#endif
103103647SjhbSYSCTL_INT(_debug, OID_AUTO, trace_on_panic, CTLFLAG_RW,
104103647Sjhb	&trace_on_panic, 0, "Print stack trace on kernel panic");
105103647Sjhb#endif
10617658Sjulian
10785202Speterint sync_on_panic = 1;
10885202SpeterSYSCTL_INT(_kern, OID_AUTO, sync_on_panic, CTLFLAG_RW,
10985202Speter	&sync_on_panic, 0, "Do a sync before rebooting from a panic");
11085202Speter
11143436SmsmithSYSCTL_NODE(_kern, OID_AUTO, shutdown, CTLFLAG_RW, 0, "Shutdown environment");
11243436Smsmith
11328000Sjulian#ifdef	HW_WDOG
11417658Sjulian/*
11527997Sjulian * If there is a hardware watchdog, point this at the function needed to
11627997Sjulian * hold it off.
11727997Sjulian * It's needed when the kernel needs to do some lengthy operations.
11827997Sjulian * e.g. in wd.c when dumping core.. It's most annoying to have
11927997Sjulian * your precious core-dump only half written because the wdog kicked in.
12027997Sjulian */
12127997Sjulianwatchdog_tickle_fn wdog_tickler = NULL;
12228000Sjulian#endif	/* HW_WDOG */
12327997Sjulian
12427997Sjulian/*
12517658Sjulian * Variable panicstr contains argument to first call to panic; used as flag
12617658Sjulian * to indicate that the kernel has already called panic.
12717658Sjulian */
12817658Sjulianconst char *panicstr;
12917658Sjulian
13093496Sphkint dumping;				/* system is dumping */
13193496Sphkstatic struct dumperinfo dumper;	/* our selected dumper */
13294169Sphkstatic struct pcb dumppcb;		/* "You Are Here" sign for dump-debuggers */
13367093Sps
13465395Speterstatic void boot(int) __dead2;
13565395Speterstatic void poweroff_wait(void *, int);
13665395Speterstatic void shutdown_halt(void *junk, int howto);
13765395Speterstatic void shutdown_panic(void *junk, int howto);
13865395Speterstatic void shutdown_reset(void *junk, int howto);
13917658Sjulian
14050107Smsmith/* register various local shutdown events */
141110859Salfredstatic void
14250107Smsmithshutdown_conf(void *unused)
14350107Smsmith{
144110859Salfred
145110859Salfred	EVENTHANDLER_REGISTER(shutdown_final, poweroff_wait, NULL,
146110859Salfred	    SHUTDOWN_PRI_FIRST);
147110859Salfred	EVENTHANDLER_REGISTER(shutdown_final, shutdown_halt, NULL,
148110859Salfred	    SHUTDOWN_PRI_LAST + 100);
149110859Salfred	EVENTHANDLER_REGISTER(shutdown_final, shutdown_panic, NULL,
150110859Salfred	    SHUTDOWN_PRI_LAST + 100);
151110859Salfred	EVENTHANDLER_REGISTER(shutdown_final, shutdown_reset, NULL,
152110859Salfred	    SHUTDOWN_PRI_LAST + 200);
15350107Smsmith}
15448868Sphk
15550107SmsmithSYSINIT(shutdown_conf, SI_SUB_INTRINSIC, SI_ORDER_ANY, shutdown_conf, NULL)
15650107Smsmith
15717658Sjulian/*
15817658Sjulian * The system call that results in a reboot
15982749Sdillon *
16082749Sdillon * MPSAFE
16117658Sjulian */
16282749Sdillon/* ARGSUSED */
16317658Sjulianint
16483366Sjulianreboot(struct thread *td, struct reboot_args *uap)
16517658Sjulian{
16617658Sjulian	int error;
16717658Sjulian
168106024Srwatson	error = 0;
169106024Srwatson#ifdef MAC
170106024Srwatson	error = mac_check_system_reboot(td->td_ucred, uap->opt);
171106024Srwatson#endif
172106024Srwatson	if (error == 0)
173106024Srwatson		error = suser(td);
174106024Srwatson	if (error == 0) {
175106024Srwatson		mtx_lock(&Giant);
17682749Sdillon		boot(uap->opt);
177106024Srwatson		mtx_unlock(&Giant);
178106024Srwatson	}
17982749Sdillon	return (error);
18017658Sjulian}
18117658Sjulian
18217658Sjulian/*
18317658Sjulian * Called by events that want to shut down.. e.g  <CTL><ALT><DEL> on a PC
18417658Sjulian */
18565268Smsmithstatic int shutdown_howto = 0;
18665268Smsmith
18717658Sjulianvoid
18865268Smsmithshutdown_nice(int howto)
18917658Sjulian{
190110859Salfred
19165268Smsmith	shutdown_howto = howto;
192110859Salfred
19317658Sjulian	/* Send a signal to init(8) and have it shutdown the world */
19417658Sjulian	if (initproc != NULL) {
19573913Sjhb		PROC_LOCK(initproc);
19617658Sjulian		psignal(initproc, SIGINT);
19773913Sjhb		PROC_UNLOCK(initproc);
19817658Sjulian	} else {
19917658Sjulian		/* No init(8) running, so simply reboot */
20017658Sjulian		boot(RB_NOSYNC);
20117658Sjulian	}
20217658Sjulian	return;
20317658Sjulian}
20417658Sjulianstatic int	waittime = -1;
20517658Sjulian
20654233Sphkstatic void
20765395Speterprint_uptime(void)
20854233Sphk{
20954233Sphk	int f;
21054233Sphk	struct timespec ts;
21154233Sphk
21254233Sphk	getnanouptime(&ts);
21354233Sphk	printf("Uptime: ");
21454233Sphk	f = 0;
21554233Sphk	if (ts.tv_sec >= 86400) {
21665764Sjhb		printf("%ldd", (long)ts.tv_sec / 86400);
21754233Sphk		ts.tv_sec %= 86400;
21854233Sphk		f = 1;
21954233Sphk	}
22054233Sphk	if (f || ts.tv_sec >= 3600) {
22165764Sjhb		printf("%ldh", (long)ts.tv_sec / 3600);
22254233Sphk		ts.tv_sec %= 3600;
22354233Sphk		f = 1;
22454233Sphk	}
22554233Sphk	if (f || ts.tv_sec >= 60) {
22665764Sjhb		printf("%ldm", (long)ts.tv_sec / 60);
22754233Sphk		ts.tv_sec %= 60;
22854233Sphk		f = 1;
22954233Sphk	}
23065764Sjhb	printf("%lds\n", (long)ts.tv_sec);
23154233Sphk}
23254233Sphk
23394169Sphkstatic void
23494169Sphkdoadump(void)
23594169Sphk{
236110859Salfred
23794169Sphk	savectx(&dumppcb);
23894169Sphk	dumping++;
23994169Sphk	dumpsys(&dumper);
24094169Sphk}
24194169Sphk
24217658Sjulian/*
24317658Sjulian *  Go through the rigmarole of shutting down..
24417658Sjulian * this used to be in machdep.c but I'll be dammned if I could see
24517658Sjulian * anything machine dependant in it.
24617658Sjulian */
24731275Sbdestatic void
24865395Speterboot(int howto)
24917658Sjulian{
25017658Sjulian
25165268Smsmith	/* collect extra flags that shutdown_nice might have set */
25265268Smsmith	howto |= shutdown_howto;
25365268Smsmith
25482119Sjhb#ifdef DDB
25582119Sjhb	/* We are out of the debugger now. */
25682119Sjhb	db_active = 0;
25782119Sjhb#endif
25882119Sjhb
25925164Speter#ifdef SMP
26065395Speter	if (smp_active)
26170861Sjake		printf("boot() called on cpu#%d\n", PCPU_GET(cpuid));
26225164Speter#endif
26327997Sjulian	/*
26427997Sjulian	 * Do any callouts that should be done BEFORE syncing the filesystems.
26527997Sjulian	 */
26650107Smsmith	EVENTHANDLER_INVOKE(shutdown_pre_sync, howto);
26727997Sjulian
26827997Sjulian	/*
26927997Sjulian	 * Now sync filesystems
27027997Sjulian	 */
27117658Sjulian	if (!cold && (howto & RB_NOSYNC) == 0 && waittime < 0) {
27217658Sjulian		register struct buf *bp;
27365707Sjasone		int iter, nbusy, pbusy;
27465707Sjasone		int subiter;
27517658Sjulian
27617658Sjulian		waittime = 0;
277107036Salfred		printf("\nsyncing disks, buffers remaining... ");
27817658Sjulian
27990361Sjulian		sync(&thread0, NULL);
28017658Sjulian
28134266Sjulian		/*
28234266Sjulian		 * With soft updates, some buffers that are
28334266Sjulian		 * written will be remarked as dirty until other
28434266Sjulian		 * buffers are written.
28534266Sjulian		 */
28665707Sjasone		for (iter = pbusy = 0; iter < 20; iter++) {
28717658Sjulian			nbusy = 0;
28817658Sjulian			for (bp = &buf[nbuf]; --bp >= buf; ) {
28948225Smckusick				if ((bp->b_flags & B_INVAL) == 0 &&
29048225Smckusick				    BUF_REFCNT(bp) > 0) {
29117658Sjulian					nbusy++;
29234266Sjulian				} else if ((bp->b_flags & (B_DELWRI | B_INVAL))
29334266Sjulian						== B_DELWRI) {
29434266Sjulian					/* bawrite(bp);*/
29534266Sjulian					nbusy++;
29617658Sjulian				}
29717658Sjulian			}
29817658Sjulian			if (nbusy == 0)
29917658Sjulian				break;
30017658Sjulian			printf("%d ", nbusy);
30165707Sjasone			if (nbusy < pbusy)
30265707Sjasone				iter = 0;
30365707Sjasone			pbusy = nbusy;
30490361Sjulian			sync(&thread0, NULL);
30583366Sjulian 			if (curthread != NULL) {
30688900Sjhb				DROP_GIANT();
30765707Sjasone   				for (subiter = 0; subiter < 50 * iter; subiter++) {
30872200Sbmilekic     					mtx_lock_spin(&sched_lock);
30983366Sjulian					curthread->td_proc->p_stats->p_ru.ru_nvcsw++;
31065707Sjasone     					mi_switch(); /* Allow interrupt threads to run */
31172200Sbmilekic     					mtx_unlock_spin(&sched_lock);
31265707Sjasone     					DELAY(1000);
31365707Sjasone   				}
31468808Sjhb				PICKUP_GIANT();
31565707Sjasone 			} else
31634266Sjulian			DELAY(50000 * iter);
31717658Sjulian		}
31853023Sphk		printf("\n");
31941137Smsmith		/*
32041137Smsmith		 * Count only busy local buffers to prevent forcing
32141137Smsmith		 * a fsck if we're just a client of a wedged NFS server
32241137Smsmith		 */
32341137Smsmith		nbusy = 0;
32441137Smsmith		for (bp = &buf[nbuf]; --bp >= buf; ) {
32548225Smckusick			if (((bp->b_flags&B_INVAL) == 0 && BUF_REFCNT(bp)) ||
32648225Smckusick			    ((bp->b_flags & (B_DELWRI|B_INVAL)) == B_DELWRI)) {
32753023Sphk				if (bp->b_dev == NODEV) {
32853452Sphk					TAILQ_REMOVE(&mountlist,
32948225Smckusick					    bp->b_vp->v_mount, mnt_list);
33053023Sphk					continue;
33153023Sphk				}
33253023Sphk				nbusy++;
33353023Sphk#if defined(SHOW_BUSYBUFS) || defined(DIAGNOSTIC)
33453023Sphk				printf(
335110585Sjeff			    "%d: dev:%s, flags:%0x, blkno:%ld, lblkno:%ld\n",
33653023Sphk				    nbusy, devtoname(bp->b_dev),
33753023Sphk				    bp->b_flags, (long)bp->b_blkno,
33853023Sphk				    (long)bp->b_lblkno);
33953023Sphk#endif
34046568Speter			}
34141137Smsmith		}
34217658Sjulian		if (nbusy) {
34317658Sjulian			/*
34417658Sjulian			 * Failed to sync all blocks. Indicate this and don't
34517658Sjulian			 * unmount filesystems (thus forcing an fsck on reboot).
34617658Sjulian			 */
34753023Sphk			printf("giving up on %d buffers\n", nbusy);
34817658Sjulian			DELAY(5000000);	/* 5 seconds */
34917658Sjulian		} else {
35017658Sjulian			printf("done\n");
35117658Sjulian			/*
35217658Sjulian			 * Unmount filesystems
35317658Sjulian			 */
35417658Sjulian			if (panicstr == 0)
35517658Sjulian				vfs_unmountall();
35617658Sjulian		}
35739237Sgibbs		DELAY(100000);		/* wait for console output to finish */
35817658Sjulian	}
35927997Sjulian
36054233Sphk	print_uptime();
36154233Sphk
36227997Sjulian	/*
36327997Sjulian	 * Ok, now do things that assume all filesystem activity has
36427997Sjulian	 * been completed.
36527997Sjulian	 */
36650107Smsmith	EVENTHANDLER_INVOKE(shutdown_post_sync, howto);
36739237Sgibbs	splhigh();
36893496Sphk	if ((howto & (RB_HALT|RB_DUMP)) == RB_DUMP &&
36994169Sphk	    !cold && dumper.dumper != NULL && !dumping)
37094169Sphk		doadump();
37139237Sgibbs
37239237Sgibbs	/* Now that we're going to really halt the system... */
37350107Smsmith	EVENTHANDLER_INVOKE(shutdown_final, howto);
37439237Sgibbs
37550107Smsmith	for(;;) ;	/* safety against shutdown_reset not working */
37650107Smsmith	/* NOTREACHED */
37750107Smsmith}
37850107Smsmith
37950107Smsmith/*
38050107Smsmith * If the shutdown was a clean halt, behave accordingly.
38150107Smsmith */
38250107Smsmithstatic void
38350107Smsmithshutdown_halt(void *junk, int howto)
38450107Smsmith{
385110859Salfred
38617658Sjulian	if (howto & RB_HALT) {
38717658Sjulian		printf("\n");
38817658Sjulian		printf("The operating system has halted.\n");
38917658Sjulian		printf("Please press any key to reboot.\n\n");
39019274Sjulian		switch (cngetc()) {
39119274Sjulian		case -1:		/* No console, just die */
39219274Sjulian			cpu_halt();
39319274Sjulian			/* NOTREACHED */
39419274Sjulian		default:
39539237Sgibbs			howto &= ~RB_HALT;
39619274Sjulian			break;
39719274Sjulian		}
39850107Smsmith	}
39950107Smsmith}
40017658Sjulian
40150107Smsmith/*
40250107Smsmith * Check to see if the system paniced, pause and then reboot
40350107Smsmith * according to the specified delay.
40450107Smsmith */
40550107Smsmithstatic void
40650107Smsmithshutdown_panic(void *junk, int howto)
40750107Smsmith{
40850107Smsmith	int loop;
40950107Smsmith
41050107Smsmith	if (howto & RB_DUMP) {
41139237Sgibbs		if (PANIC_REBOOT_WAIT_TIME != 0) {
41239237Sgibbs			if (PANIC_REBOOT_WAIT_TIME != -1) {
41339237Sgibbs				printf("Automatic reboot in %d seconds - "
41439237Sgibbs				       "press a key on the console to abort\n",
41539237Sgibbs					PANIC_REBOOT_WAIT_TIME);
41639237Sgibbs				for (loop = PANIC_REBOOT_WAIT_TIME * 10;
41739237Sgibbs				     loop > 0; --loop) {
41839237Sgibbs					DELAY(1000 * 100); /* 1/10th second */
41939237Sgibbs					/* Did user type a key? */
42039237Sgibbs					if (cncheckc() != -1)
42139237Sgibbs						break;
42217658Sjulian				}
42339237Sgibbs				if (!loop)
42450107Smsmith					return;
42517658Sjulian			}
42639237Sgibbs		} else { /* zero time specified - reboot NOW */
42750107Smsmith			return;
42817658Sjulian		}
42989522Snik		printf("--> Press a key on the console to reboot,\n");
43089522Snik		printf("--> or switch off the system now.\n");
43139237Sgibbs		cngetc();
43217658Sjulian	}
43350107Smsmith}
43450107Smsmith
43550107Smsmith/*
43650107Smsmith * Everything done, now reset
43750107Smsmith */
43850107Smsmithstatic void
43950107Smsmithshutdown_reset(void *junk, int howto)
44050107Smsmith{
441110859Salfred
44217658Sjulian	printf("Rebooting...\n");
44317658Sjulian	DELAY(1000000);	/* wait 1 sec for printf's to complete and be read */
44417677Sjulian	/* cpu_boot(howto); */ /* doesn't do anything at the moment */
44517658Sjulian	cpu_reset();
44650107Smsmith	/* NOTREACHED */ /* assuming reset worked */
44717658Sjulian}
44817658Sjulian
449108682Sphk/*
450108682Sphk * Print a backtrace if we can.
451108682Sphk */
452108682Sphk
453108682Sphkvoid
454108682Sphkbacktrace(void)
455108682Sphk{
456110859Salfred
457108682Sphk#ifdef DDB
458110778Speter	printf("Stack backtrace:\n");
459108682Sphk	db_print_backtrace();
460108682Sphk#else
461108682Sphk	printf("Sorry, need DDB option to print backtrace");
462108682Sphk#endif
463108682Sphk}
464108682Sphk
46575570Sjhb#ifdef SMP
466101155Sjhbstatic u_int panic_cpu = NOCPU;
46775570Sjhb#endif
46875570Sjhb
46917658Sjulian/*
47017658Sjulian * Panic is called on unresolvable fatal errors.  It prints "panic: mesg",
47117658Sjulian * and then reboots.  If we are called twice, then we avoid trying to sync
47217658Sjulian * the disks as this often leads to recursive panics.
47382749Sdillon *
47482749Sdillon * MPSAFE
47517658Sjulian */
47617658Sjulianvoid
47717658Sjulianpanic(const char *fmt, ...)
47817658Sjulian{
479100209Sgallatin	struct thread *td = curthread;
480103647Sjhb	int bootopt, newpanic;
48117658Sjulian	va_list ap;
48238874Sache	static char buf[256];
48317658Sjulian
48465557Sjasone#ifdef SMP
48582115Sjhb	/*
48682115Sjhb	 * We don't want multiple CPU's to panic at the same time, so we
487101155Sjhb	 * use panic_cpu as a simple spinlock.  We have to keep checking
488101155Sjhb	 * panic_cpu if we are spinning in case the panic on the first
48982115Sjhb	 * CPU is canceled.
49082115Sjhb	 */
491101155Sjhb	if (panic_cpu != PCPU_GET(cpuid))
492101155Sjhb		while (atomic_cmpset_int(&panic_cpu, NOCPU,
493101155Sjhb		    PCPU_GET(cpuid)) == 0)
494101155Sjhb			while (panic_cpu != NOCPU)
495101155Sjhb				; /* nothing */
49665557Sjasone#endif
49765557Sjasone
49817658Sjulian	bootopt = RB_AUTOBOOT | RB_DUMP;
499103647Sjhb	newpanic = 0;
50017658Sjulian	if (panicstr)
50117658Sjulian		bootopt |= RB_NOSYNC;
502103647Sjhb	else {
50317658Sjulian		panicstr = fmt;
504103647Sjhb		newpanic = 1;
505103647Sjhb	}
50617658Sjulian
50717658Sjulian	va_start(ap, fmt);
50841514Sarchie	(void)vsnprintf(buf, sizeof(buf), fmt, ap);
50938874Sache	if (panicstr == fmt)
51038874Sache		panicstr = buf;
51117658Sjulian	va_end(ap);
51238874Sache	printf("panic: %s\n", buf);
51326100Sfsmp#ifdef SMP
51472091Sasmodai	/* two separate prints in case of an unmapped page and trap */
51570861Sjake	printf("cpuid = %d; ", PCPU_GET(cpuid));
51669335Sjhb#ifdef APIC_IO
51729128Speter	printf("lapic.id = %08x\n", lapic.id);
51899828Sjhb#else
51999828Sjhb	printf("\n");
52026100Sfsmp#endif
52169335Sjhb#endif
52217658Sjulian
52317658Sjulian#if defined(DDB)
524103647Sjhb	if (newpanic && trace_on_panic)
525110778Speter		backtrace();
52617658Sjulian	if (debugger_on_panic)
52717658Sjulian		Debugger ("panic");
52882223Sjhb#ifdef RESTARTABLE_PANICS
52982115Sjhb	/* See if the user aborted the panic, in which case we continue. */
53082115Sjhb	if (panicstr == NULL) {
53182115Sjhb#ifdef SMP
532101155Sjhb		atomic_store_rel_int(&panic_cpu, NOCPU);
53317658Sjulian#endif
53482115Sjhb		return;
53582115Sjhb	}
53682115Sjhb#endif
53782223Sjhb#endif
538113633Sjhb	mtx_lock_spin(&sched_lock);
539100209Sgallatin	td->td_flags |= TDF_INPANIC;
540113633Sjhb	mtx_unlock_spin(&sched_lock);
54185202Speter	if (!sync_on_panic)
54285202Speter		bootopt |= RB_NOSYNC;
54317658Sjulian	boot(bootopt);
54417658Sjulian}
54517658Sjulian
54617768Sjulian/*
54743436Smsmith * Support for poweroff delay.
54843436Smsmith */
54954248Smsmith#ifndef POWEROFF_DELAY
55054248Smsmith# define POWEROFF_DELAY 5000
55154248Smsmith#endif
55254248Smsmithstatic int poweroff_delay = POWEROFF_DELAY;
55354248Smsmith
55443436SmsmithSYSCTL_INT(_kern_shutdown, OID_AUTO, poweroff_delay, CTLFLAG_RW,
55543436Smsmith	&poweroff_delay, 0, "");
55643436Smsmith
557110859Salfredstatic void
55850107Smsmithpoweroff_wait(void *junk, int howto)
55943436Smsmith{
560110859Salfred
561110859Salfred	if (!(howto & RB_POWEROFF) || poweroff_delay <= 0)
56243436Smsmith		return;
56343436Smsmith	DELAY(poweroff_delay * 1000);
56443436Smsmith}
56555539Sluoqi
56655539Sluoqi/*
56755539Sluoqi * Some system processes (e.g. syncer) need to be stopped at appropriate
56855539Sluoqi * points in their main loops prior to a system shutdown, so that they
56955539Sluoqi * won't interfere with the shutdown process (e.g. by holding a disk buf
57055539Sluoqi * to cause sync to fail).  For each of these system processes, register
57155539Sluoqi * shutdown_kproc() as a handler for one of shutdown events.
57255539Sluoqi */
57355539Sluoqistatic int kproc_shutdown_wait = 60;
57455539SluoqiSYSCTL_INT(_kern_shutdown, OID_AUTO, kproc_shutdown_wait, CTLFLAG_RW,
57555539Sluoqi    &kproc_shutdown_wait, 0, "");
57655539Sluoqi
57755539Sluoqivoid
57870063Sjhbkproc_shutdown(void *arg, int howto)
57955539Sluoqi{
58055539Sluoqi	struct proc *p;
58155539Sluoqi	int error;
58255539Sluoqi
58355539Sluoqi	if (panicstr)
58455539Sluoqi		return;
58555539Sluoqi
58655539Sluoqi	p = (struct proc *)arg;
58755539Sluoqi	printf("Waiting (max %d seconds) for system process `%s' to stop...",
58855862Sluoqi	    kproc_shutdown_wait, p->p_comm);
58970063Sjhb	error = kthread_suspend(p, kproc_shutdown_wait * hz);
59055539Sluoqi
59155539Sluoqi	if (error == EWOULDBLOCK)
59255539Sluoqi		printf("timed out\n");
59355539Sluoqi	else
59455539Sluoqi		printf("stopped\n");
59555539Sluoqi}
59693496Sphk
59793496Sphk/* Registration of dumpers */
59893496Sphkint
59993496Sphkset_dumper(struct dumperinfo *di)
60093496Sphk{
601110859Salfred
60293496Sphk	if (di == NULL) {
60393496Sphk		bzero(&dumper, sizeof dumper);
60493496Sphk		return (0);
60593496Sphk	}
60693496Sphk	if (dumper.dumper != NULL)
60793496Sphk		return (EBUSY);
60893496Sphk	dumper = *di;
60993496Sphk	return (0);
61093496Sphk}
61193496Sphk
612105531Stmm#if defined(__powerpc__)
61393496Sphkvoid
61493496Sphkdumpsys(struct dumperinfo *di __unused)
61593496Sphk{
61693496Sphk
61793496Sphk	printf("Kernel dumps not implemented on this architecture\n");
61893496Sphk}
61993496Sphk#endif
620