fusu.S revision 266311
1231990Smp/* $NetBSD: fusu.S,v 1.10 2003/12/01 13:34:44 rearnsha Exp $ */ 259243Sobrien 359243Sobrien/*- 459243Sobrien * Copyright (c) 1996-1998 Mark Brinicombe. 559243Sobrien * All rights reserved. 659243Sobrien * 759243Sobrien * Redistribution and use in source and binary forms, with or without 859243Sobrien * modification, are permitted provided that the following conditions 959243Sobrien * are met: 1059243Sobrien * 1. Redistributions of source code must retain the above copyright 1159243Sobrien * notice, this list of conditions and the following disclaimer. 1259243Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1359243Sobrien * notice, this list of conditions and the following disclaimer in the 1459243Sobrien * documentation and/or other materials provided with the distribution. 1559243Sobrien * 3. All advertising materials mentioning features or use of this software 1659243Sobrien * must display the following acknowledgement: 17100616Smp * This product includes software developed by Mark Brinicombe 1859243Sobrien * 4. The name of the company nor the name of the author may be used to 1959243Sobrien * endorse or promote products derived from this software without specific 2059243Sobrien * prior written permission. 2159243Sobrien * 2259243Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 2359243Sobrien * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 2459243Sobrien * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2559243Sobrien * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 2659243Sobrien * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2759243Sobrien * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2859243Sobrien * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2959243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3059243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3159243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3259243Sobrien * SUCH DAMAGE. 3359243Sobrien * 3459243Sobrien */ 3559243Sobrien 3659243Sobrien#include <machine/asm.h> 3759243Sobrien#include <machine/armreg.h> 3859243Sobrien#include "assym.s" 3959243Sobrien__FBSDID("$FreeBSD: stable/10/sys/arm/arm/fusu.S 266311 2014-05-17 13:53:38Z ian $"); 4059243Sobrien 4159243Sobrien#ifdef _ARM_ARCH_6 42231990Smp#define GET_PCB(tmp) \ 4359243Sobrien mrc p15, 0, tmp, c13, c0, 4; \ 4459243Sobrien add tmp, tmp, #(TD_PCB) 4559243Sobrien#else 4659243Sobrien.Lcurpcb: 4759243Sobrien .word _C_LABEL(__pcpu) + PC_CURPCB 48145479Smp#define GET_PCB(tmp) \ 49145479Smp ldr tmp, .Lcurpcb 5059243Sobrien#endif 5159243Sobrien 5259243Sobrien/* 5359243Sobrien * fuword(caddr_t uaddr); 5459243Sobrien * Fetch an int from the user's address space. 5559243Sobrien */ 5659243Sobrien 5759243SobrienENTRY_NP(casuword32) 5859243SobrienENTRY(casuword) 5959243Sobrien GET_PCB(r3) 6059243Sobrien ldr r3, [r3] 6159243Sobrien 6259243Sobrien#ifdef DIAGNOSTIC 6359243Sobrien teq r3, #0x00000000 6459243Sobrien beq .Lfusupcbfault 6559243Sobrien#endif 6659243Sobrien stmfd sp!, {r4, r5} 6759243Sobrien adr r4, .Lcasuwordfault 6859243Sobrien str r4, [r3, #PCB_ONFAULT] 6959243Sobrien ldrt r5, [r0] 7059243Sobrien cmp r5, r1 7159243Sobrien movne r0, r5 7259243Sobrien streqt r2, [r0] 7359243Sobrien moveq r0, r1 7459243Sobrien ldmfd sp!, {r4, r5} 7559243Sobrien mov r1, #0x00000000 7659243Sobrien str r1, [r3, #PCB_ONFAULT] 7759243Sobrien RET 7859243SobrienEND(casuword32) 7959243SobrienEND(casuword) 8059243Sobrien 81231990Smp/* 8259243Sobrien * Handle faults from casuword. Clean up and return -1. 8359243Sobrien */ 8459243Sobrien 85167465Smp.Lcasuwordfault: 86167465Smp mov r0, #0x00000000 8759243Sobrien str r0, [r3, #PCB_ONFAULT] 8859243Sobrien mvn r0, #0x00000000 8959243Sobrien ldmfd sp!, {r4, r5} 9059243Sobrien RET 9159243Sobrien 9259243Sobrien/* 93145479Smp * fuword(caddr_t uaddr); 9459243Sobrien * Fetch an int from the user's address space. 9559243Sobrien */ 9659243Sobrien 9759243SobrienENTRY_NP(fuword32) 9859243SobrienENTRY(fuword) 9959243Sobrien GET_PCB(r2) 10059243Sobrien ldr r2, [r2] 10159243Sobrien 10259243Sobrien#ifdef DIAGNOSTIC 103167465Smp teq r2, #0x00000000 104145479Smp beq .Lfusupcbfault 105145479Smp#endif 106145479Smp 107145479Smp adr r1, .Lfusufault 10859243Sobrien str r1, [r2, #PCB_ONFAULT] 10959243Sobrien 110145479Smp ldrt r3, [r0] 11159243Sobrien 11269408Sache mov r1, #0x00000000 11359243Sobrien str r1, [r2, #PCB_ONFAULT] 11459243Sobrien mov r0, r3 11559243Sobrien RET 11659243SobrienEND(fuword32) 11759243SobrienEND(fuword) 11859243Sobrien 11959243Sobrien/* 12059243Sobrien * fusword(caddr_t uaddr); 12159243Sobrien * Fetch a short from the user's address space. 12259243Sobrien */ 123100616Smp 12459243SobrienENTRY(fusword) 125100616Smp GET_PCB(r2) 126100616Smp ldr r2, [r2] 12759243Sobrien 12859243Sobrien#ifdef DIAGNOSTIC 12959243Sobrien teq r2, #0x00000000 13059243Sobrien beq .Lfusupcbfault 13159243Sobrien#endif 13259243Sobrien 13359243Sobrien adr r1, .Lfusufault 13459243Sobrien str r1, [r2, #PCB_ONFAULT] 13559243Sobrien 136145479Smp ldrbt r3, [r0], #1 13759243Sobrien ldrbt ip, [r0] 138167465Smp#ifdef __ARMEB__ 13959243Sobrien orr r0, ip, r3, asl #8 140145479Smp#else 14159243Sobrien orr r0, r3, ip, asl #8 142195609Smp#endif 14359243Sobrien mov r1, #0x00000000 14459243Sobrien str r1, [r2, #PCB_ONFAULT] 145167465Smp RET 14683098SmpEND(fusword) 147167465Smp 14883098Smp/* 149167465Smp * fuswintr(caddr_t uaddr); 15083098Smp * Fetch a short from the user's address space. Can be called during an 151167465Smp * interrupt. 152167465Smp */ 15359243Sobrien 154167465SmpENTRY(fuswintr) 15559243Sobrien ldr r2, Lblock_userspace_access 156167465Smp ldr r2, [r2] 157167465Smp teq r2, #0 158167465Smp mvnne r0, #0x00000000 159167465Smp RETne 16059243Sobrien 161167465Smp GET_PCB(r2) 16259243Sobrien ldr r2, [r2] 163231990Smp 164231990Smp#ifdef DIAGNOSTIC 165231990Smp teq r2, #0x00000000 166231990Smp beq .Lfusupcbfault 167231990Smp#endif 168231990Smp 169231990Smp adr r1, _C_LABEL(fusubailout) 170231990Smp str r1, [r2, #PCB_ONFAULT] 171231990Smp 172231990Smp ldrbt r3, [r0], #1 173231990Smp ldrbt ip, [r0] 174231990Smp#ifdef __ARMEB__ 175231990Smp orr r0, ip, r3, asl #8 176231990Smp#else 177231990Smp orr r0, r3, ip, asl #8 178231990Smp#endif 179231990Smp 180231990Smp mov r1, #0x00000000 181231990Smp str r1, [r2, #PCB_ONFAULT] 182231990Smp RET 183231990SmpEND(fuswintr) 184231990Smp 185231990SmpLblock_userspace_access: 186231990Smp .word _C_LABEL(block_userspace_access) 187231990Smp 188231990Smp .data 189231990Smp .align 0 190231990Smp .global _C_LABEL(block_userspace_access) 191231990Smp_C_LABEL(block_userspace_access): 192231990Smp .word 0 193231990Smp .text 194231990Smp 195231990Smp/* 196231990Smp * fubyte(caddr_t uaddr); 197231990Smp * Fetch a byte from the user's address space. 198231990Smp */ 199231990Smp 200231990SmpENTRY(fubyte) 201231990Smp GET_PCB(r2) 202231990Smp ldr r2, [r2] 203231990Smp 204231990Smp#ifdef DIAGNOSTIC 205231990Smp teq r2, #0x00000000 206231990Smp beq .Lfusupcbfault 207231990Smp#endif 208231990Smp 209231990Smp adr r1, .Lfusufault 210231990Smp str r1, [r2, #PCB_ONFAULT] 211231990Smp 212231990Smp ldrbt r3, [r0] 213231990Smp 214231990Smp mov r1, #0x00000000 215231990Smp str r1, [r2, #PCB_ONFAULT] 216231990Smp mov r0, r3 217231990Smp RET 218231990SmpEND(fubyte) 219231990Smp 220231990Smp/* 221231990Smp * Handle faults from [fs]u*(). Clean up and return -1. 222231990Smp */ 223231990Smp 224231990Smp.Lfusufault: 225231990Smp mov r0, #0x00000000 226231990Smp str r0, [r2, #PCB_ONFAULT] 227231990Smp mvn r0, #0x00000000 228231990Smp RET 229231990Smp 230231990Smp/* 231231990Smp * Handle faults from [fs]u*(). Clean up and return -1. This differs from 232231990Smp * fusufault() in that trap() will recognise it and return immediately rather 233231990Smp * than trying to page fault. 23459243Sobrien */ 235167465Smp 23659243Sobrien/* label must be global as fault.c references it */ 237167465Smp .global _C_LABEL(fusubailout) 238167465Smp_C_LABEL(fusubailout): 239167465Smp mov r0, #0x00000000 240167465Smp str r0, [r2, #PCB_ONFAULT] 241167465Smp mvn r0, #0x00000000 242167465Smp RET 243145479Smp 24459243Sobrien#ifdef DIAGNOSTIC 245145479Smp/* 24659243Sobrien * Handle earlier faults from [fs]u*(), due to no pcb 247145479Smp */ 248167465Smp 249145479Smp.Lfusupcbfault: 250131962Smp mov r1, r0 251167465Smp adr r0, fusupcbfaulttext 25259243Sobrien b _C_LABEL(panic) 253231990Smp 25469408Sachefusupcbfaulttext: 25559243Sobrien .asciz "Yikes - no valid PCB during fusuxxx() addr=%08x\n" 25669408Sache .align 0 25759243Sobrien#endif 25859243Sobrien 25959243Sobrien/* 26059243Sobrien * suword(caddr_t uaddr, int x); 26159243Sobrien * Store an int in the user's address space. 26259243Sobrien */ 26359243Sobrien 26459243SobrienENTRY_NP(suword32) 26559243SobrienENTRY(suword) 26659243Sobrien GET_PCB(r2) 267231990Smp ldr r2, [r2] 268231990Smp 269231990Smp#ifdef DIAGNOSTIC 270231990Smp teq r2, #0x00000000 271231990Smp beq .Lfusupcbfault 272231990Smp#endif 273231990Smp 27459243Sobrien adr r3, .Lfusufault 27559243Sobrien str r3, [r2, #PCB_ONFAULT] 27659243Sobrien 277167465Smp strt r1, [r0] 278145479Smp 279145479Smp mov r0, #0x00000000 28059243Sobrien str r0, [r2, #PCB_ONFAULT] 28159243Sobrien RET 28259243SobrienEND(suword32) 28359243SobrienEND(suword) 28459243Sobrien 28559243Sobrien/* 28659243Sobrien * suswintr(caddr_t uaddr, short x); 28759243Sobrien * Store a short in the user's address space. Can be called during an 28859243Sobrien * interrupt. 28959243Sobrien */ 29059243Sobrien 29159243SobrienENTRY(suswintr) 29259243Sobrien ldr r2, Lblock_userspace_access 29359243Sobrien ldr r2, [r2] 29459243Sobrien teq r2, #0 29559243Sobrien mvnne r0, #0x00000000 29659243Sobrien RETne 29759243Sobrien 29859243Sobrien GET_PCB(r2) 29959243Sobrien ldr r2, [r2] 30059243Sobrien 30159243Sobrien#ifdef DIAGNOSTIC 30259243Sobrien teq r2, #0x00000000 30359243Sobrien beq .Lfusupcbfault 30459243Sobrien#endif 305167465Smp 306167465Smp adr r3, _C_LABEL(fusubailout) 30759243Sobrien str r3, [r2, #PCB_ONFAULT] 30859243Sobrien 309167465Smp#ifdef __ARMEB__ 31059243Sobrien mov ip, r1, lsr #8 31159243Sobrien strbt ip, [r0], #1 31259243Sobrien#else 31359243Sobrien strbt r1, [r0], #1 31459243Sobrien mov r1, r1, lsr #8 31559243Sobrien#endif 31659243Sobrien strbt r1, [r0] 31759243Sobrien 31859243Sobrien mov r0, #0x00000000 31969408Sache str r0, [r2, #PCB_ONFAULT] 32059243Sobrien RET 32159243SobrienEND(suswintr) 32259243Sobrien 32359243Sobrien/* 32459243Sobrien * susword(caddr_t uaddr, short x); 32569408Sache * Store a short in the user's address space. 32659243Sobrien */ 32759243Sobrien 32859243SobrienENTRY(susword) 329231990Smp GET_PCB(r2) 33059243Sobrien ldr r2, [r2] 33159243Sobrien 33259243Sobrien#ifdef DIAGNOSTIC 33359243Sobrien teq r2, #0x00000000 33459243Sobrien beq .Lfusupcbfault 33559243Sobrien#endif 33659243Sobrien 33759243Sobrien adr r3, .Lfusufault 33859243Sobrien str r3, [r2, #PCB_ONFAULT] 33959243Sobrien 34059243Sobrien#ifdef __ARMEB__ 34159243Sobrien mov ip, r1, lsr #8 34259243Sobrien strbt ip, [r0], #1 34359243Sobrien#else 34459243Sobrien strbt r1, [r0], #1 34559243Sobrien mov r1, r1, lsr #8 34659243Sobrien#endif 34759243Sobrien strbt r1, [r0] 34859243Sobrien 349231990Smp mov r0, #0x00000000 350231990Smp str r0, [r2, #PCB_ONFAULT] 35159243Sobrien RET 35259243SobrienEND(susword) 353231990Smp 354231990Smp/* 35559243Sobrien * subyte(caddr_t uaddr, char x); 35659243Sobrien * Store a byte in the user's address space. 357167465Smp */ 35859243Sobrien 35959243SobrienENTRY(subyte) 36059243Sobrien GET_PCB(r2) 36159243Sobrien ldr r2, [r2] 36259243Sobrien 36359243Sobrien 36459243Sobrien#ifdef DIAGNOSTIC 36559243Sobrien teq r2, #0x00000000 36659243Sobrien beq .Lfusupcbfault 36759243Sobrien#endif 36859243Sobrien 36959243Sobrien adr r3, .Lfusufault 37059243Sobrien str r3, [r2, #PCB_ONFAULT] 37159243Sobrien 37259243Sobrien strbt r1, [r0] 37359243Sobrien mov r0, #0x00000000 37459243Sobrien str r0, [r2, #PCB_ONFAULT] 37559243Sobrien RET 37659243SobrienEND(subyte) 37759243Sobrien 37859243Sobrien