Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145312636
D904.id1988.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
80 KB
Referenced Files
None
Subscribers
None
D904.id1988.diff
View Options
Index: sys/amd64/include/dump.h
===================================================================
--- /dev/null
+++ sys/amd64/include/dump.h
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (c) 2014 EMC Corp.
+ * Copyright (c) 2014 Conrad Meyer <conrad.meyer@isilon.com>
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * 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$
+ */
+
+#ifndef _MACHINE_DUMP_H_
+#define _MACHINE_DUMP_H_
+
+#define KERNELDUMP_VERSION KERNELDUMP_AMD64_VERSION
+#define EM_VALUE EM_X86_64
+/* 20 phys_avail entry pairs correspond to 10 md_pa's */
+#define DUMPSYS_MD_PA_NPAIRS 10
+
+static inline void
+dumpsys_md_pa_init(void)
+{
+
+ dumpsys_gen_md_pa_init();
+}
+
+static inline struct md_pa *
+dumpsys_md_pa_next(struct md_pa *p)
+{
+
+ return dumpsys_gen_md_pa_next(p);
+}
+
+static inline void
+dumpsys_wbinv_all(void)
+{
+
+ dumpsys_gen_wbinv_all();
+}
+
+static inline void
+dumpsys_unmap_chunk(vm_paddr_t pa, size_t s, void *va)
+{
+
+ dumpsys_gen_unmap_chunk(pa, s, va);
+}
+
+#endif /* !_MACHINE_DUMP_H_ */
Index: sys/arm/arm/dump_machdep.c
===================================================================
--- sys/arm/arm/dump_machdep.c
+++ sys/arm/arm/dump_machdep.c
@@ -42,137 +42,16 @@
#endif
#include <vm/vm.h>
#include <vm/pmap.h>
+#include <machine/dump.h>
#include <machine/elf.h>
#include <machine/md_var.h>
#include <machine/pcb.h>
#include <machine/armreg.h>
-CTASSERT(sizeof(struct kerneldumpheader) == 512);
-
-int do_minidump = 1;
-SYSCTL_INT(_debug, OID_AUTO, minidump, CTLFLAG_RWTUN, &do_minidump, 0,
- "Enable mini crash dumps");
-
-/*
- * Don't touch the first SIZEOF_METADATA bytes on the dump device. This
- * is to protect us from metadata and to protect metadata from us.
- */
-#define SIZEOF_METADATA (64*1024)
-
-#define MD_ALIGN(x) (((off_t)(x) + PAGE_MASK) & ~PAGE_MASK)
-#define DEV_ALIGN(x) (((off_t)(x) + (DEV_BSIZE-1)) & ~(DEV_BSIZE-1))
-extern struct pcb dumppcb;
-
-struct md_pa {
- vm_paddr_t md_start;
- vm_paddr_t md_size;
-};
-
-typedef int callback_t(struct md_pa *, int, void *);
-
-static struct kerneldumpheader kdh;
-static off_t dumplo, fileofs;
-
-/* Handle buffered writes. */
-static char buffer[DEV_BSIZE];
-static size_t fragsz;
-
-/* XXX: I suppose 20 should be enough. */
-static struct md_pa dump_map[20];
-
-static void
-md_pa_init(void)
-{
- int n, idx;
-
- bzero(dump_map, sizeof(dump_map));
- for (n = 0; n < sizeof(dump_map) / sizeof(dump_map[0]); n++) {
- idx = n * 2;
- if (dump_avail[idx] == 0 && dump_avail[idx + 1] == 0)
- break;
- dump_map[n].md_start = dump_avail[idx];
- dump_map[n].md_size = dump_avail[idx + 1] - dump_avail[idx];
- }
-}
-
-static struct md_pa *
-md_pa_first(void)
-{
-
- return (&dump_map[0]);
-}
-
-static struct md_pa *
-md_pa_next(struct md_pa *mdp)
+void
+dumpsys_wbinv_all(void)
{
- mdp++;
- if (mdp->md_size == 0)
- mdp = NULL;
- return (mdp);
-}
-
-static int
-buf_write(struct dumperinfo *di, char *ptr, size_t sz)
-{
- size_t len;
- int error;
-
- while (sz) {
- len = DEV_BSIZE - fragsz;
- if (len > sz)
- len = sz;
- bcopy(ptr, buffer + fragsz, len);
- fragsz += len;
- ptr += len;
- sz -= len;
- if (fragsz == DEV_BSIZE) {
- error = dump_write(di, buffer, 0, dumplo,
- DEV_BSIZE);
- if (error)
- return error;
- dumplo += DEV_BSIZE;
- fragsz = 0;
- }
- }
-
- return (0);
-}
-
-static int
-buf_flush(struct dumperinfo *di)
-{
- int error;
-
- if (fragsz == 0)
- return (0);
-
- error = dump_write(di, buffer, 0, dumplo, DEV_BSIZE);
- dumplo += DEV_BSIZE;
- fragsz = 0;
- return (error);
-}
-
-extern vm_offset_t kernel_l1kva;
-extern char *pouet2;
-
-static int
-cb_dumpdata(struct md_pa *mdp, int seqnr, void *arg)
-{
- struct dumperinfo *di = (struct dumperinfo*)arg;
- vm_paddr_t pa;
- uint32_t pgs;
- size_t counter, sz, chunk;
- int c, error;
-
- error = 0; /* catch case in which chunk size is 0 */
- counter = 0;
- pgs = mdp->md_size / PAGE_SIZE;
- pa = mdp->md_start;
-
- printf(" chunk %d: %dMB (%d pages)", seqnr, pgs * PAGE_SIZE / (
- 1024*1024), pgs);
-
/*
* Make sure we write coherent data. Note that in the SMP case this
* only operates on the L1 cache of the current CPU, but all other CPUs
@@ -184,199 +63,16 @@
#ifdef __XSCALE__
xscale_cache_clean_minidata();
#endif
- while (pgs) {
- chunk = pgs;
- if (chunk > MAXDUMPPGS)
- chunk = MAXDUMPPGS;
- sz = chunk << PAGE_SHIFT;
- counter += sz;
- if (counter >> 24) {
- printf(" %d", pgs * PAGE_SIZE);
- counter &= (1<<24) - 1;
- }
- if (pa == (pa & L1_ADDR_BITS)) {
- pmap_kenter_section(0, pa & L1_ADDR_BITS, 0);
- cpu_tlb_flushID_SE(0);
- cpu_cpwait();
- }
-#ifdef SW_WATCHDOG
- wdog_kern_pat(WD_LASTVAL);
-#endif
- error = dump_write(di,
- (void *)(pa - (pa & L1_ADDR_BITS)),0, dumplo, sz);
- if (error)
- break;
- dumplo += sz;
- pgs -= chunk;
- pa += sz;
-
- /* Check for user abort. */
- c = cncheckc();
- if (c == 0x03)
- return (ECANCELED);
- if (c != -1)
- printf(" (CTRL-C to abort) ");
- }
- printf(" ... %s\n", (error) ? "fail" : "ok");
- return (error);
-}
-
-static int
-cb_dumphdr(struct md_pa *mdp, int seqnr, void *arg)
-{
- struct dumperinfo *di = (struct dumperinfo*)arg;
- Elf_Phdr phdr;
- uint64_t size;
- int error;
-
- size = mdp->md_size;
- bzero(&phdr, sizeof(phdr));
- phdr.p_type = PT_LOAD;
- phdr.p_flags = PF_R; /* XXX */
- phdr.p_offset = fileofs;
- phdr.p_vaddr = mdp->md_start;
- phdr.p_paddr = mdp->md_start;
- phdr.p_filesz = size;
- phdr.p_memsz = size;
- phdr.p_align = PAGE_SIZE;
-
- error = buf_write(di, (char*)&phdr, sizeof(phdr));
- fileofs += phdr.p_filesz;
- return (error);
-}
-
-static int
-cb_size(struct md_pa *mdp, int seqnr, void *arg)
-{
- uint32_t *sz = (uint32_t*)arg;
-
- *sz += (uint32_t)mdp->md_size;
- return (0);
-}
-
-static int
-foreach_chunk(callback_t cb, void *arg)
-{
- struct md_pa *mdp;
- int error, seqnr;
-
- seqnr = 0;
- mdp = md_pa_first();
- while (mdp != NULL) {
- error = (*cb)(mdp, seqnr++, arg);
- if (error)
- return (-error);
- mdp = md_pa_next(mdp);
- }
- return (seqnr);
}
-int
-dumpsys(struct dumperinfo *di)
+void
+dumpsys_map_chunk(vm_paddr_t pa, size_t chunk __unused, void **va)
{
- Elf_Ehdr ehdr;
- uint32_t dumpsize;
- off_t hdrgap;
- size_t hdrsz;
- int error;
- if (do_minidump)
- return (minidumpsys(di));
-
- bzero(&ehdr, sizeof(ehdr));
- ehdr.e_ident[EI_MAG0] = ELFMAG0;
- ehdr.e_ident[EI_MAG1] = ELFMAG1;
- ehdr.e_ident[EI_MAG2] = ELFMAG2;
- ehdr.e_ident[EI_MAG3] = ELFMAG3;
- ehdr.e_ident[EI_CLASS] = ELF_CLASS;
-#if BYTE_ORDER == LITTLE_ENDIAN
- ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
-#else
- ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
-#endif
- ehdr.e_ident[EI_VERSION] = EV_CURRENT;
- ehdr.e_ident[EI_OSABI] = ELFOSABI_STANDALONE; /* XXX big picture? */
- ehdr.e_type = ET_CORE;
- ehdr.e_machine = EM_ARM;
- ehdr.e_phoff = sizeof(ehdr);
- ehdr.e_flags = 0;
- ehdr.e_ehsize = sizeof(ehdr);
- ehdr.e_phentsize = sizeof(Elf_Phdr);
- ehdr.e_shentsize = sizeof(Elf_Shdr);
-
- md_pa_init();
-
- /* Calculate dump size. */
- dumpsize = 0L;
- ehdr.e_phnum = foreach_chunk(cb_size, &dumpsize);
- hdrsz = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize;
- fileofs = MD_ALIGN(hdrsz);
- dumpsize += fileofs;
- hdrgap = fileofs - DEV_ALIGN(hdrsz);
-
- /* Determine dump offset on device. */
- if (di->mediasize < SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2) {
- error = ENOSPC;
- goto fail;
+ if (pa == (pa & L1_ADDR_BITS)) {
+ pmap_kenter_section(0, pa & L1_ADDR_BITS, 0);
+ cpu_tlb_flushID_SE(0);
+ cpu_cpwait();
}
- dumplo = di->mediaoffset + di->mediasize - dumpsize;
- dumplo -= sizeof(kdh) * 2;
-
- mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_ARM_VERSION, dumpsize, di->blocksize);
-
- printf("Dumping %llu MB (%d chunks)\n", (long long)dumpsize >> 20,
- ehdr.e_phnum);
-
- /* Dump leader */
- error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
- if (error)
- goto fail;
- dumplo += sizeof(kdh);
-
- /* Dump ELF header */
- error = buf_write(di, (char*)&ehdr, sizeof(ehdr));
- if (error)
- goto fail;
-
- /* Dump program headers */
- error = foreach_chunk(cb_dumphdr, di);
- if (error < 0)
- goto fail;
- buf_flush(di);
-
- /*
- * All headers are written using blocked I/O, so we know the
- * current offset is (still) block aligned. Skip the alignement
- * in the file to have the segment contents aligned at page
- * boundary. We cannot use MD_ALIGN on dumplo, because we don't
- * care and may very well be unaligned within the dump device.
- */
- dumplo += hdrgap;
-
- /* Dump memory chunks (updates dumplo) */
- error = foreach_chunk(cb_dumpdata, di);
- if (error < 0)
- goto fail;
-
- /* Dump trailer */
- error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
- if (error)
- goto fail;
-
- /* Signal completion, signoff and exit stage left. */
- dump_write(di, NULL, 0, 0, 0);
- printf("\nDump complete\n");
- return (0);
-
- fail:
- if (error < 0)
- error = -error;
-
- if (error == ECANCELED)
- printf("\nDump aborted\n");
- else if (error == ENOSPC)
- printf("\nDump failed. Partition too small.\n");
- else
- printf("\n** DUMP FAILED (ERROR %d) **\n", error);
- return (error);
+ *va = (void *)(pa - (pa & L1_ADDR_BITS));
}
Index: sys/arm/include/dump.h
===================================================================
--- /dev/null
+++ sys/arm/include/dump.h
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 2014 EMC Corp.
+ * Copyright (c) 2014 Conrad Meyer <conrad.meyer@isilon.com>
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * 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$
+ */
+
+#ifndef _MACHINE_DUMP_H_
+#define _MACHINE_DUMP_H_
+
+#define KERNELDUMP_VERSION KERNELDUMP_ARM_VERSION
+#define EM_VALUE EM_ARM
+/* XXX: I suppose 20 should be enough. */
+#define DUMPSYS_MD_PA_NPAIRS 20
+
+void dumpsys_wbinv_all(void);
+
+static inline void
+dumpsys_md_pa_init(void)
+{
+
+ dumpsys_gen_md_pa_init();
+}
+
+static inline struct md_pa *
+dumpsys_md_pa_next(struct md_pa *p)
+{
+
+ return dumpsys_gen_md_pa_next(p);
+}
+
+static inline void
+dumpsys_unmap_chunk(vm_paddr_t pa, size_t s, void *va)
+{
+
+ dumpsys_gen_unmap_chunk(pa, s, va);
+}
+
+#endif /* !_MACHINE_DUMP_H_ */
Index: sys/conf/files
===================================================================
--- sys/conf/files
+++ sys/conf/files
@@ -2937,6 +2937,7 @@
kern/kern_context.c standard
kern/kern_descrip.c standard
kern/kern_dtrace.c optional kdtrace_hooks
+kern/kern_dump.c standard
kern/kern_environment.c standard
kern/kern_et.c standard
kern/kern_event.c standard
Index: sys/conf/files.powerpc
===================================================================
--- sys/conf/files.powerpc
+++ sys/conf/files.powerpc
@@ -183,7 +183,6 @@
powerpc/powerpc/db_hwwatch.c optional ddb
powerpc/powerpc/db_interface.c optional ddb
powerpc/powerpc/db_trace.c optional ddb
-powerpc/powerpc/dump_machdep.c standard
powerpc/powerpc/elf32_machdep.c optional powerpc | compat_freebsd32
powerpc/powerpc/elf64_machdep.c optional powerpc64
powerpc/powerpc/exec_machdep.c standard
Index: sys/i386/include/dump.h
===================================================================
--- /dev/null
+++ sys/i386/include/dump.h
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (c) 2014 EMC Corp.
+ * Copyright (c) 2014 Conrad Meyer <conrad.meyer@isilon.com>
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * 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$
+ */
+
+#ifndef _MACHINE_DUMP_H_
+#define _MACHINE_DUMP_H_
+
+#define KERNELDUMP_VERSION KERNELDUMP_I386_VERSION
+#define EM_VALUE EM_386
+/* 20 phys_avail entry pairs correspond to 10 md_pa's */
+#define DUMPSYS_MD_PA_NPAIRS 10
+
+static inline void
+dumpsys_md_pa_init(void)
+{
+
+ dumpsys_gen_md_pa_init();
+}
+
+static inline struct md_pa *
+dumpsys_md_pa_next(struct md_pa *p)
+{
+
+ return dumpsys_gen_md_pa_next(p);
+}
+
+static inline void
+dumpsys_wbinv_all(void)
+{
+
+ dumpsys_gen_wbinv_all();
+}
+
+static inline void
+dumpsys_unmap_chunk(vm_paddr_t pa, size_t s, void *va)
+{
+
+ dumpsys_gen_unmap_chunk(pa, s, va);
+}
+
+#endif /* !_MACHINE_DUMP_H_ */
Index: sys/kern/kern_dump.c
===================================================================
--- sys/kern/kern_dump.c
+++ sys/kern/kern_dump.c
@@ -35,26 +35,26 @@
#include <sys/cons.h>
#include <sys/sysctl.h>
#include <sys/kernel.h>
+#include <sys/proc.h>
#include <sys/kerneldump.h>
+#ifdef SW_WATCHDOG
#include <sys/watchdog.h>
+#endif
#include <vm/vm.h>
+#include <vm/vm_param.h>
#include <vm/pmap.h>
+#include <machine/dump.h>
#include <machine/elf.h>
#include <machine/md_var.h>
-
-#ifdef __amd64__
-#define KERNELDUMP_VERSION KERNELDUMP_AMD64_VERSION
-#define EM_VALUE EM_X86_64
-#else
-#define KERNELDUMP_VERSION KERNELDUMP_I386_VERSION
-#define EM_VALUE EM_386
-#endif
+#include <machine/pcb.h>
CTASSERT(sizeof(struct kerneldumpheader) == 512);
+#ifndef __sparc__
int do_minidump = 1;
SYSCTL_INT(_debug, OID_AUTO, minidump, CTLFLAG_RWTUN, &do_minidump, 0,
"Enable mini crash dumps");
+#endif
/*
* Don't touch the first SIZEOF_METADATA bytes on the dump device. This
@@ -65,25 +65,17 @@
#define MD_ALIGN(x) (((off_t)(x) + PAGE_MASK) & ~PAGE_MASK)
#define DEV_ALIGN(x) (((off_t)(x) + (DEV_BSIZE-1)) & ~(DEV_BSIZE-1))
-struct md_pa {
- vm_paddr_t md_start;
- vm_paddr_t md_size;
-};
-
-typedef int callback_t(struct md_pa *, int, void *);
-
-static struct kerneldumpheader kdh;
-static off_t dumplo, fileofs;
+off_t dumplo;
/* Handle buffered writes. */
static char buffer[DEV_BSIZE];
static size_t fragsz;
-/* 20 phys_avail entry pairs correspond to 10 md_pa's */
-static struct md_pa dump_map[10];
+struct md_pa dump_map[DUMPSYS_MD_PA_NPAIRS];
-static void
-md_pa_init(void)
+#if !defined(__sparc__) && !defined(__powerpc__)
+void
+dumpsys_gen_md_pa_init(void)
{
int n, idx;
@@ -96,17 +88,14 @@
dump_map[n].md_size = dump_avail[idx + 1] - dump_avail[idx];
}
}
+#endif
-static struct md_pa *
-md_pa_first(void)
+struct md_pa *
+dumpsys_gen_md_pa_next(struct md_pa *mdp)
{
- return (&dump_map[0]);
-}
-
-static struct md_pa *
-md_pa_next(struct md_pa *mdp)
-{
+ if (mdp == NULL)
+ return (&dump_map[0]);
mdp++;
if (mdp->md_size == 0)
@@ -114,8 +103,23 @@
return (mdp);
}
-static int
-buf_write(struct dumperinfo *di, char *ptr, size_t sz)
+void
+dumpsys_gen_wbinv_all(void)
+{
+
+ /* nop */;
+}
+
+void
+dumpsys_gen_unmap_chunk(vm_paddr_t pa __unused, size_t chunk __unused,
+ void *va __unused)
+{
+
+ /* nop */;
+}
+
+int
+dumpsys_buf_write(struct dumperinfo *di, char *ptr, size_t sz)
{
size_t len;
int error;
@@ -141,8 +145,8 @@
return (0);
}
-static int
-buf_flush(struct dumperinfo *di)
+int
+dumpsys_buf_flush(struct dumperinfo *di)
{
int error;
@@ -155,17 +159,18 @@
return (error);
}
-#define PG2MB(pgs) ((pgs + (1 << 8) - 1) >> 8)
+CTASSERT(PAGE_SHIFT < 20);
+#define PG2MB(pgs) ((pgs + (1 << (20 - PAGE_SHIFT)) - 1) >> (20 - PAGE_SHIFT))
-static int
-cb_dumpdata(struct md_pa *mdp, int seqnr, void *arg)
+int
+dumpsys_cb_dumpdata(struct md_pa *mdp, int seqnr, void *arg)
{
struct dumperinfo *di = (struct dumperinfo*)arg;
- vm_paddr_t a, pa;
+ vm_paddr_t pa;
void *va;
uint64_t pgs;
size_t counter, sz, chunk;
- int i, c, error, twiddle;
+ int c, error, twiddle;
u_int maxdumppgs;
error = 0; /* catch case in which chunk size is 0 */
@@ -181,6 +186,7 @@
printf(" chunk %d: %juMB (%ju pages)", seqnr, (uintmax_t)PG2MB(pgs),
(uintmax_t)pgs);
+ dumpsys_wbinv_all();
while (pgs) {
chunk = pgs;
if (chunk > maxdumppgs)
@@ -191,14 +197,14 @@
printf(" %ju", (uintmax_t)PG2MB(pgs));
counter &= (1<<24) - 1;
}
- for (i = 0; i < chunk; i++) {
- a = pa + i * PAGE_SIZE;
- va = pmap_kenter_temporary(trunc_page(a), i);
- }
+ dumpsys_map_chunk(pa, chunk, &va);
+#ifdef SW_WATCHDOG
wdog_kern_pat(WD_LASTVAL);
+#endif
error = dump_write(di, va, 0, dumplo, sz);
+ dumpsys_unmap_chunk(pa, chunk, va);
if (error)
break;
dumplo += sz;
@@ -216,6 +222,26 @@
return (error);
}
+int
+dumpsys_foreach_chunk(dumpsys_callback_t cb, void *arg)
+{
+ struct md_pa *mdp;
+ int error, seqnr;
+
+ seqnr = 0;
+ mdp = dumpsys_md_pa_next(NULL);
+ while (mdp != NULL) {
+ error = (*cb)(mdp, seqnr++, arg);
+ if (error)
+ return (-error);
+ mdp = dumpsys_md_pa_next(mdp);
+ }
+ return (seqnr);
+}
+
+#ifndef DUMPSYS_HAS_MD_DUMPSYS
+static off_t fileofs;
+
static int
cb_dumphdr(struct md_pa *mdp, int seqnr, void *arg)
{
@@ -229,13 +255,18 @@
phdr.p_type = PT_LOAD;
phdr.p_flags = PF_R; /* XXX */
phdr.p_offset = fileofs;
+#ifdef __powerpc__
+ phdr.p_vaddr = (do_minidump? mdp->md_start : ~0L);
+ phdr.p_paddr = (do_minidump? ~0L : mdp->md_start);
+#else
phdr.p_vaddr = mdp->md_start;
phdr.p_paddr = mdp->md_start;
+#endif
phdr.p_filesz = size;
phdr.p_memsz = size;
phdr.p_align = PAGE_SIZE;
- error = buf_write(di, (char*)&phdr, sizeof(phdr));
+ error = dumpsys_buf_write(di, (char*)&phdr, sizeof(phdr));
fileofs += phdr.p_filesz;
return (error);
}
@@ -249,35 +280,20 @@
return (0);
}
-static int
-foreach_chunk(callback_t cb, void *arg)
-{
- struct md_pa *mdp;
- int error, seqnr;
-
- seqnr = 0;
- mdp = md_pa_first();
- while (mdp != NULL) {
- error = (*cb)(mdp, seqnr++, arg);
- if (error)
- return (-error);
- mdp = md_pa_next(mdp);
- }
- return (seqnr);
-}
-
int
dumpsys(struct dumperinfo *di)
{
+ struct kerneldumpheader kdh;
Elf_Ehdr ehdr;
uint64_t dumpsize;
off_t hdrgap;
size_t hdrsz;
int error;
+#ifndef __powerpc__
if (do_minidump)
return (minidumpsys(di));
-
+#endif
bzero(&ehdr, sizeof(ehdr));
ehdr.e_ident[EI_MAG0] = ELFMAG0;
ehdr.e_ident[EI_MAG1] = ELFMAG1;
@@ -299,11 +315,11 @@
ehdr.e_phentsize = sizeof(Elf_Phdr);
ehdr.e_shentsize = sizeof(Elf_Shdr);
- md_pa_init();
+ dumpsys_md_pa_init();
/* Calculate dump size. */
dumpsize = 0L;
- ehdr.e_phnum = foreach_chunk(cb_size, &dumpsize);
+ ehdr.e_phnum = dumpsys_foreach_chunk(cb_size, &dumpsize);
hdrsz = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize;
fileofs = MD_ALIGN(hdrsz);
dumpsize += fileofs;
@@ -320,7 +336,7 @@
mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_VERSION, dumpsize,
di->blocksize);
- printf("Dumping %llu MB (%d chunks)\n", (long long)dumpsize >> 20,
+ printf("Dumping %ju MB (%d chunks)\n", (uintmax_t)dumpsize >> 20,
ehdr.e_phnum);
/* Dump leader */
@@ -330,15 +346,15 @@
dumplo += sizeof(kdh);
/* Dump ELF header */
- error = buf_write(di, (char*)&ehdr, sizeof(ehdr));
+ error = dumpsys_buf_write(di, (char*)&ehdr, sizeof(ehdr));
if (error)
goto fail;
/* Dump program headers */
- error = foreach_chunk(cb_dumphdr, di);
+ error = dumpsys_foreach_chunk(cb_dumphdr, di);
if (error < 0)
goto fail;
- buf_flush(di);
+ dumpsys_buf_flush(di);
/*
* All headers are written using blocked I/O, so we know the
@@ -350,7 +366,7 @@
dumplo += hdrgap;
/* Dump memory chunks (updates dumplo) */
- error = foreach_chunk(cb_dumpdata, di);
+ error = dumpsys_foreach_chunk(dumpsys_cb_dumpdata, di);
if (error < 0)
goto fail;
@@ -376,3 +392,4 @@
printf("\n** DUMP FAILED (ERROR %d) **\n", error);
return (error);
}
+#endif /* !DUMPSYS_HAS_MD_DUMPSYS */
Index: sys/mips/include/dump.h
===================================================================
--- /dev/null
+++ sys/mips/include/dump.h
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 2014 EMC Corp.
+ * Copyright (c) 2014 Conrad Meyer <conrad.meyer@isilon.com>
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * 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$
+ */
+
+#ifndef _MACHINE_DUMP_H_
+#define _MACHINE_DUMP_H_
+
+#define KERNELDUMP_VERSION KERNELDUMP_MIPS_VERSION
+#define EM_VALUE EM_MIPS
+/* XXX: I suppose 20 should be enough. */
+#define DUMPSYS_MD_PA_NPAIRS 20
+
+void dumpsys_wbinv_all(void);
+
+static inline void
+dumpsys_md_pa_init(void)
+{
+
+ dumpsys_gen_md_pa_init();
+}
+
+static inline struct md_pa *
+dumpsys_md_pa_next(struct md_pa *p)
+{
+
+ return dumpsys_gen_md_pa_next(p);
+}
+
+static inline void
+dumpsys_unmap_chunk(vm_paddr_t pa, size_t s, void *va)
+{
+
+ dumpsys_gen_unmap_chunk(pa, s, va);
+}
+
+#endif /* !_MACHINE_DUMP_H_ */
Index: sys/mips/include/md_var.h
===================================================================
--- sys/mips/include/md_var.h
+++ sys/mips/include/md_var.h
@@ -80,4 +80,5 @@
void dump_add_page(vm_paddr_t);
void dump_drop_page(vm_paddr_t);
int minidumpsys(struct dumperinfo *);
+
#endif /* !_MACHINE_MD_VAR_H_ */
Index: sys/mips/mips/dump_machdep.c
===================================================================
--- sys/mips/mips/dump_machdep.c
+++ sys/mips/mips/dump_machdep.c
@@ -42,327 +42,24 @@
#endif
#include <vm/vm.h>
#include <vm/pmap.h>
+#include <machine/dump.h>
#include <machine/elf.h>
#include <machine/md_var.h>
#include <machine/pcb.h>
#include <machine/cache.h>
-CTASSERT(sizeof(struct kerneldumpheader) == 512);
-
-int do_minidump = 1;
-SYSCTL_INT(_debug, OID_AUTO, minidump, CTLFLAG_RWTUN, &do_minidump, 0,
- "Enable mini crash dumps");
-
-/*
- * Don't touch the first SIZEOF_METADATA bytes on the dump device. This
- * is to protect us from metadata and to protect metadata from us.
- */
-#define SIZEOF_METADATA (64*1024)
-
-#define MD_ALIGN(x) (((off_t)(x) + PAGE_MASK) & ~PAGE_MASK)
-#define DEV_ALIGN(x) (((off_t)(x) + (DEV_BSIZE-1)) & ~(DEV_BSIZE-1))
-extern struct pcb dumppcb;
-
-struct md_pa {
- vm_paddr_t md_start;
- vm_paddr_t md_size;
-};
-
-typedef int callback_t(struct md_pa *, int, void *);
-
-static struct kerneldumpheader kdh;
-static off_t dumplo, fileofs;
-
-/* Handle buffered writes. */
-static char buffer[DEV_BSIZE];
-static size_t fragsz;
-
-/* XXX: I suppose 20 should be enough. */
-static struct md_pa dump_map[20];
-
-static void
-md_pa_init(void)
-{
- int n, idx;
-
- bzero(dump_map, sizeof(dump_map));
- for (n = 0; n < sizeof(dump_map) / sizeof(dump_map[0]); n++) {
- idx = n * 2;
- if (dump_avail[idx] == 0 && dump_avail[idx + 1] == 0)
- break;
- dump_map[n].md_start = dump_avail[idx];
- dump_map[n].md_size = dump_avail[idx + 1] - dump_avail[idx];
- }
-}
-
-static struct md_pa *
-md_pa_first(void)
-{
-
- return (&dump_map[0]);
-}
-
-static struct md_pa *
-md_pa_next(struct md_pa *mdp)
-{
-
- mdp++;
- if (mdp->md_size == 0)
- mdp = NULL;
- return (mdp);
-}
-
-static int
-buf_write(struct dumperinfo *di, char *ptr, size_t sz)
+void
+dumpsys_wbinv_all(void)
{
- size_t len;
- int error;
-
- while (sz) {
- len = DEV_BSIZE - fragsz;
- if (len > sz)
- len = sz;
- bcopy(ptr, buffer + fragsz, len);
- fragsz += len;
- ptr += len;
- sz -= len;
- if (fragsz == DEV_BSIZE) {
- error = dump_write(di, buffer, 0, dumplo,
- DEV_BSIZE);
- if (error)
- return error;
- dumplo += DEV_BSIZE;
- fragsz = 0;
- }
- }
-
- return (0);
-}
-
-static int
-buf_flush(struct dumperinfo *di)
-{
- int error;
-
- if (fragsz == 0)
- return (0);
-
- error = dump_write(di, buffer, 0, dumplo, DEV_BSIZE);
- dumplo += DEV_BSIZE;
- fragsz = 0;
- return (error);
-}
-
-extern vm_offset_t kernel_l1kva;
-extern char *pouet2;
-
-static int
-cb_dumpdata(struct md_pa *mdp, int seqnr, void *arg)
-{
- struct dumperinfo *di = (struct dumperinfo*)arg;
- vm_paddr_t pa;
- uint32_t pgs;
- size_t counter, sz, chunk;
- int c, error;
-
- error = 0; /* catch case in which chunk size is 0 */
- counter = 0;
- pgs = mdp->md_size / PAGE_SIZE;
- pa = mdp->md_start;
-
- printf(" chunk %d: %dMB (%d pages)", seqnr, pgs * PAGE_SIZE / (
- 1024*1024), pgs);
/* Make sure we write coherent datas. */
mips_dcache_wbinv_all();
- while (pgs) {
- chunk = pgs;
- if (chunk > MAXDUMPPGS)
- chunk = MAXDUMPPGS;
- sz = chunk << PAGE_SHIFT;
- counter += sz;
- if (counter >> 24) {
- printf(" %d", pgs * PAGE_SIZE);
- counter &= (1<<24) - 1;
- }
-
-#ifdef SW_WATCHDOG
- wdog_kern_pat(WD_LASTVAL);
-#endif
- error = dump_write(di, (void *)(intptr_t)(pa),0, dumplo, sz); /* XXX fix PA */
- if (error)
- break;
- dumplo += sz;
- pgs -= chunk;
- pa += sz;
-
- /* Check for user abort. */
- c = cncheckc();
- if (c == 0x03)
- return (ECANCELED);
- if (c != -1)
- printf(" (CTRL-C to abort) ");
- }
- printf(" ... %s\n", (error) ? "fail" : "ok");
- return (error);
-}
-
-static int
-cb_dumphdr(struct md_pa *mdp, int seqnr, void *arg)
-{
- struct dumperinfo *di = (struct dumperinfo*)arg;
- Elf_Phdr phdr;
- uint64_t size;
- int error;
-
- size = mdp->md_size;
- bzero(&phdr, sizeof(phdr));
- phdr.p_type = PT_LOAD;
- phdr.p_flags = PF_R; /* XXX */
- phdr.p_offset = fileofs;
- phdr.p_vaddr = mdp->md_start;
- phdr.p_paddr = mdp->md_start;
- phdr.p_filesz = size;
- phdr.p_memsz = size;
- phdr.p_align = PAGE_SIZE;
-
- error = buf_write(di, (char*)&phdr, sizeof(phdr));
- fileofs += phdr.p_filesz;
- return (error);
-}
-
-static int
-cb_size(struct md_pa *mdp, int seqnr, void *arg)
-{
- uint32_t *sz = (uint32_t*)arg;
-
- *sz += (uint32_t)mdp->md_size;
- return (0);
-}
-
-static int
-foreach_chunk(callback_t cb, void *arg)
-{
- struct md_pa *mdp;
- int error, seqnr;
-
- seqnr = 0;
- mdp = md_pa_first();
- while (mdp != NULL) {
- error = (*cb)(mdp, seqnr++, arg);
- if (error)
- return (-error);
- mdp = md_pa_next(mdp);
- }
- return (seqnr);
}
-int
-dumpsys(struct dumperinfo *di)
+void
+dumpsys_map_chunk(vm_paddr_t pa, size_t chunk __unused, void **va)
{
- Elf_Ehdr ehdr;
- uint32_t dumpsize;
- off_t hdrgap;
- size_t hdrsz;
- int error;
-
- if (do_minidump)
- return (minidumpsys(di));
-
- bzero(&ehdr, sizeof(ehdr));
- ehdr.e_ident[EI_MAG0] = ELFMAG0;
- ehdr.e_ident[EI_MAG1] = ELFMAG1;
- ehdr.e_ident[EI_MAG2] = ELFMAG2;
- ehdr.e_ident[EI_MAG3] = ELFMAG3;
- ehdr.e_ident[EI_CLASS] = ELF_CLASS;
-#if BYTE_ORDER == LITTLE_ENDIAN
- ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
-#else
- ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
-#endif
- ehdr.e_ident[EI_VERSION] = EV_CURRENT;
- ehdr.e_ident[EI_OSABI] = ELFOSABI_STANDALONE; /* XXX big picture? */
- ehdr.e_type = ET_CORE;
- ehdr.e_machine = EM_MIPS;
- ehdr.e_phoff = sizeof(ehdr);
- ehdr.e_flags = 0;
- ehdr.e_ehsize = sizeof(ehdr);
- ehdr.e_phentsize = sizeof(Elf_Phdr);
- ehdr.e_shentsize = sizeof(Elf_Shdr);
-
- md_pa_init();
-
- /* Calculate dump size. */
- dumpsize = 0L;
- ehdr.e_phnum = foreach_chunk(cb_size, &dumpsize);
- hdrsz = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize;
- fileofs = MD_ALIGN(hdrsz);
- dumpsize += fileofs;
- hdrgap = fileofs - DEV_ALIGN(hdrsz);
-
- /* Determine dump offset on device. */
- if (di->mediasize < SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2) {
- error = ENOSPC;
- goto fail;
- }
- dumplo = di->mediaoffset + di->mediasize - dumpsize;
- dumplo -= sizeof(kdh) * 2;
-
- mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_MIPS_VERSION, dumpsize, di->blocksize);
-
- printf("Dumping %llu MB (%d chunks)\n", (long long)dumpsize >> 20,
- ehdr.e_phnum);
-
- /* Dump leader */
- error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
- if (error)
- goto fail;
- dumplo += sizeof(kdh);
-
- /* Dump ELF header */
- error = buf_write(di, (char*)&ehdr, sizeof(ehdr));
- if (error)
- goto fail;
-
- /* Dump program headers */
- error = foreach_chunk(cb_dumphdr, di);
- if (error < 0)
- goto fail;
- buf_flush(di);
-
- /*
- * All headers are written using blocked I/O, so we know the
- * current offset is (still) block aligned. Skip the alignement
- * in the file to have the segment contents aligned at page
- * boundary. We cannot use MD_ALIGN on dumplo, because we don't
- * care and may very well be unaligned within the dump device.
- */
- dumplo += hdrgap;
-
- /* Dump memory chunks (updates dumplo) */
- error = foreach_chunk(cb_dumpdata, di);
- if (error < 0)
- goto fail;
-
- /* Dump trailer */
- error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
- if (error)
- goto fail;
-
- /* Signal completion, signoff and exit stage left. */
- dump_write(di, NULL, 0, 0, 0);
- printf("\nDump complete\n");
- return (0);
-
- fail:
- if (error < 0)
- error = -error;
- if (error == ECANCELED)
- printf("\nDump aborted\n");
- else if (error == ENOSPC)
- printf("\nDump failed. Partition too small.\n");
- else
- printf("\n** DUMP FAILED (ERROR %d) **\n", error);
- return (error);
+ /* XXX fix PA */
+ *va = (void*)(intptr_t)pa;
}
Index: sys/powerpc/aim/mmu_oea.c
===================================================================
--- sys/powerpc/aim/mmu_oea.c
+++ sys/powerpc/aim/mmu_oea.c
@@ -106,6 +106,7 @@
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/conf.h>
#include <sys/queue.h>
#include <sys/cpuset.h>
#include <sys/ktr.h>
@@ -163,8 +164,6 @@
extern unsigned char _etext[];
extern unsigned char _end[];
-extern int dumpsys_minidump;
-
/*
* Map of physical memory regions.
*/
@@ -314,9 +313,8 @@
void moea_page_set_memattr(mmu_t mmu, vm_page_t m, vm_memattr_t ma);
boolean_t moea_dev_direct_mapped(mmu_t, vm_paddr_t, vm_size_t);
static void moea_sync_icache(mmu_t, pmap_t, vm_offset_t, vm_size_t);
-vm_offset_t moea_dumpsys_map(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
- vm_size_t *sz);
-struct pmap_md * moea_scan_md(mmu_t mmu, struct pmap_md *prev);
+void moea_dumpsys_map(mmu_t mmu, vm_paddr_t pa, size_t sz, void **va);
+void moea_scan_init(mmu_t mmu);
static mmu_method_t moea_methods[] = {
MMUMETHOD(mmu_clear_modify, moea_clear_modify),
@@ -363,7 +361,7 @@
MMUMETHOD(mmu_kenter, moea_kenter),
MMUMETHOD(mmu_kenter_attr, moea_kenter_attr),
MMUMETHOD(mmu_dev_direct_mapped,moea_dev_direct_mapped),
- MMUMETHOD(mmu_scan_md, moea_scan_md),
+ MMUMETHOD(mmu_scan_init, moea_scan_init),
MMUMETHOD(mmu_dumpsys_map, moea_dumpsys_map),
{ 0, 0 }
@@ -2628,100 +2626,73 @@
PMAP_UNLOCK(pm);
}
-vm_offset_t
-moea_dumpsys_map(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
- vm_size_t *sz)
+void
+moea_dumpsys_map(mmu_t mmu, vm_paddr_t pa, size_t sz, void **va)
{
- if (md->md_vaddr == ~0UL)
- return (md->md_paddr + ofs);
- else
- return (md->md_vaddr + ofs);
+
+ *va = (void *)pa;
}
-struct pmap_md *
-moea_scan_md(mmu_t mmu, struct pmap_md *prev)
+extern struct md_pa dump_map[PHYS_AVAIL_SZ + 1];
+
+void
+moea_scan_init(mmu_t mmu)
{
- static struct pmap_md md;
struct pvo_entry *pvo;
vm_offset_t va;
-
- if (dumpsys_minidump) {
- md.md_paddr = ~0UL; /* Minidumps use virtual addresses. */
- if (prev == NULL) {
- /* 1st: kernel .data and .bss. */
- md.md_index = 1;
- md.md_vaddr = trunc_page((uintptr_t)_etext);
- md.md_size = round_page((uintptr_t)_end) - md.md_vaddr;
- return (&md);
+ int i;
+
+ if (!do_minidump) {
+ /* Initialize phys. segments for dumpsys(). */
+ memset(&dump_map, 0, sizeof(dump_map));
+ mem_regions(&pregions, &pregions_sz, ®ions, ®ions_sz);
+ for (i = 0; i < pregions_sz; i++) {
+ dump_map[i].md_start = pregions[i].mr_start;
+ dump_map[i].md_size = pregions[i].mr_size;
}
- switch (prev->md_index) {
- case 1:
- /* 2nd: msgbuf and tables (see pmap_bootstrap()). */
- md.md_index = 2;
- md.md_vaddr = (vm_offset_t)msgbufp->msg_ptr;
- md.md_size = round_page(msgbufp->msg_size);
+ return;
+ }
+
+ /* Virtual segments for minidumps: */
+ memset(&dump_map, 0, sizeof(dump_map));
+
+ /* 1st: kernel .data and .bss. */
+ dump_map[0].md_start = trunc_page((uintptr_t)_etext);
+ dump_map[0].md_size = round_page((uintptr_t)_end) - dump_map[0].md_start;
+
+ /* 2nd: msgbuf and tables (see pmap_bootstrap()). */
+ dump_map[1].md_start = (vm_paddr_t)msgbufp->msg_ptr;
+ dump_map[1].md_size = round_page(msgbufp->msg_size);
+
+ /* 3rd: kernel VM. */
+ va = dump_map[1].md_start + dump_map[1].md_size;
+ /* Find start of next chunk (from va). */
+ while (va < virtual_end) {
+ /* Don't dump the buffer cache. */
+ if (va >= kmi.buffer_sva && va < kmi.buffer_eva) {
+ va = kmi.buffer_eva;
+ continue;
+ }
+ pvo = moea_pvo_find_va(kernel_pmap, va & ~ADDR_POFF, NULL);
+ if (pvo != NULL && (pvo->pvo_pte.pte.pte_hi & PTE_VALID))
break;
- case 2:
- /* 3rd: kernel VM. */
- va = prev->md_vaddr + prev->md_size;
- /* Find start of next chunk (from va). */
- while (va < virtual_end) {
- /* Don't dump the buffer cache. */
- if (va >= kmi.buffer_sva &&
- va < kmi.buffer_eva) {
- va = kmi.buffer_eva;
- continue;
- }
- pvo = moea_pvo_find_va(kernel_pmap,
- va & ~ADDR_POFF, NULL);
- if (pvo != NULL &&
- (pvo->pvo_pte.pte.pte_hi & PTE_VALID))
- break;
- va += PAGE_SIZE;
- }
- if (va < virtual_end) {
- md.md_vaddr = va;
- va += PAGE_SIZE;
- /* Find last page in chunk. */
- while (va < virtual_end) {
- /* Don't run into the buffer cache. */
- if (va == kmi.buffer_sva)
- break;
- pvo = moea_pvo_find_va(kernel_pmap,
- va & ~ADDR_POFF, NULL);
- if (pvo == NULL ||
- !(pvo->pvo_pte.pte.pte_hi & PTE_VALID))
- break;
- va += PAGE_SIZE;
- }
- md.md_size = va - md.md_vaddr;
+ va += PAGE_SIZE;
+ }
+ if (va < virtual_end) {
+ dump_map[2].md_start = va;
+ va += PAGE_SIZE;
+ /* Find last page in chunk. */
+ while (va < virtual_end) {
+ /* Don't run into the buffer cache. */
+ if (va == kmi.buffer_sva)
break;
- }
- md.md_index = 3;
- /* FALLTHROUGH */
- default:
- return (NULL);
- }
- } else { /* minidumps */
- mem_regions(&pregions, &pregions_sz,
- ®ions, ®ions_sz);
-
- if (prev == NULL) {
- /* first physical chunk. */
- md.md_paddr = pregions[0].mr_start;
- md.md_size = pregions[0].mr_size;
- md.md_vaddr = ~0UL;
- md.md_index = 1;
- } else if (md.md_index < pregions_sz) {
- md.md_paddr = pregions[md.md_index].mr_start;
- md.md_size = pregions[md.md_index].mr_size;
- md.md_vaddr = ~0UL;
- md.md_index++;
- } else {
- /* There's no next physical chunk. */
- return (NULL);
+ pvo = moea_pvo_find_va(kernel_pmap, va & ~ADDR_POFF,
+ NULL);
+ if (pvo == NULL ||
+ !(pvo->pvo_pte.pte.pte_hi & PTE_VALID))
+ break;
+ va += PAGE_SIZE;
}
+ dump_map[2].md_size = va - dump_map[2].md_start;
}
-
- return (&md);
}
Index: sys/powerpc/aim/mmu_oea64.c
===================================================================
--- sys/powerpc/aim/mmu_oea64.c
+++ sys/powerpc/aim/mmu_oea64.c
@@ -107,6 +107,7 @@
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/conf.h>
#include <sys/queue.h>
#include <sys/cpuset.h>
#include <sys/ktr.h>
@@ -187,8 +188,6 @@
extern unsigned char _etext[];
extern unsigned char _end[];
-extern int dumpsys_minidump;
-
/*
* Map of physical memory regions.
*/
@@ -327,9 +326,9 @@
void moea64_kenter(mmu_t, vm_offset_t, vm_paddr_t);
boolean_t moea64_dev_direct_mapped(mmu_t, vm_paddr_t, vm_size_t);
static void moea64_sync_icache(mmu_t, pmap_t, vm_offset_t, vm_size_t);
-vm_offset_t moea64_dumpsys_map(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
- vm_size_t *sz);
-struct pmap_md * moea64_scan_md(mmu_t mmu, struct pmap_md *prev);
+void moea64_dumpsys_map(mmu_t mmu, vm_paddr_t pa, size_t sz,
+ void **va);
+void moea64_scan_init(mmu_t mmu);
static mmu_method_t moea64_methods[] = {
MMUMETHOD(mmu_clear_modify, moea64_clear_modify),
@@ -375,7 +374,7 @@
MMUMETHOD(mmu_kenter, moea64_kenter),
MMUMETHOD(mmu_kenter_attr, moea64_kenter_attr),
MMUMETHOD(mmu_dev_direct_mapped,moea64_dev_direct_mapped),
- MMUMETHOD(mmu_scan_md, moea64_scan_md),
+ MMUMETHOD(mmu_scan_init, moea64_scan_init),
MMUMETHOD(mmu_dumpsys_map, moea64_dumpsys_map),
{ 0, 0 }
@@ -2612,97 +2611,72 @@
PMAP_UNLOCK(pm);
}
-vm_offset_t
-moea64_dumpsys_map(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
- vm_size_t *sz)
+void
+moea64_dumpsys_map(mmu_t mmu, vm_paddr_t pa, size_t sz, void **va)
{
- if (md->md_vaddr == ~0UL)
- return (md->md_paddr + ofs);
- else
- return (md->md_vaddr + ofs);
+
+ *va = (void *)pa;
}
-struct pmap_md *
-moea64_scan_md(mmu_t mmu, struct pmap_md *prev)
+extern struct md_pa dump_map[PHYS_AVAIL_SZ + 1];
+
+void
+moea64_scan_init(mmu_t mmu)
{
- static struct pmap_md md;
struct pvo_entry *pvo;
vm_offset_t va;
-
- if (dumpsys_minidump) {
- md.md_paddr = ~0UL; /* Minidumps use virtual addresses. */
- if (prev == NULL) {
- /* 1st: kernel .data and .bss. */
- md.md_index = 1;
- md.md_vaddr = trunc_page((uintptr_t)_etext);
- md.md_size = round_page((uintptr_t)_end) - md.md_vaddr;
- return (&md);
+ int i;
+
+ if (!do_minidump) {
+ /* Initialize phys. segments for dumpsys(). */
+ memset(&dump_map, 0, sizeof(dump_map));
+ mem_regions(&pregions, &pregions_sz, ®ions, ®ions_sz);
+ for (i = 0; i < pregions_sz; i++) {
+ dump_map[i].md_start = pregions[i].mr_start;
+ dump_map[i].md_size = pregions[i].mr_size;
}
- switch (prev->md_index) {
- case 1:
- /* 2nd: msgbuf and tables (see pmap_bootstrap()). */
- md.md_index = 2;
- md.md_vaddr = (vm_offset_t)msgbufp->msg_ptr;
- md.md_size = round_page(msgbufp->msg_size);
+ return;
+ }
+
+ /* Virtual segments for minidumps: */
+ memset(&dump_map, 0, sizeof(dump_map));
+
+ /* 1st: kernel .data and .bss. */
+ dump_map[0].md_start = trunc_page((uintptr_t)_etext);
+ dump_map[0].md_size = round_page((uintptr_t)_end) - dump_map[0].md_start;
+
+ /* 2nd: msgbuf and tables (see pmap_bootstrap()). */
+ dump_map[1].md_start = (vm_paddr_t)msgbufp->msg_ptr;
+ dump_map[1].md_size = round_page(msgbufp->msg_size);
+
+ /* 3rd: kernel VM. */
+ va = dump_map[1].md_start + dump_map[1].md_size;
+ /* Find start of next chunk (from va). */
+ while (va < virtual_end) {
+ /* Don't dump the buffer cache. */
+ if (va >= kmi.buffer_sva && va < kmi.buffer_eva) {
+ va = kmi.buffer_eva;
+ continue;
+ }
+ pvo = moea64_pvo_find_va(kernel_pmap, va & ~ADDR_POFF);
+ if (pvo != NULL && (pvo->pvo_pte.lpte.pte_hi & LPTE_VALID))
break;
- case 2:
- /* 3rd: kernel VM. */
- va = prev->md_vaddr + prev->md_size;
- /* Find start of next chunk (from va). */
- while (va < virtual_end) {
- /* Don't dump the buffer cache. */
- if (va >= kmi.buffer_sva &&
- va < kmi.buffer_eva) {
- va = kmi.buffer_eva;
- continue;
- }
- pvo = moea64_pvo_find_va(kernel_pmap,
- va & ~ADDR_POFF);
- if (pvo != NULL &&
- (pvo->pvo_pte.lpte.pte_hi & LPTE_VALID))
- break;
- va += PAGE_SIZE;
- }
- if (va < virtual_end) {
- md.md_vaddr = va;
- va += PAGE_SIZE;
- /* Find last page in chunk. */
- while (va < virtual_end) {
- /* Don't run into the buffer cache. */
- if (va == kmi.buffer_sva)
- break;
- pvo = moea64_pvo_find_va(kernel_pmap,
- va & ~ADDR_POFF);
- if (pvo == NULL ||
- !(pvo->pvo_pte.lpte.pte_hi & LPTE_VALID))
- break;
- va += PAGE_SIZE;
- }
- md.md_size = va - md.md_vaddr;
+ va += PAGE_SIZE;
+ }
+ if (va < virtual_end) {
+ dump_map[2].md_start = va;
+ va += PAGE_SIZE;
+ /* Find last page in chunk. */
+ while (va < virtual_end) {
+ /* Don't run into the buffer cache. */
+ if (va == kmi.buffer_sva)
break;
- }
- md.md_index = 3;
- /* FALLTHROUGH */
- default:
- return (NULL);
- }
- } else { /* minidumps */
- if (prev == NULL) {
- /* first physical chunk. */
- md.md_paddr = pregions[0].mr_start;
- md.md_size = pregions[0].mr_size;
- md.md_vaddr = ~0UL;
- md.md_index = 1;
- } else if (md.md_index < pregions_sz) {
- md.md_paddr = pregions[md.md_index].mr_start;
- md.md_size = pregions[md.md_index].mr_size;
- md.md_vaddr = ~0UL;
- md.md_index++;
- } else {
- /* There's no next physical chunk. */
- return (NULL);
+ pvo = moea64_pvo_find_va(kernel_pmap, va & ~ADDR_POFF);
+ if (pvo == NULL ||
+ !(pvo->pvo_pte.lpte.pte_hi & LPTE_VALID))
+ break;
+ va += PAGE_SIZE;
}
+ dump_map[2].md_size = va - dump_map[2].md_start;
}
-
- return (&md);
}
Index: sys/powerpc/booke/pmap.c
===================================================================
--- sys/powerpc/booke/pmap.c
+++ sys/powerpc/booke/pmap.c
@@ -52,6 +52,7 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/conf.h>
#include <sys/malloc.h>
#include <sys/ktr.h>
#include <sys/proc.h>
@@ -100,8 +101,6 @@
#define TODO panic("%s: not implemented", __func__);
-extern int dumpsys_minidump;
-
extern unsigned char _etext[];
extern unsigned char _end[];
@@ -322,11 +321,11 @@
static boolean_t mmu_booke_dev_direct_mapped(mmu_t, vm_paddr_t, vm_size_t);
static void mmu_booke_sync_icache(mmu_t, pmap_t, vm_offset_t,
vm_size_t);
-static vm_offset_t mmu_booke_dumpsys_map(mmu_t, struct pmap_md *,
- vm_size_t, vm_size_t *);
-static void mmu_booke_dumpsys_unmap(mmu_t, struct pmap_md *,
- vm_size_t, vm_offset_t);
-static struct pmap_md *mmu_booke_scan_md(mmu_t, struct pmap_md *);
+static void mmu_booke_dumpsys_map(mmu_t, vm_paddr_t pa, size_t,
+ void **);
+static void mmu_booke_dumpsys_unmap(mmu_t, vm_paddr_t pa, size_t,
+ void *);
+static void mmu_booke_scan_init(mmu_t);
static mmu_method_t mmu_booke_methods[] = {
/* pmap dispatcher interface */
@@ -381,7 +380,7 @@
/* dumpsys() support */
MMUMETHOD(mmu_dumpsys_map, mmu_booke_dumpsys_map),
MMUMETHOD(mmu_dumpsys_unmap, mmu_booke_dumpsys_unmap),
- MMUMETHOD(mmu_scan_md, mmu_booke_scan_md),
+ MMUMETHOD(mmu_scan_init, mmu_booke_scan_init),
{ 0, 0 }
};
@@ -2534,139 +2533,124 @@
return (EFAULT);
}
-vm_offset_t
-mmu_booke_dumpsys_map(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
- vm_size_t *sz)
+void
+mmu_booke_dumpsys_map(mmu_t mmu, vm_paddr_t pa, size_t sz, void **va)
{
- vm_paddr_t pa, ppa;
- vm_offset_t va;
+ vm_paddr_t ppa;
+ vm_offset_t ofs;
vm_size_t gran;
- /* Raw physical memory dumps don't have a virtual address. */
- if (md->md_vaddr == ~0UL) {
- /* We always map a 256MB page at 256M. */
- gran = 256 * 1024 * 1024;
- pa = md->md_paddr + ofs;
- ppa = pa & ~(gran - 1);
- ofs = pa - ppa;
- va = gran;
- tlb1_set_entry(va, ppa, gran, _TLB_ENTRY_IO);
- if (*sz > (gran - ofs))
- *sz = gran - ofs;
- return (va + ofs);
- }
-
/* Minidumps are based on virtual memory addresses. */
- va = md->md_vaddr + ofs;
- if (va >= kernstart + kernsize) {
- gran = PAGE_SIZE - (va & PAGE_MASK);
- if (*sz > gran)
- *sz = gran;
+ if (do_minidump) {
+ *va = (void *)pa;
+ return;
}
- return (va);
+
+ /* Raw physical memory dumps don't have a virtual address. */
+ /* We always map a 256MB page at 256M. */
+ gran = 256 * 1024 * 1024;
+ ppa = pa & ~(gran - 1);
+ ofs = pa - ppa;
+ *va = (void *)gran;
+ tlb1_set_entry((vm_offset_t)va, ppa, gran, _TLB_ENTRY_IO);
+
+ if (sz > (gran - ofs))
+ tlb1_set_entry((vm_offset_t)(va + gran), ppa + gran, gran,
+ _TLB_ENTRY_IO);
}
void
-mmu_booke_dumpsys_unmap(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
- vm_offset_t va)
+mmu_booke_dumpsys_unmap(mmu_t mmu, vm_paddr_t pa, size_t sz, void *va)
{
+ vm_paddr_t ppa;
+ vm_offset_t ofs;
+ vm_size_t gran;
+
+ /* Minidumps are based on virtual memory addresses. */
+ /* Nothing to do... */
+ if (do_minidump)
+ return;
/* Raw physical memory dumps don't have a virtual address. */
- if (md->md_vaddr == ~0UL) {
+ tlb1_idx--;
+ tlb1[tlb1_idx].mas1 = 0;
+ tlb1[tlb1_idx].mas2 = 0;
+ tlb1[tlb1_idx].mas3 = 0;
+ tlb1_write_entry(tlb1_idx);
+
+ gran = 256 * 1024 * 1024;
+ ppa = pa & ~(gran - 1);
+ ofs = pa - ppa;
+ if (sz > (gran - ofs)) {
tlb1_idx--;
tlb1[tlb1_idx].mas1 = 0;
tlb1[tlb1_idx].mas2 = 0;
tlb1[tlb1_idx].mas3 = 0;
tlb1_write_entry(tlb1_idx);
- return;
}
-
- /* Minidumps are based on virtual memory addresses. */
- /* Nothing to do... */
}
-struct pmap_md *
-mmu_booke_scan_md(mmu_t mmu, struct pmap_md *prev)
+extern struct md_pa dump_map[PHYS_AVAIL_SZ + 1];
+
+void
+mmu_booke_scan_init(mmu_t mmu)
{
- static struct pmap_md md;
- pte_t *pte;
vm_offset_t va;
-
- if (dumpsys_minidump) {
- md.md_paddr = ~0UL; /* Minidumps use virtual addresses. */
- if (prev == NULL) {
- /* 1st: kernel .data and .bss. */
- md.md_index = 1;
- md.md_vaddr = trunc_page((uintptr_t)_etext);
- md.md_size = round_page((uintptr_t)_end) - md.md_vaddr;
- return (&md);
+ pte_t *pte;
+ int i;
+
+ if (!do_minidump) {
+ /* Initialize phys. segments for dumpsys(). */
+ memset(&dump_map, 0, sizeof(dump_map));
+ mem_regions(&physmem_regions, &physmem_regions_sz, &availmem_regions,
+ &availmem_regions_sz);
+ for (i = 0; i < physmem_regions_sz; i++) {
+ dump_map[i].md_start = physmem_regions[i].mr_start;
+ dump_map[i].md_size = physmem_regions[i].mr_size;
+ }
+ return;
+ }
+
+ /* Virtual segments for minidumps: */
+ memset(&dump_map, 0, sizeof(dump_map));
+
+ /* 1st: kernel .data and .bss. */
+ dump_map[0].md_start = trunc_page((uintptr_t)_etext);
+ dump_map[0].md_size = round_page((uintptr_t)_end) - dump_map[0].md_start;
+
+ /* 2nd: msgbuf and tables (see pmap_bootstrap()). */
+ dump_map[1].md_start = data_start;
+ dump_map[1].md_size = data_end - data_start;
+
+ /* 3rd: kernel VM. */
+ va = dump_map[1].md_start + dump_map[1].md_size;
+ /* Find start of next chunk (from va). */
+ while (va < virtual_end) {
+ /* Don't dump the buffer cache. */
+ if (va >= kmi.buffer_sva && va < kmi.buffer_eva) {
+ va = kmi.buffer_eva;
+ continue;
}
- switch (prev->md_index) {
- case 1:
- /* 2nd: msgbuf and tables (see pmap_bootstrap()). */
- md.md_index = 2;
- md.md_vaddr = data_start;
- md.md_size = data_end - data_start;
+ pte = pte_find(mmu, kernel_pmap, va);
+ if (pte != NULL && PTE_ISVALID(pte))
break;
- case 2:
- /* 3rd: kernel VM. */
- va = prev->md_vaddr + prev->md_size;
- /* Find start of next chunk (from va). */
- while (va < virtual_end) {
- /* Don't dump the buffer cache. */
- if (va >= kmi.buffer_sva &&
- va < kmi.buffer_eva) {
- va = kmi.buffer_eva;
- continue;
- }
- pte = pte_find(mmu, kernel_pmap, va);
- if (pte != NULL && PTE_ISVALID(pte))
- break;
- va += PAGE_SIZE;
- }
- if (va < virtual_end) {
- md.md_vaddr = va;
- va += PAGE_SIZE;
- /* Find last page in chunk. */
- while (va < virtual_end) {
- /* Don't run into the buffer cache. */
- if (va == kmi.buffer_sva)
- break;
- pte = pte_find(mmu, kernel_pmap, va);
- if (pte == NULL || !PTE_ISVALID(pte))
- break;
- va += PAGE_SIZE;
- }
- md.md_size = va - md.md_vaddr;
+ va += PAGE_SIZE;
+ }
+ if (va < virtual_end) {
+ dump_map[2].md_start = va;
+ va += PAGE_SIZE;
+ /* Find last page in chunk. */
+ while (va < virtual_end) {
+ /* Don't run into the buffer cache. */
+ if (va == kmi.buffer_sva)
break;
- }
- md.md_index = 3;
- /* FALLTHROUGH */
- default:
- return (NULL);
- }
- } else { /* minidumps */
- mem_regions(&physmem_regions, &physmem_regions_sz,
- &availmem_regions, &availmem_regions_sz);
-
- if (prev == NULL) {
- /* first physical chunk. */
- md.md_paddr = physmem_regions[0].mr_start;
- md.md_size = physmem_regions[0].mr_size;
- md.md_vaddr = ~0UL;
- md.md_index = 1;
- } else if (md.md_index < physmem_regions_sz) {
- md.md_paddr = physmem_regions[md.md_index].mr_start;
- md.md_size = physmem_regions[md.md_index].mr_size;
- md.md_vaddr = ~0UL;
- md.md_index++;
- } else {
- /* There's no next physical chunk. */
- return (NULL);
+ pte = pte_find(mmu, kernel_pmap, va);
+ if (pte == NULL || !PTE_ISVALID(pte))
+ break;
+ va += PAGE_SIZE;
}
+ dump_map[2].md_size = va - dump_map[2].md_start;
}
-
- return (&md);
}
/*
Index: sys/powerpc/include/dump.h
===================================================================
--- /dev/null
+++ sys/powerpc/include/dump.h
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 2014 EMC Corp.
+ * Copyright (c) 2014 Conrad Meyer <conrad.meyer@isilon.com>
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * 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$
+ */
+
+#ifndef _MACHINE_DUMP_H_
+#define _MACHINE_DUMP_H_
+
+#define KERNELDUMP_VERSION KERNELDUMP_POWERPC_VERSION
+#define EM_VALUE ELF_ARCH /* Defined in powerpc/include/elf.h */
+#define DUMPSYS_MD_PA_NPAIRS (PHYS_AVAIL_SZ + 1)
+
+void dumpsys_md_pa_init(void);
+void dumpsys_unmap_chunk(vm_paddr_t, size_t, void *);
+
+static inline struct md_pa *
+dumpsys_md_pa_next(struct md_pa *p)
+{
+
+ return dumpsys_gen_md_pa_next(p);
+}
+
+static inline void
+dumpsys_wbinv_all(void)
+{
+
+ dumpsys_gen_wbinv_all();
+}
+
+#endif /* !_MACHINE_DUMP_H_ */
Index: sys/powerpc/include/pmap.h
===================================================================
--- sys/powerpc/include/pmap.h
+++ sys/powerpc/include/pmap.h
@@ -74,13 +74,6 @@
#include <machine/slb.h>
#include <machine/tlb.h>
-struct pmap_md {
- u_int md_index;
- vm_paddr_t md_paddr;
- vm_offset_t md_vaddr;
- vm_size_t md_size;
-};
-
#if defined(AIM)
#if !defined(NPMAPS)
@@ -252,11 +245,6 @@
extern int pmap_bootstrapped;
-extern vm_offset_t pmap_dumpsys_map(struct pmap_md *, vm_size_t, vm_size_t *);
-extern void pmap_dumpsys_unmap(struct pmap_md *, vm_size_t, vm_offset_t);
-
-extern struct pmap_md *pmap_scan_md(struct pmap_md *);
-
vm_offset_t pmap_early_io_map(vm_paddr_t pa, vm_size_t size);
#endif
Index: sys/powerpc/powerpc/dump_machdep.c
===================================================================
--- sys/powerpc/powerpc/dump_machdep.c
+++ sys/powerpc/powerpc/dump_machdep.c
@@ -1,315 +0,0 @@
-/*-
- * Copyright (c) 2002 Marcel Moolenaar
- * All rights reserved.
- *
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "opt_watchdog.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/cons.h>
-#include <sys/kernel.h>
-#include <sys/kerneldump.h>
-#include <sys/sysctl.h>
-#ifdef SW_WATCHDOG
-#include <sys/watchdog.h>
-#endif
-#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <machine/elf.h>
-#include <machine/md_var.h>
-
-CTASSERT(sizeof(struct kerneldumpheader) == 512);
-
-/*
- * Don't touch the first SIZEOF_METADATA bytes on the dump device. This
- * is to protect us from metadata and to protect metadata from us.
- */
-#define SIZEOF_METADATA (64*1024)
-
-#define MD_ALIGN(x) (((off_t)(x) + PAGE_MASK) & ~PAGE_MASK)
-#define DEV_ALIGN(x) (((off_t)(x) + (DEV_BSIZE-1)) & ~(DEV_BSIZE-1))
-
-typedef int callback_t(struct pmap_md *, int, void *);
-
-static struct kerneldumpheader kdh;
-static off_t dumplo, fileofs;
-
-/* Handle buffered writes. */
-static char buffer[DEV_BSIZE];
-static size_t fragsz;
-
-int dumpsys_minidump = 1;
-SYSCTL_INT(_debug, OID_AUTO, minidump, CTLFLAG_RD, &dumpsys_minidump, 0,
- "Kernel makes compressed crash dumps");
-
-static int
-buf_write(struct dumperinfo *di, char *ptr, size_t sz)
-{
- size_t len;
- int error;
-
- while (sz) {
- len = DEV_BSIZE - fragsz;
- if (len > sz)
- len = sz;
- bcopy(ptr, buffer + fragsz, len);
- fragsz += len;
- ptr += len;
- sz -= len;
- if (fragsz == DEV_BSIZE) {
- error = di->dumper(di->priv, buffer, 0, dumplo,
- DEV_BSIZE);
- if (error)
- return error;
- dumplo += DEV_BSIZE;
- fragsz = 0;
- }
- }
-
- return (0);
-}
-
-static int
-buf_flush(struct dumperinfo *di)
-{
- int error;
-
- if (fragsz == 0)
- return (0);
-
- error = di->dumper(di->priv, buffer, 0, dumplo, DEV_BSIZE);
- dumplo += DEV_BSIZE;
- fragsz = 0;
- return (error);
-}
-
-static int
-cb_dumpdata(struct pmap_md *md, int seqnr, void *arg)
-{
- struct dumperinfo *di = (struct dumperinfo*)arg;
- vm_offset_t va;
- size_t counter, ofs, resid, sz, maxsz;
- int c, error, twiddle;
-
- error = 0;
- counter = 0; /* Update twiddle every 16MB */
- twiddle = 0;
-
- ofs = 0; /* Logical offset within the chunk */
- resid = md->md_size;
- maxsz = min(DFLTPHYS, di->maxiosize);
-
- printf(" chunk %d: %lu bytes ", seqnr, (u_long)resid);
-
- while (resid) {
- sz = min(resid, maxsz);
- va = pmap_dumpsys_map(md, ofs, &sz);
- counter += sz;
- if (counter >> 24) {
- printf("%c\b", "|/-\\"[twiddle++ & 3]);
- counter &= (1<<24) - 1;
- }
-#ifdef SW_WATCHDOG
- wdog_kern_pat(WD_LASTVAL);
-#endif
- error = di->dumper(di->priv, (void*)va, 0, dumplo, sz);
- pmap_dumpsys_unmap(md, ofs, va);
- if (error)
- break;
- dumplo += sz;
- resid -= sz;
- ofs += sz;
-
- /* Check for user abort. */
- c = cncheckc();
- if (c == 0x03)
- return (ECANCELED);
- if (c != -1)
- printf("(CTRL-C to abort) ");
- }
- printf("... %s\n", (error) ? "fail" : "ok");
- return (error);
-}
-
-static int
-cb_dumphdr(struct pmap_md *md, int seqnr, void *arg)
-{
- struct dumperinfo *di = (struct dumperinfo*)arg;
- Elf_Phdr phdr;
- int error;
-
- bzero(&phdr, sizeof(phdr));
- phdr.p_type = PT_LOAD;
- phdr.p_flags = PF_R; /* XXX */
- phdr.p_offset = fileofs;
- phdr.p_vaddr = md->md_vaddr;
- phdr.p_paddr = md->md_paddr;
- phdr.p_filesz = md->md_size;
- phdr.p_memsz = md->md_size;
- phdr.p_align = PAGE_SIZE;
-
- error = buf_write(di, (char*)&phdr, sizeof(phdr));
- fileofs += phdr.p_filesz;
- return (error);
-}
-
-static int
-cb_size(struct pmap_md *md, int seqnr, void *arg)
-{
- uint32_t *sz = (uint32_t*)arg;
-
- *sz += md->md_size;
- return (0);
-}
-
-static int
-foreach_chunk(callback_t cb, void *arg)
-{
- struct pmap_md *md;
- int error, seqnr;
-
- seqnr = 0;
- md = pmap_scan_md(NULL);
- while (md != NULL) {
- error = (*cb)(md, seqnr++, arg);
- if (error)
- return (-error);
- md = pmap_scan_md(md);
- }
- return (seqnr);
-}
-
-int
-dumpsys(struct dumperinfo *di)
-{
- Elf_Ehdr ehdr;
- uint32_t dumpsize;
- off_t hdrgap;
- size_t hdrsz;
- int error;
-
- bzero(&ehdr, sizeof(ehdr));
- ehdr.e_ident[EI_MAG0] = ELFMAG0;
- ehdr.e_ident[EI_MAG1] = ELFMAG1;
- ehdr.e_ident[EI_MAG2] = ELFMAG2;
- ehdr.e_ident[EI_MAG3] = ELFMAG3;
- ehdr.e_ident[EI_CLASS] = ELF_TARG_CLASS;
-#if BYTE_ORDER == LITTLE_ENDIAN
- ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
-#else
- ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
-#endif
- ehdr.e_ident[EI_VERSION] = EV_CURRENT;
- ehdr.e_ident[EI_OSABI] = ELFOSABI_STANDALONE; /* XXX big picture? */
- ehdr.e_type = ET_CORE;
- ehdr.e_machine = ELF_ARCH; /* Defined in powerpc/include/elf.h */
- ehdr.e_phoff = sizeof(ehdr);
- ehdr.e_ehsize = sizeof(ehdr);
- ehdr.e_phentsize = sizeof(Elf_Phdr);
- ehdr.e_shentsize = sizeof(Elf_Shdr);
-
- /* Calculate dump size. */
- dumpsize = 0L;
- ehdr.e_phnum = foreach_chunk(cb_size, &dumpsize);
- hdrsz = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize;
- fileofs = MD_ALIGN(hdrsz);
- dumpsize += fileofs;
- hdrgap = fileofs - DEV_ALIGN(hdrsz);
-
- /* For block devices, determine the dump offset on the device. */
- if (di->mediasize > 0) {
- if (di->mediasize <
- SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2) {
- error = ENOSPC;
- goto fail;
- }
- dumplo = di->mediaoffset + di->mediasize - dumpsize;
- dumplo -= sizeof(kdh) * 2;
- } else
- dumplo = 0;
-
- mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_POWERPC_VERSION, dumpsize,
- di->blocksize);
-
- printf("Dumping %u MB (%d chunks)\n", dumpsize >> 20,
- ehdr.e_phnum);
-
- /* Dump leader */
- error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
- if (error)
- goto fail;
- dumplo += sizeof(kdh);
-
- /* Dump ELF header */
- error = buf_write(di, (char*)&ehdr, sizeof(ehdr));
- if (error)
- goto fail;
-
- /* Dump program headers */
- error = foreach_chunk(cb_dumphdr, di);
- if (error < 0)
- goto fail;
- buf_flush(di);
-
- /*
- * All headers are written using blocked I/O, so we know the
- * current offset is (still) block aligned. Skip the alignement
- * in the file to have the segment contents aligned at page
- * boundary. We cannot use MD_ALIGN on dumplo, because we don't
- * care and may very well be unaligned within the dump device.
- */
- dumplo += hdrgap;
-
- /* Dump memory chunks (updates dumplo) */
- error = foreach_chunk(cb_dumpdata, di);
- if (error < 0)
- goto fail;
-
- /* Dump trailer */
- error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
- if (error)
- goto fail;
-
- /* Signal completion, signoff and exit stage left. */
- dump_write(di, NULL, 0, 0, 0);
- printf("\nDump complete\n");
- return (0);
-
- fail:
- if (error < 0)
- error = -error;
-
- if (error == ECANCELED)
- printf("\nDump aborted\n");
- else if (error == ENOSPC)
- printf("\nDump failed. Partition too small.\n");
- else
- printf("\n** DUMP FAILED (ERROR %d) **\n", error);
- return (error);
-}
Index: sys/powerpc/powerpc/mmu_if.m
===================================================================
--- sys/powerpc/powerpc/mmu_if.m
+++ sys/powerpc/powerpc/mmu_if.m
@@ -107,11 +107,6 @@
return;
}
- static struct pmap_md *mmu_null_scan_md(mmu_t mmu, struct pmap_md *p)
- {
- return (NULL);
- }
-
static void *mmu_null_mapdev_attr(mmu_t mmu, vm_offset_t pa,
vm_size_t size, vm_memattr_t ma)
{
@@ -905,46 +900,36 @@
/**
* @brief Create temporary memory mapping for use by dumpsys().
*
- * @param _md The memory chunk in which the mapping lies.
- * @param _ofs The offset within the chunk of the mapping.
+ * @param _pa The physical page to map.
* @param _sz The requested size of the mapping.
- *
- * @retval vm_offset_t The virtual address of the mapping.
- *
- * The sz argument is modified to reflect the actual size of the
- * mapping.
+ * @param _va The virtual address of the mapping.
*/
-METHOD vm_offset_t dumpsys_map {
+METHOD void dumpsys_map {
mmu_t _mmu;
- struct pmap_md *_md;
- vm_size_t _ofs;
- vm_size_t *_sz;
+ vm_paddr_t _pa;
+ size_t _sz;
+ void **_va;
};
/**
* @brief Remove temporary dumpsys() mapping.
*
- * @param _md The memory chunk in which the mapping lies.
- * @param _ofs The offset within the chunk of the mapping.
+ * @param _pa The physical page to map.
+ * @param _sz The requested size of the mapping.
* @param _va The virtual address of the mapping.
*/
METHOD void dumpsys_unmap {
mmu_t _mmu;
- struct pmap_md *_md;
- vm_size_t _ofs;
- vm_offset_t _va;
+ vm_paddr_t _pa;
+ size_t _sz;
+ void *_va;
};
/**
- * @brief Scan/iterate memory chunks.
- *
- * @param _prev The previously returned chunk or NULL.
- *
- * @retval The next (or first when _prev is NULL) chunk.
+ * @brief Initialize memory chunks for dumpsys.
*/
-METHOD struct pmap_md * scan_md {
+METHOD void scan_init {
mmu_t _mmu;
- struct pmap_md *_prev;
-} DEFAULT mmu_null_scan_md;
+};
Index: sys/powerpc/powerpc/pmap_dispatch.c
===================================================================
--- sys/powerpc/powerpc/pmap_dispatch.c
+++ sys/powerpc/powerpc/pmap_dispatch.c
@@ -43,6 +43,7 @@
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/conf.h>
#include <sys/lock.h>
#include <sys/ktr.h>
#include <sys/mutex.h>
@@ -51,6 +52,8 @@
#include <vm/vm.h>
#include <vm/vm_page.h>
+#include <machine/dump.h>
+#include <machine/md_var.h>
#include <machine/mmuvar.h>
#include <machine/smp.h>
@@ -522,28 +525,28 @@
return (MMU_SYNC_ICACHE(mmu_obj, pm, va, sz));
}
-vm_offset_t
-pmap_dumpsys_map(struct pmap_md *md, vm_size_t ofs, vm_size_t *sz)
+void
+dumpsys_map_chunk(vm_paddr_t pa, size_t sz, void **va)
{
- CTR4(KTR_PMAP, "%s(%p, %#x, %#x)", __func__, md, ofs, *sz);
- return (MMU_DUMPSYS_MAP(mmu_obj, md, ofs, sz));
+ CTR4(KTR_PMAP, "%s(%#jx, %#zx, %p)", __func__, (uintmax_t)pa, sz, va);
+ return (MMU_DUMPSYS_MAP(mmu_obj, pa, sz, va));
}
void
-pmap_dumpsys_unmap(struct pmap_md *md, vm_size_t ofs, vm_offset_t va)
+dumpsys_unmap_chunk(vm_paddr_t pa, size_t sz, void *va)
{
- CTR4(KTR_PMAP, "%s(%p, %#x, %#x)", __func__, md, ofs, va);
- return (MMU_DUMPSYS_UNMAP(mmu_obj, md, ofs, va));
+ CTR4(KTR_PMAP, "%s(%#jx, %#zx, %p)", __func__, (uintmax_t)pa, sz, va);
+ return (MMU_DUMPSYS_UNMAP(mmu_obj, pa, sz, va));
}
-struct pmap_md *
-pmap_scan_md(struct pmap_md *prev)
+void
+dumpsys_md_pa_init(void)
{
- CTR2(KTR_PMAP, "%s(%p)", __func__, prev);
- return (MMU_SCAN_MD(mmu_obj, prev));
+ CTR1(KTR_PMAP, "%s()", __func__);
+ return (MMU_SCAN_INIT(mmu_obj));
}
/*
Index: sys/sparc64/include/dump.h
===================================================================
--- /dev/null
+++ sys/sparc64/include/dump.h
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 2014 EMC Corp.
+ * Copyright (c) 2014 Conrad Meyer <conrad.meyer@isilon.com>
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * 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$
+ */
+
+#ifndef _MACHINE_DUMP_H_
+#define _MACHINE_DUMP_H_
+
+#define DUMPSYS_MD_PA_NPAIRS 128
+#define DUMPSYS_HAS_MD_DUMPSYS 1
+
+void dumpsys_md_pa_init(void);
+
+static inline struct md_pa *
+dumpsys_md_pa_next(struct md_pa *p)
+{
+
+ return dumpsys_gen_md_pa_next(p);
+}
+
+static inline void
+dumpsys_wbinv_all(void)
+{
+
+ dumpsys_gen_wbinv_all();
+}
+
+static inline void
+dumpsys_unmap_chunk(vm_paddr_t pa, size_t s, void *va)
+{
+
+ dumpsys_gen_unmap_chunk(pa, s, va);
+}
+
+#endif /* !_MACHINE_DUMP_H_ */
Index: sys/sparc64/sparc64/dump_machdep.c
===================================================================
--- sys/sparc64/sparc64/dump_machdep.c
+++ sys/sparc64/sparc64/dump_machdep.c
@@ -39,62 +39,36 @@
#include <vm/vm_param.h>
#include <vm/pmap.h>
+#include <machine/dump.h>
#include <machine/metadata.h>
+#include <machine/md_var.h>
#include <machine/kerneldump.h>
#include <machine/ofw_mem.h>
#include <machine/tsb.h>
#include <machine/tlb.h>
-CTASSERT(sizeof(struct kerneldumpheader) == DEV_BSIZE);
+static off_t fileofs;
-static struct kerneldumpheader kdh;
-static off_t dumplo, dumppos;
+extern off_t dumplo;
+extern struct md_pa dump_map[DUMPSYS_MD_PA_NPAIRS];
-/* Handle buffered writes. */
-static char buffer[DEV_BSIZE];
-static vm_size_t fragsz;
-
-#define MAXDUMPSZ (MAXDUMPPGS << PAGE_SHIFT)
-
-static int
-buf_write(struct dumperinfo *di, char *ptr, size_t sz)
+void
+dumpsys_md_pa_init(void)
{
- size_t len;
- int error;
-
- while (sz) {
- len = DEV_BSIZE - fragsz;
- if (len > sz)
- len = sz;
- bcopy(ptr, buffer + fragsz, len);
- fragsz += len;
- ptr += len;
- sz -= len;
- if (fragsz == DEV_BSIZE) {
- error = dump_write(di, buffer, 0, dumplo,
- DEV_BSIZE);
- if (error)
- return error;
- dumplo += DEV_BSIZE;
- fragsz = 0;
- }
- }
+ int i;
- return (0);
+ memset(dump_map, 0, sizeof(dump_map));
+ for (i = 0; i < sparc64_nmemreg; i++) {
+ dump_map[i].md_start = sparc64_memreg[i].mr_start;
+ dump_map[i].md_size = sparc64_memreg[i].mr_size;
+ }
}
-static int
-buf_flush(struct dumperinfo *di)
+void
+dumpsys_map_chunk(vm_paddr_t pa, size_t chunk __unused, void **va)
{
- int error;
-
- if (fragsz == 0)
- return (0);
- error = dump_write(di, buffer, 0, dumplo, DEV_BSIZE);
- dumplo += DEV_BSIZE;
- fragsz = 0;
- return (error);
+ *va = (void*)TLB_PHYS_TO_DIRECT(pa);
}
static int
@@ -104,47 +78,15 @@
r.dr_pa = pa;
r.dr_size = size;
- r.dr_offs = dumppos;
- dumppos += size;
- return (buf_write(di, (char *)&r, sizeof(r)));
-}
-
-static int
-blk_dump(struct dumperinfo *di, vm_paddr_t pa, vm_size_t size)
-{
- vm_size_t pos, rsz;
- vm_offset_t va;
- int c, counter, error, twiddle;
-
- printf(" chunk at %#lx: %ld bytes ", (u_long)pa, (long)size);
-
- va = 0L;
- error = counter = twiddle = 0;
- for (pos = 0; pos < size; pos += MAXDUMPSZ, counter++) {
- if (counter % 128 == 0)
- printf("%c\b", "|/-\\"[twiddle++ & 3]);
- rsz = size - pos;
- rsz = (rsz > MAXDUMPSZ) ? MAXDUMPSZ : rsz;
- va = TLB_PHYS_TO_DIRECT(pa + pos);
- error = dump_write(di, (void *)va, 0, dumplo, rsz);
- if (error)
- break;
- dumplo += rsz;
-
- /* Check for user abort. */
- c = cncheckc();
- if (c == 0x03)
- return (ECANCELED);
- if (c != -1)
- printf("(CTRL-C to abort) ");
- }
- printf("... %s\n", (error) ? "fail" : "ok");
- return (error);
+ r.dr_offs = fileofs;
+ fileofs += size;
+ return (dumpsys_buf_write(di, (char *)&r, sizeof(r)));
}
int
dumpsys(struct dumperinfo *di)
{
+ struct kerneldumpheader kdh;
struct sparc64_dump_hdr hdr;
vm_size_t size, totsize, hdrsize;
int error, i, nreg;
@@ -189,10 +131,10 @@
hdr.dh_tsb_mask = tsb_kernel_mask;
hdr.dh_nregions = nreg;
- if (buf_write(di, (char *)&hdr, sizeof(hdr)) != 0)
+ if (dumpsys_buf_write(di, (char *)&hdr, sizeof(hdr)) != 0)
goto fail;
- dumppos = hdrsize;
+ fileofs = hdrsize;
/* Now, write out the region descriptors. */
for (i = 0; i < sparc64_nmemreg; i++) {
error = reg_write(di, sparc64_memreg[i].mr_start,
@@ -200,15 +142,12 @@
if (error != 0)
goto fail;
}
- buf_flush(di);
+ dumpsys_buf_flush(di);
/* Dump memory chunks. */
- for (i = 0; i < sparc64_nmemreg; i++) {
- error = blk_dump(di, sparc64_memreg[i].mr_start,
- sparc64_memreg[i].mr_size);
- if (error != 0)
- goto fail;
- }
+ error = dumpsys_foreach_chunk(dumpsys_cb_dumpdata, di);
+ if (error < 0)
+ goto fail;
/* Dump trailer */
error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
@@ -221,6 +160,9 @@
return (0);
fail:
+ if (error < 0)
+ error = -error;
+
/* XXX It should look more like VMS :-) */
printf("** DUMP FAILED (ERROR %d) **\n", error);
return (error);
Index: sys/sys/conf.h
===================================================================
--- sys/sys/conf.h
+++ sys/sys/conf.h
@@ -334,11 +334,30 @@
off_t mediasize; /* Space available in bytes. */
};
+struct md_pa {
+ vm_paddr_t md_start;
+ vm_paddr_t md_size;
+};
+
int set_dumper(struct dumperinfo *, const char *_devname);
int dump_write(struct dumperinfo *, void *, vm_offset_t, off_t, size_t);
int dumpsys(struct dumperinfo *);
int doadump(boolean_t);
+void dumpsys_map_chunk(vm_paddr_t, size_t, void **);
+typedef int dumpsys_callback_t(struct md_pa *, int, void *);
+int dumpsys_foreach_chunk(dumpsys_callback_t, void *);
+int dumpsys_cb_dumpdata(struct md_pa *, int, void *);
+int dumpsys_buf_write(struct dumperinfo *, char *, size_t);
+int dumpsys_buf_flush(struct dumperinfo *);
extern int dumping; /* system is dumping */
+extern int do_minidump;
+
+#if !defined(__sparc__) && !defined(__powerpc__)
+void dumpsys_gen_md_pa_init(void);
+#endif
+struct md_pa *dumpsys_gen_md_pa_next(struct md_pa *);
+void dumpsys_gen_wbinv_all(void);
+void dumpsys_gen_unmap_chunk(vm_paddr_t, size_t, void *);
#endif /* _KERNEL */
Index: sys/x86/x86/dump_machdep.c
===================================================================
--- sys/x86/x86/dump_machdep.c
+++ sys/x86/x86/dump_machdep.c
@@ -30,349 +30,19 @@
#include "opt_watchdog.h"
#include <sys/param.h>
-#include <sys/systm.h>
#include <sys/conf.h>
-#include <sys/cons.h>
-#include <sys/sysctl.h>
-#include <sys/kernel.h>
-#include <sys/kerneldump.h>
-#include <sys/watchdog.h>
+#include <sys/systm.h>
#include <vm/vm.h>
#include <vm/pmap.h>
-#include <machine/elf.h>
-#include <machine/md_var.h>
-
-#ifdef __amd64__
-#define KERNELDUMP_VERSION KERNELDUMP_AMD64_VERSION
-#define EM_VALUE EM_X86_64
-#else
-#define KERNELDUMP_VERSION KERNELDUMP_I386_VERSION
-#define EM_VALUE EM_386
-#endif
-
-CTASSERT(sizeof(struct kerneldumpheader) == 512);
-
-int do_minidump = 1;
-SYSCTL_INT(_debug, OID_AUTO, minidump, CTLFLAG_RWTUN, &do_minidump, 0,
- "Enable mini crash dumps");
-
-/*
- * Don't touch the first SIZEOF_METADATA bytes on the dump device. This
- * is to protect us from metadata and to protect metadata from us.
- */
-#define SIZEOF_METADATA (64*1024)
-
-#define MD_ALIGN(x) (((off_t)(x) + PAGE_MASK) & ~PAGE_MASK)
-#define DEV_ALIGN(x) (((off_t)(x) + (DEV_BSIZE-1)) & ~(DEV_BSIZE-1))
-
-struct md_pa {
- vm_paddr_t md_start;
- vm_paddr_t md_size;
-};
-
-typedef int callback_t(struct md_pa *, int, void *);
-static struct kerneldumpheader kdh;
-static off_t dumplo, fileofs;
-
-/* Handle buffered writes. */
-static char buffer[DEV_BSIZE];
-static size_t fragsz;
-
-/* 20 phys_avail entry pairs correspond to 10 md_pa's */
-static struct md_pa dump_map[10];
-
-static void
-md_pa_init(void)
+void
+dumpsys_map_chunk(vm_paddr_t pa, size_t chunk, void **va)
{
- int n, idx;
+ int i;
+ vm_paddr_t a;
- bzero(dump_map, sizeof(dump_map));
- for (n = 0; n < sizeof(dump_map) / sizeof(dump_map[0]); n++) {
- idx = n * 2;
- if (dump_avail[idx] == 0 && dump_avail[idx + 1] == 0)
- break;
- dump_map[n].md_start = dump_avail[idx];
- dump_map[n].md_size = dump_avail[idx + 1] - dump_avail[idx];
+ for (i = 0; i < chunk; i++) {
+ a = pa + i * PAGE_SIZE;
+ *va = pmap_kenter_temporary(trunc_page(a), i);
}
}
-
-static struct md_pa *
-md_pa_first(void)
-{
-
- return (&dump_map[0]);
-}
-
-static struct md_pa *
-md_pa_next(struct md_pa *mdp)
-{
-
- mdp++;
- if (mdp->md_size == 0)
- mdp = NULL;
- return (mdp);
-}
-
-static int
-buf_write(struct dumperinfo *di, char *ptr, size_t sz)
-{
- size_t len;
- int error;
-
- while (sz) {
- len = DEV_BSIZE - fragsz;
- if (len > sz)
- len = sz;
- bcopy(ptr, buffer + fragsz, len);
- fragsz += len;
- ptr += len;
- sz -= len;
- if (fragsz == DEV_BSIZE) {
- error = dump_write(di, buffer, 0, dumplo,
- DEV_BSIZE);
- if (error)
- return error;
- dumplo += DEV_BSIZE;
- fragsz = 0;
- }
- }
-
- return (0);
-}
-
-static int
-buf_flush(struct dumperinfo *di)
-{
- int error;
-
- if (fragsz == 0)
- return (0);
-
- error = dump_write(di, buffer, 0, dumplo, DEV_BSIZE);
- dumplo += DEV_BSIZE;
- fragsz = 0;
- return (error);
-}
-
-#define PG2MB(pgs) ((pgs + (1 << 8) - 1) >> 8)
-
-static int
-cb_dumpdata(struct md_pa *mdp, int seqnr, void *arg)
-{
- struct dumperinfo *di = (struct dumperinfo*)arg;
- vm_paddr_t a, pa;
- void *va;
- uint64_t pgs;
- size_t counter, sz, chunk;
- int i, c, error, twiddle;
- u_int maxdumppgs;
-
- error = 0; /* catch case in which chunk size is 0 */
- counter = 0; /* Update twiddle every 16MB */
- twiddle = 0;
- va = 0;
- pgs = mdp->md_size / PAGE_SIZE;
- pa = mdp->md_start;
- maxdumppgs = min(di->maxiosize / PAGE_SIZE, MAXDUMPPGS);
- if (maxdumppgs == 0) /* seatbelt */
- maxdumppgs = 1;
-
- printf(" chunk %d: %juMB (%ju pages)", seqnr, (uintmax_t)PG2MB(pgs),
- (uintmax_t)pgs);
-
- while (pgs) {
- chunk = pgs;
- if (chunk > maxdumppgs)
- chunk = maxdumppgs;
- sz = chunk << PAGE_SHIFT;
- counter += sz;
- if (counter >> 24) {
- printf(" %ju", (uintmax_t)PG2MB(pgs));
- counter &= (1<<24) - 1;
- }
- for (i = 0; i < chunk; i++) {
- a = pa + i * PAGE_SIZE;
- va = pmap_kenter_temporary(trunc_page(a), i);
- }
-
- wdog_kern_pat(WD_LASTVAL);
-
- error = dump_write(di, va, 0, dumplo, sz);
- if (error)
- break;
- dumplo += sz;
- pgs -= chunk;
- pa += sz;
-
- /* Check for user abort. */
- c = cncheckc();
- if (c == 0x03)
- return (ECANCELED);
- if (c != -1)
- printf(" (CTRL-C to abort) ");
- }
- printf(" ... %s\n", (error) ? "fail" : "ok");
- return (error);
-}
-
-static int
-cb_dumphdr(struct md_pa *mdp, int seqnr, void *arg)
-{
- struct dumperinfo *di = (struct dumperinfo*)arg;
- Elf_Phdr phdr;
- uint64_t size;
- int error;
-
- size = mdp->md_size;
- bzero(&phdr, sizeof(phdr));
- phdr.p_type = PT_LOAD;
- phdr.p_flags = PF_R; /* XXX */
- phdr.p_offset = fileofs;
- phdr.p_vaddr = mdp->md_start;
- phdr.p_paddr = mdp->md_start;
- phdr.p_filesz = size;
- phdr.p_memsz = size;
- phdr.p_align = PAGE_SIZE;
-
- error = buf_write(di, (char*)&phdr, sizeof(phdr));
- fileofs += phdr.p_filesz;
- return (error);
-}
-
-static int
-cb_size(struct md_pa *mdp, int seqnr, void *arg)
-{
- uint64_t *sz = (uint64_t*)arg;
-
- *sz += (uint64_t)mdp->md_size;
- return (0);
-}
-
-static int
-foreach_chunk(callback_t cb, void *arg)
-{
- struct md_pa *mdp;
- int error, seqnr;
-
- seqnr = 0;
- mdp = md_pa_first();
- while (mdp != NULL) {
- error = (*cb)(mdp, seqnr++, arg);
- if (error)
- return (-error);
- mdp = md_pa_next(mdp);
- }
- return (seqnr);
-}
-
-int
-dumpsys(struct dumperinfo *di)
-{
- Elf_Ehdr ehdr;
- uint64_t dumpsize;
- off_t hdrgap;
- size_t hdrsz;
- int error;
-
- if (do_minidump)
- return (minidumpsys(di));
-
- bzero(&ehdr, sizeof(ehdr));
- ehdr.e_ident[EI_MAG0] = ELFMAG0;
- ehdr.e_ident[EI_MAG1] = ELFMAG1;
- ehdr.e_ident[EI_MAG2] = ELFMAG2;
- ehdr.e_ident[EI_MAG3] = ELFMAG3;
- ehdr.e_ident[EI_CLASS] = ELF_CLASS;
-#if BYTE_ORDER == LITTLE_ENDIAN
- ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
-#else
- ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
-#endif
- ehdr.e_ident[EI_VERSION] = EV_CURRENT;
- ehdr.e_ident[EI_OSABI] = ELFOSABI_STANDALONE; /* XXX big picture? */
- ehdr.e_type = ET_CORE;
- ehdr.e_machine = EM_VALUE;
- ehdr.e_phoff = sizeof(ehdr);
- ehdr.e_flags = 0;
- ehdr.e_ehsize = sizeof(ehdr);
- ehdr.e_phentsize = sizeof(Elf_Phdr);
- ehdr.e_shentsize = sizeof(Elf_Shdr);
-
- md_pa_init();
-
- /* Calculate dump size. */
- dumpsize = 0L;
- ehdr.e_phnum = foreach_chunk(cb_size, &dumpsize);
- hdrsz = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize;
- fileofs = MD_ALIGN(hdrsz);
- dumpsize += fileofs;
- hdrgap = fileofs - DEV_ALIGN(hdrsz);
-
- /* Determine dump offset on device. */
- if (di->mediasize < SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2) {
- error = ENOSPC;
- goto fail;
- }
- dumplo = di->mediaoffset + di->mediasize - dumpsize;
- dumplo -= sizeof(kdh) * 2;
-
- mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_VERSION, dumpsize,
- di->blocksize);
-
- printf("Dumping %llu MB (%d chunks)\n", (long long)dumpsize >> 20,
- ehdr.e_phnum);
-
- /* Dump leader */
- error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
- if (error)
- goto fail;
- dumplo += sizeof(kdh);
-
- /* Dump ELF header */
- error = buf_write(di, (char*)&ehdr, sizeof(ehdr));
- if (error)
- goto fail;
-
- /* Dump program headers */
- error = foreach_chunk(cb_dumphdr, di);
- if (error < 0)
- goto fail;
- buf_flush(di);
-
- /*
- * All headers are written using blocked I/O, so we know the
- * current offset is (still) block aligned. Skip the alignement
- * in the file to have the segment contents aligned at page
- * boundary. We cannot use MD_ALIGN on dumplo, because we don't
- * care and may very well be unaligned within the dump device.
- */
- dumplo += hdrgap;
-
- /* Dump memory chunks (updates dumplo) */
- error = foreach_chunk(cb_dumpdata, di);
- if (error < 0)
- goto fail;
-
- /* Dump trailer */
- error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
- if (error)
- goto fail;
-
- /* Signal completion, signoff and exit stage left. */
- dump_write(di, NULL, 0, 0, 0);
- printf("\nDump complete\n");
- return (0);
-
- fail:
- if (error < 0)
- error = -error;
-
- if (error == ECANCELED)
- printf("\nDump aborted\n");
- else if (error == ENOSPC)
- printf("\nDump failed. Partition too small.\n");
- else
- printf("\n** DUMP FAILED (ERROR %d) **\n", error);
- return (error);
-}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Feb 19, 7:09 AM (20 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28872082
Default Alt Text
D904.id1988.diff (80 KB)
Attached To
Mode
D904: Refactor dumpsys() to remove excessive code duplication
Attached
Detach File
Event Timeline
Log In to Comment