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 #include <sys/cdefs.h>
57 __FBSDID("$FreeBSD: releng/5.2/sys/powerpc/powerpc/copyinout.c 113038 2003-04-03 21:36:33Z obrien $");
58
59 #include <sys/param.h>
60 #include <sys/systm.h>
61 #include <sys/proc.h>
62
63 #include <vm/vm.h>
64 #include <vm/pmap.h>
65 #include <vm/vm_map.h>
66
67 int setfault(faultbuf); /* defined in locore.S */
68
69 /*
70 * Makes sure that the right segment of userspace is mapped in.
71 */
72 static __inline void
73 set_user_sr(register_t vsid)
74 {
75
76 isync();
77 __asm __volatile ("mtsr %0,%1" :: "n"(USER_SR), "r"(vsid));
78 isync();
79 }
80
81 int
82 copyout(const void *kaddr, void *udaddr, size_t len)
83 {
84 struct thread *td;
85 pmap_t pm;
86 faultbuf env;
87 const char *kp;
88 char *up, *p;
89 size_t l;
90
91 td = PCPU_GET(curthread);
92 pm = &td->td_proc->p_vmspace->vm_pmap;
93
94 if (setfault(env)) {
95 td->td_pcb->pcb_onfault = NULL;
96 return (EFAULT);
97 }
98
99 kp = kaddr;
100 up = udaddr;
101
102 while (len > 0) {
103 p = (char *)USER_ADDR + ((u_int)up & ~SEGMENT_MASK);
104
105 l = ((char *)USER_ADDR + SEGMENT_LENGTH) - p;
106 if (l > len)
107 l = len;
108
109 set_user_sr(pm->pm_sr[(u_int)up >> ADDR_SR_SHFT]);
110
111 bcopy(kp, p, l);
112
113 up += l;
114 kp += l;
115 len -= l;
116 }
117
118 td->td_pcb->pcb_onfault = NULL;
119 return (0);
120 }
121
122 int
123 copyin(const void *udaddr, void *kaddr, size_t len)
124 {
125 struct thread *td;
126 pmap_t pm;
127 faultbuf env;
128 const char *up;
129 char *kp, *p;
130 size_t l;
131
132 td = PCPU_GET(curthread);
133 pm = &td->td_proc->p_vmspace->vm_pmap;
134
135 if (setfault(env)) {
136 td->td_pcb->pcb_onfault = NULL;
137 return (EFAULT);
138 }
139
140 kp = kaddr;
141 up = udaddr;
142
143 while (len > 0) {
144 p = (char *)USER_ADDR + ((u_int)up & ~SEGMENT_MASK);
145
146 l = ((char *)USER_ADDR + SEGMENT_LENGTH) - p;
147 if (l > len)
148 l = len;
149
150 set_user_sr(pm->pm_sr[(u_int)up >> ADDR_SR_SHFT]);
151
152 bcopy(p, kp, l);
153
154 up += l;
155 kp += l;
156 len -= l;
157 }
158
159 td->td_pcb->pcb_onfault = NULL;
160 return (0);
161 }
162
163 int
164 copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done)
165 {
166 struct thread *td;
167 pmap_t pm;
168 faultbuf env;
169 const char *up;
170 char *kp;
171 size_t l;
172 int rv, c;
173
174 td = PCPU_GET(curthread);
175 pm = &td->td_proc->p_vmspace->vm_pmap;
176
177 if (setfault(env)) {
178 td->td_pcb->pcb_onfault = NULL;
179 return (EFAULT);
180 }
181
182 kp = kaddr;
183 up = udaddr;
184
185 rv = ENAMETOOLONG;
186
187 for (l = 0; len-- > 0; l++) {
188 if ((c = fubyte(up++)) < 0) {
189 rv = EFAULT;
190 break;
191 }
192
193 if (!(*kp++ = c)) {
194 l++;
195 rv = 0;
196 break;
197 }
198 }
199
200 if (done != NULL) {
201 *done = l;
202 }
203
204 td->td_pcb->pcb_onfault = NULL;
205 return (rv);
206 }
207
208 int
209 subyte(void *addr, int byte)
210 {
211 struct thread *td;
212 pmap_t pm;
213 faultbuf env;
214 char *p;
215
216 td = PCPU_GET(curthread);
217 pm = &td->td_proc->p_vmspace->vm_pmap;
218 p = (char *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
219
220 if (setfault(env)) {
221 td->td_pcb->pcb_onfault = NULL;
222 return (-1);
223 }
224
225 set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);
226
227 *p = (char)byte;
228
229 td->td_pcb->pcb_onfault = NULL;
230 return (0);
231 }
232
233 int
234 suword(void *addr, long word)
235 {
236 struct thread *td;
237 pmap_t pm;
238 faultbuf env;
239 long *p;
240
241 td = PCPU_GET(curthread);
242 pm = &td->td_proc->p_vmspace->vm_pmap;
243 p = (long *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
244
245 if (setfault(env)) {
246 td->td_pcb->pcb_onfault = NULL;
247 return (-1);
248 }
249
250 set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);
251
252 *p = word;
253
254 td->td_pcb->pcb_onfault = NULL;
255 return (0);
256 }
257
258 int
259 suword32(void *addr, int32_t word)
260 {
261 return (suword(addr, (long)word));
262 }
263
264
265 int
266 fubyte(const void *addr)
267 {
268 struct thread *td;
269 pmap_t pm;
270 faultbuf env;
271 u_char *p;
272 int val;
273
274 td = PCPU_GET(curthread);
275 pm = &td->td_proc->p_vmspace->vm_pmap;
276 p = (u_char *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
277
278 if (setfault(env)) {
279 td->td_pcb->pcb_onfault = NULL;
280 return (-1);
281 }
282
283 set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);
284
285 val = *p;
286
287 td->td_pcb->pcb_onfault = NULL;
288 return (val);
289 }
290
291 long
292 fuword(const void *addr)
293 {
294 struct thread *td;
295 pmap_t pm;
296 faultbuf env;
297 long *p, val;
298
299 td = PCPU_GET(curthread);
300 pm = &td->td_proc->p_vmspace->vm_pmap;
301 p = (long *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
302
303 if (setfault(env)) {
304 td->td_pcb->pcb_onfault = NULL;
305 return (-1);
306 }
307
308 set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);
309
310 val = *p;
311
312 td->td_pcb->pcb_onfault = NULL;
313 return (val);
314 }
315
316 int32_t
317 fuword32(const void *addr)
318 {
319 return ((int32_t)fuword(addr));
320 }
Cache object: 28dc0a3a6485d763296ae9532bd90045
|