linux/arch/parisc/lib/lusercopy.S
<<
>>
Prefs
   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#include <linux/linkage.h>
  41
  42        /*
  43         * get_sr gets the appropriate space value into
  44         * sr1 for kernel/user space access, depending
  45         * on the flag stored in the task structure.
  46         */
  47
  48        .macro  get_sr
  49        mfctl       %cr30,%r1
  50        ldw         TI_SEGMENT(%r1),%r22
  51        mfsp        %sr3,%r1
  52        or,<>       %r22,%r0,%r0
  53        copy        %r0,%r1
  54        mtsp        %r1,%sr1
  55        .endm
  56
  57        .macro fixup_branch lbl
  58        ldil        L%\lbl, %r1
  59        ldo         R%\lbl(%r1), %r1
  60        bv          %r0(%r1)
  61        .endm
  62
  63        /*
  64         * long lstrncpy_from_user(char *dst, const char *src, long n)
  65         *
  66         * Returns -EFAULT if exception before terminator,
  67         *         N if the entire buffer filled,
  68         *         otherwise strlen (i.e. excludes zero byte)
  69         */
  70
  71ENTRY(lstrncpy_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
  90ENDPROC(lstrncpy_from_user)
  91
  92        .section .fixup,"ax"
  933:      fixup_branch $lsfu_exit
  94        ldi         -EFAULT,%r28
  95        .previous
  96
  97        .section __ex_table,"aw"
  98        ASM_ULONG_INSN 1b,3b
  99        ASM_ULONG_INSN 2b,3b
 100        .previous
 101
 102        .procend
 103
 104        /*
 105         * unsigned long lclear_user(void *to, unsigned long n)
 106         *
 107         * Returns 0 for success.
 108         * otherwise, returns number of bytes not transferred.
 109         */
 110
 111ENTRY(lclear_user)
 112        .proc
 113        .callinfo NO_CALLS
 114        .entry
 115        comib,=,n   0,%r25,$lclu_done
 116        get_sr
 117$lclu_loop:
 118        addib,<>    -1,%r25,$lclu_loop
 1191:      stbs,ma     %r0,1(%sr1,%r26)
 120
 121$lclu_done:
 122        bv          %r0(%r2)
 123        copy        %r25,%r28
 124        .exit
 125ENDPROC(lclear_user)
 126
 127        .section .fixup,"ax"
 1282:      fixup_branch $lclu_done
 129        ldo        1(%r25),%r25
 130        .previous
 131
 132        .section __ex_table,"aw"
 133        ASM_ULONG_INSN 1b,2b
 134        .previous
 135
 136        .procend
 137
 138        /*
 139         * long lstrnlen_user(char *s, long n)
 140         *
 141         * Returns 0 if exception before zero byte or reaching N,
 142         *         N+1 if N would be exceeded,
 143         *         else strlen + 1 (i.e. includes zero byte).
 144         */
 145
 146ENTRY(lstrnlen_user)
 147        .proc
 148        .callinfo NO_CALLS
 149        .entry
 150        comib,=     0,%r25,$lslen_nzero
 151        copy        %r26,%r24
 152        get_sr
 1531:      ldbs,ma     1(%sr1,%r26),%r1
 154$lslen_loop:
 155        comib,=,n   0,%r1,$lslen_done
 156        addib,<>    -1,%r25,$lslen_loop
 1572:      ldbs,ma     1(%sr1,%r26),%r1
 158$lslen_done:
 159        bv          %r0(%r2)
 160        sub         %r26,%r24,%r28
 161        .exit
 162
 163$lslen_nzero:
 164        b           $lslen_done
 165        ldo         1(%r26),%r26 /* special case for N == 0 */
 166ENDPROC(lstrnlen_user)
 167
 168        .section .fixup,"ax"
 1693:      fixup_branch $lslen_done
 170        copy        %r24,%r26    /* reset r26 so 0 is returned on fault */
 171        .previous
 172
 173        .section __ex_table,"aw"
 174        ASM_ULONG_INSN 1b,3b
 175        ASM_ULONG_INSN 2b,3b
 176        .previous
 177
 178        .procend
 179
 180        .end
 181
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.