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