copyinout.c revision 125687
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: head/sys/powerpc/aim/copyinout.c 125687 2004-02-11 07:27:34Z 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 70int setfault(faultbuf); /* defined in locore.S */ 71 72/* 73 * Makes sure that the right segment of userspace is mapped in. 74 */ 75static __inline void 76set_user_sr(register_t vsid) 77{ 78 79 isync(); 80 __asm __volatile ("mtsr %0,%1" :: "n"(USER_SR), "r"(vsid)); 81 isync(); 82} 83 84int 85copyout(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 125int 126copyin(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 166int 167copyinstr(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 211int 212subyte(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 236int 237suword(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 261int 262suword32(void *addr, int32_t word) 263{ 264 return (suword(addr, (long)word)); 265} 266 267 268int 269fubyte(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 294long 295fuword(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 319int32_t 320fuword32(const void *addr) 321{ 322 return ((int32_t)fuword(addr)); 323} 324