1/*	$OpenBSD: mem.c,v 1.24 2019/12/20 13:34:41 visa Exp $	*/
2/*	$NetBSD: mem.c,v 1.6 1995/04/10 11:55:03 mycroft Exp $	*/
3
4/*
5 * Copyright (c) 1988 University of Utah.
6 * Copyright (c) 1982, 1986, 1990, 1993
7 *	The Regents of the University of California.  All rights reserved.
8 *
9 * This code is derived from software contributed to Berkeley by
10 * the Systems Programming Group of the University of Utah Computer
11 * Science Department and Ralph Campbell.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 *    notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 *    notice, this list of conditions and the following disclaimer in the
20 *    documentation and/or other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use of this software
22 *    must display the following acknowledgement:
23 *	This product includes software developed by the University of
24 *	California, Berkeley and its contributors.
25 * 4. Neither the name of the University nor the names of its contributors
26 *    may be used to endorse or promote products derived from this software
27 *    without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * SUCH DAMAGE.
40 *
41 *	@(#)mem.c	8.3 (Berkeley) 1/12/94
42 */
43
44/*
45 * Memory special file
46 */
47
48#include <sys/param.h>
49#include <sys/conf.h>
50#include <sys/buf.h>
51#include <sys/filio.h>
52#include <sys/proc.h>
53#include <sys/msgbuf.h>
54#include <sys/systm.h>
55#include <sys/uio.h>
56#include <sys/malloc.h>
57
58#include <machine/autoconf.h>
59#include <machine/cpu.h>
60#include <machine/memconf.h>
61
62#include <uvm/uvm_extern.h>
63
64int is_memory_range(paddr_t, psize_t, psize_t);
65
66caddr_t zeropage;
67
68#define mmread  mmrw
69#define mmwrite mmrw
70cdev_decl(mm);
71
72int
73mmopen(dev_t dev, int flag, int mode, struct proc *p)
74{
75	extern int allowkmem;
76
77	switch (minor(dev)) {
78	case 0:
79	case 1:
80		if (securelevel <= 0 || allowkmem)
81			break;
82		return (EPERM);
83	case 2:
84	case 12:
85		break;
86	default:
87		return (ENXIO);
88	}
89	return (0);
90}
91
92int
93mmclose(dev_t dev, int flag, int mode, struct proc *p)
94{
95	return (0);
96}
97
98int
99mmrw(dev_t dev, struct uio *uio, int flags)
100{
101	struct iovec *iov;
102	int allowed;
103	int error = 0;
104	size_t c;
105	vaddr_t v;
106
107	while (uio->uio_resid > 0 && error == 0) {
108		iov = uio->uio_iov;
109		if (iov->iov_len == 0) {
110			uio->uio_iov++;
111			uio->uio_iovcnt--;
112			if (uio->uio_iovcnt < 0)
113				panic("mmrw");
114			continue;
115		}
116		switch (minor(dev)) {
117
118		/* minor device 0 is physical memory */
119		case 0:
120			v = uio->uio_offset;
121			c = iov->iov_len;
122			if (v + c < v || v + c > ptoa((psize_t)physmem))
123				return (EFAULT);
124			v = (vaddr_t)PHYS_TO_XKPHYS(v, CCA_NONCOHERENT);
125			error = uiomove((caddr_t)v, c, uio);
126			continue;
127
128		/* minor device 1 is kernel memory */
129		case 1:
130			v = uio->uio_offset;
131			c = ulmin(iov->iov_len, MAXPHYS);
132
133			/* Allow access to RAM through XKPHYS... */
134			if (IS_XKPHYS(v))
135				allowed = is_memory_range(XKPHYS_TO_PHYS(v),
136				    (psize_t)c, 0);
137			/* ...or through CKSEG0... */
138			else if (v >= CKSEG0_BASE &&
139			    v < CKSEG0_BASE + CKSEG_SIZE)
140				allowed = is_memory_range(CKSEG0_TO_PHYS(v),
141				    (psize_t)c, CKSEG_SIZE);
142			/* ...or through CKSEG1... */
143			else if (v >= CKSEG1_BASE &&
144			    v < CKSEG1_BASE + CKSEG_SIZE)
145				allowed = is_memory_range(CKSEG1_TO_PHYS(v),
146				    (psize_t)c, CKSEG_SIZE);
147			/* ...otherwise, check it's within kernel kvm limits. */
148			else
149				allowed = uvm_kernacc((caddr_t)v, c,
150				    uio->uio_rw == UIO_READ ? B_READ : B_WRITE);
151
152			if (allowed) {
153				error = uiomove((caddr_t)v, c, uio);
154				continue;
155			} else {
156				return (EFAULT);
157			}
158
159		/* minor device 2 is /dev/null */
160		case 2:
161			if (uio->uio_rw == UIO_WRITE)
162				uio->uio_resid = 0;
163			return (0);
164
165		/* minor device 12 is /dev/zero */
166		case 12:
167			if (uio->uio_rw == UIO_WRITE) {
168				c = iov->iov_len;
169				break;
170			}
171			if (zeropage == NULL)
172				zeropage = malloc(PAGE_SIZE, M_TEMP,
173				    M_WAITOK | M_ZERO);
174			c = ulmin(iov->iov_len, PAGE_SIZE);
175			error = uiomove(zeropage, c, uio);
176			continue;
177
178		default:
179			return (ENODEV);
180		}
181		if (error)
182			break;
183		iov->iov_base += c;
184		iov->iov_len -= c;
185		uio->uio_offset += c;
186		uio->uio_resid -= c;
187	}
188	return error;
189}
190
191paddr_t
192mmmmap(dev_t dev, off_t off, int prot)
193{
194	return -1;
195}
196
197int
198mmioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
199{
200        switch (cmd) {
201        case FIONBIO:
202        case FIOASYNC:
203                /* handled by fd layer */
204                return 0;
205        }
206
207	return (EOPNOTSUPP);
208}
209