1b2b3ffcdSSimon Schubert /*-
2b2b3ffcdSSimon Schubert * Copyright (c) 1989, 1992, 1993
3b2b3ffcdSSimon Schubert * The Regents of the University of California. All rights reserved.
4b2b3ffcdSSimon Schubert *
5b2b3ffcdSSimon Schubert * This code is derived from software developed by the Computer Systems
6b2b3ffcdSSimon Schubert * Engineering group at Lawrence Berkeley Laboratory under DARPA contract
7b2b3ffcdSSimon Schubert * BG 91-66 and contributed to Berkeley.
8b2b3ffcdSSimon Schubert *
9b2b3ffcdSSimon Schubert * Redistribution and use in source and binary forms, with or without
10b2b3ffcdSSimon Schubert * modification, are permitted provided that the following conditions
11b2b3ffcdSSimon Schubert * are met:
12b2b3ffcdSSimon Schubert * 1. Redistributions of source code must retain the above copyright
13b2b3ffcdSSimon Schubert * notice, this list of conditions and the following disclaimer.
14b2b3ffcdSSimon Schubert * 2. Redistributions in binary form must reproduce the above copyright
15b2b3ffcdSSimon Schubert * notice, this list of conditions and the following disclaimer in the
16b2b3ffcdSSimon Schubert * documentation and/or other materials provided with the distribution.
17dc71b7abSJustin C. Sherrill * 3. Neither the name of the University nor the names of its contributors
18b2b3ffcdSSimon Schubert * may be used to endorse or promote products derived from this software
19b2b3ffcdSSimon Schubert * without specific prior written permission.
20b2b3ffcdSSimon Schubert *
21b2b3ffcdSSimon Schubert * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22b2b3ffcdSSimon Schubert * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b2b3ffcdSSimon Schubert * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b2b3ffcdSSimon Schubert * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25b2b3ffcdSSimon Schubert * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b2b3ffcdSSimon Schubert * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b2b3ffcdSSimon Schubert * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b2b3ffcdSSimon Schubert * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b2b3ffcdSSimon Schubert * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b2b3ffcdSSimon Schubert * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b2b3ffcdSSimon Schubert * SUCH DAMAGE.
32b2b3ffcdSSimon Schubert *
33b2b3ffcdSSimon Schubert * @(#)kvm_hp300.c 8.1 (Berkeley) 6/4/93
34b2b3ffcdSSimon Schubert * $FreeBSD: src/lib/libkvm/kvm_amd64.c,v 1.16 2003/04/30 21:05:33 peter Exp $
35b2b3ffcdSSimon Schubert */
36b2b3ffcdSSimon Schubert
37b2b3ffcdSSimon Schubert /*
38b2b3ffcdSSimon Schubert * x86_64 machine dependent routines for kvm. Hopefully, the forthcoming
39b2b3ffcdSSimon Schubert * vm code will one day obsolete this module.
40b2b3ffcdSSimon Schubert */
41b2b3ffcdSSimon Schubert
42b2b3ffcdSSimon Schubert #include <sys/user.h> /* MUST BE FIRST */
43b2b3ffcdSSimon Schubert #include <sys/param.h>
44b2b3ffcdSSimon Schubert #include <sys/stat.h>
4578a7b07aSAlex Hornung #include <sys/mman.h>
4678a7b07aSAlex Hornung #include <sys/elf_common.h>
47b2b3ffcdSSimon Schubert #include <stdlib.h>
4878a7b07aSAlex Hornung #include <string.h>
49b2b3ffcdSSimon Schubert #include <unistd.h>
50b2b3ffcdSSimon Schubert #include <nlist.h>
51b2b3ffcdSSimon Schubert
52*40209b5bSzrj #include <cpu/pmap.h>
53b2b3ffcdSSimon Schubert #include <vm/vm.h>
54b2b3ffcdSSimon Schubert #include <vm/vm_param.h>
55b2b3ffcdSSimon Schubert
5678a7b07aSAlex Hornung #include <machine/elf.h>
5778a7b07aSAlex Hornung
58b2b3ffcdSSimon Schubert #include <limits.h>
59b2b3ffcdSSimon Schubert
609b52fe00Szrj #include "kvm.h"
61b2b3ffcdSSimon Schubert #include "kvm_private.h"
62b2b3ffcdSSimon Schubert
63b2b3ffcdSSimon Schubert #ifndef btop
64b2b3ffcdSSimon Schubert #define btop(x) (x86_64_btop(x))
65b2b3ffcdSSimon Schubert #define ptob(x) (x86_64_ptob(x))
66b2b3ffcdSSimon Schubert #endif
67b2b3ffcdSSimon Schubert
68b2b3ffcdSSimon Schubert struct vmstate {
6978a7b07aSAlex Hornung int minidump; /* 1 = minidump mode */
7078a7b07aSAlex Hornung void *mmapbase;
7178a7b07aSAlex Hornung size_t mmapsize;
72b2b3ffcdSSimon Schubert pml4_entry_t *PML4;
73b2b3ffcdSSimon Schubert };
74b2b3ffcdSSimon Schubert
7578a7b07aSAlex Hornung /*
7678a7b07aSAlex Hornung * Map the ELF headers into the process' address space. We do this in two
7778a7b07aSAlex Hornung * steps: first the ELF header itself and using that information the whole
7878a7b07aSAlex Hornung * set of headers. (Taken from kvm_ia64.c)
7978a7b07aSAlex Hornung */
8078a7b07aSAlex Hornung static int
_kvm_maphdrs(kvm_t * kd,size_t sz)8178a7b07aSAlex Hornung _kvm_maphdrs(kvm_t *kd, size_t sz)
8278a7b07aSAlex Hornung {
8378a7b07aSAlex Hornung struct vmstate *vm = kd->vmst;
8478a7b07aSAlex Hornung
8578a7b07aSAlex Hornung if (kd->vmst->minidump) {
8678a7b07aSAlex Hornung _kvm_minidump_freevtop(kd);
8778a7b07aSAlex Hornung return (0);
8878a7b07aSAlex Hornung }
8978a7b07aSAlex Hornung
9078a7b07aSAlex Hornung /* munmap() previous mmap(). */
9178a7b07aSAlex Hornung if (vm->mmapbase != NULL) {
9278a7b07aSAlex Hornung munmap(vm->mmapbase, vm->mmapsize);
9378a7b07aSAlex Hornung vm->mmapbase = NULL;
9478a7b07aSAlex Hornung }
9578a7b07aSAlex Hornung
9678a7b07aSAlex Hornung vm->mmapsize = sz;
9778a7b07aSAlex Hornung vm->mmapbase = mmap(NULL, sz, PROT_READ, MAP_PRIVATE, kd->pmfd, 0);
9878a7b07aSAlex Hornung if (vm->mmapbase == MAP_FAILED) {
9978a7b07aSAlex Hornung _kvm_err(kd, kd->program, "cannot mmap corefile");
10078a7b07aSAlex Hornung return (-1);
10178a7b07aSAlex Hornung }
10278a7b07aSAlex Hornung return (0);
10378a7b07aSAlex Hornung }
10478a7b07aSAlex Hornung
10578a7b07aSAlex Hornung /*
10678a7b07aSAlex Hornung * Translate a physical memory address to a file-offset in the crash-dump.
10778a7b07aSAlex Hornung * (Taken from kvm_ia64.c)
10878a7b07aSAlex Hornung */
10978a7b07aSAlex Hornung static size_t
_kvm_pa2off(kvm_t * kd,uint64_t pa,off_t * ofs)11078a7b07aSAlex Hornung _kvm_pa2off(kvm_t *kd, uint64_t pa, off_t *ofs)
11178a7b07aSAlex Hornung {
11278a7b07aSAlex Hornung Elf_Ehdr *e = kd->vmst->mmapbase;
11378a7b07aSAlex Hornung Elf_Phdr *p;
11478a7b07aSAlex Hornung int n;
11578a7b07aSAlex Hornung
11678a7b07aSAlex Hornung if (kd->rawdump) {
11778a7b07aSAlex Hornung *ofs = pa;
11878a7b07aSAlex Hornung return (PAGE_SIZE - ((size_t)pa & PAGE_MASK));
11978a7b07aSAlex Hornung }
12078a7b07aSAlex Hornung
12178a7b07aSAlex Hornung p = (Elf_Phdr*)((char*)e + e->e_phoff);
12278a7b07aSAlex Hornung n = e->e_phnum;
12378a7b07aSAlex Hornung
12478a7b07aSAlex Hornung while (n && (pa < p->p_paddr || pa >= p->p_paddr + p->p_memsz))
12578a7b07aSAlex Hornung p++, n--;
12678a7b07aSAlex Hornung if (n == 0)
12778a7b07aSAlex Hornung return (0);
12878a7b07aSAlex Hornung *ofs = (pa - p->p_paddr) + p->p_offset;
12978a7b07aSAlex Hornung return (PAGE_SIZE - ((size_t)pa & PAGE_MASK));
13078a7b07aSAlex Hornung }
13178a7b07aSAlex Hornung
132b2b3ffcdSSimon Schubert void
_kvm_freevtop(kvm_t * kd)133b2b3ffcdSSimon Schubert _kvm_freevtop(kvm_t *kd)
134b2b3ffcdSSimon Schubert {
13578a7b07aSAlex Hornung struct vmstate *vm = kd->vmst;
13678a7b07aSAlex Hornung
13778a7b07aSAlex Hornung if (kd->vmst->minidump) {
13878a7b07aSAlex Hornung _kvm_minidump_freevtop(kd);
13978a7b07aSAlex Hornung return;
140b2b3ffcdSSimon Schubert }
14178a7b07aSAlex Hornung
14278a7b07aSAlex Hornung if (vm->mmapbase != NULL)
14378a7b07aSAlex Hornung munmap(vm->mmapbase, vm->mmapsize);
14478a7b07aSAlex Hornung if (vm->PML4)
14578a7b07aSAlex Hornung free(vm->PML4);
14678a7b07aSAlex Hornung free(vm);
14778a7b07aSAlex Hornung kd->vmst = NULL;
148b2b3ffcdSSimon Schubert }
149b2b3ffcdSSimon Schubert
150b2b3ffcdSSimon Schubert int
_kvm_initvtop(kvm_t * kd)151b2b3ffcdSSimon Schubert _kvm_initvtop(kvm_t *kd)
152b2b3ffcdSSimon Schubert {
153f042963aSzrj struct nlist nlists[2];
154b2b3ffcdSSimon Schubert u_long pa;
155b2b3ffcdSSimon Schubert u_long kernbase;
156b2b3ffcdSSimon Schubert pml4_entry_t *PML4;
15778a7b07aSAlex Hornung Elf_Ehdr *ehdr;
15878a7b07aSAlex Hornung size_t hdrsz;
15978a7b07aSAlex Hornung char minihdr[8];
160c0202573SMatthew Dillon struct pcb dumppcb;
161b2b3ffcdSSimon Schubert
16278a7b07aSAlex Hornung if (pread(kd->pmfd, &minihdr, 8, 0) == 8)
16378a7b07aSAlex Hornung if (memcmp(&minihdr, "minidump", 8) == 0)
16478a7b07aSAlex Hornung return (_kvm_minidump_initvtop(kd));
16578a7b07aSAlex Hornung
16678a7b07aSAlex Hornung kd->vmst = (struct vmstate *)_kvm_malloc(kd, sizeof(*kd->vmst));
16778a7b07aSAlex Hornung if (kd->vmst == 0) {
168b2b3ffcdSSimon Schubert _kvm_err(kd, kd->program, "cannot allocate vm");
169b2b3ffcdSSimon Schubert return (-1);
170b2b3ffcdSSimon Schubert }
17178a7b07aSAlex Hornung kd->vmst->PML4 = 0;
17278a7b07aSAlex Hornung
17378a7b07aSAlex Hornung if (_kvm_maphdrs(kd, sizeof(Elf_Ehdr)) == -1)
17478a7b07aSAlex Hornung return (-1);
17578a7b07aSAlex Hornung /*
176c0202573SMatthew Dillon * Check if this is indeed an ELF header. If not, assume old style
177c0202573SMatthew Dillon *dump or memory layout.
17878a7b07aSAlex Hornung */
17978a7b07aSAlex Hornung ehdr = kd->vmst->mmapbase;
18078a7b07aSAlex Hornung if (!IS_ELF(*ehdr)) {
18178a7b07aSAlex Hornung kd->rawdump = 1;
18278a7b07aSAlex Hornung munmap(kd->vmst->mmapbase, kd->vmst->mmapsize);
18378a7b07aSAlex Hornung kd->vmst->mmapbase = NULL;
18478a7b07aSAlex Hornung } else {
18578a7b07aSAlex Hornung hdrsz = ehdr->e_phoff + ehdr->e_phentsize * ehdr->e_phnum;
18678a7b07aSAlex Hornung if (_kvm_maphdrs(kd, hdrsz) == -1)
18778a7b07aSAlex Hornung return (-1);
18878a7b07aSAlex Hornung }
189b2b3ffcdSSimon Schubert
190f042963aSzrj nlists[0].n_name = "kernbase";
191f042963aSzrj nlists[1].n_name = 0;
192b2b3ffcdSSimon Schubert
193f042963aSzrj if (kvm_nlist(kd, nlists) != 0) {
194b2b3ffcdSSimon Schubert _kvm_err(kd, kd->program, "bad namelist - no kernbase");
195b2b3ffcdSSimon Schubert return (-1);
196b2b3ffcdSSimon Schubert }
197f042963aSzrj kernbase = nlists[0].n_value;
198b2b3ffcdSSimon Schubert
199f042963aSzrj nlists[0].n_name = "dumppcb";
200f042963aSzrj nlists[1].n_name = 0;
201b2b3ffcdSSimon Schubert
202f042963aSzrj if (kvm_nlist(kd, nlists) != 0) {
203c0202573SMatthew Dillon _kvm_err(kd, kd->program, "bad namelist - no dumppcb");
204b2b3ffcdSSimon Schubert return (-1);
205b2b3ffcdSSimon Schubert }
206f042963aSzrj if (kvm_read(kd, (nlists[0].n_value - kernbase), &dumppcb,
207c0202573SMatthew Dillon sizeof(dumppcb)) != sizeof(dumppcb)) {
208c0202573SMatthew Dillon _kvm_err(kd, kd->program, "cannot read dumppcb");
209b2b3ffcdSSimon Schubert return (-1);
210b2b3ffcdSSimon Schubert }
211c0202573SMatthew Dillon pa = dumppcb.pcb_cr3 & PG_FRAME;
212c0202573SMatthew Dillon
213b2b3ffcdSSimon Schubert PML4 = _kvm_malloc(kd, PAGE_SIZE);
214b2b3ffcdSSimon Schubert if (kvm_read(kd, pa, PML4, PAGE_SIZE) != PAGE_SIZE) {
215c0202573SMatthew Dillon _kvm_err(kd, kd->program, "cannot read dumppcb");
216b2b3ffcdSSimon Schubert return (-1);
217b2b3ffcdSSimon Schubert }
21878a7b07aSAlex Hornung kd->vmst->PML4 = PML4;
219b2b3ffcdSSimon Schubert return (0);
220b2b3ffcdSSimon Schubert }
221b2b3ffcdSSimon Schubert
222b2b3ffcdSSimon Schubert static int
_kvm_vatop(kvm_t * kd,u_long va,off_t * pa)22378a7b07aSAlex Hornung _kvm_vatop(kvm_t *kd, u_long va, off_t *pa)
224b2b3ffcdSSimon Schubert {
225b2b3ffcdSSimon Schubert struct vmstate *vm;
226b2b3ffcdSSimon Schubert u_long offset;
227b2b3ffcdSSimon Schubert u_long pdpe_pa;
228b2b3ffcdSSimon Schubert u_long pde_pa;
229b2b3ffcdSSimon Schubert u_long pte_pa;
230b2b3ffcdSSimon Schubert pml4_entry_t pml4e;
231b2b3ffcdSSimon Schubert pdp_entry_t pdpe;
232b2b3ffcdSSimon Schubert pd_entry_t pde;
233b2b3ffcdSSimon Schubert pt_entry_t pte;
234b2b3ffcdSSimon Schubert u_long pml4eindex;
235b2b3ffcdSSimon Schubert u_long pdpeindex;
236b2b3ffcdSSimon Schubert u_long pdeindex;
237b2b3ffcdSSimon Schubert u_long pteindex;
23878a7b07aSAlex Hornung u_long a;
23978a7b07aSAlex Hornung off_t ofs;
24078a7b07aSAlex Hornung size_t s;
241b2b3ffcdSSimon Schubert
242b2b3ffcdSSimon Schubert vm = kd->vmst;
243b2b3ffcdSSimon Schubert offset = va & (PAGE_SIZE - 1);
244b2b3ffcdSSimon Schubert
245b2b3ffcdSSimon Schubert /*
246b2b3ffcdSSimon Schubert * If we are initializing (kernel page table descriptor pointer
247b2b3ffcdSSimon Schubert * not yet set) then return pa == va to avoid infinite recursion.
248b2b3ffcdSSimon Schubert */
249678e8cc6SSascha Wildner if (vm->PML4 == NULL) {
25078a7b07aSAlex Hornung s = _kvm_pa2off(kd, va, pa);
25178a7b07aSAlex Hornung if (s == 0) {
25278a7b07aSAlex Hornung _kvm_err(kd, kd->program,
25378a7b07aSAlex Hornung "_kvm_vatop: bootstrap data not in dump");
25478a7b07aSAlex Hornung goto invalid;
25578a7b07aSAlex Hornung } else
256b2b3ffcdSSimon Schubert return (PAGE_SIZE - offset);
257b2b3ffcdSSimon Schubert }
258b2b3ffcdSSimon Schubert
259b2b3ffcdSSimon Schubert pml4eindex = (va >> PML4SHIFT) & (NPML4EPG - 1);
260b2b3ffcdSSimon Schubert pml4e = vm->PML4[pml4eindex];
261a86ce0cdSMatthew Dillon if (((u_long)pml4e & X86_PG_V) == 0) {
26278a7b07aSAlex Hornung _kvm_err(kd, kd->program, "_kvm_vatop: pml4e not valid");
263b2b3ffcdSSimon Schubert goto invalid;
26478a7b07aSAlex Hornung }
265b2b3ffcdSSimon Schubert
266b2b3ffcdSSimon Schubert pdpeindex = (va >> PDPSHIFT) & (NPDPEPG-1);
26778a7b07aSAlex Hornung pdpe_pa = ((u_long)pml4e & PG_FRAME) +
26878a7b07aSAlex Hornung (pdpeindex * sizeof(pdp_entry_t));
269b2b3ffcdSSimon Schubert
27078a7b07aSAlex Hornung s = _kvm_pa2off(kd, pdpe_pa, &ofs);
271c0202573SMatthew Dillon if (s < sizeof pdpe) {
27278a7b07aSAlex Hornung _kvm_err(kd, kd->program, "_kvm_vatop: pdpe_pa not found");
27378a7b07aSAlex Hornung goto invalid;
27478a7b07aSAlex Hornung }
27578a7b07aSAlex Hornung if (lseek(kd->pmfd, ofs, 0) == -1) {
276b2b3ffcdSSimon Schubert _kvm_syserr(kd, kd->program, "_kvm_vatop: lseek pdpe_pa");
277b2b3ffcdSSimon Schubert goto invalid;
278b2b3ffcdSSimon Schubert }
279b2b3ffcdSSimon Schubert if (read(kd->pmfd, &pdpe, sizeof pdpe) != sizeof pdpe) {
280b2b3ffcdSSimon Schubert _kvm_syserr(kd, kd->program, "_kvm_vatop: read pdpe");
281b2b3ffcdSSimon Schubert goto invalid;
282b2b3ffcdSSimon Schubert }
283a86ce0cdSMatthew Dillon if (((u_long)pdpe & X86_PG_V) == 0) {
28478a7b07aSAlex Hornung _kvm_err(kd, kd->program, "_kvm_vatop: pdpe not valid");
285b2b3ffcdSSimon Schubert goto invalid;
28678a7b07aSAlex Hornung }
287b2b3ffcdSSimon Schubert
288b2b3ffcdSSimon Schubert pdeindex = (va >> PDRSHIFT) & (NPDEPG-1);
289b2b3ffcdSSimon Schubert pde_pa = ((u_long)pdpe & PG_FRAME) + (pdeindex * sizeof(pd_entry_t));
290b2b3ffcdSSimon Schubert
29178a7b07aSAlex Hornung s = _kvm_pa2off(kd, pde_pa, &ofs);
292c0202573SMatthew Dillon if (s < sizeof pde) {
29378a7b07aSAlex Hornung _kvm_syserr(kd, kd->program, "_kvm_vatop: pde_pa not found");
29478a7b07aSAlex Hornung goto invalid;
29578a7b07aSAlex Hornung }
29678a7b07aSAlex Hornung if (lseek(kd->pmfd, ofs, 0) == -1) {
29778a7b07aSAlex Hornung _kvm_err(kd, kd->program, "_kvm_vatop: lseek pde_pa");
298b2b3ffcdSSimon Schubert goto invalid;
299b2b3ffcdSSimon Schubert }
300b2b3ffcdSSimon Schubert if (read(kd->pmfd, &pde, sizeof pde) != sizeof pde) {
301b2b3ffcdSSimon Schubert _kvm_syserr(kd, kd->program, "_kvm_vatop: read pde");
302b2b3ffcdSSimon Schubert goto invalid;
303b2b3ffcdSSimon Schubert }
304a86ce0cdSMatthew Dillon if (((u_long)pde & X86_PG_V) == 0) {
30578a7b07aSAlex Hornung _kvm_err(kd, kd->program, "_kvm_vatop: pde not valid");
306b2b3ffcdSSimon Schubert goto invalid;
30778a7b07aSAlex Hornung }
308b2b3ffcdSSimon Schubert
309a86ce0cdSMatthew Dillon if ((u_long)pde & X86_PG_PS) {
310b2b3ffcdSSimon Schubert /*
311b2b3ffcdSSimon Schubert * No final-level page table; ptd describes one 2MB page.
312b2b3ffcdSSimon Schubert */
313b2b3ffcdSSimon Schubert #define PAGE2M_MASK (NBPDR - 1)
314b2b3ffcdSSimon Schubert #define PG_FRAME2M (~PAGE2M_MASK)
31578a7b07aSAlex Hornung a = ((u_long)pde & PG_FRAME2M) + (va & PAGE2M_MASK);
31678a7b07aSAlex Hornung s = _kvm_pa2off(kd, a, pa);
31778a7b07aSAlex Hornung if (s == 0) {
31878a7b07aSAlex Hornung _kvm_err(kd, kd->program,
31978a7b07aSAlex Hornung "_kvm_vatop: 2MB page address not in dump");
32078a7b07aSAlex Hornung goto invalid;
32178a7b07aSAlex Hornung } else {
322b2b3ffcdSSimon Schubert return (NBPDR - (va & PAGE2M_MASK));
323b2b3ffcdSSimon Schubert }
32478a7b07aSAlex Hornung }
325b2b3ffcdSSimon Schubert
326b2b3ffcdSSimon Schubert pteindex = (va >> PAGE_SHIFT) & (NPTEPG-1);
327b2b3ffcdSSimon Schubert pte_pa = ((u_long)pde & PG_FRAME) + (pteindex * sizeof(pt_entry_t));
328b2b3ffcdSSimon Schubert
32978a7b07aSAlex Hornung s = _kvm_pa2off(kd, pte_pa, &ofs);
330c0202573SMatthew Dillon if (s < sizeof pte) {
33178a7b07aSAlex Hornung _kvm_err(kd, kd->program, "_kvm_vatop: pte_pa not found");
33278a7b07aSAlex Hornung goto invalid;
33378a7b07aSAlex Hornung }
33478a7b07aSAlex Hornung if (lseek(kd->pmfd, ofs, 0) == -1) {
335b2b3ffcdSSimon Schubert _kvm_syserr(kd, kd->program, "_kvm_vatop: lseek");
336b2b3ffcdSSimon Schubert goto invalid;
337b2b3ffcdSSimon Schubert }
338b2b3ffcdSSimon Schubert if (read(kd->pmfd, &pte, sizeof pte) != sizeof pte) {
339b2b3ffcdSSimon Schubert _kvm_syserr(kd, kd->program, "_kvm_vatop: read");
340b2b3ffcdSSimon Schubert goto invalid;
341b2b3ffcdSSimon Schubert }
342a86ce0cdSMatthew Dillon if (((u_long)pte & X86_PG_V) == 0) {
34378a7b07aSAlex Hornung _kvm_err(kd, kd->program, "_kvm_vatop: pte not valid");
344b2b3ffcdSSimon Schubert goto invalid;
34578a7b07aSAlex Hornung }
346b2b3ffcdSSimon Schubert
34778a7b07aSAlex Hornung a = ((u_long)pte & PG_FRAME) + offset;
34878a7b07aSAlex Hornung s = _kvm_pa2off(kd, a, pa);
34978a7b07aSAlex Hornung if (s == 0) {
35078a7b07aSAlex Hornung _kvm_err(kd, kd->program, "_kvm_vatop: address not in dump");
35178a7b07aSAlex Hornung goto invalid;
35278a7b07aSAlex Hornung } else
353b2b3ffcdSSimon Schubert return (PAGE_SIZE - offset);
354b2b3ffcdSSimon Schubert
355b2b3ffcdSSimon Schubert invalid:
35678a7b07aSAlex Hornung _kvm_err(kd, 0, "invalid address (0x%lx)", va);
357b2b3ffcdSSimon Schubert return (0);
358b2b3ffcdSSimon Schubert }
359b2b3ffcdSSimon Schubert
360b2b3ffcdSSimon Schubert int
_kvm_kvatop(kvm_t * kd,u_long va,off_t * pa)36178a7b07aSAlex Hornung _kvm_kvatop(kvm_t *kd, u_long va, off_t *pa)
362b2b3ffcdSSimon Schubert {
36378a7b07aSAlex Hornung if (kd->vmst->minidump)
36478a7b07aSAlex Hornung return (_kvm_minidump_kvatop(kd, va, pa));
36578a7b07aSAlex Hornung
36678a7b07aSAlex Hornung if (kvm_ishost(kd)) {
36778a7b07aSAlex Hornung _kvm_err(kd, 0, "kvm_vatop called in live kernel!");
36878a7b07aSAlex Hornung return((off_t)0);
36978a7b07aSAlex Hornung }
37078a7b07aSAlex Hornung
371b2b3ffcdSSimon Schubert return (_kvm_vatop(kd, va, pa));
372b2b3ffcdSSimon Schubert }
373