fusu.S revision 275520
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: head/sys/arm/arm/fusu.S 275520 2014-12-05 19:08:36Z andrew $"); 40 41 .syntax unified 42 43#ifdef _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 * fuword(caddr_t uaddr); 56 * Fetch an int from the user's address space. 57 */ 58 59ENTRY(casuword) 60EENTRY_NP(casuword32) 61 GET_PCB(r3) 62 ldr r3, [r3] 63 64#ifdef DIAGNOSTIC 65 teq r3, #0x00000000 66 beq .Lfusupcbfault 67#endif 68 stmfd sp!, {r4, r5} 69 adr r4, .Lcasuwordfault 70 str r4, [r3, #PCB_ONFAULT] 71#ifdef _ARM_ARCH_6 721: 73 cmp r0, #KERNBASE 74 mvnhs r0, #0 75 bhs 2f 76 77 ldrex r5, [r0] 78 cmp r5, r1 79 movne r0, r5 80 bne 2f 81 strex r5, r2, [r0] 82 cmp r5, #0 83 bne 1b 84#else 85 ldrt r5, [r0] 86 cmp r5, r1 87 movne r0, r5 88 strteq r2, [r0] 89#endif 90 moveq r0, r1 912: 92 ldmfd sp!, {r4, r5} 93 mov r1, #0x00000000 94 str r1, [r3, #PCB_ONFAULT] 95 RET 96EEND(casuword32) 97END(casuword) 98 99/* 100 * Handle faults from casuword. Clean up and return -1. 101 */ 102 103.Lcasuwordfault: 104 mov r0, #0x00000000 105 str r0, [r3, #PCB_ONFAULT] 106 mvn r0, #0x00000000 107 ldmfd sp!, {r4, r5} 108 RET 109 110/* 111 * fuword(caddr_t uaddr); 112 * Fetch an int from the user's address space. 113 */ 114 115ENTRY(fuword) 116EENTRY_NP(fuword32) 117 GET_PCB(r2) 118 ldr r2, [r2] 119 120#ifdef DIAGNOSTIC 121 teq r2, #0x00000000 122 beq .Lfusupcbfault 123#endif 124 125 adr r1, .Lfusufault 126 str r1, [r2, #PCB_ONFAULT] 127 128 ldrt r3, [r0] 129 130 mov r1, #0x00000000 131 str r1, [r2, #PCB_ONFAULT] 132 mov r0, r3 133 RET 134EEND(fuword32) 135END(fuword) 136 137/* 138 * fusword(caddr_t uaddr); 139 * Fetch a short from the user's address space. 140 */ 141 142ENTRY(fusword) 143 GET_PCB(r2) 144 ldr r2, [r2] 145 146#ifdef DIAGNOSTIC 147 teq r2, #0x00000000 148 beq .Lfusupcbfault 149#endif 150 151 adr r1, .Lfusufault 152 str r1, [r2, #PCB_ONFAULT] 153 154 ldrbt r3, [r0], #1 155 ldrbt ip, [r0] 156#ifdef __ARMEB__ 157 orr r0, ip, r3, asl #8 158#else 159 orr r0, r3, ip, asl #8 160#endif 161 mov r1, #0x00000000 162 str r1, [r2, #PCB_ONFAULT] 163 RET 164END(fusword) 165 166/* 167 * fuswintr(caddr_t uaddr); 168 * Fetch a short from the user's address space. Can be called during an 169 * interrupt. 170 */ 171 172ENTRY(fuswintr) 173 ldr r2, Lblock_userspace_access 174 ldr r2, [r2] 175 teq r2, #0 176 mvnne r0, #0x00000000 177 RETne 178 179 GET_PCB(r2) 180 ldr r2, [r2] 181 182#ifdef DIAGNOSTIC 183 teq r2, #0x00000000 184 beq .Lfusupcbfault 185#endif 186 187 adr r1, _C_LABEL(fusubailout) 188 str r1, [r2, #PCB_ONFAULT] 189 190 ldrbt r3, [r0], #1 191 ldrbt ip, [r0] 192#ifdef __ARMEB__ 193 orr r0, ip, r3, asl #8 194#else 195 orr r0, r3, ip, asl #8 196#endif 197 198 mov r1, #0x00000000 199 str r1, [r2, #PCB_ONFAULT] 200 RET 201END(fuswintr) 202 203Lblock_userspace_access: 204 .word _C_LABEL(block_userspace_access) 205 206 .data 207 .align 0 208 .global _C_LABEL(block_userspace_access) 209_C_LABEL(block_userspace_access): 210 .word 0 211 .text 212 213/* 214 * fubyte(caddr_t uaddr); 215 * Fetch a byte from the user's address space. 216 */ 217 218ENTRY(fubyte) 219 GET_PCB(r2) 220 ldr r2, [r2] 221 222#ifdef DIAGNOSTIC 223 teq r2, #0x00000000 224 beq .Lfusupcbfault 225#endif 226 227 adr r1, .Lfusufault 228 str r1, [r2, #PCB_ONFAULT] 229 230 ldrbt r3, [r0] 231 232 mov r1, #0x00000000 233 str r1, [r2, #PCB_ONFAULT] 234 mov r0, r3 235 RET 236END(fubyte) 237 238/* 239 * Handle faults from [fs]u*(). Clean up and return -1. 240 */ 241 242.Lfusufault: 243 mov r0, #0x00000000 244 str r0, [r2, #PCB_ONFAULT] 245 mvn r0, #0x00000000 246 RET 247 248/* 249 * Handle faults from [fs]u*(). Clean up and return -1. This differs from 250 * fusufault() in that trap() will recognise it and return immediately rather 251 * than trying to page fault. 252 */ 253 254/* label must be global as fault.c references it */ 255 .global _C_LABEL(fusubailout) 256_C_LABEL(fusubailout): 257 mov r0, #0x00000000 258 str r0, [r2, #PCB_ONFAULT] 259 mvn r0, #0x00000000 260 RET 261 262#ifdef DIAGNOSTIC 263/* 264 * Handle earlier faults from [fs]u*(), due to no pcb 265 */ 266 267.Lfusupcbfault: 268 mov r1, r0 269 adr r0, fusupcbfaulttext 270 b _C_LABEL(panic) 271 272fusupcbfaulttext: 273 .asciz "Yikes - no valid PCB during fusuxxx() addr=%08x\n" 274 .align 0 275#endif 276 277/* 278 * suword(caddr_t uaddr, int x); 279 * Store an int in the user's address space. 280 */ 281 282ENTRY(suword) 283EENTRY_NP(suword32) 284 GET_PCB(r2) 285 ldr r2, [r2] 286 287#ifdef DIAGNOSTIC 288 teq r2, #0x00000000 289 beq .Lfusupcbfault 290#endif 291 292 adr r3, .Lfusufault 293 str r3, [r2, #PCB_ONFAULT] 294 295 strt r1, [r0] 296 297 mov r0, #0x00000000 298 str r0, [r2, #PCB_ONFAULT] 299 RET 300EEND(suword32) 301END(suword) 302 303/* 304 * suswintr(caddr_t uaddr, short x); 305 * Store a short in the user's address space. Can be called during an 306 * interrupt. 307 */ 308 309ENTRY(suswintr) 310 ldr r2, Lblock_userspace_access 311 ldr r2, [r2] 312 teq r2, #0 313 mvnne r0, #0x00000000 314 RETne 315 316 GET_PCB(r2) 317 ldr r2, [r2] 318 319#ifdef DIAGNOSTIC 320 teq r2, #0x00000000 321 beq .Lfusupcbfault 322#endif 323 324 adr r3, _C_LABEL(fusubailout) 325 str r3, [r2, #PCB_ONFAULT] 326 327#ifdef __ARMEB__ 328 mov ip, r1, lsr #8 329 strbt ip, [r0], #1 330#else 331 strbt r1, [r0], #1 332 mov r1, r1, lsr #8 333#endif 334 strbt r1, [r0] 335 336 mov r0, #0x00000000 337 str r0, [r2, #PCB_ONFAULT] 338 RET 339END(suswintr) 340 341/* 342 * susword(caddr_t uaddr, short x); 343 * Store a short in the user's address space. 344 */ 345 346ENTRY(susword) 347 GET_PCB(r2) 348 ldr r2, [r2] 349 350#ifdef DIAGNOSTIC 351 teq r2, #0x00000000 352 beq .Lfusupcbfault 353#endif 354 355 adr r3, .Lfusufault 356 str r3, [r2, #PCB_ONFAULT] 357 358#ifdef __ARMEB__ 359 mov ip, r1, lsr #8 360 strbt ip, [r0], #1 361#else 362 strbt r1, [r0], #1 363 mov r1, r1, lsr #8 364#endif 365 strbt r1, [r0] 366 367 mov r0, #0x00000000 368 str r0, [r2, #PCB_ONFAULT] 369 RET 370END(susword) 371 372/* 373 * subyte(caddr_t uaddr, char x); 374 * Store a byte in the user's address space. 375 */ 376 377ENTRY(subyte) 378 GET_PCB(r2) 379 ldr r2, [r2] 380 381 382#ifdef DIAGNOSTIC 383 teq r2, #0x00000000 384 beq .Lfusupcbfault 385#endif 386 387 adr r3, .Lfusufault 388 str r3, [r2, #PCB_ONFAULT] 389 390 strbt r1, [r0] 391 mov r0, #0x00000000 392 str r0, [r2, #PCB_ONFAULT] 393 RET 394END(subyte) 395