uio_machdep.c revision 127788
1219820Sjeff/* 2219820Sjeff * Copyright (c) 2004 Alan L. Cox <alc@cs.rice.edu> 3219820Sjeff * Copyright (c) 1982, 1986, 1991, 1993 4219820Sjeff * The Regents of the University of California. All rights reserved. 5219820Sjeff * (c) UNIX System Laboratories, Inc. 6219820Sjeff * All or some portions of this file are derived from material licensed 7219820Sjeff * to the University of California by American Telephone and Telegraph 8219820Sjeff * Co. or Unix System Laboratories, Inc. and are reproduced herein with 9219820Sjeff * the permission of UNIX System Laboratories, Inc. 10219820Sjeff * 11219820Sjeff * Redistribution and use in source and binary forms, with or without 12219820Sjeff * modification, are permitted provided that the following conditions 13219820Sjeff * are met: 14219820Sjeff * 1. Redistributions of source code must retain the above copyright 15219820Sjeff * notice, this list of conditions and the following disclaimer. 16219820Sjeff * 2. Redistributions in binary form must reproduce the above copyright 17219820Sjeff * notice, this list of conditions and the following disclaimer in the 18219820Sjeff * documentation and/or other materials provided with the distribution. 19219820Sjeff * 3. All advertising materials mentioning features or use of this software 20219820Sjeff * must display the following acknowledgement: 21219820Sjeff * This product includes software developed by the University of 22219820Sjeff * California, Berkeley and its contributors. 23219820Sjeff * 4. Neither the name of the University nor the names of its contributors 24219820Sjeff * may be used to endorse or promote products derived from this software 25219820Sjeff * without specific prior written permission. 26219820Sjeff * 27219820Sjeff * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28219820Sjeff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29219820Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30219820Sjeff * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31219820Sjeff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32219820Sjeff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33219820Sjeff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34219820Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35219820Sjeff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36219820Sjeff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37219820Sjeff * SUCH DAMAGE. 38219820Sjeff * 39219820Sjeff * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94 40219820Sjeff */ 41219820Sjeff 42219820Sjeff#include <sys/cdefs.h> 43219820Sjeff__FBSDID("$FreeBSD: head/sys/sparc64/sparc64/uio_machdep.c 127788 2004-04-03 09:16:27Z alc $"); 44219820Sjeff 45219820Sjeff#include <sys/param.h> 46219820Sjeff#include <sys/kernel.h> 47219820Sjeff#include <sys/lock.h> 48219820Sjeff#include <sys/mutex.h> 49219820Sjeff#include <sys/proc.h> 50219820Sjeff#include <sys/sf_buf.h> 51219820Sjeff#include <sys/systm.h> 52219820Sjeff#include <sys/uio.h> 53219820Sjeff 54219820Sjeff#include <vm/vm.h> 55219820Sjeff#include <vm/vm_page.h> 56219820Sjeff#include <vm/vm_param.h> 57219820Sjeff 58219820Sjeff#include <machine/tlb.h> 59219820Sjeff 60219820Sjeff/* 61219820Sjeff * Implement uiomove(9) from physical memory using a combination 62219820Sjeff * of the direct mapping and sf_bufs to reduce the creation and 63219820Sjeff * destruction of ephemeral mappings. 64219820Sjeff */ 65219820Sjeffint 66219820Sjeffuiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio) 67219820Sjeff{ 68219820Sjeff struct sf_buf *sf; 69219820Sjeff struct thread *td = curthread; 70219820Sjeff struct iovec *iov; 71219820Sjeff void *cp; 72219820Sjeff vm_offset_t page_offset; 73219820Sjeff vm_paddr_t pa; 74219820Sjeff vm_page_t m; 75219820Sjeff size_t cnt; 76219820Sjeff int error = 0; 77219820Sjeff int save = 0; 78219820Sjeff 79219820Sjeff KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, 80219820Sjeff ("uiomove_fromphys: mode")); 81219820Sjeff KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, 82219820Sjeff ("uiomove_fromphys proc")); 83219820Sjeff if (td != NULL) { 84219820Sjeff mtx_lock_spin(&sched_lock); 85219820Sjeff save = td->td_flags & TDF_DEADLKTREAT; 86219820Sjeff td->td_flags |= TDF_DEADLKTREAT; 87219820Sjeff mtx_unlock_spin(&sched_lock); 88219820Sjeff } 89219820Sjeff while (n > 0 && uio->uio_resid) { 90219820Sjeff iov = uio->uio_iov; 91219820Sjeff cnt = iov->iov_len; 92219820Sjeff if (cnt == 0) { 93219820Sjeff uio->uio_iov++; 94219820Sjeff uio->uio_iovcnt--; 95219820Sjeff continue; 96219820Sjeff } 97219820Sjeff if (cnt > n) 98219820Sjeff cnt = n; 99219820Sjeff page_offset = offset & PAGE_MASK; 100219820Sjeff cnt = min(cnt, PAGE_SIZE - page_offset); 101219820Sjeff m = ma[offset >> PAGE_SHIFT]; 102219820Sjeff pa = VM_PAGE_TO_PHYS(m); 103219820Sjeff if (m->md.color != DCACHE_COLOR(pa)) { 104219820Sjeff sf = sf_buf_alloc(m, 0); 105219820Sjeff cp = (char *)sf_buf_kva(sf) + page_offset; 106219820Sjeff } else { 107219820Sjeff sf = NULL; 108219820Sjeff cp = (char *)TLB_PHYS_TO_DIRECT(pa) + page_offset; 109219820Sjeff } 110219820Sjeff switch (uio->uio_segflg) { 111219820Sjeff case UIO_USERSPACE: 112219820Sjeff if (ticks - PCPU_GET(switchticks) >= hogticks) 113219820Sjeff uio_yield(); 114219820Sjeff if (uio->uio_rw == UIO_READ) 115219820Sjeff error = copyout(cp, iov->iov_base, cnt); 116219820Sjeff else 117219820Sjeff error = copyin(iov->iov_base, cp, cnt); 118219820Sjeff if (error) 119219820Sjeff goto out; 120219820Sjeff break; 121219820Sjeff case UIO_SYSSPACE: 122219820Sjeff if (uio->uio_rw == UIO_READ) 123219820Sjeff bcopy(cp, iov->iov_base, cnt); 124219820Sjeff else 125219820Sjeff bcopy(iov->iov_base, cp, cnt); 126219820Sjeff break; 127219820Sjeff case UIO_NOCOPY: 128219820Sjeff break; 129219820Sjeff } 130219820Sjeff if (sf != NULL) 131219820Sjeff sf_buf_free(sf); 132219820Sjeff iov->iov_base = (char *)iov->iov_base + cnt; 133219820Sjeff iov->iov_len -= cnt; 134219820Sjeff uio->uio_resid -= cnt; 135219820Sjeff uio->uio_offset += cnt; 136219820Sjeff offset += cnt; 137219820Sjeff n -= cnt; 138219820Sjeff } 139219820Sjeffout: 140219820Sjeff if (td != NULL && save == 0) { 141219820Sjeff mtx_lock_spin(&sched_lock); 142219820Sjeff td->td_flags &= ~TDF_DEADLKTREAT; 143219820Sjeff mtx_unlock_spin(&sched_lock); 144219820Sjeff } 145219820Sjeff return (error); 146219820Sjeff} 147219820Sjeff