xref: /freebsd/lib/libkvm/kvm_minidump_i386.c (revision 1d386b48)
1e9ca6fe4SPeter Wemm /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
35e53a4f9SPedro F. Giffuni  *
4e9ca6fe4SPeter Wemm  * Copyright (c) 2006 Peter Wemm
5e9ca6fe4SPeter Wemm  *
6e9ca6fe4SPeter Wemm  * Redistribution and use in source and binary forms, with or without
7e9ca6fe4SPeter Wemm  * modification, are permitted provided that the following conditions
8e9ca6fe4SPeter Wemm  * are met:
9e9ca6fe4SPeter Wemm  * 1. Redistributions of source code must retain the above copyright
10e9ca6fe4SPeter Wemm  *    notice, this list of conditions and the following disclaimer.
11e9ca6fe4SPeter Wemm  * 2. Redistributions in binary form must reproduce the above copyright
12e9ca6fe4SPeter Wemm  *    notice, this list of conditions and the following disclaimer in the
13e9ca6fe4SPeter Wemm  *    documentation and/or other materials provided with the distribution.
14e9ca6fe4SPeter Wemm  *
15e9ca6fe4SPeter Wemm  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16e9ca6fe4SPeter Wemm  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17e9ca6fe4SPeter Wemm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18e9ca6fe4SPeter Wemm  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19e9ca6fe4SPeter Wemm  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20e9ca6fe4SPeter Wemm  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21e9ca6fe4SPeter Wemm  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22e9ca6fe4SPeter Wemm  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23e9ca6fe4SPeter Wemm  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24e9ca6fe4SPeter Wemm  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25e9ca6fe4SPeter Wemm  * SUCH DAMAGE.
26e9ca6fe4SPeter Wemm  */
27e9ca6fe4SPeter Wemm 
28e9ca6fe4SPeter Wemm #include <sys/cdefs.h>
29e9ca6fe4SPeter Wemm /*
307f911abeSJohn Baldwin  * i386 machine dependent routines for kvm and minidumps.
31e9ca6fe4SPeter Wemm  */
32e9ca6fe4SPeter Wemm 
33e9ca6fe4SPeter Wemm #include <sys/param.h>
347f911abeSJohn Baldwin #include <sys/endian.h>
357f911abeSJohn Baldwin #include <stdint.h>
36e9ca6fe4SPeter Wemm #include <stdlib.h>
37953e4134SEd Schouten #include <string.h>
38e9ca6fe4SPeter Wemm #include <unistd.h>
398baaf913SWill Andrews #include <vm/vm.h>
40e9ca6fe4SPeter Wemm #include <kvm.h>
41e9ca6fe4SPeter Wemm 
427f911abeSJohn Baldwin #include "../../sys/i386/include/minidump.h"
43e9ca6fe4SPeter Wemm 
44e9ca6fe4SPeter Wemm #include <limits.h>
45e9ca6fe4SPeter Wemm 
46e9ca6fe4SPeter Wemm #include "kvm_private.h"
477f911abeSJohn Baldwin #include "kvm_i386.h"
48e9ca6fe4SPeter Wemm 
497f911abeSJohn Baldwin #define	i386_round_page(x)	roundup2((kvaddr_t)(x), I386_PAGE_SIZE)
50e9ca6fe4SPeter Wemm 
51e9ca6fe4SPeter Wemm struct vmstate {
52e9ca6fe4SPeter Wemm 	struct minidumphdr hdr;
53e9ca6fe4SPeter Wemm };
54e9ca6fe4SPeter Wemm 
55c9057838SWill Andrews static i386_pte_pae_t
_i386_pte_pae_get(kvm_t * kd,u_long pteindex)56c9057838SWill Andrews _i386_pte_pae_get(kvm_t *kd, u_long pteindex)
57c9057838SWill Andrews {
58c9057838SWill Andrews 	i386_pte_pae_t *pte = _kvm_pmap_get(kd, pteindex, sizeof(*pte));
59c9057838SWill Andrews 
60c9057838SWill Andrews 	return le64toh(*pte);
61c9057838SWill Andrews }
62c9057838SWill Andrews 
63c9057838SWill Andrews static i386_pte_t
_i386_pte_get(kvm_t * kd,u_long pteindex)64c9057838SWill Andrews _i386_pte_get(kvm_t *kd, u_long pteindex)
65c9057838SWill Andrews {
66c9057838SWill Andrews 	i386_pte_t *pte = _kvm_pmap_get(kd, pteindex, sizeof(*pte));
67c9057838SWill Andrews 
68c9057838SWill Andrews 	return le32toh(*pte);
69c9057838SWill Andrews }
70c9057838SWill Andrews 
71e9ca6fe4SPeter Wemm static int
_i386_minidump_probe(kvm_t * kd)727f911abeSJohn Baldwin _i386_minidump_probe(kvm_t *kd)
73e9ca6fe4SPeter Wemm {
74e9ca6fe4SPeter Wemm 
757f911abeSJohn Baldwin 	return (_kvm_probe_elf_kernel(kd, ELFCLASS32, EM_386) &&
767f911abeSJohn Baldwin 	    _kvm_is_minidump(kd));
77e9ca6fe4SPeter Wemm }
78e9ca6fe4SPeter Wemm 
797f911abeSJohn Baldwin static void
_i386_minidump_freevtop(kvm_t * kd)807f911abeSJohn Baldwin _i386_minidump_freevtop(kvm_t *kd)
81e9ca6fe4SPeter Wemm {
82e9ca6fe4SPeter Wemm 	struct vmstate *vm = kd->vmst;
83e9ca6fe4SPeter Wemm 
84e9ca6fe4SPeter Wemm 	free(vm);
85e9ca6fe4SPeter Wemm 	kd->vmst = NULL;
86e9ca6fe4SPeter Wemm }
87e9ca6fe4SPeter Wemm 
887f911abeSJohn Baldwin static int
_i386_minidump_initvtop(kvm_t * kd)897f911abeSJohn Baldwin _i386_minidump_initvtop(kvm_t *kd)
90e9ca6fe4SPeter Wemm {
91e9ca6fe4SPeter Wemm 	struct vmstate *vmst;
9200e66147SD Scott Phillips 	off_t off, dump_avail_off, sparse_off;
93e9ca6fe4SPeter Wemm 
94e9ca6fe4SPeter Wemm 	vmst = _kvm_malloc(kd, sizeof(*vmst));
95fb0e1892SEnji Cooper 	if (vmst == NULL) {
96e9ca6fe4SPeter Wemm 		_kvm_err(kd, kd->program, "cannot allocate vm");
97e9ca6fe4SPeter Wemm 		return (-1);
98e9ca6fe4SPeter Wemm 	}
99e9ca6fe4SPeter Wemm 	kd->vmst = vmst;
100e9ca6fe4SPeter Wemm 	if (pread(kd->pmfd, &vmst->hdr, sizeof(vmst->hdr), 0) !=
101e9ca6fe4SPeter Wemm 	    sizeof(vmst->hdr)) {
102e9ca6fe4SPeter Wemm 		_kvm_err(kd, kd->program, "cannot read dump header");
103e9ca6fe4SPeter Wemm 		return (-1);
104e9ca6fe4SPeter Wemm 	}
105e9ca6fe4SPeter Wemm 	if (strncmp(MINIDUMP_MAGIC, vmst->hdr.magic, sizeof(vmst->hdr.magic)) != 0) {
106e9ca6fe4SPeter Wemm 		_kvm_err(kd, kd->program, "not a minidump for this platform");
107e9ca6fe4SPeter Wemm 		return (-1);
108e9ca6fe4SPeter Wemm 	}
1097f911abeSJohn Baldwin 	vmst->hdr.version = le32toh(vmst->hdr.version);
11000e66147SD Scott Phillips 	if (vmst->hdr.version != MINIDUMP_VERSION && vmst->hdr.version != 1) {
111e9ca6fe4SPeter Wemm 		_kvm_err(kd, kd->program, "wrong minidump version. expected %d got %d",
112e9ca6fe4SPeter Wemm 		    MINIDUMP_VERSION, vmst->hdr.version);
113e9ca6fe4SPeter Wemm 		return (-1);
114e9ca6fe4SPeter Wemm 	}
1157f911abeSJohn Baldwin 	vmst->hdr.msgbufsize = le32toh(vmst->hdr.msgbufsize);
1167f911abeSJohn Baldwin 	vmst->hdr.bitmapsize = le32toh(vmst->hdr.bitmapsize);
1177f911abeSJohn Baldwin 	vmst->hdr.ptesize = le32toh(vmst->hdr.ptesize);
1187f911abeSJohn Baldwin 	vmst->hdr.kernbase = le32toh(vmst->hdr.kernbase);
1197f911abeSJohn Baldwin 	vmst->hdr.paemode = le32toh(vmst->hdr.paemode);
12000e66147SD Scott Phillips 	vmst->hdr.dumpavailsize = vmst->hdr.version == MINIDUMP_VERSION ?
12100e66147SD Scott Phillips 	    le32toh(vmst->hdr.dumpavailsize) : 0;
122e9ca6fe4SPeter Wemm 
123e9ca6fe4SPeter Wemm 	/* Skip header and msgbuf */
12400e66147SD Scott Phillips 	dump_avail_off = I386_PAGE_SIZE + i386_round_page(vmst->hdr.msgbufsize);
12500e66147SD Scott Phillips 
12600e66147SD Scott Phillips 	/* Skip dump_avail */
12700e66147SD Scott Phillips 	off = dump_avail_off + i386_round_page(vmst->hdr.dumpavailsize);
128e9ca6fe4SPeter Wemm 
129ffdeef32SWill Andrews 	sparse_off = off + i386_round_page(vmst->hdr.bitmapsize) +
130ffdeef32SWill Andrews 	    i386_round_page(vmst->hdr.ptesize);
13100e66147SD Scott Phillips 	if (_kvm_pt_init(kd, vmst->hdr.dumpavailsize, dump_avail_off,
132b957b185SMark Johnston 	    vmst->hdr.bitmapsize, off, sparse_off, I386_PAGE_SIZE) == -1) {
133e9ca6fe4SPeter Wemm 		return (-1);
134e9ca6fe4SPeter Wemm 	}
1357f911abeSJohn Baldwin 	off += i386_round_page(vmst->hdr.bitmapsize);
136e9ca6fe4SPeter Wemm 
137c9057838SWill Andrews 	if (_kvm_pmap_init(kd, vmst->hdr.ptesize, off) == -1) {
138e9ca6fe4SPeter Wemm 		return (-1);
139e9ca6fe4SPeter Wemm 	}
140ffdeef32SWill Andrews 	off += i386_round_page(vmst->hdr.ptesize);
141e9ca6fe4SPeter Wemm 
142e9ca6fe4SPeter Wemm 	return (0);
143e9ca6fe4SPeter Wemm }
144e9ca6fe4SPeter Wemm 
145e9ca6fe4SPeter Wemm static int
_i386_minidump_vatop_pae(kvm_t * kd,kvaddr_t va,off_t * pa)1467f911abeSJohn Baldwin _i386_minidump_vatop_pae(kvm_t *kd, kvaddr_t va, off_t *pa)
147e9ca6fe4SPeter Wemm {
148e9ca6fe4SPeter Wemm 	struct vmstate *vm;
1497f911abeSJohn Baldwin 	i386_physaddr_pae_t offset;
1507f911abeSJohn Baldwin 	i386_pte_pae_t pte;
1517f911abeSJohn Baldwin 	kvaddr_t pteindex;
1527f911abeSJohn Baldwin 	i386_physaddr_pae_t a;
153e9ca6fe4SPeter Wemm 	off_t ofs;
154e9ca6fe4SPeter Wemm 
155e9ca6fe4SPeter Wemm 	vm = kd->vmst;
1567f911abeSJohn Baldwin 	offset = va & I386_PAGE_MASK;
157e9ca6fe4SPeter Wemm 
158e9ca6fe4SPeter Wemm 	if (va >= vm->hdr.kernbase) {
1597f911abeSJohn Baldwin 		pteindex = (va - vm->hdr.kernbase) >> I386_PAGE_SHIFT;
160c9057838SWill Andrews 		if (pteindex >= vm->hdr.ptesize / sizeof(pte))
1618fb15a24SWill Andrews 			goto invalid;
162c9057838SWill Andrews 		pte = _i386_pte_pae_get(kd, pteindex);
1637f911abeSJohn Baldwin 		if ((pte & I386_PG_V) == 0) {
1647f911abeSJohn Baldwin 			_kvm_err(kd, kd->program,
1657f911abeSJohn Baldwin 			    "_i386_minidump_vatop_pae: pte not valid");
166e9ca6fe4SPeter Wemm 			goto invalid;
167e9ca6fe4SPeter Wemm 		}
1687f911abeSJohn Baldwin 		a = pte & I386_PG_FRAME_PAE;
169c9057838SWill Andrews 		ofs = _kvm_pt_find(kd, a, I386_PAGE_SIZE);
170e9ca6fe4SPeter Wemm 		if (ofs == -1) {
1717f911abeSJohn Baldwin 			_kvm_err(kd, kd->program,
1727f911abeSJohn Baldwin 	    "_i386_minidump_vatop_pae: physical address 0x%jx not in minidump",
1737f911abeSJohn Baldwin 			    (uintmax_t)a);
174e9ca6fe4SPeter Wemm 			goto invalid;
175e9ca6fe4SPeter Wemm 		}
176e9ca6fe4SPeter Wemm 		*pa = ofs + offset;
1777f911abeSJohn Baldwin 		return (I386_PAGE_SIZE - offset);
178e9ca6fe4SPeter Wemm 	} else {
1797f911abeSJohn Baldwin 		_kvm_err(kd, kd->program,
1807f911abeSJohn Baldwin 	    "_i386_minidump_vatop_pae: virtual address 0x%jx not minidumped",
1817f911abeSJohn Baldwin 		    (uintmax_t)va);
182e9ca6fe4SPeter Wemm 		goto invalid;
183e9ca6fe4SPeter Wemm 	}
184e9ca6fe4SPeter Wemm 
185e9ca6fe4SPeter Wemm invalid:
1867f911abeSJohn Baldwin 	_kvm_err(kd, 0, "invalid address (0x%jx)", (uintmax_t)va);
187e9ca6fe4SPeter Wemm 	return (0);
188e9ca6fe4SPeter Wemm }
189e9ca6fe4SPeter Wemm 
190e9ca6fe4SPeter Wemm static int
_i386_minidump_vatop(kvm_t * kd,kvaddr_t va,off_t * pa)1917f911abeSJohn Baldwin _i386_minidump_vatop(kvm_t *kd, kvaddr_t va, off_t *pa)
192e9ca6fe4SPeter Wemm {
193e9ca6fe4SPeter Wemm 	struct vmstate *vm;
1947f911abeSJohn Baldwin 	i386_physaddr_t offset;
1957f911abeSJohn Baldwin 	i386_pte_t pte;
1967f911abeSJohn Baldwin 	kvaddr_t pteindex;
1977f911abeSJohn Baldwin 	i386_physaddr_t a;
198e9ca6fe4SPeter Wemm 	off_t ofs;
199e9ca6fe4SPeter Wemm 
200e9ca6fe4SPeter Wemm 	vm = kd->vmst;
2017f911abeSJohn Baldwin 	offset = va & I386_PAGE_MASK;
202e9ca6fe4SPeter Wemm 
203e9ca6fe4SPeter Wemm 	if (va >= vm->hdr.kernbase) {
2047f911abeSJohn Baldwin 		pteindex = (va - vm->hdr.kernbase) >> I386_PAGE_SHIFT;
205c9057838SWill Andrews 		if (pteindex >= vm->hdr.ptesize / sizeof(pte))
2068fb15a24SWill Andrews 			goto invalid;
207c9057838SWill Andrews 		pte = _i386_pte_get(kd, pteindex);
2087f911abeSJohn Baldwin 		if ((pte & I386_PG_V) == 0) {
2097f911abeSJohn Baldwin 			_kvm_err(kd, kd->program,
2107f911abeSJohn Baldwin 			    "_i386_minidump_vatop: pte not valid");
211e9ca6fe4SPeter Wemm 			goto invalid;
212e9ca6fe4SPeter Wemm 		}
2137f911abeSJohn Baldwin 		a = pte & I386_PG_FRAME;
214c9057838SWill Andrews 		ofs = _kvm_pt_find(kd, a, I386_PAGE_SIZE);
215e9ca6fe4SPeter Wemm 		if (ofs == -1) {
2167f911abeSJohn Baldwin 			_kvm_err(kd, kd->program,
2177f911abeSJohn Baldwin 	    "_i386_minidump_vatop: physical address 0x%jx not in minidump",
2187f911abeSJohn Baldwin 			    (uintmax_t)a);
219e9ca6fe4SPeter Wemm 			goto invalid;
220e9ca6fe4SPeter Wemm 		}
221e9ca6fe4SPeter Wemm 		*pa = ofs + offset;
2227f911abeSJohn Baldwin 		return (I386_PAGE_SIZE - offset);
223e9ca6fe4SPeter Wemm 	} else {
2247f911abeSJohn Baldwin 		_kvm_err(kd, kd->program,
2257f911abeSJohn Baldwin 	    "_i386_minidump_vatop: virtual address 0x%jx not minidumped",
2267f911abeSJohn Baldwin 		    (uintmax_t)va);
227e9ca6fe4SPeter Wemm 		goto invalid;
228e9ca6fe4SPeter Wemm 	}
229e9ca6fe4SPeter Wemm 
230e9ca6fe4SPeter Wemm invalid:
2317f911abeSJohn Baldwin 	_kvm_err(kd, 0, "invalid address (0x%jx)", (uintmax_t)va);
232e9ca6fe4SPeter Wemm 	return (0);
233e9ca6fe4SPeter Wemm }
234e9ca6fe4SPeter Wemm 
2357f911abeSJohn Baldwin static int
_i386_minidump_kvatop(kvm_t * kd,kvaddr_t va,off_t * pa)2367f911abeSJohn Baldwin _i386_minidump_kvatop(kvm_t *kd, kvaddr_t va, off_t *pa)
237e9ca6fe4SPeter Wemm {
238e9ca6fe4SPeter Wemm 
239e9ca6fe4SPeter Wemm 	if (ISALIVE(kd)) {
2407f911abeSJohn Baldwin 		_kvm_err(kd, 0, "_i386_minidump_kvatop called in live kernel!");
241e9ca6fe4SPeter Wemm 		return (0);
242e9ca6fe4SPeter Wemm 	}
243e9ca6fe4SPeter Wemm 	if (kd->vmst->hdr.paemode)
2447f911abeSJohn Baldwin 		return (_i386_minidump_vatop_pae(kd, va, pa));
245e9ca6fe4SPeter Wemm 	else
2467f911abeSJohn Baldwin 		return (_i386_minidump_vatop(kd, va, pa));
247e9ca6fe4SPeter Wemm }
2487f911abeSJohn Baldwin 
249c9057838SWill Andrews static vm_prot_t
_i386_entry_to_prot(uint64_t pte)250c9057838SWill Andrews _i386_entry_to_prot(uint64_t pte)
251c9057838SWill Andrews {
252c9057838SWill Andrews 	vm_prot_t prot = VM_PROT_READ;
253c9057838SWill Andrews 
254c9057838SWill Andrews 	/* Source: i386/pmap.c:pmap_protect() */
255c9057838SWill Andrews 	if (pte & I386_PG_RW)
256c9057838SWill Andrews 		prot |= VM_PROT_WRITE;
257c9057838SWill Andrews 	if ((pte & I386_PG_NX) == 0)
258c9057838SWill Andrews 		prot |= VM_PROT_EXECUTE;
259c9057838SWill Andrews 
260c9057838SWill Andrews 	return prot;
261c9057838SWill Andrews }
262c9057838SWill Andrews 
263c9057838SWill Andrews struct i386_iter {
264c9057838SWill Andrews 	kvm_t *kd;
265c9057838SWill Andrews 	u_long nptes;
266c9057838SWill Andrews 	u_long pteindex;
267c9057838SWill Andrews };
268c9057838SWill Andrews 
269c9057838SWill Andrews static void
_i386_iterator_init(struct i386_iter * it,kvm_t * kd)270c9057838SWill Andrews _i386_iterator_init(struct i386_iter *it, kvm_t *kd)
271c9057838SWill Andrews {
272c9057838SWill Andrews 	struct vmstate *vm = kd->vmst;
273c9057838SWill Andrews 
274c9057838SWill Andrews 	it->kd = kd;
275c9057838SWill Andrews 	it->pteindex = 0;
276c9057838SWill Andrews 	if (vm->hdr.paemode) {
277c9057838SWill Andrews 		it->nptes = vm->hdr.ptesize / sizeof(i386_pte_pae_t);
278c9057838SWill Andrews 	} else {
279c9057838SWill Andrews 		it->nptes = vm->hdr.ptesize / sizeof(i386_pte_t);
280c9057838SWill Andrews 	}
281c9057838SWill Andrews 	return;
282c9057838SWill Andrews }
283c9057838SWill Andrews 
284c9057838SWill Andrews static int
_i386_iterator_next(struct i386_iter * it,u_long * pa,u_long * va,u_long * dva,vm_prot_t * prot)285c9057838SWill Andrews _i386_iterator_next(struct i386_iter *it, u_long *pa, u_long *va, u_long *dva,
286c9057838SWill Andrews     vm_prot_t *prot)
287c9057838SWill Andrews {
288c9057838SWill Andrews 	struct vmstate *vm = it->kd->vmst;
289c9057838SWill Andrews 	i386_pte_t pte32;
290c9057838SWill Andrews 	i386_pte_pae_t pte64;
291c9057838SWill Andrews 	int found = 0;
292c9057838SWill Andrews 
293c9057838SWill Andrews 	*dva = 0;
2948baaf913SWill Andrews 	*pa = 0;
2958baaf913SWill Andrews 	*va = 0;
2968baaf913SWill Andrews 	*dva = 0;
2978baaf913SWill Andrews 	*prot = 0;
298c9057838SWill Andrews 	for (; it->pteindex < it->nptes && found == 0; it->pteindex++) {
299c9057838SWill Andrews 		if (vm->hdr.paemode) {
300c9057838SWill Andrews 			pte64 = _i386_pte_pae_get(it->kd, it->pteindex);
301c9057838SWill Andrews 			if ((pte64 & I386_PG_V) == 0)
302c9057838SWill Andrews 				continue;
303c9057838SWill Andrews 			*prot = _i386_entry_to_prot(pte64);
304c9057838SWill Andrews 			*pa = pte64 & I386_PG_FRAME_PAE;
305c9057838SWill Andrews 		} else {
306c9057838SWill Andrews 			pte32 = _i386_pte_get(it->kd, it->pteindex);
307c9057838SWill Andrews 			if ((pte32 & I386_PG_V) == 0)
308c9057838SWill Andrews 				continue;
309c9057838SWill Andrews 			*prot = _i386_entry_to_prot(pte32);
310c9057838SWill Andrews 			*pa = pte32 & I386_PG_FRAME;
311c9057838SWill Andrews 		}
312c9057838SWill Andrews 		*va = vm->hdr.kernbase + (it->pteindex << I386_PAGE_SHIFT);
313c9057838SWill Andrews 		found = 1;
314c9057838SWill Andrews 	}
315c9057838SWill Andrews 	return found;
316c9057838SWill Andrews }
317c9057838SWill Andrews 
318c9057838SWill Andrews static int
_i386_minidump_walk_pages(kvm_t * kd,kvm_walk_pages_cb_t * cb,void * arg)319c9057838SWill Andrews _i386_minidump_walk_pages(kvm_t *kd, kvm_walk_pages_cb_t *cb, void *arg)
320c9057838SWill Andrews {
321c9057838SWill Andrews 	struct i386_iter it;
322c9057838SWill Andrews 	u_long dva, pa, va;
323c9057838SWill Andrews 	vm_prot_t prot;
324c9057838SWill Andrews 
325c9057838SWill Andrews 	_i386_iterator_init(&it, kd);
326c9057838SWill Andrews 	while (_i386_iterator_next(&it, &pa, &va, &dva, &prot)) {
327c9057838SWill Andrews 		if (!_kvm_visit_cb(kd, cb, arg, pa, va, dva,
328c9057838SWill Andrews 		    prot, I386_PAGE_SIZE, 0)) {
329c9057838SWill Andrews 			return (0);
330c9057838SWill Andrews 		}
331c9057838SWill Andrews 	}
332c9057838SWill Andrews 	return (1);
333c9057838SWill Andrews }
334c9057838SWill Andrews 
335881b0edbSEnji Cooper static struct kvm_arch kvm_i386_minidump = {
3367f911abeSJohn Baldwin 	.ka_probe = _i386_minidump_probe,
3377f911abeSJohn Baldwin 	.ka_initvtop = _i386_minidump_initvtop,
3387f911abeSJohn Baldwin 	.ka_freevtop = _i386_minidump_freevtop,
3397f911abeSJohn Baldwin 	.ka_kvatop = _i386_minidump_kvatop,
3407f911abeSJohn Baldwin 	.ka_native = _i386_native,
341c9057838SWill Andrews 	.ka_walk_pages = _i386_minidump_walk_pages,
3427f911abeSJohn Baldwin };
3437f911abeSJohn Baldwin 
3447f911abeSJohn Baldwin KVM_ARCH(kvm_i386_minidump);
345