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
57 static const char rcsid[] =
58 "$FreeBSD: releng/5.0/sys/powerpc/powerpc/copyinout.c 98480 2002-06-20 07:13:35Z peter $";
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
69 int setfault(faultbuf); /* defined in locore.S */
70
71 /*
72 * Makes sure that the right segment of userspace is mapped in.
73 */
74 static __inline void
75 set_user_sr(register_t vsid)
76 {
77
78 isync();
79 __asm __volatile ("mtsr %0,%1" :: "n"(USER_SR), "r"(vsid));
80 isync();
81 }
82
83 int
84 copyout(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
124 int
125 copyin(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
165 int
166 copyinstr(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
210 int
211 subyte(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
235 int
236 suword(void *addr, long word)
237 {
238 struct thread *td;
239 pmap_t pm;
240 faultbuf env;
241 long *p;
242
243 td = PCPU_GET(curthread);
244 pm = &td->td_proc->p_vmspace->vm_pmap;
245 p = (long *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
246
247 if (setfault(env)) {
248 td->td_pcb->pcb_onfault = NULL;
249 return (EFAULT);
250 }
251
252 set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);
253
254 *p = word;
255
256 td->td_pcb->pcb_onfault = NULL;
257 return (0);
258 }
259
260 int
261 suword32(void *addr, int32_t word)
262 {
263 return (suword(addr, (long)word));
264 }
265
266
267 int
268 fubyte(const void *addr)
269 {
270 struct thread *td;
271 pmap_t pm;
272 faultbuf env;
273 char *p;
274 int val;
275
276 td = PCPU_GET(curthread);
277 pm = &td->td_proc->p_vmspace->vm_pmap;
278 p = (char *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
279
280 if (setfault(env)) {
281 td->td_pcb->pcb_onfault = NULL;
282 return (EFAULT);
283 }
284
285 set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);
286
287 val = (int)*p;
288
289 td->td_pcb->pcb_onfault = NULL;
290 return (val);
291 }
292
293 long
294 fuword(const void *addr)
295 {
296 struct thread *td;
297 pmap_t pm;
298 faultbuf env;
299 long *p, val;
300
301 td = PCPU_GET(curthread);
302 pm = &td->td_proc->p_vmspace->vm_pmap;
303 p = (long *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
304
305 if (setfault(env)) {
306 td->td_pcb->pcb_onfault = NULL;
307 return (EFAULT);
308 }
309
310 set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);
311
312 val = *p;
313
314 td->td_pcb->pcb_onfault = NULL;
315 return (val);
316 }
317
318 int32_t
319 fuword32(const void *addr)
320 {
321 return ((int32_t)fuword(addr));
322 }
Cache object: 85838c0147328b67701d8f628596b6ee
|