]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_subr.c
xnu-517.9.4.tar.gz
[apple/xnu.git] / bsd / kern / kern_subr.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
23 /*
24 * Copyright (c) 1982, 1986, 1991, 1993
25 * The Regents of the University of California. All rights reserved.
26 * (c) UNIX System Laboratories, Inc.
27 * All or some portions of this file are derived from material licensed
28 * to the University of California by American Telephone and Telegraph
29 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
30 * the permission of UNIX System Laboratories, Inc.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94
61 */
62
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/proc.h>
66 #include <sys/malloc.h>
67 #include <sys/queue.h>
68 #include <vm/pmap.h>
69
70 #include <kdebug.h>
71
72 #include <sys/kdebug.h>
73 #define DBG_UIO_COPYOUT 16
74 #define DBG_UIO_COPYIN 17
75
76
77 int
78 uiomove(cp, n, uio)
79 register caddr_t cp;
80 register int n;
81 register struct uio *uio;
82 {
83 return uiomove64((addr64_t)((unsigned int)cp), n, uio);
84 }
85
86 int
87 uiomove64(addr64_t cp, int n, struct uio *uio)
88 {
89 register struct iovec *iov;
90 u_int cnt;
91 int error = 0;
92
93 #if DIAGNOSTIC
94 if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE)
95 panic("uiomove: mode");
96 if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != current_proc())
97 panic("uiomove proc");
98 #endif
99
100 while (n > 0 && uio->uio_resid) {
101 iov = uio->uio_iov;
102 cnt = iov->iov_len;
103 if (cnt == 0) {
104 uio->uio_iov++;
105 uio->uio_iovcnt--;
106 continue;
107 }
108 if (cnt > n)
109 cnt = n;
110 switch (uio->uio_segflg) {
111
112 case UIO_USERSPACE:
113 case UIO_USERISPACE:
114 if (uio->uio_rw == UIO_READ)
115 {
116 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYOUT)) | DBG_FUNC_START,
117 (int)cp, (int)iov->iov_base, cnt, 0,0);
118
119 error = copyout( CAST_DOWN(caddr_t, cp), iov->iov_base, cnt );
120
121 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYOUT)) | DBG_FUNC_END,
122 (int)cp, (int)iov->iov_base, cnt, 0,0);
123 }
124 else
125 {
126 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYIN)) | DBG_FUNC_START,
127 (int)iov->iov_base, (int)cp, cnt, 0,0);
128
129 error = copyin(iov->iov_base, CAST_DOWN(caddr_t, cp), cnt);
130
131 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYIN)) | DBG_FUNC_END,
132 (int)iov->iov_base, (int)cp, cnt, 0,0);
133 }
134 if (error)
135 return (error);
136 break;
137
138 case UIO_SYSSPACE:
139 if (uio->uio_rw == UIO_READ)
140 error = copywithin(CAST_DOWN(caddr_t, cp), iov->iov_base,
141 cnt);
142 else
143 error = copywithin(iov->iov_base, CAST_DOWN(caddr_t, cp),
144 cnt);
145 break;
146
147 case UIO_PHYS_USERSPACE:
148 if (uio->uio_rw == UIO_READ)
149 {
150 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYOUT)) | DBG_FUNC_START,
151 (int)cp, (int)iov->iov_base, cnt, 1,0);
152
153 if (error = copypv((addr64_t)cp, (addr64_t)((unsigned int)iov->iov_base), cnt, cppvPsrc | cppvNoRefSrc)) /* Copy physical to virtual */
154 error = EFAULT;
155
156 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYOUT)) | DBG_FUNC_END,
157 (int)cp, (int)iov->iov_base, cnt, 1,0);
158 }
159 else
160 {
161 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYIN)) | DBG_FUNC_START,
162 (int)iov->iov_base, (int)cp, cnt, 1,0);
163
164 if (error = copypv((addr64_t)((unsigned int)iov->iov_base), (addr64_t)cp, cnt, cppvPsnk | cppvNoRefSrc | cppvNoModSnk)) /* Copy virtual to physical */
165 error = EFAULT;
166
167 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYIN)) | DBG_FUNC_END,
168 (int)iov->iov_base, (int)cp, cnt, 1,0);
169 }
170 if (error)
171 return (error);
172 break;
173
174 case UIO_PHYS_SYSSPACE:
175 if (uio->uio_rw == UIO_READ)
176 {
177 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYOUT)) | DBG_FUNC_START,
178 (int)cp, (int)iov->iov_base, cnt, 2,0);
179
180 if (error = copypv((addr64_t)cp, (addr64_t)((unsigned int)iov->iov_base), cnt, cppvKmap | cppvPsrc | cppvNoRefSrc)) /* Copy physical to virtual */
181 error = EFAULT;
182
183 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYOUT)) | DBG_FUNC_END,
184 (int)cp, (int)iov->iov_base, cnt, 2,0);
185 }
186 else
187 {
188 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYIN)) | DBG_FUNC_START,
189 (int)iov->iov_base, (int)cp, cnt, 2,0);
190
191 if (error = copypv((addr64_t)((unsigned int)iov->iov_base), (addr64_t)cp, cnt, cppvKmap | cppvPsnk | cppvNoRefSrc | cppvNoModSnk)) /* Copy virtual to physical */
192 error = EFAULT;
193
194 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYIN)) | DBG_FUNC_END,
195 (int)iov->iov_base, (int)cp, cnt, 2,0);
196 }
197 if (error)
198 return (error);
199 break;
200 }
201 iov->iov_base += cnt;
202 iov->iov_len -= cnt;
203 uio->uio_resid -= cnt;
204 uio->uio_offset += cnt;
205 cp += cnt;
206 n -= cnt;
207 }
208 return (error);
209 }
210
211 /*
212 * Give next character to user as result of read.
213 */
214 int
215 ureadc(c, uio)
216 register int c;
217 register struct uio *uio;
218 {
219 register struct iovec *iov;
220
221 if (uio->uio_resid <= 0)
222 panic("ureadc: non-positive resid");
223 again:
224 if (uio->uio_iovcnt == 0)
225 panic("ureadc: non-positive iovcnt");
226 iov = uio->uio_iov;
227 if (iov->iov_len <= 0) {
228 uio->uio_iovcnt--;
229 uio->uio_iov++;
230 goto again;
231 }
232 switch (uio->uio_segflg) {
233
234 case UIO_USERSPACE:
235 if (subyte(iov->iov_base, c) < 0)
236 return (EFAULT);
237 break;
238
239 case UIO_SYSSPACE:
240 *iov->iov_base = c;
241 break;
242
243 case UIO_USERISPACE:
244 if (suibyte(iov->iov_base, c) < 0)
245 return (EFAULT);
246 break;
247 }
248 iov->iov_base++;
249 iov->iov_len--;
250 uio->uio_resid--;
251 uio->uio_offset++;
252 return (0);
253 }
254
255 #if defined(vax) || defined(ppc)
256 /* unused except by ct.c, other oddities XXX */
257 /*
258 * Get next character written in by user from uio.
259 */
260 uwritec(uio)
261 struct uio *uio;
262 {
263 register struct iovec *iov;
264 register int c;
265
266 if (uio->uio_resid <= 0)
267 return (-1);
268 again:
269 if (uio->uio_iovcnt <= 0)
270 panic("uwritec: non-positive iovcnt");
271 iov = uio->uio_iov;
272 if (iov->iov_len == 0) {
273 uio->uio_iov++;
274 if (--uio->uio_iovcnt == 0)
275 return (-1);
276 goto again;
277 }
278 switch (uio->uio_segflg) {
279
280 case UIO_USERSPACE:
281 c = fubyte(iov->iov_base);
282 break;
283
284 case UIO_SYSSPACE:
285 c = *iov->iov_base & 0377;
286 break;
287
288 case UIO_USERISPACE:
289 c = fuibyte(iov->iov_base);
290 break;
291
292 default:
293 c = 0; /* avoid uninitialized variable warning */
294 panic("uwritec: bogus uio_segflg");
295 break;
296 }
297 if (c < 0)
298 return (-1);
299 iov->iov_base++;
300 iov->iov_len--;
301 uio->uio_resid--;
302 uio->uio_offset++;
303 return (c);
304 }
305 #endif /* vax || ppc */
306
307 /*
308 * General routine to allocate a hash table.
309 */
310 void *
311 hashinit(elements, type, hashmask)
312 int elements, type;
313 u_long *hashmask;
314 {
315 long hashsize;
316 LIST_HEAD(generic, generic) *hashtbl;
317 int i;
318
319 if (elements <= 0)
320 panic("hashinit: bad cnt");
321 for (hashsize = 1; hashsize <= elements; hashsize <<= 1)
322 continue;
323 hashsize >>= 1;
324 MALLOC(hashtbl, struct generic *,
325 (u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK);
326 bzero(hashtbl, (u_long)hashsize * sizeof(*hashtbl));
327 for (i = 0; i < hashsize; i++)
328 LIST_INIT(&hashtbl[i]);
329 *hashmask = hashsize - 1;
330 return (hashtbl);
331 }