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$"); 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/vmparam.h> 69 70 71int setfault(faultbuf); /* defined in locore.S */ 72 73static int 74is_uaddr(const void *addr) 75{ 76 int rv = ((vm_offset_t)addr <= VM_MAXUSER_ADDRESS) ? 1 : 0; 77 78 return rv; 79} 80 81int 82copyout(const void *kaddr, void *udaddr, size_t len) 83{ 84 struct thread *td; 85 faultbuf env; 86 87 if (!is_uaddr(udaddr)) 88 return (EFAULT); 89 90 td = curthread; 91 92 if (setfault(env)) { 93 td->td_pcb->pcb_onfault = NULL; 94 return (EFAULT); 95 } 96 97 bcopy(kaddr, udaddr, len); 98 99 td->td_pcb->pcb_onfault = NULL; 100 return (0); 101} 102 103int 104copyin(const void *udaddr, void *kaddr, size_t len) 105{ 106 struct thread *td; 107 faultbuf env; 108 109 if (!is_uaddr(udaddr) || is_uaddr(kaddr)) 110 return (EFAULT); 111 112 td = curthread; 113 114 if (setfault(env)) { 115 td->td_pcb->pcb_onfault = NULL; 116 return (EFAULT); 117 } 118 119 bcopy(udaddr, kaddr, len); 120 121 td->td_pcb->pcb_onfault = NULL; 122 return (0); 123} 124 125int 126copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done) 127{ 128 struct thread *td; 129 faultbuf env; 130 const char *up; 131 char *kp; 132 size_t l; 133 int rv, c; 134 135 if (!is_uaddr(udaddr) || is_uaddr(kaddr)) 136 return (EFAULT); 137 138 td = curthread; 139 140 if (setfault(env)) { 141 td->td_pcb->pcb_onfault = NULL; 142 return (EFAULT); 143 } 144 145 kp = kaddr; 146 up = udaddr; 147 148 rv = ENAMETOOLONG; 149 150 for (l = 0; len-- > 0; l++) { 151 152 c = *up++; 153 154 if (!(*kp++ = c)) { 155 l++; 156 rv = 0; 157 break; 158 } 159 } 160 161 if (done != NULL) { 162 *done = l; 163 } 164 165 td->td_pcb->pcb_onfault = NULL; 166 return (rv); 167} 168 169int 170subyte(void *addr, int byte) 171{ 172 struct thread *td; 173 faultbuf env; 174 175 if (!is_uaddr(addr)) 176 return (EFAULT); 177 178 td = curthread; 179 180 if (setfault(env)) { 181 td->td_pcb->pcb_onfault = NULL; 182 return (EFAULT); 183 } 184 185 *(char *)addr = (char)byte; 186 187 td->td_pcb->pcb_onfault = NULL; 188 return (0); 189} 190 191int 192suword(void *addr, long word) 193{ 194 struct thread *td; 195 faultbuf env; 196 197 if (!is_uaddr(addr)) 198 return (EFAULT); 199 200 td = curthread; 201 202 if (setfault(env)) { 203 td->td_pcb->pcb_onfault = NULL; 204 return (EFAULT); 205 } 206 207 *(long *)addr = word; 208 209 td->td_pcb->pcb_onfault = NULL; 210 return (0); 211} 212 213int 214suword32(void *addr, int32_t word) 215{ 216 217 return (suword(addr, (long)word)); 218} 219 220 221int 222fubyte(const void *addr) 223{ 224 struct thread *td; 225 faultbuf env; 226 int val; 227 228 if (!is_uaddr(addr)) 229 return (EFAULT); 230 231 td = curthread; 232 233 if (setfault(env)) { 234 td->td_pcb->pcb_onfault = NULL; 235 return (EFAULT); 236 } 237 238 val = *(const u_char *)addr; 239 240 td->td_pcb->pcb_onfault = NULL; 241 return (val); 242} 243 244long 245fuword(const void *addr) 246{ 247 struct thread *td; 248 faultbuf env; 249 long val; 250 251 if (!is_uaddr(addr)) 252 return (EFAULT); 253 254 td = curthread; 255 256 if (setfault(env)) { 257 td->td_pcb->pcb_onfault = NULL; 258 return (EFAULT); 259 } 260 261 val = *(const long *)addr; 262 263 td->td_pcb->pcb_onfault = NULL; 264 return (val); 265} 266 267int32_t 268fuword32(const void *addr) 269{ 270 271 return ((int32_t)fuword(addr)); 272} 273 274uint32_t 275casuword32(volatile uint32_t *base, uint32_t oldval, uint32_t newval) 276{ 277 278 return (casuword((volatile u_long *)base, oldval, newval)); 279} 280 281u_long 282casuword(volatile u_long *addr, u_long old, u_long new) 283{ 284 struct thread *td; 285 faultbuf env; 286 u_long val; 287 288 if (!((vm_offset_t)addr <= VM_MAXUSER_ADDRESS)) 289 return (EFAULT); 290 291 td = curthread; 292 293 if (setfault(env)) { 294 td->td_pcb->pcb_onfault = NULL; 295 return (EFAULT); 296 } 297 298 __asm __volatile ( 299 "1:\tlwarx %0, 0, %2\n\t" /* load old value */ 300 "cmplw %3, %0\n\t" /* compare */ 301 "bne 2f\n\t" /* exit if not equal */ 302 "stwcx. %4, 0, %2\n\t" /* attempt to store */ 303 "bne- 1b\n\t" /* spin if failed */ 304 "b 3f\n\t" /* we've succeeded */ 305 "2:\n\t" 306 "stwcx. %0, 0, %2\n\t" /* clear reservation (74xx) */ 307 "3:\n\t" 308 : "=&r" (val), "=m" (*addr) 309 : "r" (addr), "r" (old), "r" (new), "m" (*addr) 310 : "cc", "memory"); 311 312 td->td_pcb->pcb_onfault = NULL; 313 314 return (val); 315} 316