kern_shutdown.c revision 90361
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 90361 2002-02-07 20:58:47Z julian $ 4017658Sjulian */ 4117658Sjulian 4217658Sjulian#include "opt_ddb.h" 4333445Seivind#include "opt_hw_wdog.h" 4428976Sbde#include "opt_panic.h" 4528976Sbde#include "opt_show_busybufs.h" 4617658Sjulian 4717658Sjulian#include <sys/param.h> 4817658Sjulian#include <sys/systm.h> 4960041Sphk#include <sys/bio.h> 5031275Sbde#include <sys/buf.h> 5178767Sjhb#include <sys/conf.h> 5278767Sjhb#include <sys/cons.h> 5381688Sbde#include <sys/disklabel.h> 5478767Sjhb#include <sys/eventhandler.h> 5517658Sjulian#include <sys/kernel.h> 5655539Sluoqi#include <sys/kthread.h> 5789601Ssobomax#include <sys/malloc.h> 5821776Sbde#include <sys/mount.h> 5978767Sjhb#include <sys/proc.h> 6078767Sjhb#include <sys/reboot.h> 6178767Sjhb#include <sys/resourcevar.h> 6278767Sjhb#include <sys/smp.h> /* smp_active */ 6317658Sjulian#include <sys/sysctl.h> 6417658Sjulian#include <sys/sysproto.h> 6578767Sjhb#include <sys/vnode.h> 6617658Sjulian 6717658Sjulian#include <machine/pcb.h> 6817658Sjulian#include <machine/md_var.h> 6917658Sjulian 7017658Sjulian#include <sys/signalvar.h> 7182119Sjhb#ifdef DDB 7282119Sjhb#include <ddb/ddb.h> 7382119Sjhb#endif 7417658Sjulian 7517658Sjulian#ifndef PANIC_REBOOT_WAIT_TIME 7617658Sjulian#define PANIC_REBOOT_WAIT_TIME 15 /* default to 15 seconds */ 7717658Sjulian#endif 7817658Sjulian 7917658Sjulian/* 8017658Sjulian * Note that stdarg.h and the ANSI style va_start macro is used for both 8117658Sjulian * ANSI and traditional C compilers. 8217658Sjulian */ 8317658Sjulian#include <machine/stdarg.h> 8417658Sjulian 8528769Sbde#ifdef DDB 8617658Sjulian#ifdef DDB_UNATTENDED 8742135Smsmithint debugger_on_panic = 0; 8817658Sjulian#else 8942135Smsmithint debugger_on_panic = 1; 9017658Sjulian#endif 9117658SjulianSYSCTL_INT(_debug, OID_AUTO, debugger_on_panic, CTLFLAG_RW, 9246381Sbillf &debugger_on_panic, 0, "Run debugger on kernel panic"); 9317658Sjulian#endif 9417658Sjulian 9585202Speterint sync_on_panic = 1; 9685202SpeterSYSCTL_INT(_kern, OID_AUTO, sync_on_panic, CTLFLAG_RW, 9785202Speter &sync_on_panic, 0, "Do a sync before rebooting from a panic"); 9885202Speter 9943436SmsmithSYSCTL_NODE(_kern, OID_AUTO, shutdown, CTLFLAG_RW, 0, "Shutdown environment"); 10043436Smsmith 10128000Sjulian#ifdef HW_WDOG 10217658Sjulian/* 10327997Sjulian * If there is a hardware watchdog, point this at the function needed to 10427997Sjulian * hold it off. 10527997Sjulian * It's needed when the kernel needs to do some lengthy operations. 10627997Sjulian * e.g. in wd.c when dumping core.. It's most annoying to have 10727997Sjulian * your precious core-dump only half written because the wdog kicked in. 10827997Sjulian */ 10927997Sjulianwatchdog_tickle_fn wdog_tickler = NULL; 11028000Sjulian#endif /* HW_WDOG */ 11127997Sjulian 11227997Sjulian/* 11317658Sjulian * Variable panicstr contains argument to first call to panic; used as flag 11417658Sjulian * to indicate that the kernel has already called panic. 11517658Sjulian */ 11617658Sjulianconst char *panicstr; 11717658Sjulian 11867093Spsint dumping; /* system is dumping */ 11967093Sps 12065395Speterstatic void boot(int) __dead2; 12165395Speterstatic void dumpsys(void); 12265395Speterstatic void poweroff_wait(void *, int); 12365395Speterstatic void shutdown_halt(void *junk, int howto); 12465395Speterstatic void shutdown_panic(void *junk, int howto); 12565395Speterstatic void shutdown_reset(void *junk, int howto); 12617658Sjulian 12750107Smsmith/* register various local shutdown events */ 12850107Smsmithstatic void 12950107Smsmithshutdown_conf(void *unused) 13050107Smsmith{ 13150107Smsmith EVENTHANDLER_REGISTER(shutdown_final, poweroff_wait, NULL, SHUTDOWN_PRI_FIRST); 13250107Smsmith EVENTHANDLER_REGISTER(shutdown_final, shutdown_halt, NULL, SHUTDOWN_PRI_LAST + 100); 13350107Smsmith EVENTHANDLER_REGISTER(shutdown_final, shutdown_panic, NULL, SHUTDOWN_PRI_LAST + 100); 13450107Smsmith EVENTHANDLER_REGISTER(shutdown_final, shutdown_reset, NULL, SHUTDOWN_PRI_LAST + 200); 13550107Smsmith} 13648868Sphk 13750107SmsmithSYSINIT(shutdown_conf, SI_SUB_INTRINSIC, SI_ORDER_ANY, shutdown_conf, NULL) 13850107Smsmith 13917658Sjulian/* 14017658Sjulian * The system call that results in a reboot 14182749Sdillon * 14282749Sdillon * MPSAFE 14317658Sjulian */ 14482749Sdillon/* ARGSUSED */ 14517658Sjulianint 14683366Sjulianreboot(struct thread *td, struct reboot_args *uap) 14717658Sjulian{ 14817658Sjulian int error; 14917658Sjulian 15082749Sdillon mtx_lock(&Giant); 15183366Sjulian if ((error = suser_td(td)) == 0) 15282749Sdillon boot(uap->opt); 15382749Sdillon mtx_unlock(&Giant); 15482749Sdillon return (error); 15517658Sjulian} 15617658Sjulian 15717658Sjulian/* 15817658Sjulian * Called by events that want to shut down.. e.g <CTL><ALT><DEL> on a PC 15917658Sjulian */ 16065268Smsmithstatic int shutdown_howto = 0; 16165268Smsmith 16217658Sjulianvoid 16365268Smsmithshutdown_nice(int howto) 16417658Sjulian{ 16565268Smsmith shutdown_howto = howto; 16665268Smsmith 16717658Sjulian /* Send a signal to init(8) and have it shutdown the world */ 16817658Sjulian if (initproc != NULL) { 16973913Sjhb PROC_LOCK(initproc); 17017658Sjulian psignal(initproc, SIGINT); 17173913Sjhb PROC_UNLOCK(initproc); 17217658Sjulian } else { 17317658Sjulian /* No init(8) running, so simply reboot */ 17417658Sjulian boot(RB_NOSYNC); 17517658Sjulian } 17617658Sjulian return; 17717658Sjulian} 17817658Sjulianstatic int waittime = -1; 17917658Sjulianstatic struct pcb dumppcb; 18017658Sjulian 18154233Sphkstatic void 18265395Speterprint_uptime(void) 18354233Sphk{ 18454233Sphk int f; 18554233Sphk struct timespec ts; 18654233Sphk 18754233Sphk getnanouptime(&ts); 18854233Sphk printf("Uptime: "); 18954233Sphk f = 0; 19054233Sphk if (ts.tv_sec >= 86400) { 19165764Sjhb printf("%ldd", (long)ts.tv_sec / 86400); 19254233Sphk ts.tv_sec %= 86400; 19354233Sphk f = 1; 19454233Sphk } 19554233Sphk if (f || ts.tv_sec >= 3600) { 19665764Sjhb printf("%ldh", (long)ts.tv_sec / 3600); 19754233Sphk ts.tv_sec %= 3600; 19854233Sphk f = 1; 19954233Sphk } 20054233Sphk if (f || ts.tv_sec >= 60) { 20165764Sjhb printf("%ldm", (long)ts.tv_sec / 60); 20254233Sphk ts.tv_sec %= 60; 20354233Sphk f = 1; 20454233Sphk } 20565764Sjhb printf("%lds\n", (long)ts.tv_sec); 20654233Sphk} 20754233Sphk 20817658Sjulian/* 20917658Sjulian * Go through the rigmarole of shutting down.. 21017658Sjulian * this used to be in machdep.c but I'll be dammned if I could see 21117658Sjulian * anything machine dependant in it. 21217658Sjulian */ 21331275Sbdestatic void 21465395Speterboot(int howto) 21517658Sjulian{ 21617658Sjulian 21765268Smsmith /* collect extra flags that shutdown_nice might have set */ 21865268Smsmith howto |= shutdown_howto; 21965268Smsmith 22082119Sjhb#ifdef DDB 22182119Sjhb /* We are out of the debugger now. */ 22282119Sjhb db_active = 0; 22382119Sjhb#endif 22482119Sjhb 22525164Speter#ifdef SMP 22665395Speter if (smp_active) 22770861Sjake printf("boot() called on cpu#%d\n", PCPU_GET(cpuid)); 22825164Speter#endif 22927997Sjulian /* 23027997Sjulian * Do any callouts that should be done BEFORE syncing the filesystems. 23127997Sjulian */ 23250107Smsmith EVENTHANDLER_INVOKE(shutdown_pre_sync, howto); 23327997Sjulian 23427997Sjulian /* 23527997Sjulian * Now sync filesystems 23627997Sjulian */ 23717658Sjulian if (!cold && (howto & RB_NOSYNC) == 0 && waittime < 0) { 23817658Sjulian register struct buf *bp; 23965707Sjasone int iter, nbusy, pbusy; 24065707Sjasone int subiter; 24117658Sjulian 24217658Sjulian waittime = 0; 24317658Sjulian printf("\nsyncing disks... "); 24417658Sjulian 24590361Sjulian sync(&thread0, NULL); 24617658Sjulian 24734266Sjulian /* 24834266Sjulian * With soft updates, some buffers that are 24934266Sjulian * written will be remarked as dirty until other 25034266Sjulian * buffers are written. 25134266Sjulian */ 25265707Sjasone for (iter = pbusy = 0; iter < 20; iter++) { 25317658Sjulian nbusy = 0; 25417658Sjulian for (bp = &buf[nbuf]; --bp >= buf; ) { 25548225Smckusick if ((bp->b_flags & B_INVAL) == 0 && 25648225Smckusick BUF_REFCNT(bp) > 0) { 25717658Sjulian nbusy++; 25834266Sjulian } else if ((bp->b_flags & (B_DELWRI | B_INVAL)) 25934266Sjulian == B_DELWRI) { 26034266Sjulian /* bawrite(bp);*/ 26134266Sjulian nbusy++; 26217658Sjulian } 26317658Sjulian } 26417658Sjulian if (nbusy == 0) 26517658Sjulian break; 26617658Sjulian printf("%d ", nbusy); 26765707Sjasone if (nbusy < pbusy) 26865707Sjasone iter = 0; 26965707Sjasone pbusy = nbusy; 27090361Sjulian sync(&thread0, NULL); 27183366Sjulian if (curthread != NULL) { 27288900Sjhb DROP_GIANT(); 27365707Sjasone for (subiter = 0; subiter < 50 * iter; subiter++) { 27472200Sbmilekic mtx_lock_spin(&sched_lock); 27583366Sjulian curthread->td_proc->p_stats->p_ru.ru_nvcsw++; 27665707Sjasone mi_switch(); /* Allow interrupt threads to run */ 27772200Sbmilekic mtx_unlock_spin(&sched_lock); 27865707Sjasone DELAY(1000); 27965707Sjasone } 28068808Sjhb PICKUP_GIANT(); 28165707Sjasone } else 28234266Sjulian DELAY(50000 * iter); 28317658Sjulian } 28453023Sphk printf("\n"); 28541137Smsmith /* 28641137Smsmith * Count only busy local buffers to prevent forcing 28741137Smsmith * a fsck if we're just a client of a wedged NFS server 28841137Smsmith */ 28941137Smsmith nbusy = 0; 29041137Smsmith for (bp = &buf[nbuf]; --bp >= buf; ) { 29148225Smckusick if (((bp->b_flags&B_INVAL) == 0 && BUF_REFCNT(bp)) || 29248225Smckusick ((bp->b_flags & (B_DELWRI|B_INVAL)) == B_DELWRI)) { 29353023Sphk if (bp->b_dev == NODEV) { 29453452Sphk TAILQ_REMOVE(&mountlist, 29548225Smckusick bp->b_vp->v_mount, mnt_list); 29653023Sphk continue; 29753023Sphk } 29853023Sphk nbusy++; 29953023Sphk#if defined(SHOW_BUSYBUFS) || defined(DIAGNOSTIC) 30053023Sphk printf( 30153023Sphk "%d: dev:%s, flags:%08lx, blkno:%ld, lblkno:%ld\n", 30253023Sphk nbusy, devtoname(bp->b_dev), 30353023Sphk bp->b_flags, (long)bp->b_blkno, 30453023Sphk (long)bp->b_lblkno); 30553023Sphk#endif 30646568Speter } 30741137Smsmith } 30817658Sjulian if (nbusy) { 30917658Sjulian /* 31017658Sjulian * Failed to sync all blocks. Indicate this and don't 31117658Sjulian * unmount filesystems (thus forcing an fsck on reboot). 31217658Sjulian */ 31353023Sphk printf("giving up on %d buffers\n", nbusy); 31417658Sjulian DELAY(5000000); /* 5 seconds */ 31517658Sjulian } else { 31617658Sjulian printf("done\n"); 31717658Sjulian /* 31817658Sjulian * Unmount filesystems 31917658Sjulian */ 32017658Sjulian if (panicstr == 0) 32117658Sjulian vfs_unmountall(); 32217658Sjulian } 32339237Sgibbs DELAY(100000); /* wait for console output to finish */ 32417658Sjulian } 32527997Sjulian 32654233Sphk print_uptime(); 32754233Sphk 32827997Sjulian /* 32927997Sjulian * Ok, now do things that assume all filesystem activity has 33027997Sjulian * been completed. 33127997Sjulian */ 33250107Smsmith EVENTHANDLER_INVOKE(shutdown_post_sync, howto); 33339237Sgibbs splhigh(); 33465394Speter if ((howto & (RB_HALT|RB_DUMP)) == RB_DUMP && !cold) 33539237Sgibbs dumpsys(); 33639237Sgibbs 33739237Sgibbs /* Now that we're going to really halt the system... */ 33850107Smsmith EVENTHANDLER_INVOKE(shutdown_final, howto); 33939237Sgibbs 34050107Smsmith for(;;) ; /* safety against shutdown_reset not working */ 34150107Smsmith /* NOTREACHED */ 34250107Smsmith} 34350107Smsmith 34450107Smsmith/* 34550107Smsmith * If the shutdown was a clean halt, behave accordingly. 34650107Smsmith */ 34750107Smsmithstatic void 34850107Smsmithshutdown_halt(void *junk, int howto) 34950107Smsmith{ 35017658Sjulian if (howto & RB_HALT) { 35117658Sjulian printf("\n"); 35217658Sjulian printf("The operating system has halted.\n"); 35317658Sjulian printf("Please press any key to reboot.\n\n"); 35419274Sjulian switch (cngetc()) { 35519274Sjulian case -1: /* No console, just die */ 35619274Sjulian cpu_halt(); 35719274Sjulian /* NOTREACHED */ 35819274Sjulian default: 35939237Sgibbs howto &= ~RB_HALT; 36019274Sjulian break; 36119274Sjulian } 36250107Smsmith } 36350107Smsmith} 36417658Sjulian 36550107Smsmith/* 36650107Smsmith * Check to see if the system paniced, pause and then reboot 36750107Smsmith * according to the specified delay. 36850107Smsmith */ 36950107Smsmithstatic void 37050107Smsmithshutdown_panic(void *junk, int howto) 37150107Smsmith{ 37250107Smsmith int loop; 37350107Smsmith 37450107Smsmith if (howto & RB_DUMP) { 37539237Sgibbs if (PANIC_REBOOT_WAIT_TIME != 0) { 37639237Sgibbs if (PANIC_REBOOT_WAIT_TIME != -1) { 37739237Sgibbs printf("Automatic reboot in %d seconds - " 37839237Sgibbs "press a key on the console to abort\n", 37939237Sgibbs PANIC_REBOOT_WAIT_TIME); 38039237Sgibbs for (loop = PANIC_REBOOT_WAIT_TIME * 10; 38139237Sgibbs loop > 0; --loop) { 38239237Sgibbs DELAY(1000 * 100); /* 1/10th second */ 38339237Sgibbs /* Did user type a key? */ 38439237Sgibbs if (cncheckc() != -1) 38539237Sgibbs break; 38617658Sjulian } 38739237Sgibbs if (!loop) 38850107Smsmith return; 38917658Sjulian } 39039237Sgibbs } else { /* zero time specified - reboot NOW */ 39150107Smsmith return; 39217658Sjulian } 39389522Snik printf("--> Press a key on the console to reboot,\n"); 39489522Snik printf("--> or switch off the system now.\n"); 39539237Sgibbs cngetc(); 39617658Sjulian } 39750107Smsmith} 39850107Smsmith 39950107Smsmith/* 40050107Smsmith * Everything done, now reset 40150107Smsmith */ 40250107Smsmithstatic void 40350107Smsmithshutdown_reset(void *junk, int howto) 40450107Smsmith{ 40517658Sjulian printf("Rebooting...\n"); 40617658Sjulian DELAY(1000000); /* wait 1 sec for printf's to complete and be read */ 40717677Sjulian /* cpu_boot(howto); */ /* doesn't do anything at the moment */ 40817658Sjulian cpu_reset(); 40950107Smsmith /* NOTREACHED */ /* assuming reset worked */ 41017658Sjulian} 41117658Sjulian 41217658Sjulian/* 41317658Sjulian * Magic number for savecore 41417658Sjulian * 41517658Sjulian * exported (symorder) and used at least by savecore(8) 41617658Sjulian * 41717658Sjulian */ 41817658Sjulianstatic u_long const dumpmag = 0x8fca0101UL; 41917658Sjulian 42017658Sjulianstatic int dumpsize = 0; /* also for savecore */ 42117658Sjulian 42217658Sjulianstatic int dodump = 1; 42317658Sjulian 42448868SphkSYSCTL_INT(_machdep, OID_AUTO, do_dump, CTLFLAG_RW, &dodump, 0, 42548868Sphk "Try to perform coredump on kernel panic"); 42648868Sphk 42748868Sphkstatic int 42865395Spetersetdumpdev(dev_t dev) 42948868Sphk{ 43050571Sphk int psize; 43148868Sphk long newdumplo; 43248868Sphk 43348868Sphk if (dev == NODEV) { 43448868Sphk dumpdev = dev; 43548868Sphk return (0); 43648868Sphk } 43749679Sphk if (devsw(dev) == NULL) 43848868Sphk return (ENXIO); /* XXX is this right? */ 43949679Sphk if (devsw(dev)->d_psize == NULL) 44048868Sphk return (ENXIO); /* XXX should be ENODEV ? */ 44149679Sphk psize = devsw(dev)->d_psize(dev); 44248868Sphk if (psize == -1) 44348868Sphk return (ENXIO); /* XXX should be ENODEV ? */ 44448868Sphk /* 44550571Sphk * XXX should clean up checking in dumpsys() to be more like this. 44648868Sphk */ 44781688Sbde newdumplo = psize - Maxmem * (PAGE_SIZE / DEV_BSIZE); 44881688Sbde if (newdumplo <= LABELSECTOR) 44948868Sphk return (ENOSPC); 45048868Sphk dumpdev = dev; 45148868Sphk dumplo = newdumplo; 45248868Sphk return (0); 45348868Sphk} 45448868Sphk 45548868Sphk 45631403Sjulian/* ARGSUSED */ 45731403Sjulianstatic void 45865395Speterdump_conf(void *dummy) 45931403Sjulian{ 46089601Ssobomax char *path; 46189601Ssobomax dev_t dev; 46289601Ssobomax 46389601Ssobomax path = malloc(MNAMELEN, M_TEMP, M_WAITOK); 46489601Ssobomax if (TUNABLE_STR_FETCH("dumpdev", path, MNAMELEN) != 0) { 46589601Ssobomax dev = getdiskbyname(path); 46689601Ssobomax if (dev != NODEV) 46789601Ssobomax dumpdev = dev; 46889601Ssobomax } 46989601Ssobomax free(path, M_TEMP); 47048868Sphk if (setdumpdev(dumpdev) != 0) 47148868Sphk dumpdev = NODEV; 47231403Sjulian} 47348868Sphk 47431403SjulianSYSINIT(dump_conf, SI_SUB_DUMP_CONF, SI_ORDER_FIRST, dump_conf, NULL) 47531403Sjulian 47648868Sphkstatic int 47762573Sphksysctl_kern_dumpdev(SYSCTL_HANDLER_ARGS) 47848868Sphk{ 47948868Sphk int error; 48048868Sphk udev_t ndumpdev; 48148868Sphk 48253838Sphk ndumpdev = dev2udev(dumpdev); 48348868Sphk error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req); 48448868Sphk if (error == 0 && req->newptr != NULL) 48553838Sphk error = setdumpdev(udev2dev(ndumpdev, 0)); 48648868Sphk return (error); 48748868Sphk} 48848868Sphk 48948868SphkSYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW, 49048868Sphk 0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", ""); 49148868Sphk 49217658Sjulian/* 49317658Sjulian * Doadump comes here after turning off memory management and 49417658Sjulian * getting on the dump stack, either when called above, or by 49517658Sjulian * the auto-restart code. 49617658Sjulian */ 49717658Sjulianstatic void 49817658Sjuliandumpsys(void) 49917658Sjulian{ 50049627Salfred int error; 50117658Sjulian 50265394Speter savectx(&dumppcb); 50317658Sjulian if (!dodump) 50417658Sjulian return; 50517658Sjulian if (dumpdev == NODEV) 50617658Sjulian return; 50749679Sphk if (!(devsw(dumpdev))) 50817658Sjulian return; 50949679Sphk if (!(devsw(dumpdev)->d_dump)) 51017658Sjulian return; 51183703Speter if (dumping++) { 51283703Speter dumping--; 51383703Speter printf("Dump already in progress, bailing...\n"); 51483703Speter return; 51583703Speter } 51617658Sjulian dumpsize = Maxmem; 51750571Sphk printf("\ndumping to dev %s, offset %ld\n", devtoname(dumpdev), dumplo); 51817658Sjulian printf("dump "); 51949679Sphk error = (*devsw(dumpdev)->d_dump)(dumpdev); 52083703Speter dumping--; 52149627Salfred if (error == 0) { 52249627Salfred printf("succeeded\n"); 52349627Salfred return; 52449627Salfred } 52549627Salfred printf("failed, reason: "); 52649627Salfred switch (error) { 52749627Salfred case ENODEV: 52849627Salfred printf("device doesn't support a dump routine\n"); 52949627Salfred break; 53017658Sjulian 53117658Sjulian case ENXIO: 53217658Sjulian printf("device bad\n"); 53317658Sjulian break; 53417658Sjulian 53517658Sjulian case EFAULT: 53617658Sjulian printf("device not ready\n"); 53717658Sjulian break; 53817658Sjulian 53917658Sjulian case EINVAL: 54017658Sjulian printf("area improper\n"); 54117658Sjulian break; 54217658Sjulian 54317658Sjulian case EIO: 54417658Sjulian printf("i/o error\n"); 54517658Sjulian break; 54617658Sjulian 54717658Sjulian case EINTR: 54817658Sjulian printf("aborted from console\n"); 54917658Sjulian break; 55017658Sjulian 55117658Sjulian default: 55249627Salfred printf("unknown, error = %d\n", error); 55317658Sjulian break; 55417658Sjulian } 55517658Sjulian} 55617658Sjulian 55774890Spsint 55886313Spsdumpstatus(vm_offset_t addr, off_t count) 55974890Sps{ 56074890Sps int c; 56174890Sps 56274890Sps if (addr % (1024 * 1024) == 0) { 56374890Sps#ifdef HW_WDOG 56474890Sps if (wdog_tickler) 56574890Sps (*wdog_tickler)(); 56674890Sps#endif 56786313Sps printf("%ld ", (long)(count / (1024 * 1024))); 56874890Sps } 56974890Sps 57074890Sps if ((c = cncheckc()) == 0x03) 57174890Sps return -1; 57274890Sps else if (c != -1) 57374890Sps printf("[CTRL-C to abort] "); 57474890Sps 57574890Sps return 0; 57674890Sps} 57774890Sps 57875570Sjhb#ifdef SMP 57975570Sjhbstatic u_int panic_cpu = NOCPU; 58075570Sjhb#endif 58175570Sjhb 58217658Sjulian/* 58317658Sjulian * Panic is called on unresolvable fatal errors. It prints "panic: mesg", 58417658Sjulian * and then reboots. If we are called twice, then we avoid trying to sync 58517658Sjulian * the disks as this often leads to recursive panics. 58682749Sdillon * 58782749Sdillon * MPSAFE 58817658Sjulian */ 58917658Sjulianvoid 59017658Sjulianpanic(const char *fmt, ...) 59117658Sjulian{ 59283312Sjhb int bootopt; 59317658Sjulian va_list ap; 59438874Sache static char buf[256]; 59517658Sjulian 59665557Sjasone#ifdef SMP 59782115Sjhb /* 59882115Sjhb * We don't want multiple CPU's to panic at the same time, so we 59982115Sjhb * use panic_cpu as a simple spinlock. We have to keep checking 60082115Sjhb * panic_cpu if we are spinning in case the panic on the first 60182115Sjhb * CPU is canceled. 60282115Sjhb */ 60383312Sjhb if (panic_cpu != PCPU_GET(cpuid)) 60482115Sjhb while (atomic_cmpset_int(&panic_cpu, NOCPU, 60583312Sjhb PCPU_GET(cpuid)) == 0) 60682115Sjhb while (panic_cpu != NOCPU) 60782115Sjhb ; /* nothing */ 60865557Sjasone#endif 60965557Sjasone 61017658Sjulian bootopt = RB_AUTOBOOT | RB_DUMP; 61117658Sjulian if (panicstr) 61217658Sjulian bootopt |= RB_NOSYNC; 61317658Sjulian else 61417658Sjulian panicstr = fmt; 61517658Sjulian 61617658Sjulian va_start(ap, fmt); 61741514Sarchie (void)vsnprintf(buf, sizeof(buf), fmt, ap); 61838874Sache if (panicstr == fmt) 61938874Sache panicstr = buf; 62017658Sjulian va_end(ap); 62138874Sache printf("panic: %s\n", buf); 62226100Sfsmp#ifdef SMP 62372091Sasmodai /* two separate prints in case of an unmapped page and trap */ 62470861Sjake printf("cpuid = %d; ", PCPU_GET(cpuid)); 62569335Sjhb#ifdef APIC_IO 62629128Speter printf("lapic.id = %08x\n", lapic.id); 62726100Sfsmp#endif 62869335Sjhb#endif 62917658Sjulian 63017658Sjulian#if defined(DDB) 63117658Sjulian if (debugger_on_panic) 63217658Sjulian Debugger ("panic"); 63382223Sjhb#ifdef RESTARTABLE_PANICS 63482115Sjhb /* See if the user aborted the panic, in which case we continue. */ 63582115Sjhb if (panicstr == NULL) { 63682115Sjhb#ifdef SMP 63782115Sjhb atomic_store_rel_int(&panic_cpu, NOCPU); 63817658Sjulian#endif 63982115Sjhb return; 64082115Sjhb } 64182115Sjhb#endif 64282223Sjhb#endif 64385202Speter if (!sync_on_panic) 64485202Speter bootopt |= RB_NOSYNC; 64517658Sjulian boot(bootopt); 64617658Sjulian} 64717658Sjulian 64817768Sjulian/* 64943436Smsmith * Support for poweroff delay. 65043436Smsmith */ 65154248Smsmith#ifndef POWEROFF_DELAY 65254248Smsmith# define POWEROFF_DELAY 5000 65354248Smsmith#endif 65454248Smsmithstatic int poweroff_delay = POWEROFF_DELAY; 65554248Smsmith 65643436SmsmithSYSCTL_INT(_kern_shutdown, OID_AUTO, poweroff_delay, CTLFLAG_RW, 65743436Smsmith &poweroff_delay, 0, ""); 65843436Smsmith 65950107Smsmithstatic void 66050107Smsmithpoweroff_wait(void *junk, int howto) 66143436Smsmith{ 66243436Smsmith if(!(howto & RB_POWEROFF) || poweroff_delay <= 0) 66343436Smsmith return; 66443436Smsmith DELAY(poweroff_delay * 1000); 66543436Smsmith} 66655539Sluoqi 66755539Sluoqi/* 66855539Sluoqi * Some system processes (e.g. syncer) need to be stopped at appropriate 66955539Sluoqi * points in their main loops prior to a system shutdown, so that they 67055539Sluoqi * won't interfere with the shutdown process (e.g. by holding a disk buf 67155539Sluoqi * to cause sync to fail). For each of these system processes, register 67255539Sluoqi * shutdown_kproc() as a handler for one of shutdown events. 67355539Sluoqi */ 67455539Sluoqistatic int kproc_shutdown_wait = 60; 67555539SluoqiSYSCTL_INT(_kern_shutdown, OID_AUTO, kproc_shutdown_wait, CTLFLAG_RW, 67655539Sluoqi &kproc_shutdown_wait, 0, ""); 67755539Sluoqi 67855539Sluoqivoid 67970063Sjhbkproc_shutdown(void *arg, int howto) 68055539Sluoqi{ 68155539Sluoqi struct proc *p; 68255539Sluoqi int error; 68355539Sluoqi 68455539Sluoqi if (panicstr) 68555539Sluoqi return; 68655539Sluoqi 68755539Sluoqi p = (struct proc *)arg; 68855539Sluoqi printf("Waiting (max %d seconds) for system process `%s' to stop...", 68955862Sluoqi kproc_shutdown_wait, p->p_comm); 69070063Sjhb error = kthread_suspend(p, kproc_shutdown_wait * hz); 69155539Sluoqi 69255539Sluoqi if (error == EWOULDBLOCK) 69355539Sluoqi printf("timed out\n"); 69455539Sluoqi else 69555539Sluoqi printf("stopped\n"); 69655539Sluoqi} 697