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$
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/buf.h>
50 #include <sys/reboot.h>
51 #include <sys/proc.h>
52 #include <sys/vnode.h>
53 #include <sys/malloc.h>
54 #include <sys/kernel.h>
55 #include <sys/mount.h>
56 #include <sys/queue.h>
57 #include <sys/sysctl.h>
58 #include <sys/conf.h>
59 #include <sys/sysproto.h>
60
61 #include <machine/pcb.h>
62 #include <machine/clock.h>
63 #include <machine/cons.h>
64 #include <machine/md_var.h>
65 #ifdef SMP
66 #include <machine/smp.h> /* smp_active, cpuid */
67 #endif
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
83 int debugger_on_panic = 0;
84 #else
85 int debugger_on_panic = 1;
86 #endif
87 SYSCTL_INT(_debug, OID_AUTO, debugger_on_panic, CTLFLAG_RW,
88 &debugger_on_panic, 0, "");
89 #endif
90
91 #ifdef HW_WDOG
92 /*
93 * If there is a hardware watchdog, point this at the function needed to
94 * hold it off.
95 * It's needed when the kernel needs to do some lengthy operations.
96 * e.g. in wd.c when dumping core.. It's most annoying to have
97 * your precious core-dump only half written because the wdog kicked in.
98 */
99 watchdog_tickle_fn wdog_tickler = NULL;
100 #endif /* HW_WDOG */
101
102 /*
103 * Variable panicstr contains argument to first call to panic; used as flag
104 * to indicate that the kernel has already called panic.
105 */
106 const char *panicstr;
107
108 /*
109 * callout list for things to do a shutdown
110 */
111 typedef struct shutdown_list_element {
112 LIST_ENTRY(shutdown_list_element) links;
113 bootlist_fn function;
114 void *arg;
115 int priority;
116 } *sle_p;
117
118 /*
119 * There are three shutdown lists. Some things need to be shut down
120 * earlier than others.
121 */
122 LIST_HEAD(shutdown_list, shutdown_list_element);
123
124 static struct shutdown_list shutdown_lists[SHUTDOWN_FINAL + 1];
125
126 static void boot __P((int)) __dead2;
127 static void dumpsys __P((void));
128 static void print_uptime __P((void));
129
130 #ifndef _SYS_SYSPROTO_H_
131 struct reboot_args {
132 int opt;
133 };
134 #endif
135 /* ARGSUSED */
136
137 /*
138 * The system call that results in a reboot
139 */
140 int
141 reboot(p, uap)
142 struct proc *p;
143 struct reboot_args *uap;
144 {
145 int error;
146
147 if ((error = suser(p->p_ucred, &p->p_acflag)))
148 return (error);
149
150 boot(uap->opt);
151 return (0);
152 }
153
154 /*
155 * Called by events that want to shut down.. e.g <CTL><ALT><DEL> on a PC
156 */
157 void
158 shutdown_nice()
159 {
160 /* Send a signal to init(8) and have it shutdown the world */
161 if (initproc != NULL) {
162 psignal(initproc, SIGINT);
163 } else {
164 /* No init(8) running, so simply reboot */
165 boot(RB_NOSYNC);
166 }
167 return;
168 }
169 static int waittime = -1;
170 static struct pcb dumppcb;
171
172 static void
173 print_uptime()
174 {
175 int f;
176 struct timespec ts;
177
178 getnanouptime(&ts);
179 printf("Uptime: ");
180 f = 0;
181 if (ts.tv_sec >= 86400) {
182 printf("%ldd", ts.tv_sec / 86400);
183 ts.tv_sec %= 86400;
184 f = 1;
185 }
186 if (f || ts.tv_sec >= 3600) {
187 printf("%ldh", ts.tv_sec / 3600);
188 ts.tv_sec %= 3600;
189 f = 1;
190 }
191 if (f || ts.tv_sec >= 60) {
192 printf("%ldm", ts.tv_sec / 60);
193 ts.tv_sec %= 60;
194 f = 1;
195 }
196 printf("%lds\n", ts.tv_sec);
197 }
198
199 /*
200 * Go through the rigmarole of shutting down..
201 * this used to be in machdep.c but I'll be dammned if I could see
202 * anything machine dependant in it.
203 */
204 static void
205 boot(howto)
206 int howto;
207 {
208 sle_p ep;
209
210 #ifdef SMP
211 if (smp_active) {
212 printf("boot() called on cpu#%d\n", cpuid);
213 }
214 #endif
215 /*
216 * Do any callouts that should be done BEFORE syncing the filesystems.
217 */
218 LIST_FOREACH(ep, &shutdown_lists[SHUTDOWN_PRE_SYNC], links)
219 (*ep->function)(howto, ep->arg);
220
221 /*
222 * Now sync filesystems
223 */
224 if (!cold && (howto & RB_NOSYNC) == 0 && waittime < 0) {
225 register struct buf *bp;
226 int iter, nbusy;
227
228 waittime = 0;
229 printf("\nsyncing disks... ");
230
231 sync(&proc0, NULL);
232
233 /*
234 * With soft updates, some buffers that are
235 * written will be remarked as dirty until other
236 * buffers are written.
237 */
238 for (iter = 0; iter < 20; iter++) {
239 nbusy = 0;
240 for (bp = &buf[nbuf]; --bp >= buf; ) {
241 if ((bp->b_flags & (B_BUSY | B_INVAL))
242 == B_BUSY) {
243 nbusy++;
244 } else if ((bp->b_flags & (B_DELWRI | B_INVAL))
245 == B_DELWRI) {
246 /* bawrite(bp);*/
247 nbusy++;
248 }
249 }
250 if (nbusy == 0)
251 break;
252 printf("%d ", nbusy);
253 sync(&proc0, NULL);
254 DELAY(50000 * iter);
255 }
256 /*
257 * Count only busy local buffers to prevent forcing
258 * a fsck if we're just a client of a wedged NFS server
259 */
260 nbusy = 0;
261 for (bp = &buf[nbuf]; --bp >= buf; ) {
262 if (((bp->b_flags & (B_BUSY | B_INVAL)) == B_BUSY)
263 ||((bp->b_flags & (B_DELWRI | B_INVAL))== B_DELWRI))
264 if(bp->b_dev == NODEV)
265 CIRCLEQ_REMOVE(&mountlist, bp->b_vp->v_mount, mnt_list);
266 else
267 nbusy++;
268
269
270 }
271 if (nbusy) {
272 /*
273 * Failed to sync all blocks. Indicate this and don't
274 * unmount filesystems (thus forcing an fsck on reboot).
275 */
276 printf("giving up\n");
277 #ifdef SHOW_BUSYBUFS
278 nbusy = 0;
279 for (bp = &buf[nbuf]; --bp >= buf; ) {
280 if ((bp->b_flags & (B_BUSY | B_INVAL))
281 == B_BUSY) {
282 nbusy++;
283 printf(
284 "%d: dev:%08lx, flags:%08lx, blkno:%ld, lblkno:%ld\n",
285 nbusy, (u_long)bp->b_dev,
286 bp->b_flags, (long)bp->b_blkno,
287 (long)bp->b_lblkno);
288 }
289 }
290 DELAY(5000000); /* 5 seconds */
291 #endif
292 } else {
293 printf("done\n");
294 /*
295 * Unmount filesystems
296 */
297 if (panicstr == 0)
298 vfs_unmountall();
299 }
300 DELAY(100000); /* wait for console output to finish */
301 }
302
303 print_uptime();
304
305 /*
306 * Ok, now do things that assume all filesystem activity has
307 * been completed.
308 */
309 LIST_FOREACH(ep, &shutdown_lists[SHUTDOWN_POST_SYNC], links)
310 (*ep->function)(howto, ep->arg);
311 splhigh();
312 if ((howto & (RB_HALT|RB_DUMP)) == RB_DUMP && !cold) {
313 savectx(&dumppcb);
314 #ifdef __i386__
315 dumppcb.pcb_cr3 = rcr3();
316 #endif
317 dumpsys();
318 }
319
320 /* Now that we're going to really halt the system... */
321 LIST_FOREACH(ep, &shutdown_lists[SHUTDOWN_FINAL], links)
322 (*ep->function)(howto, ep->arg);
323
324 if (howto & RB_HALT) {
325 printf("\n");
326 printf("The operating system has halted.\n");
327 printf("Please press any key to reboot.\n\n");
328 switch (cngetc()) {
329 case -1: /* No console, just die */
330 cpu_halt();
331 /* NOTREACHED */
332 default:
333 howto &= ~RB_HALT;
334 break;
335 }
336 } else if (howto & RB_DUMP) {
337 /* System Paniced */
338
339 if (PANIC_REBOOT_WAIT_TIME != 0) {
340 if (PANIC_REBOOT_WAIT_TIME != -1) {
341 int loop;
342 printf("Automatic reboot in %d seconds - "
343 "press a key on the console to abort\n",
344 PANIC_REBOOT_WAIT_TIME);
345 for (loop = PANIC_REBOOT_WAIT_TIME * 10;
346 loop > 0; --loop) {
347 DELAY(1000 * 100); /* 1/10th second */
348 /* Did user type a key? */
349 if (cncheckc() != -1)
350 break;
351 }
352 if (!loop)
353 goto die;
354 }
355 } else { /* zero time specified - reboot NOW */
356 goto die;
357 }
358 printf("--> Press a key on the console to reboot <--\n");
359 cngetc();
360 }
361 die:
362 printf("Rebooting...\n");
363 DELAY(1000000); /* wait 1 sec for printf's to complete and be read */
364 /* cpu_boot(howto); */ /* doesn't do anything at the moment */
365 cpu_reset();
366 for(;;) ;
367 /* NOTREACHED */
368 }
369
370 /*
371 * Magic number for savecore
372 *
373 * exported (symorder) and used at least by savecore(8)
374 *
375 */
376 static u_long const dumpmag = 0x8fca0101UL;
377
378 static int dumpsize = 0; /* also for savecore */
379
380 static int dodump = 1;
381 SYSCTL_INT(_machdep, OID_AUTO, do_dump, CTLFLAG_RW, &dodump, 0, "");
382
383 /* ARGSUSED */
384 static void dump_conf __P((void *dummy));
385 static void
386 dump_conf(dummy)
387 void *dummy;
388 {
389 cpu_dumpconf();
390 }
391 SYSINIT(dump_conf, SI_SUB_DUMP_CONF, SI_ORDER_FIRST, dump_conf, NULL)
392
393 /*
394 * Doadump comes here after turning off memory management and
395 * getting on the dump stack, either when called above, or by
396 * the auto-restart code.
397 */
398 static void
399 dumpsys(void)
400 {
401
402 if (!dodump)
403 return;
404 if (dumpdev == NODEV)
405 return;
406 if (!(bdevsw[major(dumpdev)]))
407 return;
408 if (!(bdevsw[major(dumpdev)]->d_dump))
409 return;
410 dumpsize = Maxmem;
411 printf("\ndumping to dev %lx, offset %ld\n", (u_long)dumpdev, dumplo);
412 printf("dump ");
413 switch ((*bdevsw[major(dumpdev)]->d_dump)(dumpdev)) {
414
415 case ENXIO:
416 printf("device bad\n");
417 break;
418
419 case EFAULT:
420 printf("device not ready\n");
421 break;
422
423 case EINVAL:
424 printf("area improper\n");
425 break;
426
427 case EIO:
428 printf("i/o error\n");
429 break;
430
431 case EINTR:
432 printf("aborted from console\n");
433 break;
434
435 default:
436 printf("succeeded\n");
437 break;
438 }
439 }
440
441 /*
442 * Panic is called on unresolvable fatal errors. It prints "panic: mesg",
443 * and then reboots. If we are called twice, then we avoid trying to sync
444 * the disks as this often leads to recursive panics.
445 */
446 void
447 panic(const char *fmt, ...)
448 {
449 int bootopt;
450 va_list ap;
451 static char buf[256];
452
453 bootopt = RB_AUTOBOOT | RB_DUMP;
454 if (panicstr)
455 bootopt |= RB_NOSYNC;
456 else
457 panicstr = fmt;
458
459 va_start(ap, fmt);
460 (void)vsnprintf(buf, sizeof(buf), fmt, ap);
461 if (panicstr == fmt)
462 panicstr = buf;
463 va_end(ap);
464 printf("panic: %s\n", buf);
465 #ifdef SMP
466 /* three seperate prints in case of an unmapped page and trap */
467 printf("mp_lock = %08x; ", mp_lock);
468 printf("cpuid = %d; ", cpuid);
469 printf("lapic.id = %08x\n", lapic.id);
470 #endif
471
472 #if defined(DDB)
473 if (debugger_on_panic)
474 Debugger ("panic");
475 #endif
476 boot(bootopt);
477 }
478
479 /*
480 * Three routines to handle adding/deleting items on the
481 * shutdown callout lists
482 *
483 * at_shutdown():
484 * Take the arguments given and put them onto the shutdown callout list.
485 * However first make sure that it's not already there.
486 * returns 0 on success.
487 */
488 int
489 at_shutdown(bootlist_fn function, void *arg, int queue)
490 {
491 return(at_shutdown_pri(function, arg, queue, SHUTDOWN_PRI_DEFAULT));
492 }
493
494 /*
495 * at_shutdown_pri():
496 * Take the arguments given and put them onto the shutdown callout list
497 * with the given execution priority.
498 * returns 0 on success.
499 */
500 int
501 at_shutdown_pri(bootlist_fn function, void *arg, int queue, int pri)
502 {
503 sle_p ep, ip;
504
505 if (queue < SHUTDOWN_PRE_SYNC
506 || queue > SHUTDOWN_FINAL) {
507 printf("at_shutdown: bad exit callout queue %d specified\n",
508 queue);
509 return (EINVAL);
510 }
511 if (rm_at_shutdown(function, arg))
512 printf("at_shutdown: exit callout entry was already present\n");
513 ep = malloc(sizeof(*ep), M_TEMP, M_NOWAIT);
514 if (ep == NULL)
515 return (ENOMEM);
516 ep->function = function;
517 ep->arg = arg;
518 ep->priority = pri;
519
520 /* Sort into list of items on this queue */
521 ip = LIST_FIRST(&shutdown_lists[queue]);
522 if (ip == NULL) {
523 LIST_INSERT_HEAD(&shutdown_lists[queue], ep, links);
524 } else {
525 for (; LIST_NEXT(ip, links) != NULL; ip = LIST_NEXT(ip, links)) {
526 if (ep->priority < ip->priority) {
527 LIST_INSERT_BEFORE(ip, ep, links);
528 ep = NULL;
529 break;
530 }
531 }
532 if (ep != NULL)
533 LIST_INSERT_AFTER(ip, ep, links);
534 }
535 return (0);
536 }
537
538 /*
539 * Scan the exit callout lists for the given items and remove them.
540 * Returns the number of items removed.
541 */
542 int
543 rm_at_shutdown(bootlist_fn function, void *arg)
544 {
545 sle_p ep;
546 int count;
547 int queue;
548
549 count = 0;
550 for (queue = SHUTDOWN_PRE_SYNC; queue < SHUTDOWN_FINAL; queue++) {
551 LIST_FOREACH(ep, &shutdown_lists[queue], links) {
552 if ((ep->function == function) && (ep->arg == arg)) {
553 LIST_REMOVE(ep, links);
554 free(ep, M_TEMP);
555 count++;
556 }
557 }
558 }
559 return (count);
560 }
Cache object: 1f27576b6be01f142143cb86e1c49fa8
|