]> git.saurik.com Git - apple/xnu.git/blob - bsd/dev/i386/mem.c
f491b76eac7de83fd707b4fda32f44612cadb10c
[apple/xnu.git] / bsd / dev / i386 / mem.c
1 /*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /*-
24 * Copyright (c) 1988 University of Utah.
25 * Copyright (c) 1982, 1986, 1990, 1993
26 * The Regents of the University of California. All rights reserved.
27 *
28 * This code is derived from software contributed to Berkeley by
29 * the Systems Programming Group of the University of Utah Computer
30 * Science Department, and code derived from software contributed to
31 * Berkeley by William Jolitz.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed by the University of
44 * California, Berkeley and its contributors.
45 * 4. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 *
61 * from: Utah $Hdr: mem.c 1.13 89/10/08$
62 * @(#)mem.c 8.1 (Berkeley) 6/11/93
63 */
64
65 #include <mach_load.h>
66
67 /*
68 * Memory special file
69 */
70
71 #include <sys/param.h>
72 #include <sys/dir.h>
73 #include <sys/proc.h>
74 #include <sys/systm.h>
75 #include <sys/vm.h>
76 #include <sys/uio_internal.h>
77 #include <sys/malloc.h>
78
79 #include <mach/vm_types.h>
80 #include <mach/vm_param.h>
81 #include <vm/vm_kern.h> /* for kernel_map */
82
83 extern vm_offset_t kvtophys(vm_offset_t va);
84 extern boolean_t kernacc(off_t, size_t );
85
86 static caddr_t devzerobuf;
87
88 int mmread(dev_t dev, struct uio *uio);
89 int mmwrite(dev_t dev, struct uio *uio);
90 int mmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p);
91 int mmrw(dev_t dev, struct uio *uio, enum uio_rw rw);
92
93 int
94 mmread(dev_t dev, struct uio *uio)
95 {
96
97 return (mmrw(dev, uio, UIO_READ));
98 }
99
100 int
101 mmwrite(dev_t dev, struct uio *uio)
102 {
103
104 return (mmrw(dev, uio, UIO_WRITE));
105 }
106
107 int
108 mmioctl(__unused dev_t dev, u_long cmd, __unused caddr_t data,
109 __unused int flag, __unused struct proc *p)
110 {
111 switch (cmd) {
112 case FIONBIO:
113 case FIOASYNC:
114 /* OK to do nothing: we always return immediately */
115 break;
116 default:
117 return ENODEV;
118 }
119
120 return (0);
121 }
122
123 int
124 mmrw(dev_t dev, struct uio *uio, enum uio_rw rw)
125 {
126 register int o;
127 register u_int c, v;
128 int error = 0;
129 vm_offset_t where;
130 vm_size_t size;
131
132 while (uio_resid(uio) > 0 && error == 0) {
133 if (uio_iov_len(uio) == 0) {
134 uio_next_iov(uio);
135 uio->uio_iovcnt--;
136 if (uio->uio_iovcnt < 0)
137 panic("mmrw");
138 continue;
139 }
140 switch (minor(dev)) {
141
142 /* minor device 0 is physical memory */
143 case 0:
144 v = trunc_page(uio->uio_offset);
145 if (uio->uio_offset >= mem_size)
146 goto fault;
147
148 size= PAGE_SIZE;
149 if (kmem_alloc(kernel_map, &where, size)
150 != KERN_SUCCESS) {
151 goto fault;
152 }
153 o = uio->uio_offset - v;
154 // LP64todo - fix this!
155 c = min(PAGE_SIZE - o, (u_int)uio_iov_len(uio));
156 error = uiomove((caddr_t) (where + o), c, uio);
157 kmem_free(kernel_map, where, PAGE_SIZE);
158 continue;
159
160 /* minor device 1 is kernel memory */
161 case 1:
162 /* Do some sanity checking */
163 if (((vm_address_t)uio->uio_offset >= VM_MAX_KERNEL_ADDRESS) ||
164 ((vm_address_t)uio->uio_offset <= VM_MIN_KERNEL_ADDRESS))
165 goto fault;
166 c = uio_iov_len(uio);
167 if (!kernacc(uio->uio_offset, c))
168 goto fault;
169 error = uiomove((caddr_t)(uintptr_t)uio->uio_offset,
170 (int)c, uio);
171 continue;
172
173 /* minor device 2 is EOF/RATHOLE */
174 case 2:
175 if (rw == UIO_READ)
176 return (0);
177 c = uio_iov_len(uio);
178 break;
179 case 3:
180 if(devzerobuf == NULL) {
181 MALLOC(devzerobuf, caddr_t,PAGE_SIZE, M_TEMP, M_WAITOK);
182 bzero(devzerobuf, PAGE_SIZE);
183 }
184 if(uio->uio_rw == UIO_WRITE) {
185 c = uio_iov_len(uio);
186 break;
187 }
188 // LP64todo - fix this!
189 c = min(uio_iov_len(uio), PAGE_SIZE);
190 error = uiomove(devzerobuf, (int)c, uio);
191 continue;
192 default:
193 goto fault;
194 break;
195 }
196
197 if (error)
198 break;
199 uio_iov_base_add(uio, c);
200 uio_iov_len_add(uio, -((int)c));
201 uio->uio_offset += c;
202 uio_setresid(uio, (uio_resid(uio) - c));
203 }
204 return (error);
205 fault:
206 return (EFAULT);
207 }
208
209
210 boolean_t
211 kernacc(
212 off_t start,
213 size_t len
214 )
215 {
216 off_t base;
217 off_t end;
218
219 base = trunc_page(start);
220 end = start + len;
221
222 while (base < end) {
223 if(kvtophys((vm_offset_t)base) == 0ULL)
224 return(FALSE);
225 base += page_size;
226 }
227
228 return (TRUE);
229 }