]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kern_subr.c
xnu-517.3.15.tar.gz
[apple/xnu.git] / bsd / kern / kern_subr.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
43866e37 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
43866e37
A
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
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
43866e37
A
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.
1c79356b
A
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>
55e303ae 71#include <vm/pmap.h>
1c79356b
A
72
73#include <kdebug.h>
74
75#include <sys/kdebug.h>
76#define DBG_UIO_COPYOUT 16
77#define DBG_UIO_COPYIN 17
78
de355530 79
1c79356b
A
80int
81uiomove(cp, n, uio)
82 register caddr_t cp;
83 register int n;
84 register struct uio *uio;
55e303ae
A
85{
86 return uiomove64((addr64_t)((unsigned int)cp), n, uio);
87}
88
89int
90uiomove64(addr64_t cp, int n, struct uio *uio)
1c79356b
A
91{
92 register struct iovec *iov;
93 u_int cnt;
94 int error = 0;
95
96#if DIAGNOSTIC
97 if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE)
98 panic("uiomove: mode");
99 if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != current_proc())
100 panic("uiomove proc");
101#endif
102
103 while (n > 0 && uio->uio_resid) {
104 iov = uio->uio_iov;
105 cnt = iov->iov_len;
106 if (cnt == 0) {
107 uio->uio_iov++;
108 uio->uio_iovcnt--;
109 continue;
110 }
111 if (cnt > n)
112 cnt = n;
113 switch (uio->uio_segflg) {
114
115 case UIO_USERSPACE:
116 case UIO_USERISPACE:
117 if (uio->uio_rw == UIO_READ)
118 {
119 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYOUT)) | DBG_FUNC_START,
55e303ae 120 (int)cp, (int)iov->iov_base, cnt, 0,0);
1c79356b 121
55e303ae 122 error = copyout( CAST_DOWN(caddr_t, cp), iov->iov_base, cnt );
1c79356b
A
123
124 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYOUT)) | DBG_FUNC_END,
55e303ae 125 (int)cp, (int)iov->iov_base, cnt, 0,0);
1c79356b
A
126 }
127 else
128 {
129 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYIN)) | DBG_FUNC_START,
55e303ae 130 (int)iov->iov_base, (int)cp, cnt, 0,0);
1c79356b 131
55e303ae 132 error = copyin(iov->iov_base, CAST_DOWN(caddr_t, cp), cnt);
1c79356b
A
133
134 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYIN)) | DBG_FUNC_END,
55e303ae 135 (int)iov->iov_base, (int)cp, cnt, 0,0);
1c79356b
A
136 }
137 if (error)
138 return (error);
139 break;
140
141 case UIO_SYSSPACE:
142 if (uio->uio_rw == UIO_READ)
55e303ae 143 error = copywithin(CAST_DOWN(caddr_t, cp), iov->iov_base,
1c79356b
A
144 cnt);
145 else
55e303ae 146 error = copywithin(iov->iov_base, CAST_DOWN(caddr_t, cp),
1c79356b
A
147 cnt);
148 break;
9bccf70c 149
1c79356b
A
150 case UIO_PHYS_USERSPACE:
151 if (uio->uio_rw == UIO_READ)
152 {
153 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYOUT)) | DBG_FUNC_START,
55e303ae
A
154 (int)cp, (int)iov->iov_base, cnt, 1,0);
155
156 if (error = copypv((addr64_t)cp, (addr64_t)((unsigned int)iov->iov_base), cnt, cppvPsrc | cppvNoRefSrc)) /* Copy physical to virtual */
157 error = EFAULT;
158
159 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYOUT)) | DBG_FUNC_END,
160 (int)cp, (int)iov->iov_base, cnt, 1,0);
161 }
162 else
163 {
164 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYIN)) | DBG_FUNC_START,
165 (int)iov->iov_base, (int)cp, cnt, 1,0);
1c79356b 166
55e303ae
A
167 if (error = copypv((addr64_t)((unsigned int)iov->iov_base), (addr64_t)cp, cnt, cppvPsnk | cppvNoRefSrc | cppvNoModSnk)) /* Copy virtual to physical */
168 error = EFAULT;
169
170 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYIN)) | DBG_FUNC_END,
171 (int)iov->iov_base, (int)cp, cnt, 1,0);
172 }
173 if (error)
174 return (error);
175 break;
176
177 case UIO_PHYS_SYSSPACE:
178 if (uio->uio_rw == UIO_READ)
179 {
180 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYOUT)) | DBG_FUNC_START,
181 (int)cp, (int)iov->iov_base, cnt, 2,0);
de355530 182
55e303ae
A
183 if (error = copypv((addr64_t)cp, (addr64_t)((unsigned int)iov->iov_base), cnt, cppvKmap | cppvPsrc | cppvNoRefSrc)) /* Copy physical to virtual */
184 error = EFAULT;
1c79356b
A
185
186 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYOUT)) | DBG_FUNC_END,
55e303ae 187 (int)cp, (int)iov->iov_base, cnt, 2,0);
1c79356b
A
188 }
189 else
190 {
191 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYIN)) | DBG_FUNC_START,
55e303ae 192 (int)iov->iov_base, (int)cp, cnt, 2,0);
1c79356b 193
55e303ae
A
194 if (error = copypv((addr64_t)((unsigned int)iov->iov_base), (addr64_t)cp, cnt, cppvKmap | cppvPsnk | cppvNoRefSrc | cppvNoModSnk)) /* Copy virtual to physical */
195 error = EFAULT;
1c79356b
A
196
197 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, DBG_UIO_COPYIN)) | DBG_FUNC_END,
55e303ae 198 (int)iov->iov_base, (int)cp, cnt, 2,0);
1c79356b
A
199 }
200 if (error)
201 return (error);
202 break;
1c79356b
A
203 }
204 iov->iov_base += cnt;
205 iov->iov_len -= cnt;
206 uio->uio_resid -= cnt;
207 uio->uio_offset += cnt;
208 cp += cnt;
209 n -= cnt;
210 }
211 return (error);
212}
213
214/*
215 * Give next character to user as result of read.
216 */
217int
218ureadc(c, uio)
219 register int c;
220 register struct uio *uio;
221{
222 register struct iovec *iov;
223
224 if (uio->uio_resid <= 0)
225 panic("ureadc: non-positive resid");
226again:
227 if (uio->uio_iovcnt == 0)
228 panic("ureadc: non-positive iovcnt");
229 iov = uio->uio_iov;
230 if (iov->iov_len <= 0) {
231 uio->uio_iovcnt--;
232 uio->uio_iov++;
233 goto again;
234 }
235 switch (uio->uio_segflg) {
236
237 case UIO_USERSPACE:
238 if (subyte(iov->iov_base, c) < 0)
239 return (EFAULT);
240 break;
241
242 case UIO_SYSSPACE:
243 *iov->iov_base = c;
244 break;
245
246 case UIO_USERISPACE:
247 if (suibyte(iov->iov_base, c) < 0)
248 return (EFAULT);
249 break;
250 }
251 iov->iov_base++;
252 iov->iov_len--;
253 uio->uio_resid--;
254 uio->uio_offset++;
255 return (0);
256}
257
258#if defined(vax) || defined(ppc)
259/* unused except by ct.c, other oddities XXX */
260/*
261 * Get next character written in by user from uio.
262 */
263uwritec(uio)
264 struct uio *uio;
265{
266 register struct iovec *iov;
267 register int c;
268
269 if (uio->uio_resid <= 0)
270 return (-1);
271again:
272 if (uio->uio_iovcnt <= 0)
273 panic("uwritec: non-positive iovcnt");
274 iov = uio->uio_iov;
275 if (iov->iov_len == 0) {
276 uio->uio_iov++;
277 if (--uio->uio_iovcnt == 0)
278 return (-1);
279 goto again;
280 }
281 switch (uio->uio_segflg) {
282
283 case UIO_USERSPACE:
284 c = fubyte(iov->iov_base);
285 break;
286
287 case UIO_SYSSPACE:
288 c = *iov->iov_base & 0377;
289 break;
290
291 case UIO_USERISPACE:
292 c = fuibyte(iov->iov_base);
293 break;
294
295 default:
296 c = 0; /* avoid uninitialized variable warning */
297 panic("uwritec: bogus uio_segflg");
298 break;
299 }
300 if (c < 0)
301 return (-1);
302 iov->iov_base++;
303 iov->iov_len--;
304 uio->uio_resid--;
305 uio->uio_offset++;
306 return (c);
307}
308#endif /* vax || ppc */
309
310/*
311 * General routine to allocate a hash table.
312 */
313void *
314hashinit(elements, type, hashmask)
315 int elements, type;
316 u_long *hashmask;
317{
318 long hashsize;
319 LIST_HEAD(generic, generic) *hashtbl;
320 int i;
321
322 if (elements <= 0)
323 panic("hashinit: bad cnt");
324 for (hashsize = 1; hashsize <= elements; hashsize <<= 1)
325 continue;
326 hashsize >>= 1;
327 MALLOC(hashtbl, struct generic *,
328 (u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK);
329 bzero(hashtbl, (u_long)hashsize * sizeof(*hashtbl));
330 for (i = 0; i < hashsize; i++)
331 LIST_INIT(&hashtbl[i]);
332 *hashmask = hashsize - 1;
333 return (hashtbl);
334}