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