Deleted Added
full compact
kern_shutdown.c (58755) kern_shutdown.c (60041)
1/*-
2 * Copyright (c) 1986, 1988, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)kern_shutdown.c 8.3 (Berkeley) 1/21/94
1/*-
2 * Copyright (c) 1986, 1988, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)kern_shutdown.c 8.3 (Berkeley) 1/21/94
39 * $FreeBSD: head/sys/kern/kern_shutdown.c 58755 2000-03-28 18:06:49Z dillon $
39 * $FreeBSD: head/sys/kern/kern_shutdown.c 60041 2000-05-05 09:59:14Z phk $
40 */
41
42#include "opt_ddb.h"
43#include "opt_hw_wdog.h"
44#include "opt_panic.h"
45#include "opt_show_busybufs.h"
46
47#include <sys/param.h>
48#include <sys/systm.h>
49#include <sys/eventhandler.h>
40 */
41
42#include "opt_ddb.h"
43#include "opt_hw_wdog.h"
44#include "opt_panic.h"
45#include "opt_show_busybufs.h"
46
47#include <sys/param.h>
48#include <sys/systm.h>
49#include <sys/eventhandler.h>
50#include <sys/bio.h>
50#include <sys/buf.h>
51#include <sys/reboot.h>
52#include <sys/proc.h>
53#include <sys/vnode.h>
54#include <sys/kernel.h>
55#include <sys/kthread.h>
56#include <sys/mount.h>
57#include <sys/queue.h>
58#include <sys/sysctl.h>
59#include <sys/conf.h>
60#include <sys/sysproto.h>
61#include <sys/cons.h>
62
63#include <machine/pcb.h>
64#include <machine/clock.h>
65#include <machine/md_var.h>
66#include <machine/smp.h> /* smp_active, cpuid */
67
68#include <sys/signalvar.h>
69
70#ifndef PANIC_REBOOT_WAIT_TIME
71#define PANIC_REBOOT_WAIT_TIME 15 /* default to 15 seconds */
72#endif
73
74/*
75 * Note that stdarg.h and the ANSI style va_start macro is used for both
76 * ANSI and traditional C compilers.
77 */
78#include <machine/stdarg.h>
79
80#ifdef DDB
81#ifdef DDB_UNATTENDED
82int debugger_on_panic = 0;
83#else
84int debugger_on_panic = 1;
85#endif
86SYSCTL_INT(_debug, OID_AUTO, debugger_on_panic, CTLFLAG_RW,
87 &debugger_on_panic, 0, "Run debugger on kernel panic");
88#endif
89
90SYSCTL_NODE(_kern, OID_AUTO, shutdown, CTLFLAG_RW, 0, "Shutdown environment");
91
92#ifdef HW_WDOG
93/*
94 * If there is a hardware watchdog, point this at the function needed to
95 * hold it off.
96 * It's needed when the kernel needs to do some lengthy operations.
97 * e.g. in wd.c when dumping core.. It's most annoying to have
98 * your precious core-dump only half written because the wdog kicked in.
99 */
100watchdog_tickle_fn wdog_tickler = NULL;
101#endif /* HW_WDOG */
102
103/*
104 * Variable panicstr contains argument to first call to panic; used as flag
105 * to indicate that the kernel has already called panic.
106 */
107const char *panicstr;
108
109static void boot __P((int)) __dead2;
110static void dumpsys __P((void));
111static int setdumpdev __P((dev_t dev));
112static void poweroff_wait __P((void *, int));
113static void print_uptime __P((void));
114static void shutdown_halt __P((void *junk, int howto));
115static void shutdown_panic __P((void *junk, int howto));
116static void shutdown_reset __P((void *junk, int howto));
117
118/* register various local shutdown events */
119static void
120shutdown_conf(void *unused)
121{
122 EVENTHANDLER_REGISTER(shutdown_final, poweroff_wait, NULL, SHUTDOWN_PRI_FIRST);
123 EVENTHANDLER_REGISTER(shutdown_final, shutdown_halt, NULL, SHUTDOWN_PRI_LAST + 100);
124 EVENTHANDLER_REGISTER(shutdown_final, shutdown_panic, NULL, SHUTDOWN_PRI_LAST + 100);
125 EVENTHANDLER_REGISTER(shutdown_final, shutdown_reset, NULL, SHUTDOWN_PRI_LAST + 200);
126}
127
128SYSINIT(shutdown_conf, SI_SUB_INTRINSIC, SI_ORDER_ANY, shutdown_conf, NULL)
129
130/* ARGSUSED */
131
132/*
133 * The system call that results in a reboot
134 */
135int
136reboot(p, uap)
137 struct proc *p;
138 struct reboot_args *uap;
139{
140 int error;
141
142 if ((error = suser(p)))
143 return (error);
144
145 boot(uap->opt);
146 return (0);
147}
148
149/*
150 * Called by events that want to shut down.. e.g <CTL><ALT><DEL> on a PC
151 */
152void
153shutdown_nice()
154{
155 /* Send a signal to init(8) and have it shutdown the world */
156 if (initproc != NULL) {
157 psignal(initproc, SIGINT);
158 } else {
159 /* No init(8) running, so simply reboot */
160 boot(RB_NOSYNC);
161 }
162 return;
163}
164static int waittime = -1;
165static struct pcb dumppcb;
166
167static void
168print_uptime()
169{
170 int f;
171 struct timespec ts;
172
173 getnanouptime(&ts);
174 printf("Uptime: ");
175 f = 0;
176 if (ts.tv_sec >= 86400) {
177 printf("%ldd", ts.tv_sec / 86400);
178 ts.tv_sec %= 86400;
179 f = 1;
180 }
181 if (f || ts.tv_sec >= 3600) {
182 printf("%ldh", ts.tv_sec / 3600);
183 ts.tv_sec %= 3600;
184 f = 1;
185 }
186 if (f || ts.tv_sec >= 60) {
187 printf("%ldm", ts.tv_sec / 60);
188 ts.tv_sec %= 60;
189 f = 1;
190 }
191 printf("%lds\n", ts.tv_sec);
192}
193
194/*
195 * Go through the rigmarole of shutting down..
196 * this used to be in machdep.c but I'll be dammned if I could see
197 * anything machine dependant in it.
198 */
199static void
200boot(howto)
201 int howto;
202{
203
204#ifdef SMP
205 if (smp_active) {
206 printf("boot() called on cpu#%d\n", cpuid);
207 }
208#endif
209 /*
210 * Do any callouts that should be done BEFORE syncing the filesystems.
211 */
212 EVENTHANDLER_INVOKE(shutdown_pre_sync, howto);
213
214 /*
215 * Now sync filesystems
216 */
217 if (!cold && (howto & RB_NOSYNC) == 0 && waittime < 0) {
218 register struct buf *bp;
219 int iter, nbusy;
220
221 waittime = 0;
222 printf("\nsyncing disks... ");
223
224 sync(&proc0, NULL);
225
226 /*
227 * With soft updates, some buffers that are
228 * written will be remarked as dirty until other
229 * buffers are written.
230 */
231 for (iter = 0; iter < 20; iter++) {
232 nbusy = 0;
233 for (bp = &buf[nbuf]; --bp >= buf; ) {
234 if ((bp->b_flags & B_INVAL) == 0 &&
235 BUF_REFCNT(bp) > 0) {
236 nbusy++;
237 } else if ((bp->b_flags & (B_DELWRI | B_INVAL))
238 == B_DELWRI) {
239 /* bawrite(bp);*/
240 nbusy++;
241 }
242 }
243 if (nbusy == 0)
244 break;
245 printf("%d ", nbusy);
246 sync(&proc0, NULL);
247 DELAY(50000 * iter);
248 }
249 printf("\n");
250 /*
251 * Count only busy local buffers to prevent forcing
252 * a fsck if we're just a client of a wedged NFS server
253 */
254 nbusy = 0;
255 for (bp = &buf[nbuf]; --bp >= buf; ) {
256 if (((bp->b_flags&B_INVAL) == 0 && BUF_REFCNT(bp)) ||
257 ((bp->b_flags & (B_DELWRI|B_INVAL)) == B_DELWRI)) {
258 if (bp->b_dev == NODEV) {
259 TAILQ_REMOVE(&mountlist,
260 bp->b_vp->v_mount, mnt_list);
261 continue;
262 }
263 nbusy++;
264#if defined(SHOW_BUSYBUFS) || defined(DIAGNOSTIC)
265 printf(
266 "%d: dev:%s, flags:%08lx, blkno:%ld, lblkno:%ld\n",
267 nbusy, devtoname(bp->b_dev),
268 bp->b_flags, (long)bp->b_blkno,
269 (long)bp->b_lblkno);
270#endif
271 }
272 }
273 if (nbusy) {
274 /*
275 * Failed to sync all blocks. Indicate this and don't
276 * unmount filesystems (thus forcing an fsck on reboot).
277 */
278 printf("giving up on %d buffers\n", nbusy);
279 DELAY(5000000); /* 5 seconds */
280 } else {
281 printf("done\n");
282 /*
283 * Unmount filesystems
284 */
285 if (panicstr == 0)
286 vfs_unmountall();
287 }
288 DELAY(100000); /* wait for console output to finish */
289 }
290
291 print_uptime();
292
293 /*
294 * Ok, now do things that assume all filesystem activity has
295 * been completed.
296 */
297 EVENTHANDLER_INVOKE(shutdown_post_sync, howto);
298 splhigh();
299 if ((howto & (RB_HALT|RB_DUMP)) == RB_DUMP && !cold) {
300 savectx(&dumppcb);
301#ifdef __i386__
302 dumppcb.pcb_cr3 = rcr3();
303#endif
304 dumpsys();
305 }
306
307 /* Now that we're going to really halt the system... */
308 EVENTHANDLER_INVOKE(shutdown_final, howto);
309
310 for(;;) ; /* safety against shutdown_reset not working */
311 /* NOTREACHED */
312}
313
314/*
315 * If the shutdown was a clean halt, behave accordingly.
316 */
317static void
318shutdown_halt(void *junk, int howto)
319{
320 if (howto & RB_HALT) {
321 printf("\n");
322 printf("The operating system has halted.\n");
323 printf("Please press any key to reboot.\n\n");
324 switch (cngetc()) {
325 case -1: /* No console, just die */
326 cpu_halt();
327 /* NOTREACHED */
328 default:
329 howto &= ~RB_HALT;
330 break;
331 }
332 }
333}
334
335/*
336 * Check to see if the system paniced, pause and then reboot
337 * according to the specified delay.
338 */
339static void
340shutdown_panic(void *junk, int howto)
341{
342 int loop;
343
344 if (howto & RB_DUMP) {
345 if (PANIC_REBOOT_WAIT_TIME != 0) {
346 if (PANIC_REBOOT_WAIT_TIME != -1) {
347 printf("Automatic reboot in %d seconds - "
348 "press a key on the console to abort\n",
349 PANIC_REBOOT_WAIT_TIME);
350 for (loop = PANIC_REBOOT_WAIT_TIME * 10;
351 loop > 0; --loop) {
352 DELAY(1000 * 100); /* 1/10th second */
353 /* Did user type a key? */
354 if (cncheckc() != -1)
355 break;
356 }
357 if (!loop)
358 return;
359 }
360 } else { /* zero time specified - reboot NOW */
361 return;
362 }
363 printf("--> Press a key on the console to reboot <--\n");
364 cngetc();
365 }
366}
367
368/*
369 * Everything done, now reset
370 */
371static void
372shutdown_reset(void *junk, int howto)
373{
374 printf("Rebooting...\n");
375 DELAY(1000000); /* wait 1 sec for printf's to complete and be read */
376 /* cpu_boot(howto); */ /* doesn't do anything at the moment */
377 cpu_reset();
378 /* NOTREACHED */ /* assuming reset worked */
379}
380
381/*
382 * Magic number for savecore
383 *
384 * exported (symorder) and used at least by savecore(8)
385 *
386 */
387static u_long const dumpmag = 0x8fca0101UL;
388
389static int dumpsize = 0; /* also for savecore */
390
391static int dodump = 1;
392
393SYSCTL_INT(_machdep, OID_AUTO, do_dump, CTLFLAG_RW, &dodump, 0,
394 "Try to perform coredump on kernel panic");
395
396static int
397setdumpdev(dev)
398 dev_t dev;
399{
400 int psize;
401 long newdumplo;
402
403 if (dev == NODEV) {
404 dumpdev = dev;
405 return (0);
406 }
407 if (devsw(dev) == NULL)
408 return (ENXIO); /* XXX is this right? */
409 if (devsw(dev)->d_psize == NULL)
410 return (ENXIO); /* XXX should be ENODEV ? */
411 psize = devsw(dev)->d_psize(dev);
412 if (psize == -1)
413 return (ENXIO); /* XXX should be ENODEV ? */
414 /*
415 * XXX should clean up checking in dumpsys() to be more like this.
416 */
417 newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE;
418 if (newdumplo < 0)
419 return (ENOSPC);
420 dumpdev = dev;
421 dumplo = newdumplo;
422 return (0);
423}
424
425
426/* ARGSUSED */
427static void dump_conf __P((void *dummy));
428static void
429dump_conf(dummy)
430 void *dummy;
431{
432 if (setdumpdev(dumpdev) != 0)
433 dumpdev = NODEV;
434}
435
436SYSINIT(dump_conf, SI_SUB_DUMP_CONF, SI_ORDER_FIRST, dump_conf, NULL)
437
438static int
439sysctl_kern_dumpdev SYSCTL_HANDLER_ARGS
440{
441 int error;
442 udev_t ndumpdev;
443
444 ndumpdev = dev2udev(dumpdev);
445 error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req);
446 if (error == 0 && req->newptr != NULL)
447 error = setdumpdev(udev2dev(ndumpdev, 0));
448 return (error);
449}
450
451SYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW,
452 0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", "");
453
454/*
455 * Doadump comes here after turning off memory management and
456 * getting on the dump stack, either when called above, or by
457 * the auto-restart code.
458 */
459static void
460dumpsys(void)
461{
462 int error;
463 static int dumping;
464
465 if (dumping++) {
466 printf("Dump already in progress, bailing...\n");
467 return;
468 }
469 if (!dodump)
470 return;
471 if (dumpdev == NODEV)
472 return;
473 if (!(devsw(dumpdev)))
474 return;
475 if (!(devsw(dumpdev)->d_dump))
476 return;
477 dumpsize = Maxmem;
478 printf("\ndumping to dev %s, offset %ld\n", devtoname(dumpdev), dumplo);
479 printf("dump ");
480 error = (*devsw(dumpdev)->d_dump)(dumpdev);
481 if (error == 0) {
482 printf("succeeded\n");
483 return;
484 }
485 printf("failed, reason: ");
486 switch (error) {
487 case ENODEV:
488 printf("device doesn't support a dump routine\n");
489 break;
490
491 case ENXIO:
492 printf("device bad\n");
493 break;
494
495 case EFAULT:
496 printf("device not ready\n");
497 break;
498
499 case EINVAL:
500 printf("area improper\n");
501 break;
502
503 case EIO:
504 printf("i/o error\n");
505 break;
506
507 case EINTR:
508 printf("aborted from console\n");
509 break;
510
511 default:
512 printf("unknown, error = %d\n", error);
513 break;
514 }
515}
516
517/*
518 * Panic is called on unresolvable fatal errors. It prints "panic: mesg",
519 * and then reboots. If we are called twice, then we avoid trying to sync
520 * the disks as this often leads to recursive panics.
521 */
522void
523panic(const char *fmt, ...)
524{
525 int bootopt;
526 va_list ap;
527 static char buf[256];
528
529 bootopt = RB_AUTOBOOT | RB_DUMP;
530 if (panicstr)
531 bootopt |= RB_NOSYNC;
532 else
533 panicstr = fmt;
534
535 va_start(ap, fmt);
536 (void)vsnprintf(buf, sizeof(buf), fmt, ap);
537 if (panicstr == fmt)
538 panicstr = buf;
539 va_end(ap);
540 printf("panic: %s\n", buf);
541#ifdef SMP
542 /* three seperate prints in case of an unmapped page and trap */
543 printf("mp_lock = %08x; ", mp_lock);
544 printf("cpuid = %d; ", cpuid);
545 printf("lapic.id = %08x\n", lapic.id);
546#endif
547
548#if defined(DDB)
549 if (debugger_on_panic)
550 Debugger ("panic");
551#endif
552 boot(bootopt);
553}
554
555/*
556 * Support for poweroff delay.
557 */
558#ifndef POWEROFF_DELAY
559# define POWEROFF_DELAY 5000
560#endif
561static int poweroff_delay = POWEROFF_DELAY;
562
563SYSCTL_INT(_kern_shutdown, OID_AUTO, poweroff_delay, CTLFLAG_RW,
564 &poweroff_delay, 0, "");
565
566static void
567poweroff_wait(void *junk, int howto)
568{
569 if(!(howto & RB_POWEROFF) || poweroff_delay <= 0)
570 return;
571 DELAY(poweroff_delay * 1000);
572}
573
574/*
575 * Some system processes (e.g. syncer) need to be stopped at appropriate
576 * points in their main loops prior to a system shutdown, so that they
577 * won't interfere with the shutdown process (e.g. by holding a disk buf
578 * to cause sync to fail). For each of these system processes, register
579 * shutdown_kproc() as a handler for one of shutdown events.
580 */
581static int kproc_shutdown_wait = 60;
582SYSCTL_INT(_kern_shutdown, OID_AUTO, kproc_shutdown_wait, CTLFLAG_RW,
583 &kproc_shutdown_wait, 0, "");
584
585void
586shutdown_kproc(void *arg, int howto)
587{
588 struct proc *p;
589 int error;
590
591 if (panicstr)
592 return;
593
594 p = (struct proc *)arg;
595 printf("Waiting (max %d seconds) for system process `%s' to stop...",
596 kproc_shutdown_wait, p->p_comm);
597 error = suspend_kproc(p, kproc_shutdown_wait * hz);
598
599 if (error == EWOULDBLOCK)
600 printf("timed out\n");
601 else
602 printf("stopped\n");
603}
51#include <sys/buf.h>
52#include <sys/reboot.h>
53#include <sys/proc.h>
54#include <sys/vnode.h>
55#include <sys/kernel.h>
56#include <sys/kthread.h>
57#include <sys/mount.h>
58#include <sys/queue.h>
59#include <sys/sysctl.h>
60#include <sys/conf.h>
61#include <sys/sysproto.h>
62#include <sys/cons.h>
63
64#include <machine/pcb.h>
65#include <machine/clock.h>
66#include <machine/md_var.h>
67#include <machine/smp.h> /* smp_active, cpuid */
68
69#include <sys/signalvar.h>
70
71#ifndef PANIC_REBOOT_WAIT_TIME
72#define PANIC_REBOOT_WAIT_TIME 15 /* default to 15 seconds */
73#endif
74
75/*
76 * Note that stdarg.h and the ANSI style va_start macro is used for both
77 * ANSI and traditional C compilers.
78 */
79#include <machine/stdarg.h>
80
81#ifdef DDB
82#ifdef DDB_UNATTENDED
83int debugger_on_panic = 0;
84#else
85int debugger_on_panic = 1;
86#endif
87SYSCTL_INT(_debug, OID_AUTO, debugger_on_panic, CTLFLAG_RW,
88 &debugger_on_panic, 0, "Run debugger on kernel panic");
89#endif
90
91SYSCTL_NODE(_kern, OID_AUTO, shutdown, CTLFLAG_RW, 0, "Shutdown environment");
92
93#ifdef HW_WDOG
94/*
95 * If there is a hardware watchdog, point this at the function needed to
96 * hold it off.
97 * It's needed when the kernel needs to do some lengthy operations.
98 * e.g. in wd.c when dumping core.. It's most annoying to have
99 * your precious core-dump only half written because the wdog kicked in.
100 */
101watchdog_tickle_fn wdog_tickler = NULL;
102#endif /* HW_WDOG */
103
104/*
105 * Variable panicstr contains argument to first call to panic; used as flag
106 * to indicate that the kernel has already called panic.
107 */
108const char *panicstr;
109
110static void boot __P((int)) __dead2;
111static void dumpsys __P((void));
112static int setdumpdev __P((dev_t dev));
113static void poweroff_wait __P((void *, int));
114static void print_uptime __P((void));
115static void shutdown_halt __P((void *junk, int howto));
116static void shutdown_panic __P((void *junk, int howto));
117static void shutdown_reset __P((void *junk, int howto));
118
119/* register various local shutdown events */
120static void
121shutdown_conf(void *unused)
122{
123 EVENTHANDLER_REGISTER(shutdown_final, poweroff_wait, NULL, SHUTDOWN_PRI_FIRST);
124 EVENTHANDLER_REGISTER(shutdown_final, shutdown_halt, NULL, SHUTDOWN_PRI_LAST + 100);
125 EVENTHANDLER_REGISTER(shutdown_final, shutdown_panic, NULL, SHUTDOWN_PRI_LAST + 100);
126 EVENTHANDLER_REGISTER(shutdown_final, shutdown_reset, NULL, SHUTDOWN_PRI_LAST + 200);
127}
128
129SYSINIT(shutdown_conf, SI_SUB_INTRINSIC, SI_ORDER_ANY, shutdown_conf, NULL)
130
131/* ARGSUSED */
132
133/*
134 * The system call that results in a reboot
135 */
136int
137reboot(p, uap)
138 struct proc *p;
139 struct reboot_args *uap;
140{
141 int error;
142
143 if ((error = suser(p)))
144 return (error);
145
146 boot(uap->opt);
147 return (0);
148}
149
150/*
151 * Called by events that want to shut down.. e.g <CTL><ALT><DEL> on a PC
152 */
153void
154shutdown_nice()
155{
156 /* Send a signal to init(8) and have it shutdown the world */
157 if (initproc != NULL) {
158 psignal(initproc, SIGINT);
159 } else {
160 /* No init(8) running, so simply reboot */
161 boot(RB_NOSYNC);
162 }
163 return;
164}
165static int waittime = -1;
166static struct pcb dumppcb;
167
168static void
169print_uptime()
170{
171 int f;
172 struct timespec ts;
173
174 getnanouptime(&ts);
175 printf("Uptime: ");
176 f = 0;
177 if (ts.tv_sec >= 86400) {
178 printf("%ldd", ts.tv_sec / 86400);
179 ts.tv_sec %= 86400;
180 f = 1;
181 }
182 if (f || ts.tv_sec >= 3600) {
183 printf("%ldh", ts.tv_sec / 3600);
184 ts.tv_sec %= 3600;
185 f = 1;
186 }
187 if (f || ts.tv_sec >= 60) {
188 printf("%ldm", ts.tv_sec / 60);
189 ts.tv_sec %= 60;
190 f = 1;
191 }
192 printf("%lds\n", ts.tv_sec);
193}
194
195/*
196 * Go through the rigmarole of shutting down..
197 * this used to be in machdep.c but I'll be dammned if I could see
198 * anything machine dependant in it.
199 */
200static void
201boot(howto)
202 int howto;
203{
204
205#ifdef SMP
206 if (smp_active) {
207 printf("boot() called on cpu#%d\n", cpuid);
208 }
209#endif
210 /*
211 * Do any callouts that should be done BEFORE syncing the filesystems.
212 */
213 EVENTHANDLER_INVOKE(shutdown_pre_sync, howto);
214
215 /*
216 * Now sync filesystems
217 */
218 if (!cold && (howto & RB_NOSYNC) == 0 && waittime < 0) {
219 register struct buf *bp;
220 int iter, nbusy;
221
222 waittime = 0;
223 printf("\nsyncing disks... ");
224
225 sync(&proc0, NULL);
226
227 /*
228 * With soft updates, some buffers that are
229 * written will be remarked as dirty until other
230 * buffers are written.
231 */
232 for (iter = 0; iter < 20; iter++) {
233 nbusy = 0;
234 for (bp = &buf[nbuf]; --bp >= buf; ) {
235 if ((bp->b_flags & B_INVAL) == 0 &&
236 BUF_REFCNT(bp) > 0) {
237 nbusy++;
238 } else if ((bp->b_flags & (B_DELWRI | B_INVAL))
239 == B_DELWRI) {
240 /* bawrite(bp);*/
241 nbusy++;
242 }
243 }
244 if (nbusy == 0)
245 break;
246 printf("%d ", nbusy);
247 sync(&proc0, NULL);
248 DELAY(50000 * iter);
249 }
250 printf("\n");
251 /*
252 * Count only busy local buffers to prevent forcing
253 * a fsck if we're just a client of a wedged NFS server
254 */
255 nbusy = 0;
256 for (bp = &buf[nbuf]; --bp >= buf; ) {
257 if (((bp->b_flags&B_INVAL) == 0 && BUF_REFCNT(bp)) ||
258 ((bp->b_flags & (B_DELWRI|B_INVAL)) == B_DELWRI)) {
259 if (bp->b_dev == NODEV) {
260 TAILQ_REMOVE(&mountlist,
261 bp->b_vp->v_mount, mnt_list);
262 continue;
263 }
264 nbusy++;
265#if defined(SHOW_BUSYBUFS) || defined(DIAGNOSTIC)
266 printf(
267 "%d: dev:%s, flags:%08lx, blkno:%ld, lblkno:%ld\n",
268 nbusy, devtoname(bp->b_dev),
269 bp->b_flags, (long)bp->b_blkno,
270 (long)bp->b_lblkno);
271#endif
272 }
273 }
274 if (nbusy) {
275 /*
276 * Failed to sync all blocks. Indicate this and don't
277 * unmount filesystems (thus forcing an fsck on reboot).
278 */
279 printf("giving up on %d buffers\n", nbusy);
280 DELAY(5000000); /* 5 seconds */
281 } else {
282 printf("done\n");
283 /*
284 * Unmount filesystems
285 */
286 if (panicstr == 0)
287 vfs_unmountall();
288 }
289 DELAY(100000); /* wait for console output to finish */
290 }
291
292 print_uptime();
293
294 /*
295 * Ok, now do things that assume all filesystem activity has
296 * been completed.
297 */
298 EVENTHANDLER_INVOKE(shutdown_post_sync, howto);
299 splhigh();
300 if ((howto & (RB_HALT|RB_DUMP)) == RB_DUMP && !cold) {
301 savectx(&dumppcb);
302#ifdef __i386__
303 dumppcb.pcb_cr3 = rcr3();
304#endif
305 dumpsys();
306 }
307
308 /* Now that we're going to really halt the system... */
309 EVENTHANDLER_INVOKE(shutdown_final, howto);
310
311 for(;;) ; /* safety against shutdown_reset not working */
312 /* NOTREACHED */
313}
314
315/*
316 * If the shutdown was a clean halt, behave accordingly.
317 */
318static void
319shutdown_halt(void *junk, int howto)
320{
321 if (howto & RB_HALT) {
322 printf("\n");
323 printf("The operating system has halted.\n");
324 printf("Please press any key to reboot.\n\n");
325 switch (cngetc()) {
326 case -1: /* No console, just die */
327 cpu_halt();
328 /* NOTREACHED */
329 default:
330 howto &= ~RB_HALT;
331 break;
332 }
333 }
334}
335
336/*
337 * Check to see if the system paniced, pause and then reboot
338 * according to the specified delay.
339 */
340static void
341shutdown_panic(void *junk, int howto)
342{
343 int loop;
344
345 if (howto & RB_DUMP) {
346 if (PANIC_REBOOT_WAIT_TIME != 0) {
347 if (PANIC_REBOOT_WAIT_TIME != -1) {
348 printf("Automatic reboot in %d seconds - "
349 "press a key on the console to abort\n",
350 PANIC_REBOOT_WAIT_TIME);
351 for (loop = PANIC_REBOOT_WAIT_TIME * 10;
352 loop > 0; --loop) {
353 DELAY(1000 * 100); /* 1/10th second */
354 /* Did user type a key? */
355 if (cncheckc() != -1)
356 break;
357 }
358 if (!loop)
359 return;
360 }
361 } else { /* zero time specified - reboot NOW */
362 return;
363 }
364 printf("--> Press a key on the console to reboot <--\n");
365 cngetc();
366 }
367}
368
369/*
370 * Everything done, now reset
371 */
372static void
373shutdown_reset(void *junk, int howto)
374{
375 printf("Rebooting...\n");
376 DELAY(1000000); /* wait 1 sec for printf's to complete and be read */
377 /* cpu_boot(howto); */ /* doesn't do anything at the moment */
378 cpu_reset();
379 /* NOTREACHED */ /* assuming reset worked */
380}
381
382/*
383 * Magic number for savecore
384 *
385 * exported (symorder) and used at least by savecore(8)
386 *
387 */
388static u_long const dumpmag = 0x8fca0101UL;
389
390static int dumpsize = 0; /* also for savecore */
391
392static int dodump = 1;
393
394SYSCTL_INT(_machdep, OID_AUTO, do_dump, CTLFLAG_RW, &dodump, 0,
395 "Try to perform coredump on kernel panic");
396
397static int
398setdumpdev(dev)
399 dev_t dev;
400{
401 int psize;
402 long newdumplo;
403
404 if (dev == NODEV) {
405 dumpdev = dev;
406 return (0);
407 }
408 if (devsw(dev) == NULL)
409 return (ENXIO); /* XXX is this right? */
410 if (devsw(dev)->d_psize == NULL)
411 return (ENXIO); /* XXX should be ENODEV ? */
412 psize = devsw(dev)->d_psize(dev);
413 if (psize == -1)
414 return (ENXIO); /* XXX should be ENODEV ? */
415 /*
416 * XXX should clean up checking in dumpsys() to be more like this.
417 */
418 newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE;
419 if (newdumplo < 0)
420 return (ENOSPC);
421 dumpdev = dev;
422 dumplo = newdumplo;
423 return (0);
424}
425
426
427/* ARGSUSED */
428static void dump_conf __P((void *dummy));
429static void
430dump_conf(dummy)
431 void *dummy;
432{
433 if (setdumpdev(dumpdev) != 0)
434 dumpdev = NODEV;
435}
436
437SYSINIT(dump_conf, SI_SUB_DUMP_CONF, SI_ORDER_FIRST, dump_conf, NULL)
438
439static int
440sysctl_kern_dumpdev SYSCTL_HANDLER_ARGS
441{
442 int error;
443 udev_t ndumpdev;
444
445 ndumpdev = dev2udev(dumpdev);
446 error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req);
447 if (error == 0 && req->newptr != NULL)
448 error = setdumpdev(udev2dev(ndumpdev, 0));
449 return (error);
450}
451
452SYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW,
453 0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", "");
454
455/*
456 * Doadump comes here after turning off memory management and
457 * getting on the dump stack, either when called above, or by
458 * the auto-restart code.
459 */
460static void
461dumpsys(void)
462{
463 int error;
464 static int dumping;
465
466 if (dumping++) {
467 printf("Dump already in progress, bailing...\n");
468 return;
469 }
470 if (!dodump)
471 return;
472 if (dumpdev == NODEV)
473 return;
474 if (!(devsw(dumpdev)))
475 return;
476 if (!(devsw(dumpdev)->d_dump))
477 return;
478 dumpsize = Maxmem;
479 printf("\ndumping to dev %s, offset %ld\n", devtoname(dumpdev), dumplo);
480 printf("dump ");
481 error = (*devsw(dumpdev)->d_dump)(dumpdev);
482 if (error == 0) {
483 printf("succeeded\n");
484 return;
485 }
486 printf("failed, reason: ");
487 switch (error) {
488 case ENODEV:
489 printf("device doesn't support a dump routine\n");
490 break;
491
492 case ENXIO:
493 printf("device bad\n");
494 break;
495
496 case EFAULT:
497 printf("device not ready\n");
498 break;
499
500 case EINVAL:
501 printf("area improper\n");
502 break;
503
504 case EIO:
505 printf("i/o error\n");
506 break;
507
508 case EINTR:
509 printf("aborted from console\n");
510 break;
511
512 default:
513 printf("unknown, error = %d\n", error);
514 break;
515 }
516}
517
518/*
519 * Panic is called on unresolvable fatal errors. It prints "panic: mesg",
520 * and then reboots. If we are called twice, then we avoid trying to sync
521 * the disks as this often leads to recursive panics.
522 */
523void
524panic(const char *fmt, ...)
525{
526 int bootopt;
527 va_list ap;
528 static char buf[256];
529
530 bootopt = RB_AUTOBOOT | RB_DUMP;
531 if (panicstr)
532 bootopt |= RB_NOSYNC;
533 else
534 panicstr = fmt;
535
536 va_start(ap, fmt);
537 (void)vsnprintf(buf, sizeof(buf), fmt, ap);
538 if (panicstr == fmt)
539 panicstr = buf;
540 va_end(ap);
541 printf("panic: %s\n", buf);
542#ifdef SMP
543 /* three seperate prints in case of an unmapped page and trap */
544 printf("mp_lock = %08x; ", mp_lock);
545 printf("cpuid = %d; ", cpuid);
546 printf("lapic.id = %08x\n", lapic.id);
547#endif
548
549#if defined(DDB)
550 if (debugger_on_panic)
551 Debugger ("panic");
552#endif
553 boot(bootopt);
554}
555
556/*
557 * Support for poweroff delay.
558 */
559#ifndef POWEROFF_DELAY
560# define POWEROFF_DELAY 5000
561#endif
562static int poweroff_delay = POWEROFF_DELAY;
563
564SYSCTL_INT(_kern_shutdown, OID_AUTO, poweroff_delay, CTLFLAG_RW,
565 &poweroff_delay, 0, "");
566
567static void
568poweroff_wait(void *junk, int howto)
569{
570 if(!(howto & RB_POWEROFF) || poweroff_delay <= 0)
571 return;
572 DELAY(poweroff_delay * 1000);
573}
574
575/*
576 * Some system processes (e.g. syncer) need to be stopped at appropriate
577 * points in their main loops prior to a system shutdown, so that they
578 * won't interfere with the shutdown process (e.g. by holding a disk buf
579 * to cause sync to fail). For each of these system processes, register
580 * shutdown_kproc() as a handler for one of shutdown events.
581 */
582static int kproc_shutdown_wait = 60;
583SYSCTL_INT(_kern_shutdown, OID_AUTO, kproc_shutdown_wait, CTLFLAG_RW,
584 &kproc_shutdown_wait, 0, "");
585
586void
587shutdown_kproc(void *arg, int howto)
588{
589 struct proc *p;
590 int error;
591
592 if (panicstr)
593 return;
594
595 p = (struct proc *)arg;
596 printf("Waiting (max %d seconds) for system process `%s' to stop...",
597 kproc_shutdown_wait, p->p_comm);
598 error = suspend_kproc(p, kproc_shutdown_wait * hz);
599
600 if (error == EWOULDBLOCK)
601 printf("timed out\n");
602 else
603 printf("stopped\n");
604}