1/* $NetBSD: fusu.S,v 1.10 2003/12/01 13:34:44 rearnsha Exp $ */ 2 3/*- 4 * Copyright (c) 1996-1998 Mark Brinicombe. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Mark Brinicombe 18 * 4. The name of the company nor the name of the author may be used to 19 * endorse or promote products derived from this software without specific 20 * prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 */ 35 36#include <machine/asm.h> 37#include <machine/armreg.h> 38#include "assym.s" 39__FBSDID("$FreeBSD$"); 40 41 .syntax unified 42 43#if __ARM_ARCH >= 6 44#define GET_PCB(tmp) \ 45 mrc p15, 0, tmp, c13, c0, 4; \ 46 add tmp, tmp, #(TD_PCB) 47#else 48.Lcurpcb: 49 .word _C_LABEL(__pcpu) + PC_CURPCB 50#define GET_PCB(tmp) \ 51 ldr tmp, .Lcurpcb 52#endif 53 54/* 55 * casueword32(volatile uint32_t *base, uint32_t oldval, uint32_t *oldvalp, 56 * uint32_t newval); 57 */ 58 59ENTRY(casueword) 60EENTRY_NP(casueword32) 61 stmfd sp!, {r4, r5, r6} 62 63 ldr r4, =(VM_MAXUSER_ADDRESS-3) 64 cmp r0, r4 65 mvncs r0, #0 66 bcs 2f 67 68 GET_PCB(r6) 69 ldr r6, [r6] 70 71#ifdef DIAGNOSTIC 72 teq r6, #0x00000000 73 ldmfdeq sp!, {r4, r5, r6} 74 beq .Lfusupcbfault 75#endif 76 77 adr r4, .Lcasuwordfault 78 str r4, [r6, #PCB_ONFAULT] 79 80#if __ARM_ARCH >= 6 811: 82 ldrex r4, [r0] 83 cmp r4, r1 84 strexeq r5, r3, [r0] 85 cmpeq r5, #1 86 beq 1b 87#else 88 ldrt r4, [r0] 89 cmp r4, r1 90 strteq r3, [r0] 91#endif 92 str r4, [r2] 93 mov r0, #0 94 str r0, [r6, #PCB_ONFAULT] 952: 96 ldmfd sp!, {r4, r5, r6} 97 RET 98EEND(casueword32) 99END(casueword) 100 101/* 102 * Handle faults from casuword. Clean up and return -1. 103 */ 104 105.Lcasuwordfault: 106 mov r0, #0x00000000 107 str r0, [r6, #PCB_ONFAULT] 108 mvn r0, #0 109 ldmfd sp!, {r4, r5, r6} 110 RET 111 112/* 113 * fueword(caddr_t uaddr, long *val); 114 * Fetch an int from the user's address space. 115 */ 116 117ENTRY(fueword) 118EENTRY_NP(fueword32) 119 ldr r3, =(VM_MAXUSER_ADDRESS-3) 120 cmp r0, r3 121 mvncs r0, #0 122 RETc(cs) 123 124 GET_PCB(r2) 125 ldr r2, [r2] 126 127#ifdef DIAGNOSTIC 128 teq r2, #0x00000000 129 beq .Lfusupcbfault 130#endif 131 132 adr r3, .Lfusufault 133 str r3, [r2, #PCB_ONFAULT] 134 135 ldrt r3, [r0] 136 str r3, [r1] 137 138 mov r0, #0x00000000 139 str r0, [r2, #PCB_ONFAULT] 140 RET 141EEND(fueword32) 142END(fueword) 143 144/* 145 * fusword(caddr_t uaddr); 146 * Fetch a short from the user's address space. 147 */ 148 149ENTRY(fusword) 150 ldr r3, =(VM_MAXUSER_ADDRESS-1) 151 cmp r0, r3 152 mvncs r0, #0 153 RETc(cs) 154 155 GET_PCB(r2) 156 ldr r2, [r2] 157 158#ifdef DIAGNOSTIC 159 teq r2, #0x00000000 160 beq .Lfusupcbfault 161#endif 162 163 adr r1, .Lfusufault 164 str r1, [r2, #PCB_ONFAULT] 165 166 ldrbt r3, [r0], #1 167 ldrbt ip, [r0] 168#ifdef __ARMEB__ 169 orr r0, ip, r3, asl #8 170#else 171 orr r0, r3, ip, asl #8 172#endif 173 mov r1, #0x00000000 174 str r1, [r2, #PCB_ONFAULT] 175 RET 176END(fusword) 177 178/* 179 * fuswintr(caddr_t uaddr); 180 * Fetch a short from the user's address space. Can be called during an 181 * interrupt. 182 */ 183 184ENTRY(fuswintr) 185 mov r0, #-1 186 RET 187END(fuswintr) 188 189/* 190 * fubyte(caddr_t uaddr); 191 * Fetch a byte from the user's address space. 192 */ 193 194ENTRY(fubyte) 195 ldr r3, =VM_MAXUSER_ADDRESS 196 cmp r0, r3 197 mvncs r0, #0 198 RETc(cs) 199 200 GET_PCB(r2) 201 ldr r2, [r2] 202 203#ifdef DIAGNOSTIC 204 teq r2, #0x00000000 205 beq .Lfusupcbfault 206#endif 207 208 adr r1, .Lfusufault 209 str r1, [r2, #PCB_ONFAULT] 210 211 ldrbt r3, [r0] 212 213 mov r1, #0x00000000 214 str r1, [r2, #PCB_ONFAULT] 215 mov r0, r3 216 RET 217END(fubyte) 218 219/* 220 * Handle faults from [fs]u*(). Clean up and return -1. 221 */ 222 223.Lfusufault: 224 mov r0, #0x00000000 225 str r0, [r2, #PCB_ONFAULT] 226 mvn r0, #0x00000000 227 RET 228 229#ifdef DIAGNOSTIC 230/* 231 * Handle earlier faults from [fs]u*(), due to no pcb 232 */ 233 234.Lfusupcbfault: 235 mov r1, r0 236 adr r0, fusupcbfaulttext 237 b _C_LABEL(panic) 238 239fusupcbfaulttext: 240 .asciz "Yikes - no valid PCB during fusuxxx() addr=%08x\n" 241 .align 2 242#endif 243 244/* 245 * suword(caddr_t uaddr, int x); 246 * Store an int in the user's address space. 247 */ 248 249ENTRY(suword) 250EENTRY_NP(suword32) 251 ldr r3, =(VM_MAXUSER_ADDRESS-3) 252 cmp r0, r3 253 mvncs r0, #0 254 RETc(cs) 255 256 GET_PCB(r2) 257 ldr r2, [r2] 258 259#ifdef DIAGNOSTIC 260 teq r2, #0x00000000 261 beq .Lfusupcbfault 262#endif 263 264 adr r3, .Lfusufault 265 str r3, [r2, #PCB_ONFAULT] 266 267 strt r1, [r0] 268 269 mov r0, #0x00000000 270 str r0, [r2, #PCB_ONFAULT] 271 RET 272EEND(suword32) 273END(suword) 274 275/* 276 * suswintr(caddr_t uaddr, short x); 277 * Store a short in the user's address space. Can be called during an 278 * interrupt. 279 */ 280 281ENTRY(suswintr) 282 mov r0, #-1 283 RET 284END(suswintr) 285 286/* 287 * susword(caddr_t uaddr, short x); 288 * Store a short in the user's address space. 289 */ 290 291ENTRY(susword) 292 ldr r3, =(VM_MAXUSER_ADDRESS-1) 293 cmp r0, r3 294 mvncs r0, #0 295 RETc(cs) 296 297 GET_PCB(r2) 298 ldr r2, [r2] 299 300#ifdef DIAGNOSTIC 301 teq r2, #0x00000000 302 beq .Lfusupcbfault 303#endif 304 305 adr r3, .Lfusufault 306 str r3, [r2, #PCB_ONFAULT] 307 308#ifdef __ARMEB__ 309 mov ip, r1, lsr #8 310 strbt ip, [r0], #1 311#else 312 strbt r1, [r0], #1 313 mov r1, r1, lsr #8 314#endif 315 strbt r1, [r0] 316 317 mov r0, #0x00000000 318 str r0, [r2, #PCB_ONFAULT] 319 RET 320END(susword) 321 322/* 323 * subyte(caddr_t uaddr, char x); 324 * Store a byte in the user's address space. 325 */ 326 327ENTRY(subyte) 328 ldr r3, =VM_MAXUSER_ADDRESS 329 cmp r0, r3 330 mvncs r0, #0 331 RETc(cs) 332 333 GET_PCB(r2) 334 ldr r2, [r2] 335 336 337#ifdef DIAGNOSTIC 338 teq r2, #0x00000000 339 beq .Lfusupcbfault 340#endif 341 342 adr r3, .Lfusufault 343 str r3, [r2, #PCB_ONFAULT] 344 345 strbt r1, [r0] 346 mov r0, #0x00000000 347 str r0, [r2, #PCB_ONFAULT] 348 RET 349END(subyte) 350