Subject: Re: 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/30/2007 22:49:24
This is a multi-part message in MIME format.
--------------070904090101020909090206
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Hi,

Attached are my latest patches to add kernel core dump support for
arm32.  (note I need to fully test them and build on something other
than cats :)

Based on comments I've changed the ABI's a bit.  First up the kcore header:
typedef struct cpu_kcore_hdr {
        uint32_t        version;                /* structure version */
        uint32_t        flags;                  /* flags */
#define KCORE_ARM_APX        0x0001             /* L1 tables are in APX
                                                   format */
        uint32_t        PAKernelL1Table;        /* PA of kernel L1 table */
        uint32_t        PAUserL1Table;          /* PA of userland L1
table */
        uint16_t        UserL1TableSize;        /* size of User L1 table */
        uint32_t        nmemsegs;               /* Number of RAM segments */
        uint32_t        omemsegs;               /* offset to memsegs */

        /* future versions will add fields here */
#if 0
        phys_ram_seg_t  memsegs[];              /* RAM segments */
#endif
} cpu_kcore_hdr_t;

Currently APX isn't decoded by libkvm.  libkvm will decode from
UserL1Table if the VA is < (UserL1TableSize << 17)

David mentioned adding fillers/place holders.  I've decided against this
as the above table should allow backwards compatibility.  If it's not
then bumping the version number should be used (most people will have
libkvm and kernel in sync)

To recover state for stack traces and debugging, dumppcb contains r8-r13.

The stack contains the following (using r13 from dumppcb)
r0   descending
r1        |
r2        |
r3       \|/
r4
r5
r6
r7
lr
cpsr <--- r13 points here

This should allow full recovery of CPU state.

Attached are the kernel and libkvm diffs.

Note that Nick has volunteered to handle the gdb parts, as he has the
necessary GPL/FSF copyright assignments in place.

Unless anyone has any major objections I'll check this in the next
couple of days.

Thanks,
Chris

--------------070904090101020909090206
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	30 Dec 2007 22:36:33 -0000
@@ -212,5 +212,37 @@ _C_LABEL(esym):	.word	_C_LABEL(end)
 ENTRY_NP(abort)
 	b	_C_LABEL(abort)
 
+/*
+ * part of doing a system dump, we need to save registers and cpsr onto the
+ * stack, then save the rest of the registers into the dumppcb
+ */
+ENTRY(dumpsys)
+	/* push registers onto stack */
+	stmfd	sp!, {r0-r7, lr}
+	
+	/* push the status bits onto the stack */
+	mrs	r0, cpsr_all
+	stmfd	sp!, {r0}
+
+	/* 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)
+
+	/* unwind the stack */
+	ldmfd	sp!, {r0}
+	ldmfd	sp!, {r0-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	30 Dec 2007 22:36:33 -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	30 Dec 2007 22:36:35 -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	30 Dec 2007 22:36:36 -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,136 @@ 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->PAKernelL1Table = pmap_kernel_L1_addr();
+	cpuhdrp->UserL1TableSize = 0;
+	cpuhdrp->nmemsegs = bootconfig.dramblocks;
+	cpuhdrp->omemsegs = ALIGN(sizeof(*cpuhdrp));
+
+	/*
+	 * 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 +227,6 @@ dumpsys()
 	int len;
 	vaddr_t dumpspace;
 
-	/* Save registers. */
-	savectx(&dumppcb);
 	/* flush everything out of caches */
 	cpu_dcache_wbinv_all();
 
@@ -138,19 +234,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 +255,11 @@ dumpsys()
 		return;
 	}
 
+	if ((error = cpu_dump()) != 0)
+		goto err;
+
+	blkno = dumplo + cpu_dumpsize();
+	dumpspace = memhook;
 	error = 0;
 	len = 0;
 
@@ -172,19 +270,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 +303,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/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	30 Dec 2007 22:36:36 -0000
@@ -0,0 +1,55 @@
+/*	$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	flags;			/* flags */
+#define	KCORE_ARM_APX        0x0001		/* L1 tables are in APX
+						   format */
+	uint32_t	PAKernelL1Table;	/* PA of kernel L1 table */
+	uint32_t	PAUserL1Table;		/* PA of userland L1 table */
+	uint16_t	UserL1TableSize;	/* size of User L1 table */
+	uint32_t	nmemsegs;		/* Number of RAM segments */
+	uint32_t	omemsegs;		/* offset to memsegs */
+
+	/* future versions will add fields here */
+#if 0
+	phys_ram_seg_t  memsegs[];		/* RAM segments */
+#endif
+} cpu_kcore_hdr_t;
+
+#endif /* _ARM_KCORE_H_ */

--------------070904090101020909090206
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	30 Dec 2007 22:39:15 -0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: kvm_arm.c,v 1.2 2001/07/16 05:45:52 matt Exp $	*/
+/* $NetBSD: kvm_arm.c,v 1.2 2001/07/16 05:45:52 matt Exp $	 */
 
 /*-
  * Copyright (C) 1996 Wolfgang Solfrank.
@@ -37,49 +37,147 @@
  * arm32 machine dependent routines for kvm.
  */
 
-#include <sys/param.h>
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD$");
+#endif				/* LIBC_SCCS and not lint */
 
+#include <sys/param.h>
 #include <sys/exec.h>
+#include <sys/kcore.h>
+#include <arm/kcore.h>
+#include <arm/arm32/pte.h>
 
 #include <stdlib.h>
 #include <db.h>
 #include <limits.h>
 #include <kvm.h>
 
+#include <unistd.h>
+
 #include "kvm_private.h"
 
 void
-_kvm_freevtop(kd)
-	kvm_t *kd;
+_kvm_freevtop(kvm_t * kd)
 {
 	if (kd->vmst != 0)
 		free(kd->vmst);
 }
 
 int
-_kvm_initvtop(kd)
-	kvm_t *kd;
+_kvm_initvtop(kvm_t * kd)
 {
 	return 0;
 }
 
 int
-_kvm_kvatop(kd, va, pa)
-	kvm_t *kd;
-	u_long va;
-	u_long *pa;
+_kvm_kvatop(kvm_t * kd, 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->flags != 0) {
+		_kvm_err(kd, 0, "kcore flags not supported");
+		return 0;
+	}
+	/*
+	 * work out which L1 table we need
+	 */
+	if (va >= (cpu_kh->UserL1TableSize << 17))
+		pde_pa = cpu_kh->PAKernelL1Table;
+	else
+		pde_pa = cpu_kh->PAUserL1Table;
+
+	/*
+	 * work out the offset into the L1 Table
+	 */
+	pde_pa += ((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:
+		*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;
 }
 
 off_t
-_kvm_pa2off(kd, pa)
-	kvm_t *kd;
-	u_long pa;
+_kvm_pa2off(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 + cpu_kh->omemsegs);
+
+	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);
 }
 
 /*
@@ -88,13 +186,12 @@ _kvm_pa2off(kd, pa)
  * have to deal with these NOT being constants!  (i.e. arm)
  */
 int
-_kvm_mdopen(kd)
-	kvm_t	*kd;
+_kvm_mdopen(kvm_t * kd)
 {
-	uintptr_t max_uva;
+	uintptr_t       max_uva;
 	extern struct ps_strings *__ps_strings;
 
-#if 0   /* XXX - These vary across arm machines... */
+#if 0				/* XXX - These vary across arm machines... */
 	kd->usrstack = USRSTACK;
 	kd->min_uva = VM_MIN_ADDRESS;
 	kd->max_uva = VM_MAXUSER_ADDRESS;
@@ -102,8 +199,8 @@ _kvm_mdopen(kd)
 	/* This is somewhat hack-ish, but it works. */
 	max_uva = (uintptr_t) (__ps_strings + 1);
 	kd->usrstack = max_uva;
-	kd->max_uva  = max_uva;
-	kd->min_uva  = 0;
+	kd->max_uva = max_uva;
+	kd->min_uva = 0;
 
 	return (0);
 }

--------------070904090101020909090206
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

--------------070904090101020909090206--