void dumpconf(void) { cpu_kcore_hdr_t *h = &cpu_kcore_hdr; u_int dumpextra, totaldumpsize; /* in disk blocks */ u_int seg, nblks; if (dumpdev == NODEV || (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0) return; if (nblks <= ctod(1)) return; dumpsize = 0; for (seg = 0; seg < h->kcore_nsegs; seg++) dumpsize += atop(h->kcore_segs[seg].size); dumpextra = cpu_dumpsize(); /* Always skip the first block, in case there is a label there. */ if (dumplo < btodb(1)) dumplo = btodb(1); /* Put dump at the end of the partition, and make it fit. */ totaldumpsize = ctod(dumpsize) + dumpextra; if (totaldumpsize > nblks - dumplo) { totaldumpsize = dbtob(nblks - dumplo); dumpsize = dtoc(totaldumpsize - dumpextra); } if (dumplo < nblks - totaldumpsize) dumplo = nblks - totaldumpsize; }
/* * Dump the machine-dependent dump header. */ u_int cpu_dump(int (*dump)(dev_t, daddr_t, caddr_t, size_t), daddr_t *blknop) { extern cpu_kcore_hdr_t cpu_kcore_hdr; char buf[dbtob(1)]; cpu_kcore_hdr_t *h; kcore_seg_t *kseg; int rc; #ifdef DIAGNOSTIC if (cpu_dumpsize() > btodb(sizeof buf)) { printf("buffer too small in cpu_dump, "); return (EINVAL); /* "aborted" */ } #endif bzero(buf, sizeof buf); kseg = (kcore_seg_t *)buf; h = (cpu_kcore_hdr_t *)(buf + ALIGN(sizeof(kcore_seg_t))); /* Create the segment header */ CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU); kseg->c_size = dbtob(1) - ALIGN(sizeof(kcore_seg_t)); bcopy(&cpu_kcore_hdr, h, sizeof(*h)); /* We can now fill kptp in the header... */ h->kcore_kptp = SH3_P1SEG_TO_PHYS((vaddr_t)pmap_kernel()->pm_ptp); rc = (*dump)(dumpdev, *blknop, buf, sizeof buf); *blknop += btodb(sizeof buf); return (rc); }
/* * This is called by configure to set dumplo and dumpsize. * Dumps always skip the first CLBYTES of disk space * in case there might be a disk label stored there. * If there is extra space, put dump at the end to * reduce the chance that swapping trashes it. */ void dumpconf(void) { extern int dumpsize; int nblks, dumpblks; /* size of dump area */ if (dumpdev == NODEV || (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0) return; if (nblks <= ctod(1)) return; dumpblks = cpu_dumpsize(); if (dumpblks < 0) return; dumpblks += ctod(physmem); /* If dump won't fit (incl. room for possible label), punt. */ if (dumpblks > (nblks - ctod(1))) return; /* Put dump at end of partition */ dumplo = nblks - dumpblks; /* dumpsize is in page units, and doesn't include headers. */ dumpsize = physmem; }
/* * This is called by main to set dumplo and dumpsize. * Dumps always skip the first PAGE_SIZE of disk space * in case there might be a disk label stored there. * If there is extra space, put dump at the end to * reduce the chance that swapping trashes it. * * Sparse dumps can't placed as close to the end as possible, because * savecore(8) has to know where to start reading in the dump device * before it has access to any of the crashed system's state. * * Note also that a sparse dump will never be larger than a full one: * in order to add a phys_ram_seg_t to the header, at least one page * must be removed. */ void cpu_dumpconf(void) { const struct bdevsw *bdev; int nblks, dumpblks; /* size of dump area */ if (dumpdev == NODEV) goto bad; bdev = bdevsw_lookup(dumpdev); if (bdev == NULL) { dumpdev = NODEV; goto bad; } if (bdev->d_psize == NULL) goto bad; nblks = (*bdev->d_psize)(dumpdev); if (nblks <= ctod(1)) goto bad; dumpblks = cpu_dumpsize(); if (dumpblks < 0) goto bad; dumpblks += ctod(cpu_dump_mempagecnt()); /* If dump won't fit (incl. room for possible label): */ if (dumpblks > (nblks - ctod(1))) { /* A sparse dump might (and hopefully will) fit. */ dumplo = ctod(1); } else { /* Put dump at end of partition */ dumplo = nblks - dumpblks; } /* dumpsize is in page units, and doesn't include headers. */ dumpsize = cpu_dump_mempagecnt(); /* Now that we've decided this will work, init ancillary stuff. */ dump_misc_init(); return; bad: dumpsize = 0; }
/* * This is called by main to set dumplo and dumpsize. * Dumps always skip the first PAGE_SIZE of disk space * in case there might be a disk label stored there. * If there is extra space, put dump at the end to * reduce the chance that swapping trashes it. */ void dumpconf(void) { const struct bdevsw *bdev; int nblks, dumpblks; /* size of dump area */ if (dumpdev == NODEV) goto bad; bdev = &bdevsw[major(dumpdev)]; if (bdev == NULL) panic("dumpconf: bad dumpdev=0x%x", dumpdev); if (bdev->d_psize == NULL) goto bad; nblks = (*bdev->d_psize)(dumpdev); if (nblks <= ctod(1)) goto bad; dumpblks = cpu_dumpsize(); if (dumpblks < 0) goto bad; dumpblks += ctod(cpu_dump_mempagecnt()); /* If dump won't fit (incl. room for possible label), punt. */ if (dumpblks > (nblks - ctod(1))) goto bad; /* Put dump at end of partition */ dumplo = nblks - dumpblks; /* dumpsize is in page units, and doesn't include headers. */ dumpsize = cpu_dump_mempagecnt(); return; bad: dumpsize = 0; }
void dodumpsys() { const struct bdevsw *bdev; daddr_t blkno; int psize; int error; int addr; int block; int len; vaddr_t dumpspace; /* flush everything out of caches */ cpu_dcache_wbinv_all(); if (dumpdev == NODEV) return; if (dumpsize == 0) { cpu_dumpconf(); } if (dumplo <= 0 || dumpsize == 0) { printf("\ndump to dev %u,%u not possible\n", major(dumpdev), minor(dumpdev)); delay(5000000); return; } printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev), minor(dumpdev), dumplo); bdev = bdevsw_lookup(dumpdev); if (bdev == NULL || bdev->d_psize == NULL) return; psize = (*bdev->d_psize)(dumpdev); printf("dump "); if (psize == -1) { printf("area unavailable\n"); return; } if ((error = cpu_dump()) != 0) goto err; blkno = dumplo + cpu_dumpsize(); dumpspace = memhook; error = 0; len = 0; for (block = 0; block < bootconfig.dramblocks && error == 0; ++block) { addr = bootconfig.dram[block].address; for (;addr < (bootconfig.dram[block].address + (bootconfig.dram[block].pages * PAGE_SIZE)); addr += PAGE_SIZE) { if ((len % (1024*1024)) == 0) printf("%d ", len / (1024*1024)); pmap_kenter_pa(dumpspace, addr, VM_PROT_READ); pmap_update(pmap_kernel()); error = (*bdev->d_dump)(dumpdev, blkno, (void *) dumpspace, PAGE_SIZE); if (error) goto err; blkno += btodb(PAGE_SIZE); len += PAGE_SIZE; } } err: switch (error) { case ENXIO: printf("device bad\n"); break; case EFAULT: printf("device not ready\n"); break; case EINVAL: printf("area improper\n"); break; case EIO: printf("i/o error\n"); break; case EINTR: printf("aborted from console\n"); break; case 0: printf("succeeded\n"); break; default: printf("error %d\n", error); break; } printf("\n\n"); delay(5000000); }
void dumpsys(void) { u_long totalbytesleft, bytes, i, n, memseg; u_long maddr; daddr_t blkno; int (*dump)(dev_t, daddr_t, caddr_t, size_t); int error; /* Save registers. */ savectx(&dumppcb); if (dumpdev == NODEV) return; /* * For dumps during autoconfiguration, * if dump device has already configured... */ if (dumpsize == 0) dumpconf(); if (dumplo <= 0 || dumpsize == 0) { printf("\ndump to dev %u,%u not possible\n", major(dumpdev), minor(dumpdev)); return; } printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev), minor(dumpdev), dumplo); error = (*bdevsw[major(dumpdev)].d_psize)(dumpdev); printf("dump "); if (error == -1) { printf("area unavailable\n"); return; } if ((error = cpu_dump()) != 0) goto err; totalbytesleft = ptoa(cpu_dump_mempagecnt()); blkno = dumplo + cpu_dumpsize(); dump = bdevsw[major(dumpdev)].d_dump; error = 0; for (memseg = 0; memseg < mem_cluster_cnt; memseg++) { maddr = mem_clusters[memseg].start; bytes = mem_clusters[memseg].size; for (i = 0; i < bytes; i += n, totalbytesleft -= n) { /* Print out how many MBs we have left to go. */ if ((totalbytesleft % (1024*1024)) == 0) printf("%ld ", totalbytesleft / (1024 * 1024)); /* Limit size for next transfer. */ n = bytes - i; if (n > BYTES_PER_DUMP) n = BYTES_PER_DUMP; (void) pmap_map(dumpspace, maddr, maddr + n, VM_PROT_READ); error = (*dump)(dumpdev, blkno, (caddr_t)dumpspace, n); if (error) goto err; maddr += n; blkno += btodb(n); /* XXX? */ #if 0 /* XXX this doesn't work. grr. */ /* operator aborting dump? */ if (sget() != NULL) { error = EINTR; break; } #endif } } err: switch (error) { case ENXIO: printf("device bad\n"); break; case EFAULT: printf("device not ready\n"); break; case EINVAL: printf("area improper\n"); break; case EIO: printf("i/o error\n"); break; case EINTR: printf("aborted from console\n"); break; case 0: printf("succeeded\n"); break; default: printf("error %d\n", error); break; } printf("\n\n"); delay(5000000); /* 5 seconds */ }