Subject: Initial diffs to make arm32 kernel core dumps work with savecore
To: None <port-arm@netbsd.org>
From: Chris Gilbert <chris@dokein.co.uk>
List: port-arm
Date: 12/15/2007 01:03:09
This is a multi-part message in MIME format.
--------------090900070401030903050304
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Hi,
Following on from making cats actually be capable of dumping kernel
cores I've updated the kernel code and libkvm code to support dumping
the extra headers etc needed for savecore to work. With some help from
Nick (skrll@) I've added support to gdb to understand kernel core
dumps. Nick did the mknative work for gdb.
The updates to dumpsys and kcore.h were taken from similar code in i386.
The asm dumpsys and dodumpsys were inspired by amd64's method of dumping
core, as it makes sure that the stack has a switchframe containing the
registers, something savectx didn't get right.
These change remove the last active reference to savectx (which didn't
work for dumpsys because the switchframe it placed on the stack is
trashed by the dumpsys C code before the stack is saved to disk)
I've broken the diffs down into bite sized chunks:
kernel.diff - changes to the kernel to support dumping the extra info
for savecore. Adds kcore.h.
pkg_list.diff - adds kcore.h to the arm comp set.
libkvm.diff - adds support to libkvm to provide the functions it needs
to save the core dump (room for optimisation as the L1 table could be
cached in memory)
gdb_mknative.diff - Nick's run of mknative to provide a kvm target for
gdb on arm
gdb_pcb.diff - Adding the processing of the dumppcb structure from the
kernel core dump to gdb
The main item to highlight is the cpu_kcore_hdr structure in
sys/arch/arm/include/kcore.h, as it's a new kernel->userland ABI for
arm, I'd like to get it right first time if possible. Currently I've
defined it as:
typedef struct cpu_kcore_hdr {
uint32_t version; /* structure version */
uint32_t isArm26; /* indicates arm26 dump */
uint32_t PAKernelL1Table; /* PA of PMAP_kernel L1 table */
uint32_t nmemsegs; /* Number of RAM segments */
#if 0
phys_ram_seg_t memsegs[]; /* RAM segments */
#endif
} cpu_kcore_hdr_t;
This provides all the info I need, however, given I've placed a version
field into it, I suspect the isArm26 field can go. Also to improve
forward/backwards compatibility I think I should add an offset to the
memsegs, so it ends up as:
typedef struct cpu_kcore_hdr {
uint32_t version; /* structure version */
uint32_t PAKernelL1Table; /* PA of PMAP_kernel L1 table */
uint32_t nmemsegs; /* Number of RAM segments */
uint32_t omemsegs; /* offset from start of structure to
memsegs []*/
#if 0
phys_ram_seg_t memsegs[]; /* RAM segments */
#endif
} cpu_kcore_hdr_t;
By using an offset it allows future versions to add extra fields to the
structure, after omemsegs, and keep some level of backwards compatibility.
Am I allowing (over-engineering) for something that may never happen?
I'm expecting that arm26 needs to save something different, and possibly
arm v6 and v7 architectures will need something else as well, hence why
I'm wanting to allow the ABI to have a bit of flexibility.
I guess the second area of ABI is the registers placed on the stack in
dumpsys. Something I was wondering is if it would help gdb by placing
the cpsr onto the stack for gdb to be able to load, or does it not
matter for a kernel dump. (note r3 is saved purely to keep the stack
8byte aligned)
The code has only been tested on cats, I need to do some builds on other
arm based platforms to make sure they don't break :)
I'm aiming to tidy up the code (make sure it meets NetBSD style
guidelines, and fix some tab vs space issues) on Monday, and check it
in, so it'd be nice to have feedback by then.
Thanks,
Chris
--------------090900070401030903050304
Content-Type: text/plain;
name="gdb_mknative.diff"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline;
filename="gdb_mknative.diff"
Index: gnu/usr.bin/gdb6/arch/arm/defs.mk
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/gnu/usr.bin/gdb6/arch/arm/defs.mk,v
retrieving revision 1.3
diff -u -p -u -r1.3 defs.mk
--- gnu/usr.bin/gdb6/arch/arm/defs.mk 6 Dec 2006 18:25:29 -0000 1.3
+++ gnu/usr.bin/gdb6/arch/arm/defs.mk 14 Dec 2007 14:44:25 -0000
@@ -1,7 +1,7 @@
# This file is automatically generated. DO NOT EDIT!
-# Generated from: NetBSD: mknative-gdb,v 1.1 2006/05/29 19:10:58 nathan=
w Exp=20
-# Generated from: NetBSD: mknative.common,v 1.8 2006/05/26 19:17:21 mrg =
Exp=20
+# Generated from: NetBSD: mknative-gdb,v 1.2 2007/02/19 18:26:22 chs Ex=
p=20
+# Generated from: NetBSD: mknative.common,v 1.9 2007/02/05 18:26:01 apb =
Exp=20
#
G_INTERNAL_CFLAGS=3D -I. -I${GNUHOSTDIST}/gdb -I${GNUHOSTDIST}/gdb/c=
onfig -DLOCALEDIR=3D"\"/usr/share/locale\"" -DHAVE_CONFIG_H -I${GNUHOSTDI=
ST}/gdb/../include/opcode -I${GNUHOSTDIST}/gdb/../readline/.. -I../bfd -=
I${GNUHOSTDIST}/gdb/../bfd -I${GNUHOSTDIST}/gdb/../include -I../intl -I$=
{GNUHOSTDIST}/gdb/../intl -DMI_OUT=3D1 -DTUI=3D1 -Wimplicit -Wreturn-typ=
e -Wcomment -Wtrigraphs -Wformat -Wparentheses -Wpointer-arith -Wformat-n=
onliteral -Wunused-label -Wunused-function -Wno-pointer-sign=20
-G_LIBGDB_OBS=3Darm-tdep.o armnbsd-tdep.o solib.o solib-svr4.o nbsd-tdep.=
o ser-base.o ser-unix.o ser-pipe.o ser-tcp.o fork-child.o inf-ptrace.o co=
relow.o nbsd-nat.o armnbsd-nat.o remote.o dcache.o remote-utils.o tracep=
oint.o ax-general.o ax-gdb.o remote-fileio.o cli-dump.o cli-decode.o cl=
i-script.o cli-cmds.o cli-setshow.o cli-utils.o cli-logging.o cli-inter=
p.o mi-out.o mi-console.o mi-cmds.o mi-cmd-env.o mi-cmd-var.o mi-cmd-bre=
ak.o mi-cmd-stack.o mi-cmd-file.o mi-cmd-disas.o mi-symbol-cmds.o mi-in=
terp.o mi-main.o mi-parse.o mi-getopt.o mi-common.o posix-hdep.o tui-com=
mand.o tui-data.o tui-disasm.o tui-file.o tui.o tui-hooks.o tui-inte=
rp.o tui-io.o tui-layout.o tui-out.o tui-regs.o tui-source.o tui-st=
ack.o tui-win.o tui-windata.o tui-wingeneral.o tui-winsource.o c-exp.=
o cp-name-parser.o objc-exp.o ada-exp.o jv-exp.o f-exp.o m2-exp.o p-=
exp.o version.o annotate.o auxv.o bfd-target.o blockframe.o breakpoi=
nt.o findvar.o regcache.o charset.o disasm.o dummy-frame.o source.o val=
ue.o eval.o valops.o valarith.o valprint.o printcmd.o block.o symtab.o s=
ymfile.o symmisc.o linespec.o dictionary.o infcall.o infcmd.o infrun.o =
expprint.o environ.o stack.o thread.o exceptions.o inf-child.o interp=
s.o main.o macrotab.o macrocmd.o macroexp.o macroscope.o event-loop.o =
event-top.o inf-loop.o completer.o gdbarch.o arch-utils.o gdbtypes.o osa=
bi.o copying.o memattr.o mem-break.o target.o parse.o language.o buildsy=
m.o std-regs.o signals.o kod.o kod-cisco.o gdb-events.o exec.o bcach=
e.o objfiles.o observer.o minsyms.o maint.o demangle.o dbxread.o coffrea=
d.o coff-pe-read.o elfread.o dwarfread.o dwarf2read.o mipsread.o stabsre=
ad.o corefile.o dwarf2expr.o dwarf2loc.o dwarf2-frame.o ada-lang.o c-la=
ng.o f-lang.o objc-lang.o ui-out.o cli-out.o varobj.o wrapper.o jv-lan=
g.o jv-valprint.o jv-typeprint.o m2-lang.o p-lang.o p-typeprint.o p-valp=
rint.o scm-exp.o scm-lang.o scm-valprint.o sentinel-frame.o complaints=
=2Eo typeprint.o ada-typeprint.o c-typeprint.o f-typeprint.o m2-typeprin=
t.o ada-valprint.o c-valprint.o cp-valprint.o f-valprint.o m2-valprint.o=
nlmread.o serial.o mdebugread.o top.o utils.o ui-file.o user-regs.o =
frame.o frame-unwind.o doublest.o frame-base.o gnu-v2-abi.o gnu-v3-abi.=
o hpacc-abi.o cp-abi.o cp-support.o cp-namespace.o reggroups.o regset.o=
trad-frame.o tramp-frame.o solib.o solib-null.o prologue-value.o inf=
low.o init.o
+G_LIBGDB_OBS=3Darm-tdep.o armnbsd-tdep.o solib.o solib-svr4.o nbsd-tdep.=
o ser-base.o ser-unix.o ser-pipe.o ser-tcp.o fork-child.o inf-ptrace.o co=
relow.o nbsd-nat.o armnbsd-nat.o bsd-kvm.o remote.o dcache.o remote-util=
s.o tracepoint.o ax-general.o ax-gdb.o remote-fileio.o cli-dump.o cli-d=
ecode.o cli-script.o cli-cmds.o cli-setshow.o cli-utils.o cli-logging.o =
cli-interp.o mi-out.o mi-console.o mi-cmds.o mi-cmd-env.o mi-cmd-var.o =
mi-cmd-break.o mi-cmd-stack.o mi-cmd-file.o mi-cmd-disas.o mi-symbol-cmd=
s.o mi-interp.o mi-main.o mi-parse.o mi-getopt.o mi-common.o nbsd-threa=
d.o posix-hdep.o tui-command.o tui-data.o tui-disasm.o tui-file.o tui.=
o tui-hooks.o tui-interp.o tui-io.o tui-layout.o tui-out.o tui-regs=
=2Eo tui-source.o tui-stack.o tui-win.o tui-windata.o tui-wingeneral=
=2Eo tui-winsource.o c-exp.o cp-name-parser.o objc-exp.o ada-exp.o j=
v-exp.o f-exp.o m2-exp.o p-exp.o version.o annotate.o auxv.o bfd-tar=
get.o blockframe.o breakpoint.o findvar.o regcache.o charset.o disasm.o=
dummy-frame.o source.o value.o eval.o valops.o valarith.o valprint.o pr=
intcmd.o block.o symtab.o symfile.o symmisc.o linespec.o dictionary.o i=
nfcall.o infcmd.o infrun.o expprint.o environ.o stack.o thread.o excep=
tions.o inf-child.o interps.o main.o macrotab.o macrocmd.o macroexp.o=
macroscope.o event-loop.o event-top.o inf-loop.o completer.o gdbarch.o=
arch-utils.o gdbtypes.o osabi.o copying.o memattr.o mem-break.o target.=
o parse.o language.o buildsym.o std-regs.o signals.o kod.o kod-cisco.o=
gdb-events.o exec.o bcache.o objfiles.o observer.o minsyms.o maint.o d=
emangle.o dbxread.o coffread.o coff-pe-read.o elfread.o dwarfread.o dwa=
rf2read.o mipsread.o stabsread.o corefile.o dwarf2expr.o dwarf2loc.o dwa=
rf2-frame.o ada-lang.o c-lang.o f-lang.o objc-lang.o ui-out.o cli-out.o=
varobj.o wrapper.o jv-lang.o jv-valprint.o jv-typeprint.o m2-lang.o p=
-lang.o p-typeprint.o p-valprint.o scm-exp.o scm-lang.o scm-valprint.o =
sentinel-frame.o complaints.o typeprint.o ada-typeprint.o c-typeprint.o=
f-typeprint.o m2-typeprint.o ada-valprint.o c-valprint.o cp-valprint.o =
f-valprint.o m2-valprint.o nlmread.o serial.o mdebugread.o top.o utils.o=
ui-file.o user-regs.o frame.o frame-unwind.o doublest.o frame-base.o=
gnu-v2-abi.o gnu-v3-abi.o hpacc-abi.o cp-abi.o cp-support.o cp-namespa=
ce.o reggroups.o regset.o trad-frame.o tramp-frame.o solib.o solib-nu=
ll.o prologue-value.o inflow.o init.o
G_SIM_OBS=3D
Index: gnu/dist/gdb6/gdb/config/arm/nbsdelf.mh
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/gnu/dist/gdb6/gdb/config/arm/nbsdelf.mh,v
retrieving revision 1.2
diff -u -p -u -r1.2 nbsdelf.mh
--- gnu/dist/gdb6/gdb/config/arm/nbsdelf.mh 6 Dec 2006 18:25:29 -0000 1.2=
+++ gnu/dist/gdb6/gdb/config/arm/nbsdelf.mh 14 Dec 2007 14:44:25 -0000
@@ -1,2 +1,4 @@
# Host: NetBSD/arm
-NATDEPFILES=3D fork-child.o inf-ptrace.o corelow.o nbsd-nat.o armnbsd-na=
t.o
+NATDEPFILES=3D fork-child.o inf-ptrace.o corelow.o nbsd-nat.o armnbsd-na=
t.o bsd-kvm.o
+
+LOADLIBES=3D -lkvm
--------------090900070401030903050304
Content-Type: text/plain;
name="gdb_pcb.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="gdb_pcb.diff"
Index: gnu/dist/gdb6/gdb/armnbsd-nat.c
===================================================================
RCS file: /cvsroot/src/gnu/dist/gdb6/gdb/armnbsd-nat.c,v
retrieving revision 1.2
diff -u -p -r1.2 armnbsd-nat.c
--- gnu/dist/gdb6/gdb/armnbsd-nat.c 24 Feb 2007 12:36:27 -0000 1.2
+++ gnu/dist/gdb6/gdb/armnbsd-nat.c 15 Dec 2007 00:16:39 -0000
@@ -31,9 +31,11 @@
#include <sys/ptrace.h>
#include <machine/reg.h>
#include <machine/frame.h>
+#include <machine/pcb.h>
#include "arm-tdep.h"
#include "inf-ptrace.h"
+#include "bsd-kvm.h"
#ifndef HAVE_GREGSET_T
typedef struct reg gregset_t;
@@ -47,6 +49,45 @@ typedef struct fpreg fpregset_t;
extern int arm_apcs_32;
+static int
+armnbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
+{
+ struct switchframe sf;
+ uint32_t r3, r4, r5, r6, r7, lr;
+ uint32_t sp;
+
+ /* The stack pointer shouldn't be zero. */
+ if (pcb->pcb_un.un_32.pcb32_sp == 0)
+ return 0;
+
+
+ /* we need to pull some regs from the stack */
+ read_memory (pcb->pcb_un.un_32.pcb32_sp, (gdb_byte *) &r3, sizeof(r3));
+ read_memory (pcb->pcb_un.un_32.pcb32_sp+4, (gdb_byte *) &r4, sizeof(r4));
+ read_memory (pcb->pcb_un.un_32.pcb32_sp+8, (gdb_byte *) &r5, sizeof(r5));
+ read_memory (pcb->pcb_un.un_32.pcb32_sp+12, (gdb_byte *) &r6, sizeof(r6));
+ read_memory (pcb->pcb_un.un_32.pcb32_sp+16, (gdb_byte *) &r7, sizeof(r7));
+ read_memory (pcb->pcb_un.un_32.pcb32_sp+20, (gdb_byte *) &lr, sizeof(lr));
+
+ sp = pcb->pcb_un.un_32.pcb32_sp + 24;
+
+ regcache_raw_supply (regcache, 3, &r3);
+ regcache_raw_supply (regcache, 4, &r4);
+ regcache_raw_supply (regcache, 5, &r5);
+ regcache_raw_supply (regcache, 6, &r6);
+ regcache_raw_supply (regcache, 7, &r7);
+ regcache_raw_supply (regcache, 8, &pcb->pcb_un.un_32.pcb32_r8);
+ regcache_raw_supply (regcache, 9, &pcb->pcb_un.un_32.pcb32_r9);
+ regcache_raw_supply (regcache, 10, &pcb->pcb_un.un_32.pcb32_r10);
+ regcache_raw_supply (regcache, 11, &pcb->pcb_un.un_32.pcb32_r11);
+ regcache_raw_supply (regcache, 12, &pcb->pcb_un.un_32.pcb32_r12);
+ regcache_raw_supply (regcache, ARM_SP_REGNUM, &sp);
+ regcache_raw_supply (regcache, ARM_LR_REGNUM, &lr);
+ regcache_raw_supply (regcache, ARM_PC_REGNUM, &lr);
+
+ return 1;
+}
+
void
supply_gregset (gregset_t *gregset)
{
@@ -551,4 +592,7 @@ _initialize_arm_netbsd_nat (void)
deprecated_add_core_fns (&arm_netbsd_core_fns);
deprecated_add_core_fns (&arm_netbsd_elfcore_fns);
+
+ /* support debugging kernel images */
+ bsd_kvm_add_target (armnbsd_supply_pcb);
}
--------------090900070401030903050304
Content-Type: text/plain;
name="kernel.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="kernel.diff"
Index: sys/arch/arm/arm32/locore.S
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/arm32/locore.S,v
retrieving revision 1.18
diff -u -p -r1.18 locore.S
--- sys/arch/arm/arm32/locore.S 11 Dec 2005 12:16:41 -0000 1.18
+++ sys/arch/arm/arm32/locore.S 15 Dec 2007 00:33:53 -0000
@@ -212,5 +212,31 @@ _C_LABEL(esym): .word _C_LABEL(end)
ENTRY_NP(abort)
b _C_LABEL(abort)
+/*
+ * part of doing a system dump, we need to build a switchframe on the stack
+ * and save it into the dump pcb
+ */
+
+ENTRY(dumpsys)
+ /* push registers onto stack */
+ stmfd sp!, {r3-r7, lr}
+
+ /* fill in dumppcb */
+ ldr r0, .Ldumppcb
+
+#ifndef __XSCALE__
+ add r2, r0, #(PCB_R8)
+ stmia r2, {r8-r13}
+#else
+ strd r8, [r0, #(PCB_R8)]
+ strd r10, [r0, #(PCB_R10)]
+ strd r12, [r0, #(PCB_R12)]
+#endif
+
+ bl _C_LABEL(dodumpsys)
+ ldmfd sp!, {r3-r7, pc}
+
+.Ldumppcb:
+ .word _C_LABEL(dumppcb)
/* End of locore.S */
Index: sys/arch/arm/arm32/mem.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/arm32/mem.c,v
retrieving revision 1.19
diff -u -p -r1.19 mem.c
--- sys/arch/arm/arm32/mem.c 4 Mar 2007 10:21:26 -0000 1.19
+++ sys/arch/arm/arm32/mem.c 15 Dec 2007 00:33:54 -0000
@@ -91,7 +91,7 @@ __KERNEL_RCSID(0, "$NetBSD: mem.c,v 1.19
#include <uvm/uvm_extern.h>
-extern char *memhook; /* poor name! */
+extern vaddr_t memhook; /* poor name! */
void *zeropage;
int physlock;
@@ -143,14 +143,14 @@ mmrw(dev, uio, flags)
v = uio->uio_offset;
prot = uio->uio_rw == UIO_READ ? VM_PROT_READ :
VM_PROT_WRITE;
- pmap_enter(pmap_kernel(), (vaddr_t)memhook,
+ pmap_enter(pmap_kernel(), memhook,
trunc_page(v), prot, prot|PMAP_WIRED);
pmap_update(pmap_kernel());
o = uio->uio_offset & PGOFSET;
c = min(uio->uio_resid, (int)(PAGE_SIZE - o));
error = uiomove((char *)memhook + o, c, uio);
- pmap_remove(pmap_kernel(), (vaddr_t)memhook,
- (vaddr_t)memhook + PAGE_SIZE);
+ pmap_remove(pmap_kernel(), memhook,
+ memhook + PAGE_SIZE);
pmap_update(pmap_kernel());
break;
Index: sys/arch/arm/arm32/pmap.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/arm32/pmap.c,v
retrieving revision 1.169
diff -u -p -r1.169 pmap.c
--- sys/arch/arm/arm32/pmap.c 8 Nov 2007 11:10:28 -0000 1.169
+++ sys/arch/arm/arm32/pmap.c 15 Dec 2007 00:33:56 -0000
@@ -303,7 +303,7 @@ static paddr_t pmap_kernel_l2ptp_phys;
*/
static pt_entry_t *csrc_pte, *cdst_pte;
static vaddr_t csrcp, cdstp;
-char *memhook;
+vaddr_t memhook;
extern void *msgbufaddr;
/*
@@ -3963,7 +3963,7 @@ pmap_bootstrap(pd_entry_t *kernel_l1pt,
pmap_set_pt_cache_mode(kernel_l1pt, (vaddr_t)csrc_pte);
pmap_alloc_specials(&virtual_avail, 1, &cdstp, &cdst_pte);
pmap_set_pt_cache_mode(kernel_l1pt, (vaddr_t)cdst_pte);
- pmap_alloc_specials(&virtual_avail, 1, (void *)&memhook, NULL);
+ pmap_alloc_specials(&virtual_avail, 1, &memhook, NULL);
pmap_alloc_specials(&virtual_avail, round_page(MSGBUFSIZE) / PAGE_SIZE,
(void *)&msgbufaddr, NULL);
@@ -4985,6 +4985,14 @@ pmap_uarea(vaddr_t va)
}
#endif /* ARM_MMU_XSCALE == 1 */
+/*
+ * return the PA of the current L1 table, for use when handling a crash dump
+ */
+uint32_t pmap_kernel_L1_addr()
+{
+ return pmap_kernel()->pm_l1->l1_physaddr;
+}
+
#if defined(DDB)
/*
* A couple of ddb-callable functions for dumping pmaps
Index: sys/arch/arm/arm32/stubs.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/arm32/stubs.c,v
retrieving revision 1.17
diff -u -p -r1.17 stubs.c
--- sys/arch/arm/arm32/stubs.c 4 Mar 2007 05:59:37 -0000 1.17
+++ sys/arch/arm/arm32/stubs.c 15 Dec 2007 00:33:56 -0000
@@ -55,9 +55,17 @@ __KERNEL_RCSID(0, "$NetBSD: stubs.c,v 1.
#include <machine/bootconfig.h>
#include <machine/pcb.h>
#include <arm/arm32/machdep.h>
+#include <arm/kcore.h>
+#include <sys/kcore.h>
+#include <sys/core.h>
+#include <sys/exec_aout.h>
extern dev_t dumpdev;
+int cpu_dump(void);
+int cpu_dumpsize(void);
+u_long cpu_dump_mempagecnt(void);
+
/*
* These variables are needed by /sbin/savecore
*/
@@ -69,7 +77,7 @@ struct pcb dumppcb;
/*
* This is called by main to set dumplo and dumpsize.
- * Dumps always skip the first CLBYTES of disk space
+ * Dumps always skip the first PAGE_SIZE of disk space
* in case there might be a disk label stored there.
* If there is extra space, put dump at the end to
* reduce the chance that swapping trashes it.
@@ -79,46 +87,135 @@ void
cpu_dumpconf()
{
const struct bdevsw *bdev;
- int nblks; /* size of dump area */
+ int nblks, dumpblks; /* size of dump area */
if (dumpdev == NODEV)
return;
bdev = bdevsw_lookup(dumpdev);
- if (bdev == NULL) {
- dumpdev = NODEV;
- return;
- }
+ if (bdev == NULL)
+ panic("dumpconf: bad dumpdev=0x%x", dumpdev);
if (bdev->d_psize == NULL)
return;
nblks = (*bdev->d_psize)(dumpdev);
if (nblks <= ctod(1))
return;
- dumpsize = physmem;
+ dumpblks = cpu_dumpsize();
+ if (dumpblks < 0)
+ goto bad;
+ dumpblks += ctod(cpu_dump_mempagecnt());
+
+ /* If dump won't fit (incl. room for possible label), punt. */
+ if (dumpblks > (nblks - ctod(1)))
+ goto bad;
+
+ /* Put dump at end of partition */
+ dumplo = nblks - dumpblks;
+
+ /* dumpsize is in page units, and doesn't include headers. */
+ dumpsize = cpu_dump_mempagecnt();
+ return;
+
+ bad:
+ dumpsize = 0;
+}
+
+/*
+ * cpu_dump: dump the machine-dependent kernel core dump headers.
+ */
+int
+cpu_dump()
+{
+ int (*dump)(dev_t, daddr_t, void *, size_t);
+ char bf[dbtob(1)];
+ kcore_seg_t *segp;
+ cpu_kcore_hdr_t *cpuhdrp;
+ phys_ram_seg_t *memsegp;
+ const struct bdevsw *bdev;
+ int i;
+
+ bdev = bdevsw_lookup(dumpdev);
+ if (bdev == NULL)
+ return (ENXIO);
+ dump = bdev->d_dump;
+
+ memset(bf, 0, sizeof bf);
+ segp = (kcore_seg_t *)bf;
+ cpuhdrp = (cpu_kcore_hdr_t *)&bf[ALIGN(sizeof(*segp))];
+ memsegp = (phys_ram_seg_t *)&bf[ ALIGN(sizeof(*segp)) +
+ ALIGN(sizeof(*cpuhdrp))];
+
+ /*
+ * Generate a segment header.
+ */
+ CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
+ segp->c_size = dbtob(1) - ALIGN(sizeof(*segp));
+
+ /*
+ * Add the machine-dependent header info.
+ */
+ cpuhdrp->version = 1;
+ cpuhdrp->isArm26 = 0;
+ cpuhdrp->PAKernelL1Table = pmap_kernel_L1_addr();
+ cpuhdrp->nmemsegs = bootconfig.dramblocks;
+
+ /*
+ * Fill in the memory segment descriptors.
+ */
+ for (i = 0; i < bootconfig.dramblocks; i++) {
+ memsegp[i].start = bootconfig.dram[i].address;
+ memsegp[i].size = bootconfig.dram[i].pages * PAGE_SIZE;
+ }
+
+ return (dump(dumpdev, dumplo, bf, dbtob(1)));
+}
+
+/*
+ * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers.
+ */
+int
+cpu_dumpsize()
+{
+ int size;
+
+ size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)) +
+ ALIGN( bootconfig.dramblocks * sizeof(phys_ram_seg_t));
+ if (roundup(size, dbtob(1)) != dbtob(1))
+ return (-1);
- /* Always skip the first CLBYTES, in case there is a label there. */
- if (dumplo < ctod(1))
- dumplo = ctod(1);
-
- /* Put dump at end of partition, and make it fit. */
- if (dumpsize > dtoc(nblks - dumplo))
- dumpsize = dtoc(nblks - dumplo);
- if (dumplo < nblks - ctod(dumpsize))
- dumplo = nblks - ctod(dumpsize);
+ return (1);
+}
+
+
+/*
+ * cpu_dump_mempagecnt: calculate the size of RAM (in pages) to be dumped.
+ */
+u_long
+cpu_dump_mempagecnt()
+{
+ u_long i, n;
+
+ n = 0;
+ for (i = 0; i < bootconfig.dramblocks; i++) {
+ n += bootconfig.dram[i].pages;
+ }
+
+ return (n);
}
/* This should be moved to machdep.c */
-extern char *memhook; /* XXX */
+extern vaddr_t memhook; /* XXX */
/*
* Doadump comes here after turning off memory management and
* getting on the dump stack, either when called above, or by
* the auto-restart code.
*/
+void dodumpsys(void);
void
-dumpsys()
+dodumpsys()
{
const struct bdevsw *bdev;
daddr_t blkno;
@@ -129,8 +226,6 @@ dumpsys()
int len;
vaddr_t dumpspace;
- /* Save registers. */
- savectx(&dumppcb);
/* flush everything out of caches */
cpu_dcache_wbinv_all();
@@ -138,19 +233,16 @@ dumpsys()
return;
if (dumpsize == 0) {
cpu_dumpconf();
- if (dumpsize == 0)
- return;
}
- if (dumplo <= 0) {
+ if (dumplo <= 0 || dumpsize == 0) {
printf("\ndump to dev %u,%u not possible\n", major(dumpdev),
minor(dumpdev));
+ delay(5000000);
return;
}
printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev),
minor(dumpdev), dumplo);
- blkno = dumplo;
- dumpspace = (vaddr_t) memhook;
bdev = bdevsw_lookup(dumpdev);
if (bdev == NULL || bdev->d_psize == NULL)
@@ -162,6 +254,11 @@ dumpsys()
return;
}
+ if ((error = cpu_dump()) != 0)
+ goto err;
+
+ blkno = dumplo + cpu_dumpsize();
+ dumpspace = memhook;
error = 0;
len = 0;
@@ -172,19 +269,18 @@ dumpsys()
addr += PAGE_SIZE) {
if ((len % (1024*1024)) == 0)
printf("%d ", len / (1024*1024));
+
pmap_kenter_pa(dumpspace, addr, VM_PROT_READ);
pmap_update(pmap_kernel());
-
error = (*bdev->d_dump)(dumpdev,
blkno, (void *) dumpspace, PAGE_SIZE);
- pmap_kremove(dumpspace, PAGE_SIZE);
- pmap_update(pmap_kernel());
- if (error) break;
+
+ if (error) goto err;
blkno += btodb(PAGE_SIZE);
len += PAGE_SIZE;
}
}
-
+err:
switch (error) {
case ENXIO:
printf("device bad\n");
@@ -206,12 +302,16 @@ dumpsys()
printf("aborted from console\n");
break;
- default:
+ case 0:
printf("succeeded\n");
break;
+
+ default:
+ printf("error %d\n", error);
+ break;
}
printf("\n\n");
- delay(1000000);
+ delay(5000000);
}
/* End of stubs.c */
Index: sys/arch/arm/include/Makefile
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/include/Makefile,v
retrieving revision 1.34
diff -u -p -r1.34 Makefile
--- sys/arch/arm/include/Makefile 18 Feb 2007 15:53:55 -0000 1.34
+++ sys/arch/arm/include/Makefile 15 Dec 2007 00:33:56 -0000
@@ -11,7 +11,7 @@ INCS= ansi.h aout_machdep.h armreg.h asm
ieee.h ieeefp.h \
int_const.h int_fmtio.h int_limits.h int_mwgwtypes.h int_types.h \
ipkdb.h \
- limits.h lock.h \
+ limits.h kcore.h lock.h \
math.h mcontext.h mutex.h \
param.h pcb.h pmc.h proc.h profile.h rwlock.h \
ptrace.h \
Index: sys/arch/arm/include/kcore.h
===================================================================
RCS file: sys/arch/arm/include/kcore.h
diff -N sys/arch/arm/include/kcore.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/arch/arm/include/kcore.h 15 Dec 2007 00:33:56 -0000
@@ -0,0 +1,48 @@
+/* $NetBSD: kcore.h,v 1.3 2005/12/26 19:23:59 perry Exp $ */
+
+/*
+ * Copyright (c) 1996 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+/*
+ * Modified for NetBSD/i386 by Jason R. Thorpe, Numerical Aerospace
+ * Simulation Facility, NASA Ames Research Center.
+ */
+
+#ifndef _ARM_KCORE_H_
+#define _ARM_KCORE_H_
+
+typedef struct cpu_kcore_hdr {
+ uint32_t version; /* structure version */
+ uint32_t isArm26; /* indicates arm26 dump */
+ uint32_t PAKernelL1Table; /* PA of PMAP_kernel L1 table */
+ uint32_t nmemsegs; /* Number of RAM segments */
+#if 0
+ phys_ram_seg_t memsegs[]; /* RAM segments */
+#endif
+} cpu_kcore_hdr_t;
+
+#endif /* _ARM_KCORE_H_ */
Index: sys/arch/arm/include/arm32/pmap.h
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/include/arm32/pmap.h,v
retrieving revision 1.83
diff -u -p -r1.83 pmap.h
--- sys/arch/arm/include/arm32/pmap.h 17 Oct 2007 19:53:41 -0000 1.83
+++ sys/arch/arm/include/arm32/pmap.h 15 Dec 2007 00:33:57 -0000
@@ -291,6 +291,8 @@ void pmap_devmap_register(const struct p
bool pmap_pageidlezero(paddr_t);
#define PMAP_PAGEIDLEZERO(pa) pmap_pageidlezero((pa))
+/* crash dump function */
+uint32_t pmap_kernel_L1_addr(void);
/*
* The current top of kernel VM
*/
--------------090900070401030903050304
Content-Type: text/plain;
name="libkvm.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="libkvm.diff"
Index: lib/libkvm/kvm_arm.c
===================================================================
RCS file: /cvsroot/src/lib/libkvm/kvm_arm.c,v
retrieving revision 1.2
diff -u -p -r1.2 kvm_arm.c
--- lib/libkvm/kvm_arm.c 16 Jul 2001 05:45:52 -0000 1.2
+++ lib/libkvm/kvm_arm.c 15 Dec 2007 00:18:03 -0000
@@ -45,6 +45,11 @@
#include <db.h>
#include <limits.h>
#include <kvm.h>
+#include <sys/kcore.h>
+#include <arm/kcore.h>
+#include <arm/arm32/pte.h>
+
+#include <unistd.h>
#include "kvm_private.h"
@@ -69,6 +74,82 @@ _kvm_kvatop(kd, va, pa)
u_long va;
u_long *pa;
{
+ cpu_kcore_hdr_t *cpu_kh;
+ pd_entry_t pde;
+ pt_entry_t pte;
+ uint32_t pde_pa, pte_pa;
+
+ if (ISALIVE(kd)) {
+ _kvm_err(kd, 0, "vatop called in live kernel!");
+ return (0);
+ }
+
+ cpu_kh = kd->cpu_data;
+
+ if (cpu_kh->version != 1)
+ {
+ _kvm_err(kd, 0, "unsupported kcore structure version");
+ return 0;
+ }
+
+ if (cpu_kh->isArm26)
+ {
+ _kvm_err(kd, 0, "arm26 kcore dumps not supported");
+ return 0;
+ }
+
+ /* first up we have to load in the L1 entry */
+ pde_pa = cpu_kh->PAKernelL1Table + ((va>>20) * sizeof(pd_entry_t));
+
+ if (pread(kd->pmfd, (void*)&pde, sizeof(pd_entry_t),
+ _kvm_pa2off(kd, pde_pa)) != sizeof(pd_entry_t)) {
+ _kvm_syserr(kd, 0, "could not read L1 entry");
+ return (0);
+ }
+
+ /* next work out what kind of record it is */
+ switch (pde & L1_TYPE_MASK)
+ {
+ case L1_TYPE_S:
+ /* an L1 section */
+ *pa = (pde & L1_S_FRAME) | (va & L1_S_OFFSET);
+ return L1_S_SIZE - (va & L1_S_OFFSET);
+ case L1_TYPE_C:
+ pte_pa = (pde & L1_C_ADDR_MASK)
+ | ((va & 0xff000) >> 10) ;
+ break;
+ case L1_TYPE_F:
+ pte_pa = (pde & L1_S_ADDR_MASK)
+ | ((va & 0xffc00) >> 8) ;
+ break;
+ default:
+ _kvm_syserr(kd, 0, "L1 entry is invalid");
+ return (0);
+ }
+
+ /* locate the pte and load it */
+ if (pread(kd->pmfd, (void*)&pte, sizeof(pt_entry_t),
+ _kvm_pa2off(kd, pte_pa)) != sizeof(pt_entry_t)) {
+ _kvm_syserr(kd, 0, "could not read L2 entry");
+ return (0);
+ }
+
+ switch (pte & L2_TYPE_MASK)
+ {
+ case L2_TYPE_L:
+ *pa = (pte & L2_L_FRAME) | (va & L2_L_OFFSET);
+ return (L2_L_SIZE - (va & L2_L_OFFSET));
+ case L2_TYPE_S:
+ *pa = (pte & L2_S_FRAME) | (va & L2_S_OFFSET);
+ return (L2_S_SIZE - (va & L2_S_OFFSET));
+ case L2_TYPE_T:
+ *pa = (pte & L2_T_FRAME) | (va & L2_T_OFFSET);
+ return (L2_T_SIZE - (va & L2_T_OFFSET));
+ default:
+ _kvm_syserr(kd, 0, "L2 entry is invalid");
+ return (0);
+ }
+
_kvm_err(kd, 0, "vatop not yet implemented!");
return 0;
}
@@ -78,8 +159,24 @@ _kvm_pa2off(kd, pa)
kvm_t *kd;
u_long pa;
{
- _kvm_err(kd, 0, "pa2off not yet implemented!");
- return 0;
+ cpu_kcore_hdr_t *cpu_kh;
+ phys_ram_seg_t *ramsegs;
+ off_t off;
+ int i;
+
+ cpu_kh = kd->cpu_data;
+ ramsegs = (void *)((char *)(void *)cpu_kh + ALIGN(sizeof *cpu_kh));
+
+ off = 0;
+ for (i = 0; i < cpu_kh->nmemsegs; i++) {
+ if (pa >= ramsegs[i].start &&
+ (pa - ramsegs[i].start) < ramsegs[i].size) {
+ off += (pa - ramsegs[i].start);
+ break;
+ }
+ off += ramsegs[i].size;
+ }
+ return (kd->dump_off + off);
}
/*
--------------090900070401030903050304
Content-Type: text/plain;
name="pkg_list.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="pkg_list.diff"
Index: distrib/sets/lists/comp/ad.arm
===================================================================
RCS file: /cvsroot/src/distrib/sets/lists/comp/ad.arm,v
retrieving revision 1.27
diff -u -p -r1.27 ad.arm
--- distrib/sets/lists/comp/ad.arm 18 Feb 2007 18:47:36 -0000 1.27
+++ distrib/sets/lists/comp/ad.arm 15 Dec 2007 00:19:29 -0000
@@ -45,6 +45,7 @@
./usr/include/arm/iomd comp-obsolete obsolete
./usr/include/arm/iomd/vidc.h comp-obsolete obsolete
./usr/include/arm/ipkdb.h comp-c-include
+./usr/include/arm/kcore.h comp-c-include
./usr/include/arm/limits.h comp-c-include
./usr/include/arm/lock.h comp-c-include
./usr/include/arm/math.h comp-c-include
--------------090900070401030903050304--