1 /*- 2 * Copyright (c) 1989, 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software developed by the Computer Systems 6 * Engineering group at Lawrence Berkeley Laboratory under DARPA contract 7 * BG 91-66 and contributed to Berkeley. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 */ 37 38 #include <sys/cdefs.h> 39 __FBSDID("$FreeBSD$"); 40 41 #if defined(LIBC_SCCS) && !defined(lint) 42 #if 0 43 static char sccsid[] = "@(#)kvm_hp300.c 8.1 (Berkeley) 6/4/93"; 44 #endif 45 #endif /* LIBC_SCCS and not lint */ 46 47 /* 48 * i386 machine dependent routines for kvm. Hopefully, the forthcoming 49 * vm code will one day obsolete this module. 50 */ 51 52 #include <sys/param.h> 53 #include <sys/user.h> 54 #include <sys/proc.h> 55 #include <sys/stat.h> 56 #include <sys/mman.h> 57 #include <stdlib.h> 58 #include <unistd.h> 59 #include <nlist.h> 60 #include <kvm.h> 61 62 #include <vm/vm.h> 63 #include <vm/vm_param.h> 64 65 #include <machine/elf.h> 66 67 #include <limits.h> 68 69 #include "kvm_private.h" 70 71 #ifndef btop 72 #define btop(x) (i386_btop(x)) 73 #define ptob(x) (i386_ptob(x)) 74 #endif 75 76 #define PG_FRAME_PAE (~((uint64_t)PAGE_MASK)) 77 #define PDRSHIFT_PAE 21 78 #define NPTEPG_PAE (PAGE_SIZE/sizeof(uint64_t)) 79 #define NBPDR_PAE (1<<PDRSHIFT_PAE) 80 81 struct vmstate { 82 void *mmapbase; 83 size_t mmapsize; 84 void *PTD; 85 int pae; 86 }; 87 88 /* 89 * Map the ELF headers into the process' address space. We do this in two 90 * steps: first the ELF header itself and using that information the whole 91 * set of headers. (Taken from kvm_ia64.c) 92 */ 93 static int 94 _kvm_maphdrs(kvm_t *kd, size_t sz) 95 { 96 struct vmstate *vm = kd->vmst; 97 98 /* munmap() previous mmap(). */ 99 if (vm->mmapbase != NULL) { 100 munmap(vm->mmapbase, vm->mmapsize); 101 vm->mmapbase = NULL; 102 } 103 104 vm->mmapsize = sz; 105 vm->mmapbase = mmap(NULL, sz, PROT_READ, MAP_PRIVATE, kd->pmfd, 0); 106 if (vm->mmapbase == MAP_FAILED) { 107 _kvm_err(kd, kd->program, "cannot mmap corefile"); 108 return (-1); 109 } 110 return (0); 111 } 112 113 /* 114 * Translate a physical memory address to a file-offset in the crash-dump. 115 * (Taken from kvm_ia64.c) 116 */ 117 static size_t 118 _kvm_pa2off(kvm_t *kd, uint64_t pa, off_t *ofs) 119 { 120 Elf_Ehdr *e = kd->vmst->mmapbase; 121 Elf_Phdr *p = (Elf_Phdr*)((char*)e + e->e_phoff); 122 int n = e->e_phnum; 123 124 while (n && (pa < p->p_paddr || pa >= p->p_paddr + p->p_memsz)) 125 p++, n--; 126 if (n == 0) 127 return (0); 128 *ofs = (pa - p->p_paddr) + p->p_offset; 129 return (PAGE_SIZE - ((size_t)pa & PAGE_MASK)); 130 } 131 132 void 133 _kvm_freevtop(kvm_t *kd) 134 { 135 struct vmstate *vm = kd->vmst; 136 137 if (vm->mmapbase != NULL) 138 munmap(vm->mmapbase, vm->mmapsize); 139 if (vm->PTD) 140 free(vm->PTD); 141 free(vm); 142 kd->vmst = NULL; 143 } 144 145 int 146 _kvm_initvtop(kvm_t *kd) 147 { 148 struct nlist nlist[2]; 149 u_long pa; 150 u_long kernbase; 151 char *PTD; 152 Elf_Ehdr *ehdr; 153 size_t hdrsz; 154 int i; 155 156 kd->vmst = (struct vmstate *)_kvm_malloc(kd, sizeof(*kd->vmst)); 157 if (kd->vmst == 0) { 158 _kvm_err(kd, kd->program, "cannot allocate vm"); 159 return (-1); 160 } 161 kd->vmst->PTD = 0; 162 163 if (_kvm_maphdrs(kd, sizeof(Elf_Ehdr)) == -1) 164 return (-1); 165 166 ehdr = kd->vmst->mmapbase; 167 hdrsz = ehdr->e_phoff + ehdr->e_phentsize * ehdr->e_phnum; 168 if (_kvm_maphdrs(kd, hdrsz) == -1) 169 return (-1); 170 171 nlist[0].n_name = "kernbase"; 172 nlist[1].n_name = 0; 173 174 if (kvm_nlist(kd, nlist) != 0) 175 kernbase = KERNBASE; /* for old kernels */ 176 else 177 kernbase = nlist[0].n_value; 178 179 nlist[0].n_name = "IdlePDPT"; 180 nlist[1].n_name = 0; 181 182 if (kvm_nlist(kd, nlist) == 0) { 183 uint64_t pa64; 184 185 if (kvm_read(kd, (nlist[0].n_value - kernbase), &pa, 186 sizeof(pa)) != sizeof(pa)) { 187 _kvm_err(kd, kd->program, "cannot read IdlePDPT"); 188 return (-1); 189 } 190 PTD = _kvm_malloc(kd, 4 * PAGE_SIZE); 191 for (i = 0; i < 4; i++) { 192 if (kvm_read(kd, pa + (i * sizeof(pa64)), &pa64, 193 sizeof(pa64)) != sizeof(pa64)) { 194 _kvm_err(kd, kd->program, "Cannot read PDPT"); 195 free(PTD); 196 return (-1); 197 } 198 if (kvm_read(kd, pa64 & PG_FRAME_PAE, 199 PTD + (i * PAGE_SIZE), PAGE_SIZE) != (PAGE_SIZE)) { 200 _kvm_err(kd, kd->program, "cannot read PDPT"); 201 free(PTD); 202 return (-1); 203 } 204 } 205 kd->vmst->PTD = PTD; 206 kd->vmst->pae = 1; 207 } else { 208 nlist[0].n_name = "IdlePTD"; 209 nlist[1].n_name = 0; 210 211 if (kvm_nlist(kd, nlist) != 0) { 212 _kvm_err(kd, kd->program, "bad namelist"); 213 return (-1); 214 } 215 if (kvm_read(kd, (nlist[0].n_value - kernbase), &pa, 216 sizeof(pa)) != sizeof(pa)) { 217 _kvm_err(kd, kd->program, "cannot read IdlePTD"); 218 return (-1); 219 } 220 PTD = _kvm_malloc(kd, PAGE_SIZE); 221 if (kvm_read(kd, pa, PTD, PAGE_SIZE) != PAGE_SIZE) { 222 _kvm_err(kd, kd->program, "cannot read PTD"); 223 return (-1); 224 } 225 kd->vmst->PTD = PTD; 226 return (0); 227 kd->vmst->pae = 0; 228 } 229 return (0); 230 } 231 232 static int 233 _kvm_vatop(kvm_t *kd, u_long va, off_t *pa) 234 { 235 struct vmstate *vm; 236 u_long offset; 237 u_long pte_pa; 238 u_long pde_pa; 239 pd_entry_t pde; 240 pt_entry_t pte; 241 u_long pdeindex; 242 u_long pteindex; 243 size_t s; 244 u_long a; 245 off_t ofs; 246 uint32_t *PTD; 247 248 vm = kd->vmst; 249 PTD = (uint32_t *)vm->PTD; 250 offset = va & (PAGE_SIZE - 1); 251 252 /* 253 * If we are initializing (kernel page table descriptor pointer 254 * not yet set) then return pa == va to avoid infinite recursion. 255 */ 256 if (PTD == 0) { 257 s = _kvm_pa2off(kd, va, pa); 258 if (s == 0) { 259 _kvm_err(kd, kd->program, 260 "_kvm_vatop: bootstrap data not in dump"); 261 goto invalid; 262 } else 263 return (PAGE_SIZE - offset); 264 } 265 266 pdeindex = va >> PDRSHIFT; 267 pde = PTD[pdeindex]; 268 if (((u_long)pde & PG_V) == 0) { 269 _kvm_err(kd, kd->program, "_kvm_vatop: pde not valid"); 270 goto invalid; 271 } 272 273 if ((u_long)pde & PG_PS) { 274 /* 275 * No second-level page table; ptd describes one 4MB page. 276 * (We assume that the kernel wouldn't set PG_PS without enabling 277 * it cr0). 278 */ 279 #define PAGE4M_MASK (NBPDR - 1) 280 #define PG_FRAME4M (~PAGE4M_MASK) 281 pde_pa = ((u_long)pde & PG_FRAME4M) + (va & PAGE4M_MASK); 282 s = _kvm_pa2off(kd, pde_pa, &ofs); 283 if (s < sizeof pde) { 284 _kvm_syserr(kd, kd->program, 285 "_kvm_vatop: pde_pa not found"); 286 goto invalid; 287 } 288 *pa = ofs; 289 return (NBPDR - (va & PAGE4M_MASK)); 290 } 291 292 pteindex = (va >> PAGE_SHIFT) & (NPTEPG-1); 293 pte_pa = ((u_long)pde & PG_FRAME) + (pteindex * sizeof(pde)); 294 295 s = _kvm_pa2off(kd, pte_pa, &ofs); 296 if (s < sizeof pte) { 297 _kvm_err(kd, kd->program, "_kvm_vatop: pdpe_pa not found"); 298 goto invalid; 299 } 300 301 /* XXX This has to be a physical address read, kvm_read is virtual */ 302 if (lseek(kd->pmfd, ofs, 0) == -1) { 303 _kvm_syserr(kd, kd->program, "_kvm_vatop: lseek"); 304 goto invalid; 305 } 306 if (read(kd->pmfd, &pte, sizeof pte) != sizeof pte) { 307 _kvm_syserr(kd, kd->program, "_kvm_vatop: read"); 308 goto invalid; 309 } 310 if (((u_long)pte & PG_V) == 0) { 311 _kvm_err(kd, kd->program, "_kvm_kvatop: pte not valid"); 312 goto invalid; 313 } 314 315 a = ((u_long)pte & PG_FRAME) + offset; 316 s =_kvm_pa2off(kd, a, pa); 317 if (s == 0) { 318 _kvm_err(kd, kd->program, "_kvm_vatop: address not in dump"); 319 goto invalid; 320 } else 321 return (PAGE_SIZE - offset); 322 323 invalid: 324 _kvm_err(kd, 0, "invalid address (0x%lx)", va); 325 return (0); 326 } 327 328 static int 329 _kvm_vatop_pae(kvm_t *kd, u_long va, off_t *pa) 330 { 331 struct vmstate *vm; 332 uint64_t offset; 333 uint64_t pte_pa; 334 uint64_t pde_pa; 335 uint64_t pde; 336 uint64_t pte; 337 u_long pdeindex; 338 u_long pteindex; 339 size_t s; 340 uint64_t a; 341 off_t ofs; 342 uint64_t *PTD; 343 344 vm = kd->vmst; 345 PTD = (uint64_t *)vm->PTD; 346 offset = va & (PAGE_SIZE - 1); 347 348 /* 349 * If we are initializing (kernel page table descriptor pointer 350 * not yet set) then return pa == va to avoid infinite recursion. 351 */ 352 if (PTD == 0) { 353 s = _kvm_pa2off(kd, va, pa); 354 if (s == 0) { 355 _kvm_err(kd, kd->program, 356 "_kvm_vatop_pae: bootstrap data not in dump"); 357 goto invalid; 358 } else 359 return (PAGE_SIZE - offset); 360 } 361 362 pdeindex = va >> PDRSHIFT_PAE; 363 pde = PTD[pdeindex]; 364 if (((u_long)pde & PG_V) == 0) { 365 _kvm_err(kd, kd->program, "_kvm_kvatop_pae: pde not valid"); 366 goto invalid; 367 } 368 369 if ((u_long)pde & PG_PS) { 370 /* 371 * No second-level page table; ptd describes one 2MB page. 372 * (We assume that the kernel wouldn't set PG_PS without enabling 373 * it cr0). 374 */ 375 #define PAGE2M_MASK (NBPDR_PAE - 1) 376 #define PG_FRAME2M (~PAGE2M_MASK) 377 pde_pa = ((u_long)pde & PG_FRAME2M) + (va & PAGE2M_MASK); 378 s = _kvm_pa2off(kd, pde_pa, &ofs); 379 if (s < sizeof pde) { 380 _kvm_syserr(kd, kd->program, 381 "_kvm_vatop_pae: pde_pa not found"); 382 goto invalid; 383 } 384 *pa = ofs; 385 return (NBPDR_PAE - (va & PAGE2M_MASK)); 386 } 387 388 pteindex = (va >> PAGE_SHIFT) & (NPTEPG_PAE-1); 389 pte_pa = ((uint64_t)pde & PG_FRAME_PAE) + (pteindex * sizeof(pde)); 390 391 s = _kvm_pa2off(kd, pte_pa, &ofs); 392 if (s < sizeof pte) { 393 _kvm_err(kd, kd->program, "_kvm_vatop_pae: pdpe_pa not found"); 394 goto invalid; 395 } 396 397 /* XXX This has to be a physical address read, kvm_read is virtual */ 398 if (lseek(kd->pmfd, ofs, 0) == -1) { 399 _kvm_syserr(kd, kd->program, "_kvm_vatop_pae: lseek"); 400 goto invalid; 401 } 402 if (read(kd->pmfd, &pte, sizeof pte) != sizeof pte) { 403 _kvm_syserr(kd, kd->program, "_kvm_vatop_pae: read"); 404 goto invalid; 405 } 406 if (((uint64_t)pte & PG_V) == 0) { 407 _kvm_err(kd, kd->program, "_kvm_vatop_pae: pte not valid"); 408 goto invalid; 409 } 410 411 a = ((uint64_t)pte & PG_FRAME_PAE) + offset; 412 s =_kvm_pa2off(kd, a, pa); 413 if (s == 0) { 414 _kvm_err(kd, kd->program, 415 "_kvm_vatop_pae: address not in dump"); 416 goto invalid; 417 } else 418 return (PAGE_SIZE - offset); 419 420 invalid: 421 _kvm_err(kd, 0, "invalid address (0x%lx)", va); 422 return (0); 423 } 424 425 int 426 _kvm_kvatop(kvm_t *kd, u_long va, off_t *pa) 427 { 428 429 if (ISALIVE(kd)) { 430 _kvm_err(kd, 0, "vatop called in live kernel!"); 431 return (0); 432 } 433 if (kd->vmst->pae) 434 return (_kvm_vatop_pae(kd, va, pa)); 435 else 436 return (_kvm_vatop(kd, va, pa)); 437 } 438