[BACK]Return to copy.s CVS log [TXT][DIR] Up to [local] / sys / arch / m68k / m68k

Annotation of sys/arch/m68k/m68k/copy.s, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: copy.s,v 1.18 2006/11/29 13:22:07 miod Exp $  */
                      2: /*     $NetBSD: copy.s,v 1.30 1998/03/04 06:39:14 thorpej Exp $        */
                      3:
                      4: /*-
                      5:  * Copyright (c) 1998 Jason R. Thorpe.  All rights reserved.
                      6:  * Copyright (c) 1994, 1995 Charles Hannum.
                      7:  * Copyright (c) 1990 The Regents of the University of California.
                      8:  * All rights reserved.
                      9:  *
                     10:  * This code is derived from software contributed to Berkeley by
                     11:  * the Systems Programming Group of the University of Utah Computer
                     12:  * Science Department.
                     13:  *
                     14:  * Redistribution and use in source and binary forms, with or without
                     15:  * modification, are permitted provided that the following conditions
                     16:  * are met:
                     17:  * 1. Redistributions of source code must retain the above copyright
                     18:  *    notice, this list of conditions and the following disclaimer.
                     19:  * 2. Redistributions in binary form must reproduce the above copyright
                     20:  *    notice, this list of conditions and the following disclaimer in the
                     21:  *    documentation and/or other materials provided with the distribution.
                     22:  * 3. Neither the name of the University nor the names of its contributors
                     23:  *    may be used to endorse or promote products derived from this software
                     24:  *    without specific prior written permission.
                     25:  *
                     26:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     28:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     29:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     30:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     31:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     32:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     33:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     34:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     35:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     36:  * SUCH DAMAGE.
                     37:  */
                     38:
                     39: /*
                     40:  * This file contains the functions for user-space access:
                     41:  * copyin/copyout, etc.
                     42:  */
                     43:
                     44: #include <machine/asm.h>
                     45:
                     46: #include "assym.h"
                     47:
                     48:        .file   "copy.s"
                     49:        .text
                     50:
                     51: #ifdef DEBUG
                     52: /*
                     53:  * The following routines all use the "moves" instruction to access
                     54:  * memory with "user" privilege while running in supervisor mode.
                     55:  * The "function code" registers actually determine what type of
                     56:  * access "moves" does, and the kernel arranges to leave them set
                     57:  * for "user data" access when these functions are called.
                     58:  *
                     59:  * The diagnostics:  CHECK_SFC,  CHECK_DFC
                     60:  * will verify that the sfc/dfc register values are correct.
                     61:  */
                     62: Lbadfc:
                     63:        PANIC("copy.s: bad sfc or dfc")
                     64:        bra     Lbadfc
                     65: #define        CHECK_SFC       movec sfc,d0; subql #FC_USERD,d0; bne Lbadfc
                     66: #define        CHECK_DFC       movec dfc,d0; subql #FC_USERD,d0; bne Lbadfc
                     67: #else  /* DEBUG */
                     68: #define        CHECK_SFC
                     69: #define        CHECK_DFC
                     70: #endif /* DEBUG */
                     71:
                     72: /*
                     73:  * copyin(caddr_t from, caddr_t to, size_t len);
                     74:  * Copy len bytes from the user's address space.
                     75:  *
                     76:  * This is probably not the best we can do, but it is still 2-10 times
                     77:  * faster than the C version in the portable gen directory.
                     78:  *
                     79:  * Things that might help:
                     80:  *     - unroll the longword copy loop (might not be good for a 68020)
                     81:  *     - longword align when possible (only on the 68020)
                     82:  */
                     83: ENTRY(copyin)
                     84:        CHECK_SFC
                     85:        movl    sp@(12),d0              | check count
                     86:        beq     Lciret                  | == 0, don't do anything
                     87:        movl    d2,sp@-                 | save scratch register
                     88:        movl    _C_LABEL(curpcb),a0     | set fault handler
                     89:        movl    #Lcifault,a0@(PCB_ONFAULT)
                     90:        movl    sp@(8),a0               | src address
                     91:        movl    sp@(12),a1              | dest address
                     92:        movl    a0,d1
                     93:        btst    #0,d1                   | src address odd?
                     94:        beq     Lcieven                 | no, skip alignment
                     95:        movsb   a0@+,d2                 | yes, copy a byte
                     96:        movb    d2,a1@+
                     97:        subql   #1,d0                   | adjust count
                     98:        beq     Lcidone                 | count 0, all done
                     99: Lcieven:
                    100:        movl    a1,d1
                    101:        btst    #0,d1                   | dest address odd?
                    102:        bne     Lcibytes                | yes, must copy bytes
                    103:        movl    d0,d1                   | OK, both even.  Get count
                    104:        lsrl    #2,d1                   |   and convert to longwords
                    105:        beq     Lcibytes                | count 0, skip longword loop
                    106:        subql   #1,d1                   | predecrement for dbf
                    107: Lcilloop:
                    108:        movsl   a0@+,d2                 | copy a longword
                    109:        movl    d2,a1@+
                    110:        dbf     d1,Lcilloop             | decrement low word of count
                    111:        subil   #0x10000,d1             | decrement high word of count
                    112:        bcc     Lcilloop
                    113:        andl    #3,d0                   | what remains
                    114:        beq     Lcidone                 | nothing, all done
                    115: Lcibytes:
                    116:        subql   #1,d0                   | predecrement for dbf
                    117: Lcibloop:
                    118:        movsb   a0@+,d2                 | copy a byte
                    119:        movb    d2,a1@+
                    120:        dbf     d0,Lcibloop             | decrement low word of count
                    121:        subil   #0x10000,d0             | decrement high word of count
                    122:        bcc     Lcibloop
                    123:        clrl    d0                      | no error
                    124: Lcidone:
                    125:        movl    _C_LABEL(curpcb),a0     | clear fault handler
                    126:        clrl    a0@(PCB_ONFAULT)
                    127:        movl    sp@+,d2                 | restore scratch register
                    128: Lciret:
                    129:        rts
                    130: Lcifault:
                    131:        moveq   #EFAULT,d0              | got a fault
                    132:        bra     Lcidone
                    133:
                    134: /*
                    135:  * copyout(caddr_t from, caddr_t to, size_t len);
                    136:  * Copy len bytes into the user's address space.
                    137:  *
                    138:  * This is probably not the best we can do, but it is still 2-10 times
                    139:  * faster than the C version in the portable gen directory.
                    140:  *
                    141:  * Things that might help:
                    142:  *     - unroll the longword copy loop (might not be good for a 68020)
                    143:  *     - longword align when possible (only on the 68020)
                    144:  */
                    145: ENTRY(copyout)
                    146:        CHECK_DFC
                    147:        movl    sp@(12),d0              | check count
                    148:        beq     Lcoret                  | == 0, don't do anything
                    149:        movl    d2,sp@-                 | save scratch register
                    150:        movl    _C_LABEL(curpcb),a0     | set fault handler
                    151:        movl    #Lcofault,a0@(PCB_ONFAULT)
                    152:        movl    sp@(8),a0               | src address
                    153:        movl    sp@(12),a1              | dest address
                    154:        movl    a0,d1
                    155:        btst    #0,d1                   | src address odd?
                    156:        beq     Lcoeven                 | no, skip alignment
                    157:        movb    a0@+,d2                 | yes, copy a byte
                    158:        movsb   d2,a1@+
                    159:        subql   #1,d0                   | adjust count
                    160:        beq     Lcodone                 | count 0, all done
                    161: Lcoeven:
                    162:        movl    a1,d1
                    163:        btst    #0,d1                   | dest address odd?
                    164:        bne     Lcobytes                | yes, must copy bytes
                    165:        movl    d0,d1                   | OK, both even.  Get count
                    166:        lsrl    #2,d1                   |   and convert to longwords
                    167:        beq     Lcobytes                | count 0, skip longword loop
                    168:        subql   #1,d1                   | predecrement for dbf
                    169: Lcolloop:
                    170:        movl    a0@+,d2                 | copy a longword
                    171:        movsl   d2,a1@+
                    172:        dbf     d1,Lcolloop             | decrement low word of count
                    173:        subil   #0x10000,d1             | decrement high word of count
                    174:        bcc     Lcolloop
                    175:        andl    #3,d0                   | what remains
                    176:        beq     Lcodone                 | nothing, all done
                    177: Lcobytes:
                    178:        subql   #1,d0                   | predecrement for dbf
                    179: Lcobloop:
                    180:        movb    a0@+,d2                 | copy a byte
                    181:        movsb   d2,a1@+
                    182:        dbf     d0,Lcobloop             | decrement low word of count
                    183:        subil   #0x10000,d0             | decrement high word of count
                    184:        bcc     Lcobloop
                    185:        clrl    d0                      | no error
                    186: Lcodone:
                    187:        movl    _C_LABEL(curpcb),a0     | clear fault handler
                    188:        clrl    a0@(PCB_ONFAULT)
                    189:        movl    sp@+,d2                 | restore scratch register
                    190: Lcoret:
                    191:        rts
                    192: Lcofault:
                    193:        moveq   #EFAULT,d0
                    194:        bra     Lcodone
                    195:
                    196: /*
                    197:  * copystr(caddr_t from, caddr_t to, size_t maxlen, size_t *lencopied);
                    198:  * Copy a NUL-terminated string, at most maxlen characters long.  Return the
                    199:  * number of characters copied (including the NUL) in *lencopied.  If the
                    200:  * string is too long, return ENAMETOOLONG; else return 0.
                    201:  */
                    202: ENTRY(copystr)
                    203:        movl    sp@(4),a0               | a0 = fromaddr
                    204:        movl    sp@(8),a1               | a1 = toaddr
                    205:        clrl    d0
                    206:        movl    sp@(12),d1              | count
                    207:        beq     Lcsdone                 | nothing to copy
                    208:        subql   #1,d1                   | predecrement for dbeq
                    209: Lcsloop:
                    210:        movb    a0@+,a1@+               | copy a byte
                    211:        dbeq    d1,Lcsloop              | decrement low word of count
                    212:        beq     Lcsdone                 | copied null, exit
                    213:        subil   #0x10000,d1             | decrement high word of count
                    214:        bcc     Lcsloop                 | more room, keep going
                    215:        moveq   #ENAMETOOLONG,d0        | ran out of space
                    216: Lcsdone:
                    217:        tstl    sp@(16)                 | length desired?
                    218:        beq     Lcsret
                    219:        subl    sp@(4),a0               | yes, calculate length copied
                    220:        movl    sp@(16),a1              | store at return location
                    221:        movl    a0,a1@
                    222: Lcsret:
                    223:        rts
                    224:
                    225: /*
                    226:  * copyinstr(caddr_t from, caddr_t to, size_t maxlen, size_t *lencopied);
                    227:  * Copy a NUL-terminated string, at most maxlen characters long, from the
                    228:  * user's address space.  Return the number of characters copied (including
                    229:  * the NUL) in *lencopied.  If the string is too long, return ENAMETOOLONG;
                    230:  * else return 0 or EFAULT.
                    231:  */
                    232: ENTRY(copyinstr)
                    233:        CHECK_SFC
                    234:        movl    _C_LABEL(curpcb),a0     | set fault handler
                    235:        movl    #Lcisfault,a0@(PCB_ONFAULT)
                    236:        movl    sp@(4),a0               | a0 = fromaddr
                    237:        movl    sp@(8),a1               | a1 = toaddr
                    238:        clrl    d0
                    239:        movl    sp@(12),d1              | count
                    240:        beq     Lcistoolong             | nothing to copy
                    241:        subql   #1,d1                   | predecrement for dbeq
                    242: Lcisloop:
                    243:        movsb   a0@+,d0                 | copy a byte
                    244:        movb    d0,a1@+
                    245:        dbeq    d1,Lcisloop             | decrement low word of count
                    246:        beq     Lcisdone                | copied null, exit
                    247:        subil   #0x10000,d1             | decrement high word of count
                    248:        bcc     Lcisloop                | more room, keep going
                    249: Lcistoolong:
                    250:        moveq   #ENAMETOOLONG,d0        | ran out of space
                    251: Lcisnull:
                    252:        cmpl    sp@(8),a1               | do not attempt to clear last byte
                    253:        beq     Lcisdone                | if we faulted on first write
                    254:        subql   #1, a1
                    255:        clrb    a1@+                    | clear last byte
                    256: Lcisdone:
                    257:        tstl    sp@(16)                 | length desired?
                    258:        beq     Lcisexit
                    259:        subl    sp@(4),a0               | yes, calculate length copied
                    260:        movl    sp@(16),a1              | store at return location
                    261:        movl    a0,a1@
                    262: Lcisexit:
                    263:        movl    _C_LABEL(curpcb),a0     | clear fault handler
                    264:        clrl    a0@(PCB_ONFAULT)
                    265:        rts
                    266: Lcisfault:
                    267:        moveq   #EFAULT,d0
                    268:        bra     Lcisnull
                    269:
                    270: /*
                    271:  * copyoutstr(caddr_t from, caddr_t to, size_t maxlen, size_t *lencopied);
                    272:  * Copy a NUL-terminated string, at most maxlen characters long, into the
                    273:  * user's address space.  Return the number of characters copied (including
                    274:  * the NUL) in *lencopied.  If the string is too long, return ENAMETOOLONG;
                    275:  * else return 0 or EFAULT.
                    276:  */
                    277: ENTRY(copyoutstr)
                    278:        CHECK_DFC
                    279:        movl    _C_LABEL(curpcb),a0     | set fault handler
                    280:        movl    #Lcosfault,a0@(PCB_ONFAULT)
                    281:        movl    sp@(4),a0               | a0 = fromaddr
                    282:        movl    sp@(8),a1               | a1 = toaddr
                    283:        clrl    d0
                    284:        movl    sp@(12),d1              | count
                    285:        beq     Lcostoolong             | nothing to copy
                    286:        subql   #1,d1                   | predecrement for dbeq
                    287: Lcosloop:
                    288:        movb    a0@+,d0                 | copy a byte
                    289:        movsb   d0,a1@+
                    290:        dbeq    d1,Lcosloop             | decrement low word of count
                    291:        beq     Lcosdone                | copied null, exit
                    292:        subil   #0x10000,d1             | decrement high word of count
                    293:        bcc     Lcosloop                | more room, keep going
                    294: Lcostoolong:
                    295:        moveq   #ENAMETOOLONG,d0        | ran out of space
                    296: Lcosdone:
                    297:        tstl    sp@(16)                 | length desired?
                    298:        beq     Lcosexit
                    299:        subl    sp@(4),a0               | yes, calculate length copied
                    300:        movl    sp@(16),a1              | store at return location
                    301:        movl    a0,a1@
                    302: Lcosexit:
                    303:        movl    _C_LABEL(curpcb),a0     | clear fault handler
                    304:        clrl    a0@(PCB_ONFAULT)
                    305:        rts
                    306: Lcosfault:
                    307:        moveq   #EFAULT,d0
                    308:        bra     Lcosdone
                    309:
                    310: /*
                    311:  * kcopy(const void *src, void *dst, size_t len);
                    312:  *
                    313:  * Copy len bytes from src to dst, aborting if we encounter a fatal
                    314:  * page fault.
                    315:  *
                    316:  * kcopy() _must_ save and restore the old fault handler since it is
                    317:  * called by uiomove(), which may be in the path of servicing a non-fatal
                    318:  * page fault.
                    319:  */
                    320: ENTRY(kcopy)
                    321:        link    a6,#-4
                    322:        movl    _C_LABEL(curpcb),a0      | set fault handler
                    323:        movl    a0@(PCB_ONFAULT),a6@(-4) | save old handler first
                    324:        movl    #Lkcfault,a0@(PCB_ONFAULT)
                    325:        movl    a6@(16),sp@-            | push len
                    326:        movl    a6@(12),sp@-            | push dst
                    327:        movl    a6@(8),sp@-             | push src
                    328:        jbsr    _C_LABEL(bcopy)         | copy it
                    329:        addl    #12,sp                  | pop args
                    330:        clrl    d0                      | success!
                    331: Lkcdone:
                    332:        movl    _C_LABEL(curpcb),a0     | restore fault handler
                    333:        movl    a6@(-4),a0@(PCB_ONFAULT)
                    334:        unlk    a6
                    335:        rts
                    336: Lkcfault:
                    337:        addl    #16,sp                  | pop args and return address
                    338:        moveq   #EFAULT,d0              | indicate a fault
                    339:        bra     Lkcdone

CVSweb