xref: /openbsd-src/sys/arch/arm64/arm64/mem.c (revision b9ae17a00bed12afbf856d60e03f648694a9de20)
1 /*	$OpenBSD: mem.c,v 1.10 2024/12/30 02:46:00 guenther Exp $	*/
2 /*	$NetBSD: mem.c,v 1.11 2003/10/16 12:02:58 jdolecek Exp $	*/
3 
4 /*
5  * Copyright (c) 1982, 1986, 1990, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * the Systems Programming Group of the University of Utah Computer
10  * Science Department.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36 /*
37  * Copyright (c) 1988 University of Utah.
38  *
39  * This code is derived from software contributed to Berkeley by
40  * the Systems Programming Group of the University of Utah Computer
41  * Science Department.
42  *
43  * Redistribution and use in source and binary forms, with or without
44  * modification, are permitted provided that the following conditions
45  * are met:
46  * 1. Redistributions of source code must retain the above copyright
47  *    notice, this list of conditions and the following disclaimer.
48  * 2. Redistributions in binary form must reproduce the above copyright
49  *    notice, this list of conditions and the following disclaimer in the
50  *    documentation and/or other materials provided with the distribution.
51  * 3. All advertising materials mentioning features or use of this software
52  *    must display the following acknowledgement:
53  *	This product includes software developed by the University of
54  *	California, Berkeley and its contributors.
55  * 4. Neither the name of the University nor the names of its contributors
56  *    may be used to endorse or promote products derived from this software
57  *    without specific prior written permission.
58  *
59  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69  * SUCH DAMAGE.
70  */
71 
72 /*
73  * Memory special file
74  */
75 
76 #include <sys/param.h>
77 #include <sys/conf.h>
78 #include <sys/buf.h>
79 #include <sys/filio.h>
80 #include <sys/systm.h>
81 #include <sys/uio.h>
82 #include <sys/malloc.h>
83 #include <sys/proc.h>
84 #include <sys/fcntl.h>
85 #include <sys/rwlock.h>
86 #include <sys/atomic.h>
87 
88 #include <machine/cpu.h>
89 #include <arm64/conf.h>
90 
91 #include <uvm/uvm_extern.h>
92 
93 caddr_t zeropage;
94 
95 /* open counter for aperture */
96 #ifdef APERTURE
97 static int ap_open_count = 0;
98 extern int allowaperture;
99 #endif
100 
101 static struct rwlock physlock = RWLOCK_INITIALIZER("mmrw");
102 
103 int
104 mmopen(dev_t dev, int flag, int mode, struct proc *p)
105 {
106 	extern int allowkmem;
107 
108 	switch (minor(dev)) {
109 	case 0:
110 	case 1:
111 		if ((int)atomic_load_int(&securelevel) <= 0 ||
112 		    atomic_load_int(&allowkmem))
113 			break;
114 		return (EPERM);
115 	case 2:
116 	case 12:
117 		break;
118 #ifdef APERTURE
119 	case 4:
120 		if (suser(p) != 0 || !allowaperture)
121 			return (EPERM);
122 
123 		/* authorize only one simultaneous open() unless
124 		 * allowaperture=3 */
125 		if (ap_open_count > 0 && allowaperture < 3)
126 			return (EPERM);
127 		ap_open_count++;
128 		break;
129 #endif
130 	default:
131 		return (ENXIO);
132 	}
133 	return (0);
134 }
135 
136 int
137 mmclose(dev_t dev, int flag, int mode, struct proc *p)
138 {
139 #ifdef APERTURE
140 	if (minor(dev) == 4)
141 		ap_open_count = 0;
142 #endif
143 	return (0);
144 }
145 
146 int
147 mmrw(dev_t dev, struct uio *uio, int flags)
148 {
149 	vaddr_t o, v;
150 	size_t c;
151 	struct iovec *iov;
152 	int error = 0;
153 	vm_prot_t prot;
154 	extern caddr_t vmmap;
155 
156 	if (minor(dev) == 0) {
157 		/* lock against other uses of shared vmmap */
158 		error = rw_enter(&physlock, RW_WRITE | RW_INTR);
159 		if (error)
160 			return (error);
161 	}
162 	while (uio->uio_resid > 0 && error == 0) {
163 		iov = uio->uio_iov;
164 		if (iov->iov_len == 0) {
165 			uio->uio_iov++;
166 			uio->uio_iovcnt--;
167 			if (uio->uio_iovcnt < 0)
168 				panic("mmrw");
169 			continue;
170 		}
171 		switch (minor(dev)) {
172 
173 		case 0:
174 			v = uio->uio_offset;
175 			prot = uio->uio_rw == UIO_READ ? PROT_READ :
176 			    PROT_WRITE;
177 			pmap_enter(pmap_kernel(), (vaddr_t)vmmap,
178 			    trunc_page(v), prot, prot|PMAP_WIRED);
179 			pmap_update(pmap_kernel());
180 			o = uio->uio_offset & PGOFSET;
181 			c = ulmin(uio->uio_resid, PAGE_SIZE - o);
182 			error = uiomove((caddr_t)vmmap + o, c, uio);
183 			pmap_remove(pmap_kernel(), (vaddr_t)vmmap,
184 			    (vaddr_t)vmmap + PAGE_SIZE);
185 			pmap_update(pmap_kernel());
186 			break;
187 
188 		case 1:
189 			v = uio->uio_offset;
190 			c = ulmin(iov->iov_len, MAXPHYS);
191 			if (!uvm_kernacc((caddr_t)v, c,
192 			    uio->uio_rw == UIO_READ ? B_READ : B_WRITE))
193 				return (EFAULT);
194 			error = uiomove((caddr_t)v, c, uio);
195 			break;
196 
197 		case 2:
198 			if (uio->uio_rw == UIO_WRITE)
199 				uio->uio_resid = 0;
200 			return (0);
201 
202 		case 12:
203 			if (uio->uio_rw == UIO_WRITE) {
204 				uio->uio_resid = 0;
205 				return (0);
206 			}
207 			if (zeropage == NULL)
208 				zeropage = malloc(PAGE_SIZE, M_TEMP,
209 				    M_WAITOK | M_ZERO);
210 			c = ulmin(iov->iov_len, PAGE_SIZE);
211 			error = uiomove(zeropage, c, uio);
212 			break;
213 
214 		default:
215 			return (ENXIO);
216 		}
217 	}
218 	if (minor(dev) == 0) {
219 		rw_exit(&physlock);
220 	}
221 	return (error);
222 }
223 
224 paddr_t
225 mmmmap(dev_t dev, off_t off, int prot)
226 {
227 	struct proc *p = curproc;	/* XXX */
228 
229 	/*
230 	 * /dev/mem is the only one that makes sense through this
231 	 * interface.  For /dev/kmem any physaddr we return here
232 	 * could be transient and hence incorrect or invalid at
233 	 * a later time.  /dev/null just doesn't make any sense
234 	 * and /dev/zero is a hack that is handled via the default
235 	 * pager in mmap().
236 	 */
237 	if (minor(dev) != 0)
238 		return (-1);
239 
240 	/* minor device 0 is physical memory */
241 
242 	if ((paddr_t)off >= ptoa((paddr_t)physmem) &&
243 	    suser(p) != 0)
244 		return -1;
245 	return off;
246 }
247 
248 int
249 mmioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
250 {
251         switch (cmd) {
252         case FIOASYNC:
253                 /* handled by fd layer */
254                 return 0;
255         }
256 
257 	return (ENOTTY);
258 }
259