128993443SEd Schouten /*- 228993443SEd Schouten * Copyright (c) 1982, 1986, 1991, 1993 328993443SEd Schouten * The Regents of the University of California. All rights reserved. 428993443SEd Schouten * (c) UNIX System Laboratories, Inc. 528993443SEd Schouten * All or some portions of this file are derived from material licensed 628993443SEd Schouten * to the University of California by American Telephone and Telegraph 728993443SEd Schouten * Co. or Unix System Laboratories, Inc. and are reproduced herein with 828993443SEd Schouten * the permission of UNIX System Laboratories, Inc. 928993443SEd Schouten * 10*4f3dc900SKonstantin Belousov * Copyright (c) 2014 The FreeBSD Foundation 11*4f3dc900SKonstantin Belousov * 12*4f3dc900SKonstantin Belousov * Portions of this software were developed by Konstantin Belousov 13*4f3dc900SKonstantin Belousov * under sponsorship from the FreeBSD Foundation. 14*4f3dc900SKonstantin Belousov * 1528993443SEd Schouten * Redistribution and use in source and binary forms, with or without 1628993443SEd Schouten * modification, are permitted provided that the following conditions 1728993443SEd Schouten * are met: 1828993443SEd Schouten * 1. Redistributions of source code must retain the above copyright 1928993443SEd Schouten * notice, this list of conditions and the following disclaimer. 2028993443SEd Schouten * 2. Redistributions in binary form must reproduce the above copyright 2128993443SEd Schouten * notice, this list of conditions and the following disclaimer in the 2228993443SEd Schouten * documentation and/or other materials provided with the distribution. 2328993443SEd Schouten * 4. Neither the name of the University nor the names of its contributors 2428993443SEd Schouten * may be used to endorse or promote products derived from this software 2528993443SEd Schouten * without specific prior written permission. 2628993443SEd Schouten * 2728993443SEd Schouten * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2828993443SEd Schouten * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2928993443SEd Schouten * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3028993443SEd Schouten * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3128993443SEd Schouten * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3228993443SEd Schouten * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3328993443SEd Schouten * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3428993443SEd Schouten * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3528993443SEd Schouten * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3628993443SEd Schouten * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3728993443SEd Schouten * SUCH DAMAGE. 3828993443SEd Schouten * 3928993443SEd Schouten * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94 4028993443SEd Schouten */ 4128993443SEd Schouten 4228993443SEd Schouten #include <sys/cdefs.h> 4328993443SEd Schouten __FBSDID("$FreeBSD$"); 4428993443SEd Schouten 4528993443SEd Schouten #include <sys/param.h> 4628993443SEd Schouten #include <sys/systm.h> 4728993443SEd Schouten #include <sys/kernel.h> 4828993443SEd Schouten #include <sys/limits.h> 4928993443SEd Schouten #include <sys/lock.h> 500f502d1cSKonstantin Belousov #include <sys/mman.h> 5128993443SEd Schouten #include <sys/proc.h> 520f502d1cSKonstantin Belousov #include <sys/resourcevar.h> 5389f6b863SAttilio Rao #include <sys/rwlock.h> 5428993443SEd Schouten #include <sys/sched.h> 5528993443SEd Schouten #include <sys/sysctl.h> 5628993443SEd Schouten #include <sys/vnode.h> 5728993443SEd Schouten 5828993443SEd Schouten #include <vm/vm.h> 591c771f92SKonstantin Belousov #include <vm/vm_param.h> 600f502d1cSKonstantin Belousov #include <vm/vm_extern.h> 6128993443SEd Schouten #include <vm/vm_page.h> 62e946b949SAttilio Rao #include <vm/vm_pageout.h> 6328993443SEd Schouten #include <vm/vm_map.h> 6428993443SEd Schouten 65f0188618SHans Petter Selasky SYSCTL_INT(_kern, KERN_IOV_MAX, iov_max, CTLFLAG_RD, SYSCTL_NULL_INT_PTR, UIO_MAXIOV, 6628993443SEd Schouten "Maximum number of elements in an I/O vector; sysconf(_SC_IOV_MAX)"); 6728993443SEd Schouten 682801687dSKonstantin Belousov static int uiomove_faultflag(void *cp, int n, struct uio *uio, int nofault); 692801687dSKonstantin Belousov 7028993443SEd Schouten int 712801687dSKonstantin Belousov copyin_nofault(const void *udaddr, void *kaddr, size_t len) 722801687dSKonstantin Belousov { 732801687dSKonstantin Belousov int error, save; 742801687dSKonstantin Belousov 752801687dSKonstantin Belousov save = vm_fault_disable_pagefaults(); 762801687dSKonstantin Belousov error = copyin(udaddr, kaddr, len); 772801687dSKonstantin Belousov vm_fault_enable_pagefaults(save); 782801687dSKonstantin Belousov return (error); 792801687dSKonstantin Belousov } 802801687dSKonstantin Belousov 812801687dSKonstantin Belousov int 822801687dSKonstantin Belousov copyout_nofault(const void *kaddr, void *udaddr, size_t len) 832801687dSKonstantin Belousov { 842801687dSKonstantin Belousov int error, save; 852801687dSKonstantin Belousov 862801687dSKonstantin Belousov save = vm_fault_disable_pagefaults(); 872801687dSKonstantin Belousov error = copyout(kaddr, udaddr, len); 882801687dSKonstantin Belousov vm_fault_enable_pagefaults(save); 892801687dSKonstantin Belousov return (error); 902801687dSKonstantin Belousov } 912801687dSKonstantin Belousov 92dd0b4fb6SKonstantin Belousov #define PHYS_PAGE_COUNT(len) (howmany(len, PAGE_SIZE) + 1) 93dd0b4fb6SKonstantin Belousov 94dd0b4fb6SKonstantin Belousov int 95dd0b4fb6SKonstantin Belousov physcopyin(void *src, vm_paddr_t dst, size_t len) 96dd0b4fb6SKonstantin Belousov { 97dd0b4fb6SKonstantin Belousov vm_page_t m[PHYS_PAGE_COUNT(len)]; 98dd0b4fb6SKonstantin Belousov struct iovec iov[1]; 99dd0b4fb6SKonstantin Belousov struct uio uio; 100dd0b4fb6SKonstantin Belousov int i; 101dd0b4fb6SKonstantin Belousov 102dd0b4fb6SKonstantin Belousov iov[0].iov_base = src; 103dd0b4fb6SKonstantin Belousov iov[0].iov_len = len; 104dd0b4fb6SKonstantin Belousov uio.uio_iov = iov; 105dd0b4fb6SKonstantin Belousov uio.uio_iovcnt = 1; 106dd0b4fb6SKonstantin Belousov uio.uio_offset = 0; 107dd0b4fb6SKonstantin Belousov uio.uio_resid = len; 108dd0b4fb6SKonstantin Belousov uio.uio_segflg = UIO_SYSSPACE; 109dd0b4fb6SKonstantin Belousov uio.uio_rw = UIO_WRITE; 110dd0b4fb6SKonstantin Belousov for (i = 0; i < PHYS_PAGE_COUNT(len); i++, dst += PAGE_SIZE) 111dd0b4fb6SKonstantin Belousov m[i] = PHYS_TO_VM_PAGE(dst); 112dd0b4fb6SKonstantin Belousov return (uiomove_fromphys(m, dst & PAGE_MASK, len, &uio)); 113dd0b4fb6SKonstantin Belousov } 114dd0b4fb6SKonstantin Belousov 115dd0b4fb6SKonstantin Belousov int 116dd0b4fb6SKonstantin Belousov physcopyout(vm_paddr_t src, void *dst, size_t len) 117dd0b4fb6SKonstantin Belousov { 118dd0b4fb6SKonstantin Belousov vm_page_t m[PHYS_PAGE_COUNT(len)]; 119dd0b4fb6SKonstantin Belousov struct iovec iov[1]; 120dd0b4fb6SKonstantin Belousov struct uio uio; 121dd0b4fb6SKonstantin Belousov int i; 122dd0b4fb6SKonstantin Belousov 123dd0b4fb6SKonstantin Belousov iov[0].iov_base = dst; 124dd0b4fb6SKonstantin Belousov iov[0].iov_len = len; 125dd0b4fb6SKonstantin Belousov uio.uio_iov = iov; 126dd0b4fb6SKonstantin Belousov uio.uio_iovcnt = 1; 127dd0b4fb6SKonstantin Belousov uio.uio_offset = 0; 128dd0b4fb6SKonstantin Belousov uio.uio_resid = len; 129dd0b4fb6SKonstantin Belousov uio.uio_segflg = UIO_SYSSPACE; 130dd0b4fb6SKonstantin Belousov uio.uio_rw = UIO_READ; 131dd0b4fb6SKonstantin Belousov for (i = 0; i < PHYS_PAGE_COUNT(len); i++, src += PAGE_SIZE) 132dd0b4fb6SKonstantin Belousov m[i] = PHYS_TO_VM_PAGE(src); 133dd0b4fb6SKonstantin Belousov return (uiomove_fromphys(m, src & PAGE_MASK, len, &uio)); 134dd0b4fb6SKonstantin Belousov } 135dd0b4fb6SKonstantin Belousov 136dd0b4fb6SKonstantin Belousov #undef PHYS_PAGE_COUNT 137dd0b4fb6SKonstantin Belousov 1382801687dSKonstantin Belousov int 13928993443SEd Schouten uiomove(void *cp, int n, struct uio *uio) 14028993443SEd Schouten { 1412801687dSKonstantin Belousov 1422801687dSKonstantin Belousov return (uiomove_faultflag(cp, n, uio, 0)); 1432801687dSKonstantin Belousov } 1442801687dSKonstantin Belousov 1452801687dSKonstantin Belousov int 1462801687dSKonstantin Belousov uiomove_nofault(void *cp, int n, struct uio *uio) 1472801687dSKonstantin Belousov { 1482801687dSKonstantin Belousov 1492801687dSKonstantin Belousov return (uiomove_faultflag(cp, n, uio, 1)); 1502801687dSKonstantin Belousov } 1512801687dSKonstantin Belousov 1522801687dSKonstantin Belousov static int 1532801687dSKonstantin Belousov uiomove_faultflag(void *cp, int n, struct uio *uio, int nofault) 1542801687dSKonstantin Belousov { 1552801687dSKonstantin Belousov struct thread *td; 15628993443SEd Schouten struct iovec *iov; 157526d0bd5SKonstantin Belousov size_t cnt; 1582801687dSKonstantin Belousov int error, newflags, save; 1592801687dSKonstantin Belousov 1602801687dSKonstantin Belousov td = curthread; 1612801687dSKonstantin Belousov error = 0; 16228993443SEd Schouten 16328993443SEd Schouten KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, 16428993443SEd Schouten ("uiomove: mode")); 1652801687dSKonstantin Belousov KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == td, 16628993443SEd Schouten ("uiomove proc")); 1672801687dSKonstantin Belousov if (!nofault) 16828993443SEd Schouten WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 16928993443SEd Schouten "Calling uiomove()"); 17028993443SEd Schouten 1712801687dSKonstantin Belousov /* XXX does it make a sense to set TDP_DEADLKTREAT for UIO_SYSSPACE ? */ 1722801687dSKonstantin Belousov newflags = TDP_DEADLKTREAT; 1735730afc9SAlan Cox if (uio->uio_segflg == UIO_USERSPACE && nofault) { 1745730afc9SAlan Cox /* 1755730afc9SAlan Cox * Fail if a non-spurious page fault occurs. 1765730afc9SAlan Cox */ 1775730afc9SAlan Cox newflags |= TDP_NOFAULTING | TDP_RESETSPUR; 1785730afc9SAlan Cox } 1792801687dSKonstantin Belousov save = curthread_pflags_set(newflags); 18028993443SEd Schouten 18128993443SEd Schouten while (n > 0 && uio->uio_resid) { 18228993443SEd Schouten iov = uio->uio_iov; 18328993443SEd Schouten cnt = iov->iov_len; 18428993443SEd Schouten if (cnt == 0) { 18528993443SEd Schouten uio->uio_iov++; 18628993443SEd Schouten uio->uio_iovcnt--; 18728993443SEd Schouten continue; 18828993443SEd Schouten } 18928993443SEd Schouten if (cnt > n) 19028993443SEd Schouten cnt = n; 19128993443SEd Schouten 19228993443SEd Schouten switch (uio->uio_segflg) { 19328993443SEd Schouten 19428993443SEd Schouten case UIO_USERSPACE: 19508b163faSMatthew D Fleming maybe_yield(); 19628993443SEd Schouten if (uio->uio_rw == UIO_READ) 19728993443SEd Schouten error = copyout(cp, iov->iov_base, cnt); 19828993443SEd Schouten else 19928993443SEd Schouten error = copyin(iov->iov_base, cp, cnt); 20028993443SEd Schouten if (error) 20128993443SEd Schouten goto out; 20228993443SEd Schouten break; 20328993443SEd Schouten 20428993443SEd Schouten case UIO_SYSSPACE: 20528993443SEd Schouten if (uio->uio_rw == UIO_READ) 20628993443SEd Schouten bcopy(cp, iov->iov_base, cnt); 20728993443SEd Schouten else 20828993443SEd Schouten bcopy(iov->iov_base, cp, cnt); 20928993443SEd Schouten break; 21028993443SEd Schouten case UIO_NOCOPY: 21128993443SEd Schouten break; 21228993443SEd Schouten } 21328993443SEd Schouten iov->iov_base = (char *)iov->iov_base + cnt; 21428993443SEd Schouten iov->iov_len -= cnt; 21528993443SEd Schouten uio->uio_resid -= cnt; 21628993443SEd Schouten uio->uio_offset += cnt; 21728993443SEd Schouten cp = (char *)cp + cnt; 21828993443SEd Schouten n -= cnt; 21928993443SEd Schouten } 22028993443SEd Schouten out: 2212801687dSKonstantin Belousov curthread_pflags_restore(save); 22228993443SEd Schouten return (error); 22328993443SEd Schouten } 22428993443SEd Schouten 22528993443SEd Schouten /* 22628993443SEd Schouten * Wrapper for uiomove() that validates the arguments against a known-good 22728993443SEd Schouten * kernel buffer. Currently, uiomove accepts a signed (n) argument, which 22828993443SEd Schouten * is almost definitely a bad thing, so we catch that here as well. We 22928993443SEd Schouten * return a runtime failure, but it might be desirable to generate a runtime 23028993443SEd Schouten * assertion failure instead. 23128993443SEd Schouten */ 23228993443SEd Schouten int 23328993443SEd Schouten uiomove_frombuf(void *buf, int buflen, struct uio *uio) 23428993443SEd Schouten { 235526d0bd5SKonstantin Belousov size_t offset, n; 23628993443SEd Schouten 23728993443SEd Schouten if (uio->uio_offset < 0 || uio->uio_resid < 0 || 23828993443SEd Schouten (offset = uio->uio_offset) != uio->uio_offset) 23928993443SEd Schouten return (EINVAL); 24028993443SEd Schouten if (buflen <= 0 || offset >= buflen) 24128993443SEd Schouten return (0); 242526d0bd5SKonstantin Belousov if ((n = buflen - offset) > IOSIZE_MAX) 24328993443SEd Schouten return (EINVAL); 24428993443SEd Schouten return (uiomove((char *)buf + offset, n, uio)); 24528993443SEd Schouten } 24628993443SEd Schouten 24728993443SEd Schouten /* 24828993443SEd Schouten * Give next character to user as result of read. 24928993443SEd Schouten */ 25028993443SEd Schouten int 25128993443SEd Schouten ureadc(int c, struct uio *uio) 25228993443SEd Schouten { 25328993443SEd Schouten struct iovec *iov; 25428993443SEd Schouten char *iov_base; 25528993443SEd Schouten 25628993443SEd Schouten WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 25728993443SEd Schouten "Calling ureadc()"); 25828993443SEd Schouten 25928993443SEd Schouten again: 26028993443SEd Schouten if (uio->uio_iovcnt == 0 || uio->uio_resid == 0) 26128993443SEd Schouten panic("ureadc"); 26228993443SEd Schouten iov = uio->uio_iov; 26328993443SEd Schouten if (iov->iov_len == 0) { 26428993443SEd Schouten uio->uio_iovcnt--; 26528993443SEd Schouten uio->uio_iov++; 26628993443SEd Schouten goto again; 26728993443SEd Schouten } 26828993443SEd Schouten switch (uio->uio_segflg) { 26928993443SEd Schouten 27028993443SEd Schouten case UIO_USERSPACE: 27128993443SEd Schouten if (subyte(iov->iov_base, c) < 0) 27228993443SEd Schouten return (EFAULT); 27328993443SEd Schouten break; 27428993443SEd Schouten 27528993443SEd Schouten case UIO_SYSSPACE: 27628993443SEd Schouten iov_base = iov->iov_base; 27728993443SEd Schouten *iov_base = c; 27828993443SEd Schouten break; 27928993443SEd Schouten 28028993443SEd Schouten case UIO_NOCOPY: 28128993443SEd Schouten break; 28228993443SEd Schouten } 28328993443SEd Schouten iov->iov_base = (char *)iov->iov_base + 1; 28428993443SEd Schouten iov->iov_len--; 28528993443SEd Schouten uio->uio_resid--; 28628993443SEd Schouten uio->uio_offset++; 28728993443SEd Schouten return (0); 28828993443SEd Schouten } 28928993443SEd Schouten 29028993443SEd Schouten int 29128993443SEd Schouten copyinfrom(const void * __restrict src, void * __restrict dst, size_t len, 29228993443SEd Schouten int seg) 29328993443SEd Schouten { 29428993443SEd Schouten int error = 0; 29528993443SEd Schouten 29628993443SEd Schouten switch (seg) { 29728993443SEd Schouten case UIO_USERSPACE: 29828993443SEd Schouten error = copyin(src, dst, len); 29928993443SEd Schouten break; 30028993443SEd Schouten case UIO_SYSSPACE: 30128993443SEd Schouten bcopy(src, dst, len); 30228993443SEd Schouten break; 30328993443SEd Schouten default: 30428993443SEd Schouten panic("copyinfrom: bad seg %d\n", seg); 30528993443SEd Schouten } 30628993443SEd Schouten return (error); 30728993443SEd Schouten } 30828993443SEd Schouten 30928993443SEd Schouten int 31028993443SEd Schouten copyinstrfrom(const void * __restrict src, void * __restrict dst, size_t len, 31128993443SEd Schouten size_t * __restrict copied, int seg) 31228993443SEd Schouten { 31328993443SEd Schouten int error = 0; 31428993443SEd Schouten 31528993443SEd Schouten switch (seg) { 31628993443SEd Schouten case UIO_USERSPACE: 31728993443SEd Schouten error = copyinstr(src, dst, len, copied); 31828993443SEd Schouten break; 31928993443SEd Schouten case UIO_SYSSPACE: 32028993443SEd Schouten error = copystr(src, dst, len, copied); 32128993443SEd Schouten break; 32228993443SEd Schouten default: 32328993443SEd Schouten panic("copyinstrfrom: bad seg %d\n", seg); 32428993443SEd Schouten } 32528993443SEd Schouten return (error); 32628993443SEd Schouten } 32728993443SEd Schouten 32828993443SEd Schouten int 329cfb09e00SAlfred Perlstein copyiniov(const struct iovec *iovp, u_int iovcnt, struct iovec **iov, int error) 33028993443SEd Schouten { 33128993443SEd Schouten u_int iovlen; 33228993443SEd Schouten 33328993443SEd Schouten *iov = NULL; 33428993443SEd Schouten if (iovcnt > UIO_MAXIOV) 33528993443SEd Schouten return (error); 33628993443SEd Schouten iovlen = iovcnt * sizeof (struct iovec); 33728993443SEd Schouten *iov = malloc(iovlen, M_IOV, M_WAITOK); 33828993443SEd Schouten error = copyin(iovp, *iov, iovlen); 33928993443SEd Schouten if (error) { 34028993443SEd Schouten free(*iov, M_IOV); 34128993443SEd Schouten *iov = NULL; 34228993443SEd Schouten } 34328993443SEd Schouten return (error); 34428993443SEd Schouten } 34528993443SEd Schouten 34628993443SEd Schouten int 347cfb09e00SAlfred Perlstein copyinuio(const struct iovec *iovp, u_int iovcnt, struct uio **uiop) 34828993443SEd Schouten { 34928993443SEd Schouten struct iovec *iov; 35028993443SEd Schouten struct uio *uio; 35128993443SEd Schouten u_int iovlen; 35228993443SEd Schouten int error, i; 35328993443SEd Schouten 35428993443SEd Schouten *uiop = NULL; 35528993443SEd Schouten if (iovcnt > UIO_MAXIOV) 35628993443SEd Schouten return (EINVAL); 35728993443SEd Schouten iovlen = iovcnt * sizeof (struct iovec); 35828993443SEd Schouten uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK); 35928993443SEd Schouten iov = (struct iovec *)(uio + 1); 36028993443SEd Schouten error = copyin(iovp, iov, iovlen); 36128993443SEd Schouten if (error) { 36228993443SEd Schouten free(uio, M_IOV); 36328993443SEd Schouten return (error); 36428993443SEd Schouten } 36528993443SEd Schouten uio->uio_iov = iov; 36628993443SEd Schouten uio->uio_iovcnt = iovcnt; 36728993443SEd Schouten uio->uio_segflg = UIO_USERSPACE; 36828993443SEd Schouten uio->uio_offset = -1; 36928993443SEd Schouten uio->uio_resid = 0; 37028993443SEd Schouten for (i = 0; i < iovcnt; i++) { 371526d0bd5SKonstantin Belousov if (iov->iov_len > IOSIZE_MAX - uio->uio_resid) { 37228993443SEd Schouten free(uio, M_IOV); 37328993443SEd Schouten return (EINVAL); 37428993443SEd Schouten } 37528993443SEd Schouten uio->uio_resid += iov->iov_len; 37628993443SEd Schouten iov++; 37728993443SEd Schouten } 37828993443SEd Schouten *uiop = uio; 37928993443SEd Schouten return (0); 38028993443SEd Schouten } 38128993443SEd Schouten 38228993443SEd Schouten struct uio * 38328993443SEd Schouten cloneuio(struct uio *uiop) 38428993443SEd Schouten { 38528993443SEd Schouten struct uio *uio; 38628993443SEd Schouten int iovlen; 38728993443SEd Schouten 38828993443SEd Schouten iovlen = uiop->uio_iovcnt * sizeof (struct iovec); 38928993443SEd Schouten uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK); 39028993443SEd Schouten *uio = *uiop; 39128993443SEd Schouten uio->uio_iov = (struct iovec *)(uio + 1); 39228993443SEd Schouten bcopy(uiop->uio_iov, uio->uio_iov, iovlen); 39328993443SEd Schouten return (uio); 39428993443SEd Schouten } 3950f502d1cSKonstantin Belousov 3960f502d1cSKonstantin Belousov /* 3970f502d1cSKonstantin Belousov * Map some anonymous memory in user space of size sz, rounded up to the page 3980f502d1cSKonstantin Belousov * boundary. 3990f502d1cSKonstantin Belousov */ 4000f502d1cSKonstantin Belousov int 4010f502d1cSKonstantin Belousov copyout_map(struct thread *td, vm_offset_t *addr, size_t sz) 4020f502d1cSKonstantin Belousov { 403cce6e354SKonstantin Belousov struct vmspace *vms; 4040f502d1cSKonstantin Belousov int error; 4050f502d1cSKonstantin Belousov vm_size_t size; 4060f502d1cSKonstantin Belousov 407cce6e354SKonstantin Belousov vms = td->td_proc->p_vmspace; 408cce6e354SKonstantin Belousov 4090f502d1cSKonstantin Belousov /* 4100f502d1cSKonstantin Belousov * Map somewhere after heap in process memory. 4110f502d1cSKonstantin Belousov */ 4120f502d1cSKonstantin Belousov PROC_LOCK(td->td_proc); 4130f502d1cSKonstantin Belousov *addr = round_page((vm_offset_t)vms->vm_daddr + 4140f502d1cSKonstantin Belousov lim_max(td->td_proc, RLIMIT_DATA)); 4150f502d1cSKonstantin Belousov PROC_UNLOCK(td->td_proc); 4160f502d1cSKonstantin Belousov 4170f502d1cSKonstantin Belousov /* round size up to page boundry */ 4180f502d1cSKonstantin Belousov size = (vm_size_t)round_page(sz); 4190f502d1cSKonstantin Belousov 4200f502d1cSKonstantin Belousov error = vm_mmap(&vms->vm_map, addr, size, PROT_READ | PROT_WRITE, 4210f502d1cSKonstantin Belousov VM_PROT_ALL, MAP_PRIVATE | MAP_ANON, OBJT_DEFAULT, NULL, 0); 4220f502d1cSKonstantin Belousov 4230f502d1cSKonstantin Belousov return (error); 4240f502d1cSKonstantin Belousov } 4250f502d1cSKonstantin Belousov 4260f502d1cSKonstantin Belousov /* 4270f502d1cSKonstantin Belousov * Unmap memory in user space. 4280f502d1cSKonstantin Belousov */ 4290f502d1cSKonstantin Belousov int 4300f502d1cSKonstantin Belousov copyout_unmap(struct thread *td, vm_offset_t addr, size_t sz) 4310f502d1cSKonstantin Belousov { 4320f502d1cSKonstantin Belousov vm_map_t map; 4330f502d1cSKonstantin Belousov vm_size_t size; 4340f502d1cSKonstantin Belousov 435937060a8SKonstantin Belousov if (sz == 0) 436937060a8SKonstantin Belousov return (0); 437937060a8SKonstantin Belousov 4380f502d1cSKonstantin Belousov map = &td->td_proc->p_vmspace->vm_map; 4390f502d1cSKonstantin Belousov size = (vm_size_t)round_page(sz); 4400f502d1cSKonstantin Belousov 441cea8f30aSKonstantin Belousov if (vm_map_remove(map, addr, addr + size) != KERN_SUCCESS) 4420f502d1cSKonstantin Belousov return (EINVAL); 4430f502d1cSKonstantin Belousov 4440f502d1cSKonstantin Belousov return (0); 4450f502d1cSKonstantin Belousov } 446*4f3dc900SKonstantin Belousov 447*4f3dc900SKonstantin Belousov #ifdef NO_FUEWORD 448*4f3dc900SKonstantin Belousov /* 449*4f3dc900SKonstantin Belousov * XXXKIB The temporal implementation of fue*() functions which do not 450*4f3dc900SKonstantin Belousov * handle usermode -1 properly, mixing it with the fault code. Keep 451*4f3dc900SKonstantin Belousov * this until MD code is written. Currently sparc64, mips and arm do 452*4f3dc900SKonstantin Belousov * not have proper implementation. 453*4f3dc900SKonstantin Belousov */ 454*4f3dc900SKonstantin Belousov 455*4f3dc900SKonstantin Belousov int 456*4f3dc900SKonstantin Belousov fueword(const void *base, long *val) 457*4f3dc900SKonstantin Belousov { 458*4f3dc900SKonstantin Belousov long res; 459*4f3dc900SKonstantin Belousov 460*4f3dc900SKonstantin Belousov res = fuword(base); 461*4f3dc900SKonstantin Belousov if (res == -1) 462*4f3dc900SKonstantin Belousov return (-1); 463*4f3dc900SKonstantin Belousov *val = res; 464*4f3dc900SKonstantin Belousov return (0); 465*4f3dc900SKonstantin Belousov } 466*4f3dc900SKonstantin Belousov 467*4f3dc900SKonstantin Belousov int 468*4f3dc900SKonstantin Belousov fueword32(const void *base, int32_t *val) 469*4f3dc900SKonstantin Belousov { 470*4f3dc900SKonstantin Belousov int32_t res; 471*4f3dc900SKonstantin Belousov 472*4f3dc900SKonstantin Belousov res = fuword32(base); 473*4f3dc900SKonstantin Belousov if (res == -1) 474*4f3dc900SKonstantin Belousov return (-1); 475*4f3dc900SKonstantin Belousov *val = res; 476*4f3dc900SKonstantin Belousov return (0); 477*4f3dc900SKonstantin Belousov } 478*4f3dc900SKonstantin Belousov 479*4f3dc900SKonstantin Belousov #ifdef _LP64 480*4f3dc900SKonstantin Belousov int 481*4f3dc900SKonstantin Belousov fueword64(const void *base, int64_t *val) 482*4f3dc900SKonstantin Belousov { 483*4f3dc900SKonstantin Belousov int32_t res; 484*4f3dc900SKonstantin Belousov 485*4f3dc900SKonstantin Belousov res = fuword64(base); 486*4f3dc900SKonstantin Belousov if (res == -1) 487*4f3dc900SKonstantin Belousov return (-1); 488*4f3dc900SKonstantin Belousov *val = res; 489*4f3dc900SKonstantin Belousov return (0); 490*4f3dc900SKonstantin Belousov } 491*4f3dc900SKonstantin Belousov #endif 492*4f3dc900SKonstantin Belousov 493*4f3dc900SKonstantin Belousov int 494*4f3dc900SKonstantin Belousov casueword32(volatile uint32_t *base, uint32_t oldval, uint32_t *oldvalp, 495*4f3dc900SKonstantin Belousov uint32_t newval) 496*4f3dc900SKonstantin Belousov { 497*4f3dc900SKonstantin Belousov int32_t ov; 498*4f3dc900SKonstantin Belousov 499*4f3dc900SKonstantin Belousov ov = casuword32(base, oldval, newval); 500*4f3dc900SKonstantin Belousov if (ov == -1) 501*4f3dc900SKonstantin Belousov return (-1); 502*4f3dc900SKonstantin Belousov *oldvalp = ov; 503*4f3dc900SKonstantin Belousov return (0); 504*4f3dc900SKonstantin Belousov } 505*4f3dc900SKonstantin Belousov 506*4f3dc900SKonstantin Belousov int 507*4f3dc900SKonstantin Belousov casueword(volatile u_long *p, u_long oldval, u_long *oldvalp, u_long newval) 508*4f3dc900SKonstantin Belousov { 509*4f3dc900SKonstantin Belousov u_long ov; 510*4f3dc900SKonstantin Belousov 511*4f3dc900SKonstantin Belousov ov = casuword(p, oldval, newval); 512*4f3dc900SKonstantin Belousov if (ov == -1) 513*4f3dc900SKonstantin Belousov return (-1); 514*4f3dc900SKonstantin Belousov *oldvalp = ov; 515*4f3dc900SKonstantin Belousov return (0); 516*4f3dc900SKonstantin Belousov } 517*4f3dc900SKonstantin Belousov #else /* NO_FUEWORD */ 518*4f3dc900SKonstantin Belousov int32_t 519*4f3dc900SKonstantin Belousov fuword32(const void *addr) 520*4f3dc900SKonstantin Belousov { 521*4f3dc900SKonstantin Belousov int rv; 522*4f3dc900SKonstantin Belousov int32_t val; 523*4f3dc900SKonstantin Belousov 524*4f3dc900SKonstantin Belousov rv = fueword32(addr, &val); 525*4f3dc900SKonstantin Belousov return (rv == -1 ? -1 : val); 526*4f3dc900SKonstantin Belousov } 527*4f3dc900SKonstantin Belousov 528*4f3dc900SKonstantin Belousov #ifdef _LP64 529*4f3dc900SKonstantin Belousov int64_t 530*4f3dc900SKonstantin Belousov fuword64(const void *addr) 531*4f3dc900SKonstantin Belousov { 532*4f3dc900SKonstantin Belousov int rv; 533*4f3dc900SKonstantin Belousov int64_t val; 534*4f3dc900SKonstantin Belousov 535*4f3dc900SKonstantin Belousov rv = fueword64(addr, &val); 536*4f3dc900SKonstantin Belousov return (rv == -1 ? -1 : val); 537*4f3dc900SKonstantin Belousov } 538*4f3dc900SKonstantin Belousov #endif /* _LP64 */ 539*4f3dc900SKonstantin Belousov 540*4f3dc900SKonstantin Belousov long 541*4f3dc900SKonstantin Belousov fuword(const void *addr) 542*4f3dc900SKonstantin Belousov { 543*4f3dc900SKonstantin Belousov long val; 544*4f3dc900SKonstantin Belousov int rv; 545*4f3dc900SKonstantin Belousov 546*4f3dc900SKonstantin Belousov rv = fueword(addr, &val); 547*4f3dc900SKonstantin Belousov return (rv == -1 ? -1 : val); 548*4f3dc900SKonstantin Belousov } 549*4f3dc900SKonstantin Belousov 550*4f3dc900SKonstantin Belousov uint32_t 551*4f3dc900SKonstantin Belousov casuword32(volatile uint32_t *addr, uint32_t old, uint32_t new) 552*4f3dc900SKonstantin Belousov { 553*4f3dc900SKonstantin Belousov int rv; 554*4f3dc900SKonstantin Belousov uint32_t val; 555*4f3dc900SKonstantin Belousov 556*4f3dc900SKonstantin Belousov rv = casueword32(addr, old, &val, new); 557*4f3dc900SKonstantin Belousov return (rv == -1 ? -1 : val); 558*4f3dc900SKonstantin Belousov } 559*4f3dc900SKonstantin Belousov 560*4f3dc900SKonstantin Belousov u_long 561*4f3dc900SKonstantin Belousov casuword(volatile u_long *addr, u_long old, u_long new) 562*4f3dc900SKonstantin Belousov { 563*4f3dc900SKonstantin Belousov int rv; 564*4f3dc900SKonstantin Belousov u_long val; 565*4f3dc900SKonstantin Belousov 566*4f3dc900SKonstantin Belousov rv = casueword(addr, old, &val, new); 567*4f3dc900SKonstantin Belousov return (rv == -1 ? -1 : val); 568*4f3dc900SKonstantin Belousov } 569*4f3dc900SKonstantin Belousov 570*4f3dc900SKonstantin Belousov #endif /* NO_FUEWORD */ 571