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
This commit is contained in:
Svatopluk Kraus 2016-01-15 18:53:06 +00:00
parent 765b890b92
commit effb4b3c8c
4 changed files with 49 additions and 11 deletions

View File

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

View File

@ -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);

View File

@ -312,7 +312,12 @@ minidumpsys(struct dumperinfo *di)
mdhdr.bitmapsize = vm_page_dump_size;
mdhdr.ptesize = ptesize;
mdhdr.kernbase = KERNBASE;
mdhdr.arch = __ARM_ARCH;
#if __ARM_ARCH >= 6
mdhdr.mmuformat = MINIDUMP_MMU_FORMAT_V6;
#else
mdhdr.mmuformat = MINIDUMP_MMU_FORMAT_V4;
#endif
mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_ARM_VERSION, dumpsize,
di->blocksize);

View File

@ -28,11 +28,18 @@
*/
#ifndef _MACHINE_MINIDUMP_H_
#define _MACHINE_MINIDUMP_H_ 1
#define _MACHINE_MINIDUMP_H_
#define MINIDUMP_MAGIC "minidump FreeBSD/arm"
#define MINIDUMP_VERSION 1
/*
* The first page of vmcore is dedicated to the following header.
* As the rest of the page is zeroed, any header extension can be
* done without version bumping. It should be taken into account
* only that new entries will be zero in old vmcores.
*/
struct minidumphdr {
char magic[24];
uint32_t version;
@ -40,6 +47,13 @@ struct minidumphdr {
uint32_t bitmapsize;
uint32_t ptesize;
uint32_t kernbase;
uint32_t arch;
uint32_t mmuformat;
};
#define MINIDUMP_MMU_FORMAT_UNKNOWN 0
#define MINIDUMP_MMU_FORMAT_V4 1
#define MINIDUMP_MMU_FORMAT_V6 2
#define MINIDUMP_MMU_FORMAT_V6_LPAE 3
#endif /* _MACHINE_MINIDUMP_H_ */