kern_shutdown.c revision 94169
1251881Speter/*-
2251881Speter * Copyright (c) 1986, 1988, 1991, 1993
3251881Speter *	The Regents of the University of California.  All rights reserved.
4251881Speter * (c) UNIX System Laboratories, Inc.
5251881Speter * All or some portions of this file are derived from material licensed
6251881Speter * to the University of California by American Telephone and Telegraph
7251881Speter * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8251881Speter * the permission of UNIX System Laboratories, Inc.
9251881Speter *
10251881Speter * Redistribution and use in source and binary forms, with or without
11251881Speter * modification, are permitted provided that the following conditions
12251881Speter * are met:
13251881Speter * 1. Redistributions of source code must retain the above copyright
14251881Speter *    notice, this list of conditions and the following disclaimer.
15251881Speter * 2. Redistributions in binary form must reproduce the above copyright
16251881Speter *    notice, this list of conditions and the following disclaimer in the
17251881Speter *    documentation and/or other materials provided with the distribution.
18251881Speter * 3. All advertising materials mentioning features or use of this software
19251881Speter *    must display the following acknowledgement:
20251881Speter *	This product includes software developed by the University of
21251881Speter *	California, Berkeley and its contributors.
22251881Speter * 4. Neither the name of the University nor the names of its contributors
23251881Speter *    may be used to endorse or promote products derived from this software
24251881Speter *    without specific prior written permission.
25251881Speter *
26251881Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27251881Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28251881Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29251881Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30251881Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31251881Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32251881Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33251881Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34251881Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35251881Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36251881Speter * SUCH DAMAGE.
37251881Speter *
38251881Speter *	@(#)kern_shutdown.c	8.3 (Berkeley) 1/21/94
39251881Speter * $FreeBSD: head/sys/kern/kern_shutdown.c 94169 2002-04-08 06:59:13Z phk $
40251881Speter */
41251881Speter
42251881Speter#include "opt_ddb.h"
43251881Speter#include "opt_hw_wdog.h"
44251881Speter#include "opt_panic.h"
45251881Speter#include "opt_show_busybufs.h"
46251881Speter
47251881Speter#include <sys/param.h>
48251881Speter#include <sys/systm.h>
49251881Speter#include <sys/bio.h>
50251881Speter#include <sys/buf.h>
51251881Speter#include <sys/conf.h>
52251881Speter#include <sys/cons.h>
53251881Speter#include <sys/disklabel.h>
54251881Speter#include <sys/eventhandler.h>
55251881Speter#include <sys/kernel.h>
56251881Speter#include <sys/kthread.h>
57251881Speter#include <sys/malloc.h>
58251881Speter#include <sys/mount.h>
59251881Speter#include <sys/proc.h>
60251881Speter#include <sys/reboot.h>
61251881Speter#include <sys/resourcevar.h>
62251881Speter#include <sys/smp.h>		/* smp_active */
63251881Speter#include <sys/sysctl.h>
64251881Speter#include <sys/sysproto.h>
65251881Speter#include <sys/vnode.h>
66251881Speter
67251881Speter#include <machine/pcb.h>
68251881Speter#include <machine/md_var.h>
69251881Speter#include <machine/smp.h>
70251881Speter
71251881Speter#include <sys/signalvar.h>
72251881Speter#ifdef DDB
73251881Speter#include <ddb/ddb.h>
74251881Speter#endif
75251881Speter
76251881Speter#ifndef PANIC_REBOOT_WAIT_TIME
77251881Speter#define PANIC_REBOOT_WAIT_TIME 15 /* default to 15 seconds */
78251881Speter#endif
79251881Speter
80251881Speter/*
81251881Speter * Note that stdarg.h and the ANSI style va_start macro is used for both
82251881Speter * ANSI and traditional C compilers.
83251881Speter */
84251881Speter#include <machine/stdarg.h>
85251881Speter
86251881Speter#ifdef DDB
87251881Speter#ifdef DDB_UNATTENDED
88251881Speterint debugger_on_panic = 0;
89251881Speter#else
90251881Speterint debugger_on_panic = 1;
91251881Speter#endif
92251881SpeterSYSCTL_INT(_debug, OID_AUTO, debugger_on_panic, CTLFLAG_RW,
93251881Speter	&debugger_on_panic, 0, "Run debugger on kernel panic");
94251881Speter#endif
95251881Speter
96251881Speterint sync_on_panic = 1;
97251881SpeterSYSCTL_INT(_kern, OID_AUTO, sync_on_panic, CTLFLAG_RW,
98251881Speter	&sync_on_panic, 0, "Do a sync before rebooting from a panic");
99251881Speter
100251881SpeterSYSCTL_NODE(_kern, OID_AUTO, shutdown, CTLFLAG_RW, 0, "Shutdown environment");
101251881Speter
102251881Speter#ifdef	HW_WDOG
103251881Speter/*
104251881Speter * If there is a hardware watchdog, point this at the function needed to
105251881Speter * hold it off.
106251881Speter * It's needed when the kernel needs to do some lengthy operations.
107251881Speter * e.g. in wd.c when dumping core.. It's most annoying to have
108251881Speter * your precious core-dump only half written because the wdog kicked in.
109251881Speter */
110251881Speterwatchdog_tickle_fn wdog_tickler = NULL;
111251881Speter#endif	/* HW_WDOG */
112251881Speter
113251881Speter/*
114251881Speter * Variable panicstr contains argument to first call to panic; used as flag
115251881Speter * to indicate that the kernel has already called panic.
116251881Speter */
117251881Speterconst char *panicstr;
118251881Speter
119251881Speterint dumping;				/* system is dumping */
120251881Speterstatic struct dumperinfo dumper;	/* our selected dumper */
121251881Speterstatic struct pcb dumppcb;		/* "You Are Here" sign for dump-debuggers */
122251881Speter
123251881Speterstatic void boot(int) __dead2;
124251881Speterstatic void poweroff_wait(void *, int);
125251881Speterstatic void shutdown_halt(void *junk, int howto);
126251881Speterstatic void shutdown_panic(void *junk, int howto);
127251881Speterstatic void shutdown_reset(void *junk, int howto);
128251881Speter
129251881Speter/* register various local shutdown events */
130251881Speterstatic void
131251881Spetershutdown_conf(void *unused)
132251881Speter{
133251881Speter	EVENTHANDLER_REGISTER(shutdown_final, poweroff_wait, NULL, SHUTDOWN_PRI_FIRST);
134251881Speter	EVENTHANDLER_REGISTER(shutdown_final, shutdown_halt, NULL, SHUTDOWN_PRI_LAST + 100);
135251881Speter	EVENTHANDLER_REGISTER(shutdown_final, shutdown_panic, NULL, SHUTDOWN_PRI_LAST + 100);
136251881Speter	EVENTHANDLER_REGISTER(shutdown_final, shutdown_reset, NULL, SHUTDOWN_PRI_LAST + 200);
137251881Speter}
138251881Speter
139251881SpeterSYSINIT(shutdown_conf, SI_SUB_INTRINSIC, SI_ORDER_ANY, shutdown_conf, NULL)
140251881Speter
141251881Speter/*
142251881Speter * The system call that results in a reboot
143251881Speter *
144251881Speter * MPSAFE
145251881Speter */
146251881Speter/* ARGSUSED */
147251881Speterint
148251881Speterreboot(struct thread *td, struct reboot_args *uap)
149251881Speter{
150251881Speter	int error;
151251881Speter
152251881Speter	mtx_lock(&Giant);
153251881Speter	if ((error = suser(td)) == 0)
154251881Speter		boot(uap->opt);
155251881Speter	mtx_unlock(&Giant);
156251881Speter	return (error);
157251881Speter}
158251881Speter
159251881Speter/*
160262253Speter * Called by events that want to shut down.. e.g  <CTL><ALT><DEL> on a PC
161262253Speter */
162251881Speterstatic int shutdown_howto = 0;
163251881Speter
164251881Spetervoid
165251881Spetershutdown_nice(int howto)
166251881Speter{
167251881Speter	shutdown_howto = howto;
168251881Speter
169251881Speter	/* Send a signal to init(8) and have it shutdown the world */
170251881Speter	if (initproc != NULL) {
171251881Speter		PROC_LOCK(initproc);
172251881Speter		psignal(initproc, SIGINT);
173251881Speter		PROC_UNLOCK(initproc);
174251881Speter	} else {
175251881Speter		/* No init(8) running, so simply reboot */
176251881Speter		boot(RB_NOSYNC);
177251881Speter	}
178251881Speter	return;
179251881Speter}
180251881Speterstatic int	waittime = -1;
181251881Speter
182251881Speterstatic void
183251881Speterprint_uptime(void)
184251881Speter{
185251881Speter	int f;
186251881Speter	struct timespec ts;
187251881Speter
188251881Speter	getnanouptime(&ts);
189251881Speter	printf("Uptime: ");
190251881Speter	f = 0;
191251881Speter	if (ts.tv_sec >= 86400) {
192251881Speter		printf("%ldd", (long)ts.tv_sec / 86400);
193289166Speter		ts.tv_sec %= 86400;
194289166Speter		f = 1;
195289166Speter	}
196289166Speter	if (f || ts.tv_sec >= 3600) {
197251881Speter		printf("%ldh", (long)ts.tv_sec / 3600);
198251881Speter		ts.tv_sec %= 3600;
199251881Speter		f = 1;
200251881Speter	}
201251881Speter	if (f || ts.tv_sec >= 60) {
202251881Speter		printf("%ldm", (long)ts.tv_sec / 60);
203251881Speter		ts.tv_sec %= 60;
204251881Speter		f = 1;
205251881Speter	}
206251881Speter	printf("%lds\n", (long)ts.tv_sec);
207251881Speter}
208251881Speter
209251881Speterstatic void
210251881Speterdoadump(void)
211251881Speter{
212251881Speter	savectx(&dumppcb);
213251881Speter	dumping++;
214251881Speter	dumpsys(&dumper);
215251881Speter}
216251881Speter
217251881Speter/*
218251881Speter *  Go through the rigmarole of shutting down..
219251881Speter * this used to be in machdep.c but I'll be dammned if I could see
220251881Speter * anything machine dependant in it.
221251881Speter */
222251881Speterstatic void
223251881Speterboot(int howto)
224251881Speter{
225251881Speter
226251881Speter	/* collect extra flags that shutdown_nice might have set */
227251881Speter	howto |= shutdown_howto;
228251881Speter
229251881Speter#ifdef DDB
230251881Speter	/* We are out of the debugger now. */
231251881Speter	db_active = 0;
232251881Speter#endif
233251881Speter
234251881Speter#ifdef SMP
235251881Speter	if (smp_active)
236251881Speter		printf("boot() called on cpu#%d\n", PCPU_GET(cpuid));
237251881Speter#endif
238251881Speter	/*
239251881Speter	 * Do any callouts that should be done BEFORE syncing the filesystems.
240251881Speter	 */
241251881Speter	EVENTHANDLER_INVOKE(shutdown_pre_sync, howto);
242251881Speter
243251881Speter	/*
244251881Speter	 * Now sync filesystems
245251881Speter	 */
246251881Speter	if (!cold && (howto & RB_NOSYNC) == 0 && waittime < 0) {
247251881Speter		register struct buf *bp;
248251881Speter		int iter, nbusy, pbusy;
249251881Speter		int subiter;
250251881Speter
251251881Speter		waittime = 0;
252251881Speter		printf("\nsyncing disks... ");
253251881Speter
254251881Speter		sync(&thread0, NULL);
255251881Speter
256251881Speter		/*
257251881Speter		 * With soft updates, some buffers that are
258251881Speter		 * written will be remarked as dirty until other
259251881Speter		 * buffers are written.
260251881Speter		 */
261251881Speter		for (iter = pbusy = 0; iter < 20; iter++) {
262251881Speter			nbusy = 0;
263251881Speter			for (bp = &buf[nbuf]; --bp >= buf; ) {
264251881Speter				if ((bp->b_flags & B_INVAL) == 0 &&
265251881Speter				    BUF_REFCNT(bp) > 0) {
266251881Speter					nbusy++;
267251881Speter				} else if ((bp->b_flags & (B_DELWRI | B_INVAL))
268251881Speter						== B_DELWRI) {
269251881Speter					/* bawrite(bp);*/
270251881Speter					nbusy++;
271251881Speter				}
272251881Speter			}
273251881Speter			if (nbusy == 0)
274251881Speter				break;
275251881Speter			printf("%d ", nbusy);
276251881Speter			if (nbusy < pbusy)
277251881Speter				iter = 0;
278251881Speter			pbusy = nbusy;
279251881Speter			sync(&thread0, NULL);
280251881Speter 			if (curthread != NULL) {
281251881Speter				DROP_GIANT();
282251881Speter   				for (subiter = 0; subiter < 50 * iter; subiter++) {
283251881Speter     					mtx_lock_spin(&sched_lock);
284251881Speter					setrunqueue(curthread);
285251881Speter					curthread->td_proc->p_stats->p_ru.ru_nvcsw++;
286251881Speter     					mi_switch(); /* Allow interrupt threads to run */
287251881Speter     					mtx_unlock_spin(&sched_lock);
288251881Speter     					DELAY(1000);
289251881Speter   				}
290251881Speter				PICKUP_GIANT();
291251881Speter 			} else
292251881Speter			DELAY(50000 * iter);
293251881Speter		}
294251881Speter		printf("\n");
295251881Speter		/*
296251881Speter		 * Count only busy local buffers to prevent forcing
297251881Speter		 * a fsck if we're just a client of a wedged NFS server
298251881Speter		 */
299251881Speter		nbusy = 0;
300251881Speter		for (bp = &buf[nbuf]; --bp >= buf; ) {
301251881Speter			if (((bp->b_flags&B_INVAL) == 0 && BUF_REFCNT(bp)) ||
302251881Speter			    ((bp->b_flags & (B_DELWRI|B_INVAL)) == B_DELWRI)) {
303251881Speter				if (bp->b_dev == NODEV) {
304251881Speter					TAILQ_REMOVE(&mountlist,
305251881Speter					    bp->b_vp->v_mount, mnt_list);
306251881Speter					continue;
307251881Speter				}
308251881Speter				nbusy++;
309251881Speter#if defined(SHOW_BUSYBUFS) || defined(DIAGNOSTIC)
310251881Speter				printf(
311251881Speter			    "%d: dev:%s, flags:%08lx, blkno:%ld, lblkno:%ld\n",
312251881Speter				    nbusy, devtoname(bp->b_dev),
313251881Speter				    bp->b_flags, (long)bp->b_blkno,
314251881Speter				    (long)bp->b_lblkno);
315251881Speter#endif
316251881Speter			}
317251881Speter		}
318251881Speter		if (nbusy) {
319251881Speter			/*
320251881Speter			 * Failed to sync all blocks. Indicate this and don't
321251881Speter			 * unmount filesystems (thus forcing an fsck on reboot).
322251881Speter			 */
323251881Speter			printf("giving up on %d buffers\n", nbusy);
324251881Speter			DELAY(5000000);	/* 5 seconds */
325251881Speter		} else {
326251881Speter			printf("done\n");
327251881Speter			/*
328251881Speter			 * Unmount filesystems
329251881Speter			 */
330251881Speter			if (panicstr == 0)
331251881Speter				vfs_unmountall();
332251881Speter		}
333251881Speter		DELAY(100000);		/* wait for console output to finish */
334251881Speter	}
335251881Speter
336251881Speter	print_uptime();
337251881Speter
338251881Speter	/*
339251881Speter	 * Ok, now do things that assume all filesystem activity has
340251881Speter	 * been completed.
341251881Speter	 */
342251881Speter	EVENTHANDLER_INVOKE(shutdown_post_sync, howto);
343251881Speter	splhigh();
344251881Speter	if ((howto & (RB_HALT|RB_DUMP)) == RB_DUMP &&
345251881Speter	    !cold && dumper.dumper != NULL && !dumping)
346251881Speter		doadump();
347251881Speter
348251881Speter	/* Now that we're going to really halt the system... */
349251881Speter	EVENTHANDLER_INVOKE(shutdown_final, howto);
350251881Speter
351251881Speter	for(;;) ;	/* safety against shutdown_reset not working */
352251881Speter	/* NOTREACHED */
353251881Speter}
354251881Speter
355251881Speter/*
356251881Speter * If the shutdown was a clean halt, behave accordingly.
357251881Speter */
358251881Speterstatic void
359251881Spetershutdown_halt(void *junk, int howto)
360251881Speter{
361251881Speter	if (howto & RB_HALT) {
362251881Speter		printf("\n");
363251881Speter		printf("The operating system has halted.\n");
364251881Speter		printf("Please press any key to reboot.\n\n");
365251881Speter		switch (cngetc()) {
366251881Speter		case -1:		/* No console, just die */
367251881Speter			cpu_halt();
368251881Speter			/* NOTREACHED */
369251881Speter		default:
370251881Speter			howto &= ~RB_HALT;
371251881Speter			break;
372251881Speter		}
373251881Speter	}
374251881Speter}
375251881Speter
376251881Speter/*
377251881Speter * Check to see if the system paniced, pause and then reboot
378251881Speter * according to the specified delay.
379251881Speter */
380251881Speterstatic void
381251881Spetershutdown_panic(void *junk, int howto)
382251881Speter{
383251881Speter	int loop;
384251881Speter
385251881Speter	if (howto & RB_DUMP) {
386251881Speter		if (PANIC_REBOOT_WAIT_TIME != 0) {
387251881Speter			if (PANIC_REBOOT_WAIT_TIME != -1) {
388251881Speter				printf("Automatic reboot in %d seconds - "
389251881Speter				       "press a key on the console to abort\n",
390251881Speter					PANIC_REBOOT_WAIT_TIME);
391251881Speter				for (loop = PANIC_REBOOT_WAIT_TIME * 10;
392251881Speter				     loop > 0; --loop) {
393251881Speter					DELAY(1000 * 100); /* 1/10th second */
394251881Speter					/* Did user type a key? */
395251881Speter					if (cncheckc() != -1)
396251881Speter						break;
397251881Speter				}
398251881Speter				if (!loop)
399251881Speter					return;
400251881Speter			}
401251881Speter		} else { /* zero time specified - reboot NOW */
402251881Speter			return;
403251881Speter		}
404251881Speter		printf("--> Press a key on the console to reboot,\n");
405251881Speter		printf("--> or switch off the system now.\n");
406251881Speter		cngetc();
407251881Speter	}
408251881Speter}
409251881Speter
410251881Speter/*
411251881Speter * Everything done, now reset
412251881Speter */
413251881Speterstatic void
414251881Spetershutdown_reset(void *junk, int howto)
415251881Speter{
416251881Speter	printf("Rebooting...\n");
417251881Speter	DELAY(1000000);	/* wait 1 sec for printf's to complete and be read */
418251881Speter	/* cpu_boot(howto); */ /* doesn't do anything at the moment */
419251881Speter	cpu_reset();
420251881Speter	/* NOTREACHED */ /* assuming reset worked */
421251881Speter}
422251881Speter
423251881Speter#ifdef SMP
424251881Speterstatic u_int panic_cpu = NOCPU;
425251881Speter#endif
426251881Speter
427251881Speter/*
428251881Speter * Panic is called on unresolvable fatal errors.  It prints "panic: mesg",
429251881Speter * and then reboots.  If we are called twice, then we avoid trying to sync
430251881Speter * the disks as this often leads to recursive panics.
431251881Speter *
432251881Speter * MPSAFE
433251881Speter */
434251881Spetervoid
435251881Speterpanic(const char *fmt, ...)
436251881Speter{
437251881Speter	int bootopt;
438251881Speter	va_list ap;
439251881Speter	static char buf[256];
440251881Speter
441251881Speter#ifdef SMP
442251881Speter	/*
443251881Speter	 * We don't want multiple CPU's to panic at the same time, so we
444251881Speter	 * use panic_cpu as a simple spinlock.  We have to keep checking
445251881Speter	 * panic_cpu if we are spinning in case the panic on the first
446251881Speter	 * CPU is canceled.
447251881Speter	 */
448251881Speter	if (panic_cpu != PCPU_GET(cpuid))
449251881Speter		while (atomic_cmpset_int(&panic_cpu, NOCPU,
450251881Speter		    PCPU_GET(cpuid)) == 0)
451251881Speter			while (panic_cpu != NOCPU)
452251881Speter				; /* nothing */
453251881Speter#endif
454251881Speter
455251881Speter	bootopt = RB_AUTOBOOT | RB_DUMP;
456251881Speter	if (panicstr)
457251881Speter		bootopt |= RB_NOSYNC;
458251881Speter	else
459251881Speter		panicstr = fmt;
460251881Speter
461251881Speter	va_start(ap, fmt);
462251881Speter	(void)vsnprintf(buf, sizeof(buf), fmt, ap);
463251881Speter	if (panicstr == fmt)
464251881Speter		panicstr = buf;
465251881Speter	va_end(ap);
466251881Speter	printf("panic: %s\n", buf);
467251881Speter#ifdef SMP
468251881Speter	/* two separate prints in case of an unmapped page and trap */
469251881Speter	printf("cpuid = %d; ", PCPU_GET(cpuid));
470251881Speter#ifdef APIC_IO
471251881Speter	printf("lapic.id = %08x\n", lapic.id);
472251881Speter#endif
473251881Speter#endif
474251881Speter
475251881Speter#if defined(DDB)
476251881Speter	if (debugger_on_panic)
477251881Speter		Debugger ("panic");
478251881Speter#ifdef RESTARTABLE_PANICS
479251881Speter	/* See if the user aborted the panic, in which case we continue. */
480251881Speter	if (panicstr == NULL) {
481251881Speter#ifdef SMP
482251881Speter		atomic_store_rel_int(&panic_cpu, NOCPU);
483251881Speter#endif
484251881Speter		return;
485251881Speter	}
486251881Speter#endif
487251881Speter#endif
488251881Speter	if (!sync_on_panic)
489251881Speter		bootopt |= RB_NOSYNC;
490251881Speter	boot(bootopt);
491251881Speter}
492251881Speter
493251881Speter/*
494251881Speter * Support for poweroff delay.
495251881Speter */
496251881Speter#ifndef POWEROFF_DELAY
497251881Speter# define POWEROFF_DELAY 5000
498251881Speter#endif
499251881Speterstatic int poweroff_delay = POWEROFF_DELAY;
500251881Speter
501251881SpeterSYSCTL_INT(_kern_shutdown, OID_AUTO, poweroff_delay, CTLFLAG_RW,
502251881Speter	&poweroff_delay, 0, "");
503251881Speter
504251881Speterstatic void
505251881Speterpoweroff_wait(void *junk, int howto)
506251881Speter{
507251881Speter	if(!(howto & RB_POWEROFF) || poweroff_delay <= 0)
508251881Speter		return;
509251881Speter	DELAY(poweroff_delay * 1000);
510251881Speter}
511251881Speter
512251881Speter/*
513251881Speter * Some system processes (e.g. syncer) need to be stopped at appropriate
514251881Speter * points in their main loops prior to a system shutdown, so that they
515251881Speter * won't interfere with the shutdown process (e.g. by holding a disk buf
516251881Speter * to cause sync to fail).  For each of these system processes, register
517251881Speter * shutdown_kproc() as a handler for one of shutdown events.
518251881Speter */
519251881Speterstatic int kproc_shutdown_wait = 60;
520251881SpeterSYSCTL_INT(_kern_shutdown, OID_AUTO, kproc_shutdown_wait, CTLFLAG_RW,
521251881Speter    &kproc_shutdown_wait, 0, "");
522251881Speter
523251881Spetervoid
524251881Speterkproc_shutdown(void *arg, int howto)
525251881Speter{
526251881Speter	struct proc *p;
527251881Speter	int error;
528251881Speter
529251881Speter	if (panicstr)
530251881Speter		return;
531251881Speter
532251881Speter	p = (struct proc *)arg;
533251881Speter	printf("Waiting (max %d seconds) for system process `%s' to stop...",
534251881Speter	    kproc_shutdown_wait, p->p_comm);
535251881Speter	error = kthread_suspend(p, kproc_shutdown_wait * hz);
536251881Speter
537251881Speter	if (error == EWOULDBLOCK)
538251881Speter		printf("timed out\n");
539251881Speter	else
540251881Speter		printf("stopped\n");
541251881Speter}
542251881Speter
543251881Speter/* Registration of dumpers */
544251881Speterint
545251881Speterset_dumper(struct dumperinfo *di)
546251881Speter{
547251881Speter	if (di == NULL) {
548251881Speter		bzero(&dumper, sizeof dumper);
549251881Speter		return (0);
550251881Speter	}
551251881Speter	if (dumper.dumper != NULL)
552251881Speter		return (EBUSY);
553251881Speter	dumper = *di;
554251881Speter	return (0);
555251881Speter}
556251881Speter
557251881Speter#if !defined(__i386__) && !defined(__ia64__)
558251881Spetervoid
559251881Speterdumpsys(struct dumperinfo *di __unused)
560251881Speter{
561251881Speter
562251881Speter	printf("Kernel dumps not implemented on this architecture\n");
563251881Speter}
564251881Speter#endif
565251881Speter