1/* 2 * User Space Access Routines 3 * 4 * Copyright (C) 2000-2002 Hewlett-Packard (John Marvin) 5 * Copyright (C) 2000 Richard Hirst <rhirst with parisc-linux.org> 6 * Copyright (C) 2001 Matthieu Delahaye <delahaym at esiee.fr> 7 * Copyright (C) 2003 Randolph Chung <tausq with parisc-linux.org> 8 * 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2, or (at your option) 13 * any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 */ 24 25/* 26 * These routines still have plenty of room for optimization 27 * (word & doubleword load/store, dual issue, store hints, etc.). 28 */ 29 30/* 31 * The following routines assume that space register 3 (sr3) contains 32 * the space id associated with the current users address space. 33 */ 34 35 36 .text 37 38#include <asm/assembly.h> 39#include <asm/errno.h> 40 41 /* 42 * get_sr gets the appropriate space value into 43 * sr1 for kernel/user space access, depending 44 * on the flag stored in the task structure. 45 */ 46 47 .macro get_sr 48 mfctl %cr30,%r1 49 ldw TI_SEGMENT(%r1),%r22 50 mfsp %sr3,%r1 51 or,<> %r22,%r0,%r0 52 copy %r0,%r1 53 mtsp %r1,%sr1 54 .endm 55 56 .macro fixup_branch lbl 57 ldil L%\lbl, %r1 58 ldo R%\lbl(%r1), %r1 59 bv %r0(%r1) 60 .endm 61 62 /* 63 * long lstrncpy_from_user(char *dst, const char *src, long n) 64 * 65 * Returns -EFAULT if exception before terminator, 66 * N if the entire buffer filled, 67 * otherwise strlen (i.e. excludes zero byte) 68 */ 69 70 .export lstrncpy_from_user,code 71lstrncpy_from_user: 72 .proc 73 .callinfo NO_CALLS 74 .entry 75 comib,= 0,%r24,$lsfu_done 76 copy %r24,%r23 77 get_sr 781: ldbs,ma 1(%sr1,%r25),%r1 79$lsfu_loop: 80 stbs,ma %r1,1(%r26) 81 comib,=,n 0,%r1,$lsfu_done 82 addib,<>,n -1,%r24,$lsfu_loop 832: ldbs,ma 1(%sr1,%r25),%r1 84$lsfu_done: 85 sub %r23,%r24,%r28 86$lsfu_exit: 87 bv %r0(%r2) 88 nop 89 .exit 90 91 .section .fixup,"ax" 923: fixup_branch $lsfu_exit 93 ldi -EFAULT,%r28 94 .previous 95 96 .section __ex_table,"aw" 97#ifdef __LP64__ 98 .dword 1b,3b 99 .dword 2b,3b 100#else 101 .word 1b,3b 102 .word 2b,3b 103#endif 104 .previous 105 106 .procend 107 108 /* 109 * unsigned long lclear_user(void *to, unsigned long n) 110 * 111 * Returns 0 for success. 112 * otherwise, returns number of bytes not transferred. 113 */ 114 115 .export lclear_user,code 116lclear_user: 117 .proc 118 .callinfo NO_CALLS 119 .entry 120 comib,=,n 0,%r25,$lclu_done 121 get_sr 122$lclu_loop: 123 addib,<> -1,%r25,$lclu_loop 1241: stbs,ma %r0,1(%sr1,%r26) 125 126$lclu_done: 127 bv %r0(%r2) 128 copy %r25,%r28 129 .exit 130 131 .section .fixup,"ax" 1322: fixup_branch $lclu_done 133 ldo 1(%r25),%r25 134 .previous 135 136 .section __ex_table,"aw" 137#ifdef __LP64__ 138 .dword 1b,2b 139#else 140 .word 1b,2b 141#endif 142 .previous 143 144 .procend 145 146 /* 147 * long lstrnlen_user(char *s, long n) 148 * 149 * Returns 0 if exception before zero byte or reaching N, 150 * N+1 if N would be exceeded, 151 * else strlen + 1 (i.e. includes zero byte). 152 */ 153 154 .export lstrnlen_user,code 155lstrnlen_user: 156 .proc 157 .callinfo NO_CALLS 158 .entry 159 comib,= 0,%r25,$lslen_nzero 160 copy %r26,%r24 161 get_sr 1621: ldbs,ma 1(%sr1,%r26),%r1 163$lslen_loop: 164 comib,=,n 0,%r1,$lslen_done 165 addib,<> -1,%r25,$lslen_loop 1662: ldbs,ma 1(%sr1,%r26),%r1 167$lslen_done: 168 bv %r0(%r2) 169 sub %r26,%r24,%r28 170 .exit 171 172$lslen_nzero: 173 b $lslen_done 174 ldo 1(%r26),%r26 /* special case for N == 0 */ 175 176 .section .fixup,"ax" 1773: fixup_branch $lslen_done 178 copy %r24,%r26 /* reset r26 so 0 is returned on fault */ 179 .previous 180 181 .section __ex_table,"aw" 182#ifdef __LP64__ 183 .dword 1b,3b 184 .dword 2b,3b 185#else 186 .word 1b,3b 187 .word 2b,3b 188#endif 189 .previous 190 191 .procend 192 193 .end 194