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> 49*7f911abeSJohn Baldwin #include <sys/endian.h> 50*7f911abeSJohn 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 56*7f911abeSJohn Baldwin #ifdef __i386__ 57*7f911abeSJohn Baldwin #include <machine/vmparam.h> /* For KERNBASE. */ 58*7f911abeSJohn Baldwin #endif 59e55a0cd8SPeter Wemm 60f95a0250SRodney W. Grimes #include <limits.h> 61f95a0250SRodney W. Grimes 62f95a0250SRodney W. Grimes #include "kvm_private.h" 63*7f911abeSJohn Baldwin #include "kvm_i386.h" 64f95a0250SRodney W. Grimes 65f95a0250SRodney W. Grimes struct vmstate { 66e55a0cd8SPeter Wemm void *PTD; 67e55a0cd8SPeter Wemm int pae; 68*7f911abeSJohn Baldwin size_t phnum; 69*7f911abeSJohn 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 { 78*7f911abeSJohn Baldwin struct vmstate *vm = kd->vmst; 79*7f911abeSJohn Baldwin GElf_Phdr *p; 80*7f911abeSJohn Baldwin size_t n; 81e55a0cd8SPeter Wemm 82d7dc9f76SHidetoshi Shimokawa if (kd->rawdump) { 83d7dc9f76SHidetoshi Shimokawa *ofs = pa; 84*7f911abeSJohn Baldwin return (I386_PAGE_SIZE - (pa & I386_PAGE_MASK)); 85d7dc9f76SHidetoshi Shimokawa } 86d7dc9f76SHidetoshi Shimokawa 87*7f911abeSJohn Baldwin p = vm->phdr; 88*7f911abeSJohn 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; 94*7f911abeSJohn Baldwin return (I386_PAGE_SIZE - (pa & I386_PAGE_MASK)); 95e55a0cd8SPeter Wemm } 96e55a0cd8SPeter Wemm 97*7f911abeSJohn Baldwin static void 98*7f911abeSJohn 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); 104*7f911abeSJohn Baldwin free(vm->phdr); 105e55a0cd8SPeter Wemm free(vm); 106e55a0cd8SPeter Wemm kd->vmst = NULL; 10721d54b07SRodney W. Grimes } 108f95a0250SRodney W. Grimes 109*7f911abeSJohn Baldwin static int 110*7f911abeSJohn Baldwin _i386_probe(kvm_t *kd) 1112f85bf6eSPeter Wemm { 112*7f911abeSJohn Baldwin 113*7f911abeSJohn Baldwin return (_kvm_probe_elf_kernel(kd, ELFCLASS32, EM_386) && 114*7f911abeSJohn Baldwin !_kvm_is_minidump(kd)); 115*7f911abeSJohn Baldwin } 116*7f911abeSJohn Baldwin 117*7f911abeSJohn Baldwin static int 118*7f911abeSJohn Baldwin _i386_initvtop(kvm_t *kd) 119*7f911abeSJohn Baldwin { 120*7f911abeSJohn Baldwin struct kvm_nlist nl[2]; 121*7f911abeSJohn Baldwin i386_physaddr_t pa; 122*7f911abeSJohn Baldwin kvaddr_t kernbase; 123e55a0cd8SPeter Wemm char *PTD; 124e55a0cd8SPeter Wemm int i; 125e9ca6fe4SPeter Wemm 126*7f911abeSJohn Baldwin kd->vmst = (struct vmstate *)_kvm_malloc(kd, sizeof(struct vmstate)); 127*7f911abeSJohn 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) { 134*7f911abeSJohn Baldwin if (_kvm_read_core_phdrs(kd, &kd->vmst->phnum, 135*7f911abeSJohn 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 142*7f911abeSJohn Baldwin if (kvm_nlist2(kd, nl) != 0) { 143*7f911abeSJohn Baldwin #ifdef __i386__ 144f85f3040SPeter Wemm kernbase = KERNBASE; /* for old kernels */ 145*7f911abeSJohn Baldwin #else 146*7f911abeSJohn Baldwin _kvm_err(kd, kd->program, "cannot resolve kernbase"); 147*7f911abeSJohn Baldwin return (-1); 148*7f911abeSJohn Baldwin #endif 149*7f911abeSJohn 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 155*7f911abeSJohn Baldwin if (kvm_nlist2(kd, nl) == 0) { 156*7f911abeSJohn Baldwin i386_physaddr_pae_t pa64; 157e55a0cd8SPeter Wemm 158*7f911abeSJohn 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 } 163*7f911abeSJohn Baldwin pa = le32toh(pa); 164*7f911abeSJohn Baldwin PTD = _kvm_malloc(kd, 4 * I386_PAGE_SIZE); 165e55a0cd8SPeter Wemm for (i = 0; i < 4; i++) { 166*7f911abeSJohn Baldwin if (kvm_read2(kd, pa + (i * sizeof(pa64)), &pa64, 167e55a0cd8SPeter Wemm sizeof(pa64)) != sizeof(pa64)) { 168e55a0cd8SPeter Wemm _kvm_err(kd, kd->program, "Cannot read PDPT"); 169e55a0cd8SPeter Wemm free(PTD); 170e55a0cd8SPeter Wemm return (-1); 171e55a0cd8SPeter Wemm } 172*7f911abeSJohn Baldwin pa64 = le64toh(pa64); 173*7f911abeSJohn Baldwin if (kvm_read2(kd, pa64 & I386_PG_FRAME_PAE, 174*7f911abeSJohn Baldwin PTD + (i * I386_PAGE_SIZE), I386_PAGE_SIZE) != 175*7f911abeSJohn Baldwin I386_PAGE_SIZE) { 176e55a0cd8SPeter Wemm _kvm_err(kd, kd->program, "cannot read PDPT"); 177e55a0cd8SPeter Wemm free(PTD); 178e55a0cd8SPeter Wemm return (-1); 179e55a0cd8SPeter Wemm } 180e55a0cd8SPeter Wemm } 181e55a0cd8SPeter Wemm kd->vmst->PTD = PTD; 182e55a0cd8SPeter Wemm kd->vmst->pae = 1; 183e55a0cd8SPeter Wemm } else { 184c10970ddSUlrich Spörlein nl[0].n_name = "IdlePTD"; 185c10970ddSUlrich Spörlein nl[1].n_name = 0; 186f95a0250SRodney W. Grimes 187*7f911abeSJohn Baldwin if (kvm_nlist2(kd, nl) != 0) { 188f95a0250SRodney W. Grimes _kvm_err(kd, kd->program, "bad namelist"); 189f95a0250SRodney W. Grimes return (-1); 190f95a0250SRodney W. Grimes } 191*7f911abeSJohn Baldwin if (kvm_read2(kd, (nl[0].n_value - kernbase), &pa, 192e55a0cd8SPeter Wemm sizeof(pa)) != sizeof(pa)) { 19321d54b07SRodney W. Grimes _kvm_err(kd, kd->program, "cannot read IdlePTD"); 194f95a0250SRodney W. Grimes return (-1); 195f95a0250SRodney W. Grimes } 196*7f911abeSJohn Baldwin pa = le32toh(pa); 197*7f911abeSJohn Baldwin PTD = _kvm_malloc(kd, I386_PAGE_SIZE); 198*7f911abeSJohn Baldwin if (kvm_read2(kd, pa, PTD, I386_PAGE_SIZE) != I386_PAGE_SIZE) { 19921d54b07SRodney W. Grimes _kvm_err(kd, kd->program, "cannot read PTD"); 200f95a0250SRodney W. Grimes return (-1); 201f95a0250SRodney W. Grimes } 202e55a0cd8SPeter Wemm kd->vmst->PTD = PTD; 203e55a0cd8SPeter Wemm kd->vmst->pae = 0; 204e55a0cd8SPeter Wemm } 205f95a0250SRodney W. Grimes return (0); 206f95a0250SRodney W. Grimes } 207f95a0250SRodney W. Grimes 208f95a0250SRodney W. Grimes static int 209*7f911abeSJohn Baldwin _i386_vatop(kvm_t *kd, kvaddr_t va, off_t *pa) 2102f85bf6eSPeter Wemm { 2112f85bf6eSPeter Wemm struct vmstate *vm; 212*7f911abeSJohn Baldwin i386_physaddr_t offset; 213*7f911abeSJohn Baldwin i386_physaddr_t pte_pa; 214*7f911abeSJohn Baldwin i386_pde_t pde; 215*7f911abeSJohn Baldwin i386_pte_t pte; 216*7f911abeSJohn Baldwin kvaddr_t pdeindex; 217*7f911abeSJohn Baldwin kvaddr_t pteindex; 218e55a0cd8SPeter Wemm size_t s; 219*7f911abeSJohn Baldwin i386_physaddr_t a; 220e55a0cd8SPeter Wemm off_t ofs; 221*7f911abeSJohn Baldwin i386_pde_t *PTD; 2222f85bf6eSPeter Wemm 2232f85bf6eSPeter Wemm vm = kd->vmst; 224*7f911abeSJohn Baldwin PTD = (i386_pde_t *)vm->PTD; 225*7f911abeSJohn Baldwin offset = va & I386_PAGE_MASK; 2262f85bf6eSPeter Wemm 2272f85bf6eSPeter Wemm /* 2282f85bf6eSPeter Wemm * If we are initializing (kernel page table descriptor pointer 2292f85bf6eSPeter Wemm * not yet set) then return pa == va to avoid infinite recursion. 2302f85bf6eSPeter Wemm */ 231e55a0cd8SPeter Wemm if (PTD == 0) { 232e55a0cd8SPeter Wemm s = _kvm_pa2off(kd, va, pa); 233e55a0cd8SPeter Wemm if (s == 0) { 234e55a0cd8SPeter Wemm _kvm_err(kd, kd->program, 235*7f911abeSJohn Baldwin "_i386_vatop: bootstrap data not in dump"); 236e55a0cd8SPeter Wemm goto invalid; 237e55a0cd8SPeter Wemm } else 238*7f911abeSJohn Baldwin return (I386_PAGE_SIZE - offset); 2392f85bf6eSPeter Wemm } 2402f85bf6eSPeter Wemm 241*7f911abeSJohn Baldwin pdeindex = va >> I386_PDRSHIFT; 242*7f911abeSJohn Baldwin pde = le32toh(PTD[pdeindex]); 243*7f911abeSJohn Baldwin if ((pde & I386_PG_V) == 0) { 244*7f911abeSJohn Baldwin _kvm_err(kd, kd->program, "_i386_vatop: pde not valid"); 2452f85bf6eSPeter Wemm goto invalid; 246e55a0cd8SPeter Wemm } 2472f85bf6eSPeter Wemm 248*7f911abeSJohn Baldwin if (pde & I386_PG_PS) { 2494afb0d5aSTor Egge /* 250*7f911abeSJohn Baldwin * No second-level page table; ptd describes one 4MB 251*7f911abeSJohn Baldwin * page. (We assume that the kernel wouldn't set 252*7f911abeSJohn Baldwin * PG_PS without enabling it cr0). 2534afb0d5aSTor Egge */ 254*7f911abeSJohn Baldwin offset = va & I386_PAGE_PS_MASK; 255*7f911abeSJohn Baldwin a = (pde & I386_PG_PS_FRAME) + offset; 256*7f911abeSJohn Baldwin s = _kvm_pa2off(kd, a, pa); 25750c3239eSJohn Baldwin if (s == 0) { 25850c3239eSJohn Baldwin _kvm_err(kd, kd->program, 259*7f911abeSJohn Baldwin "_i386_vatop: 4MB page address not in dump"); 260e55a0cd8SPeter Wemm goto invalid; 261e55a0cd8SPeter Wemm } 262*7f911abeSJohn Baldwin return (I386_NBPDR - offset); 2634afb0d5aSTor Egge } 2644afb0d5aSTor Egge 265*7f911abeSJohn Baldwin pteindex = (va >> I386_PAGE_SHIFT) & (I386_NPTEPG - 1); 266*7f911abeSJohn Baldwin pte_pa = (pde & I386_PG_FRAME) + (pteindex * sizeof(pte)); 267e55a0cd8SPeter Wemm 268e55a0cd8SPeter Wemm s = _kvm_pa2off(kd, pte_pa, &ofs); 269*7f911abeSJohn Baldwin if (s < sizeof(pte)) { 270*7f911abeSJohn Baldwin _kvm_err(kd, kd->program, "_i386_vatop: pte_pa not found"); 271e55a0cd8SPeter Wemm goto invalid; 272e55a0cd8SPeter Wemm } 2732f85bf6eSPeter Wemm 2742f85bf6eSPeter Wemm /* XXX This has to be a physical address read, kvm_read is virtual */ 275*7f911abeSJohn Baldwin if (pread(kd->pmfd, &pte, sizeof(pte), ofs) != sizeof(pte)) { 276*7f911abeSJohn Baldwin _kvm_syserr(kd, kd->program, "_i386_vatop: pread"); 2772f85bf6eSPeter Wemm goto invalid; 2782f85bf6eSPeter Wemm } 279*7f911abeSJohn Baldwin pte = le32toh(pte); 280*7f911abeSJohn Baldwin if ((pte & I386_PG_V) == 0) { 281e55a0cd8SPeter Wemm _kvm_err(kd, kd->program, "_kvm_kvatop: pte not valid"); 2822f85bf6eSPeter Wemm goto invalid; 283e55a0cd8SPeter Wemm } 2842f85bf6eSPeter Wemm 285*7f911abeSJohn Baldwin a = (pte & I386_PG_FRAME) + offset; 286e55a0cd8SPeter Wemm s = _kvm_pa2off(kd, a, pa); 287e55a0cd8SPeter Wemm if (s == 0) { 288*7f911abeSJohn Baldwin _kvm_err(kd, kd->program, "_i386_vatop: address not in dump"); 289e55a0cd8SPeter Wemm goto invalid; 290e55a0cd8SPeter Wemm } else 291*7f911abeSJohn Baldwin return (I386_PAGE_SIZE - offset); 2922f85bf6eSPeter Wemm 2932f85bf6eSPeter Wemm invalid: 294*7f911abeSJohn Baldwin _kvm_err(kd, 0, "invalid address (0x%jx)", (uintmax_t)va); 295e55a0cd8SPeter Wemm return (0); 296e55a0cd8SPeter Wemm } 297e55a0cd8SPeter Wemm 298e55a0cd8SPeter Wemm static int 299*7f911abeSJohn Baldwin _i386_vatop_pae(kvm_t *kd, kvaddr_t va, off_t *pa) 300e55a0cd8SPeter Wemm { 301e55a0cd8SPeter Wemm struct vmstate *vm; 302*7f911abeSJohn Baldwin i386_physaddr_pae_t offset; 303*7f911abeSJohn Baldwin i386_physaddr_pae_t pte_pa; 304*7f911abeSJohn Baldwin i386_pde_pae_t pde; 305*7f911abeSJohn Baldwin i386_pte_pae_t pte; 306*7f911abeSJohn Baldwin kvaddr_t pdeindex; 307*7f911abeSJohn Baldwin kvaddr_t pteindex; 308e55a0cd8SPeter Wemm size_t s; 309*7f911abeSJohn Baldwin i386_physaddr_pae_t a; 310e55a0cd8SPeter Wemm off_t ofs; 311*7f911abeSJohn Baldwin i386_pde_pae_t *PTD; 312e55a0cd8SPeter Wemm 313e55a0cd8SPeter Wemm vm = kd->vmst; 314*7f911abeSJohn Baldwin PTD = (i386_pde_pae_t *)vm->PTD; 315*7f911abeSJohn Baldwin offset = va & I386_PAGE_MASK; 316e55a0cd8SPeter Wemm 317e55a0cd8SPeter Wemm /* 318e55a0cd8SPeter Wemm * If we are initializing (kernel page table descriptor pointer 319e55a0cd8SPeter Wemm * not yet set) then return pa == va to avoid infinite recursion. 320e55a0cd8SPeter Wemm */ 321e55a0cd8SPeter Wemm if (PTD == 0) { 322e55a0cd8SPeter Wemm s = _kvm_pa2off(kd, va, pa); 323e55a0cd8SPeter Wemm if (s == 0) { 324e55a0cd8SPeter Wemm _kvm_err(kd, kd->program, 325*7f911abeSJohn Baldwin "_i386_vatop_pae: bootstrap data not in dump"); 326e55a0cd8SPeter Wemm goto invalid; 327e55a0cd8SPeter Wemm } else 328*7f911abeSJohn Baldwin return (I386_PAGE_SIZE - offset); 329e55a0cd8SPeter Wemm } 330e55a0cd8SPeter Wemm 331*7f911abeSJohn Baldwin pdeindex = va >> I386_PDRSHIFT_PAE; 332*7f911abeSJohn Baldwin pde = le64toh(PTD[pdeindex]); 333*7f911abeSJohn Baldwin if ((pde & I386_PG_V) == 0) { 334e55a0cd8SPeter Wemm _kvm_err(kd, kd->program, "_kvm_kvatop_pae: pde not valid"); 335e55a0cd8SPeter Wemm goto invalid; 336e55a0cd8SPeter Wemm } 337e55a0cd8SPeter Wemm 338*7f911abeSJohn Baldwin if (pde & I386_PG_PS) { 339e55a0cd8SPeter Wemm /* 340*7f911abeSJohn Baldwin * No second-level page table; ptd describes one 2MB 341*7f911abeSJohn Baldwin * page. (We assume that the kernel wouldn't set 342*7f911abeSJohn Baldwin * PG_PS without enabling it cr0). 343e55a0cd8SPeter Wemm */ 344*7f911abeSJohn Baldwin offset = va & I386_PAGE_PS_MASK_PAE; 345*7f911abeSJohn Baldwin a = (pde & I386_PG_PS_FRAME_PAE) + offset; 346*7f911abeSJohn Baldwin s = _kvm_pa2off(kd, a, pa); 34750c3239eSJohn Baldwin if (s == 0) { 34850c3239eSJohn Baldwin _kvm_err(kd, kd->program, 349*7f911abeSJohn Baldwin "_i386_vatop: 2MB page address not in dump"); 350e55a0cd8SPeter Wemm goto invalid; 351e55a0cd8SPeter Wemm } 352*7f911abeSJohn Baldwin return (I386_NBPDR_PAE - offset); 353e55a0cd8SPeter Wemm } 354e55a0cd8SPeter Wemm 355*7f911abeSJohn Baldwin pteindex = (va >> I386_PAGE_SHIFT) & (I386_NPTEPG_PAE - 1); 356*7f911abeSJohn Baldwin pte_pa = (pde & I386_PG_FRAME_PAE) + (pteindex * sizeof(pde)); 357e55a0cd8SPeter Wemm 358e55a0cd8SPeter Wemm s = _kvm_pa2off(kd, pte_pa, &ofs); 359*7f911abeSJohn Baldwin if (s < sizeof(pte)) { 360*7f911abeSJohn Baldwin _kvm_err(kd, kd->program, "_i386_vatop_pae: pdpe_pa not found"); 361e55a0cd8SPeter Wemm goto invalid; 362e55a0cd8SPeter Wemm } 363e55a0cd8SPeter Wemm 364e55a0cd8SPeter Wemm /* XXX This has to be a physical address read, kvm_read is virtual */ 365*7f911abeSJohn Baldwin if (pread(kd->pmfd, &pte, sizeof(pte), ofs) != sizeof(pte)) { 366*7f911abeSJohn Baldwin _kvm_syserr(kd, kd->program, "_i386_vatop_pae: read"); 367e55a0cd8SPeter Wemm goto invalid; 368e55a0cd8SPeter Wemm } 369*7f911abeSJohn Baldwin pte = le64toh(pte); 370*7f911abeSJohn Baldwin if ((pte & I386_PG_V) == 0) { 371*7f911abeSJohn Baldwin _kvm_err(kd, kd->program, "_i386_vatop_pae: pte not valid"); 372e55a0cd8SPeter Wemm goto invalid; 373e55a0cd8SPeter Wemm } 374e55a0cd8SPeter Wemm 375*7f911abeSJohn Baldwin a = (pte & I386_PG_FRAME_PAE) + offset; 376e55a0cd8SPeter Wemm s = _kvm_pa2off(kd, a, pa); 377e55a0cd8SPeter Wemm if (s == 0) { 378e55a0cd8SPeter Wemm _kvm_err(kd, kd->program, 379*7f911abeSJohn Baldwin "_i386_vatop_pae: address not in dump"); 380e55a0cd8SPeter Wemm goto invalid; 381e55a0cd8SPeter Wemm } else 382*7f911abeSJohn Baldwin return (I386_PAGE_SIZE - offset); 383e55a0cd8SPeter Wemm 384e55a0cd8SPeter Wemm invalid: 385*7f911abeSJohn Baldwin _kvm_err(kd, 0, "invalid address (0x%jx)", (uintmax_t)va); 3862f85bf6eSPeter Wemm return (0); 387f95a0250SRodney W. Grimes } 388f95a0250SRodney W. Grimes 389*7f911abeSJohn Baldwin static int 390*7f911abeSJohn Baldwin _i386_kvatop(kvm_t *kd, kvaddr_t va, off_t *pa) 3912f85bf6eSPeter Wemm { 392e55a0cd8SPeter Wemm 393e55a0cd8SPeter Wemm if (ISALIVE(kd)) { 394e55a0cd8SPeter Wemm _kvm_err(kd, 0, "vatop called in live kernel!"); 395e55a0cd8SPeter Wemm return (0); 396e55a0cd8SPeter Wemm } 397e55a0cd8SPeter Wemm if (kd->vmst->pae) 398*7f911abeSJohn Baldwin return (_i386_vatop_pae(kd, va, pa)); 399e55a0cd8SPeter Wemm else 400*7f911abeSJohn Baldwin return (_i386_vatop(kd, va, pa)); 401f95a0250SRodney W. Grimes } 402*7f911abeSJohn Baldwin 403*7f911abeSJohn Baldwin int 404*7f911abeSJohn Baldwin _i386_native(kvm_t *kd) 405*7f911abeSJohn Baldwin { 406*7f911abeSJohn Baldwin 407*7f911abeSJohn Baldwin #ifdef __i386__ 408*7f911abeSJohn Baldwin return (1); 409*7f911abeSJohn Baldwin #else 410*7f911abeSJohn Baldwin return (0); 411*7f911abeSJohn Baldwin #endif 412*7f911abeSJohn Baldwin } 413*7f911abeSJohn Baldwin 414*7f911abeSJohn Baldwin struct kvm_arch kvm_i386 = { 415*7f911abeSJohn Baldwin .ka_probe = _i386_probe, 416*7f911abeSJohn Baldwin .ka_initvtop = _i386_initvtop, 417*7f911abeSJohn Baldwin .ka_freevtop = _i386_freevtop, 418*7f911abeSJohn Baldwin .ka_kvatop = _i386_kvatop, 419*7f911abeSJohn Baldwin .ka_native = _i386_native, 420*7f911abeSJohn Baldwin }; 421*7f911abeSJohn Baldwin 422*7f911abeSJohn Baldwin KVM_ARCH(kvm_i386); 423