uio_machdep.c revision 130028
1284990Scy/*
2284990Scy * Copyright (c) 2004 Alan L. Cox <alc@cs.rice.edu>
3284990Scy * Copyright (c) 1982, 1986, 1991, 1993
4284990Scy *	The Regents of the University of California.  All rights reserved.
5284990Scy * (c) UNIX System Laboratories, Inc.
6284990Scy * All or some portions of this file are derived from material licensed
7284990Scy * to the University of California by American Telephone and Telegraph
8284990Scy * Co. or Unix System Laboratories, Inc. and are reproduced herein with
9284990Scy * the permission of UNIX System Laboratories, Inc.
10284990Scy *
11284990Scy * Redistribution and use in source and binary forms, with or without
12284990Scy * modification, are permitted provided that the following conditions
13284990Scy * are met:
14284990Scy * 1. Redistributions of source code must retain the above copyright
15284990Scy *    notice, this list of conditions and the following disclaimer.
16284990Scy * 2. Redistributions in binary form must reproduce the above copyright
17284990Scy *    notice, this list of conditions and the following disclaimer in the
18284990Scy *    documentation and/or other materials provided with the distribution.
19284990Scy * 3. All advertising materials mentioning features or use of this software
20284990Scy *    must display the following acknowledgement:
21284990Scy *	This product includes software developed by the University of
22284990Scy *	California, Berkeley and its contributors.
23284990Scy * 4. Neither the name of the University nor the names of its contributors
24284990Scy *    may be used to endorse or promote products derived from this software
25284990Scy *    without specific prior written permission.
26284990Scy *
27284990Scy * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28284990Scy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29284990Scy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30284990Scy * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31284990Scy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32284990Scy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33284990Scy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34284990Scy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35284990Scy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36284990Scy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37284990Scy * SUCH DAMAGE.
38284990Scy *
39284990Scy *	@(#)kern_subr.c	8.3 (Berkeley) 1/21/94
40284990Scy */
41284990Scy
42284990Scy#include <sys/cdefs.h>
43284990Scy__FBSDID("$FreeBSD: head/sys/arm/arm/uio_machdep.c 130028 2004-06-03 10:22:47Z tjr $");
44284990Scy
45284990Scy#include <sys/param.h>
46284990Scy#include <sys/kernel.h>
47284990Scy#include <sys/lock.h>
48284990Scy#include <sys/mutex.h>
49284990Scy#include <sys/proc.h>
50284990Scy#include <sys/systm.h>
51284990Scy#include <sys/uio.h>
52284990Scy
53284990Scy#include <vm/vm.h>
54284990Scy#include <vm/vm_page.h>
55284990Scy
56284990Scy#include <machine/vmparam.h>
57284990Scy
58284990Scy/*
59284990Scy * Implement uiomove(9) from physical memory using the direct map to
60284990Scy * avoid the creation and destruction of ephemeral mappings.
61284990Scy */
62284990Scyint
63284990Scyuiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
64284990Scy{
65284990Scy	struct thread *td = curthread;
66284990Scy	struct iovec *iov;
67284990Scy	void *cp;
68284990Scy	vm_offset_t page_offset;
69284990Scy	size_t cnt;
70284990Scy	int error = 0;
71284990Scy	int save = 0;
72284990Scy
73284990Scy	KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE,
74284990Scy	    ("uiomove_fromphys: mode"));
75284990Scy	KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread,
76284990Scy	    ("uiomove_fromphys proc"));
77284990Scy	save = td->td_pflags & TDP_DEADLKTREAT;
78284990Scy	td->td_pflags |= TDP_DEADLKTREAT;
79284990Scy	while (n > 0 && uio->uio_resid) {
80284990Scy		iov = uio->uio_iov;
81284990Scy		cnt = iov->iov_len;
82284990Scy		if (cnt == 0) {
83284990Scy			uio->uio_iov++;
84284990Scy			uio->uio_iovcnt--;
85284990Scy			continue;
86284990Scy		}
87284990Scy		if (cnt > n)
88284990Scy			cnt = n;
89284990Scy		page_offset = offset & PAGE_MASK;
90284990Scy		cnt = min(cnt, PAGE_SIZE - page_offset);
91284990Scy		cp = (char *)VM_PAGE_TO_PHYS(ma[offset >> PAGE_SHIFT]) +
92284990Scy		    page_offset;
93284990Scy		switch (uio->uio_segflg) {
94284990Scy		case UIO_USERSPACE:
95284990Scy			if (ticks - PCPU_GET(switchticks) >= hogticks)
96284990Scy				uio_yield();
97284990Scy			if (uio->uio_rw == UIO_READ)
98284990Scy				error = copyout(cp, iov->iov_base, cnt);
99284990Scy			else
100				error = copyin(iov->iov_base, cp, cnt);
101			if (error)
102				goto out;
103			break;
104		case UIO_SYSSPACE:
105			if (uio->uio_rw == UIO_READ)
106				bcopy(cp, iov->iov_base, cnt);
107			else
108				bcopy(iov->iov_base, cp, cnt);
109			break;
110		case UIO_NOCOPY:
111			break;
112		}
113		iov->iov_base = (char *)iov->iov_base + cnt;
114		iov->iov_len -= cnt;
115		uio->uio_resid -= cnt;
116		uio->uio_offset += cnt;
117		offset += cnt;
118		n -= cnt;
119	}
120out:
121	if (save == 0)
122		td->td_pflags &= ~TDP_DEADLKTREAT;
123	return (error);
124}
125