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 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 * fubyte(caddr_t uaddr); 180 * Fetch a byte from the user's address space. 181 */ 182 183ENTRY(fubyte) 184 ldr r3, =VM_MAXUSER_ADDRESS 185 cmp r0, r3 186 mvncs r0, #0 187 RETc(cs) 188 189 GET_PCB(r2) 190 ldr r2, [r2] 191 192#ifdef DIAGNOSTIC 193 teq r2, #0x00000000 194 beq .Lfusupcbfault 195#endif 196 197 adr r1, .Lfusufault 198 str r1, [r2, #PCB_ONFAULT] 199 200 ldrbt r3, [r0] 201 202 mov r1, #0x00000000 203 str r1, [r2, #PCB_ONFAULT] 204 mov r0, r3 205 RET 206END(fubyte) 207 208/* 209 * Handle faults from [fs]u*(). Clean up and return -1. 210 */ 211 212.Lfusufault: 213 mov r0, #0x00000000 214 str r0, [r2, #PCB_ONFAULT] 215 mvn r0, #0x00000000 216 RET 217 218#ifdef DIAGNOSTIC 219/* 220 * Handle earlier faults from [fs]u*(), due to no pcb 221 */ 222 223.Lfusupcbfault: 224 mov r1, r0 225 adr r0, fusupcbfaulttext 226 b _C_LABEL(panic) 227 228fusupcbfaulttext: 229 .asciz "Yikes - no valid PCB during fusuxxx() addr=%08x\n" 230 .align 2 231#endif 232 233/* 234 * suword(caddr_t uaddr, int x); 235 * Store an int in the user's address space. 236 */ 237 238ENTRY(suword) 239EENTRY_NP(suword32) 240 ldr r3, =(VM_MAXUSER_ADDRESS-3) 241 cmp r0, r3 242 mvncs r0, #0 243 RETc(cs) 244 245 GET_PCB(r2) 246 ldr r2, [r2] 247 248#ifdef DIAGNOSTIC 249 teq r2, #0x00000000 250 beq .Lfusupcbfault 251#endif 252 253 adr r3, .Lfusufault 254 str r3, [r2, #PCB_ONFAULT] 255 256 strt r1, [r0] 257 258 mov r0, #0x00000000 259 str r0, [r2, #PCB_ONFAULT] 260 RET 261EEND(suword32) 262END(suword) 263 264/* 265 * susword(caddr_t uaddr, short x); 266 * Store a short in the user's address space. 267 */ 268 269ENTRY(susword) 270 ldr r3, =(VM_MAXUSER_ADDRESS-1) 271 cmp r0, r3 272 mvncs r0, #0 273 RETc(cs) 274 275 GET_PCB(r2) 276 ldr r2, [r2] 277 278#ifdef DIAGNOSTIC 279 teq r2, #0x00000000 280 beq .Lfusupcbfault 281#endif 282 283 adr r3, .Lfusufault 284 str r3, [r2, #PCB_ONFAULT] 285 286#ifdef __ARMEB__ 287 mov ip, r1, lsr #8 288 strbt ip, [r0], #1 289#else 290 strbt r1, [r0], #1 291 mov r1, r1, lsr #8 292#endif 293 strbt r1, [r0] 294 295 mov r0, #0x00000000 296 str r0, [r2, #PCB_ONFAULT] 297 RET 298END(susword) 299 300/* 301 * subyte(caddr_t uaddr, char x); 302 * Store a byte in the user's address space. 303 */ 304 305ENTRY(subyte) 306 ldr r3, =VM_MAXUSER_ADDRESS 307 cmp r0, r3 308 mvncs r0, #0 309 RETc(cs) 310 311 GET_PCB(r2) 312 ldr r2, [r2] 313 314 315#ifdef DIAGNOSTIC 316 teq r2, #0x00000000 317 beq .Lfusupcbfault 318#endif 319 320 adr r3, .Lfusufault 321 str r3, [r2, #PCB_ONFAULT] 322 323 strbt r1, [r0] 324 mov r0, #0x00000000 325 str r0, [r2, #PCB_ONFAULT] 326 RET 327END(subyte) 328