kern_shutdown.c revision 26657
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 * $Id: kern_shutdown.c,v 1.15 1997/05/24 18:35:44 fsmp Exp $ 40 */ 41 42#include "opt_ddb.h" 43 44#include <sys/param.h> 45#include <sys/systm.h> 46#include <sys/reboot.h> 47#include <sys/msgbuf.h> 48#include <sys/proc.h> 49#include <sys/vnode.h> 50#include <sys/tty.h> 51#include <sys/tprintf.h> 52#include <sys/syslog.h> 53#include <sys/malloc.h> 54#include <sys/kernel.h> 55#include <sys/mount.h> 56#include <sys/sysctl.h> 57#include <sys/conf.h> 58#include <sys/sysproto.h> 59 60#include <machine/pcb.h> 61#include <machine/clock.h> 62#include <machine/cons.h> 63#include <machine/md_var.h> 64 65#include <sys/utsname.h> 66#include <sys/signalvar.h> 67 68#ifndef PANIC_REBOOT_WAIT_TIME 69#define PANIC_REBOOT_WAIT_TIME 15 /* default to 15 seconds */ 70#endif 71 72/* 73 * Note that stdarg.h and the ANSI style va_start macro is used for both 74 * ANSI and traditional C compilers. 75 */ 76#include <machine/stdarg.h> 77 78#if defined(DDB) 79#ifdef DDB_UNATTENDED 80 static int debugger_on_panic = 0; 81#else 82 static int debugger_on_panic = 1; 83#endif 84 85SYSCTL_INT(_debug, OID_AUTO, debugger_on_panic, CTLFLAG_RW, 86 &debugger_on_panic, 0, ""); 87#endif 88 89 90/* 91 * Variable panicstr contains argument to first call to panic; used as flag 92 * to indicate that the kernel has already called panic. 93 */ 94const char *panicstr; 95 96/* 97 * callout list for things to do a shutdown 98 */ 99typedef struct shutdown_list_element { 100 struct shutdown_list_element *next; 101 bootlist_fn function; 102 void *arg; 103} *sle_p; 104 105/* 106 * there are two shutdown lists. Some things need to be shut down 107 * Earlier than others. 108 */ 109static sle_p shutdown_list1; 110static sle_p shutdown_list2; 111 112 113static void dumpsys(void); 114 115#ifndef _SYS_SYSPROTO_H_ 116struct reboot_args { 117 int opt; 118}; 119#endif 120/* ARGSUSED */ 121 122/* 123 * The system call that results in a reboot 124 */ 125int 126reboot(p, uap, retval) 127 struct proc *p; 128 struct reboot_args *uap; 129 int *retval; 130{ 131 int error; 132 133 if ((error = suser(p->p_ucred, &p->p_acflag))) 134 return (error); 135 136 boot(uap->opt); 137 return (0); 138} 139 140/* 141 * Called by events that want to shut down.. e.g <CTL><ALT><DEL> on a PC 142 */ 143void 144shutdown_nice(void) 145{ 146 /* Send a signal to init(8) and have it shutdown the world */ 147 if (initproc != NULL) { 148 psignal(initproc, SIGINT); 149 } else { 150 /* No init(8) running, so simply reboot */ 151 boot(RB_NOSYNC); 152 } 153 return; 154} 155static int waittime = -1; 156static struct pcb dumppcb; 157 158/* 159 * Go through the rigmarole of shutting down.. 160 * this used to be in machdep.c but I'll be dammned if I could see 161 * anything machine dependant in it. 162 */ 163void 164boot(howto) 165 int howto; 166{ 167 sle_p ep; 168 169#ifdef SMP 170 int c, spins; 171 172 /* don't accidently start it */ 173 if (smp_active) { 174 smp_active = 1; 175 176 spins = 100; 177 178 printf("boot() called on cpu#%d\n", cpunumber()); 179 while ((c = cpunumber()) != 0) { 180 if (spins-- < 1) { 181 printf("timeout waiting for cpu #0!\n"); 182 break; 183 } 184 printf("oops, I'm on cpu#%d, I need to be on cpu#0!\n", 185 c); 186 tsleep((caddr_t)&smp_active, PZERO, "cpu0wt", 10); 187 } 188 } 189#endif 190 ep = shutdown_list1; 191 while (ep) { 192 shutdown_list1 = ep->next; 193 (*ep->function)(howto, ep->arg); 194 ep = ep->next; 195 } 196 if (!cold && (howto & RB_NOSYNC) == 0 && waittime < 0) { 197 register struct buf *bp; 198 int iter, nbusy; 199 200 waittime = 0; 201 printf("\nsyncing disks... "); 202 203 sync(&proc0, NULL, NULL); 204 205 for (iter = 0; iter < 20; iter++) { 206 nbusy = 0; 207 for (bp = &buf[nbuf]; --bp >= buf; ) { 208 if ((bp->b_flags & (B_BUSY | B_INVAL)) == B_BUSY) { 209 nbusy++; 210 } 211 } 212 if (nbusy == 0) 213 break; 214 printf("%d ", nbusy); 215 DELAY(40000 * iter); 216 } 217 if (nbusy) { 218 /* 219 * Failed to sync all blocks. Indicate this and don't 220 * unmount filesystems (thus forcing an fsck on reboot). 221 */ 222 printf("giving up\n"); 223#ifdef SHOW_BUSYBUFS 224 nbusy = 0; 225 for (bp = &buf[nbuf]; --bp >= buf; ) { 226 if ((bp->b_flags & (B_BUSY | B_INVAL)) == B_BUSY) { 227 nbusy++; 228 printf("%d: dev:%08x, flags:%08x, blkno:%d, lblkno:%d\n", nbusy, bp->b_dev, bp->b_flags, bp->b_blkno, bp->b_lblkno); 229 } 230 } 231 DELAY(5000000); /* 5 seconds */ 232#endif 233 } else { 234 printf("done\n"); 235 /* 236 * Unmount filesystems 237 */ 238 if (panicstr == 0) 239 vfs_unmountall(); 240 } 241 DELAY(100000); /* wait for console output to finish */ 242 } 243 ep = shutdown_list2; 244 while (ep) { 245 shutdown_list2 = ep->next; 246 (*ep->function)(howto, ep->arg); 247 ep = ep->next; 248 } 249 splhigh(); 250 if (howto & RB_HALT) { 251 cpu_power_down(); 252 printf("\n"); 253 printf("The operating system has halted.\n"); 254 printf("Please press any key to reboot.\n\n"); 255 switch (cngetc()) { 256 case -1: /* No console, just die */ 257 cpu_halt(); 258 /* NOTREACHED */ 259 default: 260 break; 261 } 262 } else { 263 if (howto & RB_DUMP) { 264 if (!cold) { 265 savectx(&dumppcb); 266 dumppcb.pcb_cr3 = rcr3(); 267 dumpsys(); 268 } 269 270 if (PANIC_REBOOT_WAIT_TIME != 0) { 271 if (PANIC_REBOOT_WAIT_TIME != -1) { 272 int loop; 273 printf("Automatic reboot in %d seconds - press a key on the console to abort\n", 274 PANIC_REBOOT_WAIT_TIME); 275 for (loop = PANIC_REBOOT_WAIT_TIME * 10; loop > 0; --loop) { 276 DELAY(1000 * 100); /* 1/10th second */ 277 /* Did user type a key? */ 278 if (cncheckc() != -1) 279 break; 280 } 281 if (!loop) 282 goto die; 283 } 284 } else { /* zero time specified - reboot NOW */ 285 goto die; 286 } 287 printf("--> Press a key on the console to reboot <--\n"); 288 cngetc(); 289 } 290 } 291die: 292 printf("Rebooting...\n"); 293 DELAY(1000000); /* wait 1 sec for printf's to complete and be read */ 294 /* cpu_boot(howto); */ /* doesn't do anything at the moment */ 295 cpu_reset(); 296 for(;;) ; 297 /* NOTREACHED */ 298} 299 300/* 301 * Magic number for savecore 302 * 303 * exported (symorder) and used at least by savecore(8) 304 * 305 */ 306static u_long const dumpmag = 0x8fca0101UL; 307 308static int dumpsize = 0; /* also for savecore */ 309 310static int dodump = 1; 311SYSCTL_INT(_machdep, OID_AUTO, do_dump, CTLFLAG_RW, &dodump, 0, ""); 312 313/* 314 * Doadump comes here after turning off memory management and 315 * getting on the dump stack, either when called above, or by 316 * the auto-restart code. 317 */ 318static void 319dumpsys(void) 320{ 321 322 if (!dodump) 323 return; 324 if (dumpdev == NODEV) 325 return; 326 if ((minor(dumpdev)&07) != 1) 327 return; 328 if (!(bdevsw[major(dumpdev)])) 329 return; 330 if (!(bdevsw[major(dumpdev)]->d_dump)) 331 return; 332 dumpsize = Maxmem; 333 printf("\ndumping to dev %lx, offset %ld\n", dumpdev, dumplo); 334 printf("dump "); 335 switch ((*bdevsw[major(dumpdev)]->d_dump)(dumpdev)) { 336 337 case ENXIO: 338 printf("device bad\n"); 339 break; 340 341 case EFAULT: 342 printf("device not ready\n"); 343 break; 344 345 case EINVAL: 346 printf("area improper\n"); 347 break; 348 349 case EIO: 350 printf("i/o error\n"); 351 break; 352 353 case EINTR: 354 printf("aborted from console\n"); 355 break; 356 357 default: 358 printf("succeeded\n"); 359 break; 360 } 361} 362 363/* 364 * Panic is called on unresolvable fatal errors. It prints "panic: mesg", 365 * and then reboots. If we are called twice, then we avoid trying to sync 366 * the disks as this often leads to recursive panics. 367 */ 368void 369panic(const char *fmt, ...) 370{ 371 int bootopt; 372 va_list ap; 373 374 bootopt = RB_AUTOBOOT | RB_DUMP; 375 if (panicstr) 376 bootopt |= RB_NOSYNC; 377 else 378 panicstr = fmt; 379 380 printf("panic: "); 381 va_start(ap, fmt); 382 vprintf(fmt, ap); 383 va_end(ap); 384 printf("\n"); 385#ifdef SMP 386 printf(" cpu#%d\n", cpunumber()); 387#endif 388 389#if defined(DDB) 390 if (debugger_on_panic) 391 Debugger ("panic"); 392#endif 393 boot(bootopt); 394} 395 396/* 397 * Two routines to handle adding/deleting items on the 398 * shutdown callout lists 399 * 400 * at_shutdown(): 401 * Take the arguments given and put them onto the shutdown callout list. 402 * However first make sure that it's not already there. 403 * returns 0 on success. 404 */ 405int 406at_shutdown(bootlist_fn function, void *arg, int position) 407{ 408 sle_p ep, *epp; 409 410 switch(position) { 411 case SHUTDOWN_PRE_SYNC: 412 epp = &shutdown_list1; 413 break; 414 case SHUTDOWN_POST_SYNC: 415 epp = &shutdown_list2; 416 break; 417 default: 418 printf("bad exit callout list specified\n"); 419 return (EINVAL); 420 } 421 if (rm_at_shutdown(function, arg)) 422 printf("exit callout entry already present\n"); 423 ep = malloc(sizeof(*ep), M_TEMP, M_NOWAIT); 424 if (ep == NULL) 425 return (ENOMEM); 426 ep->next = *epp; 427 ep->function = function; 428 ep->arg = arg; 429 *epp = ep; 430 return (0); 431} 432 433/* 434 * Scan the exit callout lists for the given items and remove them. 435 * Returns the number of items removed. 436 */ 437int 438rm_at_shutdown(bootlist_fn function, void *arg) 439{ 440 sle_p *epp, ep; 441 int count; 442 443 count = 0; 444 epp = &shutdown_list1; 445 ep = *epp; 446 while (ep) { 447 if ((ep->function == function) && (ep->arg == arg)) { 448 *epp = ep->next; 449 free(ep, M_TEMP); 450 count++; 451 } else { 452 epp = &ep->next; 453 } 454 ep = *epp; 455 } 456 epp = &shutdown_list2; 457 ep = *epp; 458 while (ep) { 459 if ((ep->function == function) && (ep->arg == arg)) { 460 *epp = ep->next; 461 free(ep, M_TEMP); 462 count++; 463 } else { 464 epp = &ep->next; 465 } 466 ep = *epp; 467 } 468 return (count); 469} 470 471