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.inc" 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 1f 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 81 mov r5, #1 82 ldrex r4, [r0] 83 cmp r4, r1 84 strexeq r5, r3, [r0] 85#else 86 ldrt r4, [r0] 87 cmp r4, r1 88 strteq r3, [r0] 89#endif 90 str r4, [r2] 91 mov r0, #0 92 str r0, [r6, #PCB_ONFAULT] 93#if __ARM_ARCH >= 6 94 mov r0, r5 95#endif 961: 97 ldmfd sp!, {r4, r5, r6} 98 RET 99EEND(casueword32) 100END(casueword) 101 102/* 103 * Handle faults from casuword. Clean up and return -1. 104 */ 105 106.Lcasuwordfault: 107 mov r0, #0x00000000 108 str r0, [r6, #PCB_ONFAULT] 109 mvn r0, #0 110 ldmfd sp!, {r4, r5, r6} 111 RET 112 113/* 114 * fueword(caddr_t uaddr, long *val); 115 * Fetch an int from the user's address space. 116 */ 117 118ENTRY(fueword) 119EENTRY_NP(fueword32) 120 ldr r3, =(VM_MAXUSER_ADDRESS-3) 121 cmp r0, r3 122 mvncs r0, #0 123 RETc(cs) 124 125 GET_PCB(r2) 126 ldr r2, [r2] 127 128#ifdef DIAGNOSTIC 129 teq r2, #0x00000000 130 beq .Lfusupcbfault 131#endif 132 133 adr r3, .Lfusufault 134 str r3, [r2, #PCB_ONFAULT] 135 136 ldrt r3, [r0] 137 str r3, [r1] 138 139 mov r0, #0x00000000 140 str r0, [r2, #PCB_ONFAULT] 141 RET 142EEND(fueword32) 143END(fueword) 144 145/* 146 * fusword(caddr_t uaddr); 147 * Fetch a short from the user's address space. 148 */ 149 150ENTRY(fusword) 151 ldr r3, =(VM_MAXUSER_ADDRESS-1) 152 cmp r0, r3 153 mvncs r0, #0 154 RETc(cs) 155 156 GET_PCB(r2) 157 ldr r2, [r2] 158 159#ifdef DIAGNOSTIC 160 teq r2, #0x00000000 161 beq .Lfusupcbfault 162#endif 163 164 adr r1, .Lfusufault 165 str r1, [r2, #PCB_ONFAULT] 166 167 ldrbt r3, [r0], #1 168 ldrbt ip, [r0] 169#ifdef __ARMEB__ 170 orr r0, ip, r3, asl #8 171#else 172 orr r0, r3, ip, asl #8 173#endif 174 mov r1, #0x00000000 175 str r1, [r2, #PCB_ONFAULT] 176 RET 177END(fusword) 178 179/* 180 * fubyte(caddr_t uaddr); 181 * Fetch a byte from the user's address space. 182 */ 183 184ENTRY(fubyte) 185 ldr r3, =VM_MAXUSER_ADDRESS 186 cmp r0, r3 187 mvncs r0, #0 188 RETc(cs) 189 190 GET_PCB(r2) 191 ldr r2, [r2] 192 193#ifdef DIAGNOSTIC 194 teq r2, #0x00000000 195 beq .Lfusupcbfault 196#endif 197 198 adr r1, .Lfusufault 199 str r1, [r2, #PCB_ONFAULT] 200 201 ldrbt r3, [r0] 202 203 mov r1, #0x00000000 204 str r1, [r2, #PCB_ONFAULT] 205 mov r0, r3 206 RET 207END(fubyte) 208 209/* 210 * Handle faults from [fs]u*(). Clean up and return -1. 211 */ 212 213.Lfusufault: 214 mov r0, #0x00000000 215 str r0, [r2, #PCB_ONFAULT] 216 mvn r0, #0x00000000 217 RET 218 219#ifdef DIAGNOSTIC 220/* 221 * Handle earlier faults from [fs]u*(), due to no pcb 222 */ 223 224.Lfusupcbfault: 225 mov r1, r0 226 adr r0, fusupcbfaulttext 227 b _C_LABEL(panic) 228 229fusupcbfaulttext: 230 .asciz "Yikes - no valid PCB during fusuxxx() addr=%08x\n" 231 .align 2 232#endif 233 234/* 235 * suword(caddr_t uaddr, int x); 236 * Store an int in the user's address space. 237 */ 238 239ENTRY(suword) 240EENTRY_NP(suword32) 241 ldr r3, =(VM_MAXUSER_ADDRESS-3) 242 cmp r0, r3 243 mvncs r0, #0 244 RETc(cs) 245 246 GET_PCB(r2) 247 ldr r2, [r2] 248 249#ifdef DIAGNOSTIC 250 teq r2, #0x00000000 251 beq .Lfusupcbfault 252#endif 253 254 adr r3, .Lfusufault 255 str r3, [r2, #PCB_ONFAULT] 256 257 strt r1, [r0] 258 259 mov r0, #0x00000000 260 str r0, [r2, #PCB_ONFAULT] 261 RET 262EEND(suword32) 263END(suword) 264 265/* 266 * susword(caddr_t uaddr, short x); 267 * Store a short in the user's address space. 268 */ 269 270ENTRY(susword) 271 ldr r3, =(VM_MAXUSER_ADDRESS-1) 272 cmp r0, r3 273 mvncs r0, #0 274 RETc(cs) 275 276 GET_PCB(r2) 277 ldr r2, [r2] 278 279#ifdef DIAGNOSTIC 280 teq r2, #0x00000000 281 beq .Lfusupcbfault 282#endif 283 284 adr r3, .Lfusufault 285 str r3, [r2, #PCB_ONFAULT] 286 287#ifdef __ARMEB__ 288 mov ip, r1, lsr #8 289 strbt ip, [r0], #1 290#else 291 strbt r1, [r0], #1 292 mov r1, r1, lsr #8 293#endif 294 strbt r1, [r0] 295 296 mov r0, #0x00000000 297 str r0, [r2, #PCB_ONFAULT] 298 RET 299END(susword) 300 301/* 302 * subyte(caddr_t uaddr, char x); 303 * Store a byte in the user's address space. 304 */ 305 306ENTRY(subyte) 307 ldr r3, =VM_MAXUSER_ADDRESS 308 cmp r0, r3 309 mvncs r0, #0 310 RETc(cs) 311 312 GET_PCB(r2) 313 ldr r2, [r2] 314 315 316#ifdef DIAGNOSTIC 317 teq r2, #0x00000000 318 beq .Lfusupcbfault 319#endif 320 321 adr r3, .Lfusufault 322 str r3, [r2, #PCB_ONFAULT] 323 324 strbt r1, [r0] 325 mov r0, #0x00000000 326 str r0, [r2, #PCB_ONFAULT] 327 RET 328END(subyte) 329