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 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 85 SYSCTL_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 */ 94 const char *panicstr; 95 96 /* 97 * callout list for things to do a shutdown 98 */ 99 typedef 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 */ 109 static sle_p shutdown_list1; 110 static sle_p shutdown_list2; 111 112 113 static void dumpsys(void); 114 115 #ifndef _SYS_SYSPROTO_H_ 116 struct reboot_args { 117 int opt; 118 }; 119 #endif 120 /* ARGSUSED */ 121 122 /* 123 * The system call that results in a reboot 124 */ 125 int 126 reboot(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 */ 143 void 144 shutdown_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 } 155 static int waittime = -1; 156 static 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 */ 163 void 164 boot(howto) 165 int howto; 166 { 167 sle_p ep; 168 169 ep = shutdown_list1; 170 while (ep) { 171 shutdown_list1 = ep->next; 172 (*ep->function)(howto, ep->arg); 173 ep = ep->next; 174 } 175 if (!cold && (howto & RB_NOSYNC) == 0 && waittime < 0) { 176 register struct buf *bp; 177 int iter, nbusy; 178 179 waittime = 0; 180 printf("\nsyncing disks... "); 181 182 sync(&proc0, NULL, NULL); 183 184 for (iter = 0; iter < 20; iter++) { 185 nbusy = 0; 186 for (bp = &buf[nbuf]; --bp >= buf; ) { 187 if ((bp->b_flags & (B_BUSY | B_INVAL)) == B_BUSY) { 188 nbusy++; 189 } 190 } 191 if (nbusy == 0) 192 break; 193 printf("%d ", nbusy); 194 DELAY(40000 * iter); 195 } 196 if (nbusy) { 197 /* 198 * Failed to sync all blocks. Indicate this and don't 199 * unmount filesystems (thus forcing an fsck on reboot). 200 */ 201 printf("giving up\n"); 202 #ifdef SHOW_BUSYBUFS 203 nbusy = 0; 204 for (bp = &buf[nbuf]; --bp >= buf; ) { 205 if ((bp->b_flags & (B_BUSY | B_INVAL)) == B_BUSY) { 206 nbusy++; 207 printf("%d: dev:%08x, flags:%08x, blkno:%d, lblkno:%d\n", nbusy, bp->b_dev, bp->b_flags, bp->b_blkno, bp->b_lblkno); 208 } 209 } 210 DELAY(5000000); /* 5 seconds */ 211 #endif 212 } else { 213 printf("done\n"); 214 /* 215 * Unmount filesystems 216 */ 217 if (panicstr == 0) 218 vfs_unmountall(); 219 } 220 DELAY(100000); /* wait for console output to finish */ 221 } 222 ep = shutdown_list2; 223 while (ep) { 224 shutdown_list2 = ep->next; 225 (*ep->function)(howto, ep->arg); 226 ep = ep->next; 227 } 228 splhigh(); 229 if (howto & RB_HALT) { 230 printf("\n"); 231 printf("The operating system has halted.\n"); 232 printf("Please press any key to reboot.\n\n"); 233 switch (cngetc()) { 234 case -1: /* No console, just die */ 235 cpu_halt(); 236 /* NOTREACHED */ 237 default: 238 break; 239 } 240 } else { 241 if (howto & RB_DUMP) { 242 if (!cold) { 243 savectx(&dumppcb); 244 dumppcb.pcb_cr3 = rcr3(); 245 dumpsys(); 246 } 247 248 if (PANIC_REBOOT_WAIT_TIME != 0) { 249 if (PANIC_REBOOT_WAIT_TIME != -1) { 250 int loop; 251 printf("Automatic reboot in %d seconds - press a key on the console to abort\n", 252 PANIC_REBOOT_WAIT_TIME); 253 for (loop = PANIC_REBOOT_WAIT_TIME * 10; loop > 0; --loop) { 254 DELAY(1000 * 100); /* 1/10th second */ 255 /* Did user type a key? */ 256 if (cncheckc() != -1) 257 break; 258 } 259 if (!loop) 260 goto die; 261 } 262 } else { /* zero time specified - reboot NOW */ 263 goto die; 264 } 265 printf("--> Press a key on the console to reboot <--\n"); 266 cngetc(); 267 } 268 } 269 die: 270 printf("Rebooting...\n"); 271 DELAY(1000000); /* wait 1 sec for printf's to complete and be read */ 272 /* cpu_boot(howto); */ /* doesn't do anything at the moment */ 273 cpu_reset(); 274 for(;;) ; 275 /* NOTREACHED */ 276 } 277 278 /* 279 * Magic number for savecore 280 * 281 * exported (symorder) and used at least by savecore(8) 282 * 283 */ 284 static u_long const dumpmag = 0x8fca0101UL; 285 286 static int dumpsize = 0; /* also for savecore */ 287 288 static int dodump = 1; 289 SYSCTL_INT(_machdep, OID_AUTO, do_dump, CTLFLAG_RW, &dodump, 0, ""); 290 291 /* 292 * Doadump comes here after turning off memory management and 293 * getting on the dump stack, either when called above, or by 294 * the auto-restart code. 295 */ 296 static void 297 dumpsys(void) 298 { 299 300 if (!dodump) 301 return; 302 if (dumpdev == NODEV) 303 return; 304 if ((minor(dumpdev)&07) != 1) 305 return; 306 if (!(bdevsw[major(dumpdev)])) 307 return; 308 if (!(bdevsw[major(dumpdev)]->d_dump)) 309 return; 310 dumpsize = Maxmem; 311 printf("\ndumping to dev %lx, offset %ld\n", dumpdev, dumplo); 312 printf("dump "); 313 switch ((*bdevsw[major(dumpdev)]->d_dump)(dumpdev)) { 314 315 case ENXIO: 316 printf("device bad\n"); 317 break; 318 319 case EFAULT: 320 printf("device not ready\n"); 321 break; 322 323 case EINVAL: 324 printf("area improper\n"); 325 break; 326 327 case EIO: 328 printf("i/o error\n"); 329 break; 330 331 case EINTR: 332 printf("aborted from console\n"); 333 break; 334 335 default: 336 printf("succeeded\n"); 337 break; 338 } 339 } 340 341 /* 342 * Panic is called on unresolvable fatal errors. It prints "panic: mesg", 343 * and then reboots. If we are called twice, then we avoid trying to sync 344 * the disks as this often leads to recursive panics. 345 */ 346 void 347 panic(const char *fmt, ...) 348 { 349 int bootopt; 350 va_list ap; 351 352 bootopt = RB_AUTOBOOT | RB_DUMP; 353 if (panicstr) 354 bootopt |= RB_NOSYNC; 355 else 356 panicstr = fmt; 357 358 printf("panic: "); 359 va_start(ap, fmt); 360 vprintf(fmt, ap); 361 va_end(ap); 362 printf("\n"); 363 364 #if defined(DDB) 365 if (debugger_on_panic) 366 Debugger ("panic"); 367 #endif 368 boot(bootopt); 369 } 370 371 /* 372 * Two routines to handle adding/deleting items on the 373 * shutdown callout lists 374 * 375 * at_shutdown(): 376 * Take the arguments given and put them onto the shutdown callout list. 377 * However first make sure that it's not already there. 378 * returns 0 on success. 379 */ 380 int 381 at_shutdown(bootlist_fn function, void *arg, int position) 382 { 383 sle_p ep, *epp; 384 385 switch(position) { 386 case SHUTDOWN_PRE_SYNC: 387 epp = &shutdown_list1; 388 break; 389 case SHUTDOWN_POST_SYNC: 390 epp = &shutdown_list2; 391 break; 392 default: 393 printf("bad exit callout list specified\n"); 394 return (EINVAL); 395 } 396 if (rm_at_shutdown(function, arg)) 397 printf("exit callout entry already present\n"); 398 ep = malloc(sizeof(*ep), M_TEMP, M_NOWAIT); 399 if (ep == NULL) 400 return (ENOMEM); 401 ep->next = *epp; 402 ep->function = function; 403 ep->arg = arg; 404 *epp = ep; 405 return (0); 406 } 407 408 /* 409 * Scan the exit callout lists for the given items and remove them. 410 * Returns the number of items removed. 411 */ 412 int 413 rm_at_shutdown(bootlist_fn function, void *arg) 414 { 415 sle_p *epp, ep; 416 int count; 417 418 count = 0; 419 epp = &shutdown_list1; 420 ep = *epp; 421 while (ep) { 422 if ((ep->function == function) && (ep->arg == arg)) { 423 *epp = ep->next; 424 free(ep, M_TEMP); 425 count++; 426 } else { 427 epp = &ep->next; 428 } 429 ep = *epp; 430 } 431 epp = &shutdown_list2; 432 ep = *epp; 433 while (ep) { 434 if ((ep->function == function) && (ep->arg == arg)) { 435 *epp = ep->next; 436 free(ep, M_TEMP); 437 count++; 438 } else { 439 epp = &ep->next; 440 } 441 ep = *epp; 442 } 443 return (count); 444 } 445 446