copyinout.c revision 97342
1/*
2 * Copyright (C) 2002 Benno Rice
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24*/
25/*-
26 * Copyright (C) 1993 Wolfgang Solfrank.
27 * Copyright (C) 1993 TooLs GmbH.
28 * All rights reserved.
29 *
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
32 * are met:
33 * 1. Redistributions of source code must retain the above copyright
34 *    notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 *    notice, this list of conditions and the following disclaimer in the
37 *    documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 *    must display the following acknowledgement:
40 *	This product includes software developed by TooLs GmbH.
41 * 4. The name of TooLs GmbH may not be used to endorse or promote products
42 *    derived from this software without specific prior written permission.
43 *
44 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
45 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
46 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
47 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
49 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
50 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
51 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
52 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
53 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 */
55
56#ifndef lint
57static const char rcsid[] =
58  "$FreeBSD: head/sys/powerpc/aim/copyinout.c 97342 2002-05-27 10:50:47Z benno $";
59#endif /* not lint */
60
61#include <sys/param.h>
62#include <sys/systm.h>
63#include <sys/proc.h>
64
65#include <vm/vm.h>
66#include <vm/pmap.h>
67#include <vm/vm_map.h>
68
69int	setfault(faultbuf);	/* defined in locore.S */
70
71/*
72 * Makes sure that the right segment of userspace is mapped in.
73 */
74static __inline void
75set_user_sr(register_t vsid)
76{
77
78	isync();
79	__asm __volatile ("mtsr %0,%1" :: "n"(USER_SR), "r"(vsid));
80	isync();
81}
82
83int
84copyout(const void *kaddr, void *udaddr, size_t len)
85{
86	struct		thread *td;
87	pmap_t		pm;
88	faultbuf	env;
89	const char	*kp;
90	char		*up, *p;
91	size_t		l;
92
93	td = PCPU_GET(curthread);
94	pm = &td->td_proc->p_vmspace->vm_pmap;
95
96	if (setfault(env)) {
97		td->td_pcb->pcb_onfault = NULL;
98		return (EFAULT);
99	}
100
101	kp = kaddr;
102	up = udaddr;
103
104	while (len > 0) {
105		p = (char *)USER_ADDR + ((u_int)up & ~SEGMENT_MASK);
106
107		l = ((char *)USER_ADDR + SEGMENT_LENGTH) - p;
108		if (l > len)
109			l = len;
110
111		set_user_sr(pm->pm_sr[(u_int)up >> ADDR_SR_SHFT]);
112
113		bcopy(kp, p, l);
114
115		up += l;
116		kp += l;
117		len -= l;
118	}
119
120	td->td_pcb->pcb_onfault = NULL;
121	return (0);
122}
123
124int
125copyin(const void *udaddr, void *kaddr, size_t len)
126{
127	struct		thread *td;
128	pmap_t		pm;
129	faultbuf	env;
130	const char	*up;
131	char		*kp, *p;
132	size_t		l;
133
134	td = PCPU_GET(curthread);
135	pm = &td->td_proc->p_vmspace->vm_pmap;
136
137	if (setfault(env)) {
138		td->td_pcb->pcb_onfault = NULL;
139		return (EFAULT);
140	}
141
142	kp = kaddr;
143	up = udaddr;
144
145	while (len > 0) {
146		p = (char *)USER_ADDR + ((u_int)up & ~SEGMENT_MASK);
147
148		l = ((char *)USER_ADDR + SEGMENT_LENGTH) - p;
149		if (l > len)
150			l = len;
151
152		set_user_sr(pm->pm_sr[(u_int)up >> ADDR_SR_SHFT]);
153
154		bcopy(p, kp, l);
155
156		up += l;
157		kp += l;
158		len -= l;
159	}
160
161	td->td_pcb->pcb_onfault = NULL;
162	return (0);
163}
164
165int
166copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done)
167{
168	struct		thread *td;
169	pmap_t		pm;
170	faultbuf	env;
171	const char	*up;
172	char		*kp;
173	size_t		l;
174	int		rv, c;
175
176	td = PCPU_GET(curthread);
177	pm = &td->td_proc->p_vmspace->vm_pmap;
178
179	if (setfault(env)) {
180		td->td_pcb->pcb_onfault = NULL;
181		return (EFAULT);
182	}
183
184	kp = kaddr;
185	up = udaddr;
186
187	rv = ENAMETOOLONG;
188
189	for (l = 0; len-- > 0; l++) {
190		if ((c = fubyte(up++)) < 0) {
191			rv = EFAULT;
192			break;
193		}
194
195		if (!(*kp++ = c)) {
196			l++;
197			rv = 0;
198			break;
199		}
200	}
201
202	if (done != NULL) {
203		*done = l;
204	}
205
206	td->td_pcb->pcb_onfault = NULL;
207	return (rv);
208}
209
210int
211subyte(void *addr, int byte)
212{
213	struct		thread *td;
214	pmap_t		pm;
215	faultbuf	env;
216	char		*p;
217
218	td = PCPU_GET(curthread);
219	pm = &td->td_proc->p_vmspace->vm_pmap;
220	p = (char *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
221
222	if (setfault(env)) {
223		td->td_pcb->pcb_onfault = NULL;
224		return (EFAULT);
225	}
226
227	set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);
228
229	*p = (char)byte;
230
231	td->td_pcb->pcb_onfault = NULL;
232	return (0);
233}
234
235int
236suibyte(void *addr, int byte)
237{
238
239	return (subyte(addr, byte));
240}
241
242int
243suword(void *addr, long word)
244{
245	struct		thread *td;
246	pmap_t		pm;
247	faultbuf	env;
248	long		*p;
249
250	td = PCPU_GET(curthread);
251	pm = &td->td_proc->p_vmspace->vm_pmap;
252	p = (long *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
253
254	if (setfault(env)) {
255		td->td_pcb->pcb_onfault = NULL;
256		return (EFAULT);
257	}
258
259	set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);
260
261	*p = word;
262
263	td->td_pcb->pcb_onfault = NULL;
264	return (0);
265}
266
267int
268suword32(void *addr, int32_t word)
269{
270	return (suword(addr, (long)word));
271}
272
273
274int
275fubyte(const void *addr)
276{
277	struct		thread *td;
278	pmap_t		pm;
279	faultbuf	env;
280	char		*p;
281	int		val;
282
283	td = PCPU_GET(curthread);
284	pm = &td->td_proc->p_vmspace->vm_pmap;
285	p = (char *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
286
287	if (setfault(env)) {
288		td->td_pcb->pcb_onfault = NULL;
289		return (EFAULT);
290	}
291
292	set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);
293
294	val = (int)*p;
295
296	td->td_pcb->pcb_onfault = NULL;
297	return (val);
298}
299
300long
301fuword(const void *addr)
302{
303	struct		thread *td;
304	pmap_t		pm;
305	faultbuf	env;
306	long		*p, val;
307
308	td = PCPU_GET(curthread);
309	pm = &td->td_proc->p_vmspace->vm_pmap;
310	p = (long *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
311
312	if (setfault(env)) {
313		td->td_pcb->pcb_onfault = NULL;
314		return (EFAULT);
315	}
316
317	set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);
318
319	val = *p;
320
321	td->td_pcb->pcb_onfault = NULL;
322	return (val);
323}
324
325int32_t
326fuword32(const void *addr)
327{
328	return ((int32_t)fuword(addr));
329}
330