1f95a0250SRodney W. Grimes /*- 2f95a0250SRodney W. Grimes * Copyright (c) 1989, 1992, 1993 3f95a0250SRodney W. Grimes * The Regents of the University of California. All rights reserved. 4f95a0250SRodney W. Grimes * 5f95a0250SRodney W. Grimes * This code is derived from software developed by the Computer Systems 6f95a0250SRodney W. Grimes * Engineering group at Lawrence Berkeley Laboratory under DARPA contract 7f95a0250SRodney W. Grimes * BG 91-66 and contributed to Berkeley. 8f95a0250SRodney W. Grimes * 9f95a0250SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 10f95a0250SRodney W. Grimes * modification, are permitted provided that the following conditions 11f95a0250SRodney W. Grimes * are met: 12f95a0250SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 13f95a0250SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 14f95a0250SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 15f95a0250SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 16f95a0250SRodney W. Grimes * documentation and/or other materials provided with the distribution. 17f95a0250SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 18f95a0250SRodney W. Grimes * may be used to endorse or promote products derived from this software 19f95a0250SRodney W. Grimes * without specific prior written permission. 20f95a0250SRodney W. Grimes * 21f95a0250SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22f95a0250SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23f95a0250SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24f95a0250SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25f95a0250SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26f95a0250SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27f95a0250SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28f95a0250SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29f95a0250SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30f95a0250SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31f95a0250SRodney W. Grimes * SUCH DAMAGE. 32f95a0250SRodney W. Grimes */ 33f95a0250SRodney W. Grimes 34e67f5b9fSMatthew Dillon #include <sys/cdefs.h> 35e67f5b9fSMatthew Dillon __FBSDID("$FreeBSD$"); 36e67f5b9fSMatthew Dillon 37f95a0250SRodney W. Grimes #if defined(LIBC_SCCS) && !defined(lint) 38c4a7cdb3SPeter Wemm #if 0 39f95a0250SRodney W. Grimes static char sccsid[] = "@(#)kvm_hp300.c 8.1 (Berkeley) 6/4/93"; 40c4a7cdb3SPeter Wemm #endif 41f95a0250SRodney W. Grimes #endif /* LIBC_SCCS and not lint */ 42f95a0250SRodney W. Grimes 43f95a0250SRodney W. Grimes /* 4421d54b07SRodney W. Grimes * i386 machine dependent routines for kvm. Hopefully, the forthcoming 45f95a0250SRodney W. Grimes * vm code will one day obsolete this module. 46f95a0250SRodney W. Grimes */ 47f95a0250SRodney W. Grimes 48f95a0250SRodney W. Grimes #include <sys/param.h> 497f911abeSJohn Baldwin #include <sys/endian.h> 507f911abeSJohn Baldwin #include <stdint.h> 5151295a4dSJordan K. Hubbard #include <stdlib.h> 52953e4134SEd Schouten #include <string.h> 53f95a0250SRodney W. Grimes #include <unistd.h> 54f95a0250SRodney W. Grimes #include <kvm.h> 55f95a0250SRodney W. Grimes 567f911abeSJohn Baldwin #ifdef __i386__ 577f911abeSJohn Baldwin #include <machine/vmparam.h> /* For KERNBASE. */ 587f911abeSJohn Baldwin #endif 59e55a0cd8SPeter Wemm 60f95a0250SRodney W. Grimes #include <limits.h> 61f95a0250SRodney W. Grimes 62f95a0250SRodney W. Grimes #include "kvm_private.h" 637f911abeSJohn Baldwin #include "kvm_i386.h" 64f95a0250SRodney W. Grimes 65f95a0250SRodney W. Grimes struct vmstate { 66e55a0cd8SPeter Wemm void *PTD; 67e55a0cd8SPeter Wemm int pae; 687f911abeSJohn Baldwin size_t phnum; 697f911abeSJohn Baldwin GElf_Phdr *phdr; 70f95a0250SRodney W. Grimes }; 71f95a0250SRodney W. Grimes 72e55a0cd8SPeter Wemm /* 73e55a0cd8SPeter Wemm * Translate a physical memory address to a file-offset in the crash-dump. 74e55a0cd8SPeter Wemm */ 75e55a0cd8SPeter Wemm static size_t 76e55a0cd8SPeter Wemm _kvm_pa2off(kvm_t *kd, uint64_t pa, off_t *ofs) 77e55a0cd8SPeter Wemm { 787f911abeSJohn Baldwin struct vmstate *vm = kd->vmst; 797f911abeSJohn Baldwin GElf_Phdr *p; 807f911abeSJohn Baldwin size_t n; 81e55a0cd8SPeter Wemm 82d7dc9f76SHidetoshi Shimokawa if (kd->rawdump) { 83d7dc9f76SHidetoshi Shimokawa *ofs = pa; 847f911abeSJohn Baldwin return (I386_PAGE_SIZE - (pa & I386_PAGE_MASK)); 85d7dc9f76SHidetoshi Shimokawa } 86d7dc9f76SHidetoshi Shimokawa 877f911abeSJohn Baldwin p = vm->phdr; 887f911abeSJohn Baldwin n = vm->phnum; 89e55a0cd8SPeter Wemm while (n && (pa < p->p_paddr || pa >= p->p_paddr + p->p_memsz)) 90e55a0cd8SPeter Wemm p++, n--; 91e55a0cd8SPeter Wemm if (n == 0) 92e55a0cd8SPeter Wemm return (0); 93e55a0cd8SPeter Wemm *ofs = (pa - p->p_paddr) + p->p_offset; 947f911abeSJohn Baldwin return (I386_PAGE_SIZE - (pa & I386_PAGE_MASK)); 95e55a0cd8SPeter Wemm } 96e55a0cd8SPeter Wemm 977f911abeSJohn Baldwin static void 987f911abeSJohn Baldwin _i386_freevtop(kvm_t *kd) 992f85bf6eSPeter Wemm { 100e55a0cd8SPeter Wemm struct vmstate *vm = kd->vmst; 101e55a0cd8SPeter Wemm 102e55a0cd8SPeter Wemm if (vm->PTD) 103e55a0cd8SPeter Wemm free(vm->PTD); 1047f911abeSJohn Baldwin free(vm->phdr); 105e55a0cd8SPeter Wemm free(vm); 106e55a0cd8SPeter Wemm kd->vmst = NULL; 10721d54b07SRodney W. Grimes } 108f95a0250SRodney W. Grimes 1097f911abeSJohn Baldwin static int 1107f911abeSJohn Baldwin _i386_probe(kvm_t *kd) 1112f85bf6eSPeter Wemm { 1127f911abeSJohn Baldwin 1137f911abeSJohn Baldwin return (_kvm_probe_elf_kernel(kd, ELFCLASS32, EM_386) && 1147f911abeSJohn Baldwin !_kvm_is_minidump(kd)); 1157f911abeSJohn Baldwin } 1167f911abeSJohn Baldwin 1177f911abeSJohn Baldwin static int 1187f911abeSJohn Baldwin _i386_initvtop(kvm_t *kd) 1197f911abeSJohn Baldwin { 1207f911abeSJohn Baldwin struct kvm_nlist nl[2]; 1217f911abeSJohn Baldwin i386_physaddr_t pa; 1227f911abeSJohn Baldwin kvaddr_t kernbase; 123e55a0cd8SPeter Wemm char *PTD; 124e55a0cd8SPeter Wemm int i; 125e9ca6fe4SPeter Wemm 1267f911abeSJohn Baldwin kd->vmst = (struct vmstate *)_kvm_malloc(kd, sizeof(struct vmstate)); 1277f911abeSJohn Baldwin if (kd->vmst == NULL) { 12821d54b07SRodney W. Grimes _kvm_err(kd, kd->program, "cannot allocate vm"); 129f95a0250SRodney W. Grimes return (-1); 13021d54b07SRodney W. Grimes } 131e55a0cd8SPeter Wemm kd->vmst->PTD = 0; 132e55a0cd8SPeter Wemm 133d7dc9f76SHidetoshi Shimokawa if (kd->rawdump == 0) { 1347f911abeSJohn Baldwin if (_kvm_read_core_phdrs(kd, &kd->vmst->phnum, 1357f911abeSJohn Baldwin &kd->vmst->phdr) == -1) 136e55a0cd8SPeter Wemm return (-1); 137d7dc9f76SHidetoshi Shimokawa } 138f95a0250SRodney W. Grimes 139c10970ddSUlrich Spörlein nl[0].n_name = "kernbase"; 140c10970ddSUlrich Spörlein nl[1].n_name = 0; 141f85f3040SPeter Wemm 1427f911abeSJohn Baldwin if (kvm_nlist2(kd, nl) != 0) { 1437f911abeSJohn Baldwin #ifdef __i386__ 144f85f3040SPeter Wemm kernbase = KERNBASE; /* for old kernels */ 1457f911abeSJohn Baldwin #else 1467f911abeSJohn Baldwin _kvm_err(kd, kd->program, "cannot resolve kernbase"); 1477f911abeSJohn Baldwin return (-1); 1487f911abeSJohn Baldwin #endif 1497f911abeSJohn Baldwin } else 150c10970ddSUlrich Spörlein kernbase = nl[0].n_value; 151f85f3040SPeter Wemm 152c10970ddSUlrich Spörlein nl[0].n_name = "IdlePDPT"; 153c10970ddSUlrich Spörlein nl[1].n_name = 0; 154e55a0cd8SPeter Wemm 1557f911abeSJohn Baldwin if (kvm_nlist2(kd, nl) == 0) { 1567f911abeSJohn Baldwin i386_physaddr_pae_t pa64; 157e55a0cd8SPeter Wemm 1587f911abeSJohn Baldwin if (kvm_read2(kd, (nl[0].n_value - kernbase), &pa, 159e55a0cd8SPeter Wemm sizeof(pa)) != sizeof(pa)) { 160e55a0cd8SPeter Wemm _kvm_err(kd, kd->program, "cannot read IdlePDPT"); 161e55a0cd8SPeter Wemm return (-1); 162e55a0cd8SPeter Wemm } 1637f911abeSJohn Baldwin pa = le32toh(pa); 1647f911abeSJohn Baldwin PTD = _kvm_malloc(kd, 4 * I386_PAGE_SIZE); 165*fb0e1892SEnji Cooper if (PTD == NULL) { 166*fb0e1892SEnji Cooper _kvm_err(kd, kd->program, "cannot allocate PTD"); 167*fb0e1892SEnji Cooper return (-1); 168*fb0e1892SEnji Cooper } 169e55a0cd8SPeter Wemm for (i = 0; i < 4; i++) { 1707f911abeSJohn Baldwin if (kvm_read2(kd, pa + (i * sizeof(pa64)), &pa64, 171e55a0cd8SPeter Wemm sizeof(pa64)) != sizeof(pa64)) { 172e55a0cd8SPeter Wemm _kvm_err(kd, kd->program, "Cannot read PDPT"); 173e55a0cd8SPeter Wemm free(PTD); 174e55a0cd8SPeter Wemm return (-1); 175e55a0cd8SPeter Wemm } 1767f911abeSJohn Baldwin pa64 = le64toh(pa64); 1777f911abeSJohn Baldwin if (kvm_read2(kd, pa64 & I386_PG_FRAME_PAE, 1787f911abeSJohn Baldwin PTD + (i * I386_PAGE_SIZE), I386_PAGE_SIZE) != 1797f911abeSJohn Baldwin I386_PAGE_SIZE) { 180e55a0cd8SPeter Wemm _kvm_err(kd, kd->program, "cannot read PDPT"); 181e55a0cd8SPeter Wemm free(PTD); 182e55a0cd8SPeter Wemm return (-1); 183e55a0cd8SPeter Wemm } 184e55a0cd8SPeter Wemm } 185e55a0cd8SPeter Wemm kd->vmst->PTD = PTD; 186e55a0cd8SPeter Wemm kd->vmst->pae = 1; 187e55a0cd8SPeter Wemm } else { 188c10970ddSUlrich Spörlein nl[0].n_name = "IdlePTD"; 189c10970ddSUlrich Spörlein nl[1].n_name = 0; 190f95a0250SRodney W. Grimes 1917f911abeSJohn Baldwin if (kvm_nlist2(kd, nl) != 0) { 192f95a0250SRodney W. Grimes _kvm_err(kd, kd->program, "bad namelist"); 193f95a0250SRodney W. Grimes return (-1); 194f95a0250SRodney W. Grimes } 1957f911abeSJohn Baldwin if (kvm_read2(kd, (nl[0].n_value - kernbase), &pa, 196e55a0cd8SPeter Wemm sizeof(pa)) != sizeof(pa)) { 19721d54b07SRodney W. Grimes _kvm_err(kd, kd->program, "cannot read IdlePTD"); 198f95a0250SRodney W. Grimes return (-1); 199f95a0250SRodney W. Grimes } 2007f911abeSJohn Baldwin pa = le32toh(pa); 2017f911abeSJohn Baldwin PTD = _kvm_malloc(kd, I386_PAGE_SIZE); 202*fb0e1892SEnji Cooper if (PTD == NULL) { 203*fb0e1892SEnji Cooper _kvm_err(kd, kd->program, "cannot allocate PTD"); 204*fb0e1892SEnji Cooper return (-1); 205*fb0e1892SEnji Cooper } 2067f911abeSJohn Baldwin if (kvm_read2(kd, pa, PTD, I386_PAGE_SIZE) != I386_PAGE_SIZE) { 20721d54b07SRodney W. Grimes _kvm_err(kd, kd->program, "cannot read PTD"); 208f95a0250SRodney W. Grimes return (-1); 209f95a0250SRodney W. Grimes } 210e55a0cd8SPeter Wemm kd->vmst->PTD = PTD; 211e55a0cd8SPeter Wemm kd->vmst->pae = 0; 212e55a0cd8SPeter Wemm } 213f95a0250SRodney W. Grimes return (0); 214f95a0250SRodney W. Grimes } 215f95a0250SRodney W. Grimes 216f95a0250SRodney W. Grimes static int 2177f911abeSJohn Baldwin _i386_vatop(kvm_t *kd, kvaddr_t va, off_t *pa) 2182f85bf6eSPeter Wemm { 2192f85bf6eSPeter Wemm struct vmstate *vm; 2207f911abeSJohn Baldwin i386_physaddr_t offset; 2217f911abeSJohn Baldwin i386_physaddr_t pte_pa; 2227f911abeSJohn Baldwin i386_pde_t pde; 2237f911abeSJohn Baldwin i386_pte_t pte; 2247f911abeSJohn Baldwin kvaddr_t pdeindex; 2257f911abeSJohn Baldwin kvaddr_t pteindex; 226e55a0cd8SPeter Wemm size_t s; 2277f911abeSJohn Baldwin i386_physaddr_t a; 228e55a0cd8SPeter Wemm off_t ofs; 2297f911abeSJohn Baldwin i386_pde_t *PTD; 2302f85bf6eSPeter Wemm 2312f85bf6eSPeter Wemm vm = kd->vmst; 2327f911abeSJohn Baldwin PTD = (i386_pde_t *)vm->PTD; 2337f911abeSJohn Baldwin offset = va & I386_PAGE_MASK; 2342f85bf6eSPeter Wemm 2352f85bf6eSPeter Wemm /* 2362f85bf6eSPeter Wemm * If we are initializing (kernel page table descriptor pointer 2372f85bf6eSPeter Wemm * not yet set) then return pa == va to avoid infinite recursion. 2382f85bf6eSPeter Wemm */ 239*fb0e1892SEnji Cooper if (PTD == NULL) { 240e55a0cd8SPeter Wemm s = _kvm_pa2off(kd, va, pa); 241e55a0cd8SPeter Wemm if (s == 0) { 242e55a0cd8SPeter Wemm _kvm_err(kd, kd->program, 2437f911abeSJohn Baldwin "_i386_vatop: bootstrap data not in dump"); 244e55a0cd8SPeter Wemm goto invalid; 245e55a0cd8SPeter Wemm } else 2467f911abeSJohn Baldwin return (I386_PAGE_SIZE - offset); 2472f85bf6eSPeter Wemm } 2482f85bf6eSPeter Wemm 2497f911abeSJohn Baldwin pdeindex = va >> I386_PDRSHIFT; 2507f911abeSJohn Baldwin pde = le32toh(PTD[pdeindex]); 2517f911abeSJohn Baldwin if ((pde & I386_PG_V) == 0) { 2527f911abeSJohn Baldwin _kvm_err(kd, kd->program, "_i386_vatop: pde not valid"); 2532f85bf6eSPeter Wemm goto invalid; 254e55a0cd8SPeter Wemm } 2552f85bf6eSPeter Wemm 2567f911abeSJohn Baldwin if (pde & I386_PG_PS) { 2574afb0d5aSTor Egge /* 2587f911abeSJohn Baldwin * No second-level page table; ptd describes one 4MB 2597f911abeSJohn Baldwin * page. (We assume that the kernel wouldn't set 2607f911abeSJohn Baldwin * PG_PS without enabling it cr0). 2614afb0d5aSTor Egge */ 2627f911abeSJohn Baldwin offset = va & I386_PAGE_PS_MASK; 2637f911abeSJohn Baldwin a = (pde & I386_PG_PS_FRAME) + offset; 2647f911abeSJohn Baldwin s = _kvm_pa2off(kd, a, pa); 26550c3239eSJohn Baldwin if (s == 0) { 26650c3239eSJohn Baldwin _kvm_err(kd, kd->program, 2677f911abeSJohn Baldwin "_i386_vatop: 4MB page address not in dump"); 268e55a0cd8SPeter Wemm goto invalid; 269e55a0cd8SPeter Wemm } 2707f911abeSJohn Baldwin return (I386_NBPDR - offset); 2714afb0d5aSTor Egge } 2724afb0d5aSTor Egge 2737f911abeSJohn Baldwin pteindex = (va >> I386_PAGE_SHIFT) & (I386_NPTEPG - 1); 2747f911abeSJohn Baldwin pte_pa = (pde & I386_PG_FRAME) + (pteindex * sizeof(pte)); 275e55a0cd8SPeter Wemm 276e55a0cd8SPeter Wemm s = _kvm_pa2off(kd, pte_pa, &ofs); 2777f911abeSJohn Baldwin if (s < sizeof(pte)) { 2787f911abeSJohn Baldwin _kvm_err(kd, kd->program, "_i386_vatop: pte_pa not found"); 279e55a0cd8SPeter Wemm goto invalid; 280e55a0cd8SPeter Wemm } 2812f85bf6eSPeter Wemm 2822f85bf6eSPeter Wemm /* XXX This has to be a physical address read, kvm_read is virtual */ 2837f911abeSJohn Baldwin if (pread(kd->pmfd, &pte, sizeof(pte), ofs) != sizeof(pte)) { 2847f911abeSJohn Baldwin _kvm_syserr(kd, kd->program, "_i386_vatop: pread"); 2852f85bf6eSPeter Wemm goto invalid; 2862f85bf6eSPeter Wemm } 2877f911abeSJohn Baldwin pte = le32toh(pte); 2887f911abeSJohn Baldwin if ((pte & I386_PG_V) == 0) { 289e55a0cd8SPeter Wemm _kvm_err(kd, kd->program, "_kvm_kvatop: pte not valid"); 2902f85bf6eSPeter Wemm goto invalid; 291e55a0cd8SPeter Wemm } 2922f85bf6eSPeter Wemm 2937f911abeSJohn Baldwin a = (pte & I386_PG_FRAME) + offset; 294e55a0cd8SPeter Wemm s = _kvm_pa2off(kd, a, pa); 295e55a0cd8SPeter Wemm if (s == 0) { 2967f911abeSJohn Baldwin _kvm_err(kd, kd->program, "_i386_vatop: address not in dump"); 297e55a0cd8SPeter Wemm goto invalid; 298e55a0cd8SPeter Wemm } else 2997f911abeSJohn Baldwin return (I386_PAGE_SIZE - offset); 3002f85bf6eSPeter Wemm 3012f85bf6eSPeter Wemm invalid: 3027f911abeSJohn Baldwin _kvm_err(kd, 0, "invalid address (0x%jx)", (uintmax_t)va); 303e55a0cd8SPeter Wemm return (0); 304e55a0cd8SPeter Wemm } 305e55a0cd8SPeter Wemm 306e55a0cd8SPeter Wemm static int 3077f911abeSJohn Baldwin _i386_vatop_pae(kvm_t *kd, kvaddr_t va, off_t *pa) 308e55a0cd8SPeter Wemm { 309e55a0cd8SPeter Wemm struct vmstate *vm; 3107f911abeSJohn Baldwin i386_physaddr_pae_t offset; 3117f911abeSJohn Baldwin i386_physaddr_pae_t pte_pa; 3127f911abeSJohn Baldwin i386_pde_pae_t pde; 3137f911abeSJohn Baldwin i386_pte_pae_t pte; 3147f911abeSJohn Baldwin kvaddr_t pdeindex; 3157f911abeSJohn Baldwin kvaddr_t pteindex; 316e55a0cd8SPeter Wemm size_t s; 3177f911abeSJohn Baldwin i386_physaddr_pae_t a; 318e55a0cd8SPeter Wemm off_t ofs; 3197f911abeSJohn Baldwin i386_pde_pae_t *PTD; 320e55a0cd8SPeter Wemm 321e55a0cd8SPeter Wemm vm = kd->vmst; 3227f911abeSJohn Baldwin PTD = (i386_pde_pae_t *)vm->PTD; 3237f911abeSJohn Baldwin offset = va & I386_PAGE_MASK; 324e55a0cd8SPeter Wemm 325e55a0cd8SPeter Wemm /* 326e55a0cd8SPeter Wemm * If we are initializing (kernel page table descriptor pointer 327e55a0cd8SPeter Wemm * not yet set) then return pa == va to avoid infinite recursion. 328e55a0cd8SPeter Wemm */ 329*fb0e1892SEnji Cooper if (PTD == NULL) { 330e55a0cd8SPeter Wemm s = _kvm_pa2off(kd, va, pa); 331e55a0cd8SPeter Wemm if (s == 0) { 332e55a0cd8SPeter Wemm _kvm_err(kd, kd->program, 3337f911abeSJohn Baldwin "_i386_vatop_pae: bootstrap data not in dump"); 334e55a0cd8SPeter Wemm goto invalid; 335e55a0cd8SPeter Wemm } else 3367f911abeSJohn Baldwin return (I386_PAGE_SIZE - offset); 337e55a0cd8SPeter Wemm } 338e55a0cd8SPeter Wemm 3397f911abeSJohn Baldwin pdeindex = va >> I386_PDRSHIFT_PAE; 3407f911abeSJohn Baldwin pde = le64toh(PTD[pdeindex]); 3417f911abeSJohn Baldwin if ((pde & I386_PG_V) == 0) { 342e55a0cd8SPeter Wemm _kvm_err(kd, kd->program, "_kvm_kvatop_pae: pde not valid"); 343e55a0cd8SPeter Wemm goto invalid; 344e55a0cd8SPeter Wemm } 345e55a0cd8SPeter Wemm 3467f911abeSJohn Baldwin if (pde & I386_PG_PS) { 347e55a0cd8SPeter Wemm /* 3487f911abeSJohn Baldwin * No second-level page table; ptd describes one 2MB 3497f911abeSJohn Baldwin * page. (We assume that the kernel wouldn't set 3507f911abeSJohn Baldwin * PG_PS without enabling it cr0). 351e55a0cd8SPeter Wemm */ 3527f911abeSJohn Baldwin offset = va & I386_PAGE_PS_MASK_PAE; 3537f911abeSJohn Baldwin a = (pde & I386_PG_PS_FRAME_PAE) + offset; 3547f911abeSJohn Baldwin s = _kvm_pa2off(kd, a, pa); 35550c3239eSJohn Baldwin if (s == 0) { 35650c3239eSJohn Baldwin _kvm_err(kd, kd->program, 3577f911abeSJohn Baldwin "_i386_vatop: 2MB page address not in dump"); 358e55a0cd8SPeter Wemm goto invalid; 359e55a0cd8SPeter Wemm } 3607f911abeSJohn Baldwin return (I386_NBPDR_PAE - offset); 361e55a0cd8SPeter Wemm } 362e55a0cd8SPeter Wemm 3637f911abeSJohn Baldwin pteindex = (va >> I386_PAGE_SHIFT) & (I386_NPTEPG_PAE - 1); 3647f911abeSJohn Baldwin pte_pa = (pde & I386_PG_FRAME_PAE) + (pteindex * sizeof(pde)); 365e55a0cd8SPeter Wemm 366e55a0cd8SPeter Wemm s = _kvm_pa2off(kd, pte_pa, &ofs); 3677f911abeSJohn Baldwin if (s < sizeof(pte)) { 3687f911abeSJohn Baldwin _kvm_err(kd, kd->program, "_i386_vatop_pae: pdpe_pa not found"); 369e55a0cd8SPeter Wemm goto invalid; 370e55a0cd8SPeter Wemm } 371e55a0cd8SPeter Wemm 372e55a0cd8SPeter Wemm /* XXX This has to be a physical address read, kvm_read is virtual */ 3737f911abeSJohn Baldwin if (pread(kd->pmfd, &pte, sizeof(pte), ofs) != sizeof(pte)) { 3747f911abeSJohn Baldwin _kvm_syserr(kd, kd->program, "_i386_vatop_pae: read"); 375e55a0cd8SPeter Wemm goto invalid; 376e55a0cd8SPeter Wemm } 3777f911abeSJohn Baldwin pte = le64toh(pte); 3787f911abeSJohn Baldwin if ((pte & I386_PG_V) == 0) { 3797f911abeSJohn Baldwin _kvm_err(kd, kd->program, "_i386_vatop_pae: pte not valid"); 380e55a0cd8SPeter Wemm goto invalid; 381e55a0cd8SPeter Wemm } 382e55a0cd8SPeter Wemm 3837f911abeSJohn Baldwin a = (pte & I386_PG_FRAME_PAE) + offset; 384e55a0cd8SPeter Wemm s = _kvm_pa2off(kd, a, pa); 385e55a0cd8SPeter Wemm if (s == 0) { 386e55a0cd8SPeter Wemm _kvm_err(kd, kd->program, 3877f911abeSJohn Baldwin "_i386_vatop_pae: address not in dump"); 388e55a0cd8SPeter Wemm goto invalid; 389e55a0cd8SPeter Wemm } else 3907f911abeSJohn Baldwin return (I386_PAGE_SIZE - offset); 391e55a0cd8SPeter Wemm 392e55a0cd8SPeter Wemm invalid: 3937f911abeSJohn Baldwin _kvm_err(kd, 0, "invalid address (0x%jx)", (uintmax_t)va); 3942f85bf6eSPeter Wemm return (0); 395f95a0250SRodney W. Grimes } 396f95a0250SRodney W. Grimes 3977f911abeSJohn Baldwin static int 3987f911abeSJohn Baldwin _i386_kvatop(kvm_t *kd, kvaddr_t va, off_t *pa) 3992f85bf6eSPeter Wemm { 400e55a0cd8SPeter Wemm 401e55a0cd8SPeter Wemm if (ISALIVE(kd)) { 402e55a0cd8SPeter Wemm _kvm_err(kd, 0, "vatop called in live kernel!"); 403e55a0cd8SPeter Wemm return (0); 404e55a0cd8SPeter Wemm } 405e55a0cd8SPeter Wemm if (kd->vmst->pae) 4067f911abeSJohn Baldwin return (_i386_vatop_pae(kd, va, pa)); 407e55a0cd8SPeter Wemm else 4087f911abeSJohn Baldwin return (_i386_vatop(kd, va, pa)); 409f95a0250SRodney W. Grimes } 4107f911abeSJohn Baldwin 4117f911abeSJohn Baldwin int 4127f911abeSJohn Baldwin _i386_native(kvm_t *kd) 4137f911abeSJohn Baldwin { 4147f911abeSJohn Baldwin 4157f911abeSJohn Baldwin #ifdef __i386__ 4167f911abeSJohn Baldwin return (1); 4177f911abeSJohn Baldwin #else 4187f911abeSJohn Baldwin return (0); 4197f911abeSJohn Baldwin #endif 4207f911abeSJohn Baldwin } 4217f911abeSJohn Baldwin 4227f911abeSJohn Baldwin struct kvm_arch kvm_i386 = { 4237f911abeSJohn Baldwin .ka_probe = _i386_probe, 4247f911abeSJohn Baldwin .ka_initvtop = _i386_initvtop, 4257f911abeSJohn Baldwin .ka_freevtop = _i386_freevtop, 4267f911abeSJohn Baldwin .ka_kvatop = _i386_kvatop, 4277f911abeSJohn Baldwin .ka_native = _i386_native, 4287f911abeSJohn Baldwin }; 4297f911abeSJohn Baldwin 4307f911abeSJohn Baldwin KVM_ARCH(kvm_i386); 431