1 /* 2 * Copyright (c) 1982, 1986, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94 39 * $FreeBSD: src/sys/kern/kern_subr.c,v 1.31.2.2 2002/04/21 08:09:37 bde Exp $ 40 * $DragonFly: src/sys/kern/kern_subr.c,v 1.27 2007/01/29 20:44:02 tgen Exp $ 41 */ 42 43 #include "opt_ddb.h" 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/kernel.h> 48 #include <sys/proc.h> 49 #include <sys/malloc.h> 50 #include <sys/lock.h> 51 #include <sys/resourcevar.h> 52 #include <sys/sysctl.h> 53 #include <sys/uio.h> 54 #include <sys/vnode.h> 55 #include <sys/sfbuf.h> 56 #include <sys/thread2.h> 57 #include <machine/limits.h> 58 59 #include <vm/vm.h> 60 #include <vm/vm_page.h> 61 #include <vm/vm_map.h> 62 63 SYSCTL_INT(_kern, KERN_IOV_MAX, iov_max, CTLFLAG_RD, NULL, UIO_MAXIOV, 64 "Maximum number of elements in an I/O vector; sysconf(_SC_IOV_MAX)"); 65 66 /* 67 * UIO_READ: copy the kernelspace cp to the user or kernelspace UIO 68 * UIO_WRITE: copy the user or kernelspace UIO to the kernelspace cp 69 * 70 * For userspace UIO's, uio_td must be the current thread. 71 */ 72 int 73 uiomove(caddr_t cp, int n, struct uio *uio) 74 { 75 struct iovec *iov; 76 u_int cnt; 77 int error = 0; 78 int save = 0; 79 int baseticks = ticks; 80 81 KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, 82 ("uiomove: mode")); 83 KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, 84 ("uiomove proc")); 85 86 if (curproc) { 87 save = curproc->p_flag & P_DEADLKTREAT; 88 curproc->p_flag |= P_DEADLKTREAT; 89 } 90 91 while (n > 0 && uio->uio_resid) { 92 iov = uio->uio_iov; 93 cnt = iov->iov_len; 94 if (cnt == 0) { 95 uio->uio_iov++; 96 uio->uio_iovcnt--; 97 continue; 98 } 99 if (cnt > n) 100 cnt = n; 101 102 switch (uio->uio_segflg) { 103 104 case UIO_USERSPACE: 105 if (ticks - baseticks >= hogticks) { 106 uio_yield(); 107 baseticks = ticks; 108 } 109 if (uio->uio_rw == UIO_READ) 110 error = copyout(cp, iov->iov_base, cnt); 111 else 112 error = copyin(iov->iov_base, cp, cnt); 113 if (error) 114 break; 115 break; 116 117 case UIO_SYSSPACE: 118 if (uio->uio_rw == UIO_READ) 119 bcopy((caddr_t)cp, iov->iov_base, cnt); 120 else 121 bcopy(iov->iov_base, (caddr_t)cp, cnt); 122 break; 123 case UIO_NOCOPY: 124 break; 125 } 126 iov->iov_base = (char *)iov->iov_base + cnt; 127 iov->iov_len -= cnt; 128 uio->uio_resid -= cnt; 129 uio->uio_offset += cnt; 130 cp += cnt; 131 n -= cnt; 132 } 133 if (curproc) 134 curproc->p_flag = (curproc->p_flag & ~P_DEADLKTREAT) | save; 135 return (error); 136 } 137 /* 138 * Wrapper for uiomove() that validates the arguments against a known-good 139 * kernel buffer. Currently, uiomove accepts a signed (n) argument, which 140 * is almost definitely a bad thing, so we catch that here as well. We 141 * return a runtime failure, but it might be desirable to generate a runtime 142 * assertion failure instead. 143 */ 144 int 145 uiomove_frombuf(void *buf, int buflen, struct uio *uio) 146 { 147 unsigned int offset, n; 148 149 if (uio->uio_offset < 0 || uio->uio_resid < 0 || 150 (offset = uio->uio_offset) != uio->uio_offset) 151 return (EINVAL); 152 if (buflen <= 0 || offset >= buflen) 153 return (0); 154 if ((n = buflen - offset) > INT_MAX) 155 return (EINVAL); 156 return (uiomove((char *)buf + offset, n, uio)); 157 } 158 159 160 int 161 uiomoveco(caddr_t cp, int n, struct uio *uio, struct vm_object *obj) 162 { 163 struct iovec *iov; 164 u_int cnt; 165 int error; 166 int baseticks = ticks; 167 168 KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, 169 ("uiomoveco: mode")); 170 KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, 171 ("uiomoveco proc")); 172 173 while (n > 0 && uio->uio_resid) { 174 iov = uio->uio_iov; 175 cnt = iov->iov_len; 176 if (cnt == 0) { 177 uio->uio_iov++; 178 uio->uio_iovcnt--; 179 continue; 180 } 181 if (cnt > n) 182 cnt = n; 183 184 switch (uio->uio_segflg) { 185 186 case UIO_USERSPACE: 187 if (ticks - baseticks >= hogticks) { 188 uio_yield(); 189 baseticks = ticks; 190 } 191 if (uio->uio_rw == UIO_READ) { 192 error = copyout(cp, iov->iov_base, cnt); 193 } else { 194 error = copyin(iov->iov_base, cp, cnt); 195 } 196 if (error) 197 return (error); 198 break; 199 200 case UIO_SYSSPACE: 201 if (uio->uio_rw == UIO_READ) 202 bcopy((caddr_t)cp, iov->iov_base, cnt); 203 else 204 bcopy(iov->iov_base, (caddr_t)cp, cnt); 205 break; 206 case UIO_NOCOPY: 207 break; 208 } 209 iov->iov_base = (char *)iov->iov_base + cnt; 210 iov->iov_len -= cnt; 211 uio->uio_resid -= cnt; 212 uio->uio_offset += cnt; 213 cp += cnt; 214 n -= cnt; 215 } 216 return (0); 217 } 218 219 /* 220 * Give next character to user as result of read. 221 */ 222 int 223 ureadc(int c, struct uio *uio) 224 { 225 struct iovec *iov; 226 char *iov_base; 227 228 again: 229 if (uio->uio_iovcnt == 0 || uio->uio_resid == 0) 230 panic("ureadc"); 231 iov = uio->uio_iov; 232 if (iov->iov_len == 0) { 233 uio->uio_iovcnt--; 234 uio->uio_iov++; 235 goto again; 236 } 237 switch (uio->uio_segflg) { 238 239 case UIO_USERSPACE: 240 if (subyte(iov->iov_base, c) < 0) 241 return (EFAULT); 242 break; 243 244 case UIO_SYSSPACE: 245 iov_base = iov->iov_base; 246 *iov_base = c; 247 iov->iov_base = iov_base; 248 break; 249 250 case UIO_NOCOPY: 251 break; 252 } 253 iov->iov_base = (char *)iov->iov_base + 1; 254 iov->iov_len--; 255 uio->uio_resid--; 256 uio->uio_offset++; 257 return (0); 258 } 259 260 /* 261 * General routine to allocate a hash table. Make the hash table size a 262 * power of 2 greater or equal to the number of elements requested, and 263 * store the masking value in *hashmask. 264 */ 265 void * 266 hashinit(int elements, struct malloc_type *type, u_long *hashmask) 267 { 268 long hashsize; 269 LIST_HEAD(generic, generic) *hashtbl; 270 int i; 271 272 if (elements <= 0) 273 panic("hashinit: bad elements"); 274 for (hashsize = 2; hashsize < elements; hashsize <<= 1) 275 continue; 276 hashtbl = kmalloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK); 277 for (i = 0; i < hashsize; i++) 278 LIST_INIT(&hashtbl[i]); 279 *hashmask = hashsize - 1; 280 return (hashtbl); 281 } 282 283 static int primes[] = { 1, 13, 31, 61, 127, 251, 509, 761, 1021, 1531, 2039, 284 2557, 3067, 3583, 4093, 4603, 5119, 5623, 6143, 6653, 285 7159, 7673, 8191, 12281, 16381, 24571, 32749 }; 286 #define NPRIMES (sizeof(primes) / sizeof(primes[0])) 287 288 /* 289 * General routine to allocate a prime number sized hash table. 290 */ 291 void * 292 phashinit(int elements, struct malloc_type *type, u_long *nentries) 293 { 294 long hashsize; 295 LIST_HEAD(generic, generic) *hashtbl; 296 int i; 297 298 if (elements <= 0) 299 panic("phashinit: bad elements"); 300 for (i = 1, hashsize = primes[1]; hashsize <= elements;) { 301 i++; 302 if (i == NPRIMES) 303 break; 304 hashsize = primes[i]; 305 } 306 hashsize = primes[i - 1]; 307 hashtbl = kmalloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK); 308 for (i = 0; i < hashsize; i++) 309 LIST_INIT(&hashtbl[i]); 310 *nentries = hashsize; 311 return (hashtbl); 312 } 313 314 /* 315 * Copyin an iovec. If the iovec array fits, use the preallocated small 316 * iovec structure. If it is too big, dynamically allocate an iovec array 317 * of sufficient size. 318 * 319 * MPSAFE 320 */ 321 int 322 iovec_copyin(struct iovec *uiov, struct iovec **kiov, struct iovec *siov, 323 size_t iov_cnt, int *iov_len) 324 { 325 struct iovec *iovp; 326 int error, i; 327 328 if (iov_cnt > UIO_MAXIOV) 329 return EMSGSIZE; 330 if (iov_cnt > UIO_SMALLIOV) { 331 MALLOC(*kiov, struct iovec *, sizeof(struct iovec) * iov_cnt, 332 M_IOV, M_WAITOK); 333 } else { 334 *kiov = siov; 335 } 336 error = copyin(uiov, *kiov, iov_cnt * sizeof(struct iovec)); 337 if (error == 0) { 338 *iov_len = 0; 339 for (i = 0, iovp = *kiov; i < iov_cnt; i++, iovp++) { 340 /* 341 * Check for both *iov_len overflows and out of 342 * range iovp->iov_len's. We limit to the 343 * capabilities of signed integers. 344 */ 345 if (*iov_len + (int)iovp->iov_len < *iov_len) 346 error = EINVAL; 347 *iov_len += (int)iovp->iov_len; 348 } 349 } 350 if (error) 351 iovec_free(kiov, siov); 352 return (error); 353 } 354 355 356 /* 357 * Copyright (c) 2004 Alan L. Cox <alc@cs.rice.edu> 358 * Copyright (c) 1982, 1986, 1991, 1993 359 * The Regents of the University of California. All rights reserved. 360 * (c) UNIX System Laboratories, Inc. 361 * All or some portions of this file are derived from material licensed 362 * to the University of California by American Telephone and Telegraph 363 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 364 * the permission of UNIX System Laboratories, Inc. 365 * 366 * Redistribution and use in source and binary forms, with or without 367 * modification, are permitted provided that the following conditions 368 * are met: 369 * 1. Redistributions of source code must retain the above copyright 370 * notice, this list of conditions and the following disclaimer. 371 * 2. Redistributions in binary form must reproduce the above copyright 372 * notice, this list of conditions and the following disclaimer in the 373 * documentation and/or other materials provided with the distribution. 374 * 4. Neither the name of the University nor the names of its contributors 375 * may be used to endorse or promote products derived from this software 376 * without specific prior written permission. 377 * 378 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 379 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 380 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 381 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 382 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 383 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 384 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 385 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 386 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 387 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 388 * SUCH DAMAGE. 389 * 390 * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94 391 * $FreeBSD: src/sys/i386/i386/uio_machdep.c,v 1.1 2004/03/21 20:28:36 alc Exp $ 392 */ 393 394 /* 395 * Implement uiomove(9) from physical memory using sf_bufs to reduce 396 * the creation and destruction of ephemeral mappings. 397 */ 398 int 399 uiomove_fromphys(vm_page_t *ma, vm_offset_t offset, int n, struct uio *uio) 400 { 401 struct sf_buf *sf; 402 struct thread *td = curthread; 403 struct iovec *iov; 404 void *cp; 405 vm_offset_t page_offset; 406 vm_page_t m; 407 size_t cnt; 408 int error = 0; 409 int save = 0; 410 411 KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, 412 ("uiomove_fromphys: mode")); 413 KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, 414 ("uiomove_fromphys proc")); 415 416 crit_enter(); 417 save = td->td_flags & TDF_DEADLKTREAT; 418 td->td_flags |= TDF_DEADLKTREAT; 419 crit_exit(); 420 421 while (n > 0 && uio->uio_resid) { 422 iov = uio->uio_iov; 423 cnt = iov->iov_len; 424 if (cnt == 0) { 425 uio->uio_iov++; 426 uio->uio_iovcnt--; 427 continue; 428 } 429 if (cnt > n) 430 cnt = n; 431 page_offset = offset & PAGE_MASK; 432 cnt = min(cnt, PAGE_SIZE - page_offset); 433 m = ma[offset >> PAGE_SHIFT]; 434 sf = sf_buf_alloc(m, SFB_CPUPRIVATE); 435 cp = (char *)sf_buf_kva(sf) + page_offset; 436 switch (uio->uio_segflg) { 437 case UIO_USERSPACE: 438 /* 439 * note: removed uioyield (it was the wrong place to 440 * put it). 441 */ 442 if (uio->uio_rw == UIO_READ) 443 error = copyout(cp, iov->iov_base, cnt); 444 else 445 error = copyin(iov->iov_base, cp, cnt); 446 if (error) { 447 sf_buf_free(sf); 448 goto out; 449 } 450 break; 451 case UIO_SYSSPACE: 452 if (uio->uio_rw == UIO_READ) 453 bcopy(cp, iov->iov_base, cnt); 454 else 455 bcopy(iov->iov_base, cp, cnt); 456 break; 457 case UIO_NOCOPY: 458 break; 459 } 460 sf_buf_free(sf); 461 iov->iov_base = (char *)iov->iov_base + cnt; 462 iov->iov_len -= cnt; 463 uio->uio_resid -= cnt; 464 uio->uio_offset += cnt; 465 offset += cnt; 466 n -= cnt; 467 } 468 out: 469 if (save == 0) { 470 crit_enter(); 471 td->td_flags &= ~TDF_DEADLKTREAT; 472 crit_exit(); 473 } 474 return (error); 475 } 476 477