1206714Sjmallett/*- 2178172Simp * Copyright (c) 1988 University of Utah. 3206714Sjmallett * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. 4206714Sjmallett * All rights reserved. 5178172Simp * 6178172Simp * This code is derived from software contributed to Berkeley by 7178172Simp * the Systems Programming Group of the University of Utah Computer 8206714Sjmallett * Science Department, and code derived from software contributed to 9206714Sjmallett * Berkeley by William Jolitz. 10178172Simp * 11178172Simp * Redistribution and use in source and binary forms, with or without 12178172Simp * modification, are permitted provided that the following conditions 13178172Simp * are met: 14178172Simp * 1. Redistributions of source code must retain the above copyright 15178172Simp * notice, this list of conditions and the following disclaimer. 16178172Simp * 2. Redistributions in binary form must reproduce the above copyright 17178172Simp * notice, this list of conditions and the following disclaimer in the 18178172Simp * documentation and/or other materials provided with the distribution. 19178172Simp * 4. Neither the name of the University nor the names of its contributors 20178172Simp * may be used to endorse or promote products derived from this software 21178172Simp * without specific prior written permission. 22178172Simp * 23178172Simp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24178172Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25178172Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26178172Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27178172Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28178172Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29178172Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30178172Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31178172Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32178172Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33178172Simp * SUCH DAMAGE. 34178172Simp * 35206714Sjmallett * from: Utah $Hdr: mem.c 1.13 89/10/08$ 36206714Sjmallett * from: @(#)mem.c 7.2 (Berkeley) 5/9/91 37178172Simp */ 38178172Simp 39206714Sjmallett#include <sys/cdefs.h> 40206714Sjmallett__FBSDID("$FreeBSD$"); 41206714Sjmallett 42178172Simp/* 43178172Simp * Memory special file 44178172Simp */ 45178172Simp 46178172Simp#include <sys/param.h> 47206714Sjmallett#include <sys/conf.h> 48206714Sjmallett#include <sys/fcntl.h> 49178172Simp#include <sys/kernel.h> 50206714Sjmallett#include <sys/lock.h> 51206714Sjmallett#include <sys/malloc.h> 52206714Sjmallett#include <sys/memrange.h> 53206714Sjmallett#include <sys/module.h> 54206714Sjmallett#include <sys/mutex.h> 55178172Simp#include <sys/proc.h> 56178172Simp#include <sys/msgbuf.h> 57178172Simp#include <sys/systm.h> 58206714Sjmallett#include <sys/signalvar.h> 59178172Simp#include <sys/uio.h> 60206714Sjmallett 61178172Simp#include <machine/md_var.h> 62206714Sjmallett#include <machine/vmparam.h> 63206714Sjmallett 64206714Sjmallett#include <vm/vm.h> 65206714Sjmallett#include <vm/pmap.h> 66206714Sjmallett#include <vm/vm_extern.h> 67206714Sjmallett#include <vm/vm_page.h> 68206714Sjmallett 69178172Simp#include <machine/memdev.h> 70178172Simp 71206714Sjmallettstruct mem_range_softc mem_range_softc; 72178172Simp 73206714Sjmallett/* ARGSUSED */ 74178172Simpint 75206714Sjmallettmemrw(struct cdev *dev, struct uio *uio, int flags) 76178172Simp{ 77206714Sjmallett struct iovec *iov; 78178172Simp int error = 0; 79206714Sjmallett vm_offset_t va, eva, off, v; 80206714Sjmallett vm_prot_t prot; 81206714Sjmallett struct vm_page m; 82206714Sjmallett vm_page_t marr; 83206714Sjmallett vm_size_t cnt; 84178172Simp 85206714Sjmallett cnt = 0; 86206714Sjmallett error = 0; 87206714Sjmallett 88206714Sjmallett GIANT_REQUIRED; 89206714Sjmallett 90226459Sjchandra pmap_page_init(&m); 91206714Sjmallett while (uio->uio_resid > 0 && !error) { 92178172Simp iov = uio->uio_iov; 93178172Simp if (iov->iov_len == 0) { 94178172Simp uio->uio_iov++; 95178172Simp uio->uio_iovcnt--; 96178172Simp if (uio->uio_iovcnt < 0) 97206714Sjmallett panic("memrw"); 98178172Simp continue; 99178172Simp } 100183397Sed if (dev2unit(dev) == CDEV_MINOR_MEM) { 101178172Simp v = uio->uio_offset; 102178172Simp 103206714Sjmallett off = uio->uio_offset & PAGE_MASK; 104206714Sjmallett cnt = PAGE_SIZE - ((vm_offset_t)iov->iov_base & 105206714Sjmallett PAGE_MASK); 106206714Sjmallett cnt = min(cnt, PAGE_SIZE - off); 107206714Sjmallett cnt = min(cnt, iov->iov_len); 108178172Simp 109206714Sjmallett m.phys_addr = trunc_page(v); 110206714Sjmallett marr = &m; 111206714Sjmallett error = uiomove_fromphys(&marr, off, cnt, uio); 112178172Simp } 113183397Sed else if (dev2unit(dev) == CDEV_MINOR_KMEM) { 114206714Sjmallett va = uio->uio_offset; 115202046Simp 116206714Sjmallett va = trunc_page(uio->uio_offset); 117206714Sjmallett eva = round_page(uio->uio_offset 118206714Sjmallett + iov->iov_len); 119178172Simp 120206714Sjmallett /* 121206714Sjmallett * Make sure that all the pages are currently resident 122206714Sjmallett * so that we don't create any zero-fill pages. 123178172Simp */ 124206718Sjmallett if (va >= VM_MIN_KERNEL_ADDRESS && 125206718Sjmallett eva <= VM_MAX_KERNEL_ADDRESS) { 126206718Sjmallett for (; va < eva; va += PAGE_SIZE) 127206718Sjmallett if (pmap_extract(kernel_pmap, va) == 0) 128206718Sjmallett return (EFAULT); 129178172Simp 130206718Sjmallett prot = (uio->uio_rw == UIO_READ) 131206718Sjmallett ? VM_PROT_READ : VM_PROT_WRITE; 132206718Sjmallett 133206718Sjmallett va = uio->uio_offset; 134206718Sjmallett if (kernacc((void *) va, iov->iov_len, prot) 135206718Sjmallett == FALSE) 136206714Sjmallett return (EFAULT); 137206718Sjmallett } 138178172Simp 139206714Sjmallett va = uio->uio_offset; 140206714Sjmallett error = uiomove((void *)va, iov->iov_len, uio); 141178172Simp continue; 142178172Simp } 143206714Sjmallett } 144178172Simp 145178172Simp return (error); 146178172Simp} 147178172Simp 148206714Sjmallett/* 149206714Sjmallett * allow user processes to MMAP some memory sections 150206714Sjmallett * instead of going through read/write 151206714Sjmallett */ 152178172Simpint 153206714Sjmallettmemmmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, 154201223Srnoland int prot, vm_memattr_t *memattr) 155178172Simp{ 156206714Sjmallett /* 157206714Sjmallett * /dev/mem is the only one that makes sense through this 158206714Sjmallett * interface. For /dev/kmem any physaddr we return here 159206714Sjmallett * could be transient and hence incorrect or invalid at 160206714Sjmallett * a later time. 161206714Sjmallett */ 162206714Sjmallett if (dev2unit(dev) != CDEV_MINOR_MEM) 163206714Sjmallett return (-1); 164178172Simp 165206714Sjmallett *paddr = offset; 166206714Sjmallett 167206714Sjmallett return (0); 168178172Simp} 169