[BACK]Return to uvm_mmap.c CVS log [TXT][DIR] Up to [local] / sys / uvm

Annotation of sys/uvm/uvm_mmap.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: uvm_mmap.c,v 1.69 2007/06/18 21:51:15 pedro Exp $     */
                      2: /*     $NetBSD: uvm_mmap.c,v 1.49 2001/02/18 21:19:08 chs Exp $        */
                      3:
                      4: /*
                      5:  * Copyright (c) 1997 Charles D. Cranor and Washington University.
                      6:  * Copyright (c) 1991, 1993 The Regents of the University of California.
                      7:  * Copyright (c) 1988 University of Utah.
                      8:  *
                      9:  * All rights reserved.
                     10:  *
                     11:  * This code is derived from software contributed to Berkeley by
                     12:  * the Systems Programming Group of the University of Utah Computer
                     13:  * Science Department.
                     14:  *
                     15:  * Redistribution and use in source and binary forms, with or without
                     16:  * modification, are permitted provided that the following conditions
                     17:  * are met:
                     18:  * 1. Redistributions of source code must retain the above copyright
                     19:  *    notice, this list of conditions and the following disclaimer.
                     20:  * 2. Redistributions in binary form must reproduce the above copyright
                     21:  *    notice, this list of conditions and the following disclaimer in the
                     22:  *    documentation and/or other materials provided with the distribution.
                     23:  * 3. All advertising materials mentioning features or use of this software
                     24:  *    must display the following acknowledgement:
                     25:  *      This product includes software developed by the Charles D. Cranor,
                     26:  *     Washington University, University of California, Berkeley and
                     27:  *     its contributors.
                     28:  * 4. Neither the name of the University nor the names of its contributors
                     29:  *    may be used to endorse or promote products derived from this software
                     30:  *    without specific prior written permission.
                     31:  *
                     32:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     33:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     34:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     35:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     36:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     37:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     38:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     39:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     40:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     41:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     42:  * SUCH DAMAGE.
                     43:  *
                     44:  * from: Utah $Hdr: vm_mmap.c 1.6 91/10/21$
                     45:  *      @(#)vm_mmap.c   8.5 (Berkeley) 5/19/94
                     46:  * from: Id: uvm_mmap.c,v 1.1.2.14 1998/01/05 21:04:26 chuck Exp
                     47:  */
                     48:
                     49: /*
                     50:  * uvm_mmap.c: system call interface into VM system, plus kernel vm_mmap
                     51:  * function.
                     52:  */
                     53: #include <sys/param.h>
                     54: #include <sys/systm.h>
                     55: #include <sys/file.h>
                     56: #include <sys/filedesc.h>
                     57: #include <sys/resourcevar.h>
                     58: #include <sys/mman.h>
                     59: #include <sys/mount.h>
                     60: #include <sys/proc.h>
                     61: #include <sys/malloc.h>
                     62: #include <sys/vnode.h>
                     63: #include <sys/conf.h>
                     64: #include <sys/stat.h>
                     65:
                     66: #include <machine/exec.h>      /* for __LDPGSZ */
                     67:
                     68: #include <miscfs/specfs/specdev.h>
                     69:
                     70: #include <sys/syscallargs.h>
                     71:
                     72: #include <uvm/uvm.h>
                     73: #include <uvm/uvm_device.h>
                     74: #include <uvm/uvm_vnode.h>
                     75:
                     76: /*
                     77:  * Page align addr and size, returning EINVAL on wraparound.
                     78:  */
                     79: #define ALIGN_ADDR(addr, size, pageoff)        do {                            \
                     80:        pageoff = (addr & PAGE_MASK);                                   \
                     81:        if (pageoff != 0) {                                             \
                     82:                if (size > SIZE_MAX - pageoff)                          \
                     83:                        return (EINVAL);        /* wraparound */        \
                     84:                addr -= pageoff;                                        \
                     85:                size += pageoff;                                        \
                     86:        }                                                               \
                     87:        if (size != 0) {                                                \
                     88:                size = (vsize_t)round_page(size);                       \
                     89:                if (size == 0)                                          \
                     90:                        return (EINVAL);        /* wraparound */        \
                     91:        }                                                               \
                     92: } while (0)
                     93:
                     94: /*
                     95:  * unimplemented VM system calls:
                     96:  */
                     97:
                     98: /*
                     99:  * sys_sbrk: sbrk system call.
                    100:  */
                    101:
                    102: /* ARGSUSED */
                    103: int
                    104: sys_sbrk(p, v, retval)
                    105:        struct proc *p;
                    106:        void *v;
                    107:        register_t *retval;
                    108: {
                    109: #if 0
                    110:        struct sys_sbrk_args /* {
                    111:                syscallarg(int) incr;
                    112:        } */ *uap = v;
                    113: #endif
                    114:
                    115:        return (ENOSYS);
                    116: }
                    117:
                    118: /*
                    119:  * sys_sstk: sstk system call.
                    120:  */
                    121:
                    122: /* ARGSUSED */
                    123: int
                    124: sys_sstk(p, v, retval)
                    125:        struct proc *p;
                    126:        void *v;
                    127:        register_t *retval;
                    128: {
                    129: #if 0
                    130:        struct sys_sstk_args /* {
                    131:                syscallarg(int) incr;
                    132:        } */ *uap = v;
                    133: #endif
                    134:
                    135:        return (ENOSYS);
                    136: }
                    137:
                    138: /*
                    139:  * sys_mquery: provide mapping hints to applications that do fixed mappings
                    140:  *
                    141:  * flags: 0 or MAP_FIXED (MAP_FIXED - means that we insist on this addr and
                    142:  *     don't care about PMAP_PREFER or such)
                    143:  * addr: hint where we'd like to place the mapping.
                    144:  * size: size of the mapping
                    145:  * fd: fd of the file we want to map
                    146:  * off: offset within the file
                    147:  */
                    148:
                    149: int
                    150: sys_mquery(p, v, retval)
                    151:        struct proc *p;
                    152:        void *v;
                    153:        register_t *retval;
                    154: {
                    155:        struct sys_mquery_args /* {
                    156:                syscallarg(void *) addr;
                    157:                syscallarg(size_t) len;
                    158:                syscallarg(int) prot;
                    159:                syscallarg(int) flags;
                    160:                syscallarg(int) fd;
                    161:                syscallarg(long) pad;
                    162:                syscallarg(off_t) pos;
                    163:        } */ *uap = v;
                    164:        struct file *fp;
                    165:        struct uvm_object *uobj;
                    166:        voff_t uoff;
                    167:        int error;
                    168:        vaddr_t vaddr;
                    169:        int flags = 0;
                    170:        vsize_t size;
                    171:        vm_prot_t prot;
                    172:        int fd;
                    173:
                    174:        vaddr = (vaddr_t) SCARG(uap, addr);
                    175:        prot = SCARG(uap, prot);
                    176:        size = (vsize_t) SCARG(uap, len);
                    177:        fd = SCARG(uap, fd);
                    178:
                    179:        if ((prot & VM_PROT_ALL) != prot)
                    180:                return (EINVAL);
                    181:
                    182:        if (SCARG(uap, flags) & MAP_FIXED)
                    183:                flags |= UVM_FLAG_FIXED;
                    184:
                    185:        if (fd >= 0) {
                    186:                if ((error = getvnode(p->p_fd, fd, &fp)) != 0)
                    187:                        return (error);
                    188:                uobj = &((struct vnode *)fp->f_data)->v_uvm.u_obj;
                    189:                uoff = SCARG(uap, pos);
                    190:        } else {
                    191:                fp = NULL;
                    192:                uobj = NULL;
                    193:                uoff = 0;
                    194:        }
                    195:
                    196:        if (vaddr == 0)
                    197:                vaddr = uvm_map_hint(p, prot);
                    198:
                    199:        /* prevent a user requested address from falling in heap space */
                    200:        if ((vaddr + size > (vaddr_t)p->p_vmspace->vm_daddr) &&
                    201:            (vaddr < (vaddr_t)p->p_vmspace->vm_daddr + MAXDSIZ)) {
                    202:                if (flags & UVM_FLAG_FIXED) {
                    203:                        error = EINVAL;
                    204:                        goto done;
                    205:                }
                    206:                vaddr = round_page((vaddr_t)p->p_vmspace->vm_daddr + MAXDSIZ);
                    207:        }
                    208: again:
                    209:
                    210:        if (uvm_map_findspace(&p->p_vmspace->vm_map, vaddr, size,
                    211:            &vaddr, uobj, uoff, 0, flags) == NULL) {
                    212:                if (flags & UVM_FLAG_FIXED)
                    213:                        error = EINVAL;
                    214:                else
                    215:                        error = ENOMEM;
                    216:        } else {
                    217:                /* prevent a returned address from falling in heap space */
                    218:                if ((vaddr + size > (vaddr_t)p->p_vmspace->vm_daddr)
                    219:                    && (vaddr < (vaddr_t)p->p_vmspace->vm_daddr + MAXDSIZ)) {
                    220:                        vaddr = round_page((vaddr_t)p->p_vmspace->vm_daddr +
                    221:                            MAXDSIZ);
                    222:                        goto again;
                    223:                }
                    224:                error = 0;
                    225:                *retval = (register_t)(vaddr);
                    226:        }
                    227: done:
                    228:        if (fp != NULL)
                    229:                FRELE(fp);
                    230:        return (error);
                    231: }
                    232:
                    233: /*
                    234:  * sys_mincore: determine if pages are in core or not.
                    235:  */
                    236:
                    237: /* ARGSUSED */
                    238: int
                    239: sys_mincore(p, v, retval)
                    240:        struct proc *p;
                    241:        void *v;
                    242:        register_t *retval;
                    243: {
                    244:        struct sys_mincore_args /* {
                    245:                syscallarg(void *) addr;
                    246:                syscallarg(size_t) len;
                    247:                syscallarg(char *) vec;
                    248:        } */ *uap = v;
                    249:        vm_page_t m;
                    250:        char *vec, pgi;
                    251:        struct uvm_object *uobj;
                    252:        struct vm_amap *amap;
                    253:        struct vm_anon *anon;
                    254:        vm_map_entry_t entry;
                    255:        vaddr_t start, end, lim;
                    256:        vm_map_t map;
                    257:        vsize_t len, npgs;
                    258:        int error = 0;
                    259:
                    260:        map = &p->p_vmspace->vm_map;
                    261:
                    262:        start = (vaddr_t)SCARG(uap, addr);
                    263:        len = SCARG(uap, len);
                    264:        vec = SCARG(uap, vec);
                    265:
                    266:        if (start & PAGE_MASK)
                    267:                return (EINVAL);
                    268:        len = round_page(len);
                    269:        end = start + len;
                    270:        if (end <= start)
                    271:                return (EINVAL);
                    272:
                    273:        npgs = len >> PAGE_SHIFT;
                    274:
                    275:        /*
                    276:         * Lock down vec, so our returned status isn't outdated by
                    277:         * storing the status byte for a page.
                    278:         */
                    279:        if ((error = uvm_vslock(p, vec, npgs, VM_PROT_WRITE)) != 0)
                    280:                return (error);
                    281:
                    282:        vm_map_lock_read(map);
                    283:
                    284:        if (uvm_map_lookup_entry(map, start, &entry) == FALSE) {
                    285:                error = ENOMEM;
                    286:                goto out;
                    287:        }
                    288:
                    289:        for (/* nothing */;
                    290:             entry != &map->header && entry->start < end;
                    291:             entry = entry->next) {
                    292:                KASSERT(!UVM_ET_ISSUBMAP(entry));
                    293:                KASSERT(start >= entry->start);
                    294:
                    295:                /* Make sure there are no holes. */
                    296:                if (entry->end < end &&
                    297:                     (entry->next == &map->header ||
                    298:                      entry->next->start > entry->end)) {
                    299:                        error = ENOMEM;
                    300:                        goto out;
                    301:                }
                    302:
                    303:                lim = end < entry->end ? end : entry->end;
                    304:
                    305:                /*
                    306:                 * Special case for objects with no "real" pages.  Those
                    307:                 * are always considered resident (mapped devices).
                    308:                 */
                    309:                if (UVM_ET_ISOBJ(entry)) {
                    310:                        KASSERT(!UVM_OBJ_IS_KERN_OBJECT(entry->object.uvm_obj));
                    311:                        if (entry->object.uvm_obj->pgops->pgo_releasepg
                    312:                            == NULL) {
                    313:                                pgi = 1;
                    314:                                for (/* nothing */; start < lim;
                    315:                                     start += PAGE_SIZE, vec++)
                    316:                                        copyout(&pgi, vec, sizeof(char));
                    317:                                continue;
                    318:                        }
                    319:                }
                    320:
                    321:                amap = entry->aref.ar_amap;     /* top layer */
                    322:                uobj = entry->object.uvm_obj;   /* bottom layer */
                    323:
                    324:                if (uobj != NULL)
                    325:                        simple_lock(&uobj->vmobjlock);
                    326:
                    327:                for (/* nothing */; start < lim; start += PAGE_SIZE, vec++) {
                    328:                        pgi = 0;
                    329:                        if (amap != NULL) {
                    330:                                /* Check the top layer first. */
                    331:                                anon = amap_lookup(&entry->aref,
                    332:                                    start - entry->start);
                    333:                                /* Don't need to lock anon here. */
                    334:                                if (anon != NULL && anon->an_page != NULL) {
                    335:                                        /*
                    336:                                         * Anon has the page for this entry
                    337:                                         * offset.
                    338:                                         */
                    339:                                        pgi = 1;
                    340:                                }
                    341:                        }
                    342:
                    343:                        if (uobj != NULL && pgi == 0) {
                    344:                                /* Check the bottom layer. */
                    345:                                m = uvm_pagelookup(uobj,
                    346:                                    entry->offset + (start - entry->start));
                    347:                                if (m != NULL) {
                    348:                                        /*
                    349:                                         * Object has the page for this entry
                    350:                                         * offset.
                    351:                                         */
                    352:                                        pgi = 1;
                    353:                                }
                    354:                        }
                    355:
                    356:                        copyout(&pgi, vec, sizeof(char));
                    357:                }
                    358:
                    359:                if (uobj != NULL)
                    360:                        simple_unlock(&uobj->vmobjlock);
                    361:        }
                    362:
                    363:  out:
                    364:        vm_map_unlock_read(map);
                    365:        uvm_vsunlock(p, SCARG(uap, vec), npgs);
                    366:        return (error);
                    367: }
                    368:
                    369: /*
                    370:  * sys_mmap: mmap system call.
                    371:  *
                    372:  * => file offset and address may not be page aligned
                    373:  *    - if MAP_FIXED, offset and address must have remainder mod PAGE_SIZE
                    374:  *    - if address isn't page aligned the mapping starts at trunc_page(addr)
                    375:  *      and the return value is adjusted up by the page offset.
                    376:  */
                    377:
                    378: int
                    379: sys_mmap(p, v, retval)
                    380:        struct proc *p;
                    381:        void *v;
                    382:        register_t *retval;
                    383: {
                    384:        struct sys_mmap_args /* {
                    385:                syscallarg(void *) addr;
                    386:                syscallarg(size_t) len;
                    387:                syscallarg(int) prot;
                    388:                syscallarg(int) flags;
                    389:                syscallarg(int) fd;
                    390:                syscallarg(long) pad;
                    391:                syscallarg(off_t) pos;
                    392:        } */ *uap = v;
                    393:        vaddr_t addr;
                    394:        struct vattr va;
                    395:        off_t pos;
                    396:        vsize_t size, pageoff;
                    397:        vm_prot_t prot, maxprot;
                    398:        int flags, fd;
                    399:        vaddr_t vm_min_address = VM_MIN_ADDRESS;
                    400:        struct filedesc *fdp = p->p_fd;
                    401:        struct file *fp = NULL;
                    402:        struct vnode *vp;
                    403:        caddr_t handle;
                    404:        int error;
                    405:
                    406:        /*
                    407:         * first, extract syscall args from the uap.
                    408:         */
                    409:
                    410:        addr = (vaddr_t) SCARG(uap, addr);
                    411:        size = (vsize_t) SCARG(uap, len);
                    412:        prot = SCARG(uap, prot);
                    413:        flags = SCARG(uap, flags);
                    414:        fd = SCARG(uap, fd);
                    415:        pos = SCARG(uap, pos);
                    416:
                    417:        /*
                    418:         * Fixup the old deprecated MAP_COPY into MAP_PRIVATE, and
                    419:         * validate the flags.
                    420:         */
                    421:        if ((prot & VM_PROT_ALL) != prot)
                    422:                return (EINVAL);
                    423:        if ((flags & MAP_FLAGMASK) != flags)
                    424:                return (EINVAL);
                    425:        if (flags & MAP_COPY)
                    426:                flags = (flags & ~MAP_COPY) | MAP_PRIVATE;
                    427:        if ((flags & (MAP_SHARED|MAP_PRIVATE)) == (MAP_SHARED|MAP_PRIVATE))
                    428:                return (EINVAL);
                    429:
                    430:        /*
                    431:         * align file position and save offset.  adjust size.
                    432:         */
                    433:        ALIGN_ADDR(pos, size, pageoff);
                    434:
                    435:        /*
                    436:         * now check (MAP_FIXED) or get (!MAP_FIXED) the "addr"
                    437:         */
                    438:
                    439:        if (flags & MAP_FIXED) {
                    440:
                    441:                /* adjust address by the same amount as we did the offset */
                    442:                addr -= pageoff;
                    443:                if (addr & PAGE_MASK)
                    444:                        return (EINVAL);                /* not page aligned */
                    445:
                    446:                if (addr > SIZE_MAX - size)
                    447:                        return (EINVAL);                /* no wrapping! */
                    448:                if (VM_MAXUSER_ADDRESS > 0 &&
                    449:                    (addr + size) > VM_MAXUSER_ADDRESS)
                    450:                        return (EINVAL);
                    451:                if (vm_min_address > 0 && addr < vm_min_address)
                    452:                        return (EINVAL);
                    453:
                    454:        } else {
                    455:
                    456:                /*
                    457:                 * not fixed: make sure we skip over the largest possible heap.
                    458:                 * we will refine our guess later (e.g. to account for VAC, etc)
                    459:                 */
                    460:                if (addr == 0)
                    461:                        addr = uvm_map_hint(p, prot);
                    462:                else if (!(flags & MAP_TRYFIXED) &&
                    463:                    addr < (vaddr_t)p->p_vmspace->vm_daddr)
                    464:                        addr = uvm_map_hint(p, prot);
                    465:        }
                    466:
                    467:        /*
                    468:         * check for file mappings (i.e. not anonymous) and verify file.
                    469:         */
                    470:        if ((flags & MAP_ANON) == 0) {
                    471:
                    472:                if ((fp = fd_getfile(fdp, fd)) == NULL)
                    473:                        return (EBADF);
                    474:
                    475:                FREF(fp);
                    476:
                    477:                if (fp->f_type != DTYPE_VNODE) {
                    478:                        error = ENODEV;         /* only mmap vnodes! */
                    479:                        goto out;
                    480:                }
                    481:                vp = (struct vnode *)fp->f_data;        /* convert to vnode */
                    482:
                    483:                if (vp->v_type != VREG && vp->v_type != VCHR &&
                    484:                    vp->v_type != VBLK) {
                    485:                        error = ENODEV; /* only REG/CHR/BLK support mmap */
                    486:                        goto out;
                    487:                }
                    488:
                    489:                if (vp->v_type == VREG && (pos + size) < pos) {
                    490:                        error = EINVAL;         /* no offset wrapping */
                    491:                        goto out;
                    492:                }
                    493:
                    494:                /* special case: catch SunOS style /dev/zero */
                    495:                if (vp->v_type == VCHR && iszerodev(vp->v_rdev)) {
                    496:                        flags |= MAP_ANON;
                    497:                        FRELE(fp);
                    498:                        fp = NULL;
                    499:                        goto is_anon;
                    500:                }
                    501:
                    502:                /*
                    503:                 * Old programs may not select a specific sharing type, so
                    504:                 * default to an appropriate one.
                    505:                 *
                    506:                 * XXX: how does MAP_ANON fit in the picture?
                    507:                 */
                    508:                if ((flags & (MAP_SHARED|MAP_PRIVATE)) == 0) {
                    509: #if defined(DEBUG)
                    510:                        printf("WARNING: defaulted mmap() share type to "
                    511:                           "%s (pid %d comm %s)\n", vp->v_type == VCHR ?
                    512:                           "MAP_SHARED" : "MAP_PRIVATE", p->p_pid,
                    513:                            p->p_comm);
                    514: #endif
                    515:                        if (vp->v_type == VCHR)
                    516:                                flags |= MAP_SHARED;    /* for a device */
                    517:                        else
                    518:                                flags |= MAP_PRIVATE;   /* for a file */
                    519:                }
                    520:
                    521:                /*
                    522:                 * MAP_PRIVATE device mappings don't make sense (and aren't
                    523:                 * supported anyway).  However, some programs rely on this,
                    524:                 * so just change it to MAP_SHARED.
                    525:                 */
                    526:                if (vp->v_type == VCHR && (flags & MAP_PRIVATE) != 0) {
                    527:                        flags = (flags & ~MAP_PRIVATE) | MAP_SHARED;
                    528:                }
                    529:
                    530:                /*
                    531:                 * now check protection
                    532:                 */
                    533:
                    534:                maxprot = VM_PROT_EXECUTE;
                    535:
                    536:                /* check read access */
                    537:                if (fp->f_flag & FREAD)
                    538:                        maxprot |= VM_PROT_READ;
                    539:                else if (prot & PROT_READ) {
                    540:                        error = EACCES;
                    541:                        goto out;
                    542:                }
                    543:
                    544:                /* check write access, shared case first */
                    545:                if (flags & MAP_SHARED) {
                    546:                        /*
                    547:                         * if the file is writable, only add PROT_WRITE to
                    548:                         * maxprot if the file is not immutable, append-only.
                    549:                         * otherwise, if we have asked for PROT_WRITE, return
                    550:                         * EPERM.
                    551:                         */
                    552:                        if (fp->f_flag & FWRITE) {
                    553:                                if ((error =
                    554:                                    VOP_GETATTR(vp, &va, p->p_ucred, p)))
                    555:                                        goto out;
                    556:                                if ((va.va_flags & (IMMUTABLE|APPEND)) == 0)
                    557:                                        maxprot |= VM_PROT_WRITE;
                    558:                                else if (prot & PROT_WRITE) {
                    559:                                        error = EPERM;
                    560:                                        goto out;
                    561:                                }
                    562:                        } else if (prot & PROT_WRITE) {
                    563:                                error = EACCES;
                    564:                                goto out;
                    565:                        }
                    566:                } else {
                    567:                        /* MAP_PRIVATE mappings can always write to */
                    568:                        maxprot |= VM_PROT_WRITE;
                    569:                }
                    570:
                    571:                /*
                    572:                 * set handle to vnode
                    573:                 */
                    574:
                    575:                handle = (caddr_t)vp;
                    576:
                    577:        } else {                /* MAP_ANON case */
                    578:                /*
                    579:                 * XXX What do we do about (MAP_SHARED|MAP_PRIVATE) == 0?
                    580:                 */
                    581:                if (fd != -1) {
                    582:                        error = EINVAL;
                    583:                        goto out;
                    584:                }
                    585:
                    586:  is_anon:              /* label for SunOS style /dev/zero */
                    587:                handle = NULL;
                    588:                maxprot = VM_PROT_ALL;
                    589:                pos = 0;
                    590:        }
                    591:
                    592:        if ((flags & MAP_ANON) != 0 ||
                    593:            ((flags & MAP_PRIVATE) != 0 && (prot & PROT_WRITE) != 0)) {
                    594:                if (size >
                    595:                    (p->p_rlimit[RLIMIT_DATA].rlim_cur - ctob(p->p_vmspace->vm_dused))) {
                    596:                        error = ENOMEM;
                    597:                        goto out;
                    598:                }
                    599:        }
                    600:
                    601:        /*
                    602:         * now let kernel internal function uvm_mmap do the work.
                    603:         */
                    604:
                    605:        error = uvm_mmap(&p->p_vmspace->vm_map, &addr, size, prot, maxprot,
                    606:            flags, handle, pos, p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur, p);
                    607:
                    608:        if (error == 0)
                    609:                /* remember to add offset */
                    610:                *retval = (register_t)(addr + pageoff);
                    611:
                    612: out:
                    613:        if (fp)
                    614:                FRELE(fp);
                    615:        return (error);
                    616: }
                    617:
                    618: /*
                    619:  * sys_msync: the msync system call (a front-end for flush)
                    620:  */
                    621:
                    622: int
                    623: sys_msync(p, v, retval)
                    624:        struct proc *p;
                    625:        void *v;
                    626:        register_t *retval;
                    627: {
                    628:        struct sys_msync_args /* {
                    629:                syscallarg(void *) addr;
                    630:                syscallarg(size_t) len;
                    631:                syscallarg(int) flags;
                    632:        } */ *uap = v;
                    633:        vaddr_t addr;
                    634:        vsize_t size, pageoff;
                    635:        vm_map_t map;
                    636:        int rv, flags, uvmflags;
                    637:
                    638:        /*
                    639:         * extract syscall args from the uap
                    640:         */
                    641:
                    642:        addr = (vaddr_t)SCARG(uap, addr);
                    643:        size = (vsize_t)SCARG(uap, len);
                    644:        flags = SCARG(uap, flags);
                    645:
                    646:        /* sanity check flags */
                    647:        if ((flags & ~(MS_ASYNC | MS_SYNC | MS_INVALIDATE)) != 0 ||
                    648:                        (flags & (MS_ASYNC | MS_SYNC | MS_INVALIDATE)) == 0 ||
                    649:                        (flags & (MS_ASYNC | MS_SYNC)) == (MS_ASYNC | MS_SYNC))
                    650:                return (EINVAL);
                    651:        if ((flags & (MS_ASYNC | MS_SYNC)) == 0)
                    652:                flags |= MS_SYNC;
                    653:
                    654:        /*
                    655:         * align the address to a page boundary, and adjust the size accordingly
                    656:         */
                    657:        ALIGN_ADDR(addr, size, pageoff);
                    658:        if (addr > SIZE_MAX - size)
                    659:                return (EINVAL);                /* disallow wrap-around. */
                    660:
                    661:        /*
                    662:         * get map
                    663:         */
                    664:
                    665:        map = &p->p_vmspace->vm_map;
                    666:
                    667:        /*
                    668:         * XXXCDC: do we really need this semantic?
                    669:         *
                    670:         * XXX Gak!  If size is zero we are supposed to sync "all modified
                    671:         * pages with the region containing addr".  Unfortunately, we
                    672:         * don't really keep track of individual mmaps so we approximate
                    673:         * by flushing the range of the map entry containing addr.
                    674:         * This can be incorrect if the region splits or is coalesced
                    675:         * with a neighbor.
                    676:         */
                    677:        if (size == 0) {
                    678:                vm_map_entry_t entry;
                    679:
                    680:                vm_map_lock_read(map);
                    681:                rv = uvm_map_lookup_entry(map, addr, &entry);
                    682:                if (rv == TRUE) {
                    683:                        addr = entry->start;
                    684:                        size = entry->end - entry->start;
                    685:                }
                    686:                vm_map_unlock_read(map);
                    687:                if (rv == FALSE)
                    688:                        return (EINVAL);
                    689:        }
                    690:
                    691:        /*
                    692:         * translate MS_ flags into PGO_ flags
                    693:         */
                    694:        uvmflags = PGO_CLEANIT;
                    695:        if (flags & MS_INVALIDATE)
                    696:                uvmflags |= PGO_FREE;
                    697:        if (flags & MS_SYNC)
                    698:                uvmflags |= PGO_SYNCIO;
                    699:        else
                    700:                uvmflags |= PGO_SYNCIO;  /* XXXCDC: force sync for now! */
                    701:
                    702:        return (uvm_map_clean(map, addr, addr+size, uvmflags));
                    703: }
                    704:
                    705: /*
                    706:  * sys_munmap: unmap a users memory
                    707:  */
                    708:
                    709: int
                    710: sys_munmap(p, v, retval)
                    711:        struct proc *p;
                    712:        void *v;
                    713:        register_t *retval;
                    714: {
                    715:        struct sys_munmap_args /* {
                    716:                syscallarg(void *) addr;
                    717:                syscallarg(size_t) len;
                    718:        } */ *uap = v;
                    719:        vaddr_t addr;
                    720:        vsize_t size, pageoff;
                    721:        vm_map_t map;
                    722:        vaddr_t vm_min_address = VM_MIN_ADDRESS;
                    723:        struct vm_map_entry *dead_entries;
                    724:
                    725:        /*
                    726:         * get syscall args...
                    727:         */
                    728:
                    729:        addr = (vaddr_t) SCARG(uap, addr);
                    730:        size = (vsize_t) SCARG(uap, len);
                    731:
                    732:        /*
                    733:         * align the address to a page boundary, and adjust the size accordingly
                    734:         */
                    735:        ALIGN_ADDR(addr, size, pageoff);
                    736:
                    737:        /*
                    738:         * Check for illegal addresses.  Watch out for address wrap...
                    739:         * Note that VM_*_ADDRESS are not constants due to casts (argh).
                    740:         */
                    741:        if (addr > SIZE_MAX - size)
                    742:                return (EINVAL);
                    743:        if (VM_MAXUSER_ADDRESS > 0 && addr + size > VM_MAXUSER_ADDRESS)
                    744:                return (EINVAL);
                    745:        if (vm_min_address > 0 && addr < vm_min_address)
                    746:                return (EINVAL);
                    747:        map = &p->p_vmspace->vm_map;
                    748:
                    749:
                    750:        vm_map_lock(map);       /* lock map so we can checkprot */
                    751:
                    752:        /*
                    753:         * interesting system call semantic: make sure entire range is
                    754:         * allocated before allowing an unmap.
                    755:         */
                    756:
                    757:        if (!uvm_map_checkprot(map, addr, addr + size, VM_PROT_NONE)) {
                    758:                vm_map_unlock(map);
                    759:                return (EINVAL);
                    760:        }
                    761:
                    762:        /*
                    763:         * doit!
                    764:         */
                    765:        uvm_unmap_remove(map, addr, addr + size, &dead_entries, p);
                    766:
                    767:        vm_map_unlock(map);     /* and unlock */
                    768:
                    769:        if (dead_entries != NULL)
                    770:                uvm_unmap_detach(dead_entries, 0);
                    771:
                    772:        return (0);
                    773: }
                    774:
                    775: /*
                    776:  * sys_mprotect: the mprotect system call
                    777:  */
                    778:
                    779: int
                    780: sys_mprotect(p, v, retval)
                    781:        struct proc *p;
                    782:        void *v;
                    783:        register_t *retval;
                    784: {
                    785:        struct sys_mprotect_args /* {
                    786:                syscallarg(void *) addr;
                    787:                syscallarg(size_t) len;
                    788:                syscallarg(int) prot;
                    789:        } */ *uap = v;
                    790:        vaddr_t addr;
                    791:        vsize_t size, pageoff;
                    792:        vm_prot_t prot;
                    793:
                    794:        /*
                    795:         * extract syscall args from uap
                    796:         */
                    797:
                    798:        addr = (vaddr_t)SCARG(uap, addr);
                    799:        size = (vsize_t)SCARG(uap, len);
                    800:        prot = SCARG(uap, prot);
                    801:
                    802:        if ((prot & VM_PROT_ALL) != prot)
                    803:                return (EINVAL);
                    804:
                    805:        /*
                    806:         * align the address to a page boundary, and adjust the size accordingly
                    807:         */
                    808:        ALIGN_ADDR(addr, size, pageoff);
                    809:        if (addr > SIZE_MAX - size)
                    810:                return (EINVAL);                /* disallow wrap-around. */
                    811:
                    812:        return (uvm_map_protect(&p->p_vmspace->vm_map, addr, addr+size,
                    813:            prot, FALSE));
                    814: }
                    815:
                    816: /*
                    817:  * sys_minherit: the minherit system call
                    818:  */
                    819:
                    820: int
                    821: sys_minherit(p, v, retval)
                    822:        struct proc *p;
                    823:        void *v;
                    824:        register_t *retval;
                    825: {
                    826:        struct sys_minherit_args /* {
                    827:                syscallarg(void *) addr;
                    828:                syscallarg(size_t) len;
                    829:                syscallarg(int) inherit;
                    830:        } */ *uap = v;
                    831:        vaddr_t addr;
                    832:        vsize_t size, pageoff;
                    833:        vm_inherit_t inherit;
                    834:
                    835:        addr = (vaddr_t)SCARG(uap, addr);
                    836:        size = (vsize_t)SCARG(uap, len);
                    837:        inherit = SCARG(uap, inherit);
                    838:
                    839:        /*
                    840:         * align the address to a page boundary, and adjust the size accordingly
                    841:         */
                    842:        ALIGN_ADDR(addr, size, pageoff);
                    843:        if (addr > SIZE_MAX - size)
                    844:                return (EINVAL);                /* disallow wrap-around. */
                    845:
                    846:        return (uvm_map_inherit(&p->p_vmspace->vm_map, addr, addr+size,
                    847:            inherit));
                    848: }
                    849:
                    850: /*
                    851:  * sys_madvise: give advice about memory usage.
                    852:  */
                    853:
                    854: /* ARGSUSED */
                    855: int
                    856: sys_madvise(p, v, retval)
                    857:        struct proc *p;
                    858:        void *v;
                    859:        register_t *retval;
                    860: {
                    861:        struct sys_madvise_args /* {
                    862:                syscallarg(void *) addr;
                    863:                syscallarg(size_t) len;
                    864:                syscallarg(int) behav;
                    865:        } */ *uap = v;
                    866:        vaddr_t addr;
                    867:        vsize_t size, pageoff;
                    868:        int advice, error;
                    869:
                    870:        addr = (vaddr_t)SCARG(uap, addr);
                    871:        size = (vsize_t)SCARG(uap, len);
                    872:        advice = SCARG(uap, behav);
                    873:
                    874:        /*
                    875:         * align the address to a page boundary, and adjust the size accordingly
                    876:         */
                    877:        ALIGN_ADDR(addr, size, pageoff);
                    878:        if (addr > SIZE_MAX - size)
                    879:                return (EINVAL);                /* disallow wrap-around. */
                    880:
                    881:        switch (advice) {
                    882:        case MADV_NORMAL:
                    883:        case MADV_RANDOM:
                    884:        case MADV_SEQUENTIAL:
                    885:                error = uvm_map_advice(&p->p_vmspace->vm_map, addr,
                    886:                    addr + size, advice);
                    887:                break;
                    888:
                    889:        case MADV_WILLNEED:
                    890:                /*
                    891:                 * Activate all these pages, pre-faulting them in if
                    892:                 * necessary.
                    893:                 */
                    894:                /*
                    895:                 * XXX IMPLEMENT ME.
                    896:                 * Should invent a "weak" mode for uvm_fault()
                    897:                 * which would only do the PGO_LOCKED pgo_get().
                    898:                 */
                    899:                return (0);
                    900:
                    901:        case MADV_DONTNEED:
                    902:                /*
                    903:                 * Deactivate all these pages.  We don't need them
                    904:                 * any more.  We don't, however, toss the data in
                    905:                 * the pages.
                    906:                 */
                    907:                error = uvm_map_clean(&p->p_vmspace->vm_map, addr, addr + size,
                    908:                    PGO_DEACTIVATE);
                    909:                break;
                    910:
                    911:        case MADV_FREE:
                    912:                /*
                    913:                 * These pages contain no valid data, and may be
                    914:                 * garbage-collected.  Toss all resources, including
                    915:                 * any swap space in use.
                    916:                 */
                    917:                error = uvm_map_clean(&p->p_vmspace->vm_map, addr, addr + size,
                    918:                    PGO_FREE);
                    919:                break;
                    920:
                    921:        case MADV_SPACEAVAIL:
                    922:                /*
                    923:                 * XXXMRG What is this?  I think it's:
                    924:                 *
                    925:                 *      Ensure that we have allocated backing-store
                    926:                 *      for these pages.
                    927:                 *
                    928:                 * This is going to require changes to the page daemon,
                    929:                 * as it will free swap space allocated to pages in core.
                    930:                 * There's also what to do for device/file/anonymous memory.
                    931:                 */
                    932:                return (EINVAL);
                    933:
                    934:        default:
                    935:                return (EINVAL);
                    936:        }
                    937:
                    938:        return (error);
                    939: }
                    940:
                    941: /*
                    942:  * sys_mlock: memory lock
                    943:  */
                    944:
                    945: int
                    946: sys_mlock(p, v, retval)
                    947:        struct proc *p;
                    948:        void *v;
                    949:        register_t *retval;
                    950: {
                    951:        struct sys_mlock_args /* {
                    952:                syscallarg(const void *) addr;
                    953:                syscallarg(size_t) len;
                    954:        } */ *uap = v;
                    955:        vaddr_t addr;
                    956:        vsize_t size, pageoff;
                    957:        int error;
                    958:
                    959:        /*
                    960:         * extract syscall args from uap
                    961:         */
                    962:        addr = (vaddr_t)SCARG(uap, addr);
                    963:        size = (vsize_t)SCARG(uap, len);
                    964:
                    965:        /*
                    966:         * align the address to a page boundary and adjust the size accordingly
                    967:         */
                    968:        ALIGN_ADDR(addr, size, pageoff);
                    969:        if (addr > SIZE_MAX - size)
                    970:                return (EINVAL);                /* disallow wrap-around. */
                    971:
                    972:        if (atop(size) + uvmexp.wired > uvmexp.wiredmax)
                    973:                return (EAGAIN);
                    974:
                    975: #ifdef pmap_wired_count
                    976:        if (size + ptoa(pmap_wired_count(vm_map_pmap(&p->p_vmspace->vm_map))) >
                    977:                        p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur)
                    978:                return (EAGAIN);
                    979: #else
                    980:        if ((error = suser(p, 0)) != 0)
                    981:                return (error);
                    982: #endif
                    983:
                    984:        error = uvm_map_pageable(&p->p_vmspace->vm_map, addr, addr+size, FALSE,
                    985:            0);
                    986:        return (error == 0 ? 0 : ENOMEM);
                    987: }
                    988:
                    989: /*
                    990:  * sys_munlock: unlock wired pages
                    991:  */
                    992:
                    993: int
                    994: sys_munlock(p, v, retval)
                    995:        struct proc *p;
                    996:        void *v;
                    997:        register_t *retval;
                    998: {
                    999:        struct sys_munlock_args /* {
                   1000:                syscallarg(const void *) addr;
                   1001:                syscallarg(size_t) len;
                   1002:        } */ *uap = v;
                   1003:        vaddr_t addr;
                   1004:        vsize_t size, pageoff;
                   1005:        int error;
                   1006:
                   1007:        /*
                   1008:         * extract syscall args from uap
                   1009:         */
                   1010:
                   1011:        addr = (vaddr_t)SCARG(uap, addr);
                   1012:        size = (vsize_t)SCARG(uap, len);
                   1013:
                   1014:        /*
                   1015:         * align the address to a page boundary, and adjust the size accordingly
                   1016:         */
                   1017:        ALIGN_ADDR(addr, size, pageoff);
                   1018:        if (addr > SIZE_MAX - size)
                   1019:                return (EINVAL);                /* disallow wrap-around. */
                   1020:
                   1021: #ifndef pmap_wired_count
                   1022:        if ((error = suser(p, 0)) != 0)
                   1023:                return (error);
                   1024: #endif
                   1025:
                   1026:        error = uvm_map_pageable(&p->p_vmspace->vm_map, addr, addr+size, TRUE,
                   1027:            0);
                   1028:        return (error == 0 ? 0 : ENOMEM);
                   1029: }
                   1030:
                   1031: /*
                   1032:  * sys_mlockall: lock all pages mapped into an address space.
                   1033:  */
                   1034:
                   1035: int
                   1036: sys_mlockall(p, v, retval)
                   1037:        struct proc *p;
                   1038:        void *v;
                   1039:        register_t *retval;
                   1040: {
                   1041:        struct sys_mlockall_args /* {
                   1042:                syscallarg(int) flags;
                   1043:        } */ *uap = v;
                   1044:        int error, flags;
                   1045:
                   1046:        flags = SCARG(uap, flags);
                   1047:
                   1048:        if (flags == 0 ||
                   1049:            (flags & ~(MCL_CURRENT|MCL_FUTURE)) != 0)
                   1050:                return (EINVAL);
                   1051:
                   1052: #ifndef pmap_wired_count
                   1053:        if ((error = suser(p, 0)) != 0)
                   1054:                return (error);
                   1055: #endif
                   1056:
                   1057:        error = uvm_map_pageable_all(&p->p_vmspace->vm_map, flags,
                   1058:            p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur);
                   1059:        if (error != 0 && error != ENOMEM)
                   1060:                return (EAGAIN);
                   1061:        return (error);
                   1062: }
                   1063:
                   1064: /*
                   1065:  * sys_munlockall: unlock all pages mapped into an address space.
                   1066:  */
                   1067:
                   1068: int
                   1069: sys_munlockall(p, v, retval)
                   1070:        struct proc *p;
                   1071:        void *v;
                   1072:        register_t *retval;
                   1073: {
                   1074:
                   1075:        (void) uvm_map_pageable_all(&p->p_vmspace->vm_map, 0, 0);
                   1076:        return (0);
                   1077: }
                   1078:
                   1079: /*
                   1080:  * uvm_mmap: internal version of mmap
                   1081:  *
                   1082:  * - used by sys_mmap, exec, and sysv shm
                   1083:  * - handle is a vnode pointer or NULL for MAP_ANON (XXX: not true,
                   1084:  *     sysv shm uses "named anonymous memory")
                   1085:  * - caller must page-align the file offset
                   1086:  */
                   1087:
                   1088: int
                   1089: uvm_mmap(map, addr, size, prot, maxprot, flags, handle, foff, locklimit, p)
                   1090:        vm_map_t map;
                   1091:        vaddr_t *addr;
                   1092:        vsize_t size;
                   1093:        vm_prot_t prot, maxprot;
                   1094:        int flags;
                   1095:        caddr_t handle;         /* XXX: VNODE? */
                   1096:        voff_t foff;
                   1097:        vsize_t locklimit;
                   1098:        struct proc *p;
                   1099: {
                   1100:        struct uvm_object *uobj;
                   1101:        struct vnode *vp;
                   1102:        int error;
                   1103:        int advice = UVM_ADV_NORMAL;
                   1104:        uvm_flag_t uvmflag = 0;
                   1105:        vsize_t align = 0;      /* userland page size */
                   1106:
                   1107:        /*
                   1108:         * check params
                   1109:         */
                   1110:
                   1111:        if (size == 0)
                   1112:                return(0);
                   1113:        if (foff & PAGE_MASK)
                   1114:                return(EINVAL);
                   1115:        if ((prot & maxprot) != prot)
                   1116:                return(EINVAL);
                   1117:
                   1118:        /*
                   1119:         * for non-fixed mappings, round off the suggested address.
                   1120:         * for fixed mappings, check alignment and zap old mappings.
                   1121:         */
                   1122:
                   1123:        if ((flags & MAP_FIXED) == 0) {
                   1124:                *addr = round_page(*addr);      /* round */
                   1125:        } else {
                   1126:                if (*addr & PAGE_MASK)
                   1127:                        return(EINVAL);
                   1128:                uvmflag |= UVM_FLAG_FIXED;
                   1129:                uvm_unmap_p(map, *addr, *addr + size, p);       /* zap! */
                   1130:        }
                   1131:
                   1132:        /*
                   1133:         * handle anon vs. non-anon mappings.   for non-anon mappings attach
                   1134:         * to underlying vm object.
                   1135:         */
                   1136:
                   1137:        if (flags & MAP_ANON) {
                   1138:                if ((flags & MAP_FIXED) == 0 && size >= __LDPGSZ)
                   1139:                        align = __LDPGSZ;
                   1140:                foff = UVM_UNKNOWN_OFFSET;
                   1141:                uobj = NULL;
                   1142:                if ((flags & MAP_SHARED) == 0)
                   1143:                        /* XXX: defer amap create */
                   1144:                        uvmflag |= UVM_FLAG_COPYONW;
                   1145:                else
                   1146:                        /* shared: create amap now */
                   1147:                        uvmflag |= UVM_FLAG_OVERLAY;
                   1148:
                   1149:        } else {
                   1150:
                   1151:                vp = (struct vnode *) handle;   /* get vnode */
                   1152:                if (vp->v_type != VCHR) {
                   1153:                        uobj = uvn_attach((void *) vp, (flags & MAP_SHARED) ?
                   1154:                           maxprot : (maxprot & ~VM_PROT_WRITE));
                   1155:
                   1156: #ifndef UBC
                   1157:                        /*
                   1158:                         * XXXCDC: hack from old code
                   1159:                         * don't allow vnodes which have been mapped
                   1160:                         * shared-writeable to persist [forces them to be
                   1161:                         * flushed out when last reference goes].
                   1162:                         * XXXCDC: interesting side effect: avoids a bug.
                   1163:                         * note that in WRITE [ufs_readwrite.c] that we
                   1164:                         * allocate buffer, uncache, and then do the write.
                   1165:                         * the problem with this is that if the uncache causes
                   1166:                         * VM data to be flushed to the same area of the file
                   1167:                         * we are writing to... in that case we've got the
                   1168:                         * buffer locked and our process goes to sleep forever.
                   1169:                         *
                   1170:                         * XXXCDC: checking maxprot protects us from the
                   1171:                         * "persistbug" program but this is not a long term
                   1172:                         * solution.
                   1173:                         *
                   1174:                         * XXXCDC: we don't bother calling uncache with the vp
                   1175:                         * VOP_LOCKed since we know that we are already
                   1176:                         * holding a valid reference to the uvn (from the
                   1177:                         * uvn_attach above), and thus it is impossible for
                   1178:                         * the uncache to kill the uvn and trigger I/O.
                   1179:                         */
                   1180:                        if (flags & MAP_SHARED) {
                   1181:                                if ((prot & VM_PROT_WRITE) ||
                   1182:                                    (maxprot & VM_PROT_WRITE)) {
                   1183:                                        uvm_vnp_uncache(vp);
                   1184:                                }
                   1185:                        }
                   1186: #else
                   1187:                        /* XXX for now, attach doesn't gain a ref */
                   1188:                        VREF(vp);
                   1189: #endif
                   1190:                } else {
                   1191:                        uobj = udv_attach((void *) &vp->v_rdev,
                   1192:                            (flags & MAP_SHARED) ? maxprot :
                   1193:                            (maxprot & ~VM_PROT_WRITE), foff, size);
                   1194:                        /*
                   1195:                         * XXX Some devices don't like to be mapped with
                   1196:                         * XXX PROT_EXEC, but we don't really have a
                   1197:                         * XXX better way of handling this, right now
                   1198:                         */
                   1199:                        if (uobj == NULL && (prot & PROT_EXEC) == 0) {
                   1200:                                maxprot &= ~VM_PROT_EXECUTE;
                   1201:                                uobj = udv_attach((void *) &vp->v_rdev,
                   1202:                                    (flags & MAP_SHARED) ? maxprot :
                   1203:                                    (maxprot & ~VM_PROT_WRITE), foff, size);
                   1204:                        }
                   1205:                        advice = UVM_ADV_RANDOM;
                   1206:                }
                   1207:
                   1208:                if (uobj == NULL)
                   1209:                        return((vp->v_type == VREG) ? ENOMEM : EINVAL);
                   1210:
                   1211:                if ((flags & MAP_SHARED) == 0)
                   1212:                        uvmflag |= UVM_FLAG_COPYONW;
                   1213:        }
                   1214:
                   1215:        /*
                   1216:         * set up mapping flags
                   1217:         */
                   1218:
                   1219:        uvmflag = UVM_MAPFLAG(prot, maxprot,
                   1220:                        (flags & MAP_SHARED) ? UVM_INH_SHARE : UVM_INH_COPY,
                   1221:                        advice, uvmflag);
                   1222:
                   1223:        error = uvm_map_p(map, addr, size, uobj, foff, align, uvmflag, p);
                   1224:
                   1225:        if (error == 0) {
                   1226:                /*
                   1227:                 * POSIX 1003.1b -- if our address space was configured
                   1228:                 * to lock all future mappings, wire the one we just made.
                   1229:                 */
                   1230:                if (prot == VM_PROT_NONE) {
                   1231:                        /*
                   1232:                         * No more work to do in this case.
                   1233:                         */
                   1234:                        return (0);
                   1235:                }
                   1236:
                   1237:                vm_map_lock(map);
                   1238:
                   1239:                if (map->flags & VM_MAP_WIREFUTURE) {
                   1240:                        if ((atop(size) + uvmexp.wired) > uvmexp.wiredmax
                   1241: #ifdef pmap_wired_count
                   1242:                            || (locklimit != 0 && (size +
                   1243:                                 ptoa(pmap_wired_count(vm_map_pmap(map)))) >
                   1244:                                locklimit)
                   1245: #endif
                   1246:                        ) {
                   1247:                                error = ENOMEM;
                   1248:                                vm_map_unlock(map);
                   1249:                                /* unmap the region! */
                   1250:                                uvm_unmap(map, *addr, *addr + size);
                   1251:                                goto bad;
                   1252:                        }
                   1253:                        /*
                   1254:                         * uvm_map_pageable() always returns the map
                   1255:                         * unlocked.
                   1256:                         */
                   1257:                        error = uvm_map_pageable(map, *addr, *addr + size,
                   1258:                            FALSE, UVM_LK_ENTER);
                   1259:                        if (error != 0) {
                   1260:                                /* unmap the region! */
                   1261:                                uvm_unmap(map, *addr, *addr + size);
                   1262:                                goto bad;
                   1263:                        }
                   1264:                        return (0);
                   1265:                }
                   1266:
                   1267:                vm_map_unlock(map);
                   1268:
                   1269:                return (0);
                   1270:        }
                   1271:
                   1272:        /*
                   1273:         * errors: first detach from the uobj, if any.
                   1274:         */
                   1275:
                   1276:        if (uobj)
                   1277:                uobj->pgops->pgo_detach(uobj);
                   1278:
                   1279: bad:
                   1280:        return (error);
                   1281: }

CVSweb