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 */ 41 42 #include "opt_ddb.h" 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/kernel.h> 47 #include <sys/proc.h> 48 #include <sys/malloc.h> 49 #include <sys/lock.h> 50 #include <sys/resourcevar.h> 51 #include <sys/sysctl.h> 52 #include <sys/uio.h> 53 #include <sys/vnode.h> 54 #include <sys/thread2.h> 55 #include <machine/limits.h> 56 57 #include <cpu/lwbuf.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 * The syscall interface is responsible for limiting the length to 73 * ssize_t for things like read() or write() which return the bytes 74 * read or written as ssize_t. These functions work with unsigned 75 * lengths. 76 */ 77 int 78 uiomove(caddr_t cp, size_t n, struct uio *uio) 79 { 80 thread_t td = curthread; 81 struct iovec *iov; 82 size_t cnt; 83 int error = 0; 84 int save = 0; 85 86 KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, 87 ("uiomove: mode")); 88 KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == td, 89 ("uiomove proc")); 90 91 crit_enter(); 92 save = td->td_flags & TDF_DEADLKTREAT; 93 td->td_flags |= TDF_DEADLKTREAT; 94 crit_exit(); 95 96 while (n > 0 && uio->uio_resid) { 97 iov = uio->uio_iov; 98 cnt = iov->iov_len; 99 if (cnt == 0) { 100 uio->uio_iov++; 101 uio->uio_iovcnt--; 102 continue; 103 } 104 if (cnt > n) 105 cnt = n; 106 107 switch (uio->uio_segflg) { 108 109 case UIO_USERSPACE: 110 lwkt_user_yield(); 111 if (uio->uio_rw == UIO_READ) 112 error = copyout(cp, iov->iov_base, cnt); 113 else 114 error = copyin(iov->iov_base, cp, cnt); 115 if (error) 116 break; 117 break; 118 119 case UIO_SYSSPACE: 120 if (uio->uio_rw == UIO_READ) 121 bcopy((caddr_t)cp, iov->iov_base, cnt); 122 else 123 bcopy(iov->iov_base, (caddr_t)cp, cnt); 124 break; 125 case UIO_NOCOPY: 126 break; 127 } 128 iov->iov_base = (char *)iov->iov_base + cnt; 129 iov->iov_len -= cnt; 130 uio->uio_resid -= cnt; 131 uio->uio_offset += cnt; 132 cp += cnt; 133 n -= cnt; 134 } 135 crit_enter(); 136 td->td_flags = (td->td_flags & ~TDF_DEADLKTREAT) | save; 137 crit_exit(); 138 return (error); 139 } 140 141 /* 142 * Like uiomove() but copies zero-fill. Only allowed for UIO_READ, 143 * for obvious reasons. 144 */ 145 int 146 uiomovez(size_t n, struct uio *uio) 147 { 148 struct iovec *iov; 149 size_t cnt; 150 int error = 0; 151 152 KASSERT(uio->uio_rw == UIO_READ, ("uiomovez: mode")); 153 KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, 154 ("uiomove proc")); 155 156 while (n > 0 && uio->uio_resid) { 157 iov = uio->uio_iov; 158 cnt = iov->iov_len; 159 if (cnt == 0) { 160 uio->uio_iov++; 161 uio->uio_iovcnt--; 162 continue; 163 } 164 if (cnt > n) 165 cnt = n; 166 167 switch (uio->uio_segflg) { 168 case UIO_USERSPACE: 169 error = copyout(ZeroPage, iov->iov_base, cnt); 170 if (error) 171 break; 172 break; 173 case UIO_SYSSPACE: 174 bzero(iov->iov_base, cnt); 175 break; 176 case UIO_NOCOPY: 177 break; 178 } 179 iov->iov_base = (char *)iov->iov_base + cnt; 180 iov->iov_len -= cnt; 181 uio->uio_resid -= cnt; 182 uio->uio_offset += cnt; 183 n -= cnt; 184 } 185 return (error); 186 } 187 188 /* 189 * Wrapper for uiomove() that validates the arguments against a known-good 190 * kernel buffer. 191 */ 192 int 193 uiomove_frombuf(void *buf, size_t buflen, struct uio *uio) 194 { 195 size_t offset; 196 197 offset = (size_t)uio->uio_offset; 198 if ((off_t)offset != uio->uio_offset) 199 return (EINVAL); 200 if (buflen == 0 || offset >= buflen) 201 return (0); 202 return (uiomove((char *)buf + offset, buflen - offset, uio)); 203 } 204 205 /* 206 * Give next character to user as result of read. 207 */ 208 int 209 ureadc(int c, struct uio *uio) 210 { 211 struct iovec *iov; 212 char *iov_base; 213 214 again: 215 if (uio->uio_iovcnt == 0 || uio->uio_resid == 0) 216 panic("ureadc"); 217 iov = uio->uio_iov; 218 if (iov->iov_len == 0) { 219 uio->uio_iovcnt--; 220 uio->uio_iov++; 221 goto again; 222 } 223 switch (uio->uio_segflg) { 224 225 case UIO_USERSPACE: 226 if (subyte(iov->iov_base, c) < 0) 227 return (EFAULT); 228 break; 229 230 case UIO_SYSSPACE: 231 iov_base = iov->iov_base; 232 *iov_base = c; 233 iov->iov_base = iov_base; 234 break; 235 236 case UIO_NOCOPY: 237 break; 238 } 239 iov->iov_base = (char *)iov->iov_base + 1; 240 iov->iov_len--; 241 uio->uio_resid--; 242 uio->uio_offset++; 243 return (0); 244 } 245 246 /* 247 * General routine to allocate a hash table. Make the hash table size a 248 * power of 2 greater or equal to the number of elements requested, and 249 * store the masking value in *hashmask. 250 */ 251 void * 252 hashinit(int elements, struct malloc_type *type, u_long *hashmask) 253 { 254 long hashsize; 255 LIST_HEAD(generic, generic) *hashtbl; 256 int i; 257 258 if (elements <= 0) 259 panic("hashinit: bad elements"); 260 for (hashsize = 2; hashsize < elements; hashsize <<= 1) 261 continue; 262 hashtbl = kmalloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK); 263 for (i = 0; i < hashsize; i++) 264 LIST_INIT(&hashtbl[i]); 265 *hashmask = hashsize - 1; 266 return (hashtbl); 267 } 268 269 /* 270 * This is a newer version which allocates a hash table of structures. 271 * 272 * The returned array will be zero'd. The caller is responsible for 273 * initializing the structures. 274 */ 275 void * 276 hashinit_ext(int elements, size_t size, struct malloc_type *type, 277 u_long *hashmask) 278 { 279 long hashsize; 280 void *hashtbl; 281 282 if (elements <= 0) 283 panic("hashinit: bad elements"); 284 for (hashsize = 2; hashsize < elements; hashsize <<= 1) 285 continue; 286 hashtbl = kmalloc((size_t)hashsize * size, type, M_WAITOK | M_ZERO); 287 *hashmask = hashsize - 1; 288 return (hashtbl); 289 } 290 291 static int primes[] = { 1, 13, 31, 61, 127, 251, 509, 761, 1021, 1531, 2039, 292 2557, 3067, 3583, 4093, 4603, 5119, 5623, 6143, 6653, 293 7159, 7673, 8191, 12281, 16381, 24571, 32749 }; 294 #define NPRIMES NELEM(primes) 295 296 /* 297 * General routine to allocate a prime number sized hash table. 298 */ 299 void * 300 phashinit(int elements, struct malloc_type *type, u_long *nentries) 301 { 302 long hashsize; 303 LIST_HEAD(generic, generic) *hashtbl; 304 int i; 305 306 if (elements <= 0) 307 panic("phashinit: bad elements"); 308 for (i = 1, hashsize = primes[1]; hashsize <= elements;) { 309 i++; 310 if (i == NPRIMES) 311 break; 312 hashsize = primes[i]; 313 } 314 hashsize = primes[i - 1]; 315 hashtbl = kmalloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK); 316 for (i = 0; i < hashsize; i++) 317 LIST_INIT(&hashtbl[i]); 318 *nentries = hashsize; 319 return (hashtbl); 320 } 321 322 /* 323 * This is a newer version which allocates a hash table of structures 324 * in a prime-number size. 325 * 326 * The returned array will be zero'd. The caller is responsible for 327 * initializing the structures. 328 */ 329 void * 330 phashinit_ext(int elements, size_t size, struct malloc_type *type, 331 u_long *nentries) 332 { 333 long hashsize; 334 void *hashtbl; 335 int i; 336 337 if (elements <= 0) 338 panic("phashinit: bad elements"); 339 for (i = 1, hashsize = primes[1]; hashsize <= elements;) { 340 i++; 341 if (i == NPRIMES) 342 break; 343 hashsize = primes[i]; 344 } 345 hashsize = primes[i - 1]; 346 hashtbl = kmalloc((size_t)hashsize * size, type, M_WAITOK | M_ZERO); 347 *nentries = hashsize; 348 return (hashtbl); 349 } 350 351 /* 352 * Copyin an iovec. If the iovec array fits, use the preallocated small 353 * iovec structure. If it is too big, dynamically allocate an iovec array 354 * of sufficient size. 355 * 356 * MPSAFE 357 */ 358 int 359 iovec_copyin(struct iovec *uiov, struct iovec **kiov, struct iovec *siov, 360 size_t iov_cnt, size_t *iov_len) 361 { 362 struct iovec *iovp; 363 int error, i; 364 size_t len; 365 366 if (iov_cnt > UIO_MAXIOV) 367 return EMSGSIZE; 368 if (iov_cnt > UIO_SMALLIOV) { 369 MALLOC(*kiov, struct iovec *, sizeof(struct iovec) * iov_cnt, 370 M_IOV, M_WAITOK); 371 } else { 372 *kiov = siov; 373 } 374 error = copyin(uiov, *kiov, iov_cnt * sizeof(struct iovec)); 375 if (error == 0) { 376 *iov_len = 0; 377 for (i = 0, iovp = *kiov; i < iov_cnt; i++, iovp++) { 378 /* 379 * Check for both *iov_len overflows and out of 380 * range iovp->iov_len's. We limit to the 381 * capabilities of signed integers. 382 * 383 * GCC4 - overflow check opt requires assign/test. 384 */ 385 len = *iov_len + iovp->iov_len; 386 if (len < *iov_len) 387 error = EINVAL; 388 *iov_len = len; 389 } 390 } 391 392 /* 393 * From userland disallow iovec's which exceed the sized size 394 * limit as the system calls return ssize_t. 395 * 396 * NOTE: Internal kernel interfaces can handle the unsigned 397 * limit. 398 */ 399 if (error == 0 && (ssize_t)*iov_len < 0) 400 error = EINVAL; 401 402 if (error) 403 iovec_free(kiov, siov); 404 return (error); 405 } 406 407 408 /* 409 * Copyright (c) 2004 Alan L. Cox <alc@cs.rice.edu> 410 * Copyright (c) 1982, 1986, 1991, 1993 411 * The Regents of the University of California. All rights reserved. 412 * (c) UNIX System Laboratories, Inc. 413 * All or some portions of this file are derived from material licensed 414 * to the University of California by American Telephone and Telegraph 415 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 416 * the permission of UNIX System Laboratories, Inc. 417 * 418 * Redistribution and use in source and binary forms, with or without 419 * modification, are permitted provided that the following conditions 420 * are met: 421 * 1. Redistributions of source code must retain the above copyright 422 * notice, this list of conditions and the following disclaimer. 423 * 2. Redistributions in binary form must reproduce the above copyright 424 * notice, this list of conditions and the following disclaimer in the 425 * documentation and/or other materials provided with the distribution. 426 * 4. Neither the name of the University nor the names of its contributors 427 * may be used to endorse or promote products derived from this software 428 * without specific prior written permission. 429 * 430 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 431 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 432 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 433 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 434 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 435 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 436 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 437 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 438 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 439 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 440 * SUCH DAMAGE. 441 * 442 * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94 443 * $FreeBSD: src/sys/i386/i386/uio_machdep.c,v 1.1 2004/03/21 20:28:36 alc Exp $ 444 */ 445 446 /* 447 * Implement uiomove(9) from physical memory using lwbuf's to reduce 448 * the creation and destruction of ephemeral mappings. 449 */ 450 int 451 uiomove_fromphys(vm_page_t *ma, vm_offset_t offset, size_t n, struct uio *uio) 452 { 453 struct lwbuf lwb_cache; 454 struct lwbuf *lwb; 455 struct thread *td = curthread; 456 struct iovec *iov; 457 void *cp; 458 vm_offset_t page_offset; 459 vm_page_t m; 460 size_t cnt; 461 int error = 0; 462 int save = 0; 463 464 KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, 465 ("uiomove_fromphys: mode")); 466 KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, 467 ("uiomove_fromphys proc")); 468 469 crit_enter(); 470 save = td->td_flags & TDF_DEADLKTREAT; 471 td->td_flags |= TDF_DEADLKTREAT; 472 crit_exit(); 473 474 while (n > 0 && uio->uio_resid) { 475 iov = uio->uio_iov; 476 cnt = iov->iov_len; 477 if (cnt == 0) { 478 uio->uio_iov++; 479 uio->uio_iovcnt--; 480 continue; 481 } 482 if (cnt > n) 483 cnt = n; 484 page_offset = offset & PAGE_MASK; 485 cnt = min(cnt, PAGE_SIZE - page_offset); 486 m = ma[offset >> PAGE_SHIFT]; 487 lwb = lwbuf_alloc(m, &lwb_cache); 488 cp = (char *)lwbuf_kva(lwb) + page_offset; 489 switch (uio->uio_segflg) { 490 case UIO_USERSPACE: 491 /* 492 * note: removed uioyield (it was the wrong place to 493 * put it). 494 */ 495 if (uio->uio_rw == UIO_READ) 496 error = copyout(cp, iov->iov_base, cnt); 497 else 498 error = copyin(iov->iov_base, cp, cnt); 499 if (error) { 500 lwbuf_free(lwb); 501 goto out; 502 } 503 break; 504 case UIO_SYSSPACE: 505 if (uio->uio_rw == UIO_READ) 506 bcopy(cp, iov->iov_base, cnt); 507 else 508 bcopy(iov->iov_base, cp, cnt); 509 break; 510 case UIO_NOCOPY: 511 break; 512 } 513 lwbuf_free(lwb); 514 iov->iov_base = (char *)iov->iov_base + cnt; 515 iov->iov_len -= cnt; 516 uio->uio_resid -= cnt; 517 uio->uio_offset += cnt; 518 offset += cnt; 519 n -= cnt; 520 } 521 out: 522 if (save == 0) { 523 crit_enter(); 524 td->td_flags &= ~TDF_DEADLKTREAT; 525 crit_exit(); 526 } 527 return (error); 528 } 529 530