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