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
90206714Sjmallett	while (uio->uio_resid > 0 && !error) {
91178172Simp		iov = uio->uio_iov;
92178172Simp		if (iov->iov_len == 0) {
93178172Simp			uio->uio_iov++;
94178172Simp			uio->uio_iovcnt--;
95178172Simp			if (uio->uio_iovcnt < 0)
96206714Sjmallett				panic("memrw");
97178172Simp			continue;
98178172Simp		}
99183397Sed		if (dev2unit(dev) == CDEV_MINOR_MEM) {
100178172Simp			v = uio->uio_offset;
101178172Simp
102206714Sjmallett			off = uio->uio_offset & PAGE_MASK;
103206714Sjmallett			cnt = PAGE_SIZE - ((vm_offset_t)iov->iov_base &
104206714Sjmallett			    PAGE_MASK);
105206714Sjmallett			cnt = min(cnt, PAGE_SIZE - off);
106206714Sjmallett			cnt = min(cnt, iov->iov_len);
107178172Simp
108206714Sjmallett			m.phys_addr = trunc_page(v);
109206714Sjmallett			marr = &m;
110206714Sjmallett			error = uiomove_fromphys(&marr, off, cnt, uio);
111178172Simp		}
112183397Sed		else if (dev2unit(dev) == CDEV_MINOR_KMEM) {
113206714Sjmallett			va = uio->uio_offset;
114202046Simp
115206714Sjmallett			va = trunc_page(uio->uio_offset);
116206714Sjmallett			eva = round_page(uio->uio_offset
117206714Sjmallett			    + iov->iov_len);
118178172Simp
119206714Sjmallett			/*
120206714Sjmallett			 * Make sure that all the pages are currently resident
121206714Sjmallett			 * so that we don't create any zero-fill pages.
122178172Simp			 */
123206718Sjmallett			if (va >= VM_MIN_KERNEL_ADDRESS &&
124206718Sjmallett			    eva <= VM_MAX_KERNEL_ADDRESS) {
125206718Sjmallett				for (; va < eva; va += PAGE_SIZE)
126206718Sjmallett					if (pmap_extract(kernel_pmap, va) == 0)
127206718Sjmallett						return (EFAULT);
128178172Simp
129206718Sjmallett				prot = (uio->uio_rw == UIO_READ)
130206718Sjmallett				    ? VM_PROT_READ : VM_PROT_WRITE;
131206718Sjmallett
132206718Sjmallett				va = uio->uio_offset;
133206718Sjmallett				if (kernacc((void *) va, iov->iov_len, prot)
134206718Sjmallett				    == FALSE)
135206714Sjmallett					return (EFAULT);
136206718Sjmallett			}
137178172Simp
138206714Sjmallett			va = uio->uio_offset;
139206714Sjmallett			error = uiomove((void *)va, iov->iov_len, uio);
140178172Simp			continue;
141178172Simp		}
142206714Sjmallett	}
143178172Simp
144178172Simp	return (error);
145178172Simp}
146178172Simp
147206714Sjmallett/*
148206714Sjmallett * allow user processes to MMAP some memory sections
149206714Sjmallett * instead of going through read/write
150206714Sjmallett */
151178172Simpint
152206714Sjmallettmemmmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr,
153201223Srnoland    int prot, vm_memattr_t *memattr)
154178172Simp{
155206714Sjmallett	/*
156206714Sjmallett	 * /dev/mem is the only one that makes sense through this
157206714Sjmallett	 * interface.  For /dev/kmem any physaddr we return here
158206714Sjmallett	 * could be transient and hence incorrect or invalid at
159206714Sjmallett	 * a later time.
160206714Sjmallett	 */
161206714Sjmallett	if (dev2unit(dev) != CDEV_MINOR_MEM)
162206714Sjmallett		return (-1);
163178172Simp
164206714Sjmallett	*paddr = offset;
165206714Sjmallett
166206714Sjmallett	return (0);
167178172Simp}
168