Annotation of kernel/machdep/ppc/fault_copy.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /*
        !            26:  * Copyright (c) 1997 Apple Computer, Inc.  All rights reserved.
        !            27:  * Copyright (c) 1994 NeXT Computer, Inc.  All rights reserved.
        !            28:  *
        !            29:  * machdep/ppc/fault_copy.c
        !            30:  *
        !            31:  * Machine dependent code for kernel user copy
        !            32:  *
        !            33:  * History :
        !            34:  * 22-Jul-1998 Umesh Vaishampayan      ([email protected])
        !            35:  *     Added safe_bzero().
        !            36:  *
        !            37:  * 30-Mar-1998 Umesh Vaishampayan  ([email protected])
        !            38:  *     Made the copy routines more robust.
        !            39:  *
        !            40:  * 22-Sep-1997  Umesh Vaishampayan  ([email protected])
        !            41:  *     Fixed error return from ENOENT to ENAMETOOLONG.
        !            42:  *
        !            43:  * March, 1997 Umesh Vaishampayan [[email protected]]
        !            44:  *     Created from sparc.
        !            45:  *
        !            46:  */
        !            47: 
        !            48: #include <diagnostic.h>
        !            49: #include <mach/mach_types.h>
        !            50: #include <sys/param.h>
        !            51: #include <sys/errno.h>
        !            52: #include <machine/setjmp.h>
        !            53: #include <machine/label_t.h>
        !            54: 
        !            55: #undef NBSEG
        !            56: #define NBSEG 0x10000000
        !            57: #undef SEGMASK
        !            58: #define SEGMASK (NBSEG-1)
        !            59: #define PGOFFSET(x) ((unsigned)x & (NBPG-1))
        !            60: #undef SEGOFFSET
        !            61: #define SEGOFFSET(x) ((unsigned)(x) & SEGMASK)
        !            62: 
        !            63: 
        !            64: caddr_t cioseg(space_t space, caddr_t addr);
        !            65: 
        !            66: int
        !            67: safe_bcopy(caddr_t src, caddr_t dst, int len)
        !            68: {
        !            69:        int error = 0;
        !            70:        label_t jmpbuf;
        !            71:        vm_offset_t tmpbuf = current_thread()->recover;
        !            72: 
        !            73: #if DIAGNOSTIC
        !            74:        if(tmpbuf)
        !            75:                kprintf("safe_bcopy() ****** NESTED SETJUMP ******\n");
        !            76: #endif /* DIAGNOSTIC */
        !            77: 
        !            78:        if (setjmp(&jmpbuf)) {
        !            79:                error = EFAULT;
        !            80:        } else {
        !            81:                current_thread()->recover = (vm_offset_t)&jmpbuf;
        !            82:                bcopy(src, dst, len);
        !            83:        }
        !            84:        current_thread()->recover = (vm_offset_t)tmpbuf;
        !            85: 
        !            86:        return(error);
        !            87: }
        !            88: 
        !            89: int
        !            90: safe_bzero(void *dst, unsigned long ulen)
        !            91: {
        !            92:        int error = 0;
        !            93:        label_t jmpbuf;
        !            94:        vm_offset_t tmpbuf = current_thread()->recover;
        !            95: 
        !            96: #if DIAGNOSTIC
        !            97:        if (tmpbuf)
        !            98:                kprintf("safe_bzero() ****** NESTED SETJUMP ******\n");
        !            99: #endif /* DIAGNOSTIC */
        !           100: 
        !           101:        if (setjmp(&jmpbuf)) {
        !           102:                error = EFAULT;
        !           103:        } else {
        !           104:                current_thread()->recover = (vm_offset_t)&jmpbuf;
        !           105:                bzero(dst, ulen);
        !           106:        }
        !           107:        current_thread()->recover = (vm_offset_t)tmpbuf;
        !           108: 
        !           109:        return(error);
        !           110: }
        !           111: 
        !           112: 
        !           113: int
        !           114: lbcopytoz(from, to, maxlen)
        !           115:     register caddr_t from, to;
        !           116:     unsigned maxlen;
        !           117: {
        !           118:        register unsigned l;
        !           119: 
        !           120:        for (l = 0; l < maxlen; l++) {
        !           121:                if (*from == '\0')
        !           122:                        return l;
        !           123:                *to++ = *from++;
        !           124:        }
        !           125:        return maxlen;
        !           126: }
        !           127: 
        !           128: /* 
        !           129:  * copy a null terminated string from the user address space into
        !           130:  * the kernel address space.
        !           131:  *   - if the user is denied read access, return EFAULT
        !           132:  *   - if the end of string isn't found before
        !           133:  *     maxlen bytes are copied,  return ENAMETOOLONG,
        !           134:  *     indicating an incomplete copy.
        !           135:  *   - otherwise, return 0, indicating success.
        !           136:  * the number of bytes copied is always returned in lencopied.
        !           137:  */
        !           138: int
        !           139: copyinstr(from, to, maxlen, lencopied)
        !           140: caddr_t from, to;
        !           141: unsigned maxlen, *lencopied;
        !           142: {
        !           143:        unsigned segroom, room = maxlen;
        !           144:        caddr_t oto = to;
        !           145:        caddr_t mapped_from;
        !           146:        unsigned l;
        !           147:        int error = 0;
        !           148:        label_t jmpbuf;
        !           149:        vm_offset_t tmpbuf = current_thread()->recover;
        !           150: 
        !           151: #if DIAGNOSTIC
        !           152:        if(tmpbuf)
        !           153:                kprintf("copyinstr() ****** NESTED SETJUMP ******\n");
        !           154: #endif /* DIAGNOSTIC */
        !           155: 
        !           156:        if (setjmp(&jmpbuf)) {
        !           157:                error = EFAULT;
        !           158:        } else {
        !           159:                current_thread()->recover = (vm_offset_t)&jmpbuf;
        !           160:                do {
        !           161:                        /* calc # of bytes to transfer from this seg. */
        !           162:                        segroom = MIN(room, NBSEG - SEGOFFSET(from));
        !           163: 
        !           164:                        mapped_from = cioseg(current_task()->map->pmap->space,from);
        !           165:                        /* this *does not* copy a terminating null */
        !           166:                        l = lbcopytoz(mapped_from, to, segroom);
        !           167: 
        !           168:                        room -= l;
        !           169:                        from += l;
        !           170:                        to   += l;
        !           171:                } while (l == segroom && room > 0);
        !           172:        }
        !           173: 
        !           174:        if (room == 0)
        !           175:                error = ENAMETOOLONG;
        !           176: 
        !           177:        if (error == 0)
        !           178:                *to++ = '\0';   // NULL terminate
        !           179: 
        !           180:        current_thread()->recover = (vm_offset_t)tmpbuf;
        !           181: 
        !           182:        if (lencopied)
        !           183:                *lencopied = to - oto;
        !           184: 
        !           185:        return error;
        !           186: }
        !           187: 
        !           188: /*
        !           189:  * Copy count bytes from (src) to (dst)
        !           190:  */
        !           191: int
        !           192: copywithin(src, dst, count)
        !           193: caddr_t src,dst;
        !           194: unsigned count;
        !           195: {
        !           196:        int error = 0;
        !           197:        label_t jmpbuf;
        !           198:        vm_offset_t tmpbuf = current_thread()->recover;
        !           199: 
        !           200:        if (setjmp(&jmpbuf)) {
        !           201:                error = EFAULT;
        !           202:        }
        !           203:        else {
        !           204:                current_thread()->recover = (vm_offset_t)&jmpbuf;
        !           205:                bcopy(src,dst,count);
        !           206:        }
        !           207: 
        !           208:        current_thread()->recover = (vm_offset_t)tmpbuf;
        !           209:        return (error);
        !           210: }
        !           211: 
        !           212: caddr_t view_user_address(caddr_t addr);
        !           213: int kdp_map_segment(unsigned int segment);
        !           214: 
        !           215: /*
        !           216:  * Copy count bytes from (src) to (dst) where one is user space
        !           217:  */
        !           218: int
        !           219: copy_for_kdp_user(src, dst, count, dir)
        !           220: caddr_t src,dst;
        !           221: unsigned count;
        !           222: int dir;
        !           223: {
        !           224:     caddr_t    msrc, mdst, ptr;
        !           225:     unsigned mcount;
        !           226:     int seg;
        !           227:     int rtn_value;
        !           228: 
        !           229: #define SEG_NUM(x)     ((((unsigned int)(x))>>28)&0xF)
        !           230: #define SEG_ADDR(x, y) ((((unsigned int)(x)) << 28) | (((unsigned int)(y)) & 0x0FFFFFFF))
        !           231: 
        !           232:     rtn_value = 0;
        !           233:     while (count > 0) {
        !           234:        if (dir) {
        !           235:            ptr = dst;
        !           236:            seg = kdp_map_segment(SEG_NUM(ptr));
        !           237:            if (seg < 0) {
        !           238:                return 1;
        !           239:            }
        !           240:            mdst = view_user_address(SEG_ADDR(seg, ptr));
        !           241:            msrc = src;
        !           242:        } else {
        !           243:            ptr = src;
        !           244:            mdst = dst;
        !           245:            seg = kdp_map_segment(SEG_NUM(ptr));
        !           246:            if (seg < 0) {
        !           247:                return 1;
        !           248:            }
        !           249:            msrc = view_user_address(SEG_ADDR(seg, ptr));
        !           250:        }
        !           251:        if (SEG_NUM(ptr) != SEG_NUM(ptr+count-1)) {
        !           252:            mcount = 0x10000000 - SEG_ADDR(0, ptr);
        !           253:            count -= mcount;
        !           254:            src += mcount;
        !           255:            dst += mcount;
        !           256:        } else {
        !           257:            mcount = count;
        !           258:            count = 0;
        !           259:        }
        !           260:        rtn_value |= safe_bcopy(msrc,mdst,mcount);
        !           261:     }
        !           262:     return rtn_value;
        !           263: }
        !           264: 
        !           265: /*
        !           266:  * Copy count bytes from (src) to (dst)
        !           267:  */
        !           268: int
        !           269: copy_for_kdp(src, dst, count, dir)
        !           270: vm_offset_t src,dst;
        !           271: unsigned count;
        !           272: int dir;
        !           273: {
        !           274:        int rtn_value = 0;
        !           275:  
        !           276:        if (dir) {
        !           277:                if (dst > VM_MAX_KERNEL_ADDRESS) {
        !           278:                        rtn_value = copy_for_kdp_user(src, dst, count, 1);
        !           279:                } else if (dst >= VM_MIN_KERNEL_ADDRESS) {
        !           280:                        rtn_value = safe_bcopy(src, dst, count);
        !           281:                        kdp_flush_icache(dst, count);
        !           282:                }
        !           283:        } else {
        !           284:                if (src > VM_MAX_KERNEL_ADDRESS) {
        !           285:                        rtn_value = copy_for_kdp_user(src, dst, count, 0);
        !           286:                } else {
        !           287:                        rtn_value = safe_bcopy(src, dst, count);
        !           288:                }
        !           289:        }
        !           290:        return rtn_value;
        !           291: }
        !           292: 
        !           293: /* 
        !           294:  * copy a null terminated string from one point to another in 
        !           295:  * the kernel address space.
        !           296:  *   - no access checks are performed.
        !           297:  *   - if the end of string isn't found before
        !           298:  *     maxlen bytes are copied,  return ENAMETOOLONG,
        !           299:  *     indicating an incomplete copy.
        !           300:  *   - otherwise, return 0, indicating success.
        !           301:  * the number of bytes copied is always returned in lencopied.
        !           302:  */
        !           303: int
        !           304: copystr(from, to, maxlen, lencopied)
        !           305:     register caddr_t from, to;
        !           306:     unsigned maxlen, *lencopied;
        !           307: {
        !           308:     register unsigned l;
        !           309:     int error = 0;
        !           310:        label_t jmpbuf;
        !           311:        vm_offset_t tmpbuf = current_thread()->recover;
        !           312: 
        !           313: #if DIAGNOSTIC
        !           314:        if(tmpbuf)
        !           315:                kprintf("copystr() ****** NESTED SETJUMP ******\n");
        !           316: #endif /* DIAGNOSTIC */
        !           317: 
        !           318:        if (setjmp(&jmpbuf)) {
        !           319:                error = EFAULT;
        !           320:        } else {
        !           321:                current_thread()->recover = (vm_offset_t)&jmpbuf;
        !           322:                for (l = 0; l < maxlen; l++)
        !           323:                        if ((*to++ = *from++) == '\0') {
        !           324:                                if (lencopied)
        !           325:                                        *lencopied = l + 1;
        !           326:                                error = 0;
        !           327:                                goto out;
        !           328:                        }
        !           329:                if (lencopied)
        !           330:                        *lencopied = maxlen;
        !           331:                error = ENAMETOOLONG;
        !           332:        }
        !           333: out:
        !           334:        current_thread()->recover = (vm_offset_t)tmpbuf;
        !           335:        return (error);
        !           336: }
        !           337: 
        !           338: /* 
        !           339:  * copy a null terminated string from the kernel address space into
        !           340:  * the user address space.
        !           341:  *   - if the user is denied write access, return EFAULT.
        !           342:  *   - if the end of string isn't found before
        !           343:  *     maxlen bytes are copied,  return ENAMETOOLONG,
        !           344:  *     indicating an incomplete copy.
        !           345:  *   - otherwise, return 0, indicating success.
        !           346:  * the number of bytes copied is always returned in lencopied.
        !           347:  */
        !           348: int
        !           349: copyoutstr(from, to, maxlen, lencopied)
        !           350:     caddr_t from, to;
        !           351:     unsigned maxlen, *lencopied;
        !           352: {
        !           353:        unsigned segroom, room = maxlen;
        !           354:        caddr_t oto = to;
        !           355:        caddr_t mapped_to;
        !           356:        unsigned l;
        !           357:        int error = 0;
        !           358:        label_t jmpbuf;
        !           359:        vm_offset_t tmpbuf = current_thread()->recover;
        !           360: 
        !           361: #if DIAGNOSTIC
        !           362:        if(tmpbuf)
        !           363:                kprintf("copyoutstr() ****** NESTED SETJUMP ******\n");
        !           364: #endif /* DIAGNOSTIC */
        !           365: 
        !           366:        if (setjmp(&jmpbuf)) {
        !           367:                error = EFAULT;
        !           368:        } else {
        !           369:                current_thread()->recover = (vm_offset_t)&jmpbuf;
        !           370:                do {
        !           371:                        /* calc # of bytes to transfer from this seg. */
        !           372:                        segroom = MIN(room, NBSEG - SEGOFFSET(to));
        !           373: 
        !           374:                        mapped_to = cioseg(current_task()->map->pmap->space,to);
        !           375: 
        !           376:                        /* this *does not* copy a terminating null */
        !           377:                        l = lbcopytoz(from, mapped_to, segroom);
        !           378: 
        !           379:                        room -= l;
        !           380:                        from += l;
        !           381:                        to   += l;
        !           382:                        mapped_to += l;  // for NULL whenever
        !           383:                } while (l == segroom && room > 0);
        !           384: 
        !           385:                /* set terminating NULL */
        !           386:                *mapped_to = '\0';
        !           387:                to++;
        !           388:        }
        !           389: 
        !           390:        if (room == 0)
        !           391:                error = ENAMETOOLONG;
        !           392: 
        !           393:        if (lencopied)
        !           394:                *lencopied = to - oto;
        !           395: 
        !           396:        current_thread()->recover = (vm_offset_t)tmpbuf;
        !           397:        return error;
        !           398: }
        !           399: 
        !           400: #undef PGOFFSET
        !           401: 
        !           402: int
        !           403: copyin(void *src, void *dst, size_t len)
        !           404: {
        !           405:        thread_t        self = current_thread();
        !           406:        vm_offset_t     tmpbuf = self->recover;
        !           407:        label_t         jmpbuf;
        !           408:        int             error = 0;
        !           409:        void            *tsrc;
        !           410:        size_t          tlen;
        !           411: 
        !           412: #if DIAGNOSTIC
        !           413:        if(tmpbuf)
        !           414:                kprintf("copyin() ****** NESTED SETJUMP ******\n");
        !           415: #endif /* DIAGNOSTIC */
        !           416: 
        !           417:        if (setjmp(&jmpbuf)) {
        !           418:                error = EFAULT;
        !           419:        }
        !           420:        else {
        !           421:                self->recover = (vm_offset_t)&jmpbuf;
        !           422:                while (len > 0) {
        !           423:                        tlen = ((SEGOFFSET(src) + len) > NBSEG) ?
        !           424:                                        NBSEG - SEGOFFSET(src) : len;
        !           425:                        tsrc = cioseg(self->task->map->pmap->space, src);
        !           426:                        bcopy(tsrc, dst, tlen);
        !           427:                        src += tlen;
        !           428:                        dst += tlen;
        !           429:                        len -= tlen;
        !           430:                }
        !           431:        }
        !           432:        self->recover = (vm_offset_t)tmpbuf;
        !           433:        return(error);
        !           434: }
        !           435: 
        !           436: int
        !           437: copyout(void *src, void *dst, size_t len)
        !           438: {
        !           439:        thread_t        self = current_thread();
        !           440:        vm_offset_t     tmpbuf = self->recover;
        !           441:        label_t         jmpbuf;
        !           442:        int             error = 0;
        !           443:        void            *tdst;
        !           444:        size_t          tlen;
        !           445: 
        !           446: #if DIAGNOSTIC
        !           447:        if(tmpbuf)
        !           448:                kprintf("copyout() ****** NESTED SETJUMP ******\n");
        !           449: #endif /* DIAGNOSTIC */
        !           450: 
        !           451:        if (setjmp(&jmpbuf)) {
        !           452:                error = EFAULT;
        !           453:        }
        !           454:        else {
        !           455:                self->recover = (vm_offset_t)&jmpbuf;
        !           456:                while (len > 0) {
        !           457:                        tlen = ((SEGOFFSET(dst) + len) > NBSEG) ?
        !           458:                                        NBSEG - SEGOFFSET(dst) : len;
        !           459:                        tdst = cioseg(self->task->map->pmap->space, dst);
        !           460:                        bcopy(src, tdst, tlen);
        !           461:                        src += tlen;
        !           462:                        dst += tlen;
        !           463:                        len -= tlen;
        !           464:                }
        !           465:        }
        !           466:        self->recover = (vm_offset_t)tmpbuf;
        !           467:        return(error);
        !           468: }
        !           469: 
        !           470: int
        !           471: copyinmsg(caddr_t src, caddr_t dst, int len)
        !           472: {
        !           473:        return(copyin(src,dst,len));
        !           474: }
        !           475: 
        !           476: int
        !           477: copyoutmsg(caddr_t src, caddr_t dst, int len)
        !           478: {
        !           479:        return(copyout(src, dst, len));
        !           480: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.