fusu.S revision 256748
1129198Scognet/* $NetBSD: fusu.S,v 1.10 2003/12/01 13:34:44 rearnsha Exp $ */ 2129198Scognet 3139735Simp/*- 4129198Scognet * Copyright (c) 1996-1998 Mark Brinicombe. 5129198Scognet * All rights reserved. 6129198Scognet * 7129198Scognet * Redistribution and use in source and binary forms, with or without 8129198Scognet * modification, are permitted provided that the following conditions 9129198Scognet * are met: 10129198Scognet * 1. Redistributions of source code must retain the above copyright 11129198Scognet * notice, this list of conditions and the following disclaimer. 12129198Scognet * 2. Redistributions in binary form must reproduce the above copyright 13129198Scognet * notice, this list of conditions and the following disclaimer in the 14129198Scognet * documentation and/or other materials provided with the distribution. 15129198Scognet * 3. All advertising materials mentioning features or use of this software 16129198Scognet * must display the following acknowledgement: 17129198Scognet * This product includes software developed by Mark Brinicombe 18129198Scognet * 4. The name of the company nor the name of the author may be used to 19129198Scognet * endorse or promote products derived from this software without specific 20129198Scognet * prior written permission. 21129198Scognet * 22129198Scognet * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 23129198Scognet * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 24129198Scognet * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25129198Scognet * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 26129198Scognet * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27129198Scognet * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28129198Scognet * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29129198Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30129198Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31129198Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32129198Scognet * SUCH DAMAGE. 33129198Scognet * 34129198Scognet */ 35129198Scognet 36129198Scognet#include <machine/asm.h> 37129198Scognet#include <machine/asmacros.h> 38129198Scognet#include <machine/armreg.h> 39129198Scognet#include "assym.s" 40129198Scognet__FBSDID("$FreeBSD: head/sys/arm/arm/fusu.S 256748 2013-10-18 17:21:47Z cognet $"); 41129198Scognet 42239268Sgonzo#ifdef _ARM_ARCH_6 43239268Sgonzo#define GET_PCB(tmp) \ 44239268Sgonzo mrc p15, 0, tmp, c13, c0, 4; \ 45239268Sgonzo add tmp, tmp, #(PC_CURPCB) 46129198Scognet#else 47129198Scognet.Lcurpcb: 48129198Scognet .word _C_LABEL(__pcpu) + PC_CURPCB 49239268Sgonzo#define GET_PCB(tmp) \ 50239268Sgonzo ldr tmp, .Lcurpcb 51129198Scognet#endif 52129198Scognet 53129198Scognet/* 54129198Scognet * fuword(caddr_t uaddr); 55129198Scognet * Fetch an int from the user's address space. 56129198Scognet */ 57129198Scognet 58161734ScognetENTRY_NP(casuword32) 59163449SdavidxuENTRY(casuword) 60239268Sgonzo GET_PCB(r3) 61137271Scognet ldr r3, [r3] 62137271Scognet 63137271Scognet#ifdef DIAGNOSTIC 64137271Scognet teq r3, #0x00000000 65137271Scognet beq .Lfusupcbfault 66137271Scognet#endif 67145452Scognet stmfd sp!, {r4, r5} 68163449Sdavidxu adr r4, .Lcasuwordfault 69137271Scognet str r4, [r3, #PCB_ONFAULT] 70256691Scognet#ifdef _ARM_ARCH_6 71256691Scognet1: 72256691Scognet cmp r0, #KERNBASE 73256748Scognet mvnhs r0, #0 74256748Scognet bhs 2f 75256691Scognet 76256691Scognet ldrex r5, [r0] 77256691Scognet cmp r5, r1 78256691Scognet movne r0, r5 79256691Scognet bne 2f 80256691Scognet strex r5, r2, [r0] 81256691Scognet cmp r5, #0 82256691Scognet bne 1b 83256691Scognet#else 84145452Scognet ldrt r5, [r0] 85145452Scognet cmp r5, r1 86145452Scognet movne r0, r5 87145452Scognet streqt r2, [r0] 88256691Scognet#endif 89145452Scognet moveq r0, r1 90256691Scognet2: 91145452Scognet ldmfd sp!, {r4, r5} 92137271Scognet mov r1, #0x00000000 93137271Scognet str r1, [r3, #PCB_ONFAULT] 94137463Scognet RET 95248361SandrewEND(casuword32) 96248361SandrewEND(casuword) 97137271Scognet 98137271Scognet/* 99163449Sdavidxu * Handle faults from casuword. Clean up and return -1. 100145452Scognet */ 101145452Scognet 102163449Sdavidxu.Lcasuwordfault: 103145452Scognet mov r0, #0x00000000 104145452Scognet str r0, [r3, #PCB_ONFAULT] 105145452Scognet mvn r0, #0x00000000 106145452Scognet ldmfd sp!, {r4, r5} 107145452Scognet RET 108248361Sandrew 109145452Scognet/* 110137271Scognet * fuword(caddr_t uaddr); 111137271Scognet * Fetch an int from the user's address space. 112137271Scognet */ 113137271Scognet 114161734ScognetENTRY_NP(fuword32) 115129198ScognetENTRY(fuword) 116239268Sgonzo GET_PCB(r2) 117129198Scognet ldr r2, [r2] 118129198Scognet 119129198Scognet#ifdef DIAGNOSTIC 120129198Scognet teq r2, #0x00000000 121129198Scognet beq .Lfusupcbfault 122129198Scognet#endif 123129198Scognet 124129198Scognet adr r1, .Lfusufault 125129198Scognet str r1, [r2, #PCB_ONFAULT] 126129198Scognet 127129198Scognet ldrt r3, [r0] 128129198Scognet 129129198Scognet mov r1, #0x00000000 130129198Scognet str r1, [r2, #PCB_ONFAULT] 131129198Scognet mov r0, r3 132137463Scognet RET 133248361SandrewEND(fuword32) 134248361SandrewEND(fuword) 135129198Scognet 136129198Scognet/* 137129198Scognet * fusword(caddr_t uaddr); 138129198Scognet * Fetch a short from the user's address space. 139129198Scognet */ 140129198Scognet 141129198ScognetENTRY(fusword) 142239268Sgonzo GET_PCB(r2) 143129198Scognet ldr r2, [r2] 144129198Scognet 145129198Scognet#ifdef DIAGNOSTIC 146129198Scognet teq r2, #0x00000000 147129198Scognet beq .Lfusupcbfault 148129198Scognet#endif 149129198Scognet 150129198Scognet adr r1, .Lfusufault 151129198Scognet str r1, [r2, #PCB_ONFAULT] 152129198Scognet 153129198Scognet ldrbt r3, [r0], #1 154129198Scognet ldrbt ip, [r0] 155129198Scognet#ifdef __ARMEB__ 156129198Scognet orr r0, ip, r3, asl #8 157129198Scognet#else 158129198Scognet orr r0, r3, ip, asl #8 159129198Scognet#endif 160129198Scognet mov r1, #0x00000000 161129198Scognet str r1, [r2, #PCB_ONFAULT] 162137463Scognet RET 163248361SandrewEND(fusword) 164129198Scognet 165129198Scognet/* 166129198Scognet * fuswintr(caddr_t uaddr); 167129198Scognet * Fetch a short from the user's address space. Can be called during an 168129198Scognet * interrupt. 169129198Scognet */ 170129198Scognet 171129198ScognetENTRY(fuswintr) 172129198Scognet ldr r2, Lblock_userspace_access 173129198Scognet ldr r2, [r2] 174129198Scognet teq r2, #0 175129198Scognet mvnne r0, #0x00000000 176137463Scognet RETne 177129198Scognet 178239268Sgonzo GET_PCB(r2) 179129198Scognet ldr r2, [r2] 180129198Scognet 181129198Scognet#ifdef DIAGNOSTIC 182129198Scognet teq r2, #0x00000000 183129198Scognet beq .Lfusupcbfault 184129198Scognet#endif 185129198Scognet 186129198Scognet adr r1, _C_LABEL(fusubailout) 187129198Scognet str r1, [r2, #PCB_ONFAULT] 188129198Scognet 189129198Scognet ldrbt r3, [r0], #1 190129198Scognet ldrbt ip, [r0] 191129198Scognet#ifdef __ARMEB__ 192129198Scognet orr r0, ip, r3, asl #8 193129198Scognet#else 194129198Scognet orr r0, r3, ip, asl #8 195129198Scognet#endif 196129198Scognet 197129198Scognet mov r1, #0x00000000 198129198Scognet str r1, [r2, #PCB_ONFAULT] 199137463Scognet RET 200248361SandrewEND(fuswintr) 201129198Scognet 202129198ScognetLblock_userspace_access: 203129198Scognet .word _C_LABEL(block_userspace_access) 204129198Scognet 205129198Scognet .data 206129198Scognet .align 0 207129198Scognet .global _C_LABEL(block_userspace_access) 208129198Scognet_C_LABEL(block_userspace_access): 209129198Scognet .word 0 210129198Scognet .text 211129198Scognet 212129198Scognet/* 213129198Scognet * fubyte(caddr_t uaddr); 214129198Scognet * Fetch a byte from the user's address space. 215129198Scognet */ 216129198Scognet 217129198ScognetENTRY(fubyte) 218239268Sgonzo GET_PCB(r2) 219129198Scognet ldr r2, [r2] 220129198Scognet 221129198Scognet#ifdef DIAGNOSTIC 222129198Scognet teq r2, #0x00000000 223129198Scognet beq .Lfusupcbfault 224129198Scognet#endif 225129198Scognet 226129198Scognet adr r1, .Lfusufault 227129198Scognet str r1, [r2, #PCB_ONFAULT] 228129198Scognet 229129198Scognet ldrbt r3, [r0] 230129198Scognet 231129198Scognet mov r1, #0x00000000 232129198Scognet str r1, [r2, #PCB_ONFAULT] 233129198Scognet mov r0, r3 234137463Scognet RET 235248361SandrewEND(fubyte) 236129198Scognet 237129198Scognet/* 238129198Scognet * Handle faults from [fs]u*(). Clean up and return -1. 239129198Scognet */ 240129198Scognet 241129198Scognet.Lfusufault: 242129198Scognet mov r0, #0x00000000 243129198Scognet str r0, [r2, #PCB_ONFAULT] 244129198Scognet mvn r0, #0x00000000 245137463Scognet RET 246129198Scognet 247129198Scognet/* 248129198Scognet * Handle faults from [fs]u*(). Clean up and return -1. This differs from 249129198Scognet * fusufault() in that trap() will recognise it and return immediately rather 250129198Scognet * than trying to page fault. 251129198Scognet */ 252129198Scognet 253129198Scognet/* label must be global as fault.c references it */ 254129198Scognet .global _C_LABEL(fusubailout) 255129198Scognet_C_LABEL(fusubailout): 256129198Scognet mov r0, #0x00000000 257129198Scognet str r0, [r2, #PCB_ONFAULT] 258129198Scognet mvn r0, #0x00000000 259137463Scognet RET 260129198Scognet 261129198Scognet#ifdef DIAGNOSTIC 262129198Scognet/* 263129198Scognet * Handle earlier faults from [fs]u*(), due to no pcb 264129198Scognet */ 265129198Scognet 266129198Scognet.Lfusupcbfault: 267129198Scognet mov r1, r0 268129198Scognet adr r0, fusupcbfaulttext 269129198Scognet b _C_LABEL(panic) 270129198Scognet 271129198Scognetfusupcbfaulttext: 272129198Scognet .asciz "Yikes - no valid PCB during fusuxxx() addr=%08x\n" 273129198Scognet .align 0 274129198Scognet#endif 275129198Scognet 276129198Scognet/* 277129198Scognet * suword(caddr_t uaddr, int x); 278129198Scognet * Store an int in the user's address space. 279129198Scognet */ 280129198Scognet 281161734ScognetENTRY_NP(suword32) 282129198ScognetENTRY(suword) 283239268Sgonzo GET_PCB(r2) 284129198Scognet ldr r2, [r2] 285129198Scognet 286129198Scognet#ifdef DIAGNOSTIC 287129198Scognet teq r2, #0x00000000 288129198Scognet beq .Lfusupcbfault 289129198Scognet#endif 290129198Scognet 291129198Scognet adr r3, .Lfusufault 292129198Scognet str r3, [r2, #PCB_ONFAULT] 293129198Scognet 294129198Scognet strt r1, [r0] 295129198Scognet 296129198Scognet mov r0, #0x00000000 297129198Scognet str r0, [r2, #PCB_ONFAULT] 298137463Scognet RET 299248361SandrewEND(suword32) 300248361SandrewEND(suword) 301129198Scognet 302129198Scognet/* 303129198Scognet * suswintr(caddr_t uaddr, short x); 304129198Scognet * Store a short in the user's address space. Can be called during an 305129198Scognet * interrupt. 306129198Scognet */ 307129198Scognet 308129198ScognetENTRY(suswintr) 309129198Scognet ldr r2, Lblock_userspace_access 310129198Scognet ldr r2, [r2] 311129198Scognet teq r2, #0 312129198Scognet mvnne r0, #0x00000000 313137463Scognet RETne 314129198Scognet 315239268Sgonzo GET_PCB(r2) 316129198Scognet ldr r2, [r2] 317129198Scognet 318129198Scognet#ifdef DIAGNOSTIC 319129198Scognet teq r2, #0x00000000 320129198Scognet beq .Lfusupcbfault 321129198Scognet#endif 322129198Scognet 323129198Scognet adr r3, _C_LABEL(fusubailout) 324129198Scognet str r3, [r2, #PCB_ONFAULT] 325129198Scognet 326129198Scognet#ifdef __ARMEB__ 327129198Scognet mov ip, r1, lsr #8 328129198Scognet strbt ip, [r0], #1 329129198Scognet#else 330129198Scognet strbt r1, [r0], #1 331129198Scognet mov r1, r1, lsr #8 332129198Scognet#endif 333129198Scognet strbt r1, [r0] 334129198Scognet 335129198Scognet mov r0, #0x00000000 336129198Scognet str r0, [r2, #PCB_ONFAULT] 337137463Scognet RET 338248361SandrewEND(suswintr) 339129198Scognet 340129198Scognet/* 341129198Scognet * susword(caddr_t uaddr, short x); 342129198Scognet * Store a short in the user's address space. 343129198Scognet */ 344129198Scognet 345129198ScognetENTRY(susword) 346239268Sgonzo GET_PCB(r2) 347129198Scognet ldr r2, [r2] 348129198Scognet 349129198Scognet#ifdef DIAGNOSTIC 350129198Scognet teq r2, #0x00000000 351129198Scognet beq .Lfusupcbfault 352129198Scognet#endif 353129198Scognet 354129198Scognet adr r3, .Lfusufault 355129198Scognet str r3, [r2, #PCB_ONFAULT] 356129198Scognet 357129198Scognet#ifdef __ARMEB__ 358129198Scognet mov ip, r1, lsr #8 359129198Scognet strbt ip, [r0], #1 360129198Scognet#else 361129198Scognet strbt r1, [r0], #1 362129198Scognet mov r1, r1, lsr #8 363129198Scognet#endif 364129198Scognet strbt r1, [r0] 365129198Scognet 366129198Scognet mov r0, #0x00000000 367129198Scognet str r0, [r2, #PCB_ONFAULT] 368137463Scognet RET 369248361SandrewEND(susword) 370129198Scognet 371129198Scognet/* 372129198Scognet * subyte(caddr_t uaddr, char x); 373129198Scognet * Store a byte in the user's address space. 374129198Scognet */ 375129198Scognet 376129198ScognetENTRY(subyte) 377239268Sgonzo GET_PCB(r2) 378129198Scognet ldr r2, [r2] 379129198Scognet 380129198Scognet 381129198Scognet#ifdef DIAGNOSTIC 382129198Scognet teq r2, #0x00000000 383129198Scognet beq .Lfusupcbfault 384129198Scognet#endif 385129198Scognet 386129198Scognet adr r3, .Lfusufault 387129198Scognet str r3, [r2, #PCB_ONFAULT] 388129198Scognet 389129198Scognet strbt r1, [r0] 390129198Scognet mov r0, #0x00000000 391129198Scognet str r0, [r2, #PCB_ONFAULT] 392137463Scognet RET 393248361SandrewEND(subyte) 394248361Sandrew 395