summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorps <ps@FreeBSD.org>2000-10-17 10:05:49 +0000
committerps <ps@FreeBSD.org>2000-10-17 10:05:49 +0000
commitc71ac689e04ce39d113325e3854477539dae464c (patch)
tree331cd4cbe2e1e3d9d7734fa4fce3e6a5554d434c
parent26207dd1489dfcba9ad2215401292904446e000a (diff)
downloadFreeBSD-src-c71ac689e04ce39d113325e3854477539dae464c.zip
FreeBSD-src-c71ac689e04ce39d113325e3854477539dae464c.tar.gz
Implement write combining for crashdumps. This is useful when
write caching is disabled on both SCSI and IDE disks where large memory dumps could take up to an hour to complete. Taking an i386 scsi based system with 512MB of ram and timing (in seconds) how long it took to complete a dump, the following results were obtained: Before: After: WCE TIME WCE TIME ------------------ ------------------ 1 141.820972 1 15.600111 0 797.265072 0 65.480465 Obtained from: Yahoo! Reviewed by: peter
-rw-r--r--sys/alpha/alpha/pmap.c4
-rw-r--r--sys/alpha/include/param.h1
-rw-r--r--sys/amd64/amd64/pmap.c17
-rw-r--r--sys/cam/scsi/scsi_da.c27
-rw-r--r--sys/dev/ata/ata-disk.c28
-rw-r--r--sys/i386/i386/pmap.c17
-rw-r--r--sys/i386/include/param.h1
-rw-r--r--sys/ia64/ia64/pmap.c4
-rw-r--r--sys/ia64/include/param.h1
-rw-r--r--sys/vm/pmap.h2
10 files changed, 73 insertions, 29 deletions
diff --git a/sys/alpha/alpha/pmap.c b/sys/alpha/alpha/pmap.c
index bdfd725..8164ca6 100644
--- a/sys/alpha/alpha/pmap.c
+++ b/sys/alpha/alpha/pmap.c
@@ -2223,9 +2223,9 @@ retry:
* during dump.
*/
void *
-pmap_kenter_temporary(vm_offset_t pa)
+pmap_kenter_temporary(vm_offset_t pa, int i)
{
- return (void *) ALPHA_PHYS_TO_K0SEG(pa);
+ return (void *) ALPHA_PHYS_TO_K0SEG(pa - (i * PAGE_SIZE));
}
#define MAX_INIT_PT (96)
diff --git a/sys/alpha/include/param.h b/sys/alpha/include/param.h
index efd4efe..ae641f6 100644
--- a/sys/alpha/include/param.h
+++ b/sys/alpha/include/param.h
@@ -107,6 +107,7 @@
#endif
#define DFLTPHYS (64 * 1024) /* default max raw I/O transfer size */
#define MAXPHYS (128 * 1024) /* max raw I/O transfer size */
+#define MAXDUMPPGS (DFLTPHYS/PAGE_SIZE)
#define CLSIZE 1
#define CLSIZELOG2 0
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index 523ef5d..3d8bbb2 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -182,6 +182,12 @@ static caddr_t CADDR2;
static pt_entry_t *msgbufmap;
struct msgbuf *msgbufp=0;
+/*
+ * Crashdump maps.
+ */
+static pt_entry_t *pt_crashdumpmap;
+static caddr_t crashdumpmap;
+
#ifdef SMP
extern pt_entry_t *SMPpt;
#else
@@ -334,6 +340,11 @@ pmap_bootstrap(firstaddr, loadaddr)
SYSMAP(caddr_t, CMAP2, CADDR2, 1)
/*
+ * Crashdump maps.
+ */
+ SYSMAP(caddr_t, pt_crashdumpmap, crashdumpmap, MAXDUMPPGS);
+
+ /*
* ptvmmap is used for reading arbitrary physical pages via /dev/mem.
* XXX ptmmap is not used.
*/
@@ -2231,10 +2242,10 @@ retry:
* to be used for panic dumps.
*/
void *
-pmap_kenter_temporary(vm_offset_t pa)
+pmap_kenter_temporary(vm_offset_t pa, int i)
{
- pmap_kenter((vm_offset_t)CADDR1, pa);
- return ((void *)CADDR1);
+ pmap_kenter((vm_offset_t)crashdumpmap + (i * PAGE_SIZE), pa);
+ return ((void *)crashdumpmap);
}
#define MAX_INIT_PT (96)
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index cc5ada2..45d3d76 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -634,7 +634,9 @@ dadump(dev_t dev)
long blkcnt;
vm_offset_t addr;
struct ccb_scsiio csio;
+ int dumppages = MAXDUMPPGS;
int error;
+ int i;
/* toss any characters present prior to dump */
while (cncheckc() != -1)
@@ -659,12 +661,17 @@ dadump(dev_t dev)
blkcnt = howmany(PAGE_SIZE, secsize);
while (num > 0) {
- void *va;
+ caddr_t va;
- if (is_physical_memory(addr)) {
- va = pmap_kenter_temporary(trunc_page(addr));
- } else {
- va = pmap_kenter_temporary(trunc_page(0));
+ if ((num / blkcnt) < dumppages)
+ dumppages = num / 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);
}
xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1);
@@ -677,9 +684,9 @@ dadump(dev_t dev)
/*byte2*/0,
/*minimum_cmd_size*/ softc->minimum_cmd_size,
blknum,
- blkcnt,
+ blkcnt * dumppages,
/*data_ptr*/(u_int8_t *) va,
- /*dxfer_len*/blkcnt * secsize,
+ /*dxfer_len*/blkcnt * secsize * dumppages,
/*sense_len*/SSD_FULL_SIZE,
DA_DEFAULT_TIMEOUT * 1000);
xpt_polled_action((union ccb *)&csio);
@@ -706,9 +713,9 @@ dadump(dev_t dev)
}
/* update block count */
- num -= blkcnt;
- blknum += blkcnt;
- addr += PAGE_SIZE;
+ num -= blkcnt * dumppages;
+ blknum += blkcnt * dumppages;
+ addr += PAGE_SIZE * dumppages;
/* operator aborting dump? */
if (cncheckc() != -1)
diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c
index dba5fbe..85421c2 100644
--- a/sys/dev/ata/ata-disk.c
+++ b/sys/dev/ata/ata-disk.c
@@ -257,7 +257,10 @@ addump(dev_t dev)
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;
@@ -269,18 +272,27 @@ addump(dev_t dev)
adp->controller->mode[ATA_DEV(adp->unit)] = ATA_PIO;
ata_reinit(adp->controller);
+ blkcnt = howmany(PAGE_SIZE, secsize);
+
while (count > 0) {
caddr_t va;
DELAY(1000);
- if (is_physical_memory(addr))
- va = pmap_kenter_temporary(trunc_page(addr));
- else
- va = pmap_kenter_temporary(trunc_page(0));
+
+ 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);
+ }
bzero(&request, sizeof(struct ad_request));
request.device = adp;
request.blockaddr = blkno;
- request.bytecount = PAGE_SIZE;
+ request.bytecount = PAGE_SIZE * dumppages;
request.data = va;
while (request.bytecount > 0) {
@@ -300,9 +312,9 @@ addump(dev_t dev)
printf("%ld ", (long)(count * DEV_BSIZE) / (1024 * 1024));
}
- blkno += howmany(PAGE_SIZE, secsize);
- count -= howmany(PAGE_SIZE, secsize);
- addr += PAGE_SIZE;
+ blkno += blkcnt * dumppages;
+ count -= blkcnt * dumppages;
+ addr += PAGE_SIZE * dumppages;
if (cncheckc() != -1)
return EINTR;
}
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index 523ef5d..3d8bbb2 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -182,6 +182,12 @@ static caddr_t CADDR2;
static pt_entry_t *msgbufmap;
struct msgbuf *msgbufp=0;
+/*
+ * Crashdump maps.
+ */
+static pt_entry_t *pt_crashdumpmap;
+static caddr_t crashdumpmap;
+
#ifdef SMP
extern pt_entry_t *SMPpt;
#else
@@ -334,6 +340,11 @@ pmap_bootstrap(firstaddr, loadaddr)
SYSMAP(caddr_t, CMAP2, CADDR2, 1)
/*
+ * Crashdump maps.
+ */
+ SYSMAP(caddr_t, pt_crashdumpmap, crashdumpmap, MAXDUMPPGS);
+
+ /*
* ptvmmap is used for reading arbitrary physical pages via /dev/mem.
* XXX ptmmap is not used.
*/
@@ -2231,10 +2242,10 @@ retry:
* to be used for panic dumps.
*/
void *
-pmap_kenter_temporary(vm_offset_t pa)
+pmap_kenter_temporary(vm_offset_t pa, int i)
{
- pmap_kenter((vm_offset_t)CADDR1, pa);
- return ((void *)CADDR1);
+ pmap_kenter((vm_offset_t)crashdumpmap + (i * PAGE_SIZE), pa);
+ return ((void *)crashdumpmap);
}
#define MAX_INIT_PT (96)
diff --git a/sys/i386/include/param.h b/sys/i386/include/param.h
index bac527e..0d17297 100644
--- a/sys/i386/include/param.h
+++ b/sys/i386/include/param.h
@@ -96,6 +96,7 @@
#endif
#define DFLTPHYS (64 * 1024) /* default max raw I/O transfer size */
#define MAXPHYS (128 * 1024) /* max raw I/O transfer size */
+#define MAXDUMPPGS (DFLTPHYS/PAGE_SIZE)
#define IOPAGES 2 /* pages of i/o permission bitmap */
#define UPAGES 2 /* pages of u-area */
diff --git a/sys/ia64/ia64/pmap.c b/sys/ia64/ia64/pmap.c
index ea7a928..b438906 100644
--- a/sys/ia64/ia64/pmap.c
+++ b/sys/ia64/ia64/pmap.c
@@ -1478,9 +1478,9 @@ pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m)
* during dump.
*/
void *
-pmap_kenter_temporary(vm_offset_t pa)
+pmap_kenter_temporary(vm_offset_t pa, int i)
{
- return (void *) IA64_PHYS_TO_RR7(pa);
+ return (void *) IA64_PHYS_TO_RR7(pa - (i * PAGE_SIZE));
}
#define MAX_INIT_PT (96)
diff --git a/sys/ia64/include/param.h b/sys/ia64/include/param.h
index 577356a..f061848 100644
--- a/sys/ia64/include/param.h
+++ b/sys/ia64/include/param.h
@@ -103,6 +103,7 @@
#endif
#define DFLTPHYS (64 * 1024) /* default max raw I/O transfer size */
#define MAXPHYS (128 * 1024) /* max raw I/O transfer size */
+#define MAXDUMPPGS (DFLTPHYS/PAGE_SIZE)
#define CLSIZE 1
#define CLSIZELOG2 0
diff --git a/sys/vm/pmap.h b/sys/vm/pmap.h
index b6afa93..1aca49d 100644
--- a/sys/vm/pmap.h
+++ b/sys/vm/pmap.h
@@ -140,7 +140,7 @@ void pmap_swapout_proc __P((struct proc *p));
void pmap_swapin_proc __P((struct proc *p));
void pmap_activate __P((struct proc *p));
vm_offset_t pmap_addr_hint __P((vm_object_t obj, vm_offset_t addr, vm_size_t size));
-void *pmap_kenter_temporary __P((vm_offset_t pa));
+void *pmap_kenter_temporary __P((vm_offset_t pa, int i));
void pmap_init2 __P((void));
#endif /* _KERNEL */
OpenPOWER on IntegriCloud