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/stat.h> 33 #include <sys/mman.h> 34 #include <sys/fnv_hash.h> 35 #include <strings.h> 36 #include <string.h> 37 #include <stdlib.h> 38 #include <unistd.h> 39 #include <nlist.h> 40 41 #include <cpu/pmap.h> 42 #include <vm/vm.h> 43 #include <vm/vm_param.h> 44 45 #include <machine/elf.h> 46 #include <machine/cpufunc.h> 47 #include <machine/minidump.h> 48 49 #include <limits.h> 50 51 #include "kvm.h" 52 #include "kvm_private.h" 53 54 struct hpte { 55 struct hpte *next; 56 vm_paddr_t pa; 57 int64_t off; 58 }; 59 60 #define HPT_SIZE 1024 61 62 /* minidump must be the first item! */ 63 struct vmstate { 64 int minidump; /* 1 = minidump mode */ 65 int pgtable; /* pagetable mode */ 66 void *hpt_head[HPT_SIZE]; 67 uint64_t *bitmap; 68 uint64_t *ptemap; 69 uint64_t kernbase; 70 uint64_t dmapbase; 71 uint64_t dmapend; 72 uint64_t bitmapsize; 73 }; 74 75 static void 76 hpt_insert(kvm_t *kd, vm_paddr_t pa, int64_t off) 77 { 78 struct hpte *hpte; 79 uint32_t fnv = FNV1_32_INIT; 80 81 fnv = fnv_32_buf(&pa, sizeof(pa), fnv); 82 fnv &= (HPT_SIZE - 1); 83 hpte = malloc(sizeof(*hpte)); 84 hpte->pa = pa; 85 hpte->off = off; 86 hpte->next = kd->vmst->hpt_head[fnv]; 87 kd->vmst->hpt_head[fnv] = hpte; 88 } 89 90 static int64_t 91 hpt_find(kvm_t *kd, vm_paddr_t pa) 92 { 93 struct hpte *hpte; 94 uint32_t fnv = FNV1_32_INIT; 95 96 fnv = fnv_32_buf(&pa, sizeof(pa), fnv); 97 fnv &= (HPT_SIZE - 1); 98 for (hpte = kd->vmst->hpt_head[fnv]; hpte != NULL; hpte = hpte->next) { 99 if (pa == hpte->pa) 100 return (hpte->off); 101 } 102 return (-1); 103 } 104 105 static int 106 inithash(kvm_t *kd, uint64_t *base, int len, off_t off) 107 { 108 uint64_t idx; 109 uint64_t bit, bits; 110 vm_paddr_t pa; 111 112 for (idx = 0; idx < len / sizeof(*base); idx++) { 113 bits = base[idx]; 114 while (bits) { 115 bit = bsfq(bits); 116 bits &= ~(1ul << bit); 117 pa = (idx * sizeof(*base) * NBBY + bit) * PAGE_SIZE; 118 hpt_insert(kd, pa, off); 119 off += PAGE_SIZE; 120 } 121 } 122 return (off); 123 } 124 125 void 126 _kvm_minidump_freevtop(kvm_t *kd) 127 { 128 struct vmstate *vm = kd->vmst; 129 130 if (vm->bitmap) 131 free(vm->bitmap); 132 if (vm->ptemap) 133 free(vm->ptemap); 134 free(vm); 135 kd->vmst = NULL; 136 } 137 138 static int _kvm_minidump_init_hdr1(kvm_t *kd, struct vmstate *vmst, 139 struct minidumphdr1 *hdr); 140 static int _kvm_minidump_init_hdr2(kvm_t *kd, struct vmstate *vmst, 141 struct minidumphdr2 *hdr); 142 143 int 144 _kvm_minidump_initvtop(kvm_t *kd) 145 { 146 struct vmstate *vmst; 147 int error; 148 union { 149 struct minidumphdr1 hdr1; 150 struct minidumphdr2 hdr2; 151 } u; 152 153 vmst = _kvm_malloc(kd, sizeof(*vmst)); 154 if (vmst == NULL) { 155 _kvm_err(kd, kd->program, "cannot allocate vm"); 156 return (-1); 157 } 158 kd->vmst = vmst; 159 bzero(vmst, sizeof(*vmst)); 160 vmst->minidump = 1; 161 162 if (pread(kd->pmfd, &u, sizeof(u), 0) != sizeof(u)) { 163 _kvm_err(kd, kd->program, "cannot read dump header"); 164 return (-1); 165 } 166 if (strncmp(MINIDUMP1_MAGIC, u.hdr1.magic, sizeof(u.hdr1.magic)) == 0 && 167 u.hdr1.version == MINIDUMP1_VERSION) { 168 error = _kvm_minidump_init_hdr1(kd, vmst, &u.hdr1); 169 } else 170 if (strncmp(MINIDUMP2_MAGIC, u.hdr1.magic, sizeof(u.hdr1.magic)) == 0 && 171 u.hdr2.version == MINIDUMP2_VERSION) { 172 error = _kvm_minidump_init_hdr2(kd, vmst, &u.hdr2); 173 } else { 174 _kvm_err(kd, kd->program, "not a minidump for this platform"); 175 error = -1; 176 } 177 return error; 178 } 179 180 static 181 int 182 _kvm_minidump_init_hdr1(kvm_t *kd, struct vmstate *vmst, 183 struct minidumphdr1 *hdr) 184 { 185 off_t off; 186 187 /* Skip header and msgbuf */ 188 off = PAGE_SIZE + round_page(hdr->msgbufsize); 189 190 vmst->bitmap = _kvm_malloc(kd, hdr->bitmapsize); 191 if (vmst->bitmap == NULL) { 192 _kvm_err(kd, kd->program, 193 "cannot allocate %jd bytes for bitmap", 194 (intmax_t)hdr->bitmapsize); 195 return (-1); 196 } 197 if (pread(kd->pmfd, vmst->bitmap, hdr->bitmapsize, off) != 198 hdr->bitmapsize) { 199 _kvm_err(kd, kd->program, 200 "cannot read %jd bytes for page bitmap", 201 (intmax_t)hdr->bitmapsize); 202 return (-1); 203 } 204 off += round_page(vmst->bitmapsize); 205 206 vmst->ptemap = _kvm_malloc(kd, hdr->ptesize); 207 if (vmst->ptemap == NULL) { 208 _kvm_err(kd, kd->program, 209 "cannot allocate %jd bytes for ptemap", 210 (intmax_t)hdr->ptesize); 211 return (-1); 212 } 213 if (pread(kd->pmfd, vmst->ptemap, hdr->ptesize, off) != 214 hdr->ptesize) { 215 _kvm_err(kd, kd->program, 216 "cannot read %jd bytes for ptemap", 217 (intmax_t)hdr->ptesize); 218 return (-1); 219 } 220 off += hdr->ptesize; 221 222 vmst->kernbase = hdr->kernbase; 223 vmst->dmapbase = hdr->dmapbase; 224 vmst->dmapend = hdr->dmapend; 225 vmst->bitmapsize = hdr->bitmapsize; 226 vmst->pgtable = 0; 227 228 /* build physical address hash table for sparse pages */ 229 inithash(kd, vmst->bitmap, hdr->bitmapsize, off); 230 231 return (0); 232 } 233 234 static 235 int 236 _kvm_minidump_init_hdr2(kvm_t *kd, struct vmstate *vmst, 237 struct minidumphdr2 *hdr) 238 { 239 off_t off; 240 241 /* Skip header and msgbuf */ 242 off = PAGE_SIZE + round_page(hdr->msgbufsize); 243 244 vmst->bitmap = _kvm_malloc(kd, hdr->bitmapsize); 245 if (vmst->bitmap == NULL) { 246 _kvm_err(kd, kd->program, 247 "cannot allocate %jd bytes for bitmap", 248 (intmax_t)hdr->bitmapsize); 249 return (-1); 250 } 251 if (pread(kd->pmfd, vmst->bitmap, hdr->bitmapsize, off) != 252 (intmax_t)hdr->bitmapsize) { 253 _kvm_err(kd, kd->program, 254 "cannot read %jd bytes for page bitmap", 255 (intmax_t)hdr->bitmapsize); 256 return (-1); 257 } 258 off += round_page(hdr->bitmapsize); 259 260 vmst->ptemap = _kvm_malloc(kd, hdr->ptesize); 261 if (vmst->ptemap == NULL) { 262 _kvm_err(kd, kd->program, 263 "cannot allocate %jd bytes for ptemap", 264 (intmax_t)hdr->ptesize); 265 return (-1); 266 } 267 if (pread(kd->pmfd, vmst->ptemap, hdr->ptesize, off) != 268 (intmax_t)hdr->ptesize) { 269 _kvm_err(kd, kd->program, 270 "cannot read %jd bytes for ptemap", 271 (intmax_t)hdr->ptesize); 272 return (-1); 273 } 274 off += hdr->ptesize; 275 276 vmst->kernbase = hdr->kernbase; 277 vmst->dmapbase = hdr->dmapbase; 278 vmst->bitmapsize = hdr->bitmapsize; 279 vmst->pgtable = 1; 280 281 /* build physical address hash table for sparse pages */ 282 inithash(kd, vmst->bitmap, hdr->bitmapsize, off); 283 284 return (0); 285 } 286 287 static int 288 _kvm_minidump_vatop(kvm_t *kd, u_long va, off_t *pa) 289 { 290 struct vmstate *vm; 291 u_long offset; 292 pt_entry_t pte; 293 u_long pteindex; 294 u_long a; 295 off_t ofs; 296 297 vm = kd->vmst; 298 offset = va & (PAGE_SIZE - 1); 299 va -= offset; /* put va on page boundary */ 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 a = (pte & PG_PS_FRAME) + 337 (va & (1024 * 1024 * 1024 - 1)); 338 break; 339 } 340 /* PD page */ 341 ofs = hpt_find(kd, pte & PG_FRAME); 342 if (ofs == -1) { 343 _kvm_err(kd, kd->program, 344 "_kvm_vatop: no phys page for pd"); 345 goto invalid; 346 } 347 348 /* 349 * Index of PT entry in PD 350 */ 351 pteindex = (va >> PDRSHIFT) & 511; 352 if (pread(kd->pmfd, &pte, sizeof(pte), 353 ofs + pteindex * sizeof(pte)) != sizeof(pte)) { 354 _kvm_err(kd, kd->program, 355 "_kvm_vatop: pd lookup not valid"); 356 goto invalid; 357 } 358 if ((pte & X86_PG_V) == 0) { 359 _kvm_err(kd, kd->program, 360 "_kvm_vatop: pt not valid"); 361 goto invalid; 362 } 363 if (pte & X86_PG_PS) { /* 2MB pages */ 364 a = (pte & PG_PS_FRAME) + 365 (va & (2048 * 1024 - 1)); 366 break; 367 } 368 ofs = hpt_find(kd, pte & PG_FRAME); 369 if (ofs == -1) { 370 _kvm_err(kd, kd->program, 371 "_kvm_vatop: no phys page for pt"); 372 goto invalid; 373 } 374 375 /* 376 * Index of pte entry in PT 377 */ 378 pteindex = (va >> PAGE_SHIFT) & 511; 379 if (pread(kd->pmfd, &pte, sizeof(pte), 380 ofs + pteindex * sizeof(pte)) != sizeof(pte)) { 381 _kvm_err(kd, kd->program, 382 "_kvm_vatop: pte lookup not valid"); 383 goto invalid; 384 } 385 386 /* 387 * Calculate end page 388 */ 389 a = pte & PG_FRAME; 390 break; 391 default: 392 _kvm_err(kd, kd->program, 393 "_kvm_vatop: bad pgtable mode "); 394 goto invalid; 395 } 396 ofs = hpt_find(kd, a); 397 if (ofs == -1) { 398 _kvm_err(kd, kd->program, "_kvm_vatop: physical address 0x%lx not in minidump", a); 399 goto invalid; 400 } 401 *pa = ofs + offset; 402 return (PAGE_SIZE - offset); 403 } else if (va >= vm->dmapbase && va < vm->dmapend) { 404 a = (va - vm->dmapbase) & ~PAGE_MASK; 405 ofs = hpt_find(kd, a); 406 if (ofs == -1) { 407 _kvm_err(kd, kd->program, "_kvm_vatop: direct map address 0x%lx not in minidump", va); 408 goto invalid; 409 } 410 *pa = ofs + offset; 411 return (PAGE_SIZE - offset); 412 } else { 413 _kvm_err(kd, kd->program, "_kvm_vatop: virtual address 0x%lx not minidumped", va); 414 goto invalid; 415 } 416 417 invalid: 418 _kvm_err(kd, 0, "invalid address (0x%lx)", va); 419 return (0); 420 } 421 422 int 423 _kvm_minidump_kvatop(kvm_t *kd, u_long va, off_t *pa) 424 { 425 if (kvm_ishost(kd)) { 426 _kvm_err(kd, 0, "kvm_vatop called in live kernel!"); 427 return((off_t)0); 428 } 429 430 return (_kvm_minidump_vatop(kd, va, pa)); 431 } 432