/* ARGSUSED */ int memrw(struct cdev *dev, struct uio *uio, int flags) { struct iovec *iov; vm_offset_t eva; vm_offset_t off; vm_offset_t ova; vm_offset_t va; vm_prot_t prot; vm_paddr_t pa; vm_size_t cnt; vm_page_t m; int error; int i; uint32_t colors; cnt = 0; colors = 1; error = 0; ova = 0; GIANT_REQUIRED; while (uio->uio_resid > 0 && error == 0) { iov = uio->uio_iov; if (iov->iov_len == 0) { uio->uio_iov++; uio->uio_iovcnt--; if (uio->uio_iovcnt < 0) panic("memrw"); continue; } if (dev2unit(dev) == CDEV_MINOR_MEM) { pa = uio->uio_offset & ~PAGE_MASK; if (!is_physical_memory(pa)) { error = EFAULT; break; } off = uio->uio_offset & PAGE_MASK; cnt = PAGE_SIZE - ((vm_offset_t)iov->iov_base & PAGE_MASK); cnt = ulmin(cnt, PAGE_SIZE - off); cnt = ulmin(cnt, iov->iov_len); m = NULL; for (i = 0; phys_avail[i] != 0; i += 2) { if (pa >= phys_avail[i] && pa < phys_avail[i + 1]) { m = PHYS_TO_VM_PAGE(pa); break; } } if (m != NULL) { if (ova == 0) { if (dcache_color_ignore == 0) colors = DCACHE_COLORS; ova = kmem_alloc_wait(kernel_map, PAGE_SIZE * colors); } if (colors != 1 && m->md.color != -1) va = ova + m->md.color * PAGE_SIZE; else va = ova; pmap_qenter(va, &m, 1); error = uiomove((void *)(va + off), cnt, uio); pmap_qremove(va, 1); } else { va = TLB_PHYS_TO_DIRECT(pa); error = uiomove((void *)(va + off), cnt, uio); } break; } else if (dev2unit(dev) == CDEV_MINOR_KMEM) { va = trunc_page(uio->uio_offset); eva = round_page(uio->uio_offset + iov->iov_len); /* * Make sure that all of the pages are currently * resident so we don't create any zero fill pages. */ for (; va < eva; va += PAGE_SIZE) if (pmap_kextract(va) == 0) return (EFAULT); prot = (uio->uio_rw == UIO_READ) ? VM_PROT_READ : VM_PROT_WRITE; va = uio->uio_offset; if (va < VM_MIN_DIRECT_ADDRESS && kernacc((void *)va, iov->iov_len, prot) == FALSE) return (EFAULT); error = uiomove((void *)va, iov->iov_len, uio); break; } /* else panic! */ } if (ova != 0) kmem_free_wakeup(kernel_map, ova, PAGE_SIZE * colors); return (error); }
void dumpsys(struct dumperinfo *di) { off_t dumplo; vm_offset_t a, addr; u_int count, left, u; void *va; int i, mb; printf("Dumping %ld MB\n", Maxmem / (1024*1024 / PAGE_SIZE)); /* Fill in the kernel dump header */ strcpy(kdh.magic, KERNELDUMPMAGIC); strcpy(kdh.architecture, "alpha"); kdh.version = htod32(KERNELDUMPVERSION); kdh.architectureversion = htod32(KERNELDUMP_ALPHA_VERSION); kdh.dumplength = htod64(Maxmem * (off_t)PAGE_SIZE); kdh.dumptime = htod64(time_second); kdh.blocksize = htod32(di->blocksize); strncpy(kdh.hostname, hostname, sizeof kdh.hostname); strncpy(kdh.versionstring, version, sizeof kdh.versionstring); if (panicstr != NULL) strncpy(kdh.panicstring, panicstr, sizeof kdh.panicstring); kdh.parity = kerneldump_parity(&kdh); /* * Check if we will have enough room to save the coredump. * The partition size needed is the sum of: * Memory to save + header + trailer + Room to leave untouched * at partition head. (an arbitrary amount). */ if (di->mediasize < Maxmem * (off_t)PAGE_SIZE + sizeof kdh * 2 + 64*1024) { printf("\nDump failed. Partition too small.\n"); return; } dumplo = di->mediaoffset + di->mediasize - Maxmem * (off_t)PAGE_SIZE; dumplo -= sizeof kdh * 2; i = di->dumper(di->priv, &kdh, NULL, dumplo, sizeof kdh); if (i) printf("\nDump failed writing header (%d)\n", i); dumplo += sizeof kdh; i = 0; addr = 0; va = 0; mb = 0; for (count = 0; count < Maxmem;) { left = Maxmem - count; if (left > MAXDUMPPGS) left = MAXDUMPPGS; for (u = 0; u < left; u++) { a = addr + u * PAGE_SIZE; if (!is_physical_memory(a)) a = 0; va = pmap_kenter_temporary(trunc_page(a), u); } i = count / (16*1024*1024 / PAGE_SIZE); if (i != mb) { printf(" %d", count / (1024 * 1024 / PAGE_SIZE)); mb = i; } i = di->dumper(di->priv, va, NULL, dumplo, left * PAGE_SIZE); if (i) break; count += left; dumplo += left * PAGE_SIZE; addr += left * PAGE_SIZE; } if (i) printf("\nDump failed writing data (%d)\n", i); i = di->dumper(di->priv, &kdh, NULL, dumplo, sizeof kdh); if (i) printf("\nDump failed writing trailer (%d)\n", i); di->dumper(di->priv, NULL, NULL, 0, 0); /* tell them we are done */ printf("\nDump complete\n"); return; }
static bool is_physical_memory(void *address) { return is_physical_memory(address, 1); }