summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/amd64/amd64/dump_machdep.c121
-rw-r--r--sys/dev/ata/ata-disk.c62
-rw-r--r--sys/dev/ida/ida_disk.c7
-rw-r--r--sys/dev/null/null.c18
-rw-r--r--sys/dev/twe/twe_freebsd.c7
-rw-r--r--sys/geom/geom_disk.c7
-rw-r--r--sys/i386/i386/dump_machdep.c121
-rw-r--r--sys/i386/i386/i386dump.c121
-rw-r--r--sys/kern/kern_shutdown.c203
-rw-r--r--sys/kern/subr_disk.c38
-rw-r--r--sys/kern/subr_xxx.c3
-rw-r--r--sys/sys/conf.h21
-rw-r--r--sys/sys/disk.h1
-rw-r--r--sys/sys/disklabel.h1
-rw-r--r--sys/sys/diskmbr.h1
-rw-r--r--sys/sys/diskpc98.h1
-rw-r--r--sys/sys/linedisc.h21
-rw-r--r--sys/sys/sysctl.h1
-rw-r--r--sys/sys/systm.h3
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 */
OpenPOWER on IntegriCloud