summaryrefslogtreecommitdiffstats
path: root/lib/libkvm
diff options
context:
space:
mode:
authorskra <skra@FreeBSD.org>2016-01-15 18:53:06 +0000
committerskra <skra@FreeBSD.org>2016-01-15 18:53:06 +0000
commit12fce57c8cb14423ce57f4c67d69098043e1dab8 (patch)
tree25c0fb18c21d2b6dfd083920de36e7f780f3e9e5 /lib/libkvm
parent60d3f112d9185ce3c85a9103d6b067ac21e1dfc8 (diff)
downloadFreeBSD-src-12fce57c8cb14423ce57f4c67d69098043e1dab8.zip
FreeBSD-src-12fce57c8cb14423ce57f4c67d69098043e1dab8.tar.gz
Add mmu format info into ARM vmcore.
Fix kvatop translation for 64K pages. Reviewed by: jhb Approved by: kib (mentor) Differential Revision: https://reviews.freebsd.org/D4942
Diffstat (limited to 'lib/libkvm')
-rw-r--r--lib/libkvm/kvm_arm.h10
-rw-r--r--lib/libkvm/kvm_minidump_arm.c27
2 files changed, 28 insertions, 9 deletions
diff --git a/lib/libkvm/kvm_arm.h b/lib/libkvm/kvm_arm.h
index 844e158..096a6b1 100644
--- a/lib/libkvm/kvm_arm.h
+++ b/lib/libkvm/kvm_arm.h
@@ -67,13 +67,16 @@ typedef uint32_t arm_pt_entry_t;
#define ARM_L1_C_ADDR_MASK 0xfffffc00 /* phys address of L2 Table */
#define ARM_L2_TYPE_INV 0x00 /* Invalid (fault) */
-#define ARM_L2_TYPE_L 0x01 /* Large Page - 64k - not used yet*/
-#define ARM_L2_TYPE_S 0x02 /* Small Page - 4 */
+#define ARM_L2_TYPE_L 0x01 /* Large Page - 64k */
+#define ARM_L2_TYPE_S 0x02 /* Small Page - 4k */
+#define ARM_L2_TYPE_T 0x03 /* Tiny Page - 1k - not used */
#define ARM_L2_TYPE_MASK 0x03
#define ARM_L2_ADDR_BITS 0x000ff000 /* L2 PTE address bits */
#ifdef __arm__
+#include <machine/acle-compat.h>
+
_Static_assert(PAGE_SHIFT == ARM_PAGE_SHIFT, "PAGE_SHIFT mismatch");
_Static_assert(PAGE_SIZE == ARM_PAGE_SIZE, "PAGE_SIZE mismatch");
_Static_assert(PAGE_MASK == ARM_PAGE_MASK, "PAGE_MASK mismatch");
@@ -99,6 +102,9 @@ _Static_assert(L1_C_ADDR_MASK == ARM_L1_C_ADDR_MASK, "L1_C_ADDR_MASK mismatch");
_Static_assert(L2_TYPE_INV == ARM_L2_TYPE_INV, "L2_TYPE_INV mismatch");
_Static_assert(L2_TYPE_L == ARM_L2_TYPE_L, "L2_TYPE_L mismatch");
_Static_assert(L2_TYPE_S == ARM_L2_TYPE_S, "L2_TYPE_S mismatch");
+#if __ARM_ARCH < 6
+_Static_assert(L2_TYPE_T == ARM_L2_TYPE_T, "L2_TYPE_T mismatch");
+#endif
_Static_assert(L2_TYPE_MASK == ARM_L2_TYPE_MASK, "L2_TYPE_MASK mismatch");
_Static_assert(L2_ADDR_BITS == ARM_L2_ADDR_BITS, "L2_ADDR_BITS mismatch");
#endif
diff --git a/lib/libkvm/kvm_minidump_arm.c b/lib/libkvm/kvm_minidump_arm.c
index 9e9cd67..4d76666 100644
--- a/lib/libkvm/kvm_minidump_arm.c
+++ b/lib/libkvm/kvm_minidump_arm.c
@@ -112,6 +112,12 @@ _arm_minidump_initvtop(kvm_t *kd)
vmst->hdr.bitmapsize = _kvm32toh(kd, vmst->hdr.bitmapsize);
vmst->hdr.ptesize = _kvm32toh(kd, vmst->hdr.ptesize);
vmst->hdr.kernbase = _kvm32toh(kd, vmst->hdr.kernbase);
+ vmst->hdr.arch = _kvm32toh(kd, vmst->hdr.arch);
+ vmst->hdr.mmuformat = _kvm32toh(kd, vmst->hdr.mmuformat);
+ if (vmst->hdr.mmuformat == MINIDUMP_MMU_FORMAT_UNKNOWN) {
+ /* This is a safe default as 1K pages are not used. */
+ vmst->hdr.mmuformat = MINIDUMP_MMU_FORMAT_V6;
+ }
/* Skip header and msgbuf */
off = ARM_PAGE_SIZE + arm_round_page(vmst->hdr.msgbufsize);
@@ -179,19 +185,27 @@ _arm_minidump_kvatop(kvm_t *kd, kvaddr_t va, off_t *pa)
if (va >= vm->hdr.kernbase) {
pteindex = (va - vm->hdr.kernbase) >> ARM_PAGE_SHIFT;
pte = _kvm32toh(kd, ptemap[pteindex]);
- if (!pte) {
+ if ((pte & ARM_L2_TYPE_MASK) == ARM_L2_TYPE_INV) {
_kvm_err(kd, kd->program,
"_arm_minidump_kvatop: pte not valid");
goto invalid;
}
if ((pte & ARM_L2_TYPE_MASK) == ARM_L2_TYPE_L) {
- offset = va & ARM_L2_L_OFFSET;
- a = pte & ARM_L2_L_FRAME;
- } else if ((pte & ARM_L2_TYPE_MASK) == ARM_L2_TYPE_S) {
+ /* 64K page -> convert to be like 4K page */
+ offset = va & ARM_L2_S_OFFSET;
+ a = (pte & ARM_L2_L_FRAME) +
+ (va & ARM_L2_L_OFFSET & ARM_L2_S_FRAME);
+ } else {
+ if (kd->vmst->hdr.mmuformat == MINIDUMP_MMU_FORMAT_V4 &&
+ (pte & ARM_L2_TYPE_MASK) == ARM_L2_TYPE_T) {
+ _kvm_err(kd, kd->program,
+ "_arm_minidump_kvatop: pte not supported");
+ goto invalid;
+ }
+ /* 4K page */
offset = va & ARM_L2_S_OFFSET;
a = pte & ARM_L2_S_FRAME;
- } else
- goto invalid;
+ }
ofs = _kvm_hpt_find(&vm->hpt, a);
if (ofs == -1) {
@@ -203,7 +217,6 @@ _arm_minidump_kvatop(kvm_t *kd, kvaddr_t va, off_t *pa)
*pa = ofs + offset;
return (ARM_PAGE_SIZE - offset);
-
} else
_kvm_err(kd, kd->program, "_arm_minidump_kvatop: virtual "
"address 0x%jx not minidumped", (uintmax_t)va);
OpenPOWER on IntegriCloud