fusu.S revision 269390
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/armreg.h> 38129198Scognet#include "assym.s" 39129198Scognet__FBSDID("$FreeBSD: head/sys/arm/arm/fusu.S 269390 2014-08-01 18:24:44Z ian $"); 40129198Scognet 41239268Sgonzo#ifdef _ARM_ARCH_6 42239268Sgonzo#define GET_PCB(tmp) \ 43239268Sgonzo mrc p15, 0, tmp, c13, c0, 4; \ 44261415Scognet add tmp, tmp, #(TD_PCB) 45129198Scognet#else 46129198Scognet.Lcurpcb: 47129198Scognet .word _C_LABEL(__pcpu) + PC_CURPCB 48239268Sgonzo#define GET_PCB(tmp) \ 49239268Sgonzo ldr tmp, .Lcurpcb 50129198Scognet#endif 51129198Scognet 52129198Scognet/* 53129198Scognet * fuword(caddr_t uaddr); 54129198Scognet * Fetch an int from the user's address space. 55129198Scognet */ 56129198Scognet 57163449SdavidxuENTRY(casuword) 58269390SianEENTRY_NP(casuword32) 59239268Sgonzo GET_PCB(r3) 60137271Scognet ldr r3, [r3] 61137271Scognet 62137271Scognet#ifdef DIAGNOSTIC 63137271Scognet teq r3, #0x00000000 64137271Scognet beq .Lfusupcbfault 65137271Scognet#endif 66145452Scognet stmfd sp!, {r4, r5} 67163449Sdavidxu adr r4, .Lcasuwordfault 68137271Scognet str r4, [r3, #PCB_ONFAULT] 69256691Scognet#ifdef _ARM_ARCH_6 70256691Scognet1: 71256691Scognet cmp r0, #KERNBASE 72256748Scognet mvnhs r0, #0 73256748Scognet bhs 2f 74256691Scognet 75256691Scognet ldrex r5, [r0] 76256691Scognet cmp r5, r1 77256691Scognet movne r0, r5 78256691Scognet bne 2f 79256691Scognet strex r5, r2, [r0] 80256691Scognet cmp r5, #0 81256691Scognet bne 1b 82256691Scognet#else 83145452Scognet ldrt r5, [r0] 84145452Scognet cmp r5, r1 85145452Scognet movne r0, r5 86145452Scognet streqt r2, [r0] 87256691Scognet#endif 88145452Scognet moveq r0, r1 89256691Scognet2: 90145452Scognet ldmfd sp!, {r4, r5} 91137271Scognet mov r1, #0x00000000 92137271Scognet str r1, [r3, #PCB_ONFAULT] 93137463Scognet RET 94269390SianEEND(casuword32) 95248361SandrewEND(casuword) 96137271Scognet 97137271Scognet/* 98163449Sdavidxu * Handle faults from casuword. Clean up and return -1. 99145452Scognet */ 100145452Scognet 101163449Sdavidxu.Lcasuwordfault: 102145452Scognet mov r0, #0x00000000 103145452Scognet str r0, [r3, #PCB_ONFAULT] 104145452Scognet mvn r0, #0x00000000 105145452Scognet ldmfd sp!, {r4, r5} 106145452Scognet RET 107248361Sandrew 108145452Scognet/* 109137271Scognet * fuword(caddr_t uaddr); 110137271Scognet * Fetch an int from the user's address space. 111137271Scognet */ 112137271Scognet 113129198ScognetENTRY(fuword) 114269390SianEENTRY_NP(fuword32) 115239268Sgonzo GET_PCB(r2) 116129198Scognet ldr r2, [r2] 117129198Scognet 118129198Scognet#ifdef DIAGNOSTIC 119129198Scognet teq r2, #0x00000000 120129198Scognet beq .Lfusupcbfault 121129198Scognet#endif 122129198Scognet 123129198Scognet adr r1, .Lfusufault 124129198Scognet str r1, [r2, #PCB_ONFAULT] 125129198Scognet 126129198Scognet ldrt r3, [r0] 127129198Scognet 128129198Scognet mov r1, #0x00000000 129129198Scognet str r1, [r2, #PCB_ONFAULT] 130129198Scognet mov r0, r3 131137463Scognet RET 132248361SandrewEND(fuword32) 133248361SandrewEND(fuword) 134129198Scognet 135129198Scognet/* 136129198Scognet * fusword(caddr_t uaddr); 137129198Scognet * Fetch a short from the user's address space. 138129198Scognet */ 139129198Scognet 140129198ScognetENTRY(fusword) 141239268Sgonzo GET_PCB(r2) 142129198Scognet ldr r2, [r2] 143129198Scognet 144129198Scognet#ifdef DIAGNOSTIC 145129198Scognet teq r2, #0x00000000 146129198Scognet beq .Lfusupcbfault 147129198Scognet#endif 148129198Scognet 149129198Scognet adr r1, .Lfusufault 150129198Scognet str r1, [r2, #PCB_ONFAULT] 151129198Scognet 152129198Scognet ldrbt r3, [r0], #1 153129198Scognet ldrbt ip, [r0] 154129198Scognet#ifdef __ARMEB__ 155129198Scognet orr r0, ip, r3, asl #8 156129198Scognet#else 157129198Scognet orr r0, r3, ip, asl #8 158129198Scognet#endif 159129198Scognet mov r1, #0x00000000 160129198Scognet str r1, [r2, #PCB_ONFAULT] 161137463Scognet RET 162248361SandrewEND(fusword) 163129198Scognet 164129198Scognet/* 165129198Scognet * fuswintr(caddr_t uaddr); 166129198Scognet * Fetch a short from the user's address space. Can be called during an 167129198Scognet * interrupt. 168129198Scognet */ 169129198Scognet 170129198ScognetENTRY(fuswintr) 171129198Scognet ldr r2, Lblock_userspace_access 172129198Scognet ldr r2, [r2] 173129198Scognet teq r2, #0 174129198Scognet mvnne r0, #0x00000000 175137463Scognet RETne 176129198Scognet 177239268Sgonzo GET_PCB(r2) 178129198Scognet ldr r2, [r2] 179129198Scognet 180129198Scognet#ifdef DIAGNOSTIC 181129198Scognet teq r2, #0x00000000 182129198Scognet beq .Lfusupcbfault 183129198Scognet#endif 184129198Scognet 185129198Scognet adr r1, _C_LABEL(fusubailout) 186129198Scognet str r1, [r2, #PCB_ONFAULT] 187129198Scognet 188129198Scognet ldrbt r3, [r0], #1 189129198Scognet ldrbt ip, [r0] 190129198Scognet#ifdef __ARMEB__ 191129198Scognet orr r0, ip, r3, asl #8 192129198Scognet#else 193129198Scognet orr r0, r3, ip, asl #8 194129198Scognet#endif 195129198Scognet 196129198Scognet mov r1, #0x00000000 197129198Scognet str r1, [r2, #PCB_ONFAULT] 198137463Scognet RET 199248361SandrewEND(fuswintr) 200129198Scognet 201129198ScognetLblock_userspace_access: 202129198Scognet .word _C_LABEL(block_userspace_access) 203129198Scognet 204129198Scognet .data 205129198Scognet .align 0 206129198Scognet .global _C_LABEL(block_userspace_access) 207129198Scognet_C_LABEL(block_userspace_access): 208129198Scognet .word 0 209129198Scognet .text 210129198Scognet 211129198Scognet/* 212129198Scognet * fubyte(caddr_t uaddr); 213129198Scognet * Fetch a byte from the user's address space. 214129198Scognet */ 215129198Scognet 216129198ScognetENTRY(fubyte) 217239268Sgonzo GET_PCB(r2) 218129198Scognet ldr r2, [r2] 219129198Scognet 220129198Scognet#ifdef DIAGNOSTIC 221129198Scognet teq r2, #0x00000000 222129198Scognet beq .Lfusupcbfault 223129198Scognet#endif 224129198Scognet 225129198Scognet adr r1, .Lfusufault 226129198Scognet str r1, [r2, #PCB_ONFAULT] 227129198Scognet 228129198Scognet ldrbt r3, [r0] 229129198Scognet 230129198Scognet mov r1, #0x00000000 231129198Scognet str r1, [r2, #PCB_ONFAULT] 232129198Scognet mov r0, r3 233137463Scognet RET 234248361SandrewEND(fubyte) 235129198Scognet 236129198Scognet/* 237129198Scognet * Handle faults from [fs]u*(). Clean up and return -1. 238129198Scognet */ 239129198Scognet 240129198Scognet.Lfusufault: 241129198Scognet mov r0, #0x00000000 242129198Scognet str r0, [r2, #PCB_ONFAULT] 243129198Scognet mvn r0, #0x00000000 244137463Scognet RET 245129198Scognet 246129198Scognet/* 247129198Scognet * Handle faults from [fs]u*(). Clean up and return -1. This differs from 248129198Scognet * fusufault() in that trap() will recognise it and return immediately rather 249129198Scognet * than trying to page fault. 250129198Scognet */ 251129198Scognet 252129198Scognet/* label must be global as fault.c references it */ 253129198Scognet .global _C_LABEL(fusubailout) 254129198Scognet_C_LABEL(fusubailout): 255129198Scognet mov r0, #0x00000000 256129198Scognet str r0, [r2, #PCB_ONFAULT] 257129198Scognet mvn r0, #0x00000000 258137463Scognet RET 259129198Scognet 260129198Scognet#ifdef DIAGNOSTIC 261129198Scognet/* 262129198Scognet * Handle earlier faults from [fs]u*(), due to no pcb 263129198Scognet */ 264129198Scognet 265129198Scognet.Lfusupcbfault: 266129198Scognet mov r1, r0 267129198Scognet adr r0, fusupcbfaulttext 268129198Scognet b _C_LABEL(panic) 269129198Scognet 270129198Scognetfusupcbfaulttext: 271129198Scognet .asciz "Yikes - no valid PCB during fusuxxx() addr=%08x\n" 272129198Scognet .align 0 273129198Scognet#endif 274129198Scognet 275129198Scognet/* 276129198Scognet * suword(caddr_t uaddr, int x); 277129198Scognet * Store an int in the user's address space. 278129198Scognet */ 279129198Scognet 280129198ScognetENTRY(suword) 281269390SianEENTRY_NP(suword32) 282239268Sgonzo GET_PCB(r2) 283129198Scognet ldr r2, [r2] 284129198Scognet 285129198Scognet#ifdef DIAGNOSTIC 286129198Scognet teq r2, #0x00000000 287129198Scognet beq .Lfusupcbfault 288129198Scognet#endif 289129198Scognet 290129198Scognet adr r3, .Lfusufault 291129198Scognet str r3, [r2, #PCB_ONFAULT] 292129198Scognet 293129198Scognet strt r1, [r0] 294129198Scognet 295129198Scognet mov r0, #0x00000000 296129198Scognet str r0, [r2, #PCB_ONFAULT] 297137463Scognet RET 298248361SandrewEND(suword32) 299248361SandrewEND(suword) 300129198Scognet 301129198Scognet/* 302129198Scognet * suswintr(caddr_t uaddr, short x); 303129198Scognet * Store a short in the user's address space. Can be called during an 304129198Scognet * interrupt. 305129198Scognet */ 306129198Scognet 307129198ScognetENTRY(suswintr) 308129198Scognet ldr r2, Lblock_userspace_access 309129198Scognet ldr r2, [r2] 310129198Scognet teq r2, #0 311129198Scognet mvnne r0, #0x00000000 312137463Scognet RETne 313129198Scognet 314239268Sgonzo GET_PCB(r2) 315129198Scognet ldr r2, [r2] 316129198Scognet 317129198Scognet#ifdef DIAGNOSTIC 318129198Scognet teq r2, #0x00000000 319129198Scognet beq .Lfusupcbfault 320129198Scognet#endif 321129198Scognet 322129198Scognet adr r3, _C_LABEL(fusubailout) 323129198Scognet str r3, [r2, #PCB_ONFAULT] 324129198Scognet 325129198Scognet#ifdef __ARMEB__ 326129198Scognet mov ip, r1, lsr #8 327129198Scognet strbt ip, [r0], #1 328129198Scognet#else 329129198Scognet strbt r1, [r0], #1 330129198Scognet mov r1, r1, lsr #8 331129198Scognet#endif 332129198Scognet strbt r1, [r0] 333129198Scognet 334129198Scognet mov r0, #0x00000000 335129198Scognet str r0, [r2, #PCB_ONFAULT] 336137463Scognet RET 337248361SandrewEND(suswintr) 338129198Scognet 339129198Scognet/* 340129198Scognet * susword(caddr_t uaddr, short x); 341129198Scognet * Store a short in the user's address space. 342129198Scognet */ 343129198Scognet 344129198ScognetENTRY(susword) 345239268Sgonzo GET_PCB(r2) 346129198Scognet ldr r2, [r2] 347129198Scognet 348129198Scognet#ifdef DIAGNOSTIC 349129198Scognet teq r2, #0x00000000 350129198Scognet beq .Lfusupcbfault 351129198Scognet#endif 352129198Scognet 353129198Scognet adr r3, .Lfusufault 354129198Scognet str r3, [r2, #PCB_ONFAULT] 355129198Scognet 356129198Scognet#ifdef __ARMEB__ 357129198Scognet mov ip, r1, lsr #8 358129198Scognet strbt ip, [r0], #1 359129198Scognet#else 360129198Scognet strbt r1, [r0], #1 361129198Scognet mov r1, r1, lsr #8 362129198Scognet#endif 363129198Scognet strbt r1, [r0] 364129198Scognet 365129198Scognet mov r0, #0x00000000 366129198Scognet str r0, [r2, #PCB_ONFAULT] 367137463Scognet RET 368248361SandrewEND(susword) 369129198Scognet 370129198Scognet/* 371129198Scognet * subyte(caddr_t uaddr, char x); 372129198Scognet * Store a byte in the user's address space. 373129198Scognet */ 374129198Scognet 375129198ScognetENTRY(subyte) 376239268Sgonzo GET_PCB(r2) 377129198Scognet ldr r2, [r2] 378129198Scognet 379129198Scognet 380129198Scognet#ifdef DIAGNOSTIC 381129198Scognet teq r2, #0x00000000 382129198Scognet beq .Lfusupcbfault 383129198Scognet#endif 384129198Scognet 385129198Scognet adr r3, .Lfusufault 386129198Scognet str r3, [r2, #PCB_ONFAULT] 387129198Scognet 388129198Scognet strbt r1, [r0] 389129198Scognet mov r0, #0x00000000 390129198Scognet str r0, [r2, #PCB_ONFAULT] 391137463Scognet RET 392248361SandrewEND(subyte) 393