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