Annotation of kernel/machdep/ppc/fault_copy.c, revision 1.1.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.