uio_machdep.c revision 134127
127837Sdavidn/* 266830Sobrien * Copyright (c) 2004 Alan L. Cox <alc@cs.rice.edu> 366830Sobrien * Copyright (c) 1982, 1986, 1991, 1993 466830Sobrien * The Regents of the University of California. All rights reserved. 566830Sobrien * (c) UNIX System Laboratories, Inc. 666830Sobrien * All or some portions of this file are derived from material licensed 766830Sobrien * to the University of California by American Telephone and Telegraph 866830Sobrien * Co. or Unix System Laboratories, Inc. and are reproduced herein with 966830Sobrien * the permission of UNIX System Laboratories, Inc. 1066830Sobrien * 1166830Sobrien * Redistribution and use in source and binary forms, with or without 1266830Sobrien * modification, are permitted provided that the following conditions 1366830Sobrien * are met: 1466830Sobrien * 1. Redistributions of source code must retain the above copyright 1566830Sobrien * notice, this list of conditions and the following disclaimer. 1666830Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1766830Sobrien * notice, this list of conditions and the following disclaimer in the 1866830Sobrien * documentation and/or other materials provided with the distribution. 1966830Sobrien * 4. Neither the name of the University nor the names of its contributors 2066830Sobrien * may be used to endorse or promote products derived from this software 2166830Sobrien * without specific prior written permission. 2266830Sobrien * 2366830Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2466830Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2566830Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2666830Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2750472Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2866830Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2927837Sdavidn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3051231Ssheldonh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3127837Sdavidn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3227837Sdavidn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3327837Sdavidn * SUCH DAMAGE. 3427837Sdavidn * 35232976Sed * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94 3627837Sdavidn */ 3727837Sdavidn 3827837Sdavidn#include <sys/cdefs.h> 3927837Sdavidn__FBSDID("$FreeBSD: head/sys/i386/i386/uio_machdep.c 134127 2004-08-21 18:50:34Z alc $"); 4027837Sdavidn 4127837Sdavidn#include <sys/param.h> 4251231Ssheldonh#include <sys/kernel.h> 4327837Sdavidn#include <sys/lock.h> 4451231Ssheldonh#include <sys/mutex.h> 4527837Sdavidn#include <sys/proc.h> 46117324Smtm#include <sys/sf_buf.h> 4762640Stg#include <sys/systm.h> 48117324Smtm#include <sys/uio.h> 4998189Sgordon 5096830Sgordon#include <vm/vm.h> 5196830Sgordon#include <vm/vm_page.h> 5296830Sgordon 5396830Sgordon/* 5496830Sgordon * Implement uiomove(9) from physical memory using sf_bufs to reduce 5596830Sgordon * the creation and destruction of ephemeral mappings. 5696830Sgordon */ 5796830Sgordonint 5896830Sgordonuiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio) 5996830Sgordon{ 6096830Sgordon struct sf_buf *sf; 6196830Sgordon struct thread *td = curthread; 62117324Smtm struct iovec *iov; 63117324Smtm void *cp; 64117324Smtm vm_offset_t page_offset; 6563307Smarkm size_t cnt; 66117324Smtm int error = 0; 67117324Smtm int save = 0; 68117324Smtm 69130151Sschweikh KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, 70136615Sschweikh ("uiomove_fromphys: mode")); 71136615Sschweikh KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, 72117324Smtm ("uiomove_fromphys proc")); 73117324Smtm save = td->td_pflags & TDP_DEADLKTREAT; 74117324Smtm td->td_pflags |= TDP_DEADLKTREAT; 75117324Smtm while (n > 0 && uio->uio_resid) { 76117324Smtm iov = uio->uio_iov; 77117324Smtm cnt = iov->iov_len; 78117324Smtm if (cnt == 0) { 7963307Smarkm uio->uio_iov++; 80117324Smtm uio->uio_iovcnt--; 81117324Smtm continue; 82117324Smtm } 83138847Srse if (cnt > n) 84138847Srse cnt = n; 8553550Sdillon page_offset = offset & PAGE_MASK; 86153027Sdougb cnt = min(cnt, PAGE_SIZE - page_offset); 87153027Sdougb sf = sf_buf_alloc(ma[offset >> PAGE_SHIFT], 0); 88153027Sdougb cp = (char *)sf_buf_kva(sf) + page_offset; 89153027Sdougb switch (uio->uio_segflg) { 90153027Sdougb case UIO_USERSPACE: 91153027Sdougb if (ticks - PCPU_GET(switchticks) >= hogticks) 92153027Sdougb uio_yield(); 93117324Smtm if (uio->uio_rw == UIO_READ) 94131135Smtm error = copyout(cp, iov->iov_base, cnt); 95131135Smtm else 96117324Smtm error = copyin(iov->iov_base, cp, cnt); 9727837Sdavidn if (error) { 98117324Smtm sf_buf_free(sf); 99117324Smtm goto out; 100117324Smtm } 101187685Sbz break; 102117324Smtm case UIO_SYSSPACE: 10327837Sdavidn if (uio->uio_rw == UIO_READ) 10486856Sdarrenr bcopy(cp, iov->iov_base, cnt); 10585219Sdarrenr else 10686856Sdarrenr bcopy(iov->iov_base, cp, cnt); 10727837Sdavidn break; 10827837Sdavidn case UIO_NOCOPY: 109 break; 110 } 111 sf_buf_free(sf); 112 iov->iov_base = (char *)iov->iov_base + cnt; 113 iov->iov_len -= cnt; 114 uio->uio_resid -= cnt; 115 uio->uio_offset += cnt; 116 offset += cnt; 117 n -= cnt; 118 } 119out: 120 if (save == 0) 121 td->td_pflags &= ~TDP_DEADLKTREAT; 122 return (error); 123} 124