1176771Sraj/*- 2176771Sraj * Copyright (c) 2004 Alan L. Cox <alc@cs.rice.edu> 3176771Sraj * Copyright (c) 1982, 1986, 1991, 1993 4176771Sraj * The Regents of the University of California. All rights reserved. 5176771Sraj * (c) UNIX System Laboratories, Inc. 6176771Sraj * All or some portions of this file are derived from material licensed 7176771Sraj * to the University of California by American Telephone and Telegraph 8176771Sraj * Co. or Unix System Laboratories, Inc. and are reproduced herein with 9176771Sraj * the permission of UNIX System Laboratories, Inc. 10176771Sraj * 11176771Sraj * Redistribution and use in source and binary forms, with or without 12176771Sraj * modification, are permitted provided that the following conditions 13176771Sraj * are met: 14176771Sraj * 1. Redistributions of source code must retain the above copyright 15176771Sraj * notice, this list of conditions and the following disclaimer. 16176771Sraj * 2. Redistributions in binary form must reproduce the above copyright 17176771Sraj * notice, this list of conditions and the following disclaimer in the 18176771Sraj * documentation and/or other materials provided with the distribution. 19176771Sraj * 4. Neither the name of the University nor the names of its contributors 20176771Sraj * may be used to endorse or promote products derived from this software 21176771Sraj * without specific prior written permission. 22176771Sraj * 23176771Sraj * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24176771Sraj * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25176771Sraj * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26176771Sraj * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27176771Sraj * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28176771Sraj * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29176771Sraj * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30176771Sraj * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31176771Sraj * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32176771Sraj * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33176771Sraj * SUCH DAMAGE. 34176771Sraj * 35176771Sraj * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94 36176771Sraj */ 37176771Sraj 38176771Sraj#include <sys/cdefs.h> 39176771Sraj__FBSDID("$FreeBSD$"); 40176771Sraj 41176771Sraj#include <sys/param.h> 42253367Sae#include <sys/systm.h> 43176771Sraj#include <sys/kernel.h> 44176771Sraj#include <sys/lock.h> 45176771Sraj#include <sys/mutex.h> 46176771Sraj#include <sys/proc.h> 47176771Sraj#include <sys/uio.h> 48176771Sraj#include <sys/sf_buf.h> 49176771Sraj 50176771Sraj#include <vm/vm.h> 51176771Sraj#include <vm/vm_page.h> 52176771Sraj 53176771Sraj#include <machine/cpu.h> 54176771Sraj#include <machine/vmparam.h> 55176771Sraj#include <machine/md_var.h> 56176771Sraj 57176771Sraj/* 58176771Sraj * Implement uiomove(9) from physical memory using sf_bufs to 59176771Sraj * avoid the creation and destruction of ephemeral mappings. 60176771Sraj */ 61176771Srajint 62176771Srajuiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio) 63176771Sraj{ 64176771Sraj struct thread *td = curthread; 65176771Sraj struct iovec *iov; 66176771Sraj void *cp; 67176771Sraj vm_offset_t page_offset; 68176771Sraj vm_page_t m; 69176771Sraj size_t cnt; 70176771Sraj int error = 0; 71176771Sraj int save = 0; 72176771Sraj struct sf_buf *sf; 73176771Sraj 74176771Sraj KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, 75176771Sraj ("uiomove_fromphys: mode")); 76176771Sraj KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, 77176771Sraj ("uiomove_fromphys proc")); 78176771Sraj 79176771Sraj save = td->td_pflags & TDP_DEADLKTREAT; 80176771Sraj td->td_pflags |= TDP_DEADLKTREAT; 81176771Sraj while (n > 0 && uio->uio_resid) { 82176771Sraj iov = uio->uio_iov; 83176771Sraj cnt = iov->iov_len; 84176771Sraj if (cnt == 0) { 85176771Sraj uio->uio_iov++; 86176771Sraj uio->uio_iovcnt--; 87176771Sraj continue; 88176771Sraj } 89176771Sraj if (cnt > n) 90176771Sraj cnt = n; 91176771Sraj page_offset = offset & PAGE_MASK; 92176771Sraj cnt = min(cnt, PAGE_SIZE - page_offset); 93176771Sraj 94176771Sraj m = ma[offset >> PAGE_SHIFT]; 95176771Sraj sf = sf_buf_alloc(m, 0); 96176771Sraj cp = (char*)sf_buf_kva(sf) + page_offset; 97176771Sraj 98176771Sraj switch (uio->uio_segflg) { 99176771Sraj case UIO_USERSPACE: 100218195Smdf maybe_yield(); 101176771Sraj if (uio->uio_rw == UIO_READ) 102176771Sraj error = copyout(cp, iov->iov_base, cnt); 103176771Sraj else 104176771Sraj error = copyin(iov->iov_base, cp, cnt); 105176771Sraj if (error) { 106176771Sraj sf_buf_free(sf); 107176771Sraj goto out; 108176771Sraj } 109176771Sraj break; 110176771Sraj case UIO_SYSSPACE: 111176771Sraj if (uio->uio_rw == UIO_READ) 112176771Sraj bcopy(cp, iov->iov_base, cnt); 113176771Sraj else 114176771Sraj bcopy(iov->iov_base, cp, cnt); 115176771Sraj break; 116176771Sraj case UIO_NOCOPY: 117176771Sraj break; 118176771Sraj } 119176771Sraj sf_buf_free(sf); 120176771Sraj iov->iov_base = (char *)iov->iov_base + cnt; 121176771Sraj iov->iov_len -= cnt; 122176771Sraj uio->uio_resid -= cnt; 123176771Sraj uio->uio_offset += cnt; 124176771Sraj offset += cnt; 125176771Sraj n -= cnt; 126176771Sraj } 127176771Srajout: 128176771Sraj if (save == 0) 129176771Sraj td->td_pflags &= ~TDP_DEADLKTREAT; 130176771Sraj return (error); 131176771Sraj} 132