summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2007-03-03 21:37:28 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2007-03-03 21:37:28 +0000
commit301ce3789c0dded4c40ebb4c1197dee00cf0fc3e (patch)
tree44351c56ccd077c95b601f112ad6c7c4d156911e
parent8f58ce59b66d35d5d484c5cfb9f5967571339ac9 (diff)
Kernel crash dumps and associated libkvm bits for landisk.
-rw-r--r--distrib/sets/lists/base/md.landisk2
-rw-r--r--distrib/sets/lists/comp/md.landisk2
-rw-r--r--lib/libkvm/kvm_sh.c144
-rw-r--r--sys/arch/landisk/include/kcore.h1
-rw-r--r--sys/arch/landisk/landisk/autoconf.c8
-rw-r--r--sys/arch/landisk/landisk/machdep.c94
-rw-r--r--sys/arch/sh/include/cpu.h5
-rw-r--r--sys/arch/sh/include/kcore.h32
-rw-r--r--sys/arch/sh/include/param.h14
-rw-r--r--sys/arch/sh/sh/sh_machdep.c153
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);
}
/*