1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/types.h> 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/vm.h> 32 #include <sys/proc.h> 33 #include <sys/file.h> 34 #include <sys/conf.h> 35 #include <sys/kmem.h> 36 #include <sys/mem.h> 37 #include <sys/mman.h> 38 #include <sys/vnode.h> 39 #include <sys/errno.h> 40 #include <sys/memlist.h> 41 #include <sys/dumphdr.h> 42 #include <sys/dumpadm.h> 43 #include <sys/ksyms.h> 44 #include <sys/compress.h> 45 #include <sys/stream.h> 46 #include <sys/strsun.h> 47 #include <sys/cmn_err.h> 48 #include <sys/bitmap.h> 49 #include <sys/modctl.h> 50 #include <sys/utsname.h> 51 #include <sys/systeminfo.h> 52 #include <sys/vmem.h> 53 #include <sys/log.h> 54 #include <sys/var.h> 55 #include <sys/debug.h> 56 #include <sys/sunddi.h> 57 #include <fs/fs_subr.h> 58 #include <sys/fs/snode.h> 59 #include <sys/ontrap.h> 60 #include <sys/panic.h> 61 #include <sys/dkio.h> 62 #include <sys/vtoc.h> 63 #include <sys/errorq.h> 64 #include <sys/fm/util.h> 65 #include <sys/fs/zfs.h> 66 67 #include <vm/hat.h> 68 #include <vm/as.h> 69 #include <vm/page.h> 70 #include <vm/seg.h> 71 #include <vm/seg_kmem.h> 72 73 kmutex_t dump_lock; /* lock for dump configuration */ 74 dumphdr_t *dumphdr; /* dump header */ 75 int dump_conflags = DUMP_KERNEL; /* dump configuration flags */ 76 vnode_t *dumpvp; /* dump device vnode pointer */ 77 u_offset_t dumpvp_size; /* size of dump device, in bytes */ 78 static u_offset_t dumpvp_limit; /* maximum write offset */ 79 char *dumppath; /* pathname of dump device */ 80 int dump_timeout = 120; /* timeout for dumping page during panic */ 81 int dump_timeleft; /* portion of dump_timeout remaining */ 82 int dump_ioerr; /* dump i/o error */ 83 84 #ifdef DEBUG 85 int dumpfaildebug = 1; /* enter debugger if dump fails */ 86 #else 87 int dumpfaildebug = 0; 88 #endif 89 90 static ulong_t *dump_bitmap; /* bitmap for marking pages to dump */ 91 static pgcnt_t dump_bitmapsize; /* size of bitmap */ 92 static pid_t *dump_pids; /* list of process IDs at dump time */ 93 static offset_t dumpvp_off; /* current dump device offset */ 94 static char *dump_cmap; /* VA for dump compression mapping */ 95 static char *dumpbuf_cur, *dumpbuf_start, *dumpbuf_end; 96 static char *dump_cbuf; /* compression buffer */ 97 static char *dump_uebuf; /* memory error detection buffer */ 98 static size_t dumpbuf_size; /* size of dumpbuf in bytes */ 99 static size_t dumpbuf_limit = 1UL << 23; /* 8MB */ 100 static size_t dump_iosize; /* device's best transfer size, if any */ 101 static uint64_t dumpbuf_thresh = 1ULL << 30; /* 1GB */ 102 static ulong_t dumpbuf_mult = 8; 103 104 /* 105 * The dump i/o buffer must be at least one page, at most xfer_size bytes, and 106 * should scale with physmem in between. The transfer size passed in will 107 * either represent a global default (maxphys) or the best size for the device. 108 * Once the physical memory size exceeds dumpbuf_thresh (1GB by default), we 109 * increase the percentage of physical memory that dumpbuf can consume by a 110 * factor of dumpbuf_mult (8 by default) to improve large memory performance. 111 * The size of the dumpbuf i/o buffer is limited by dumpbuf_limit (8MB by 112 * default) because the dump performance saturates beyond a certain size. 113 */ 114 static size_t 115 dumpbuf_iosize(size_t xfer_size) 116 { 117 pgcnt_t scale = physmem; 118 size_t iosize; 119 120 if (scale >= dumpbuf_thresh / PAGESIZE) { 121 scale *= dumpbuf_mult; /* increase scaling factor */ 122 iosize = MIN(xfer_size, scale) & PAGEMASK; 123 if (dumpbuf_limit && iosize > dumpbuf_limit) 124 iosize = MAX(PAGESIZE, dumpbuf_limit & PAGEMASK); 125 } else 126 iosize = MAX(PAGESIZE, MIN(xfer_size, scale) & PAGEMASK); 127 128 return (iosize); 129 } 130 131 static void 132 dumpbuf_resize(void) 133 { 134 char *old_buf = dumpbuf_start; 135 size_t old_size = dumpbuf_size; 136 char *new_buf; 137 size_t new_size; 138 139 ASSERT(MUTEX_HELD(&dump_lock)); 140 141 if ((new_size = dumpbuf_iosize(MAX(dump_iosize, maxphys))) <= old_size) 142 return; /* no need to reallocate buffer */ 143 144 new_buf = kmem_alloc(new_size, KM_SLEEP); 145 dumpbuf_size = new_size; 146 dumpbuf_start = new_buf; 147 dumpbuf_end = new_buf + new_size; 148 kmem_free(old_buf, old_size); 149 } 150 151 static void 152 dumphdr_init(void) 153 { 154 pgcnt_t npages = 0; 155 156 ASSERT(MUTEX_HELD(&dump_lock)); 157 158 if (dumphdr == NULL) { 159 dumphdr = kmem_zalloc(sizeof (dumphdr_t), KM_SLEEP); 160 dumphdr->dump_magic = DUMP_MAGIC; 161 dumphdr->dump_version = DUMP_VERSION; 162 dumphdr->dump_wordsize = DUMP_WORDSIZE; 163 dumphdr->dump_pageshift = PAGESHIFT; 164 dumphdr->dump_pagesize = PAGESIZE; 165 dumphdr->dump_utsname = utsname; 166 (void) strcpy(dumphdr->dump_platform, platform); 167 dump_cmap = vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP); 168 dumpbuf_size = dumpbuf_iosize(maxphys); 169 dumpbuf_start = kmem_alloc(dumpbuf_size, KM_SLEEP); 170 dumpbuf_end = dumpbuf_start + dumpbuf_size; 171 dump_cbuf = kmem_alloc(PAGESIZE, KM_SLEEP); /* compress buf */ 172 dump_uebuf = kmem_alloc(PAGESIZE, KM_SLEEP); /* UE buf */ 173 dump_pids = kmem_alloc(v.v_proc * sizeof (pid_t), KM_SLEEP); 174 } 175 176 npages = num_phys_pages(); 177 178 if (dump_bitmapsize != npages) { 179 void *map = kmem_alloc(BT_SIZEOFMAP(npages), KM_SLEEP); 180 kmem_free(dump_bitmap, BT_SIZEOFMAP(dump_bitmapsize)); 181 dump_bitmap = map; 182 dump_bitmapsize = npages; 183 } 184 } 185 186 /* 187 * Establish a new dump device. 188 */ 189 int 190 dumpinit(vnode_t *vp, char *name, int justchecking) 191 { 192 vnode_t *cvp; 193 vattr_t vattr; 194 vnode_t *cdev_vp; 195 int error = 0; 196 197 ASSERT(MUTEX_HELD(&dump_lock)); 198 199 dumphdr_init(); 200 201 cvp = common_specvp(vp); 202 if (cvp == dumpvp) 203 return (0); 204 205 /* 206 * Determine whether this is a plausible dump device. We want either: 207 * (1) a real device that's not mounted and has a cb_dump routine, or 208 * (2) a swapfile on some filesystem that has a vop_dump routine. 209 */ 210 if ((error = VOP_OPEN(&cvp, FREAD | FWRITE, kcred, NULL)) != 0) 211 return (error); 212 213 vattr.va_mask = AT_SIZE | AT_TYPE | AT_RDEV; 214 if ((error = VOP_GETATTR(cvp, &vattr, 0, kcred, NULL)) == 0) { 215 if (vattr.va_type == VBLK || vattr.va_type == VCHR) { 216 if (devopsp[getmajor(vattr.va_rdev)]-> 217 devo_cb_ops->cb_dump == nodev) 218 error = ENOTSUP; 219 else if (vfs_devismounted(vattr.va_rdev)) 220 error = EBUSY; 221 } else { 222 if (vn_matchopval(cvp, VOPNAME_DUMP, fs_nosys) || 223 !IS_SWAPVP(cvp)) 224 error = ENOTSUP; 225 } 226 } 227 228 if (error == 0 && vattr.va_size < 2 * DUMP_LOGSIZE + DUMP_ERPTSIZE) 229 error = ENOSPC; 230 231 if (error || justchecking) { 232 (void) VOP_CLOSE(cvp, FREAD | FWRITE, 1, (offset_t)0, 233 kcred, NULL); 234 return (error); 235 } 236 237 VN_HOLD(cvp); 238 239 if (dumpvp != NULL) 240 dumpfini(); /* unconfigure the old dump device */ 241 242 dumpvp = cvp; 243 dumpvp_size = vattr.va_size & -DUMP_OFFSET; 244 dumppath = kmem_alloc(strlen(name) + 1, KM_SLEEP); 245 (void) strcpy(dumppath, name); 246 dump_iosize = 0; 247 248 /* 249 * If the dump device is a block device, attempt to open up the 250 * corresponding character device and determine its maximum transfer 251 * size. We use this information to potentially resize dumpbuf to a 252 * larger and more optimal size for performing i/o to the dump device. 253 */ 254 if (cvp->v_type == VBLK && 255 (cdev_vp = makespecvp(VTOS(cvp)->s_dev, VCHR)) != NULL) { 256 if (VOP_OPEN(&cdev_vp, FREAD | FWRITE, kcred, NULL) == 0) { 257 size_t blk_size; 258 struct dk_cinfo dki; 259 struct vtoc vtoc; 260 261 if (VOP_IOCTL(cdev_vp, DKIOCGVTOC, (intptr_t)&vtoc, 262 FKIOCTL, kcred, NULL, NULL) == 0 && 263 vtoc.v_sectorsz != 0) 264 blk_size = vtoc.v_sectorsz; 265 else 266 blk_size = DEV_BSIZE; 267 268 if (VOP_IOCTL(cdev_vp, DKIOCINFO, (intptr_t)&dki, 269 FKIOCTL, kcred, NULL, NULL) == 0) { 270 dump_iosize = dki.dki_maxtransfer * blk_size; 271 dumpbuf_resize(); 272 } 273 /* 274 * If we are working with a zvol then call into 275 * it to dumpify itself. 276 */ 277 if (strcmp(dki.dki_dname, ZVOL_DRIVER) == 0) { 278 if ((error = VOP_IOCTL(cdev_vp, 279 DKIOCDUMPINIT, NULL, FKIOCTL, kcred, 280 NULL, NULL)) != 0) { 281 dumpfini(); 282 } 283 } 284 285 (void) VOP_CLOSE(cdev_vp, FREAD | FWRITE, 1, 0, 286 kcred, NULL); 287 } 288 289 VN_RELE(cdev_vp); 290 } 291 292 cmn_err(CE_CONT, "?dump on %s size %llu MB\n", name, dumpvp_size >> 20); 293 294 return (error); 295 } 296 297 void 298 dumpfini(void) 299 { 300 vattr_t vattr; 301 boolean_t is_zfs = B_FALSE; 302 vnode_t *cdev_vp; 303 ASSERT(MUTEX_HELD(&dump_lock)); 304 305 kmem_free(dumppath, strlen(dumppath) + 1); 306 307 /* 308 * Determine if we are using zvols for our dump device 309 */ 310 vattr.va_mask = AT_RDEV; 311 if (VOP_GETATTR(dumpvp, &vattr, 0, kcred, NULL) == 0) { 312 is_zfs = (getmajor(vattr.va_rdev) == 313 ddi_name_to_major(ZFS_DRIVER)) ? B_TRUE : B_FALSE; 314 } 315 316 /* 317 * If we have a zvol dump device then we call into zfs so 318 * that it may have a chance to cleanup. 319 */ 320 if (is_zfs && 321 (cdev_vp = makespecvp(VTOS(dumpvp)->s_dev, VCHR)) != NULL) { 322 if (VOP_OPEN(&cdev_vp, FREAD | FWRITE, kcred, NULL) == 0) { 323 (void) VOP_IOCTL(cdev_vp, DKIOCDUMPFINI, NULL, FKIOCTL, 324 kcred, NULL, NULL); 325 (void) VOP_CLOSE(cdev_vp, FREAD | FWRITE, 1, 0, 326 kcred, NULL); 327 } 328 VN_RELE(cdev_vp); 329 } 330 331 (void) VOP_CLOSE(dumpvp, FREAD | FWRITE, 1, (offset_t)0, kcred, NULL); 332 333 VN_RELE(dumpvp); 334 335 dumpvp = NULL; 336 dumpvp_size = 0; 337 dumppath = NULL; 338 } 339 340 static pfn_t 341 dump_bitnum_to_pfn(pgcnt_t bitnum) 342 { 343 struct memlist *mp; 344 345 for (mp = phys_install; mp != NULL; mp = mp->next) { 346 if (bitnum < (mp->size >> PAGESHIFT)) 347 return ((mp->address >> PAGESHIFT) + bitnum); 348 bitnum -= mp->size >> PAGESHIFT; 349 } 350 return (PFN_INVALID); 351 } 352 353 static pgcnt_t 354 dump_pfn_to_bitnum(pfn_t pfn) 355 { 356 struct memlist *mp; 357 pgcnt_t bitnum = 0; 358 359 for (mp = phys_install; mp != NULL; mp = mp->next) { 360 if (pfn >= (mp->address >> PAGESHIFT) && 361 pfn < ((mp->address + mp->size) >> PAGESHIFT)) 362 return (bitnum + pfn - (mp->address >> PAGESHIFT)); 363 bitnum += mp->size >> PAGESHIFT; 364 } 365 return ((pgcnt_t)-1); 366 } 367 368 static offset_t 369 dumpvp_flush(void) 370 { 371 size_t size = P2ROUNDUP(dumpbuf_cur - dumpbuf_start, PAGESIZE); 372 int err; 373 374 if (dumpvp_off + size > dumpvp_limit) { 375 dump_ioerr = ENOSPC; 376 } else if (size != 0) { 377 if (panicstr) 378 err = VOP_DUMP(dumpvp, dumpbuf_start, 379 lbtodb(dumpvp_off), btod(size), NULL); 380 else 381 err = vn_rdwr(UIO_WRITE, dumpvp, dumpbuf_start, size, 382 dumpvp_off, UIO_SYSSPACE, 0, dumpvp_limit, 383 kcred, 0); 384 if (err && dump_ioerr == 0) 385 dump_ioerr = err; 386 } 387 dumpvp_off += size; 388 dumpbuf_cur = dumpbuf_start; 389 dump_timeleft = dump_timeout; 390 return (dumpvp_off); 391 } 392 393 void 394 dumpvp_write(const void *va, size_t size) 395 { 396 while (size != 0) { 397 size_t len = MIN(size, dumpbuf_end - dumpbuf_cur); 398 if (len == 0) { 399 (void) dumpvp_flush(); 400 } else { 401 bcopy(va, dumpbuf_cur, len); 402 va = (char *)va + len; 403 dumpbuf_cur += len; 404 size -= len; 405 } 406 } 407 } 408 409 /*ARGSUSED*/ 410 static void 411 dumpvp_ksyms_write(const void *src, void *dst, size_t size) 412 { 413 dumpvp_write(src, size); 414 } 415 416 /* 417 * Mark 'pfn' in the bitmap and dump its translation table entry. 418 */ 419 void 420 dump_addpage(struct as *as, void *va, pfn_t pfn) 421 { 422 mem_vtop_t mem_vtop; 423 pgcnt_t bitnum; 424 425 if ((bitnum = dump_pfn_to_bitnum(pfn)) != (pgcnt_t)-1) { 426 if (!BT_TEST(dump_bitmap, bitnum)) { 427 dumphdr->dump_npages++; 428 BT_SET(dump_bitmap, bitnum); 429 } 430 dumphdr->dump_nvtop++; 431 mem_vtop.m_as = as; 432 mem_vtop.m_va = va; 433 mem_vtop.m_pfn = pfn; 434 dumpvp_write(&mem_vtop, sizeof (mem_vtop_t)); 435 } 436 dump_timeleft = dump_timeout; 437 } 438 439 /* 440 * Mark 'pfn' in the bitmap 441 */ 442 void 443 dump_page(pfn_t pfn) 444 { 445 pgcnt_t bitnum; 446 447 if ((bitnum = dump_pfn_to_bitnum(pfn)) != (pgcnt_t)-1) { 448 if (!BT_TEST(dump_bitmap, bitnum)) { 449 dumphdr->dump_npages++; 450 BT_SET(dump_bitmap, bitnum); 451 } 452 } 453 dump_timeleft = dump_timeout; 454 } 455 456 /* 457 * Dump the <as, va, pfn> information for a given address space. 458 * SEGOP_DUMP() will call dump_addpage() for each page in the segment. 459 */ 460 static void 461 dump_as(struct as *as) 462 { 463 struct seg *seg; 464 465 AS_LOCK_ENTER(as, &as->a_lock, RW_READER); 466 for (seg = AS_SEGFIRST(as); seg; seg = AS_SEGNEXT(as, seg)) { 467 if (seg->s_as != as) 468 break; 469 if (seg->s_ops == NULL) 470 continue; 471 SEGOP_DUMP(seg); 472 } 473 AS_LOCK_EXIT(as, &as->a_lock); 474 475 if (seg != NULL) 476 cmn_err(CE_WARN, "invalid segment %p in address space %p", 477 (void *)seg, (void *)as); 478 } 479 480 static int 481 dump_process(pid_t pid) 482 { 483 proc_t *p = sprlock(pid); 484 485 if (p == NULL) 486 return (-1); 487 if (p->p_as != &kas) { 488 mutex_exit(&p->p_lock); 489 dump_as(p->p_as); 490 mutex_enter(&p->p_lock); 491 } 492 493 sprunlock(p); 494 495 return (0); 496 } 497 498 void 499 dump_ereports(void) 500 { 501 u_offset_t dumpvp_start; 502 erpt_dump_t ed; 503 504 if (dumpvp == NULL || dumphdr == NULL) 505 return; 506 507 dumpbuf_cur = dumpbuf_start; 508 dumpvp_limit = dumpvp_size - (DUMP_OFFSET + DUMP_LOGSIZE); 509 dumpvp_start = dumpvp_limit - DUMP_ERPTSIZE; 510 dumpvp_off = dumpvp_start; 511 512 fm_ereport_dump(); 513 if (panicstr) 514 errorq_dump(); 515 516 bzero(&ed, sizeof (ed)); /* indicate end of ereports */ 517 dumpvp_write(&ed, sizeof (ed)); 518 (void) dumpvp_flush(); 519 520 if (!panicstr) { 521 (void) VOP_PUTPAGE(dumpvp, dumpvp_start, 522 (size_t)(dumpvp_off - dumpvp_start), 523 B_INVAL | B_FORCE, kcred, NULL); 524 } 525 } 526 527 void 528 dump_messages(void) 529 { 530 log_dump_t ld; 531 mblk_t *mctl, *mdata; 532 queue_t *q, *qlast; 533 u_offset_t dumpvp_start; 534 535 if (dumpvp == NULL || dumphdr == NULL || log_consq == NULL) 536 return; 537 538 dumpbuf_cur = dumpbuf_start; 539 dumpvp_limit = dumpvp_size - DUMP_OFFSET; 540 dumpvp_start = dumpvp_limit - DUMP_LOGSIZE; 541 dumpvp_off = dumpvp_start; 542 543 qlast = NULL; 544 do { 545 for (q = log_consq; q->q_next != qlast; q = q->q_next) 546 continue; 547 for (mctl = q->q_first; mctl != NULL; mctl = mctl->b_next) { 548 dump_timeleft = dump_timeout; 549 mdata = mctl->b_cont; 550 ld.ld_magic = LOG_MAGIC; 551 ld.ld_msgsize = MBLKL(mctl->b_cont); 552 ld.ld_csum = checksum32(mctl->b_rptr, MBLKL(mctl)); 553 ld.ld_msum = checksum32(mdata->b_rptr, MBLKL(mdata)); 554 dumpvp_write(&ld, sizeof (ld)); 555 dumpvp_write(mctl->b_rptr, MBLKL(mctl)); 556 dumpvp_write(mdata->b_rptr, MBLKL(mdata)); 557 } 558 } while ((qlast = q) != log_consq); 559 560 ld.ld_magic = 0; /* indicate end of messages */ 561 dumpvp_write(&ld, sizeof (ld)); 562 (void) dumpvp_flush(); 563 if (!panicstr) { 564 (void) VOP_PUTPAGE(dumpvp, dumpvp_start, 565 (size_t)(dumpvp_off - dumpvp_start), 566 B_INVAL | B_FORCE, kcred, NULL); 567 } 568 } 569 570 static void 571 dump_pagecopy(void *src, void *dst) 572 { 573 long *wsrc = (long *)src; 574 long *wdst = (long *)dst; 575 const ulong_t ncopies = PAGESIZE / sizeof (long); 576 volatile int w = 0; 577 volatile int ueoff = -1; 578 on_trap_data_t otd; 579 580 if (on_trap(&otd, OT_DATA_EC)) { 581 if (ueoff == -1) { 582 uint64_t pa; 583 584 ueoff = w * sizeof (long); 585 pa = ptob((uint64_t)hat_getpfnum(kas.a_hat, src)) 586 + ueoff; 587 cmn_err(CE_WARN, "memory error at PA 0x%08x.%08x", 588 (uint32_t)(pa >> 32), (uint32_t)pa); 589 } 590 #ifdef _LP64 591 wdst[w++] = 0xbadecc00badecc; 592 #else 593 wdst[w++] = 0xbadecc; 594 #endif 595 } 596 while (w < ncopies) { 597 wdst[w] = wsrc[w]; 598 w++; 599 } 600 no_trap(); 601 } 602 603 /* 604 * Dump the system. 605 */ 606 void 607 dumpsys(void) 608 { 609 pfn_t pfn; 610 pgcnt_t bitnum; 611 int npages = 0; 612 int percent_done = 0; 613 uint32_t csize; 614 u_offset_t total_csize = 0; 615 int compress_ratio; 616 proc_t *p; 617 pid_t npids, pidx; 618 char *content; 619 620 if (dumpvp == NULL || dumphdr == NULL) { 621 uprintf("skipping system dump - no dump device configured\n"); 622 return; 623 } 624 dumpbuf_cur = dumpbuf_start; 625 626 /* 627 * Calculate the starting block for dump. If we're dumping on a 628 * swap device, start 1/5 of the way in; otherwise, start at the 629 * beginning. And never use the first page -- it may be a disk label. 630 */ 631 if (dumpvp->v_flag & VISSWAP) 632 dumphdr->dump_start = P2ROUNDUP(dumpvp_size / 5, DUMP_OFFSET); 633 else 634 dumphdr->dump_start = DUMP_OFFSET; 635 636 dumphdr->dump_flags = DF_VALID | DF_COMPLETE | DF_LIVE; 637 dumphdr->dump_crashtime = gethrestime_sec(); 638 dumphdr->dump_npages = 0; 639 dumphdr->dump_nvtop = 0; 640 bzero(dump_bitmap, BT_SIZEOFMAP(dump_bitmapsize)); 641 dump_timeleft = dump_timeout; 642 643 if (panicstr) { 644 dumphdr->dump_flags &= ~DF_LIVE; 645 (void) VOP_DUMPCTL(dumpvp, DUMP_FREE, NULL, NULL); 646 (void) VOP_DUMPCTL(dumpvp, DUMP_ALLOC, NULL, NULL); 647 (void) vsnprintf(dumphdr->dump_panicstring, DUMP_PANICSIZE, 648 panicstr, panicargs); 649 } 650 651 if (dump_conflags & DUMP_ALL) 652 content = "all"; 653 else if (dump_conflags & DUMP_CURPROC) 654 content = "kernel + curproc"; 655 else 656 content = "kernel"; 657 uprintf("dumping to %s, offset %lld, content: %s\n", dumppath, 658 dumphdr->dump_start, content); 659 660 /* 661 * Leave room for the message and ereport save areas and terminal dump 662 * header. 663 */ 664 dumpvp_limit = dumpvp_size - DUMP_LOGSIZE - DUMP_OFFSET - DUMP_ERPTSIZE; 665 666 /* 667 * Write out the symbol table. It's no longer compressed, 668 * so its 'size' and 'csize' are equal. 669 */ 670 dumpvp_off = dumphdr->dump_ksyms = dumphdr->dump_start + PAGESIZE; 671 dumphdr->dump_ksyms_size = dumphdr->dump_ksyms_csize = 672 ksyms_snapshot(dumpvp_ksyms_write, NULL, LONG_MAX); 673 674 /* 675 * Write out the translation map. 676 */ 677 dumphdr->dump_map = dumpvp_flush(); 678 dump_as(&kas); 679 dumphdr->dump_nvtop += dump_plat_addr(); 680 681 /* 682 * call into hat, which may have unmapped pages that also need to 683 * be in the dump 684 */ 685 hat_dump(); 686 687 if (dump_conflags & DUMP_ALL) { 688 mutex_enter(&pidlock); 689 690 for (npids = 0, p = practive; p != NULL; p = p->p_next) 691 dump_pids[npids++] = p->p_pid; 692 693 mutex_exit(&pidlock); 694 695 for (pidx = 0; pidx < npids; pidx++) 696 (void) dump_process(dump_pids[pidx]); 697 698 for (bitnum = 0; bitnum < dump_bitmapsize; bitnum++) { 699 dump_timeleft = dump_timeout; 700 BT_SET(dump_bitmap, bitnum); 701 } 702 dumphdr->dump_npages = dump_bitmapsize; 703 dumphdr->dump_flags |= DF_ALL; 704 705 } else if (dump_conflags & DUMP_CURPROC) { 706 /* 707 * Determine which pid is to be dumped. If we're panicking, we 708 * dump the process associated with panic_thread (if any). If 709 * this is a live dump, we dump the process associated with 710 * curthread. 711 */ 712 npids = 0; 713 if (panicstr) { 714 if (panic_thread != NULL && 715 panic_thread->t_procp != NULL && 716 panic_thread->t_procp != &p0) { 717 dump_pids[npids++] = 718 panic_thread->t_procp->p_pid; 719 } 720 } else { 721 dump_pids[npids++] = curthread->t_procp->p_pid; 722 } 723 724 if (npids && dump_process(dump_pids[0]) == 0) 725 dumphdr->dump_flags |= DF_CURPROC; 726 else 727 dumphdr->dump_flags |= DF_KERNEL; 728 729 } else { 730 dumphdr->dump_flags |= DF_KERNEL; 731 } 732 733 dumphdr->dump_hashmask = (1 << highbit(dumphdr->dump_nvtop - 1)) - 1; 734 735 /* 736 * Write out the pfn table. 737 */ 738 dumphdr->dump_pfn = dumpvp_flush(); 739 for (bitnum = 0; bitnum < dump_bitmapsize; bitnum++) { 740 dump_timeleft = dump_timeout; 741 if (!BT_TEST(dump_bitmap, bitnum)) 742 continue; 743 pfn = dump_bitnum_to_pfn(bitnum); 744 ASSERT(pfn != PFN_INVALID); 745 dumpvp_write(&pfn, sizeof (pfn_t)); 746 } 747 dump_plat_pfn(); 748 749 /* 750 * Write out all the pages. 751 */ 752 dumphdr->dump_data = dumpvp_flush(); 753 for (bitnum = 0; bitnum < dump_bitmapsize; bitnum++) { 754 dump_timeleft = dump_timeout; 755 if (!BT_TEST(dump_bitmap, bitnum)) 756 continue; 757 pfn = dump_bitnum_to_pfn(bitnum); 758 ASSERT(pfn != PFN_INVALID); 759 760 /* 761 * Map in page frame 'pfn', scan it for UE's while copying 762 * the data to dump_uebuf, unmap it, compress dump_uebuf into 763 * dump_cbuf, and write out dump_cbuf. The UE check ensures 764 * that we don't lose the whole dump because of a latent UE. 765 */ 766 hat_devload(kas.a_hat, dump_cmap, PAGESIZE, pfn, PROT_READ, 767 HAT_LOAD_NOCONSIST); 768 dump_pagecopy(dump_cmap, dump_uebuf); 769 hat_unload(kas.a_hat, dump_cmap, PAGESIZE, HAT_UNLOAD); 770 csize = (uint32_t)compress(dump_uebuf, dump_cbuf, PAGESIZE); 771 dumpvp_write(&csize, sizeof (uint32_t)); 772 dumpvp_write(dump_cbuf, csize); 773 if (dump_ioerr) { 774 dumphdr->dump_flags &= ~DF_COMPLETE; 775 dumphdr->dump_npages = npages; 776 break; 777 } 778 total_csize += csize; 779 if (++npages * 100LL / dumphdr->dump_npages > percent_done) { 780 uprintf("^\r%3d%% done", ++percent_done); 781 if (!panicstr) 782 delay(1); /* let the output be sent */ 783 } 784 } 785 dumphdr->dump_npages += dump_plat_data(dump_cbuf); 786 787 (void) dumpvp_flush(); 788 789 /* 790 * Write out the initial and terminal dump headers. 791 */ 792 dumpvp_off = dumphdr->dump_start; 793 dumpvp_write(dumphdr, sizeof (dumphdr_t)); 794 (void) dumpvp_flush(); 795 796 dumpvp_limit = dumpvp_size; 797 dumpvp_off = dumpvp_limit - DUMP_OFFSET; 798 dumpvp_write(dumphdr, sizeof (dumphdr_t)); 799 (void) dumpvp_flush(); 800 801 compress_ratio = (int)(100LL * npages / (btopr(total_csize + 1))); 802 803 uprintf("\r%3d%% done: %d pages dumped, compression ratio %d.%02d, ", 804 percent_done, npages, compress_ratio / 100, compress_ratio % 100); 805 806 if (dump_ioerr == 0) { 807 uprintf("dump succeeded\n"); 808 } else { 809 uprintf("dump failed: error %d\n", dump_ioerr); 810 if (panicstr && dumpfaildebug) 811 debug_enter("dump failed"); 812 } 813 814 /* 815 * Write out all undelivered messages. This has to be the *last* 816 * thing we do because the dump process itself emits messages. 817 */ 818 if (panicstr) { 819 dump_ereports(); 820 dump_messages(); 821 } 822 823 delay(2 * hz); /* let people see the 'done' message */ 824 dump_timeleft = 0; 825 dump_ioerr = 0; 826 } 827 828 /* 829 * This function is called whenever the memory size, as represented 830 * by the phys_install list, changes. 831 */ 832 void 833 dump_resize() 834 { 835 mutex_enter(&dump_lock); 836 dumphdr_init(); 837 dumpbuf_resize(); 838 mutex_exit(&dump_lock); 839 } 840 841 /* 842 * This function allows for dynamic resizing of a dump area. It assumes that 843 * the underlying device has update its appropriate size(9P). 844 */ 845 int 846 dumpvp_resize() 847 { 848 int error; 849 vattr_t vattr; 850 851 mutex_enter(&dump_lock); 852 vattr.va_mask = AT_SIZE; 853 if ((error = VOP_GETATTR(dumpvp, &vattr, 0, kcred, NULL)) != 0) { 854 mutex_exit(&dump_lock); 855 return (error); 856 } 857 858 if (error == 0 && vattr.va_size < 2 * DUMP_LOGSIZE + DUMP_ERPTSIZE) { 859 mutex_exit(&dump_lock); 860 return (ENOSPC); 861 } 862 863 dumpvp_size = vattr.va_size & -DUMP_OFFSET; 864 mutex_exit(&dump_lock); 865 return (0); 866 } 867