summaryrefslogtreecommitdiff
path: root/sys/arch
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 /sys/arch
parent8f58ce59b66d35d5d484c5cfb9f5967571339ac9 (diff)
Kernel crash dumps and associated libkvm bits for landisk.
Diffstat (limited to 'sys/arch')
-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
7 files changed, 282 insertions, 25 deletions
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);
}
/*