uio_machdep.c revision 127788
1144518Sdavidxu/* 2144518Sdavidxu * Copyright (c) 2004 Alan L. Cox <alc@cs.rice.edu> 3144518Sdavidxu * Copyright (c) 1982, 1986, 1991, 1993 4144518Sdavidxu * The Regents of the University of California. All rights reserved. 5144518Sdavidxu * (c) UNIX System Laboratories, Inc. 6144518Sdavidxu * All or some portions of this file are derived from material licensed 7144518Sdavidxu * to the University of California by American Telephone and Telegraph 8144518Sdavidxu * Co. or Unix System Laboratories, Inc. and are reproduced herein with 9144518Sdavidxu * the permission of UNIX System Laboratories, Inc. 10144518Sdavidxu * 11144518Sdavidxu * Redistribution and use in source and binary forms, with or without 12144518Sdavidxu * modification, are permitted provided that the following conditions 13144518Sdavidxu * are met: 14144518Sdavidxu * 1. Redistributions of source code must retain the above copyright 15144518Sdavidxu * notice, this list of conditions and the following disclaimer. 16144518Sdavidxu * 2. Redistributions in binary form must reproduce the above copyright 17144518Sdavidxu * notice, this list of conditions and the following disclaimer in the 18144518Sdavidxu * documentation and/or other materials provided with the distribution. 19144518Sdavidxu * 3. All advertising materials mentioning features or use of this software 20144518Sdavidxu * must display the following acknowledgement: 21144518Sdavidxu * This product includes software developed by the University of 22144518Sdavidxu * California, Berkeley and its contributors. 23144518Sdavidxu * 4. Neither the name of the University nor the names of its contributors 24144518Sdavidxu * may be used to endorse or promote products derived from this software 25144518Sdavidxu * without specific prior written permission. 26144518Sdavidxu * 27297706Skib * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28297706Skib * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29297706Skib * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30144518Sdavidxu * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31144518Sdavidxu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32144518Sdavidxu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33177853Sdavidxu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34177853Sdavidxu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35177853Sdavidxu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36300043Skib * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37177853Sdavidxu * SUCH DAMAGE. 38177853Sdavidxu * 39177853Sdavidxu * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94 40177853Sdavidxu */ 41177853Sdavidxu 42177853Sdavidxu#include <sys/cdefs.h> 43163334Sdavidxu__FBSDID("$FreeBSD: head/sys/i386/i386/uio_machdep.c 127788 2004-04-03 09:16:27Z alc $"); 44163334Sdavidxu 45163334Sdavidxu#include <sys/param.h> 46293858Svangyzen#include <sys/kernel.h> 47163334Sdavidxu#include <sys/lock.h> 48163334Sdavidxu#include <sys/mutex.h> 49163334Sdavidxu#include <sys/proc.h> 50163334Sdavidxu#include <sys/sf_buf.h> 51212077Sdavidxu#include <sys/systm.h> 52212077Sdavidxu#include <sys/uio.h> 53212077Sdavidxu 54293858Svangyzen#include <vm/vm.h> 55293858Svangyzen#include <vm/vm_page.h> 56212077Sdavidxu 57212077Sdavidxu/* 58212077Sdavidxu * Implement uiomove(9) from physical memory using sf_bufs to reduce 59144518Sdavidxu * the creation and destruction of ephemeral mappings. 60179970Sdavidxu */ 61161680Sdavidxuint 62179970Sdavidxuuiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio) 63179970Sdavidxu{ 64300043Skib struct sf_buf *sf; 65300043Skib struct thread *td = curthread; 66179970Sdavidxu struct iovec *iov; 67300043Skib void *cp; 68300043Skib vm_offset_t page_offset; 69300043Skib size_t cnt; 70300043Skib int error = 0; 71300043Skib int save = 0; 72300043Skib 73300043Skib KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, 74300043Skib ("uiomove_fromphys: mode")); 75300043Skib KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, 76300043Skib ("uiomove_fromphys proc")); 77300043Skib if (td != NULL) { 78300043Skib mtx_lock_spin(&sched_lock); 79300043Skib save = td->td_flags & TDF_DEADLKTREAT; 80300043Skib td->td_flags |= TDF_DEADLKTREAT; 81179970Sdavidxu mtx_unlock_spin(&sched_lock); 82161680Sdavidxu } 83161680Sdavidxu while (n > 0 && uio->uio_resid) { 84216641Sdavidxu iov = uio->uio_iov; 85216641Sdavidxu cnt = iov->iov_len; 86161680Sdavidxu if (cnt == 0) { 87216641Sdavidxu uio->uio_iov++; 88216641Sdavidxu uio->uio_iovcnt--; 89216641Sdavidxu continue; 90300043Skib } 91216641Sdavidxu if (cnt > n) 92216641Sdavidxu cnt = n; 93300043Skib page_offset = offset & PAGE_MASK; 94300043Skib cnt = min(cnt, PAGE_SIZE - page_offset); 95300043Skib sf = sf_buf_alloc(ma[offset >> PAGE_SHIFT], 0); 96216641Sdavidxu cp = (char *)sf_buf_kva(sf) + page_offset; 97300043Skib switch (uio->uio_segflg) { 98300043Skib case UIO_USERSPACE: 99300043Skib if (ticks - PCPU_GET(switchticks) >= hogticks) 100300043Skib uio_yield(); 101300043Skib if (uio->uio_rw == UIO_READ) 102300043Skib error = copyout(cp, iov->iov_base, cnt); 103300043Skib else 104300043Skib error = copyin(iov->iov_base, cp, cnt); 105300043Skib if (error) 106300043Skib goto out; 107300043Skib break; 108300043Skib case UIO_SYSSPACE: 109300043Skib if (uio->uio_rw == UIO_READ) 110300043Skib bcopy(cp, iov->iov_base, cnt); 111300043Skib else 112300043Skib bcopy(iov->iov_base, cp, cnt); 113216641Sdavidxu break; 114300043Skib case UIO_NOCOPY: 115300043Skib break; 116216641Sdavidxu } 117216641Sdavidxu sf_buf_free(sf); 118216641Sdavidxu iov->iov_base = (char *)iov->iov_base + cnt; 119216641Sdavidxu iov->iov_len -= cnt; 120179970Sdavidxu uio->uio_resid -= cnt; 121232144Sdavidxu uio->uio_offset += cnt; 122161680Sdavidxu offset += cnt; 123232144Sdavidxu n -= cnt; 124232144Sdavidxu } 125179970Sdavidxuout: 126179970Sdavidxu if (td != NULL && save == 0) { 127179970Sdavidxu mtx_lock_spin(&sched_lock); 128232144Sdavidxu td->td_flags &= ~TDF_DEADLKTREAT; 129232144Sdavidxu mtx_unlock_spin(&sched_lock); 130232144Sdavidxu } 131232144Sdavidxu return (error); 132232144Sdavidxu} 133232144Sdavidxu