diff options
-rw-r--r-- | sys/amd64/amd64/dump_machdep.c | 121 | ||||
-rw-r--r-- | sys/dev/ata/ata-disk.c | 62 | ||||
-rw-r--r-- | sys/dev/ida/ida_disk.c | 7 | ||||
-rw-r--r-- | sys/dev/null/null.c | 18 | ||||
-rw-r--r-- | sys/dev/twe/twe_freebsd.c | 7 | ||||
-rw-r--r-- | sys/geom/geom_disk.c | 7 | ||||
-rw-r--r-- | sys/i386/i386/dump_machdep.c | 121 | ||||
-rw-r--r-- | sys/i386/i386/i386dump.c | 121 | ||||
-rw-r--r-- | sys/kern/kern_shutdown.c | 203 | ||||
-rw-r--r-- | sys/kern/subr_disk.c | 38 | ||||
-rw-r--r-- | sys/kern/subr_xxx.c | 3 | ||||
-rw-r--r-- | sys/sys/conf.h | 21 | ||||
-rw-r--r-- | sys/sys/disk.h | 1 | ||||
-rw-r--r-- | sys/sys/disklabel.h | 1 | ||||
-rw-r--r-- | sys/sys/diskmbr.h | 1 | ||||
-rw-r--r-- | sys/sys/diskpc98.h | 1 | ||||
-rw-r--r-- | sys/sys/linedisc.h | 21 | ||||
-rw-r--r-- | sys/sys/sysctl.h | 1 | ||||
-rw-r--r-- | sys/sys/systm.h | 3 |
19 files changed, 502 insertions, 256 deletions
diff --git a/sys/amd64/amd64/dump_machdep.c b/sys/amd64/amd64/dump_machdep.c new file mode 100644 index 0000000..b914af1 --- /dev/null +++ b/sys/amd64/amd64/dump_machdep.c @@ -0,0 +1,121 @@ +/*- + * Copyright (c) 2002 Poul-Henning Kamp + * Copyright (c) 2002 Networks Associates Technology, Inc. + * All rights reserved. + * + * This software was developed for the FreeBSD Project by Poul-Henning Kamp + * and NAI Labs, the Security Research Division of Network Associates, Inc. + * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the + * DARPA CHATS research program. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the authors may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/kernel.h> +#include <sys/kerneldump.h> +#include <vm/vm.h> +#include <vm/pmap.h> +#include <machine/md_var.h> + +static struct kerneldumpheader kdh; + +void +dumpsys(struct dumperinfo *di) +{ + off_t dumplo; + vm_offset_t a, addr; + u_int count, left, u; + void *va; + int i, mb; + + printf("Dumping %u MB\n", Maxmem / (1024*1024 / PAGE_SIZE)); + + if (sizeof kdh != 512) { + printf( + "Compiled struct kerneldumpheader is %d, not %d bytes\n", + sizeof kdh, 512); + return; + } + + /* Fill in the kernel dump header */ + strcpy(kdh.magic, KERNELDUMPMAGIC); + strcpy(kdh.architecture, "i386"); + kdh.version = KERNELDUMPVERSION; + kdh.architectureversion = KERNELDUMP_I386_VERSION; + kdh.dumplength = Maxmem * (off_t)PAGE_SIZE; + kdh.blocksize = di->blocksize; + kdh.dumptime = time_second; + strncpy(kdh.hostname, hostname, sizeof kdh.hostname); + strncpy(kdh.versionstring, version, sizeof kdh.versionstring); + if (panicstr != NULL) + strncpy(kdh.panicstring, panicstr, sizeof kdh.panicstring); + kdh.parity = kerneldump_parity(&kdh); + + dumplo = di->mediaoffset + di->mediasize - Maxmem * (off_t)PAGE_SIZE; + dumplo -= sizeof kdh * 2; + i = di->dumper(di->priv, &kdh, NULL, dumplo, sizeof kdh); + if (i) + printf("\nDump failed writing header (%d)\n", i); + dumplo += sizeof kdh; + i = 0; + addr = 0; + va = 0; + mb = 0; + for (count = 0; count < Maxmem;) { + left = Maxmem - count; + if (left > MAXDUMPPGS) + left = MAXDUMPPGS; + for (u = 0; u < left; u++) { + a = addr + u * PAGE_SIZE; + if (!is_physical_memory(a)) + a = 0; + va = pmap_kenter_temporary(trunc_page(a), u); + } + i = count / (16*1024*1024 / PAGE_SIZE); + if (i != mb) { + printf(" %d", count / (1024 * 1024 / PAGE_SIZE)); + mb = i; + } + i = di->dumper(di->priv, va, NULL, dumplo, left * PAGE_SIZE); + if (i) + break; + count += left; + dumplo += left * PAGE_SIZE; + addr += left * PAGE_SIZE; + } + if (i) + printf("\nDump failed writing data (%d)\n", i); + i = di->dumper(di->priv, &kdh, NULL, dumplo, sizeof kdh); + if (i) + printf("\nDump failed writing trailer (%d)\n", i); + di->dumper(di->priv, NULL, NULL, 0, 0); /* tell them we are done */ + printf("\nDump complete\n"); + return; +} diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c index 8a5ef87..8f21ea1 100644 --- a/sys/dev/ata/ata-disk.c +++ b/sys/dev/ata/ata-disk.c @@ -293,50 +293,29 @@ adstrategy(struct bio *bp) ata_start(adp->device->channel); } -int -addump(dev_t dev) +static int +addump(dev_t dev, void *virtual, vm_offset_t physical, off_t offset, size_t length) { struct ad_softc *adp = dev->si_drv1; struct ad_request request; - u_int count, blkno, secsize; - vm_offset_t addr = 0; - long blkcnt; - int dumppages = MAXDUMPPGS; - int error; - int i; - - if ((error = disk_dumpcheck(dev, &count, &blkno, &secsize))) - return error; - + static int once; + if (!adp) return ENXIO; - /* force PIO mode for dumps */ - adp->device->mode = ATA_PIO; - ata_reinit(adp->device->channel); - - blkcnt = howmany(PAGE_SIZE, secsize); - - while (count > 0) { - caddr_t va = NULL; - DELAY(1000); - - if ((count / blkcnt) < dumppages) - dumppages = count / blkcnt; - - for (i = 0; i < dumppages; ++i) { - vm_offset_t a = addr + (i * PAGE_SIZE); - if (is_physical_memory(a)) - va = pmap_kenter_temporary(trunc_page(a), i); - else - va = pmap_kenter_temporary(trunc_page(0), i); - } + if (!once) { + /* force PIO mode for dumps */ + adp->device->mode = ATA_PIO; + ata_reinit(adp->device->channel); + once = 1; + } + if (length > 0) { bzero(&request, sizeof(struct ad_request)); request.softc = adp; - request.blockaddr = blkno; - request.bytecount = PAGE_SIZE * dumppages; - request.data = va; + request.blockaddr = offset / DEV_BSIZE; + request.bytecount = length; + request.data = virtual; while (request.bytecount > 0) { ad_transfer(&request); @@ -346,17 +325,10 @@ addump(dev_t dev) request.bytecount -= request.currentsize; DELAY(20); } - - if (dumpstatus(addr, (off_t)count * DEV_BSIZE) < 0) - return EINTR; - - blkno += blkcnt * dumppages; - count -= blkcnt * dumppages; - addr += PAGE_SIZE * dumppages; + } else { + if (ata_wait(adp->device, ATA_S_READY | ATA_S_DSC) < 0) + ata_prtdev(adp->device, "timeout waiting for final ready\n"); } - - if (ata_wait(adp->device, ATA_S_READY | ATA_S_DSC) < 0) - ata_prtdev(adp->device, "timeout waiting for final ready\n"); return 0; } diff --git a/sys/dev/ida/ida_disk.c b/sys/dev/ida/ida_disk.c index 0a919d1..256b5aa 100644 --- a/sys/dev/ida/ida_disk.c +++ b/sys/dev/ida/ida_disk.c @@ -186,8 +186,12 @@ bad: } static int -idad_dump(dev_t dev) +idad_dump(dev_t dev, void *virtual, vm_offset_t physical, off_t offset, size_t length) { + + /* This needs modified to the new dump API */ + return (ENXIO); +#if 0 struct idad_softc *drv; u_int count, blkno, secsize; long blkcnt; @@ -231,6 +235,7 @@ idad_dump(dev_t dev) addr += PAGE_SIZE * dumppages; } return (0); +#endif } void diff --git a/sys/dev/null/null.c b/sys/dev/null/null.c index f7eaa77..ec0d521 100644 --- a/sys/dev/null/null.c +++ b/sys/dev/null/null.c @@ -33,6 +33,7 @@ #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/module.h> +#include <sys/disklabel.h> #include <sys/bus.h> #include <machine/bus.h> #include <machine/resource.h> @@ -43,6 +44,7 @@ static dev_t null_dev; static dev_t zero_dev; static d_write_t null_write; +static d_ioctl_t null_ioctl; static d_read_t zero_read; #define CDEV_MAJOR 2 @@ -54,7 +56,7 @@ static struct cdevsw null_cdevsw = { /* close */ (d_close_t *)nullop, /* read */ (d_read_t *)nullop, /* write */ null_write, - /* ioctl */ noioctl, + /* ioctl */ null_ioctl, /* poll */ nopoll, /* mmap */ nommap, /* strategy */ nostrategy, @@ -91,6 +93,20 @@ null_write(dev_t dev, struct uio *uio, int flag) } static int +null_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td) +{ + int error; + + if (cmd != DIOCGKERNELDUMP) + return (noioctl(dev, cmd, data, fflag, td)); + error = suser_td(td); + if (error) + return (error); + return (set_dumper(NULL)); +} + + +static int zero_read(dev_t dev, struct uio *uio, int flag) { u_int c; diff --git a/sys/dev/twe/twe_freebsd.c b/sys/dev/twe/twe_freebsd.c index 1fffe4e..403d9d8 100644 --- a/sys/dev/twe/twe_freebsd.c +++ b/sys/dev/twe/twe_freebsd.c @@ -701,8 +701,12 @@ twed_strategy(twe_bio *bp) * System crashdump support */ int -twed_dump(dev_t dev) +twed_dump(dev_t dev, void *virtual, vm_offset_t physical, off_t offset, size_t length) { + + /* XXX: this needs modified to the new dump API */ + return (ENXIO); +#if 0 struct twed_softc *twed_sc = (struct twed_softc *)dev->si_drv1; struct twe_softc *twe_sc = (struct twe_softc *)twed_sc->twed_controller; u_int count, blkno, secsize; @@ -747,6 +751,7 @@ twed_dump(dev_t dev) addr += PAGE_SIZE * dumppages; } return(0); +#endif } /******************************************************************************** diff --git a/sys/geom/geom_disk.c b/sys/geom/geom_disk.c index 11bbd60..c02e8a5 100644 --- a/sys/geom/geom_disk.c +++ b/sys/geom/geom_disk.c @@ -228,13 +228,6 @@ disk_invalidate (struct disk *disk) { } -int -disk_dumpcheck(dev_t dev, u_int *count, u_int *blkno, u_int *secsize) -{ - - return (ENXIO); -} - SYSCTL_INT(_debug_sizeof, OID_AUTO, disklabel, CTLFLAG_RD, 0, sizeof(struct disklabel), "sizeof(struct disklabel)"); diff --git a/sys/i386/i386/dump_machdep.c b/sys/i386/i386/dump_machdep.c new file mode 100644 index 0000000..b914af1 --- /dev/null +++ b/sys/i386/i386/dump_machdep.c @@ -0,0 +1,121 @@ +/*- + * Copyright (c) 2002 Poul-Henning Kamp + * Copyright (c) 2002 Networks Associates Technology, Inc. + * All rights reserved. + * + * This software was developed for the FreeBSD Project by Poul-Henning Kamp + * and NAI Labs, the Security Research Division of Network Associates, Inc. + * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the + * DARPA CHATS research program. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the authors may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/kernel.h> +#include <sys/kerneldump.h> +#include <vm/vm.h> +#include <vm/pmap.h> +#include <machine/md_var.h> + +static struct kerneldumpheader kdh; + +void +dumpsys(struct dumperinfo *di) +{ + off_t dumplo; + vm_offset_t a, addr; + u_int count, left, u; + void *va; + int i, mb; + + printf("Dumping %u MB\n", Maxmem / (1024*1024 / PAGE_SIZE)); + + if (sizeof kdh != 512) { + printf( + "Compiled struct kerneldumpheader is %d, not %d bytes\n", + sizeof kdh, 512); + return; + } + + /* Fill in the kernel dump header */ + strcpy(kdh.magic, KERNELDUMPMAGIC); + strcpy(kdh.architecture, "i386"); + kdh.version = KERNELDUMPVERSION; + kdh.architectureversion = KERNELDUMP_I386_VERSION; + kdh.dumplength = Maxmem * (off_t)PAGE_SIZE; + kdh.blocksize = di->blocksize; + kdh.dumptime = time_second; + strncpy(kdh.hostname, hostname, sizeof kdh.hostname); + strncpy(kdh.versionstring, version, sizeof kdh.versionstring); + if (panicstr != NULL) + strncpy(kdh.panicstring, panicstr, sizeof kdh.panicstring); + kdh.parity = kerneldump_parity(&kdh); + + dumplo = di->mediaoffset + di->mediasize - Maxmem * (off_t)PAGE_SIZE; + dumplo -= sizeof kdh * 2; + i = di->dumper(di->priv, &kdh, NULL, dumplo, sizeof kdh); + if (i) + printf("\nDump failed writing header (%d)\n", i); + dumplo += sizeof kdh; + i = 0; + addr = 0; + va = 0; + mb = 0; + for (count = 0; count < Maxmem;) { + left = Maxmem - count; + if (left > MAXDUMPPGS) + left = MAXDUMPPGS; + for (u = 0; u < left; u++) { + a = addr + u * PAGE_SIZE; + if (!is_physical_memory(a)) + a = 0; + va = pmap_kenter_temporary(trunc_page(a), u); + } + i = count / (16*1024*1024 / PAGE_SIZE); + if (i != mb) { + printf(" %d", count / (1024 * 1024 / PAGE_SIZE)); + mb = i; + } + i = di->dumper(di->priv, va, NULL, dumplo, left * PAGE_SIZE); + if (i) + break; + count += left; + dumplo += left * PAGE_SIZE; + addr += left * PAGE_SIZE; + } + if (i) + printf("\nDump failed writing data (%d)\n", i); + i = di->dumper(di->priv, &kdh, NULL, dumplo, sizeof kdh); + if (i) + printf("\nDump failed writing trailer (%d)\n", i); + di->dumper(di->priv, NULL, NULL, 0, 0); /* tell them we are done */ + printf("\nDump complete\n"); + return; +} diff --git a/sys/i386/i386/i386dump.c b/sys/i386/i386/i386dump.c new file mode 100644 index 0000000..b914af1 --- /dev/null +++ b/sys/i386/i386/i386dump.c @@ -0,0 +1,121 @@ +/*- + * Copyright (c) 2002 Poul-Henning Kamp + * Copyright (c) 2002 Networks Associates Technology, Inc. + * All rights reserved. + * + * This software was developed for the FreeBSD Project by Poul-Henning Kamp + * and NAI Labs, the Security Research Division of Network Associates, Inc. + * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the + * DARPA CHATS research program. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the authors may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/kernel.h> +#include <sys/kerneldump.h> +#include <vm/vm.h> +#include <vm/pmap.h> +#include <machine/md_var.h> + +static struct kerneldumpheader kdh; + +void +dumpsys(struct dumperinfo *di) +{ + off_t dumplo; + vm_offset_t a, addr; + u_int count, left, u; + void *va; + int i, mb; + + printf("Dumping %u MB\n", Maxmem / (1024*1024 / PAGE_SIZE)); + + if (sizeof kdh != 512) { + printf( + "Compiled struct kerneldumpheader is %d, not %d bytes\n", + sizeof kdh, 512); + return; + } + + /* Fill in the kernel dump header */ + strcpy(kdh.magic, KERNELDUMPMAGIC); + strcpy(kdh.architecture, "i386"); + kdh.version = KERNELDUMPVERSION; + kdh.architectureversion = KERNELDUMP_I386_VERSION; + kdh.dumplength = Maxmem * (off_t)PAGE_SIZE; + kdh.blocksize = di->blocksize; + kdh.dumptime = time_second; + strncpy(kdh.hostname, hostname, sizeof kdh.hostname); + strncpy(kdh.versionstring, version, sizeof kdh.versionstring); + if (panicstr != NULL) + strncpy(kdh.panicstring, panicstr, sizeof kdh.panicstring); + kdh.parity = kerneldump_parity(&kdh); + + dumplo = di->mediaoffset + di->mediasize - Maxmem * (off_t)PAGE_SIZE; + dumplo -= sizeof kdh * 2; + i = di->dumper(di->priv, &kdh, NULL, dumplo, sizeof kdh); + if (i) + printf("\nDump failed writing header (%d)\n", i); + dumplo += sizeof kdh; + i = 0; + addr = 0; + va = 0; + mb = 0; + for (count = 0; count < Maxmem;) { + left = Maxmem - count; + if (left > MAXDUMPPGS) + left = MAXDUMPPGS; + for (u = 0; u < left; u++) { + a = addr + u * PAGE_SIZE; + if (!is_physical_memory(a)) + a = 0; + va = pmap_kenter_temporary(trunc_page(a), u); + } + i = count / (16*1024*1024 / PAGE_SIZE); + if (i != mb) { + printf(" %d", count / (1024 * 1024 / PAGE_SIZE)); + mb = i; + } + i = di->dumper(di->priv, va, NULL, dumplo, left * PAGE_SIZE); + if (i) + break; + count += left; + dumplo += left * PAGE_SIZE; + addr += left * PAGE_SIZE; + } + if (i) + printf("\nDump failed writing data (%d)\n", i); + i = di->dumper(di->priv, &kdh, NULL, dumplo, sizeof kdh); + if (i) + printf("\nDump failed writing trailer (%d)\n", i); + di->dumper(di->priv, NULL, NULL, 0, 0); /* tell them we are done */ + printf("\nDump complete\n"); + return; +} diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c index 80cb9e6..66f3911 100644 --- a/sys/kern/kern_shutdown.c +++ b/sys/kern/kern_shutdown.c @@ -64,7 +64,6 @@ #include <sys/sysproto.h> #include <sys/vnode.h> -#include <machine/pcb.h> #include <machine/md_var.h> #include <machine/smp.h> @@ -116,11 +115,10 @@ watchdog_tickle_fn wdog_tickler = NULL; */ const char *panicstr; -int dumping; /* system is dumping */ -dev_t dumpdev = NODEV; +int dumping; /* system is dumping */ +static struct dumperinfo dumper; /* our selected dumper */ static void boot(int) __dead2; -static void dumpsys(void); static void poweroff_wait(void *, int); static void shutdown_halt(void *junk, int howto); static void shutdown_panic(void *junk, int howto); @@ -178,7 +176,6 @@ shutdown_nice(int howto) return; } static int waittime = -1; -static struct pcb dumppcb; static void print_uptime(void) @@ -334,8 +331,11 @@ boot(int howto) */ EVENTHANDLER_INVOKE(shutdown_post_sync, howto); splhigh(); - if ((howto & (RB_HALT|RB_DUMP)) == RB_DUMP && !cold) - dumpsys(); + if ((howto & (RB_HALT|RB_DUMP)) == RB_DUMP && + !cold && dumper.dumper != NULL && !dumping) { + dumping++; + dumpsys(&dumper); + } /* Now that we're going to really halt the system... */ EVENTHANDLER_INVOKE(shutdown_final, howto); @@ -412,172 +412,6 @@ shutdown_reset(void *junk, int howto) /* NOTREACHED */ /* assuming reset worked */ } -/* - * Magic number for savecore - * - * exported (symorder) and used at least by savecore(8) - * - */ -static u_long const dumpmag = 0x8fca0101UL; - -static int dumpsize = 0; /* also for savecore */ - -static int dodump = 1; - -SYSCTL_INT(_machdep, OID_AUTO, do_dump, CTLFLAG_RW, &dodump, 0, - "Try to perform coredump on kernel panic"); - -static int -setdumpdev(dev_t dev) -{ - int psize; - long newdumplo; - - if (dev == NODEV) { - dumpdev = dev; - return (0); - } - if (devsw(dev) == NULL) - return (ENXIO); /* XXX is this right? */ - if (devsw(dev)->d_psize == NULL) - return (ENXIO); /* XXX should be ENODEV ? */ - psize = devsw(dev)->d_psize(dev); - if (psize == -1) - return (ENXIO); /* XXX should be ENODEV ? */ - /* - * XXX should clean up checking in dumpsys() to be more like this. - */ - newdumplo = psize - Maxmem * (PAGE_SIZE / DEV_BSIZE); - if (newdumplo <= LABELSECTOR) - return (ENOSPC); - dumpdev = dev; - dumplo = newdumplo; - return (0); -} - - -/* ARGSUSED */ -static void -dump_conf(void *dummy) -{ - char *path; - dev_t dev; - - path = malloc(MNAMELEN, M_TEMP, M_WAITOK); - if (TUNABLE_STR_FETCH("dumpdev", path, MNAMELEN) != 0) { - dev = getdiskbyname(path); - if (dev != NODEV) - dumpdev = dev; - } - free(path, M_TEMP); - if (setdumpdev(dumpdev) != 0) - dumpdev = NODEV; -} - -SYSINIT(dump_conf, SI_SUB_DUMP_CONF, SI_ORDER_FIRST, dump_conf, NULL) - -static int -sysctl_kern_dumpdev(SYSCTL_HANDLER_ARGS) -{ - int error; - udev_t ndumpdev; - - ndumpdev = dev2udev(dumpdev); - error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req); - if (error == 0 && req->newptr != NULL) - error = setdumpdev(udev2dev(ndumpdev, 0)); - return (error); -} - -SYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW, - 0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", ""); - -/* - * Doadump comes here after turning off memory management and - * getting on the dump stack, either when called above, or by - * the auto-restart code. - */ -static void -dumpsys(void) -{ - int error; - - savectx(&dumppcb); - if (!dodump) - return; - if (dumpdev == NODEV) - return; - if (!(devsw(dumpdev))) - return; - if (!(devsw(dumpdev)->d_dump)) - return; - if (dumping++) { - dumping--; - printf("Dump already in progress, bailing...\n"); - return; - } - dumpsize = Maxmem; - printf("\ndumping to dev %s, offset %ld\n", devtoname(dumpdev), dumplo); - printf("dump "); - error = (*devsw(dumpdev)->d_dump)(dumpdev); - dumping--; - if (error == 0) { - printf("succeeded\n"); - return; - } - printf("failed, reason: "); - switch (error) { - case ENODEV: - printf("device doesn't support a dump routine\n"); - break; - - case ENXIO: - printf("device bad\n"); - break; - - case EFAULT: - printf("device not ready\n"); - break; - - case EINVAL: - printf("area improper\n"); - break; - - case EIO: - printf("i/o error\n"); - break; - - case EINTR: - printf("aborted from console\n"); - break; - - default: - printf("unknown, error = %d\n", error); - break; - } -} - -int -dumpstatus(vm_offset_t addr, off_t count) -{ - int c; - - if (addr % (1024 * 1024) == 0) { -#ifdef HW_WDOG - if (wdog_tickler) - (*wdog_tickler)(); -#endif - printf("%ld ", (long)(count / (1024 * 1024))); - } - - if ((c = cncheckc()) == 0x03) - return -1; - else if (c != -1) - printf("[CTRL-C to abort] "); - - return 0; -} - #ifdef SMP static u_int panic_cpu = NOCPU; #endif @@ -697,3 +531,26 @@ kproc_shutdown(void *arg, int howto) else printf("stopped\n"); } + +/* Registration of dumpers */ +int +set_dumper(struct dumperinfo *di) +{ + if (di == NULL) { + bzero(&dumper, sizeof dumper); + return (0); + } + if (dumper.dumper != NULL) + return (EBUSY); + dumper = *di; + return (0); +} + +#ifndef __i386__ +void +dumpsys(struct dumperinfo *di __unused) +{ + + printf("Kernel dumps not implemented on this architecture\n"); +} +#endif diff --git a/sys/kern/subr_disk.c b/sys/kern/subr_disk.c index a4ef2d8..155cfc3 100644 --- a/sys/kern/subr_disk.c +++ b/sys/kern/subr_disk.c @@ -198,31 +198,26 @@ disk_create(int unit, struct disk *dp, int flags, struct cdevsw *cdevsw, struct return (dev); } -int -disk_dumpcheck(dev_t dev, u_int *count, u_int *blkno, u_int *secsize) +static int +diskdumpconf(u_int onoff, dev_t dev, struct disk *dp) { - struct disk *dp; + struct dumperinfo di; struct disklabel *dl; - u_int boff; - dp = dev->si_disk; - if (!dp) - return (ENXIO); - if (!dp->d_slice) - return (ENXIO); + if (!onoff) + return(set_dumper(NULL)); dl = dsgetlabel(dev, dp->d_slice); if (!dl) return (ENXIO); - *count = Maxmem * (PAGE_SIZE / dl->d_secsize); - if (dumplo <= LABELSECTOR || - (dumplo + *count > dl->d_partitions[dkpart(dev)].p_size)) - return (EINVAL); - boff = dl->d_partitions[dkpart(dev)].p_offset + - dp->d_slice->dss_slices[dkslice(dev)].ds_offset; - *blkno = boff + dumplo; - *secsize = dl->d_secsize; - return (0); - + bzero(&di, sizeof di); + di.dumper = (dumper_t *)dp->d_devsw->d_dump; + di.priv = dp->d_dev; + di.blocksize = dl->d_secsize; + di.mediaoffset = (off_t)(dl->d_partitions[dkpart(dev)].p_offset + + dp->d_slice->dss_slices[dkslice(dev)].ds_offset) * DEV_BSIZE; + di.mediasize = + (off_t)(dl->d_partitions[dkpart(dev)].p_size) * DEV_BSIZE; + return(set_dumper(&di)); } void @@ -388,12 +383,17 @@ diskioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td) { struct disk *dp; int error; + u_int u; dev_t pdev; pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); dp = pdev->si_disk; if (!dp) return (ENXIO); + if (cmd == DIOCGKERNELDUMP) { + u = *(u_int *)data; + return (diskdumpconf(u, dev, dp)); + } error = dsioctl(dev, cmd, data, fflag, &dp->d_slice); if (error == ENOIOCTL) error = dp->d_devsw->d_ioctl(dev, cmd, data, fflag, td); diff --git a/sys/kern/subr_xxx.c b/sys/kern/subr_xxx.c index 7eb169c..c9d2676 100644 --- a/sys/kern/subr_xxx.c +++ b/sys/kern/subr_xxx.c @@ -143,8 +143,7 @@ nommap(dev, offset, nprot) } int -nodump(dev) - dev_t dev; +nodump(dev_t dev, void *virtual __unused, vm_offset_t physical __unused, off_t offset __unused, size_t length __unused) { return (ENODEV); diff --git a/sys/sys/conf.h b/sys/sys/conf.h index c4a2a86..fc3b586 100644 --- a/sys/sys/conf.h +++ b/sys/sys/conf.h @@ -139,7 +139,7 @@ typedef int d_close_t(dev_t dev, int fflag, int devtype, struct thread *td); typedef void d_strategy_t(struct bio *bp); typedef int d_ioctl_t(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td); -typedef int d_dump_t(dev_t dev); +typedef int d_dump_t(dev_t dev,void *virtual, vm_offset_t physical, off_t offset, size_t length); typedef int d_psize_t(dev_t dev); typedef int d_read_t(dev_t dev, struct uio *uio, int ioflag); @@ -354,6 +354,25 @@ typedef void (*dev_clone_fn)(void *arg, char *name, int namelen, dev_t *result); int dev_stdclone(char *name, char **namep, const char *stem, int *unit); EVENTHANDLER_DECLARE(dev_clone, dev_clone_fn); +/* Stuff relating to kernel-dump */ + +typedef int dumper_t( + void *priv, /* Private to the driver. */ + void *virtual, /* Virtual (mapped) address. */ + vm_offset_t physical, /* Physical address of virtual. */ + off_t offset, /* Byte-offset to write at. */ + size_t length); /* Number of bytes to dump. */ + +struct dumperinfo { + dumper_t *dumper; /* Dumping function. */ + void *priv; /* Private parts. */ + u_int blocksize; /* Size of block in bytes. */ + off_t mediaoffset; /* Initial offset in bytes. */ + off_t mediasize; /* Space available in bytes. */ +}; + +int set_dumper(struct dumperinfo *); +void dumpsys(struct dumperinfo *); extern int dumping; /* system is dumping */ #endif /* _KERNEL */ diff --git a/sys/sys/disk.h b/sys/sys/disk.h index b224740..128e582 100644 --- a/sys/sys/disk.h +++ b/sys/sys/disk.h @@ -39,7 +39,6 @@ struct disk { dev_t disk_create(int unit, struct disk *disk, int flags, struct cdevsw *cdevsw, struct cdevsw *diskdevsw); void disk_destroy(dev_t dev); -int disk_dumpcheck(dev_t dev, u_int *count, u_int *blkno, u_int *secsize); struct disk *disk_enumerate(struct disk *disk); void disk_invalidate(struct disk *disk); diff --git a/sys/sys/disklabel.h b/sys/sys/disklabel.h index a4e0751..643ebac 100644 --- a/sys/sys/disklabel.h +++ b/sys/sys/disklabel.h @@ -436,6 +436,7 @@ struct dos_partition { #define DIOCGFWSECTORS _IOR('d', 130, u_int) /* Get firmware sectorcount */ #define DIOCGFWHEADS _IOR('d', 131, u_int) /* Get firmware headcount */ #define DIOCGFWCYLINDERS _IOR('d', 132, u_int) /* Get firmware cyl'scount */ +#define DIOCGKERNELDUMP _IOW('d', 133, u_int) /* Set/Clear kernel dumps */ #ifdef _KERNEL diff --git a/sys/sys/diskmbr.h b/sys/sys/diskmbr.h index a4e0751..643ebac 100644 --- a/sys/sys/diskmbr.h +++ b/sys/sys/diskmbr.h @@ -436,6 +436,7 @@ struct dos_partition { #define DIOCGFWSECTORS _IOR('d', 130, u_int) /* Get firmware sectorcount */ #define DIOCGFWHEADS _IOR('d', 131, u_int) /* Get firmware headcount */ #define DIOCGFWCYLINDERS _IOR('d', 132, u_int) /* Get firmware cyl'scount */ +#define DIOCGKERNELDUMP _IOW('d', 133, u_int) /* Set/Clear kernel dumps */ #ifdef _KERNEL diff --git a/sys/sys/diskpc98.h b/sys/sys/diskpc98.h index a4e0751..643ebac 100644 --- a/sys/sys/diskpc98.h +++ b/sys/sys/diskpc98.h @@ -436,6 +436,7 @@ struct dos_partition { #define DIOCGFWSECTORS _IOR('d', 130, u_int) /* Get firmware sectorcount */ #define DIOCGFWHEADS _IOR('d', 131, u_int) /* Get firmware headcount */ #define DIOCGFWCYLINDERS _IOR('d', 132, u_int) /* Get firmware cyl'scount */ +#define DIOCGKERNELDUMP _IOW('d', 133, u_int) /* Set/Clear kernel dumps */ #ifdef _KERNEL diff --git a/sys/sys/linedisc.h b/sys/sys/linedisc.h index c4a2a86..fc3b586 100644 --- a/sys/sys/linedisc.h +++ b/sys/sys/linedisc.h @@ -139,7 +139,7 @@ typedef int d_close_t(dev_t dev, int fflag, int devtype, struct thread *td); typedef void d_strategy_t(struct bio *bp); typedef int d_ioctl_t(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td); -typedef int d_dump_t(dev_t dev); +typedef int d_dump_t(dev_t dev,void *virtual, vm_offset_t physical, off_t offset, size_t length); typedef int d_psize_t(dev_t dev); typedef int d_read_t(dev_t dev, struct uio *uio, int ioflag); @@ -354,6 +354,25 @@ typedef void (*dev_clone_fn)(void *arg, char *name, int namelen, dev_t *result); int dev_stdclone(char *name, char **namep, const char *stem, int *unit); EVENTHANDLER_DECLARE(dev_clone, dev_clone_fn); +/* Stuff relating to kernel-dump */ + +typedef int dumper_t( + void *priv, /* Private to the driver. */ + void *virtual, /* Virtual (mapped) address. */ + vm_offset_t physical, /* Physical address of virtual. */ + off_t offset, /* Byte-offset to write at. */ + size_t length); /* Number of bytes to dump. */ + +struct dumperinfo { + dumper_t *dumper; /* Dumping function. */ + void *priv; /* Private parts. */ + u_int blocksize; /* Size of block in bytes. */ + off_t mediaoffset; /* Initial offset in bytes. */ + off_t mediasize; /* Space available in bytes. */ +}; + +int set_dumper(struct dumperinfo *); +void dumpsys(struct dumperinfo *); extern int dumping; /* system is dumping */ #endif /* _KERNEL */ diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index 086381f..65275d6 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -372,7 +372,6 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry); { "bootfile", CTLTYPE_STRING }, \ { "maxfilesperproc", CTLTYPE_INT }, \ { "maxprocperuid", CTLTYPE_INT }, \ - { "dumpdev", CTLTYPE_STRUCT }, /* we lie; don't print as int */ \ { "ipc", CTLTYPE_NODE }, \ { "dummy", CTLTYPE_INT }, \ { "ps_strings", CTLTYPE_INT }, \ diff --git a/sys/sys/systm.h b/sys/sys/systm.h index dfbba68..f98d1d7 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -62,9 +62,6 @@ extern struct cv selwait; /* select conditional variable */ extern int physmem; /* physical memory */ -extern dev_t dumpdev; /* dump device */ -extern long dumplo; /* offset into dumpdev */ - extern dev_t rootdev; /* root device */ extern dev_t rootdevs[2]; /* possible root devices */ extern char *rootdevnames[2]; /* names of possible root devices */ |