diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2007-03-03 21:37:28 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2007-03-03 21:37:28 +0000 |
commit | 301ce3789c0dded4c40ebb4c1197dee00cf0fc3e (patch) | |
tree | 44351c56ccd077c95b601f112ad6c7c4d156911e | |
parent | 8f58ce59b66d35d5d484c5cfb9f5967571339ac9 (diff) |
Kernel crash dumps and associated libkvm bits for landisk.
-rw-r--r-- | distrib/sets/lists/base/md.landisk | 2 | ||||
-rw-r--r-- | distrib/sets/lists/comp/md.landisk | 2 | ||||
-rw-r--r-- | lib/libkvm/kvm_sh.c | 144 | ||||
-rw-r--r-- | sys/arch/landisk/include/kcore.h | 1 | ||||
-rw-r--r-- | sys/arch/landisk/landisk/autoconf.c | 8 | ||||
-rw-r--r-- | sys/arch/landisk/landisk/machdep.c | 94 | ||||
-rw-r--r-- | sys/arch/sh/include/cpu.h | 5 | ||||
-rw-r--r-- | sys/arch/sh/include/kcore.h | 32 | ||||
-rw-r--r-- | sys/arch/sh/include/param.h | 14 | ||||
-rw-r--r-- | sys/arch/sh/sh/sh_machdep.c | 153 |
10 files changed, 401 insertions, 54 deletions
diff --git a/distrib/sets/lists/base/md.landisk b/distrib/sets/lists/base/md.landisk index a9380783e2e..0ddb4ba2883 100644 --- a/distrib/sets/lists/base/md.landisk +++ b/distrib/sets/lists/base/md.landisk @@ -1557,6 +1557,7 @@ ./usr/libdata/perl5/site_perl/sh-openbsd/landisk/ieeefp.ph ./usr/libdata/perl5/site_perl/sh-openbsd/landisk/internal_types.ph ./usr/libdata/perl5/site_perl/sh-openbsd/landisk/intr.ph +./usr/libdata/perl5/site_perl/sh-openbsd/landisk/kcore.ph ./usr/libdata/perl5/site_perl/sh-openbsd/landisk/limits.ph ./usr/libdata/perl5/site_perl/sh-openbsd/landisk/loadfile_machdep.ph ./usr/libdata/perl5/site_perl/sh-openbsd/landisk/lock.ph @@ -1954,6 +1955,7 @@ ./usr/libdata/perl5/site_perl/sh-openbsd/sh/intcreg.ph ./usr/libdata/perl5/site_perl/sh-openbsd/sh/internal_types.ph ./usr/libdata/perl5/site_perl/sh-openbsd/sh/intr.ph +./usr/libdata/perl5/site_perl/sh-openbsd/sh/kcore.ph ./usr/libdata/perl5/site_perl/sh-openbsd/sh/limits.ph ./usr/libdata/perl5/site_perl/sh-openbsd/sh/lock.ph ./usr/libdata/perl5/site_perl/sh-openbsd/sh/locore.ph diff --git a/distrib/sets/lists/comp/md.landisk b/distrib/sets/lists/comp/md.landisk index 4bf44929a01..ee64dae9285 100644 --- a/distrib/sets/lists/comp/md.landisk +++ b/distrib/sets/lists/comp/md.landisk @@ -172,6 +172,7 @@ ./usr/include/landisk/ieeefp.h ./usr/include/landisk/internal_types.h ./usr/include/landisk/intr.h +./usr/include/landisk/kcore.h ./usr/include/landisk/limits.h ./usr/include/landisk/loadfile_machdep.h ./usr/include/landisk/lock.h @@ -220,6 +221,7 @@ ./usr/include/sh/intcreg.h ./usr/include/sh/internal_types.h ./usr/include/sh/intr.h +./usr/include/sh/kcore.h ./usr/include/sh/limits.h ./usr/include/sh/lock.h ./usr/include/sh/locore.h diff --git a/lib/libkvm/kvm_sh.c b/lib/libkvm/kvm_sh.c index 4940acbb7d3..52326a2eec4 100644 --- a/lib/libkvm/kvm_sh.c +++ b/lib/libkvm/kvm_sh.c @@ -1,47 +1,43 @@ -/* $OpenBSD: kvm_sh.c,v 1.1 2006/10/10 22:07:10 miod Exp $ */ +/* $OpenBSD: kvm_sh.c,v 1.2 2007/03/03 21:37:27 miod Exp $ */ /* - * Copyright (c) 2002, Miodrag Vallat. - * All rights reserved. + * Copyright (c) 2007 Miodrag Vallat. * - * 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. + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice, this permission notice, and the disclaimer below + * appear in all copies. * - * 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. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/param.h> +#include <sys/core.h> +#include <sys/kcore.h> #include <unistd.h> #include <stdlib.h> +#include <nlist.h> #include <kvm.h> #include <db.h> #include "kvm_private.h" +#include <machine/cpu.h> +#include <machine/kcore.h> +#include <machine/pte.h> +#include <machine/vmparam.h> + void _kvm_freevtop(kvm_t *kd) { - if (kd->vmst != NULL) { - free(kd->vmst); - kd->vmst = NULL; - } } int @@ -50,17 +46,97 @@ _kvm_initvtop(kvm_t *kd) return (0); } +/* + * Translate a kernel virtual address to a physical address by walking + * the kernels page table. + */ + +/* Stolen from sys/arch/sh/include/pmap.h we can't really include */ +#define __PMAP_PTP_N 512 /* # of page table page maps 2GB. */ +/* Stolen from sys/arch/sh/sh/pmap.c */ +#define __PMAP_PTP_SHIFT 22 +#define __PMAP_PTP_PG_N (PAGE_SIZE / sizeof(pt_entry_t)) +#define __PMAP_PTP_INDEX(va) (((va) >> __PMAP_PTP_SHIFT) & (__PMAP_PTP_N - 1)) +#define __PMAP_PTP_OFSET(va) ((va >> PGSHIFT) & (__PMAP_PTP_PG_N - 1)) + int _kvm_kvatop(kvm_t *kd, u_long va, paddr_t *pa) { - int offset; + cpu_kcore_hdr_t *h = kd->cpu_data; + u_int l1idx, l2idx; + vaddr_t l2va; + pt_entry_t l1pte, l2pte; + off_t pteoffset; if (ISALIVE(kd)) { _kvm_err(kd, 0, "vatop called in live kernel!"); return (0); } - /* TODO */ + /* + * P1 and P2 segments addresses are trivial. + */ + if (va >= SH3_P1SEG_BASE && va <= SH3_P1SEG_END) { + *pa = SH3_P1SEG_TO_PHYS(va); + return (int)((vaddr_t)SH3_P1SEG_END + 1 - va); + } + if (va >= SH3_P2SEG_BASE && va <= SH3_P2SEG_END) { + *pa = SH3_P2SEG_TO_PHYS(va); + return (int)((vaddr_t)SH3_P2SEG_END + 1 - va); + } + + /* + * P3 segment addresses need kernel page table walk. + */ + if (va >= SH3_P3SEG_BASE && va < SH3_P3SEG_END) { + l1idx = __PMAP_PTP_INDEX(va - VM_MIN_KERNEL_ADDRESS); + l2idx = __PMAP_PTP_OFSET(va); + + /* read level 1 pte */ + pteoffset = h->kcore_kptp + sizeof(pt_entry_t) * l1idx; + if (_kvm_pread(kd, kd->pmfd, (char *)&l1pte, sizeof(l1pte), + _kvm_pa2off(kd, pteoffset)) != sizeof(l1pte)) { + _kvm_syserr(kd, 0, "could not read level 1 pte"); + goto bad; + } + + /* check pte for validity */ + if ((l1pte & PG_V) == 0) { + _kvm_err(kd, 0, "invalid level 1 pte: no valid bit"); + goto bad; + } + + l2va = l1pte & PG_PPN; + if (l2va < SH3_P1SEG_BASE || l2va > SH3_P1SEG_END) { + _kvm_err(kd, 0, "invalid level 1 pte: out of P1"); + goto bad; + } + + /* read level 2 pte */ + pteoffset = SH3_P1SEG_TO_PHYS(l2va) + + sizeof(pt_entry_t) * l2idx; + if (_kvm_pread(kd, kd->pmfd, (char *)&l2pte, sizeof(l2pte), + _kvm_pa2off(kd, pteoffset)) != sizeof(l2pte)) { + _kvm_syserr(kd, 0, "could not read level 2 pte"); + goto bad; + } + + /* check pte for validity */ + if ((l2pte & PG_V) == 0) { + _kvm_err(kd, 0, "invalid level 2 pte: no valid bit"); + goto bad; + } + + *pa = (l2pte & PG_PPN) | (va & PAGE_MASK); + return (PAGE_SIZE - (va & PAGE_MASK)); + } + + /* + * All other addresses are incorrect. + */ + _kvm_err(kd, 0, "not a kernel virtual address"); +bad: + *pa = (paddr_t)-1; return (0); } @@ -70,7 +146,17 @@ _kvm_kvatop(kvm_t *kd, u_long va, paddr_t *pa) off_t _kvm_pa2off(kvm_t *kd, paddr_t pa) { - /* TODO */ + cpu_kcore_hdr_t *h = kd->cpu_data; + phys_ram_seg_t *seg = h->kcore_segs; + off_t off = kd->dump_off; + u_int i; + + for (i = h->kcore_nsegs; i != 0; i--) { + if (pa >= seg->start && pa < seg->start + seg->size) + return (off + (pa - seg->start)); + off += seg->size; + } + + _kvm_err(kd, 0, "physical address out of the image (%lx)", pa); return (0); } - diff --git a/sys/arch/landisk/include/kcore.h b/sys/arch/landisk/include/kcore.h new file mode 100644 index 00000000000..9aafa045767 --- /dev/null +++ b/sys/arch/landisk/include/kcore.h @@ -0,0 +1 @@ +#include <sh/kcore.h> diff --git a/sys/arch/landisk/landisk/autoconf.c b/sys/arch/landisk/landisk/autoconf.c index 3f99c61e347..7facbd1c6fc 100644 --- a/sys/arch/landisk/landisk/autoconf.c +++ b/sys/arch/landisk/landisk/autoconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: autoconf.c,v 1.4 2006/11/06 19:42:52 miod Exp $ */ +/* $OpenBSD: autoconf.c,v 1.5 2007/03/03 21:37:27 miod Exp $ */ /* $NetBSD: autoconf.c,v 1.1 2006/09/01 21:26:18 uwe Exp $ */ /*- @@ -43,6 +43,7 @@ #include <dev/cons.h> +#include <machine/cpu.h> #include <machine/intr.h> int cold = 1; @@ -51,9 +52,6 @@ struct device *booted_device; struct device *root_device; void diskconf(void); -#ifdef notyet -void dumpconf(void); -#endif struct device *parsedisk(char *, int, int, dev_t *); void setroot(void); int findblkmajor(struct device *); @@ -85,9 +83,7 @@ diskconf(void) printf("boot device: %s\n", booted_device ? booted_device->dv_xname : "<unknown>"); setroot(); -#ifdef notyet dumpconf(); -#endif } static struct nam2blk { diff --git a/sys/arch/landisk/landisk/machdep.c b/sys/arch/landisk/landisk/machdep.c index cce14dadb6a..82a34ba864f 100644 --- a/sys/arch/landisk/landisk/machdep.c +++ b/sys/arch/landisk/landisk/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.8 2007/02/06 23:13:37 miod Exp $ */ +/* $OpenBSD: machdep.c,v 1.9 2007/03/03 21:37:27 miod Exp $ */ /* $NetBSD: machdep.c,v 1.1 2006/09/01 21:26:18 uwe Exp $ */ /*- @@ -81,6 +81,9 @@ #include <sys/mount.h> #include <sys/reboot.h> #include <sys/sysctl.h> +#include <sys/exec.h> +#include <sys/core.h> +#include <sys/kcore.h> #include <uvm/uvm_extern.h> @@ -95,6 +98,7 @@ #include <sh/mmu_sh4.h> #include <machine/cpu.h> +#include <machine/kcore.h> #include <landisk/landisk/landiskreg.h> @@ -109,6 +113,7 @@ char machine[] = MACHINE; /* landisk */ __dead void landisk_startup(int, char *); __dead void main(void); +void cpu_init_kcore_hdr(void); extern u_int32_t getramsize(void); @@ -153,6 +158,7 @@ landisk_startup(int howto, char *_esym) uvm_page_physload(atop(IOM_RAM_BEGIN), atop(IOM_RAM_BEGIN + ramsize), kernend, atop(IOM_RAM_BEGIN + ramsize), VM_FREELIST_DEFAULT); + cpu_init_kcore_hdr(); /* need to be done before pmap_bootstrap */ /* Initialize proc0 u-area */ sh_proc0_init(); @@ -193,7 +199,8 @@ boot(int howto) { if (cold) { - howto |= RB_HALT; + if ((howto & RB_USERREQ) == 0) + howto |= RB_HALT; goto haltsys; } @@ -204,19 +211,18 @@ boot(int howto) * If we've been adjusting the clock, the todr * will be out of synch; adjust it now. */ - resettodr(); + if ((howto & RB_TIMEBAD) == 0) + resettodr(); + else + printf("WARNING: not updating battery clock\n"); } - /* wait 1s */ - delay(1 * 1000 * 1000); - /* Disable interrupts. */ splhigh(); /* Do a dump if requested. */ - if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) { + if (howto & RB_DUMP) dumpsys(); - } haltsys: doshutdownhooks(); @@ -225,6 +231,7 @@ haltsys: _reg_write_1(LANDISK_PWRMNG, PWRMNG_POWEROFF); delay(1 * 1000 * 1000); printf("POWEROFF FAILED!\n"); + howto |= RB_HALT; } if (howto & RB_HALT) { @@ -376,3 +383,74 @@ InitializeBsc(void) _reg_write_2(SH4_FRQCR, FRQCR_VAL); } #endif /* !DONT_INIT_BSC */ + +/* + * Dump the machine-dependent dump header. + */ +u_int +cpu_dump(int (*dump)(dev_t, daddr_t, caddr_t, size_t), daddr_t *blknop) +{ + extern cpu_kcore_hdr_t cpu_kcore_hdr; + char buf[dbtob(1)]; + cpu_kcore_hdr_t *h; + kcore_seg_t *kseg; + int rc; + +#ifdef DIAGNOSTIC + if (cpu_dumpsize() > btodb(sizeof buf)) { + printf("buffer too small in cpu_dump, "); + return (EINVAL); /* "aborted" */ + } +#endif + + bzero(buf, sizeof buf); + kseg = (kcore_seg_t *)buf; + h = (cpu_kcore_hdr_t *)(buf + ALIGN(sizeof(kcore_seg_t))); + + /* Create the segment header */ + CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU); + kseg->c_size = dbtob(1) - ALIGN(sizeof(kcore_seg_t)); + + bcopy(&cpu_kcore_hdr, h, sizeof(*h)); + /* We can now fill kptp in the header... */ + h->kcore_kptp = SH3_P1SEG_TO_PHYS((vaddr_t)pmap_kernel()->pm_ptp); + + rc = (*dump)(dumpdev, *blknop, buf, sizeof buf); + *blknop += btodb(sizeof buf); + return (rc); +} + +/* + * Return the size of the machine-dependent dump header, in disk blocks. + */ +u_int +cpu_dumpsize() +{ + u_int size; + + size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)); + return (btodb(roundup(size, dbtob(1)))); +} + +/* + * Fill the machine-dependent dump header. + */ +void +cpu_init_kcore_hdr() +{ + extern cpu_kcore_hdr_t cpu_kcore_hdr; + cpu_kcore_hdr_t *h = &cpu_kcore_hdr; + phys_ram_seg_t *seg = cpu_kcore_hdr.kcore_segs; + struct vm_physseg *physseg = vm_physmem; + u_int i; + + bzero(h, sizeof(*h)); + + h->kcore_nsegs = min(NPHYS_RAM_SEGS, (u_int)vm_nphysseg); + for (i = h->kcore_nsegs; i != 0; i--) { + seg->start = ptoa(physseg->start); + seg->size = (psize_t)ptoa(physseg->end - physseg->start); + seg++; + physseg++; + } +} diff --git a/sys/arch/sh/include/cpu.h b/sys/arch/sh/include/cpu.h index 721d3275b77..a4906007317 100644 --- a/sys/arch/sh/include/cpu.h +++ b/sys/arch/sh/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.5 2007/03/02 06:11:54 miod Exp $ */ +/* $OpenBSD: cpu.h,v 1.6 2007/03/03 21:37:27 miod Exp $ */ /* $NetBSD: cpu.h,v 1.41 2006/01/21 04:24:12 uwe Exp $ */ /*- @@ -207,6 +207,9 @@ void savectx(struct pcb *); struct fpreg; void fpu_save(struct fpreg *); void fpu_restore(struct fpreg *); +u_int cpu_dump(int (*)(dev_t, daddr_t, caddr_t, size_t), daddr_t *); +u_int cpu_dumpsize(void); +void dumpconf(void); void dumpsys(void); #endif /* _KERNEL */ #endif /* !_SH_CPU_H_ */ diff --git a/sys/arch/sh/include/kcore.h b/sys/arch/sh/include/kcore.h new file mode 100644 index 00000000000..29e3bc0800c --- /dev/null +++ b/sys/arch/sh/include/kcore.h @@ -0,0 +1,32 @@ +/* $OpenBSD: kcore.h,v 1.1 2007/03/03 21:37:27 miod Exp $ */ + +/* + * Copyright (c) 2007 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice, this permission notice, and the disclaimer below + * appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SH_KCORE_H_ +#define _SH_KCORE_H_ + +/* this should be >= VM_PHYSSEG_MAX from <machine/vmparam.h> */ +#define NPHYS_RAM_SEGS 8 + +typedef struct cpu_kcore_hdr { + paddr_t kcore_kptp; + unsigned int kcore_nsegs; + phys_ram_seg_t kcore_segs[NPHYS_RAM_SEGS]; +} cpu_kcore_hdr_t; + +#endif /* _SH_KCORE_H_ */ diff --git a/sys/arch/sh/include/param.h b/sys/arch/sh/include/param.h index a2eec2d29ed..efb8a4b9dbb 100644 --- a/sys/arch/sh/include/param.h +++ b/sys/arch/sh/include/param.h @@ -1,4 +1,4 @@ -/* $OpenBSD: param.h,v 1.2 2006/11/03 17:28:01 drahn Exp $ */ +/* $OpenBSD: param.h,v 1.3 2007/03/03 21:37:27 miod Exp $ */ /* $NetBSD: param.h,v 1.15 2006/08/28 13:43:35 yamt Exp $ */ /*- @@ -104,13 +104,17 @@ #define MSGBUFSIZE NBPG /* default message buffer size */ #endif +/* pages to bytes */ #define btoc(x) (((x) + PAGE_MASK) >> PAGE_SHIFT) #define ctob(x) ((x) << PAGE_SHIFT) -#define btodb(bytes) /* calculates (bytes / DEV_BSIZE) */ \ - ((bytes) >> DEV_BSHIFT) -#define dbtob(db) /* calculates (db * DEV_BSIZE) */ \ - ((db) << DEV_BSHIFT) +/* pages to disk blocks */ +#define ctod(x) ((x) << (PAGE_SHIFT - DEV_BSHIFT)) +#define dtoc(x) ((x) >> (PAGE_SHIFT - DEV_BSHIFT)) + +/* bytes to disk blocks */ +#define btodb(x) ((x) >> DEV_BSHIFT) +#define dbtob(x) ((x) << DEV_BSHIFT) /* * Constants related to network buffer management. diff --git a/sys/arch/sh/sh/sh_machdep.c b/sys/arch/sh/sh/sh_machdep.c index 05b6bced8e8..a6b1e05916b 100644 --- a/sys/arch/sh/sh/sh_machdep.c +++ b/sys/arch/sh/sh/sh_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sh_machdep.c,v 1.9 2007/03/02 06:11:54 miod Exp $ */ +/* $OpenBSD: sh_machdep.c,v 1.10 2007/03/03 21:37:27 miod Exp $ */ /* $NetBSD: sh3_machdep.c,v 1.59 2006/03/04 01:13:36 uwe Exp $ */ /* @@ -101,6 +101,9 @@ #include <sys/user.h> #include <sys/sched.h> #include <sys/msg.h> +#include <sys/conf.h> +#include <sys/core.h> +#include <sys/kcore.h> #include <uvm/uvm_extern.h> @@ -112,6 +115,7 @@ #include <sh/mmu.h> #include <sh/trap.h> #include <sh/intr.h> +#include <sh/kcore.h> #ifdef NBUF int nbuf = NBUF; @@ -143,7 +147,7 @@ struct user *proc0paddr; /* init_main.c use this. */ struct pcb *curpcb; struct md_upte *curupte; /* SH3 wired u-area hack */ -#define VBR (uint8_t *)SH3_PHYS_TO_P1SEG(IOM_RAM_BEGIN) +#define VBR (u_int8_t *)SH3_PHYS_TO_P1SEG(IOM_RAM_BEGIN) vaddr_t ram_start = SH3_PHYS_TO_P1SEG(IOM_RAM_BEGIN); /* exception handler holder (sh/sh/vectors.S) */ extern char sh_vector_generic[], sh_vector_generic_end[]; @@ -160,9 +164,10 @@ caddr_t allocsys(caddr_t); /* * These variables are needed by /sbin/savecore */ -uint32_t dumpmag = 0x8fca0101; /* magic number */ -int dumpsize; /* pages */ +u_int32_t dumpmag = 0x8fca0101; /* magic number */ +u_int dumpsize; /* pages */ long dumplo; /* blocks */ +cpu_kcore_hdr_t cpu_kcore_hdr; int kbd_reset; @@ -424,9 +429,147 @@ allocsys(caddr_t v) } void +dumpconf() +{ + cpu_kcore_hdr_t *h = &cpu_kcore_hdr; + u_int dumpextra, totaldumpsize; /* in disk blocks */ + u_int seg, nblks; + int maj; + + if (dumpdev == NODEV) + return; + + maj = major(dumpdev); + if (maj < 0 || maj >= nblkdev) { + printf("dumpconf: bad dumpdev=0x%x\n", dumpdev); + dumpdev = NODEV; + return; + } + if (bdevsw[maj].d_psize == NULL) + return; + nblks = (u_int)(*bdevsw[maj].d_psize)(dumpdev); + if (nblks <= btodb(1U)) + return; + + dumpsize = 0; + for (seg = 0; seg < h->kcore_nsegs; seg++) + dumpsize += atop(h->kcore_segs[seg].size); + dumpextra = cpu_dumpsize(); + + /* Always skip the first block, in case there is a label there. */ + if (dumplo < btodb(1)); + dumplo = btodb(1); + + /* Put dump at the end of the partition, and make it fit. */ + totaldumpsize = ctod(dumpsize) + dumpextra; + if (totaldumpsize > nblks - dumplo) { + totaldumpsize = dbtob(nblks - dumplo); + dumpsize = dtoc(totaldumpsize - dumpextra); + } + if (dumplo < nblks - totaldumpsize) + dumplo = nblks - totaldumpsize; +} + +void dumpsys() { - /* TODO */ + cpu_kcore_hdr_t *h = &cpu_kcore_hdr; + daddr_t blkno; + int (*dump)(dev_t, daddr_t, caddr_t, size_t); + u_int page = 0; + paddr_t dumppa; + u_int seg; + int rc; + extern int msgbufmapped; + + /* Don't record dump messages in msgbuf. */ + msgbufmapped = 0; + + /* Make sure dump settings are valid. */ + if (dumpdev == NODEV) + return; + if (dumpsize == 0) { + dumpconf(); + if (dumpsize == 0) + return; + } + if (dumplo <= 0) { + printf("\ndump to dev 0x%x not possible, not enough space\n", + dumpdev); + return; + } + + dump = bdevsw[major(dumpdev)].d_dump; + blkno = dumplo; + + printf("\ndumping to dev 0x%x offset %ld\n", dumpdev, dumplo); + + printf("dump "); + + /* Write dump header */ + rc = cpu_dump(dump, &blkno); + if (rc != 0) + goto bad; + + for (seg = 0; seg < h->kcore_nsegs; seg++) { + u_int pagesleft; + + pagesleft = atop(h->kcore_segs[seg].size); + dumppa = (paddr_t)h->kcore_segs[seg].start; + + while (pagesleft != 0) { + u_int npages; + +#define NPGMB atop(1024 * 1024) + if (page != 0 && (page % NPGMB) == 0) + printf("%u ", page / NPGMB); + + /* do not dump more than 1MB at once */ + npages = min(pagesleft, NPGMB); +#undef NPGMB + npages = min(npages, dumpsize); + + rc = (*dump)(dumpdev, blkno, + (caddr_t)SH3_PHYS_TO_P2SEG(dumppa), ptoa(npages)); + if (rc != 0) + goto bad; + + pagesleft -= npages; + dumppa += ptoa(npages); + page += npages; + dumpsize -= npages; + if (dumpsize == 0) + goto bad; /* if truncated dump */ + blkno += ctod(npages); + } + } +bad: + switch (rc) { + case 0: + printf("succeeded\n"); + break; + case ENXIO: + printf("device bad\n"); + break; + case EFAULT: + printf("device not ready\n"); + break; + case EINVAL: + printf("area improper\n"); + break; + case EIO: + printf("I/O error\n"); + break; + case EINTR: + printf("aborted\n"); + break; + default: + printf("error %d\n", rc); + break; + } + + /* make sure console can output our last message */ + delay(1 * 1000 * 1000); } /* |