1 /*- 2 * Copyright (c) 2006 Peter Wemm 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 /* 27 * AMD64 machine dependent routines for kvm and minidumps. 28 */ 29 30 #include <sys/user.h> /* MUST BE FIRST */ 31 #include <sys/param.h> 32 #include <sys/proc.h> 33 #include <sys/stat.h> 34 #include <sys/mman.h> 35 #include <sys/fnv_hash.h> 36 #include <strings.h> 37 #include <string.h> 38 #include <stdlib.h> 39 #include <unistd.h> 40 #include <nlist.h> 41 42 #include <cpu/pmap.h> 43 #include <vm/vm.h> 44 #include <vm/vm_param.h> 45 46 #include <machine/elf.h> 47 #include <machine/cpufunc.h> 48 #include <machine/minidump.h> 49 50 #include <limits.h> 51 52 #include "kvm.h" 53 #include "kvm_private.h" 54 55 struct hpte { 56 struct hpte *next; 57 vm_paddr_t pa; 58 int64_t off; 59 }; 60 61 #define HPT_SIZE 1024 62 63 /* minidump must be the first item! */ 64 struct vmstate { 65 int minidump; /* 1 = minidump mode */ 66 int pgtable; /* pagetable mode */ 67 void *hpt_head[HPT_SIZE]; 68 uint64_t *bitmap; 69 uint64_t *ptemap; 70 uint64_t kernbase; 71 uint64_t dmapbase; 72 uint64_t dmapend; 73 uint64_t bitmapsize; 74 }; 75 76 static void 77 hpt_insert(kvm_t *kd, vm_paddr_t pa, int64_t off) 78 { 79 struct hpte *hpte; 80 uint32_t fnv = FNV1_32_INIT; 81 82 fnv = fnv_32_buf(&pa, sizeof(pa), fnv); 83 fnv &= (HPT_SIZE - 1); 84 hpte = malloc(sizeof(*hpte)); 85 hpte->pa = pa; 86 hpte->off = off; 87 hpte->next = kd->vmst->hpt_head[fnv]; 88 kd->vmst->hpt_head[fnv] = hpte; 89 } 90 91 static int64_t 92 hpt_find(kvm_t *kd, vm_paddr_t pa) 93 { 94 struct hpte *hpte; 95 uint32_t fnv = FNV1_32_INIT; 96 97 fnv = fnv_32_buf(&pa, sizeof(pa), fnv); 98 fnv &= (HPT_SIZE - 1); 99 for (hpte = kd->vmst->hpt_head[fnv]; hpte != NULL; hpte = hpte->next) { 100 if (pa == hpte->pa) 101 return (hpte->off); 102 } 103 return (-1); 104 } 105 106 static int 107 inithash(kvm_t *kd, uint64_t *base, int len, off_t off) 108 { 109 uint64_t idx; 110 uint64_t bit, bits; 111 vm_paddr_t pa; 112 113 for (idx = 0; idx < len / sizeof(*base); idx++) { 114 bits = base[idx]; 115 while (bits) { 116 bit = bsfq(bits); 117 bits &= ~(1ul << bit); 118 pa = (idx * sizeof(*base) * NBBY + bit) * PAGE_SIZE; 119 hpt_insert(kd, pa, off); 120 off += PAGE_SIZE; 121 } 122 } 123 return (off); 124 } 125 126 void 127 _kvm_minidump_freevtop(kvm_t *kd) 128 { 129 struct vmstate *vm = kd->vmst; 130 131 if (vm->bitmap) 132 free(vm->bitmap); 133 if (vm->ptemap) 134 free(vm->ptemap); 135 free(vm); 136 kd->vmst = NULL; 137 } 138 139 static int _kvm_minidump_init_hdr1(kvm_t *kd, struct vmstate *vmst, 140 struct minidumphdr1 *hdr); 141 static int _kvm_minidump_init_hdr2(kvm_t *kd, struct vmstate *vmst, 142 struct minidumphdr2 *hdr); 143 144 int 145 _kvm_minidump_initvtop(kvm_t *kd) 146 { 147 struct vmstate *vmst; 148 int error; 149 union { 150 struct minidumphdr1 hdr1; 151 struct minidumphdr2 hdr2; 152 } u; 153 154 vmst = _kvm_malloc(kd, sizeof(*vmst)); 155 if (vmst == NULL) { 156 _kvm_err(kd, kd->program, "cannot allocate vm"); 157 return (-1); 158 } 159 kd->vmst = vmst; 160 bzero(vmst, sizeof(*vmst)); 161 vmst->minidump = 1; 162 163 if (pread(kd->pmfd, &u, sizeof(u), 0) != sizeof(u)) { 164 _kvm_err(kd, kd->program, "cannot read dump header"); 165 return (-1); 166 } 167 if (strncmp(MINIDUMP1_MAGIC, u.hdr1.magic, sizeof(u.hdr1.magic)) == 0 && 168 u.hdr1.version == MINIDUMP1_VERSION) { 169 error = _kvm_minidump_init_hdr1(kd, vmst, &u.hdr1); 170 } else 171 if (strncmp(MINIDUMP2_MAGIC, u.hdr1.magic, sizeof(u.hdr1.magic)) == 0 && 172 u.hdr2.version == MINIDUMP2_VERSION) { 173 error = _kvm_minidump_init_hdr2(kd, vmst, &u.hdr2); 174 } else { 175 _kvm_err(kd, kd->program, "not a minidump for this platform"); 176 error = -1; 177 } 178 return error; 179 } 180 181 static 182 int 183 _kvm_minidump_init_hdr1(kvm_t *kd, struct vmstate *vmst, 184 struct minidumphdr1 *hdr) 185 { 186 off_t off; 187 188 /* Skip header and msgbuf */ 189 off = PAGE_SIZE + round_page(hdr->msgbufsize); 190 191 vmst->bitmap = _kvm_malloc(kd, hdr->bitmapsize); 192 if (vmst->bitmap == NULL) { 193 _kvm_err(kd, kd->program, 194 "cannot allocate %jd bytes for bitmap", 195 (intmax_t)hdr->bitmapsize); 196 return (-1); 197 } 198 if (pread(kd->pmfd, vmst->bitmap, hdr->bitmapsize, off) != 199 hdr->bitmapsize) { 200 _kvm_err(kd, kd->program, 201 "cannot read %jd bytes for page bitmap", 202 (intmax_t)hdr->bitmapsize); 203 return (-1); 204 } 205 off += round_page(vmst->bitmapsize); 206 207 vmst->ptemap = _kvm_malloc(kd, hdr->ptesize); 208 if (vmst->ptemap == NULL) { 209 _kvm_err(kd, kd->program, 210 "cannot allocate %jd bytes for ptemap", 211 (intmax_t)hdr->ptesize); 212 return (-1); 213 } 214 if (pread(kd->pmfd, vmst->ptemap, hdr->ptesize, off) != 215 hdr->ptesize) { 216 _kvm_err(kd, kd->program, 217 "cannot read %jd bytes for ptemap", 218 (intmax_t)hdr->ptesize); 219 return (-1); 220 } 221 off += hdr->ptesize; 222 223 vmst->kernbase = hdr->kernbase; 224 vmst->dmapbase = hdr->dmapbase; 225 vmst->dmapend = hdr->dmapend; 226 vmst->bitmapsize = hdr->bitmapsize; 227 vmst->pgtable = 0; 228 229 /* build physical address hash table for sparse pages */ 230 inithash(kd, vmst->bitmap, hdr->bitmapsize, off); 231 232 return (0); 233 } 234 235 static 236 int 237 _kvm_minidump_init_hdr2(kvm_t *kd, struct vmstate *vmst, 238 struct minidumphdr2 *hdr) 239 { 240 off_t off; 241 242 /* Skip header and msgbuf */ 243 off = PAGE_SIZE + round_page(hdr->msgbufsize); 244 245 vmst->bitmap = _kvm_malloc(kd, hdr->bitmapsize); 246 if (vmst->bitmap == NULL) { 247 _kvm_err(kd, kd->program, 248 "cannot allocate %jd bytes for bitmap", 249 (intmax_t)hdr->bitmapsize); 250 return (-1); 251 } 252 if (pread(kd->pmfd, vmst->bitmap, hdr->bitmapsize, off) != 253 (intmax_t)hdr->bitmapsize) { 254 _kvm_err(kd, kd->program, 255 "cannot read %jd bytes for page bitmap", 256 (intmax_t)hdr->bitmapsize); 257 return (-1); 258 } 259 off += round_page(hdr->bitmapsize); 260 261 vmst->ptemap = _kvm_malloc(kd, hdr->ptesize); 262 if (vmst->ptemap == NULL) { 263 _kvm_err(kd, kd->program, 264 "cannot allocate %jd bytes for ptemap", 265 (intmax_t)hdr->ptesize); 266 return (-1); 267 } 268 if (pread(kd->pmfd, vmst->ptemap, hdr->ptesize, off) != 269 (intmax_t)hdr->ptesize) { 270 _kvm_err(kd, kd->program, 271 "cannot read %jd bytes for ptemap", 272 (intmax_t)hdr->ptesize); 273 return (-1); 274 } 275 off += hdr->ptesize; 276 277 vmst->kernbase = hdr->kernbase; 278 vmst->dmapbase = hdr->dmapbase; 279 vmst->bitmapsize = hdr->bitmapsize; 280 vmst->pgtable = 1; 281 282 /* build physical address hash table for sparse pages */ 283 inithash(kd, vmst->bitmap, hdr->bitmapsize, off); 284 285 return (0); 286 } 287 288 static int 289 _kvm_minidump_vatop(kvm_t *kd, u_long va, off_t *pa) 290 { 291 struct vmstate *vm; 292 u_long offset; 293 pt_entry_t pte; 294 u_long pteindex; 295 u_long a; 296 off_t ofs; 297 298 vm = kd->vmst; 299 offset = va & (PAGE_SIZE - 1); 300 301 if (va >= vm->kernbase) { 302 switch (vm->pgtable) { 303 case 0: 304 /* 305 * Page tables are specifically dumped (old style) 306 */ 307 pteindex = (va - vm->kernbase) >> PAGE_SHIFT; 308 pte = vm->ptemap[pteindex]; 309 if (((u_long)pte & X86_PG_V) == 0) { 310 _kvm_err(kd, kd->program, 311 "_kvm_vatop: pte not valid"); 312 goto invalid; 313 } 314 a = pte & PG_FRAME; 315 break; 316 case 1: 317 /* 318 * Kernel page table pages are included in the 319 * sparse map. We only dump the contents of 320 * the PDs (zero-filling any empty entries). 321 * 322 * Index of PD entry in PDP & PDP in PML4E together. 323 * 324 * First shift by 30 (1GB) - gives us an index 325 * into PD entries. We do not PDP entries in the 326 * PML4E, so there are 512 * 512 PD entries possible. 327 */ 328 pteindex = (va >> PDPSHIFT) & (512 * 512 - 1); 329 pte = vm->ptemap[pteindex]; 330 if ((pte & X86_PG_V) == 0) { 331 _kvm_err(kd, kd->program, 332 "_kvm_vatop: pd not valid"); 333 goto invalid; 334 } 335 if (pte & X86_PG_PS) { /* 1GB pages */ 336 pte += va & (1024 * 1024 * 1024 - 1); 337 goto shortcut; 338 } 339 ofs = hpt_find(kd, pte & PG_FRAME); 340 if (ofs == -1) { 341 _kvm_err(kd, kd->program, 342 "_kvm_vatop: no phys page for pd"); 343 goto invalid; 344 } 345 346 /* 347 * Index of PT entry in PD 348 */ 349 pteindex = (va >> PDRSHIFT) & 511; 350 if (pread(kd->pmfd, &pte, sizeof(pte), 351 ofs + pteindex * sizeof(pte)) != sizeof(pte)) { 352 _kvm_err(kd, kd->program, 353 "_kvm_vatop: pd lookup not valid"); 354 goto invalid; 355 } 356 if ((pte & X86_PG_V) == 0) { 357 _kvm_err(kd, kd->program, 358 "_kvm_vatop: pt not valid"); 359 goto invalid; 360 } 361 if (pte & X86_PG_PS) { /* 2MB pages */ 362 pte += va & (2048 * 1024 - 1); 363 goto shortcut; 364 } 365 ofs = hpt_find(kd, pte & PG_FRAME); 366 if (ofs == -1) { 367 _kvm_err(kd, kd->program, 368 "_kvm_vatop: no phys page for pt"); 369 goto invalid; 370 } 371 372 /* 373 * Index of pte entry in PT 374 */ 375 pteindex = (va >> PAGE_SHIFT) & 511; 376 if (pread(kd->pmfd, &pte, sizeof(pte), 377 ofs + pteindex * sizeof(pte)) != sizeof(pte)) { 378 _kvm_err(kd, kd->program, 379 "_kvm_vatop: pte lookup not valid"); 380 goto invalid; 381 } 382 383 /* 384 * Calculate end page 385 */ 386 shortcut: 387 a = pte & PG_FRAME; 388 break; 389 default: 390 _kvm_err(kd, kd->program, 391 "_kvm_vatop: bad pgtable mode "); 392 goto invalid; 393 } 394 ofs = hpt_find(kd, a); 395 if (ofs == -1) { 396 _kvm_err(kd, kd->program, "_kvm_vatop: physical address 0x%lx not in minidump", a); 397 goto invalid; 398 } 399 *pa = ofs + offset; 400 return (PAGE_SIZE - offset); 401 } else if (va >= vm->dmapbase && va < vm->dmapend) { 402 a = (va - vm->dmapbase) & ~PAGE_MASK; 403 ofs = hpt_find(kd, a); 404 if (ofs == -1) { 405 _kvm_err(kd, kd->program, "_kvm_vatop: direct map address 0x%lx not in minidump", va); 406 goto invalid; 407 } 408 *pa = ofs + offset; 409 return (PAGE_SIZE - offset); 410 } else { 411 _kvm_err(kd, kd->program, "_kvm_vatop: virtual address 0x%lx not minidumped", va); 412 goto invalid; 413 } 414 415 invalid: 416 _kvm_err(kd, 0, "invalid address (0x%lx)", va); 417 return (0); 418 } 419 420 int 421 _kvm_minidump_kvatop(kvm_t *kd, u_long va, off_t *pa) 422 { 423 if (kvm_ishost(kd)) { 424 _kvm_err(kd, 0, "kvm_vatop called in live kernel!"); 425 return((off_t)0); 426 } 427 428 return (_kvm_minidump_vatop(kd, va, pa)); 429 } 430