xref: /freebsd/sys/amd64/amd64/mem.c (revision afe61c15161c324a7af299a9b8457aba5afc92db)
1 /*-
2  * Copyright (c) 1988 University of Utah.
3  * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * the Systems Programming Group of the University of Utah Computer
8  * Science Department, and code derived from software contributed to
9  * Berkeley by William Jolitz.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by the University of
22  *	California, Berkeley and its contributors.
23  * 4. Neither the name of the University nor the names of its contributors
24  *    may be used to endorse or promote products derived from this software
25  *    without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  *
39  *	from: Utah $Hdr: mem.c 1.13 89/10/08$
40  *	from: @(#)mem.c	7.2 (Berkeley) 5/9/91
41  *	$Id: mem.c,v 1.6 1993/12/19 00:50:06 wollman Exp $
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/systm.h>
52 #include <sys/uio.h>
53 #include <sys/malloc.h>
54 #include <sys/proc.h>
55 
56 #include <machine/cpu.h>
57 #include <machine/psl.h>
58 
59 #include <vm/vm_param.h>
60 #include <vm/lock.h>
61 #include <vm/vm_prot.h>
62 #include <vm/pmap.h>
63 
64 extern        char *ptvmmap;            /* poor name! */
65 /*ARGSUSED*/
66 int
67 mmclose(dev, uio, flags)
68 	dev_t dev;
69 	struct uio *uio;
70 	int flags;
71 {
72 	struct trapframe *fp;
73 
74 	switch (minor(dev)) {
75 	case 14:
76 		fp = (struct trapframe *)curproc->p_md.md_regs;
77 		fp->tf_eflags &= ~PSL_IOPL;
78 		break;
79 	default:
80 		break;
81 	}
82 	return(0);
83 }
84 /*ARGSUSED*/
85 int
86 mmopen(dev, uio, flags)
87 	dev_t dev;
88 	struct uio *uio;
89 	int flags;
90 {
91 	struct trapframe *fp;
92 
93 	switch (minor(dev)) {
94 	case 14:
95 		fp = (struct trapframe *)curproc->p_md.md_regs;
96 		fp->tf_eflags |= PSL_IOPL;
97 		break;
98 	default:
99 		break;
100 	}
101 	return(0);
102 }
103 /*ARGSUSED*/
104 int
105 mmrw(dev, uio, flags)
106 	dev_t dev;
107 	struct uio *uio;
108 	int flags;
109 {
110 	register int o;
111 	register u_int c, v;
112 	register struct iovec *iov;
113 	int error = 0;
114 	caddr_t zbuf = NULL;
115 
116 	while (uio->uio_resid > 0 && error == 0) {
117 		iov = uio->uio_iov;
118 		if (iov->iov_len == 0) {
119 			uio->uio_iov++;
120 			uio->uio_iovcnt--;
121 			if (uio->uio_iovcnt < 0)
122 				panic("mmrw");
123 			continue;
124 		}
125 		switch (minor(dev)) {
126 
127 /* minor device 0 is physical memory */
128 		case 0:
129 			v = uio->uio_offset;
130 			pmap_enter(kernel_pmap, (vm_offset_t)ptvmmap, v,
131 				uio->uio_rw == UIO_READ ? VM_PROT_READ : VM_PROT_WRITE,
132 				TRUE);
133 			o = (int)uio->uio_offset & PGOFSET;
134 			c = (u_int)(NBPG - ((int)iov->iov_base & PGOFSET));
135 			c = min(c, (u_int)(NBPG - o));
136 			c = min(c, (u_int)iov->iov_len);
137 			error = uiomove((caddr_t)&ptvmmap[o], (int)c, uio);
138 			pmap_remove(kernel_pmap, (vm_offset_t)ptvmmap,
139 				    (vm_offset_t)&ptvmmap[NBPG]);
140 			continue;
141 
142 /* minor device 1 is kernel memory */
143 		case 1:
144 			c = iov->iov_len;
145 			if (!kernacc((caddr_t)(int)uio->uio_offset, c,
146 			    uio->uio_rw == UIO_READ ? B_READ : B_WRITE))
147 				return(EFAULT);
148 			error = uiomove((caddr_t)(int)uio->uio_offset, (int)c, uio);
149 			continue;
150 
151 /* minor device 2 is EOF/RATHOLE */
152 		case 2:
153 			if (uio->uio_rw == UIO_READ)
154 				return (0);
155 			c = iov->iov_len;
156 			break;
157 
158 /* minor device 12 (/dev/zero) is source of nulls on read, rathole on write */
159 		case 12:
160 			if (uio->uio_rw == UIO_WRITE) {
161 				c = iov->iov_len;
162 				break;
163 			}
164 			if (zbuf == NULL) {
165 				zbuf = (caddr_t)
166 				    malloc(CLBYTES, M_TEMP, M_WAITOK);
167 				bzero(zbuf, CLBYTES);
168 			}
169 			c = min(iov->iov_len, CLBYTES);
170 			error = uiomove(zbuf, (int)c, uio);
171 			continue;
172 
173 #ifdef notyet
174 /* 386 I/O address space (/dev/ioport[bwl]) is a read/write access to seperate
175    i/o device address bus, different than memory bus. Semantics here are
176    very different than ordinary read/write, as if iov_len is a multiple
177    an implied string move from a single port will be done. Note that lseek
178    must be used to set the port number reliably. */
179 		case 14:
180 			if (iov->iov_len == 1) {
181 				u_char tmp;
182 				tmp = inb(uio->uio_offset);
183 				error = uiomove (&tmp, iov->iov_len, uio);
184 			} else {
185 				if (!useracc((caddr_t)iov->iov_base,
186 					iov->iov_len, uio->uio_rw))
187 					return (EFAULT);
188 				insb(uio->uio_offset, iov->iov_base,
189 					iov->iov_len);
190 			}
191 			break;
192 		case 15:
193 			if (iov->iov_len == sizeof (short)) {
194 				u_short tmp;
195 				tmp = inw(uio->uio_offset);
196 				error = uiomove (&tmp, iov->iov_len, uio);
197 			} else {
198 				if (!useracc((caddr_t)iov->iov_base,
199 					iov->iov_len, uio->uio_rw))
200 					return (EFAULT);
201 				insw(uio->uio_offset, iov->iov_base,
202 					iov->iov_len/ sizeof (short));
203 			}
204 			break;
205 		case 16:
206 			if (iov->iov_len == sizeof (long)) {
207 				u_long tmp;
208 				tmp = inl(uio->uio_offset);
209 				error = uiomove (&tmp, iov->iov_len, uio);
210 			} else {
211 				if (!useracc((caddr_t)iov->iov_base,
212 					iov->iov_len, uio->uio_rw))
213 					return (EFAULT);
214 				insl(uio->uio_offset, iov->iov_base,
215 					iov->iov_len/ sizeof (long));
216 			}
217 			break;
218 #endif
219 
220 		default:
221 			return (ENXIO);
222 		}
223 		if (error)
224 			break;
225 		iov->iov_base += c;
226 		iov->iov_len -= c;
227 		uio->uio_offset += c;
228 		uio->uio_resid -= c;
229 	}
230 	if (zbuf)
231 		free(zbuf, M_TEMP);
232 	return (error);
233 }
234 
235 
236 
237 
238 /*******************************************************\
239 * allow user processes to MMAP some memory sections	*
240 * instead of going through read/write			*
241 \*******************************************************/
242 int memmmap(dev_t dev, int offset, int nprot)
243 {
244 	switch (minor(dev))
245 	{
246 
247 /* minor device 0 is physical memory */
248 	case 0:
249         	return i386_btop(offset);
250 
251 /* minor device 1 is kernel memory */
252 	case 1:
253         	return i386_btop(vtophys(offset));
254 
255 	default:
256 		return -1;
257 	}
258 }
259 
260