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