Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F111587480
D3319.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D3319.diff
View Options
Index: head/lib/libkvm/kvm_aarch64.c
===================================================================
--- head/lib/libkvm/kvm_aarch64.c
+++ head/lib/libkvm/kvm_aarch64.c
@@ -1,5 +1,6 @@
/*-
- * Copyright (c) 2014 The FreeBSD Foundation
+ * Copyright (C) 2006 Bruce M. Simpson.
+ * Copyright (c) 2015 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Andrew Turner under
@@ -27,38 +28,78 @@
* SUCH DAMAGE.
*/
+/*
+ * arm64 (AArch64) machine dependent routines for kvm.
+ */
+
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/mman.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
+#include <machine/pmap.h>
#include <limits.h>
#include <kvm.h>
-#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
#include "kvm_private.h"
+/* minidump must be the first item! */
+struct vmstate {
+ int minidump; /* 1 = minidump mode */
+ void *mmapbase;
+ size_t mmapsize;
+};
+
void
_kvm_freevtop(kvm_t *kd)
{
- printf("_kvm_freevtop\n");
- abort();
+ if (kd->vmst != 0) {
+ if (kd->vmst->minidump)
+ return (_kvm_minidump_freevtop(kd));
+ if (kd->vmst->mmapbase != NULL)
+ munmap(kd->vmst->mmapbase, kd->vmst->mmapsize);
+ free(kd->vmst);
+ kd->vmst = NULL;
+ }
}
int
_kvm_initvtop(kvm_t *kd)
{
+ char minihdr[8];
+
+ if (!kd->rawdump) {
+ if (pread(kd->pmfd, &minihdr, 8, 0) == 8) {
+ if (memcmp(&minihdr, "minidump", 8) == 0)
+ return (_kvm_minidump_initvtop(kd));
+ } else {
+ _kvm_err(kd, kd->program, "cannot read header");
+ return (-1);
+ }
+ }
- printf("_kvm_initvtop\n");
- abort();
+ _kvm_err(kd, 0, "_kvm_initvtop: Unsupported image type");
+ return (-1);
}
int
_kvm_kvatop(kvm_t *kd, u_long va, off_t *pa)
{
- printf("_kvm_kvatop\n");
- abort();
+ if (kd->vmst->minidump)
+ return _kvm_minidump_kvatop(kd, va, pa);
+
+
+ _kvm_err(kd, 0, "_kvm_kvatop: Unsupported image type");
+ return (0);
}
Index: head/lib/libkvm/kvm_minidump_aarch64.c
===================================================================
--- head/lib/libkvm/kvm_minidump_aarch64.c
+++ head/lib/libkvm/kvm_minidump_aarch64.c
@@ -0,0 +1,269 @@
+/*-
+ * Copyright (c) 2006 Peter Wemm
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * From: FreeBSD: src/lib/libkvm/kvm_minidump_amd64.c r261799
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * ARM64 (AArch64) machine dependent routines for kvm and minidumps.
+ */
+
+#include <sys/param.h>
+#include <sys/user.h>
+#include <sys/proc.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/fnv_hash.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <nlist.h>
+#include <kvm.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+
+#include <machine/elf.h>
+#include <machine/cpufunc.h>
+#include <machine/pte.h>
+#include <machine/minidump.h>
+
+#include <limits.h>
+#include <stdint.h>
+
+#include "kvm_private.h"
+
+struct hpte {
+ struct hpte *next;
+ vm_paddr_t pa;
+ int64_t off;
+};
+
+#define HPT_SIZE 1024
+
+/* minidump must be the first item! */
+struct vmstate {
+ int minidump; /* 1 = minidump mode */
+ struct minidumphdr hdr;
+ void *hpt_head[HPT_SIZE];
+ uint64_t *bitmap;
+ uint64_t *page_map;
+};
+
+static void
+hpt_insert(kvm_t *kd, vm_paddr_t pa, int64_t off)
+{
+ struct hpte *hpte;
+ uint32_t fnv = FNV1_32_INIT;
+
+ fnv = fnv_32_buf(&pa, sizeof(pa), fnv);
+ fnv &= (HPT_SIZE - 1);
+ hpte = malloc(sizeof(*hpte));
+ hpte->pa = pa;
+ hpte->off = off;
+ hpte->next = kd->vmst->hpt_head[fnv];
+ kd->vmst->hpt_head[fnv] = hpte;
+}
+
+static int64_t
+hpt_find(kvm_t *kd, vm_paddr_t pa)
+{
+ struct hpte *hpte;
+ uint32_t fnv = FNV1_32_INIT;
+
+ fnv = fnv_32_buf(&pa, sizeof(pa), fnv);
+ fnv &= (HPT_SIZE - 1);
+ for (hpte = kd->vmst->hpt_head[fnv]; hpte != NULL; hpte = hpte->next) {
+ if (pa == hpte->pa)
+ return (hpte->off);
+ }
+ return (-1);
+}
+
+static int
+inithash(kvm_t *kd, uint64_t *base, int len, off_t off)
+{
+ uint64_t idx;
+ uint64_t bit, bits;
+ vm_paddr_t pa;
+
+ for (idx = 0; idx < len / sizeof(*base); idx++) {
+ bits = base[idx];
+ while (bits) {
+ bit = ffsl(bits) - 1;
+ bits &= ~(1ul << bit);
+ pa = (idx * sizeof(*base) * NBBY + bit) * PAGE_SIZE;
+ hpt_insert(kd, pa, off);
+ off += PAGE_SIZE;
+ }
+ }
+ return (off);
+}
+
+void
+_kvm_minidump_freevtop(kvm_t *kd)
+{
+ struct vmstate *vm = kd->vmst;
+
+ free(vm->bitmap);
+ free(vm->page_map);
+ free(vm);
+ kd->vmst = NULL;
+}
+
+int
+_kvm_minidump_initvtop(kvm_t *kd)
+{
+ struct vmstate *vmst;
+ off_t off;
+
+ vmst = _kvm_malloc(kd, sizeof(*vmst));
+ if (vmst == 0) {
+ _kvm_err(kd, kd->program, "cannot allocate vm");
+ return (-1);
+ }
+ kd->vmst = vmst;
+ vmst->minidump = 1;
+ if (pread(kd->pmfd, &vmst->hdr, sizeof(vmst->hdr), 0) !=
+ sizeof(vmst->hdr)) {
+ _kvm_err(kd, kd->program, "cannot read dump header");
+ return (-1);
+ }
+ if (strncmp(MINIDUMP_MAGIC, vmst->hdr.magic,
+ sizeof(vmst->hdr.magic)) != 0) {
+ _kvm_err(kd, kd->program, "not a minidump for this platform");
+ return (-1);
+ }
+
+ if (vmst->hdr.version != MINIDUMP_VERSION && vmst->hdr.version != 1) {
+ _kvm_err(kd, kd->program, "wrong minidump version. "
+ "Expected %d got %d", MINIDUMP_VERSION, vmst->hdr.version);
+ return (-1);
+ }
+
+ /* Skip header and msgbuf */
+ off = PAGE_SIZE + round_page(vmst->hdr.msgbufsize);
+
+ vmst->bitmap = _kvm_malloc(kd, vmst->hdr.bitmapsize);
+ if (vmst->bitmap == NULL) {
+ _kvm_err(kd, kd->program,
+ "cannot allocate %d bytes for bitmap",
+ vmst->hdr.bitmapsize);
+ return (-1);
+ }
+ if (pread(kd->pmfd, vmst->bitmap, vmst->hdr.bitmapsize, off) !=
+ vmst->hdr.bitmapsize) {
+ _kvm_err(kd, kd->program,
+ "cannot read %d bytes for page bitmap",
+ vmst->hdr.bitmapsize);
+ return (-1);
+ }
+ off += round_page(vmst->hdr.bitmapsize);
+
+ vmst->page_map = _kvm_malloc(kd, vmst->hdr.pmapsize);
+ if (vmst->page_map == NULL) {
+ _kvm_err(kd, kd->program,
+ "cannot allocate %d bytes for page_map",
+ vmst->hdr.pmapsize);
+ return (-1);
+ }
+ /* This is the end of the dump, savecore may have truncated it. */
+ if (pread(kd->pmfd, vmst->page_map, vmst->hdr.pmapsize, off) <
+ PAGE_SIZE) {
+ _kvm_err(kd, kd->program, "cannot read %d bytes for page_map",
+ vmst->hdr.pmapsize);
+ }
+ off += vmst->hdr.pmapsize;
+
+ /* build physical address hash table for sparse pages */
+ inithash(kd, vmst->bitmap, vmst->hdr.bitmapsize, off);
+
+ return (0);
+}
+
+static int
+_kvm_minidump_vatop(kvm_t *kd, u_long va, off_t *pa)
+{
+ struct vmstate *vm;
+ u_long offset;
+ pt_entry_t l3;
+ u_long l3_index;
+ u_long a;
+ off_t ofs;
+
+ vm = kd->vmst;
+ offset = va & PAGE_MASK;
+
+ if (va >= vm->hdr.dmapbase && va < vm->hdr.dmapend) {
+ a = (va - vm->hdr.dmapbase + vm->hdr.dmapphys) & ~PAGE_MASK;
+ ofs = hpt_find(kd, a);
+ if (ofs == -1) {
+ _kvm_err(kd, kd->program, "_kvm_vatop: "
+ "direct map address 0x%lx not in minidump", va);
+ goto invalid;
+ }
+ *pa = ofs + offset;
+ return (PAGE_SIZE - offset);
+ } else if (va >= vm->hdr.kernbase) {
+ l3_index = (va - vm->hdr.kernbase) >> L3_SHIFT;
+ if (l3_index >= vm->hdr.pmapsize / sizeof(*vm->page_map))
+ goto invalid;
+ l3 = vm->page_map[l3_index];
+ if ((l3 & ATTR_DESCR_MASK) != L3_PAGE) {
+ _kvm_err(kd, kd->program, "_kvm_vatop: pde not valid");
+ goto invalid;
+ }
+ a = l3 & ~ATTR_MASK;
+ ofs = hpt_find(kd, a);
+ if (ofs == -1) {
+ _kvm_err(kd, kd->program, "_kvm_vatop: "
+ "physical address 0x%lx not in minidump", a);
+ goto invalid;
+ }
+ *pa = ofs + offset;
+ return (PAGE_SIZE - offset);
+ } else {
+ _kvm_err(kd, kd->program,
+ "_kvm_vatop: virtual address 0x%lx not minidumped", va);
+ goto invalid;
+ }
+
+invalid:
+ _kvm_err(kd, 0, "invalid address (0x%lx)", va);
+ return (0);
+}
+
+int
+_kvm_minidump_kvatop(kvm_t *kd, u_long va, off_t *pa)
+{
+
+ if (ISALIVE(kd)) {
+ _kvm_err(kd, 0, "kvm_kvatop called in live kernel!");
+ return (0);
+ }
+ return (_kvm_minidump_vatop(kd, va, pa));
+}
Index: head/lib/libkvm/kvm_private.h
===================================================================
--- head/lib/libkvm/kvm_private.h
+++ head/lib/libkvm/kvm_private.h
@@ -104,8 +104,8 @@
int _kvm_dpcpu_initialized(kvm_t *, int);
uintptr_t _kvm_dpcpu_validaddr(kvm_t *, uintptr_t);
-#if defined(__amd64__) || defined(__i386__) || defined(__arm__) || \
- defined(__mips__)
+#if defined(__aarch64__) || defined(__amd64__) || defined(__arm__) || \
+ defined(__i386__) || defined(__mips__)
void _kvm_minidump_freevtop(kvm_t *);
int _kvm_minidump_initvtop(kvm_t *);
int _kvm_minidump_kvatop(kvm_t *, u_long, off_t *);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Mar 6, 3:54 PM (8 h, 45 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17009001
Default Alt Text
D3319.diff (9 KB)
Attached To
Mode
D3319: Add support to read arm64 minidumps to libkvm
Attached
Detach File
Event Timeline
Log In to Comment