Changeset View
Changeset View
Standalone View
Standalone View
head/lib/libkvm/kvm_minidump_amd64.c
Show First 20 Lines • Show All 117 Lines • ▼ Show 20 Lines | _amd64_minidump_freevtop(kvm_t *kd) | ||||
free(vm); | free(vm); | ||||
kd->vmst = NULL; | kd->vmst = NULL; | ||||
} | } | ||||
static int | static int | ||||
_amd64_minidump_initvtop(kvm_t *kd) | _amd64_minidump_initvtop(kvm_t *kd) | ||||
{ | { | ||||
struct vmstate *vmst; | struct vmstate *vmst; | ||||
off_t off, sparse_off; | off_t off, dump_avail_off, sparse_off; | ||||
vmst = _kvm_malloc(kd, sizeof(*vmst)); | vmst = _kvm_malloc(kd, sizeof(*vmst)); | ||||
if (vmst == NULL) { | if (vmst == NULL) { | ||||
_kvm_err(kd, kd->program, "cannot allocate vm"); | _kvm_err(kd, kd->program, "cannot allocate vm"); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
kd->vmst = vmst; | kd->vmst = vmst; | ||||
if (pread(kd->pmfd, &vmst->hdr, sizeof(vmst->hdr), 0) != | if (pread(kd->pmfd, &vmst->hdr, sizeof(vmst->hdr), 0) != | ||||
sizeof(vmst->hdr)) { | sizeof(vmst->hdr)) { | ||||
_kvm_err(kd, kd->program, "cannot read dump header"); | _kvm_err(kd, kd->program, "cannot read dump header"); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
if (strncmp(MINIDUMP_MAGIC, vmst->hdr.magic, sizeof(vmst->hdr.magic)) != 0) { | if (strncmp(MINIDUMP_MAGIC, vmst->hdr.magic, sizeof(vmst->hdr.magic)) != 0) { | ||||
_kvm_err(kd, kd->program, "not a minidump for this platform"); | _kvm_err(kd, kd->program, "not a minidump for this platform"); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
/* | /* | ||||
* NB: amd64 minidump header is binary compatible between version 1 | * NB: amd64 minidump header is binary compatible between version 1 | ||||
* and version 2; this may not be the case for the future versions. | * and version 2; version 3 adds the dumpavailsize field | ||||
*/ | */ | ||||
vmst->hdr.version = le32toh(vmst->hdr.version); | vmst->hdr.version = le32toh(vmst->hdr.version); | ||||
if (vmst->hdr.version != MINIDUMP_VERSION && vmst->hdr.version != 1) { | if (vmst->hdr.version > MINIDUMP_VERSION || vmst->hdr.version < 1) { | ||||
_kvm_err(kd, kd->program, "wrong minidump version. expected %d got %d", | _kvm_err(kd, kd->program, "wrong minidump version. expected %d got %d", | ||||
MINIDUMP_VERSION, vmst->hdr.version); | MINIDUMP_VERSION, vmst->hdr.version); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
vmst->hdr.msgbufsize = le32toh(vmst->hdr.msgbufsize); | vmst->hdr.msgbufsize = le32toh(vmst->hdr.msgbufsize); | ||||
vmst->hdr.bitmapsize = le32toh(vmst->hdr.bitmapsize); | vmst->hdr.bitmapsize = le32toh(vmst->hdr.bitmapsize); | ||||
vmst->hdr.pmapsize = le32toh(vmst->hdr.pmapsize); | vmst->hdr.pmapsize = le32toh(vmst->hdr.pmapsize); | ||||
vmst->hdr.kernbase = le64toh(vmst->hdr.kernbase); | vmst->hdr.kernbase = le64toh(vmst->hdr.kernbase); | ||||
vmst->hdr.dmapbase = le64toh(vmst->hdr.dmapbase); | vmst->hdr.dmapbase = le64toh(vmst->hdr.dmapbase); | ||||
vmst->hdr.dmapend = le64toh(vmst->hdr.dmapend); | vmst->hdr.dmapend = le64toh(vmst->hdr.dmapend); | ||||
vmst->hdr.dumpavailsize = vmst->hdr.version == MINIDUMP_VERSION ? | |||||
le32toh(vmst->hdr.dumpavailsize) : 0; | |||||
/* Skip header and msgbuf */ | /* Skip header and msgbuf */ | ||||
off = AMD64_PAGE_SIZE + amd64_round_page(vmst->hdr.msgbufsize); | dump_avail_off = AMD64_PAGE_SIZE + amd64_round_page(vmst->hdr.msgbufsize); | ||||
/* Skip dump_avail */ | |||||
off = dump_avail_off + amd64_round_page(vmst->hdr.dumpavailsize); | |||||
sparse_off = off + amd64_round_page(vmst->hdr.bitmapsize) + | sparse_off = off + amd64_round_page(vmst->hdr.bitmapsize) + | ||||
amd64_round_page(vmst->hdr.pmapsize); | amd64_round_page(vmst->hdr.pmapsize); | ||||
if (_kvm_pt_init(kd, vmst->hdr.bitmapsize, off, sparse_off, | if (_kvm_pt_init(kd, vmst->hdr.dumpavailsize, dump_avail_off, | ||||
AMD64_PAGE_SIZE, sizeof(uint64_t)) == -1) { | vmst->hdr.bitmapsize, off, sparse_off, AMD64_PAGE_SIZE, | ||||
sizeof(uint64_t)) == -1) { | |||||
return (-1); | return (-1); | ||||
} | } | ||||
off += amd64_round_page(vmst->hdr.bitmapsize); | off += amd64_round_page(vmst->hdr.bitmapsize); | ||||
if (_kvm_pmap_init(kd, vmst->hdr.pmapsize, off) == -1) { | if (_kvm_pmap_init(kd, vmst->hdr.pmapsize, off) == -1) { | ||||
return (-1); | return (-1); | ||||
} | } | ||||
off += amd64_round_page(vmst->hdr.pmapsize); | off += amd64_round_page(vmst->hdr.pmapsize); | ||||
▲ Show 20 Lines • Show All 191 Lines • ▼ Show 20 Lines | if ((pde & AMD64_PG_PS) != 0) { | ||||
* Large page. Iterate on each 4K page section | * Large page. Iterate on each 4K page section | ||||
* within this page. This differs from 4K pages in | * within this page. This differs from 4K pages in | ||||
* that every page here uses the same PDE to | * that every page here uses the same PDE to | ||||
* generate permissions. | * generate permissions. | ||||
*/ | */ | ||||
pa = (pde & AMD64_PG_PS_FRAME) + | pa = (pde & AMD64_PG_PS_FRAME) + | ||||
((va & AMD64_PDRMASK) ^ VA_OFF(vm, va)); | ((va & AMD64_PDRMASK) ^ VA_OFF(vm, va)); | ||||
dva = vm->hdr.dmapbase + pa; | dva = vm->hdr.dmapbase + pa; | ||||
_kvm_bitmap_set(&bm, pa, AMD64_PAGE_SIZE); | _kvm_bitmap_set(&bm, _kvm_pa_bit_id(kd, pa, AMD64_PAGE_SIZE)); | ||||
if (!_kvm_visit_cb(kd, cb, arg, pa, va, dva, | if (!_kvm_visit_cb(kd, cb, arg, pa, va, dva, | ||||
_amd64_entry_to_prot(pde), AMD64_NBPDR, pgsz)) { | _amd64_entry_to_prot(pde), AMD64_NBPDR, pgsz)) { | ||||
goto out; | goto out; | ||||
} | } | ||||
continue; | continue; | ||||
} | } | ||||
/* 4K pages: pde references another page of entries. */ | /* 4K pages: pde references another page of entries. */ | ||||
ptes = _amd64_pde_first_pte(kd, pdeindex); | ptes = _amd64_pde_first_pte(kd, pdeindex); | ||||
/* Ignore page directory pages that were not dumped. */ | /* Ignore page directory pages that were not dumped. */ | ||||
if (ptes == NULL) | if (ptes == NULL) | ||||
continue; | continue; | ||||
for (i = 0; i < AMD64_NPTEPG; i++) { | for (i = 0; i < AMD64_NPTEPG; i++) { | ||||
amd64_pte_t pte = (u_long)ptes[i]; | amd64_pte_t pte = (u_long)ptes[i]; | ||||
pa = pte & AMD64_PG_FRAME; | pa = pte & AMD64_PG_FRAME; | ||||
dva = vm->hdr.dmapbase + pa; | dva = vm->hdr.dmapbase + pa; | ||||
if ((pte & AMD64_PG_V) != 0) { | if ((pte & AMD64_PG_V) != 0) { | ||||
_kvm_bitmap_set(&bm, pa, AMD64_PAGE_SIZE); | _kvm_bitmap_set(&bm, | ||||
_kvm_pa_bit_id(kd, pa, AMD64_PAGE_SIZE)); | |||||
if (!_kvm_visit_cb(kd, cb, arg, pa, va, dva, | if (!_kvm_visit_cb(kd, cb, arg, pa, va, dva, | ||||
_amd64_entry_to_prot(pte), pgsz, 0)) { | _amd64_entry_to_prot(pte), pgsz, 0)) { | ||||
goto out; | goto out; | ||||
} | } | ||||
} | } | ||||
va += AMD64_PAGE_SIZE; | va += AMD64_PAGE_SIZE; | ||||
} | } | ||||
} | } | ||||
while (_kvm_bitmap_next(&bm, &bmindex)) { | while (_kvm_bitmap_next(&bm, &bmindex)) { | ||||
pa = bmindex * AMD64_PAGE_SIZE; | pa = _kvm_bit_id_pa(kd, bmindex, AMD64_PAGE_SIZE); | ||||
if (pa == _KVM_PA_INVALID) | |||||
break; | |||||
dva = vm->hdr.dmapbase + pa; | dva = vm->hdr.dmapbase + pa; | ||||
if (vm->hdr.dmapend < (dva + pgsz)) | if (vm->hdr.dmapend < (dva + pgsz)) | ||||
break; | break; | ||||
va = 0; | va = 0; | ||||
/* amd64/pmap.c: create_pagetables(): dmap always R|W. */ | /* amd64/pmap.c: create_pagetables(): dmap always R|W. */ | ||||
prot = VM_PROT_READ | VM_PROT_WRITE; | prot = VM_PROT_READ | VM_PROT_WRITE; | ||||
if (!_kvm_visit_cb(kd, cb, arg, pa, va, dva, prot, pgsz, 0)) { | if (!_kvm_visit_cb(kd, cb, arg, pa, va, dva, prot, pgsz, 0)) { | ||||
goto out; | goto out; | ||||
Show All 20 Lines |