예제 #1
0
/* 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);
}
예제 #2
0
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;
}
예제 #3
0
파일: mmu.cpp 프로젝트: looncraz/haiku
static bool
is_physical_memory(void *address)
{
	return is_physical_memory(address, 1);
}