svn commit: r273828 - in stable/10: lib/libkvm sys/arm/arm sys/sys

Andrew Turner andrew at FreeBSD.org
Wed Oct 29 16:36:09 UTC 2014


Author: andrew
Date: Wed Oct 29 16:36:08 2014
New Revision: 273828
URL: https://svnweb.freebsd.org/changeset/base/273828

Log:
  MFC r273284:
  
   Allow libkvm to get the kernel va to pa delta without the need for
   physaddr. This should allow for a kernel where PHYSADDR and KERNPHYSADDR
   are both undefined.
  
   For now libkvm will use the old method of reading physaddr and kernaddr
   to allow it to work with old kernels. This could be removed in the future
   when enough time has passed.

Modified:
  stable/10/lib/libkvm/kvm_arm.c
  stable/10/sys/arm/arm/dump_machdep.c
  stable/10/sys/sys/elf_common.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/lib/libkvm/kvm_arm.c
==============================================================================
--- stable/10/lib/libkvm/kvm_arm.c	Wed Oct 29 16:24:02 2014	(r273827)
+++ stable/10/lib/libkvm/kvm_arm.c	Wed Oct 29 16:36:08 2014	(r273828)
@@ -128,8 +128,10 @@ _kvm_initvtop(kvm_t *kd)
 	u_long kernbase, physaddr, pa;
 	pd_entry_t *l1pt;
 	Elf32_Ehdr *ehdr;
+	Elf32_Phdr *phdr;
 	size_t hdrsz;
 	char minihdr[8];
+	int found, i;
 
 	if (!kd->rawdump) {
 		if (pread(kd->pmfd, &minihdr, 8, 0) == 8) {
@@ -154,19 +156,33 @@ _kvm_initvtop(kvm_t *kd)
 	hdrsz = ehdr->e_phoff + ehdr->e_phentsize * ehdr->e_phnum;
 	if (_kvm_maphdrs(kd, hdrsz) == -1)
 		return (-1);
-	nl[0].n_name = "kernbase";
-	nl[1].n_name = NULL;
-	if (kvm_nlist(kd, nl) != 0)
-		kernbase = KERNBASE;
-	else
-		kernbase = nl[0].n_value;
 
-	nl[0].n_name = "physaddr";
-	if (kvm_nlist(kd, nl) != 0) {
-		_kvm_err(kd, kd->program, "couldn't get phys addr");
-		return (-1);
+	phdr = (Elf32_Phdr *)((uint8_t *)ehdr + ehdr->e_phoff);
+	found = 0;
+	for (i = 0; i < ehdr->e_phnum; i++) {
+		if (phdr[i].p_type == PT_DUMP_DELTA) {
+			kernbase = phdr[i].p_vaddr;
+			physaddr = phdr[i].p_paddr;
+			found = 1;
+			break;
+		}
+	}
+
+	nl[1].n_name = NULL;
+	if (!found) {
+		nl[0].n_name = "kernbase";
+		if (kvm_nlist(kd, nl) != 0)
+			kernbase = KERNBASE;
+		else
+			kernbase = nl[0].n_value;
+
+		nl[0].n_name = "physaddr";
+		if (kvm_nlist(kd, nl) != 0) {
+			_kvm_err(kd, kd->program, "couldn't get phys addr");
+			return (-1);
+		}
+		physaddr = nl[0].n_value;
 	}
-	physaddr = nl[0].n_value;
 	nl[0].n_name = "kernel_l1pa";
 	if (kvm_nlist(kd, nl) != 0) {
 		_kvm_err(kd, kd->program, "bad namelist");

Modified: stable/10/sys/arm/arm/dump_machdep.c
==============================================================================
--- stable/10/sys/arm/arm/dump_machdep.c	Wed Oct 29 16:24:02 2014	(r273827)
+++ stable/10/sys/arm/arm/dump_machdep.c	Wed Oct 29 16:36:08 2014	(r273828)
@@ -246,6 +246,29 @@ cb_dumphdr(struct md_pa *mdp, int seqnr,
 	return (error);
 }
 
+/*
+ * Add a header to be used by libkvm to get the va to pa delta
+ */
+static int
+dump_os_header(struct dumperinfo *di)
+{
+	Elf_Phdr phdr;
+	int error;
+
+	bzero(&phdr, sizeof(phdr));
+	phdr.p_type = PT_DUMP_DELTA;
+	phdr.p_flags = PF_R;			/* XXX */
+	phdr.p_offset = 0;
+	phdr.p_vaddr = KERNVIRTADDR;
+	phdr.p_paddr = pmap_kextract(KERNVIRTADDR);
+	phdr.p_filesz = 0;
+	phdr.p_memsz = 0;
+	phdr.p_align = PAGE_SIZE;
+
+	error = buf_write(di, (char*)&phdr, sizeof(phdr));
+	return (error);
+}
+
 static int
 cb_size(struct md_pa *mdp, int seqnr, void *arg)
 {
@@ -311,7 +334,7 @@ dumpsys(struct dumperinfo *di)
 
 	/* Calculate dump size. */
 	dumpsize = 0L;
-	ehdr.e_phnum = foreach_chunk(cb_size, &dumpsize);
+	ehdr.e_phnum = foreach_chunk(cb_size, &dumpsize) + 1;
 	hdrsz = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize;
 	fileofs = MD_ALIGN(hdrsz);
 	dumpsize += fileofs;
@@ -328,7 +351,7 @@ dumpsys(struct dumperinfo *di)
 	mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_ARM_VERSION, dumpsize, di->blocksize);
 
 	printf("Dumping %llu MB (%d chunks)\n", (long long)dumpsize >> 20,
-	    ehdr.e_phnum);
+	    ehdr.e_phnum - 1);
 
 	/* Dump leader */
 	error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh));
@@ -343,6 +366,8 @@ dumpsys(struct dumperinfo *di)
 
 	/* Dump program headers */
 	error = foreach_chunk(cb_dumphdr, di);
+	if (error >= 0)
+		error = dump_os_header(di);
 	if (error < 0)
 		goto fail;
 	buf_flush(di);

Modified: stable/10/sys/sys/elf_common.h
==============================================================================
--- stable/10/sys/sys/elf_common.h	Wed Oct 29 16:24:02 2014	(r273827)
+++ stable/10/sys/sys/elf_common.h	Wed Oct 29 16:36:08 2014	(r273828)
@@ -339,6 +339,8 @@ typedef struct {
 #define	PT_GNU_EH_FRAME	0x6474e550
 #define	PT_GNU_STACK	0x6474e551
 #define	PT_GNU_RELRO	0x6474e552
+#define	PT_DUMP_DELTA	0x6fb5d000	/* va->pa map for kernel dumps
+					   (currently arm). */
 #define	PT_LOSUNW	0x6ffffffa
 #define	PT_SUNWBSS	0x6ffffffa	/* Sun Specific segment */
 #define	PT_SUNWSTACK	0x6ffffffb	/* describes the stack segment */


More information about the svn-src-all mailing list