FreeBSD Bugzilla – Attachment 148257 Details for
Bug 193873
[PATCH] Unify dumpsys() under generic kern_dump.c.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
v2 of the patch rebased on top of r273035 (past conflicting r272766)
a.patch (text/plain), 90.92 KB, created by
Conrad Meyer
on 2014-10-13 14:12:46 UTC
(
hide
)
Description:
v2 of the patch rebased on top of r273035 (past conflicting r272766)
Filename:
MIME Type:
Creator:
Conrad Meyer
Created:
2014-10-13 14:12:46 UTC
Size:
90.92 KB
patch
obsolete
>From e206b5ae3707faec0a1e34af8a822011eb44a23b Mon Sep 17 00:00:00 2001 >From: Conrad Meyer <conrad.meyer@isilon.com> >Date: Sun, 21 Sep 2014 17:29:32 -0700 >Subject: [PATCH] Unify dumpsys() under generic kern_dump.c. > >(To varying degrees by arch.) > >x86, ARM, and MIPS are all relatively similar and straightforward. Some >MD-specific methods are left in dump_machdep.c in each arch to provide >mach-dependent implementations. (Map a region temporarily for dumping, >unmap a region, iterate physical memory segments, flush WB caches.) > >Sparc and PowerPC are weirder. PowerPC had a merged dump/minidump path >that used a different md_pa structure, pmap_md, plumbed through its MMU >interface. So, that was ripped out and replaced with the standard path. > >Sparc uses its own non-ELF dumping header and that makes its dumpsys >different enough that unification wasn't an improvement. However, some >logic shared with other archs (blk_dump == cb_dumpdata) was refactored >away. > >Patch build-tested against: > - ARMv6 / CHROMEBOOK > - AMD64 / GENERIC > - i386 / GENERIC > - MIPS / WZR-300HP > - MIPS64 / SWARM64_SMP > - PPC / MPC85XX (cpu=booke) > - PPC / GENERIC (cpu=aim) > - PPC64 / GENERIC64 (cpu=aim64) > - Sparc64 / GENERIC > >Sponsored by: EMC / Isilon storage division >--- > sys/amd64/include/dump.h | 66 ++++++ > sys/arm/arm/dump_machdep.c | 324 +---------------------------- > sys/arm/include/dump.h | 61 ++++++ > sys/conf/files | 1 + > sys/conf/files.powerpc | 1 - > sys/i386/include/dump.h | 66 ++++++ > sys/kern/kern_dump.c | 395 ++++++++++++++++++++++++++++++++++++ > sys/mips/include/dump.h | 61 ++++++ > sys/mips/include/md_var.h | 1 + > sys/mips/mips/dump_machdep.c | 317 +---------------------------- > sys/powerpc/aim/mmu_oea.c | 153 ++++++-------- > sys/powerpc/aim/mmu_oea64.c | 150 ++++++-------- > sys/powerpc/booke/pmap.c | 214 +++++++++---------- > sys/powerpc/include/dump.h | 54 +++++ > sys/powerpc/include/pmap.h | 12 -- > sys/powerpc/powerpc/dump_machdep.c | 315 ---------------------------- > sys/powerpc/powerpc/mmu_if.m | 43 ++-- > sys/powerpc/powerpc/pmap_dispatch.c | 25 ++- > sys/sparc64/include/dump.h | 59 ++++++ > sys/sparc64/sparc64/dump_machdep.c | 116 +++-------- > sys/sys/conf.h | 19 ++ > sys/x86/x86/dump_machdep.c | 346 +------------------------------ > 22 files changed, 1088 insertions(+), 1711 deletions(-) > create mode 100644 sys/amd64/include/dump.h > create mode 100644 sys/arm/include/dump.h > create mode 100644 sys/i386/include/dump.h > create mode 100644 sys/kern/kern_dump.c > create mode 100644 sys/mips/include/dump.h > create mode 100644 sys/powerpc/include/dump.h > delete mode 100644 sys/powerpc/powerpc/dump_machdep.c > create mode 100644 sys/sparc64/include/dump.h > >diff --git a/sys/amd64/include/dump.h b/sys/amd64/include/dump.h >new file mode 100644 >index 0000000..8975326 >--- /dev/null (revision 0) >+++ 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_ */ >diff --git a/sys/arm/arm/dump_machdep.c b/sys/arm/arm/dump_machdep.c >index d8104d1..9137ae9 100644 >--- sys/arm/arm/dump_machdep.c (revision ) >+++ sys/arm/arm/dump_machdep.c >@@ -40,141 +40,20 @@ __FBSDID("$FreeBSD$"); > #ifdef SW_WATCHDOG > #include <sys/watchdog.h> > #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 > * have already been stopped, and their flush/invalidate was done as > * part of stopping. >@@ -182,201 +61,18 @@ cb_dumpdata(struct md_pa *mdp, int seqnr, void *arg) > cpu_idcache_wbinv_all(); > cpu_l2cache_wbinv_all(); > #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)); > } >diff --git a/sys/arm/include/dump.h b/sys/arm/include/dump.h >new file mode 100644 >index 0000000..ec31050 >--- /dev/null (revision 0) >+++ 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_ */ >diff --git a/sys/conf/files b/sys/conf/files >index 9d2a787..1359600 100644 >--- sys/conf/files (revision ) >+++ sys/conf/files >@@ -2935,10 +2935,11 @@ kern/kern_cons.c standard > kern/kern_cpu.c standard > kern/kern_cpuset.c standard > 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 > kern/kern_exec.c standard > kern/kern_exit.c standard >diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc >index 10515a5..ced3115 100644 >--- sys/conf/files.powerpc (revision ) >+++ sys/conf/files.powerpc >@@ -181,11 +181,10 @@ powerpc/powerpc/copystr.c standard > powerpc/powerpc/cpu.c standard > powerpc/powerpc/db_disasm.c optional ddb > 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 > powerpc/powerpc/fpu.c standard > powerpc/powerpc/fuswintr.c standard >diff --git a/sys/i386/include/dump.h b/sys/i386/include/dump.h >new file mode 100644 >index 0000000..5b8247e >--- /dev/null (revision 0) >+++ 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_ */ >diff --git a/sys/kern/kern_dump.c b/sys/kern/kern_dump.c >new file mode 100644 >index 0000000..a9fff83 >--- /dev/null (revision 0) >+++ sys/kern/kern_dump.c >@@ -0,0 +1,395 @@ >+/*- >+ * 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/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> >+#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 >+ * 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)) >+ >+off_t dumplo; >+ >+/* Handle buffered writes. */ >+static char buffer[DEV_BSIZE]; >+static size_t fragsz; >+ >+struct md_pa dump_map[DUMPSYS_MD_PA_NPAIRS]; >+ >+#if !defined(__sparc__) && !defined(__powerpc__) >+void >+dumpsys_gen_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]; >+ } >+} >+#endif >+ >+struct md_pa * >+dumpsys_gen_md_pa_next(struct md_pa *mdp) >+{ >+ >+ if (mdp == NULL) >+ return (&dump_map[0]); >+ >+ mdp++; >+ if (mdp->md_size == 0) >+ mdp = NULL; >+ return (mdp); >+} >+ >+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; >+ >+ 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); >+} >+ >+int >+dumpsys_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); >+} >+ >+CTASSERT(PAGE_SHIFT < 20); >+#define PG2MB(pgs) ((pgs + (1 << (20 - PAGE_SHIFT)) - 1) >> (20 - PAGE_SHIFT)) >+ >+int >+dumpsys_cb_dumpdata(struct md_pa *mdp, int seqnr, void *arg) >+{ >+ struct dumperinfo *di = (struct dumperinfo*)arg; >+ vm_paddr_t pa; >+ void *va; >+ uint64_t pgs; >+ size_t counter, sz, chunk; >+ int 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); >+ >+ dumpsys_wbinv_all(); >+ 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; >+ } >+ >+ 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; >+ 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); >+} >+ >+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) >+{ >+ 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; >+#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 = dumpsys_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); >+} >+ >+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; >+ 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); >+ >+ dumpsys_md_pa_init(); >+ >+ /* Calculate dump size. */ >+ dumpsize = 0L; >+ 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; >+ 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 %ju MB (%d chunks)\n", (uintmax_t)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 = dumpsys_buf_write(di, (char*)&ehdr, sizeof(ehdr)); >+ if (error) >+ goto fail; >+ >+ /* Dump program headers */ >+ error = dumpsys_foreach_chunk(cb_dumphdr, di); >+ if (error < 0) >+ goto fail; >+ dumpsys_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 = dumpsys_foreach_chunk(dumpsys_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); >+} >+#endif /* !DUMPSYS_HAS_MD_DUMPSYS */ >diff --git a/sys/mips/include/dump.h b/sys/mips/include/dump.h >new file mode 100644 >index 0000000..77daf26 >--- /dev/null (revision 0) >+++ 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_ */ >diff --git a/sys/mips/include/md_var.h b/sys/mips/include/md_var.h >index f3778a8..622781d 100644 >--- sys/mips/include/md_var.h (revision ) >+++ sys/mips/include/md_var.h >@@ -78,6 +78,7 @@ void busdma_swi(void); > > struct dumperinfo; > void dump_add_page(vm_paddr_t); > void dump_drop_page(vm_paddr_t); > int minidumpsys(struct dumperinfo *); >+ > #endif /* !_MACHINE_MD_VAR_H_ */ >diff --git a/sys/mips/mips/dump_machdep.c b/sys/mips/mips/dump_machdep.c >index fa96e79..dd33f3e7 100644 >--- sys/mips/mips/dump_machdep.c (revision ) >+++ sys/mips/mips/dump_machdep.c >@@ -40,329 +40,26 @@ __FBSDID("$FreeBSD$"); > #ifdef SW_WATCHDOG > #include <sys/watchdog.h> > #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; > } >diff --git a/sys/powerpc/aim/mmu_oea.c b/sys/powerpc/aim/mmu_oea.c >index 742dd70..1f69fd3 100644 >--- sys/powerpc/aim/mmu_oea.c (revision ) >+++ sys/powerpc/aim/mmu_oea.c >@@ -104,10 +104,11 @@ __FBSDID("$FreeBSD$"); > > #include "opt_kstack_pages.h" > > #include <sys/param.h> > #include <sys/kernel.h> >+#include <sys/conf.h> > #include <sys/queue.h> > #include <sys/cpuset.h> > #include <sys/ktr.h> > #include <sys/lock.h> > #include <sys/msgbuf.h> >@@ -161,12 +162,10 @@ struct ofw_map { > }; > > extern unsigned char _etext[]; > extern unsigned char _end[]; > >-extern int dumpsys_minidump; >- > /* > * Map of physical memory regions. > */ > static struct mem_region *regions; > static struct mem_region *pregions; >@@ -312,13 +311,12 @@ vm_paddr_t moea_kextract(mmu_t, vm_offset_t); > void moea_kenter_attr(mmu_t, vm_offset_t, vm_offset_t, vm_memattr_t); > void moea_kenter(mmu_t, vm_offset_t, vm_paddr_t); > 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), > MMUMETHOD(mmu_copy_page, moea_copy_page), > MMUMETHOD(mmu_copy_pages, moea_copy_pages), >@@ -361,11 +359,11 @@ static mmu_method_t moea_methods[] = { > MMUMETHOD(mmu_unmapdev, moea_unmapdev), > MMUMETHOD(mmu_kextract, moea_kextract), > 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 } > }; > >@@ -2626,102 +2624,75 @@ moea_sync_icache(mmu_t mmu, pmap_t pm, vm_offset_t va, vm_size_t sz) > sz -= len; > } > 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); > } >diff --git a/sys/powerpc/aim/mmu_oea64.c b/sys/powerpc/aim/mmu_oea64.c >index 2db7fcb..05729b6 100644 >--- sys/powerpc/aim/mmu_oea64.c (revision ) >+++ sys/powerpc/aim/mmu_oea64.c >@@ -105,10 +105,11 @@ __FBSDID("$FreeBSD$"); > #include "opt_compat.h" > #include "opt_kstack_pages.h" > > #include <sys/param.h> > #include <sys/kernel.h> >+#include <sys/conf.h> > #include <sys/queue.h> > #include <sys/cpuset.h> > #include <sys/ktr.h> > #include <sys/lock.h> > #include <sys/msgbuf.h> >@@ -185,12 +186,10 @@ struct ofw_map { > }; > > extern unsigned char _etext[]; > extern unsigned char _end[]; > >-extern int dumpsys_minidump; >- > /* > * Map of physical memory regions. > */ > static struct mem_region *regions; > static struct mem_region *pregions; >@@ -325,13 +324,13 @@ vm_paddr_t moea64_kextract(mmu_t, vm_offset_t); > void moea64_page_set_memattr(mmu_t, vm_page_t m, vm_memattr_t ma); > void moea64_kenter_attr(mmu_t, vm_offset_t, vm_offset_t, vm_memattr_t ma); > 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), > MMUMETHOD(mmu_copy_page, moea64_copy_page), > MMUMETHOD(mmu_copy_pages, moea64_copy_pages), >@@ -373,11 +372,11 @@ static mmu_method_t moea64_methods[] = { > MMUMETHOD(mmu_unmapdev, moea64_unmapdev), > MMUMETHOD(mmu_kextract, moea64_kextract), > 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 } > }; > >@@ -2610,99 +2609,74 @@ moea64_sync_icache(mmu_t mmu, pmap_t pm, vm_offset_t va, vm_size_t sz) > sz -= len; > } > 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); > } >diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c >index 942ad12..a61fff4 100644 >--- sys/powerpc/booke/pmap.c (revision ) >+++ sys/powerpc/booke/pmap.c >@@ -50,10 +50,11 @@ > > #include <sys/cdefs.h> > __FBSDID("$FreeBSD$"); > > #include <sys/param.h> >+#include <sys/conf.h> > #include <sys/malloc.h> > #include <sys/ktr.h> > #include <sys/proc.h> > #include <sys/user.h> > #include <sys/queue.h> >@@ -98,12 +99,10 @@ __FBSDID("$FreeBSD$"); > #define debugf(fmt, args...) > #endif > > #define TODO panic("%s: not implemented", __func__); > >-extern int dumpsys_minidump; >- > extern unsigned char _etext[]; > extern unsigned char _end[]; > > extern uint32_t *bootinfo; > >@@ -320,15 +319,15 @@ static void mmu_booke_kenter(mmu_t, vm_offset_t, vm_paddr_t); > static void mmu_booke_kenter_attr(mmu_t, vm_offset_t, vm_paddr_t, vm_memattr_t); > static void mmu_booke_kremove(mmu_t, vm_offset_t); > 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 */ > MMUMETHOD(mmu_clear_modify, mmu_booke_clear_modify), > MMUMETHOD(mmu_copy, mmu_booke_copy), >@@ -379,11 +378,11 @@ static mmu_method_t mmu_booke_methods[] = { > MMUMETHOD(mmu_unmapdev, mmu_booke_unmapdev), > > /* 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 } > }; > > MMU_DEF(booke_mmu, MMU_TYPE_BOOKE, mmu_booke_methods, 0); >@@ -2532,143 +2531,128 @@ mmu_booke_dev_direct_mapped(mmu_t mmu, vm_paddr_t pa, vm_size_t size) > } > > 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); > } > > /* > * Map a set of physical memory pages into the kernel virtual address space. > * Return a pointer to where it is mapped. This routine is intended to be used >diff --git a/sys/powerpc/include/dump.h b/sys/powerpc/include/dump.h >new file mode 100644 >index 0000000..83c18fd >--- /dev/null (revision 0) >+++ 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_ */ >diff --git a/sys/powerpc/include/pmap.h b/sys/powerpc/include/pmap.h >index 663cd1a..9a853f6 100644 >--- sys/powerpc/include/pmap.h (revision ) >+++ sys/powerpc/include/pmap.h >@@ -72,17 +72,10 @@ > #include <machine/sr.h> > #include <machine/pte.h> > #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) > #define NPMAPS 32768 > #endif /* !defined(NPMAPS) */ >@@ -250,15 +243,10 @@ extern vm_offset_t virtual_end; > > extern vm_offset_t msgbuf_phys; > > 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 > > #endif /* !_MACHINE_PMAP_H_ */ >diff --git a/sys/powerpc/powerpc/dump_machdep.c b/sys/powerpc/powerpc/dump_machdep.c >deleted file mode 100644 >index 14e2f0f..0000000 >--- sys/powerpc/powerpc/dump_machdep.c (revision ) >+++ /dev/null >@@ -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); >-} >diff --git a/sys/powerpc/powerpc/mmu_if.m b/sys/powerpc/powerpc/mmu_if.m >index 5c44b71..caf0fb0 100644 >--- sys/powerpc/powerpc/mmu_if.m (revision ) >+++ sys/powerpc/powerpc/mmu_if.m >@@ -105,15 +105,10 @@ CODE { > vm_ooffset_t offset, vm_offset_t *addr, vm_size_t size) > { > 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) > { > return MMU_MAPDEV(mmu, pa, size); > } >@@ -903,48 +898,38 @@ METHOD void sync_icache { > > > /** > * @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; >+}; >diff --git a/sys/powerpc/powerpc/pmap_dispatch.c b/sys/powerpc/powerpc/pmap_dispatch.c >index 7f3f913..39169be 100644 >--- sys/powerpc/powerpc/pmap_dispatch.c (revision ) >+++ sys/powerpc/powerpc/pmap_dispatch.c >@@ -41,18 +41,21 @@ __FBSDID("$FreeBSD$"); > * as the PMAP layer makes extensive use of mutexes. > */ > > #include <sys/param.h> > #include <sys/kernel.h> >+#include <sys/conf.h> > #include <sys/lock.h> > #include <sys/ktr.h> > #include <sys/mutex.h> > #include <sys/systm.h> > > #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> > > #include "mmu_if.h" > >@@ -520,32 +523,32 @@ pmap_sync_icache(pmap_t pm, vm_offset_t va, vm_size_t sz) > > CTR4(KTR_PMAP, "%s(%p, %#x, %#x)", __func__, pm, va, sz); > 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)); > } > > /* > * MMU install routines. Highest priority wins, equal priority also > * overrides allowing last-set to win. >diff --git a/sys/sparc64/include/dump.h b/sys/sparc64/include/dump.h >new file mode 100644 >index 0000000..2f714c0 >--- /dev/null (revision 0) >+++ 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_ */ >diff --git a/sys/sparc64/sparc64/dump_machdep.c b/sys/sparc64/sparc64/dump_machdep.c >index 5af21cc..d85bdcb 100644 >--- sys/sparc64/sparc64/dump_machdep.c (revision ) >+++ sys/sparc64/sparc64/dump_machdep.c >@@ -37,116 +37,58 @@ __FBSDID("$FreeBSD$"); > > #include <vm/vm.h> > #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 > reg_write(struct dumperinfo *di, vm_paddr_t pa, vm_size_t size) > { > struct sparc64_dump_reg r; > > 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; > > /* Calculate dump size. */ >@@ -187,30 +129,27 @@ dumpsys(struct dumperinfo *di) > hdr.dh_tsb_pa = tsb_kernel_phys; > hdr.dh_tsb_size = tsb_kernel_size; > 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, > sparc64_memreg[i].mr_size); > 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)); > if (error) > goto fail; >@@ -219,9 +158,12 @@ dumpsys(struct dumperinfo *di) > dump_write(di, NULL, 0, 0, 0); > printf("\nDump complete\n"); > return (0); > > fail: >+ if (error < 0) >+ error = -error; >+ > /* XXX It should look more like VMS :-) */ > printf("** DUMP FAILED (ERROR %d) **\n", error); > return (error); > } >diff --git a/sys/sys/conf.h b/sys/sys/conf.h >index f8a9a3c..fc92f71 100644 >--- sys/sys/conf.h (revision ) >+++ sys/sys/conf.h >@@ -332,14 +332,33 @@ struct dumperinfo { > u_int maxiosize; /* Max size allowed for an individual I/O */ > off_t mediaoffset; /* Initial offset in bytes. */ > 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 */ > > #endif /* !_SYS_CONF_H_ */ >diff --git a/sys/x86/x86/dump_machdep.c b/sys/x86/x86/dump_machdep.c >index 4e048bf..601557f 100644 >--- sys/x86/x86/dump_machdep.c (revision ) >+++ sys/x86/x86/dump_machdep.c >@@ -28,351 +28,21 @@ > __FBSDID("$FreeBSD$"); > > #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); >-} >-- >1.9.3 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 193873
:
147599
|
147868
|
147869
|
148257
|
149303