xref: /openbsd/sys/arch/sh/sh/mem.c (revision b9ae17a0)
1 /*	$OpenBSD: mem.c,v 1.15 2024/12/30 02:46:00 guenther Exp $	*/
2 /*	$NetBSD: mem.c,v 1.21 2006/07/23 22:06:07 ad Exp $	*/
3 
4 /*
5  * Copyright (c) 2002 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  * Copyright (c) 1982, 1986, 1990, 1993
8  *	The Regents of the University of California.  All rights reserved.
9  *
10  * This code is derived from software contributed to Berkeley by
11  * the Systems Programming Group of the University of Utah Computer
12  * Science Department.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  * 3. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  *	@(#)mem.c	8.3 (Berkeley) 1/12/94
39  */
40 
41 /*
42  * Copyright (c) 1988 University of Utah.
43  *
44  * This code is derived from software contributed to Berkeley by
45  * the Systems Programming Group of the University of Utah Computer
46  * Science Department.
47  *
48  * Redistribution and use in source and binary forms, with or without
49  * modification, are permitted provided that the following conditions
50  * are met:
51  * 1. Redistributions of source code must retain the above copyright
52  *    notice, this list of conditions and the following disclaimer.
53  * 2. Redistributions in binary form must reproduce the above copyright
54  *    notice, this list of conditions and the following disclaimer in the
55  *    documentation and/or other materials provided with the distribution.
56  * 3. All advertising materials mentioning features or use of this software
57  *    must display the following acknowledgement:
58  *	This product includes software developed by the University of
59  *	California, Berkeley and its contributors.
60  * 4. Neither the name of the University nor the names of its contributors
61  *    may be used to endorse or promote products derived from this software
62  *    without specific prior written permission.
63  *
64  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
65  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
66  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
67  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
68  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
69  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
70  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
71  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
72  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
73  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
74  * SUCH DAMAGE.
75  *
76  *	@(#)mem.c	8.3 (Berkeley) 1/12/94
77  */
78 
79 /*
80  * Memory special file
81  */
82 
83 #include <sys/param.h>
84 #include <sys/systm.h>
85 #include <sys/buf.h>
86 #include <sys/filio.h>
87 #include <sys/uio.h>
88 #include <sys/malloc.h>
89 #include <sys/proc.h>
90 #include <sys/conf.h>
91 #include <sys/atomic.h>
92 
93 #include <uvm/uvm_extern.h>
94 
95 caddr_t zeropage;
96 boolean_t __mm_mem_addr(paddr_t);
97 
98 #define mmread	mmrw
99 #define mmwrite	mmrw
100 cdev_decl(mm);
101 
102 
103 int
mmopen(dev_t dev,int flag,int mode,struct proc * p)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 	default:
119 		return (ENXIO);
120 	}
121 	return (0);
122 }
123 
124 int
mmclose(dev_t dev,int flag,int mode,struct proc * p)125 mmclose(dev_t dev, int flag, int mode, struct proc *p)
126 {
127 	return (0);
128 }
129 
130 int
mmrw(dev_t dev,struct uio * uio,int flags)131 mmrw(dev_t dev, struct uio *uio, int flags)
132 {
133 	struct iovec *iov;
134 	vaddr_t v, o;
135 	size_t c;
136 	int error = 0;
137 
138 	while (uio->uio_resid > 0 && !error) {
139 		iov = uio->uio_iov;
140 		if (iov->iov_len == 0) {
141 			uio->uio_iov++;
142 			uio->uio_iovcnt--;
143 			if (uio->uio_iovcnt < 0)
144 				panic("mmrw");
145 			continue;
146 		}
147 
148 		v = uio->uio_offset;
149 
150 		switch (minor(dev)) {
151 		case 0:
152 			/* Physical address */
153 			if (__mm_mem_addr(v)) {
154 				o = v & PGOFSET;
155 				c = ulmin(uio->uio_resid, PAGE_SIZE - o);
156 				error = uiomove((caddr_t)SH3_PHYS_TO_P1SEG(v),
157 				    c, uio);
158 			} else {
159 				return (EFAULT);
160 			}
161 			break;
162 
163 		case 1:
164 			if (v < SH3_P1SEG_BASE)			/* P0 */
165 				return (EFAULT);
166 			if (v < SH3_P2SEG_BASE) {		/* P1 */
167 				/* permitted */
168 			/*
169 				if (__mm_mem_addr(SH3_P1SEG_TO_PHYS(v))
170 				    == FALSE)
171 					return (EFAULT);
172 			*/
173 				c = ulmin(iov->iov_len, MAXPHYS);
174 				error = uiomove((caddr_t)v, c, uio);
175 			} else if (v < SH3_P3SEG_BASE)		/* P2 */
176 				return (EFAULT);
177 			else {					/* P3 */
178 				c = ulmin(iov->iov_len, MAXPHYS);
179 				if (!uvm_kernacc((void *)v, c,
180 				    uio->uio_rw == UIO_READ ? B_READ : B_WRITE))
181 					return (EFAULT);
182 				error = uiomove((caddr_t)v, c, uio);
183 			}
184 			break;
185 
186 		case 2:
187 			if (uio->uio_rw == UIO_WRITE)
188 				uio->uio_resid = 0;
189 			return (0);
190 
191 		case 12:
192 			if (uio->uio_rw == UIO_WRITE) {
193 				uio->uio_resid = 0;
194 				return (0);
195 			}
196 			if (zeropage == NULL)
197 				zeropage = malloc(PAGE_SIZE, M_TEMP,
198 				    M_WAITOK | M_ZERO);
199 			c = ulmin(iov->iov_len, PAGE_SIZE);
200 			error = uiomove(zeropage, c, uio);
201 			break;
202 
203 		default:
204 			return (ENXIO);
205 		}
206 	}
207 
208 	return (error);
209 }
210 
211 paddr_t
mmmmap(dev_t dev,off_t off,int prot)212 mmmmap(dev_t dev, off_t off, int prot)
213 {
214 	struct proc *p = curproc;
215 
216 	if (minor(dev) != 0)
217 		return (-1);
218 
219 	if (__mm_mem_addr((paddr_t)off) == FALSE && suser(p) != 0)
220 		return (-1);
221 	return ((paddr_t)off);
222 }
223 
224 int
mmioctl(dev_t dev,u_long cmd,caddr_t data,int flags,struct proc * p)225 mmioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
226 {
227         switch (cmd) {
228         case FIOASYNC:
229                 /* handled by fd layer */
230                 return 0;
231         }
232 
233 	return (ENOTTY);
234 }
235 
236 /*
237  * boolean_t __mm_mem_addr(paddr_t pa):
238  *	Check specified physical address is in physical memory, with the
239  *	kernel image off-limits.
240  */
241 boolean_t
__mm_mem_addr(paddr_t pa)242 __mm_mem_addr(paddr_t pa)
243 {
244 #if 0
245 	extern vaddr_t kernend; /* from machdep.c */
246 #endif
247 	struct vm_physseg *seg;
248 	unsigned int segno;
249 
250 	for (segno = 0, seg = vm_physmem; segno < vm_nphysseg; segno++, seg++) {
251 		if (pa < seg->start || pa >= seg->end)
252 			continue;
253 
254 #if 0
255 		/*
256 		 * This assumes the kernel image occupies the beginning of a
257 		 * memory segment.
258 		 */
259 		if (kernend >= seg->start && kernend < seg->end) {
260 			if (pa < kernend)
261 				return (FALSE);
262 		}
263 #endif
264 
265 		return (TRUE);
266 	}
267 
268 	return (FALSE);
269 }
270