kern_shutdown.c revision 108682
117658Sjulian/*- 217658Sjulian * Copyright (c) 1986, 1988, 1991, 1993 317658Sjulian * The Regents of the University of California. All rights reserved. 417658Sjulian * (c) UNIX System Laboratories, Inc. 517658Sjulian * All or some portions of this file are derived from material licensed 617658Sjulian * to the University of California by American Telephone and Telegraph 717658Sjulian * Co. or Unix System Laboratories, Inc. and are reproduced herein with 817658Sjulian * the permission of UNIX System Laboratories, Inc. 917658Sjulian * 1017658Sjulian * Redistribution and use in source and binary forms, with or without 1117658Sjulian * modification, are permitted provided that the following conditions 1217658Sjulian * are met: 1317658Sjulian * 1. Redistributions of source code must retain the above copyright 1417658Sjulian * notice, this list of conditions and the following disclaimer. 1517658Sjulian * 2. Redistributions in binary form must reproduce the above copyright 1617658Sjulian * notice, this list of conditions and the following disclaimer in the 1717658Sjulian * documentation and/or other materials provided with the distribution. 1817658Sjulian * 3. All advertising materials mentioning features or use of this software 1917658Sjulian * must display the following acknowledgement: 2017658Sjulian * This product includes software developed by the University of 2117658Sjulian * California, Berkeley and its contributors. 2217658Sjulian * 4. Neither the name of the University nor the names of its contributors 2317658Sjulian * may be used to endorse or promote products derived from this software 2417658Sjulian * without specific prior written permission. 2517658Sjulian * 2617658Sjulian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2717658Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2817658Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2917658Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3017658Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3117658Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3217658Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3317658Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3417658Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3517658Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3617658Sjulian * SUCH DAMAGE. 3717658Sjulian * 3817658Sjulian * @(#)kern_shutdown.c 8.3 (Berkeley) 1/21/94 3950477Speter * $FreeBSD: head/sys/kern/kern_shutdown.c 108682 2003-01-04 20:54:58Z phk $ 4017658Sjulian */ 4117658Sjulian 4217658Sjulian#include "opt_ddb.h" 43103647Sjhb#include "opt_ddb_trace.h" 44103647Sjhb#include "opt_ddb_unattended.h" 4533445Seivind#include "opt_hw_wdog.h" 46106024Srwatson#include "opt_mac.h" 4728976Sbde#include "opt_panic.h" 4828976Sbde#include "opt_show_busybufs.h" 4917658Sjulian 5017658Sjulian#include <sys/param.h> 5117658Sjulian#include <sys/systm.h> 5260041Sphk#include <sys/bio.h> 5331275Sbde#include <sys/buf.h> 5478767Sjhb#include <sys/conf.h> 5578767Sjhb#include <sys/cons.h> 5681688Sbde#include <sys/disklabel.h> 5778767Sjhb#include <sys/eventhandler.h> 5817658Sjulian#include <sys/kernel.h> 5955539Sluoqi#include <sys/kthread.h> 60106024Srwatson#include <sys/mac.h> 6189601Ssobomax#include <sys/malloc.h> 6221776Sbde#include <sys/mount.h> 6378767Sjhb#include <sys/proc.h> 6478767Sjhb#include <sys/reboot.h> 6578767Sjhb#include <sys/resourcevar.h> 6678767Sjhb#include <sys/smp.h> /* smp_active */ 6717658Sjulian#include <sys/sysctl.h> 6817658Sjulian#include <sys/sysproto.h> 6978767Sjhb#include <sys/vnode.h> 7017658Sjulian 7194169Sphk#include <machine/pcb.h> 7217658Sjulian#include <machine/md_var.h> 7391778Sjake#include <machine/smp.h> 7417658Sjulian 7517658Sjulian#include <sys/signalvar.h> 7682119Sjhb#ifdef DDB 7782119Sjhb#include <ddb/ddb.h> 7882119Sjhb#endif 7917658Sjulian 8017658Sjulian#ifndef PANIC_REBOOT_WAIT_TIME 8117658Sjulian#define PANIC_REBOOT_WAIT_TIME 15 /* default to 15 seconds */ 8217658Sjulian#endif 8317658Sjulian 8417658Sjulian/* 8517658Sjulian * Note that stdarg.h and the ANSI style va_start macro is used for both 8617658Sjulian * ANSI and traditional C compilers. 8717658Sjulian */ 8817658Sjulian#include <machine/stdarg.h> 8917658Sjulian 9028769Sbde#ifdef DDB 9117658Sjulian#ifdef DDB_UNATTENDED 9242135Smsmithint debugger_on_panic = 0; 9317658Sjulian#else 9442135Smsmithint debugger_on_panic = 1; 9517658Sjulian#endif 9617658SjulianSYSCTL_INT(_debug, OID_AUTO, debugger_on_panic, CTLFLAG_RW, 9746381Sbillf &debugger_on_panic, 0, "Run debugger on kernel panic"); 98103647Sjhb 99103647Sjhb#ifdef DDB_TRACE 100103647Sjhbint trace_on_panic = 1; 101103647Sjhb#else 102103647Sjhbint trace_on_panic = 0; 10317658Sjulian#endif 104103647SjhbSYSCTL_INT(_debug, OID_AUTO, trace_on_panic, CTLFLAG_RW, 105103647Sjhb &trace_on_panic, 0, "Print stack trace on kernel panic"); 106103647Sjhb#endif 10717658Sjulian 10885202Speterint sync_on_panic = 1; 10985202SpeterSYSCTL_INT(_kern, OID_AUTO, sync_on_panic, CTLFLAG_RW, 11085202Speter &sync_on_panic, 0, "Do a sync before rebooting from a panic"); 11185202Speter 11243436SmsmithSYSCTL_NODE(_kern, OID_AUTO, shutdown, CTLFLAG_RW, 0, "Shutdown environment"); 11343436Smsmith 11428000Sjulian#ifdef HW_WDOG 11517658Sjulian/* 11627997Sjulian * If there is a hardware watchdog, point this at the function needed to 11727997Sjulian * hold it off. 11827997Sjulian * It's needed when the kernel needs to do some lengthy operations. 11927997Sjulian * e.g. in wd.c when dumping core.. It's most annoying to have 12027997Sjulian * your precious core-dump only half written because the wdog kicked in. 12127997Sjulian */ 12227997Sjulianwatchdog_tickle_fn wdog_tickler = NULL; 12328000Sjulian#endif /* HW_WDOG */ 12427997Sjulian 12527997Sjulian/* 12617658Sjulian * Variable panicstr contains argument to first call to panic; used as flag 12717658Sjulian * to indicate that the kernel has already called panic. 12817658Sjulian */ 12917658Sjulianconst char *panicstr; 13017658Sjulian 13193496Sphkint dumping; /* system is dumping */ 13293496Sphkstatic struct dumperinfo dumper; /* our selected dumper */ 13394169Sphkstatic struct pcb dumppcb; /* "You Are Here" sign for dump-debuggers */ 13467093Sps 13565395Speterstatic void boot(int) __dead2; 13665395Speterstatic void poweroff_wait(void *, int); 13765395Speterstatic void shutdown_halt(void *junk, int howto); 13865395Speterstatic void shutdown_panic(void *junk, int howto); 13965395Speterstatic void shutdown_reset(void *junk, int howto); 14017658Sjulian 14150107Smsmith/* register various local shutdown events */ 14250107Smsmithstatic void 14350107Smsmithshutdown_conf(void *unused) 14450107Smsmith{ 14550107Smsmith EVENTHANDLER_REGISTER(shutdown_final, poweroff_wait, NULL, SHUTDOWN_PRI_FIRST); 14650107Smsmith EVENTHANDLER_REGISTER(shutdown_final, shutdown_halt, NULL, SHUTDOWN_PRI_LAST + 100); 14750107Smsmith EVENTHANDLER_REGISTER(shutdown_final, shutdown_panic, NULL, SHUTDOWN_PRI_LAST + 100); 14850107Smsmith EVENTHANDLER_REGISTER(shutdown_final, shutdown_reset, NULL, SHUTDOWN_PRI_LAST + 200); 14950107Smsmith} 15048868Sphk 15150107SmsmithSYSINIT(shutdown_conf, SI_SUB_INTRINSIC, SI_ORDER_ANY, shutdown_conf, NULL) 15250107Smsmith 15317658Sjulian/* 15417658Sjulian * The system call that results in a reboot 15582749Sdillon * 15682749Sdillon * MPSAFE 15717658Sjulian */ 15882749Sdillon/* ARGSUSED */ 15917658Sjulianint 16083366Sjulianreboot(struct thread *td, struct reboot_args *uap) 16117658Sjulian{ 16217658Sjulian int error; 16317658Sjulian 164106024Srwatson error = 0; 165106024Srwatson#ifdef MAC 166106024Srwatson error = mac_check_system_reboot(td->td_ucred, uap->opt); 167106024Srwatson#endif 168106024Srwatson if (error == 0) 169106024Srwatson error = suser(td); 170106024Srwatson if (error == 0) { 171106024Srwatson mtx_lock(&Giant); 17282749Sdillon boot(uap->opt); 173106024Srwatson mtx_unlock(&Giant); 174106024Srwatson } 17582749Sdillon return (error); 17617658Sjulian} 17717658Sjulian 17817658Sjulian/* 17917658Sjulian * Called by events that want to shut down.. e.g <CTL><ALT><DEL> on a PC 18017658Sjulian */ 18165268Smsmithstatic int shutdown_howto = 0; 18265268Smsmith 18317658Sjulianvoid 18465268Smsmithshutdown_nice(int howto) 18517658Sjulian{ 18665268Smsmith shutdown_howto = howto; 18765268Smsmith 18817658Sjulian /* Send a signal to init(8) and have it shutdown the world */ 18917658Sjulian if (initproc != NULL) { 19073913Sjhb PROC_LOCK(initproc); 19117658Sjulian psignal(initproc, SIGINT); 19273913Sjhb PROC_UNLOCK(initproc); 19317658Sjulian } else { 19417658Sjulian /* No init(8) running, so simply reboot */ 19517658Sjulian boot(RB_NOSYNC); 19617658Sjulian } 19717658Sjulian return; 19817658Sjulian} 19917658Sjulianstatic int waittime = -1; 20017658Sjulian 20154233Sphkstatic void 20265395Speterprint_uptime(void) 20354233Sphk{ 20454233Sphk int f; 20554233Sphk struct timespec ts; 20654233Sphk 20754233Sphk getnanouptime(&ts); 20854233Sphk printf("Uptime: "); 20954233Sphk f = 0; 21054233Sphk if (ts.tv_sec >= 86400) { 21165764Sjhb printf("%ldd", (long)ts.tv_sec / 86400); 21254233Sphk ts.tv_sec %= 86400; 21354233Sphk f = 1; 21454233Sphk } 21554233Sphk if (f || ts.tv_sec >= 3600) { 21665764Sjhb printf("%ldh", (long)ts.tv_sec / 3600); 21754233Sphk ts.tv_sec %= 3600; 21854233Sphk f = 1; 21954233Sphk } 22054233Sphk if (f || ts.tv_sec >= 60) { 22165764Sjhb printf("%ldm", (long)ts.tv_sec / 60); 22254233Sphk ts.tv_sec %= 60; 22354233Sphk f = 1; 22454233Sphk } 22565764Sjhb printf("%lds\n", (long)ts.tv_sec); 22654233Sphk} 22754233Sphk 22894169Sphkstatic void 22994169Sphkdoadump(void) 23094169Sphk{ 23194169Sphk savectx(&dumppcb); 23294169Sphk dumping++; 23394169Sphk dumpsys(&dumper); 23494169Sphk} 23594169Sphk 23617658Sjulian/* 23717658Sjulian * Go through the rigmarole of shutting down.. 23817658Sjulian * this used to be in machdep.c but I'll be dammned if I could see 23917658Sjulian * anything machine dependant in it. 24017658Sjulian */ 24131275Sbdestatic void 24265395Speterboot(int howto) 24317658Sjulian{ 24417658Sjulian 24565268Smsmith /* collect extra flags that shutdown_nice might have set */ 24665268Smsmith howto |= shutdown_howto; 24765268Smsmith 24882119Sjhb#ifdef DDB 24982119Sjhb /* We are out of the debugger now. */ 25082119Sjhb db_active = 0; 25182119Sjhb#endif 25282119Sjhb 25325164Speter#ifdef SMP 25465395Speter if (smp_active) 25570861Sjake printf("boot() called on cpu#%d\n", PCPU_GET(cpuid)); 25625164Speter#endif 25727997Sjulian /* 25827997Sjulian * Do any callouts that should be done BEFORE syncing the filesystems. 25927997Sjulian */ 26050107Smsmith EVENTHANDLER_INVOKE(shutdown_pre_sync, howto); 26127997Sjulian 26227997Sjulian /* 26327997Sjulian * Now sync filesystems 26427997Sjulian */ 26517658Sjulian if (!cold && (howto & RB_NOSYNC) == 0 && waittime < 0) { 26617658Sjulian register struct buf *bp; 26765707Sjasone int iter, nbusy, pbusy; 26865707Sjasone int subiter; 26917658Sjulian 27017658Sjulian waittime = 0; 271107036Salfred printf("\nsyncing disks, buffers remaining... "); 27217658Sjulian 27390361Sjulian sync(&thread0, NULL); 27417658Sjulian 27534266Sjulian /* 27634266Sjulian * With soft updates, some buffers that are 27734266Sjulian * written will be remarked as dirty until other 27834266Sjulian * buffers are written. 27934266Sjulian */ 28065707Sjasone for (iter = pbusy = 0; iter < 20; iter++) { 28117658Sjulian nbusy = 0; 28217658Sjulian for (bp = &buf[nbuf]; --bp >= buf; ) { 28348225Smckusick if ((bp->b_flags & B_INVAL) == 0 && 28448225Smckusick BUF_REFCNT(bp) > 0) { 28517658Sjulian nbusy++; 28634266Sjulian } else if ((bp->b_flags & (B_DELWRI | B_INVAL)) 28734266Sjulian == B_DELWRI) { 28834266Sjulian /* bawrite(bp);*/ 28934266Sjulian nbusy++; 29017658Sjulian } 29117658Sjulian } 29217658Sjulian if (nbusy == 0) 29317658Sjulian break; 29417658Sjulian printf("%d ", nbusy); 29565707Sjasone if (nbusy < pbusy) 29665707Sjasone iter = 0; 29765707Sjasone pbusy = nbusy; 29890361Sjulian sync(&thread0, NULL); 29983366Sjulian if (curthread != NULL) { 30088900Sjhb DROP_GIANT(); 30165707Sjasone for (subiter = 0; subiter < 50 * iter; subiter++) { 30272200Sbmilekic mtx_lock_spin(&sched_lock); 30383366Sjulian curthread->td_proc->p_stats->p_ru.ru_nvcsw++; 30465707Sjasone mi_switch(); /* Allow interrupt threads to run */ 30572200Sbmilekic mtx_unlock_spin(&sched_lock); 30665707Sjasone DELAY(1000); 30765707Sjasone } 30868808Sjhb PICKUP_GIANT(); 30965707Sjasone } else 31034266Sjulian DELAY(50000 * iter); 31117658Sjulian } 31253023Sphk printf("\n"); 31341137Smsmith /* 31441137Smsmith * Count only busy local buffers to prevent forcing 31541137Smsmith * a fsck if we're just a client of a wedged NFS server 31641137Smsmith */ 31741137Smsmith nbusy = 0; 31841137Smsmith for (bp = &buf[nbuf]; --bp >= buf; ) { 31948225Smckusick if (((bp->b_flags&B_INVAL) == 0 && BUF_REFCNT(bp)) || 32048225Smckusick ((bp->b_flags & (B_DELWRI|B_INVAL)) == B_DELWRI)) { 32153023Sphk if (bp->b_dev == NODEV) { 32253452Sphk TAILQ_REMOVE(&mountlist, 32348225Smckusick bp->b_vp->v_mount, mnt_list); 32453023Sphk continue; 32553023Sphk } 32653023Sphk nbusy++; 32753023Sphk#if defined(SHOW_BUSYBUFS) || defined(DIAGNOSTIC) 32853023Sphk printf( 32953023Sphk "%d: dev:%s, flags:%08lx, blkno:%ld, lblkno:%ld\n", 33053023Sphk nbusy, devtoname(bp->b_dev), 33153023Sphk bp->b_flags, (long)bp->b_blkno, 33253023Sphk (long)bp->b_lblkno); 33353023Sphk#endif 33446568Speter } 33541137Smsmith } 33617658Sjulian if (nbusy) { 33717658Sjulian /* 33817658Sjulian * Failed to sync all blocks. Indicate this and don't 33917658Sjulian * unmount filesystems (thus forcing an fsck on reboot). 34017658Sjulian */ 34153023Sphk printf("giving up on %d buffers\n", nbusy); 34217658Sjulian DELAY(5000000); /* 5 seconds */ 34317658Sjulian } else { 34417658Sjulian printf("done\n"); 34517658Sjulian /* 34617658Sjulian * Unmount filesystems 34717658Sjulian */ 34817658Sjulian if (panicstr == 0) 34917658Sjulian vfs_unmountall(); 35017658Sjulian } 35139237Sgibbs DELAY(100000); /* wait for console output to finish */ 35217658Sjulian } 35327997Sjulian 35454233Sphk print_uptime(); 35554233Sphk 35627997Sjulian /* 35727997Sjulian * Ok, now do things that assume all filesystem activity has 35827997Sjulian * been completed. 35927997Sjulian */ 36050107Smsmith EVENTHANDLER_INVOKE(shutdown_post_sync, howto); 36139237Sgibbs splhigh(); 36293496Sphk if ((howto & (RB_HALT|RB_DUMP)) == RB_DUMP && 36394169Sphk !cold && dumper.dumper != NULL && !dumping) 36494169Sphk doadump(); 36539237Sgibbs 36639237Sgibbs /* Now that we're going to really halt the system... */ 36750107Smsmith EVENTHANDLER_INVOKE(shutdown_final, howto); 36839237Sgibbs 36950107Smsmith for(;;) ; /* safety against shutdown_reset not working */ 37050107Smsmith /* NOTREACHED */ 37150107Smsmith} 37250107Smsmith 37350107Smsmith/* 37450107Smsmith * If the shutdown was a clean halt, behave accordingly. 37550107Smsmith */ 37650107Smsmithstatic void 37750107Smsmithshutdown_halt(void *junk, int howto) 37850107Smsmith{ 37917658Sjulian if (howto & RB_HALT) { 38017658Sjulian printf("\n"); 38117658Sjulian printf("The operating system has halted.\n"); 38217658Sjulian printf("Please press any key to reboot.\n\n"); 38319274Sjulian switch (cngetc()) { 38419274Sjulian case -1: /* No console, just die */ 38519274Sjulian cpu_halt(); 38619274Sjulian /* NOTREACHED */ 38719274Sjulian default: 38839237Sgibbs howto &= ~RB_HALT; 38919274Sjulian break; 39019274Sjulian } 39150107Smsmith } 39250107Smsmith} 39317658Sjulian 39450107Smsmith/* 39550107Smsmith * Check to see if the system paniced, pause and then reboot 39650107Smsmith * according to the specified delay. 39750107Smsmith */ 39850107Smsmithstatic void 39950107Smsmithshutdown_panic(void *junk, int howto) 40050107Smsmith{ 40150107Smsmith int loop; 40250107Smsmith 40350107Smsmith if (howto & RB_DUMP) { 40439237Sgibbs if (PANIC_REBOOT_WAIT_TIME != 0) { 40539237Sgibbs if (PANIC_REBOOT_WAIT_TIME != -1) { 40639237Sgibbs printf("Automatic reboot in %d seconds - " 40739237Sgibbs "press a key on the console to abort\n", 40839237Sgibbs PANIC_REBOOT_WAIT_TIME); 40939237Sgibbs for (loop = PANIC_REBOOT_WAIT_TIME * 10; 41039237Sgibbs loop > 0; --loop) { 41139237Sgibbs DELAY(1000 * 100); /* 1/10th second */ 41239237Sgibbs /* Did user type a key? */ 41339237Sgibbs if (cncheckc() != -1) 41439237Sgibbs break; 41517658Sjulian } 41639237Sgibbs if (!loop) 41750107Smsmith return; 41817658Sjulian } 41939237Sgibbs } else { /* zero time specified - reboot NOW */ 42050107Smsmith return; 42117658Sjulian } 42289522Snik printf("--> Press a key on the console to reboot,\n"); 42389522Snik printf("--> or switch off the system now.\n"); 42439237Sgibbs cngetc(); 42517658Sjulian } 42650107Smsmith} 42750107Smsmith 42850107Smsmith/* 42950107Smsmith * Everything done, now reset 43050107Smsmith */ 43150107Smsmithstatic void 43250107Smsmithshutdown_reset(void *junk, int howto) 43350107Smsmith{ 43417658Sjulian printf("Rebooting...\n"); 43517658Sjulian DELAY(1000000); /* wait 1 sec for printf's to complete and be read */ 43617677Sjulian /* cpu_boot(howto); */ /* doesn't do anything at the moment */ 43717658Sjulian cpu_reset(); 43850107Smsmith /* NOTREACHED */ /* assuming reset worked */ 43917658Sjulian} 44017658Sjulian 441108682Sphk/* 442108682Sphk * Print a backtrace if we can. 443108682Sphk */ 444108682Sphk 445108682Sphkvoid 446108682Sphkbacktrace(void) 447108682Sphk{ 448108682Sphk#ifdef DDB 449108682Sphk db_print_backtrace(); 450108682Sphk#else 451108682Sphk printf("Sorry, need DDB option to print backtrace"); 452108682Sphk#endif 453108682Sphk} 454108682Sphk 45575570Sjhb#ifdef SMP 456101155Sjhbstatic u_int panic_cpu = NOCPU; 45775570Sjhb#endif 45875570Sjhb 45917658Sjulian/* 46017658Sjulian * Panic is called on unresolvable fatal errors. It prints "panic: mesg", 46117658Sjulian * and then reboots. If we are called twice, then we avoid trying to sync 46217658Sjulian * the disks as this often leads to recursive panics. 46382749Sdillon * 46482749Sdillon * MPSAFE 46517658Sjulian */ 46617658Sjulianvoid 46717658Sjulianpanic(const char *fmt, ...) 46817658Sjulian{ 469100209Sgallatin struct thread *td = curthread; 470103647Sjhb int bootopt, newpanic; 47117658Sjulian va_list ap; 47238874Sache static char buf[256]; 47317658Sjulian 47465557Sjasone#ifdef SMP 47582115Sjhb /* 47682115Sjhb * We don't want multiple CPU's to panic at the same time, so we 477101155Sjhb * use panic_cpu as a simple spinlock. We have to keep checking 478101155Sjhb * panic_cpu if we are spinning in case the panic on the first 47982115Sjhb * CPU is canceled. 48082115Sjhb */ 481101155Sjhb if (panic_cpu != PCPU_GET(cpuid)) 482101155Sjhb while (atomic_cmpset_int(&panic_cpu, NOCPU, 483101155Sjhb PCPU_GET(cpuid)) == 0) 484101155Sjhb while (panic_cpu != NOCPU) 485101155Sjhb ; /* nothing */ 48665557Sjasone#endif 48765557Sjasone 48817658Sjulian bootopt = RB_AUTOBOOT | RB_DUMP; 489103647Sjhb newpanic = 0; 49017658Sjulian if (panicstr) 49117658Sjulian bootopt |= RB_NOSYNC; 492103647Sjhb else { 49317658Sjulian panicstr = fmt; 494103647Sjhb newpanic = 1; 495103647Sjhb } 49617658Sjulian 49717658Sjulian va_start(ap, fmt); 49841514Sarchie (void)vsnprintf(buf, sizeof(buf), fmt, ap); 49938874Sache if (panicstr == fmt) 50038874Sache panicstr = buf; 50117658Sjulian va_end(ap); 50238874Sache printf("panic: %s\n", buf); 50326100Sfsmp#ifdef SMP 50472091Sasmodai /* two separate prints in case of an unmapped page and trap */ 50570861Sjake printf("cpuid = %d; ", PCPU_GET(cpuid)); 50669335Sjhb#ifdef APIC_IO 50729128Speter printf("lapic.id = %08x\n", lapic.id); 50899828Sjhb#else 50999828Sjhb printf("\n"); 51026100Sfsmp#endif 51169335Sjhb#endif 51217658Sjulian 51317658Sjulian#if defined(DDB) 514103647Sjhb if (newpanic && trace_on_panic) 515103647Sjhb db_print_backtrace(); 51617658Sjulian if (debugger_on_panic) 51717658Sjulian Debugger ("panic"); 51882223Sjhb#ifdef RESTARTABLE_PANICS 51982115Sjhb /* See if the user aborted the panic, in which case we continue. */ 52082115Sjhb if (panicstr == NULL) { 52182115Sjhb#ifdef SMP 522101155Sjhb atomic_store_rel_int(&panic_cpu, NOCPU); 52317658Sjulian#endif 52482115Sjhb return; 52582115Sjhb } 52682115Sjhb#endif 52782223Sjhb#endif 528100209Sgallatin td->td_flags |= TDF_INPANIC; 52985202Speter if (!sync_on_panic) 53085202Speter bootopt |= RB_NOSYNC; 53117658Sjulian boot(bootopt); 53217658Sjulian} 53317658Sjulian 53417768Sjulian/* 53543436Smsmith * Support for poweroff delay. 53643436Smsmith */ 53754248Smsmith#ifndef POWEROFF_DELAY 53854248Smsmith# define POWEROFF_DELAY 5000 53954248Smsmith#endif 54054248Smsmithstatic int poweroff_delay = POWEROFF_DELAY; 54154248Smsmith 54243436SmsmithSYSCTL_INT(_kern_shutdown, OID_AUTO, poweroff_delay, CTLFLAG_RW, 54343436Smsmith &poweroff_delay, 0, ""); 54443436Smsmith 54550107Smsmithstatic void 54650107Smsmithpoweroff_wait(void *junk, int howto) 54743436Smsmith{ 54843436Smsmith if(!(howto & RB_POWEROFF) || poweroff_delay <= 0) 54943436Smsmith return; 55043436Smsmith DELAY(poweroff_delay * 1000); 55143436Smsmith} 55255539Sluoqi 55355539Sluoqi/* 55455539Sluoqi * Some system processes (e.g. syncer) need to be stopped at appropriate 55555539Sluoqi * points in their main loops prior to a system shutdown, so that they 55655539Sluoqi * won't interfere with the shutdown process (e.g. by holding a disk buf 55755539Sluoqi * to cause sync to fail). For each of these system processes, register 55855539Sluoqi * shutdown_kproc() as a handler for one of shutdown events. 55955539Sluoqi */ 56055539Sluoqistatic int kproc_shutdown_wait = 60; 56155539SluoqiSYSCTL_INT(_kern_shutdown, OID_AUTO, kproc_shutdown_wait, CTLFLAG_RW, 56255539Sluoqi &kproc_shutdown_wait, 0, ""); 56355539Sluoqi 56455539Sluoqivoid 56570063Sjhbkproc_shutdown(void *arg, int howto) 56655539Sluoqi{ 56755539Sluoqi struct proc *p; 56855539Sluoqi int error; 56955539Sluoqi 57055539Sluoqi if (panicstr) 57155539Sluoqi return; 57255539Sluoqi 57355539Sluoqi p = (struct proc *)arg; 57455539Sluoqi printf("Waiting (max %d seconds) for system process `%s' to stop...", 57555862Sluoqi kproc_shutdown_wait, p->p_comm); 57670063Sjhb error = kthread_suspend(p, kproc_shutdown_wait * hz); 57755539Sluoqi 57855539Sluoqi if (error == EWOULDBLOCK) 57955539Sluoqi printf("timed out\n"); 58055539Sluoqi else 58155539Sluoqi printf("stopped\n"); 58255539Sluoqi} 58393496Sphk 58493496Sphk/* Registration of dumpers */ 58593496Sphkint 58693496Sphkset_dumper(struct dumperinfo *di) 58793496Sphk{ 58893496Sphk if (di == NULL) { 58993496Sphk bzero(&dumper, sizeof dumper); 59093496Sphk return (0); 59193496Sphk } 59293496Sphk if (dumper.dumper != NULL) 59393496Sphk return (EBUSY); 59493496Sphk dumper = *di; 59593496Sphk return (0); 59693496Sphk} 59793496Sphk 598105531Stmm#if defined(__powerpc__) 59993496Sphkvoid 60093496Sphkdumpsys(struct dumperinfo *di __unused) 60193496Sphk{ 60293496Sphk 60393496Sphk printf("Kernel dumps not implemented on this architecture\n"); 60493496Sphk} 60593496Sphk#endif 606