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