Beispiel #1
0
void
bs_remap_earlyboot(void)
{
	int i;
	vm_offset_t pa, spa, va;
	vm_memattr_t ma;

	for (i = 0; i < earlyboot_map_idx; i++) {
		spa = earlyboot_mappings[i].addr;
		if (spa == earlyboot_mappings[i].virt &&
		   pmap_dev_direct_mapped(spa, earlyboot_mappings[i].size) == 0)
			continue;

		ma = VM_MEMATTR_DEFAULT;
		switch (earlyboot_mappings[i].flags) {
			case BUS_SPACE_MAP_CACHEABLE:
				ma = VM_MEMATTR_CACHEABLE;
				break;
			case BUS_SPACE_MAP_PREFETCHABLE:
				ma = VM_MEMATTR_PREFETCHABLE;
				break;
		}

		pa = trunc_page(spa);
		va = trunc_page(earlyboot_mappings[i].virt);
		while (pa < spa + earlyboot_mappings[i].size) {
			pmap_kenter_attr(va, pa, ma);
			va += PAGE_SIZE;
			pa += PAGE_SIZE;
		}
	}
}
Beispiel #2
0
/*
 * allow user processes to MMAP some memory sections
 * instead of going through read/write
 */
int
memmmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr,
    int prot, vm_memattr_t *memattr)
{
	int i;

	/*
	 * /dev/mem is the only one that makes sense through this
	 * interface.  For /dev/kmem any physaddr we return here
	 * could be transient and hence incorrect or invalid at
	 * a later time.
	 */
	if (dev2unit(dev) != CDEV_MINOR_MEM)
		return (-1);

	/* Only direct-mapped addresses. */
	if (mem_valid(offset, 0)
	    && pmap_dev_direct_mapped(offset, 0))
		return (EFAULT);

	*paddr = offset;

	for (i = 0; i < mem_range_softc.mr_ndesc; i++) {
		if (!(mem_range_softc.mr_desc[i].mr_flags & MDF_ACTIVE))
			continue;

		if (offset >= mem_range_softc.mr_desc[i].mr_base &&
		    offset < mem_range_softc.mr_desc[i].mr_base +
		    mem_range_softc.mr_desc[i].mr_len) {
			switch (mem_range_softc.mr_desc[i].mr_flags &
			    MDF_ATTRMASK) {
			case MDF_WRITEBACK:
				*memattr = VM_MEMATTR_WRITE_BACK;
				break;
			case MDF_WRITECOMBINE:
				*memattr = VM_MEMATTR_WRITE_COMBINING;
				break;
			case MDF_UNCACHEABLE:
				*memattr = VM_MEMATTR_UNCACHEABLE;
				break;
			case MDF_WRITETHROUGH:
				*memattr = VM_MEMATTR_WRITE_THROUGH;
				break;
			}

			break;
		}
	}

	return (0);
}
Beispiel #3
0
/* ARGSUSED */
int
memrw(struct cdev *dev, struct uio *uio, int flags)
{
	struct iovec *iov;
	int error = 0;
	vm_offset_t va, eva, off, v;
	vm_prot_t prot;
	struct vm_page m;
	vm_page_t marr;
	vm_size_t cnt;

	cnt = 0;
	error = 0;

	GIANT_REQUIRED;

	while (uio->uio_resid > 0 && !error) {
		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) {
kmem_direct_mapped:	v = uio->uio_offset;

			off = uio->uio_offset & PAGE_MASK;
			cnt = PAGE_SIZE - ((vm_offset_t)iov->iov_base &
			    PAGE_MASK);
			cnt = min(cnt, PAGE_SIZE - off);
			cnt = min(cnt, iov->iov_len);

			if (mem_valid(v, cnt)) {
				error = EFAULT;
				break;
			}
	
			if (!pmap_dev_direct_mapped(v, cnt)) {
				error = uiomove((void *)v, cnt, uio);
			} else {
				m.phys_addr = trunc_page(v);
				marr = &m;
				error = uiomove_fromphys(&marr, off, cnt, uio);
			}
		}
		else if (dev2unit(dev) == CDEV_MINOR_KMEM) {
			va = uio->uio_offset;

			if ((va < VM_MIN_KERNEL_ADDRESS) || (va > virtual_end))
				goto kmem_direct_mapped;

			va = trunc_page(uio->uio_offset);
			eva = round_page(uio->uio_offset
			    + iov->iov_len);

			/* 
			 * Make sure that all the pages are currently resident
			 * so that we don't create any zero-fill pages.
			 */

			for (; va < eva; va += PAGE_SIZE)
				if (pmap_extract(kernel_pmap, va) == 0)
					return (EFAULT);

			prot = (uio->uio_rw == UIO_READ)
			    ? VM_PROT_READ : VM_PROT_WRITE;

			va = uio->uio_offset;
			if (kernacc((void *) va, iov->iov_len, prot)
			    == FALSE)
				return (EFAULT);

			error = uiomove((void *)va, iov->iov_len, uio);

			continue;
		}
	}

	return (error);
}