Annotation of 43BSDReno/sys/kern/kern_mman.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution is only permitted until one year after the first shipment
        !             6:  * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
        !             7:  * binary forms are permitted provided that: (1) source distributions retain
        !             8:  * this entire copyright notice and comment, and (2) distributions including
        !             9:  * binaries display the following acknowledgement:  This product includes
        !            10:  * software developed by the University of California, Berkeley and its
        !            11:  * contributors'' in the documentation or other materials provided with the
        !            12:  * distribution and in all advertising materials mentioning features or use
        !            13:  * of this software.  Neither the name of the University nor the names of
        !            14:  * its contributors may be used to endorse or promote products derived from
        !            15:  * this software without specific prior written permission.
        !            16:  * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
        !            17:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
        !            18:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            19:  *
        !            20:  *     @(#)kern_mman.c 7.18 (Berkeley) 6/30/90
        !            21:  */
        !            22: 
        !            23: #include "param.h"
        !            24: #include "systm.h"
        !            25: #include "map.h"
        !            26: #include "user.h"
        !            27: #include "proc.h"
        !            28: #include "buf.h"
        !            29: #include "vnode.h"
        !            30: #include "specdev.h"
        !            31: #include "seg.h"
        !            32: #include "acct.h"
        !            33: #include "wait.h"
        !            34: #include "vm.h"
        !            35: #include "text.h"
        !            36: #include "file.h"
        !            37: #include "vadvise.h"
        !            38: #include "cmap.h"
        !            39: #include "trace.h"
        !            40: #include "mman.h"
        !            41: #include "mapmem.h"
        !            42: #include "malloc.h"
        !            43: #include "conf.h"
        !            44: 
        !            45: #include "machine/cpu.h"
        !            46: #include "machine/reg.h"
        !            47: #include "machine/psl.h"
        !            48: #include "machine/pte.h"
        !            49: #include "machine/mtpr.h"
        !            50: 
        !            51: /*
        !            52:  * The MMAP code here is temporary; it provides support
        !            53:  * only for mmaping devices such as frame buffers.
        !            54:  * All to be different next time...
        !            55:  */
        !            56: #ifndef MAPMEM
        !            57: #undef MMAP            /* XXX */
        !            58: #endif
        !            59: 
        !            60: #ifdef MMAP
        !            61: struct mapmemops mmapops = {
        !            62:        (int (*)())0, (int (*)())0, (int (*)())0, (int (*)())0
        !            63: };
        !            64: #endif
        !            65: 
        !            66: /* ARGSUSED */
        !            67: sbrk(p, uap, retval)
        !            68:        struct proc *p;
        !            69:        struct args {
        !            70:                int     incr;
        !            71:        } *uap;
        !            72:        int *retval;
        !            73: {
        !            74: 
        !            75:        /* Not yet implemented */
        !            76:        return (EOPNOTSUPP);
        !            77: }
        !            78: 
        !            79: /* ARGSUSED */
        !            80: sstk(p, uap, retval)
        !            81:        struct proc *p;
        !            82:        struct args {
        !            83:                int     incr;
        !            84:        } *uap;
        !            85:        int *retval;
        !            86: {
        !            87: 
        !            88:        /* Not yet implemented */
        !            89:        return (EOPNOTSUPP);
        !            90: }
        !            91: 
        !            92: /* ARGSUSED */
        !            93: getpagesize(p, uap, retval)
        !            94:        struct proc *p;
        !            95:        struct args *uap;
        !            96:        int *retval;
        !            97: {
        !            98: 
        !            99:        *retval = NBPG * CLSIZE;
        !           100:        return (0);
        !           101: }
        !           102: 
        !           103: /* ARGSUSED */
        !           104: smmap(p, uap, retval)
        !           105:        register struct proc *p;
        !           106:        register struct args {
        !           107:                caddr_t addr;
        !           108:                int     len;
        !           109:                int     prot;
        !           110:                int     share;
        !           111:                int     fd;
        !           112:                off_t   pos;
        !           113:        } *uap;
        !           114:        int *retval;
        !           115: {
        !           116: #ifndef MMAP
        !           117:        return (EOPNOTSUPP);
        !           118: #else
        !           119:        register struct file *fp;
        !           120:        struct mapmem *mp;
        !           121:        struct vnode *vp;
        !           122:        register struct pte *pte;
        !           123:        struct pte *dpte;
        !           124:        register int off;
        !           125:        int error, fv, lv, pm, (*mapfun)();
        !           126:        dev_t dev;
        !           127: 
        !           128:        if (error = getvnode(u.u_ofile, uap->fd, &fp))
        !           129:                return (error);
        !           130:        vp = (struct vnode *)fp->f_data;
        !           131:        if (vp->v_type != VCHR)
        !           132:                return (EINVAL);
        !           133:        dev = vp->v_rdev;
        !           134:        mapfun = cdevsw[major(dev)].d_mmap;
        !           135:        if (mapfun == NULL)
        !           136:                return (EINVAL);
        !           137:        if (((int)uap->addr & CLOFSET) || (uap->pos & CLOFSET) ||
        !           138:            uap->len <= 0 || (uap->len & CLOFSET))
        !           139:                return (EINVAL);
        !           140:        if ((uap->prot & PROT_WRITE) && (fp->f_flag&FWRITE) == 0)
        !           141:                return (EINVAL);
        !           142:        if ((uap->prot & PROT_READ) && (fp->f_flag&FREAD) == 0)
        !           143:                return (EINVAL);
        !           144:        if (uap->share != MAP_SHARED)
        !           145:                return (EINVAL);
        !           146:        for (off = 0; off < uap->len; off += NBPG)
        !           147:                if ((*mapfun)(dev, uap->pos+off, uap->prot) == -1)
        !           148:                        return (EINVAL);                /* Needs translation */
        !           149:        /*
        !           150:         * Allocate a descriptor for this region and expand page
        !           151:         * table to accomodate.
        !           152:         */
        !           153:        if (uap->prot & PROT_WRITE) {
        !           154:                pm = PG_UW|PG_FOD|PG_V;
        !           155:                off = MM_RW;
        !           156:        } else {
        !           157:                pm = PG_URKR|PG_FOD|PG_V;
        !           158:                off = MM_RO;
        !           159:        }
        !           160: #if defined(hp300)
        !           161:        pm |= PG_CI;
        !           162:        off |= MM_CI;
        !           163: #endif
        !           164:        error = mmalloc(p, uap->fd, &uap->addr, uap->len, off, &mmapops, &mp);
        !           165:        if (error)
        !           166:                return (error);
        !           167:        /*
        !           168:         * Now map it in.
        !           169:         * Can't use mmmapin() because of args to map function.
        !           170:         */
        !           171:        fv = btop(uap->addr);
        !           172:        pte = vtopte(p, fv);
        !           173:        dpte = dptopte(p, u.u_dsize);
        !           174:        for (off = 0; off < uap->len; off += NBPG) {
        !           175:                if ((off&CLOFSET) == 0 && pte < dpte)
        !           176:                        p->p_rssize -= vmemfree(pte, CLSIZE);
        !           177:                *(int *)pte = pm;
        !           178:                pte->pg_pfnum = (*mapfun)(dev, uap->pos+off, uap->prot);
        !           179:                pte++;
        !           180:        }
        !           181:        newptes(vtopte(p, fv), fv, btoc(uap->len));
        !           182:        u.u_pofile[uap->fd] |= UF_MAPPED;
        !           183:        return (0);
        !           184: #endif /* MMAP */
        !           185: }
        !           186: 
        !           187: /* ARGSUSED */
        !           188: msync(p, uap, retval)
        !           189:        struct proc *p;
        !           190:        struct args {
        !           191:                char    *addr;
        !           192:                int     len;
        !           193:        } *uap;
        !           194:        int *retval;
        !           195: {
        !           196: 
        !           197:        /* Not yet implemented */
        !           198:        return (EOPNOTSUPP);
        !           199: }
        !           200: 
        !           201: /* ARGSUSED */
        !           202: munmap(p, uap, retval)
        !           203:        register struct proc *p;
        !           204:        register struct args {
        !           205:                caddr_t addr;
        !           206:                int     len;
        !           207:        } *uap;
        !           208:        int *retval;
        !           209: {
        !           210: #ifndef MMAP
        !           211:        return (EOPNOTSUPP);
        !           212: #else
        !           213:        register struct mapmem *mp;
        !           214:        register int fd;
        !           215:        caddr_t eaddr;
        !           216:        int error;
        !           217: 
        !           218:        if (((int)uap->addr & CLOFSET) ||
        !           219:            uap->len <= 0 || (uap->len & CLOFSET))
        !           220:                return (EINVAL);
        !           221:        /*
        !           222:         * Locate region mapping this range. If found, unmap it.
        !           223:         */
        !           224:        eaddr = uap->addr + uap->len - 1;
        !           225:        for (mp = u.u_mmap; mp; mp = mp->mm_next)
        !           226:                if (mp->mm_ops == &mmapops &&
        !           227:                    uap->addr >= mp->mm_uva && eaddr < mp->mm_uva+mp->mm_size)
        !           228:                        break;
        !           229:        if (mp == MMNIL)
        !           230:                return (EINVAL);
        !           231:        fd = mp->mm_id;
        !           232:        mmmapout(p, mp);
        !           233:        error = mmfree(mp);
        !           234:        /*
        !           235:         * If no other range has this descriptor mapped, mark it as unmapped.
        !           236:         */
        !           237:        for (mp = u.u_mmap; mp; mp = mp->mm_next)
        !           238:                if (mp->mm_id == fd)
        !           239:                        break;
        !           240:        if (mp == MMNIL)
        !           241:                u.u_pofile[fd] &= ~UF_MAPPED;
        !           242:        return (error);
        !           243: #endif /* MMAP */
        !           244: }
        !           245: 
        !           246: munmapfd(fd)
        !           247:        int fd;
        !           248: {
        !           249:        int error = 0;
        !           250: #ifdef MMAP
        !           251:        struct proc *p = u.u_procp;             /* XXX */
        !           252:        register struct mapmem *mp, **mpp;
        !           253: 
        !           254:        if (p->p_flag & SVFORK)
        !           255:                return (0);
        !           256:        mpp = &u.u_mmap;
        !           257:        for (mp = *mpp; mp; mp = *mpp) {
        !           258:                if (mp->mm_ops == &mmapops && mp->mm_id == fd) {
        !           259:                        mmmapout(p, mp);
        !           260:                        error = mmfree(mp);
        !           261:                } else
        !           262:                        mpp = &mp->mm_next;
        !           263:        }
        !           264: #endif
        !           265:        u.u_pofile[fd] &= ~UF_MAPPED;
        !           266:        return (error);
        !           267: }
        !           268: 
        !           269: /* ARGSUSED */
        !           270: mprotect(p, uap, retval)
        !           271:        struct proc *p;
        !           272:        struct args {
        !           273:                char    *addr;
        !           274:                int     len;
        !           275:                int     prot;
        !           276:        } *uap;
        !           277:        int *retval;
        !           278: {
        !           279: 
        !           280:        /* Not yet implemented */
        !           281:        return (EOPNOTSUPP);
        !           282: }
        !           283: 
        !           284: /* ARGSUSED */
        !           285: madvise(p, uap, retval)
        !           286:        struct proc *p;
        !           287:        struct args {
        !           288:                char    *addr;
        !           289:                int     len;
        !           290:                int     behav;
        !           291:        } *uap;
        !           292:        int *retval;
        !           293: {
        !           294: 
        !           295:        /* Not yet implemented */
        !           296:        return (EOPNOTSUPP);
        !           297: }
        !           298: 
        !           299: /* ARGSUSED */
        !           300: mincore(p, uap, retval)
        !           301:        struct proc *p;
        !           302:        struct args {
        !           303:                char    *addr;
        !           304:                int     len;
        !           305:                char    *vec;
        !           306:        } *uap;
        !           307:        int *retval;
        !           308: {
        !           309: 
        !           310:        /* Not yet implemented */
        !           311:        return (EOPNOTSUPP);
        !           312: }
        !           313: 
        !           314: /* BEGIN DEFUNCT */
        !           315: /* ARGSUSED */
        !           316: obreak(p, uap, retval)
        !           317:        struct proc *p;
        !           318:        struct args {
        !           319:                char    *nsiz;
        !           320:        } *uap;
        !           321:        int *retval;
        !           322: {
        !           323:        register segsz_t n, d, ds;
        !           324:        int error;
        !           325: 
        !           326:        /*
        !           327:         * set n to new data size
        !           328:         */
        !           329:        n = btoc(uap->nsiz) - dptov(p, 0);
        !           330:        if (n < 0)
        !           331:                n = 0;
        !           332:        /*
        !           333:         * since we can't pass a -ve argument for the difference to chksize,
        !           334:         * if d is negative, make ds equal to the final value and clear d.
        !           335:         * keep the real difference in n for later use in expand.
        !           336:         */
        !           337:        ds = u.u_dsize;
        !           338:        if ((n = d = clrnd(n - u.u_dsize)) < 0) {
        !           339:                ds += d;
        !           340:                d = 0;
        !           341:        }
        !           342:        if (ctob(ds + d) > u.u_rlimit[RLIMIT_DATA].rlim_cur)
        !           343:                return (ENOMEM);
        !           344:        if (error =
        !           345:            chksize((u_int)u.u_tsize, (u_int)ds, (u_int)d, (u_int)u.u_ssize))
        !           346:                return (error);
        !           347: #ifdef MAPMEM
        !           348:        /*
        !           349:         * If change would conflict with any mapped memory segment
        !           350:         * return ENOMEM.
        !           351:         */
        !           352:        if (u.u_mmap && n != 0) {
        !           353:                caddr_t low, high;
        !           354: 
        !           355:                low = (caddr_t) ctob(dptov(p, ds));
        !           356:                high = low + ctob((n < 0) ? -n : n);
        !           357:                if (mmclash(u.u_mmap, low, high))
        !           358:                        return (ENOMEM);
        !           359:        }
        !           360: #endif
        !           361:        if (error = swpexpand(ds + d, u.u_ssize, &u.u_dmap, &u.u_smap))
        !           362:                return (error);
        !           363:        if (p->p_mmsize && (p->p_mmsize -= n) < 0)
        !           364:                p->p_mmsize = 0;
        !           365:        expand((int)n, 0);
        !           366:        return (0);
        !           367: }
        !           368: 
        !           369: /*
        !           370:  * Macros for clearing a page's reference bits.
        !           371:  */
        !           372: #ifdef REFBIT
        !           373: #if !defined(tahoe)
        !           374: #define uncache(pte)           /* XXX */
        !           375: #endif
        !           376: 
        !           377: #define CLRREF(pte, c, p, i) { \
        !           378:        if (!isatpte(p, pte)) \
        !           379:                uncache(pte); \
        !           380:        if (pte->pg_u) { \
        !           381:                c = &cmap[pgtocm(pte->pg_pfnum)]; \
        !           382:                if (c->c_lock) \
        !           383:                        continue; \
        !           384:                pte->pg_u = 0; \
        !           385:                if (anycl(pte, pg_m)) \
        !           386:                        pte->pg_m = 1; \
        !           387:                distcl(pte); \
        !           388:                if (isatpte(p, pte)) \
        !           389:                        distpte(p->p_textp, i, pte); \
        !           390:        } \
        !           391: }
        !           392: #else
        !           393: #define CLRREF(pte, c, p, i) { \
        !           394:        c = &cmap[pgtocm(pte->pg_pfnum)]; \
        !           395:        if (c->c_lock) \
        !           396:                continue; \
        !           397:        pte->pg_v = 0; \
        !           398:        if (anycl(pte, pg_m)) \
        !           399:                pte->pg_m = 1; \
        !           400:        distcl(pte); \
        !           401:        if (isatpte(p, pte)) \
        !           402:                distpte(p->p_textp, i, pte); \
        !           403: }
        !           404: #endif
        !           405: 
        !           406: /* ARGSUSED */
        !           407: ovadvise(rp, uap, retval)
        !           408:        register struct proc *rp;
        !           409:        struct args {
        !           410:                int     anom;
        !           411:        } *uap;
        !           412:        int *retval;
        !           413: {
        !           414:        int oanom = rp->p_flag & SUANOM;
        !           415:        register struct pte *pte;
        !           416:        register struct cmap *c;
        !           417:        register unsigned i;
        !           418: 
        !           419:        trace(TR_VADVISE, uap->anom, rp->p_pid);
        !           420:        rp->p_flag &= ~(SSEQL|SUANOM);
        !           421:        switch (uap->anom) {
        !           422: 
        !           423:        case VA_ANOM:
        !           424:                rp->p_flag |= SUANOM;
        !           425:                break;
        !           426: 
        !           427:        case VA_SEQL:
        !           428:                rp->p_flag |= SSEQL;
        !           429:                break;
        !           430:        }
        !           431:        if ((oanom && (rp->p_flag & SUANOM) == 0) || uap->anom == VA_FLUSH) {
        !           432:                for (i = 0; i < rp->p_dsize; i += CLSIZE) {
        !           433:                        pte = dptopte(rp, i);
        !           434: #ifdef MAPMEM
        !           435:                        /* don't do mmap pages */
        !           436:                        if (pte->pg_v && !pte->pg_fod)
        !           437: #else
        !           438:                        if (pte->pg_v)
        !           439: #endif
        !           440:                                CLRREF(pte, c, rp, i);
        !           441:                }
        !           442:        }
        !           443:        if (uap->anom == VA_FLUSH) {    /* invalidate all pages */
        !           444:                for (i = 1; i < rp->p_ssize; i += CLSIZE) {
        !           445:                        pte = sptopte(rp, i);
        !           446:                        if (pte->pg_v)
        !           447:                                CLRREF(pte, c, rp, i);
        !           448:                }
        !           449:                for (i = 0; i < rp->p_tsize; i += CLSIZE) {
        !           450:                        pte = tptopte(rp, i);
        !           451:                        if (pte->pg_v)
        !           452:                                CLRREF(pte, c, rp, i);
        !           453:                }
        !           454:        }
        !           455: #if defined(vax) || defined(tahoe)
        !           456:        mtpr(TBIA, 0);
        !           457: #endif
        !           458: #if defined(hp300)
        !           459:        TBIAU();
        !           460: #endif
        !           461: #if defined(i386)
        !           462:        tlbflush();
        !           463: #endif
        !           464:        return (0);
        !           465: }
        !           466: /* END DEFUNCT */
        !           467: 
        !           468: /*
        !           469:  * Grow the stack to include the SP; true return if successful.
        !           470:  * Clients do not care about the cause of the error.
        !           471:  */
        !           472: grow(sp)
        !           473:        unsigned sp;
        !           474: {
        !           475:        int si, error;
        !           476: 
        !           477:        if (sp >= USRSTACK-ctob(u.u_ssize))
        !           478:                return (0);
        !           479:        si = clrnd(btoc((USRSTACK-sp)) - u.u_ssize + SINCR);
        !           480:        if (ctob(si) > u.u_rlimit[RLIMIT_STACK].rlim_cur)
        !           481:                return (0);
        !           482:        if (error = chksize((u_int)u.u_tsize, (u_int)u.u_dsize, (u_int)0,
        !           483:            (u_int)u.u_ssize+si))
        !           484:                return (0);
        !           485:        if (error = swpexpand(u.u_dsize, u.u_ssize + si, &u.u_dmap, &u.u_smap))
        !           486:                return (0);
        !           487:        expand(si, 1);
        !           488:        return (1);
        !           489: }
        !           490: 
        !           491: #ifdef MAPMEM
        !           492: 
        !           493: /*
        !           494:  * Called from vpassvm() after full context has been passed from fup to tup.
        !           495:  * Always called in the context of the parent.  NOTE: routines should NOT
        !           496:  * destroy regions.
        !           497:  */
        !           498: mmvfork(fup, tup)
        !           499:        struct user *fup, *tup;
        !           500: {
        !           501:        register struct mapmem *mp;
        !           502: 
        !           503:        tup->u_mmap = fup->u_mmap;
        !           504:        fup->u_mmap = (struct mapmem *) 0;
        !           505:        for (mp = tup->u_mmap; mp; mp = mp->mm_next)
        !           506:                if (mp->mm_ops->mm_vfork)
        !           507:                        (*mp->mm_ops->mm_vfork)(mp, fup, tup);
        !           508: }
        !           509: 
        !           510: /*
        !           511:  * Called from procdup() for both parent and child.  If in parent
        !           512:  * we need to duplicate mapped memory regions.  In both parent and
        !           513:  * child, we call object specific routine.
        !           514:  */
        !           515: mmfork(pup, cup)
        !           516:        struct user *pup, *cup;
        !           517: {
        !           518:        register struct mapmem *mp, **mpp;
        !           519:        int error = 0;
        !           520: 
        !           521:        if (pup) {
        !           522:                mmdup(pup, cup);
        !           523:                for (mp = pup->u_mmap; mp; mp = mp->mm_next)
        !           524:                        if (mp->mm_ops->mm_fork)
        !           525:                                (*mp->mm_ops->mm_fork)(mp, 0);
        !           526:        } else {
        !           527:                mpp = &u.u_mmap;
        !           528:                for (mp = *mpp; mp; mp = *mpp) {
        !           529:                        if (mp->mm_ops->mm_fork)
        !           530:                                (*mp->mm_ops->mm_fork)(mp, 1);
        !           531:                        if (*mpp == mp)
        !           532:                                mpp = &mp->mm_next;
        !           533:                }
        !           534:                error = mmexpand(u.u_procp);
        !           535:        }
        !           536:        return (error);
        !           537: }
        !           538: 
        !           539: /*
        !           540:  * Its not clear that having a seperate exec routine is useful since
        !           541:  * exec frees the address space immediately afterwards.  We probably
        !           542:  * need a post-exec hook to reestablish any mappings that persist
        !           543:  * across execs.
        !           544:  */
        !           545: mmexec(p)
        !           546:        struct proc *p;
        !           547: {
        !           548:        register struct mapmem *mp, **mpp;
        !           549:        int error1, error = 0;
        !           550: 
        !           551:        mpp = &u.u_mmap;
        !           552:        for (mp = *mpp; mp; mp = *mpp) {
        !           553:                if (mp->mm_ops->mm_exec)
        !           554:                        error = (*mp->mm_ops->mm_exec)(mp);
        !           555:                if (*mpp == mp) {
        !           556:                        *mpp = mp->mm_next;
        !           557:                        MMFREE(mp);
        !           558:                }
        !           559:        }
        !           560:        if (error1 = mmexpand(p))
        !           561:                return (error1);
        !           562:        if (p->p_mmsize)
        !           563:                panic("mmexec");
        !           564:        return (error);
        !           565: }
        !           566: 
        !           567: /*
        !           568:  * Called from exit just before releasing address space.
        !           569:  * We always reclaim resources regardless of what the object routine does.
        !           570:  */
        !           571: mmexit(p)
        !           572:        struct proc *p;
        !           573: {
        !           574:        register struct mapmem *mp, **mpp;
        !           575:        int error1, error = 0;
        !           576: 
        !           577:        mpp = &u.u_mmap;
        !           578:        for (mp = *mpp; mp; mp = *mpp) {
        !           579:                if (mp->mm_ops->mm_exit)
        !           580:                        error = (*mp->mm_ops->mm_exit)(mp);
        !           581:                if (*mpp == mp) {
        !           582:                        *mpp = mp->mm_next;
        !           583:                        MMFREE(mp);
        !           584:                }
        !           585:        }
        !           586:        if (error1 = mmexpand(p))
        !           587:                return (error1);
        !           588:        if (p->p_mmsize)
        !           589:                panic("mmexit");
        !           590:        return (error);
        !           591: }
        !           592: 
        !           593: /*
        !           594:  * Called from core just before dumping process image to core file.
        !           595:  * Used to unmap regions which cannot be dumped; e.g. a region mapping
        !           596:  * hardware registers which are write-only or must be accessed as bytes.
        !           597:  */
        !           598: mmcore(p)
        !           599:        struct proc *p;
        !           600: {
        !           601:        register struct mapmem *mp, **mpp;
        !           602:        int error = 0, error1, changed = 0;
        !           603: 
        !           604:        mpp = &u.u_mmap;
        !           605:        for (mp = *mpp; mp; mp = *mpp) {
        !           606:                if ((mp->mm_prot & MM_NOCORE) == 0) {
        !           607:                        mpp = &mp->mm_next;
        !           608:                        continue;
        !           609:                }
        !           610:                if (mp->mm_ops->mm_exit)
        !           611:                        error = (*mp->mm_ops->mm_exit)(mp);
        !           612:                if (*mpp == mp) {
        !           613:                        *mpp = mp->mm_next;
        !           614:                        MMFREE(mp);
        !           615:                }
        !           616:                changed++;
        !           617:        }
        !           618:        if (changed && (error1 = mmexpand(p)))
        !           619:                return (error1);
        !           620:        return (error);
        !           621: }
        !           622: 
        !           623: /*
        !           624:  * Duplicate mapped memory regions in a forked process.
        !           625:  * XXX child may wind up short a few regions if not enough resources.
        !           626:  */
        !           627: mmdup(pu, cu)
        !           628:        struct user *pu, *cu;
        !           629: {
        !           630:        register struct mapmem *pmp, *cmp;
        !           631:        register struct pte *ppte, *cpte;
        !           632:        register segsz_t count;
        !           633: 
        !           634:        /*
        !           635:         * First duplicate the mmap chain
        !           636:         */
        !           637:        MMALLOC(cu->u_mmap);
        !           638:        pmp = pu->u_mmap;
        !           639:        cmp = cu->u_mmap;
        !           640:        while (pmp && cmp) {
        !           641:                *cmp = *pmp;
        !           642:                if (pmp->mm_next)
        !           643:                        MMALLOC(cmp->mm_next);
        !           644:                pmp = pmp->mm_next;
        !           645:                cmp = cmp->mm_next;
        !           646:        }
        !           647:        /*
        !           648:         * Now duplicate user address space that vmdup() won't do
        !           649:         * i.e. mapped regions outside of data segment.
        !           650:         */
        !           651:        ppte = dptopte(pu->u_procp, pu->u_procp->p_dsize);
        !           652:        cpte = dptopte(cu->u_procp, cu->u_procp->p_dsize);
        !           653:        for (count = pu->u_procp->p_mmsize; count; count--) {
        !           654:                if (ppte->pg_fod && ppte->pg_v)
        !           655:                        *(int *)cpte = *(int *)ppte;
        !           656:                ppte++, cpte++;
        !           657:        }
        !           658:        cu->u_procp->p_flag |= SPTECHG;
        !           659: }
        !           660: 
        !           661: mmalloc(p, id, uvap, size, prot, ops, mpp)
        !           662:        struct proc *p;
        !           663:        caddr_t *uvap;
        !           664:        segsz_t size;
        !           665:        struct mapmemops *ops;
        !           666:        struct mapmem **mpp;
        !           667: {
        !           668:        register struct mapmem *mp;
        !           669:        register u_int uva;
        !           670:        int error;
        !           671: 
        !           672:        /*
        !           673:         * Validate size first
        !           674:         */
        !           675:        if (size <= 0 || (size & CLOFSET))
        !           676:                return(EINVAL);
        !           677:        /*
        !           678:         * A uva of zero means to map at our discretion.
        !           679:         * Our strategy is to place the segment at the max of:
        !           680:         *      - the current data + mapped memory size
        !           681:         *      - the default data size limit
        !           682:         *        (if it will fit within the MAXDSIZ limit)
        !           683:         * If this is the first mapped memory region beyond the data
        !           684:         * segment we round to a MMSEG boundary to allow for data
        !           685:         * segment growth.
        !           686:         */
        !           687:        uva = (u_int) *uvap;
        !           688:        if (uva == 0) {
        !           689:                register u_int uva2;
        !           690: 
        !           691:                uva = ctob(dptov(p, u.u_dsize + p->p_mmsize));
        !           692:                uva2 = ctob(dptov(p, btoc(DFLDSIZ)));
        !           693:                uva2 = ((uva2 + (MMSEG-1)) & ~(MMSEG-1));
        !           694:                if (uva < uva2 &&
        !           695:                    uva2 + size < ctob(dptov(p, btoc(MAXDSIZ))))
        !           696:                        uva = uva2;
        !           697:                else if (p->p_mmsize == 0)
        !           698:                        uva = ((uva + (MMSEG-1)) & ~(MMSEG-1));
        !           699:        }
        !           700:        /*
        !           701:         * Impose necessary constraints on address.
        !           702:         */
        !           703:        if ((uva & CLOFSET) || uva < ctob(dptov(p, 0)) ||
        !           704:            uva+size >= ctob(sptov(p, u.u_ssize)))
        !           705:                return (EINVAL);
        !           706:        if (mmclash(u.u_mmap, (caddr_t)uva, (caddr_t)uva+size))
        !           707:                return (EINVAL);
        !           708:        /*
        !           709:         * Finally, allocate and initialize descriptor and expand
        !           710:         * user address space as necessary.
        !           711:         */
        !           712:        MMALLOC(mp);
        !           713:        if (mp == MMNIL)
        !           714:                return (ENOMEM);
        !           715:        mp->mm_next = u.u_mmap;
        !           716:        mp->mm_id = id;
        !           717:        mp->mm_uva = (caddr_t) uva;
        !           718:        mp->mm_size = size;
        !           719:        mp->mm_prot = prot;
        !           720:        mp->mm_ops = ops;
        !           721:        u.u_mmap = mp;
        !           722:        if (error = mmexpand(p)) {
        !           723:                u.u_mmap = mp->mm_next;
        !           724:                MMFREE(mp);
        !           725:                return(error);
        !           726:        }
        !           727:        *uvap = (caddr_t) uva;
        !           728:        *mpp = mp;
        !           729:        return(0);
        !           730: }
        !           731: 
        !           732: mmfree(p, mp)
        !           733:        struct proc *p;
        !           734:        register struct mapmem *mp;
        !           735: {
        !           736:        register struct mapmem *cmp, **mpp;
        !           737: 
        !           738:        /*
        !           739:         * Remove region from chain
        !           740:         */
        !           741:        mpp = &u.u_mmap;
        !           742:        for (cmp = *mpp; cmp; cmp = *mpp) {
        !           743:                if (cmp == mp)
        !           744:                        break;
        !           745:                mpp = &cmp->mm_next;
        !           746:        }
        !           747:        if (cmp == MMNIL)
        !           748:                panic("mmfree");
        !           749:        *mpp = mp->mm_next;
        !           750:        MMFREE(mp);
        !           751:        return (mmexpand(p));
        !           752: }
        !           753: 
        !           754: mmmapin(p, mp, mapfunc)
        !           755:        register struct proc *p;
        !           756:        register struct mapmem *mp;
        !           757:        int (*mapfunc)();
        !           758: {
        !           759:        register struct pte *pte;
        !           760:        register int off;
        !           761:        struct pte *dpte;
        !           762:        int pm, fv, lv;
        !           763: 
        !           764:        /*
        !           765:         * Verify that range can be mapped
        !           766:         */
        !           767:        for (off = 0; off < mp->mm_size; off += NBPG)
        !           768:                if ((*mapfunc)(mp, off) == -1)
        !           769:                        return (EINVAL);
        !           770:        /*
        !           771:         * Now verify that region is in range
        !           772:         */
        !           773:        fv = btop(mp->mm_uva);
        !           774:        lv = btop(mp->mm_uva + mp->mm_size - 1);
        !           775:        if (fv < dptov(p, 0) ||
        !           776:            lv >= dptov(p, u.u_dsize + p->p_mmsize))
        !           777:                return (ENOMEM);
        !           778:        /*
        !           779:         * Finally, do the mapping.
        !           780:         */
        !           781:        if (mp->mm_prot & MM_RO)
        !           782:                pm = PG_URKR|PG_FOD|PG_V;
        !           783:        else
        !           784:                pm = PG_UW|PG_FOD|PG_V;
        !           785: #if defined(hp300)
        !           786:        if (mp->mm_prot & MM_CI)
        !           787:                pm |= PG_CI;
        !           788: #endif
        !           789:        pte = vtopte(p, fv);
        !           790:        dpte = dptopte(p, u.u_dsize);
        !           791:        for (off = 0; off < mp->mm_size; off += NBPG) {
        !           792:                if ((off&CLOFSET) == 0 && pte < dpte)
        !           793:                        p->p_rssize -= vmemfree(pte, CLSIZE);
        !           794:                *(int *)pte = pm;
        !           795:                pte->pg_pfnum = (*mapfunc)(mp, off);
        !           796:                pte++;
        !           797:        }
        !           798:        newptes(vtopte(p, fv), (u_int)fv, (int)btoc(mp->mm_size));
        !           799:        return (0);
        !           800: }
        !           801: 
        !           802: mmmapout(p, mp)
        !           803:        register struct proc *p;
        !           804:        register struct mapmem *mp;
        !           805: {
        !           806:        register struct pte *pte;
        !           807:        register int off;
        !           808:        struct pte *dpte;
        !           809:        int fv, lv;
        !           810: 
        !           811:        fv = btop(mp->mm_uva);
        !           812:        lv = btop(mp->mm_uva + mp->mm_size - 1);
        !           813:        if (fv < dptov(p, 0) ||
        !           814:            lv >= dptov(p, u.u_dsize + p->p_mmsize))
        !           815:                panic("mmmapout");
        !           816:        pte = vtopte(p, fv);
        !           817:        dpte = dptopte(p, u.u_dsize);
        !           818:        for (off = 0; off < mp->mm_size; off += NBPG) {
        !           819:                if (pte < dpte) {
        !           820:                        if ((off & CLOFSET) == 0)
        !           821:                                p->p_rssize -= vmemfree(pte, CLSIZE);
        !           822:                        *(int *)pte = (PG_UW|PG_FOD);
        !           823:                        ((struct fpte *)pte)->pg_fileno = PG_FZERO;
        !           824:                } else
        !           825:                        *(int *)pte = 0;
        !           826:                pte++;
        !           827:        }
        !           828:        newptes(vtopte(p, fv), (u_int)fv, (int)btoc(mp->mm_size));
        !           829: }
        !           830: 
        !           831: mmexpand(p)
        !           832:        struct proc *p;
        !           833: {
        !           834:        register int szpt, change;
        !           835:        caddr_t high;
        !           836:        segsz_t nsize, oms;
        !           837: 
        !           838:        oms = p->p_mmsize;
        !           839:        /*
        !           840:         * Get new mmsize based on existing regions and use
        !           841:         * that to calculate change in page table size.
        !           842:         */
        !           843:        if (u.u_mmap) {
        !           844:                mmrange(u.u_mmap, (caddr_t *)0, &high);
        !           845:                nsize = btop(high) - dptov(p, u.u_dsize) + 1;
        !           846:                if (nsize < 0)
        !           847:                        nsize = 0;
        !           848:        } else
        !           849:                nsize = 0;
        !           850:        change = nsize - oms;
        !           851:        if (change == 0)
        !           852:                return(0);
        !           853: 
        !           854:        /*
        !           855:         * Ensure data + mapped memory fits within maximum data limit.
        !           856:         * This is possibly a little restrictive, but it helps keep
        !           857:         * page table sizes down.
        !           858:         */
        !           859:        if (change > 0 &&
        !           860:            (ctob(oms+change) > u.u_rlimit[RLIMIT_DATA].rlim_max ||
        !           861:             ctob(u.u_dsize+oms+change) > u.u_rlimit[RLIMIT_DATA].rlim_max))
        !           862:                return(ENOMEM);
        !           863:        /*
        !           864:         * Expand page table if necessary.
        !           865:         * Note that ptexpand takes care of flushing the translation buffer.
        !           866:         */
        !           867:        p->p_mmsize += change;
        !           868: #if defined(hp300) || defined(i386)
        !           869:        szpt = ptsize(p) - u.u_pcb.pcb_szpt;
        !           870:        if (szpt > 0)
        !           871:                ptexpand(szpt, u.u_dsize, oms, u.u_ssize);
        !           872:        setp0lr(u.u_pcb.pcb_p0lr + change);
        !           873: #endif
        !           874: #if defined(vax) || defined(tahoe)
        !           875: #if defined(vax)
        !           876:        szpt = (u.u_pcb.pcb_p1br + (u.u_pcb.pcb_p1lr&~PME_CLR)) -
        !           877:                (u.u_pcb.pcb_p0br + (u.u_pcb.pcb_p0lr&~AST_CLR));
        !           878: #else
        !           879:        szpt = (u.u_pcb.pcb_p2br + u.u_pcb.pcb_p2lr) -
        !           880:                (u.u_pcb.pcb_p0br + u.u_pcb.pcb_p0lr);
        !           881: #endif
        !           882:        if (change > szpt)
        !           883:                ptexpand(clrnd(ctopt(change - szpt)), u.u_dsize, oms, u.u_ssize);
        !           884:        /*
        !           885:         * Clear new ptes.
        !           886:         * We need to do this because there may be bogus (yet technically
        !           887:         * valid) ptes above the old p0lr value.  This can happen if the
        !           888:         * data segment has shrunk in the past leaving such ptes behind.
        !           889:         * There is no need to invalidate such ptes at that time since the
        !           890:         * length register will prevent their use.  We are safe on the HPs
        !           891:         * because we do invalidate old ptes in setp0lr() when shrinking.
        !           892:         */
        !           893:        if (change > 0) {
        !           894:                struct pte *bpte;
        !           895: 
        !           896: #if defined(vax)
        !           897:                bpte = u.u_pcb.pcb_p0br + (u.u_pcb.pcb_p0lr&~AST_CLR);
        !           898: #else
        !           899:                bpte = u.u_pcb.pcb_p0br + u.u_pcb.pcb_p0lr;
        !           900: #endif
        !           901:                bzero((caddr_t)bpte, change * sizeof(struct pte));
        !           902:                mtpr(TBIA, 0);
        !           903:        }
        !           904:        /* avoid side-effects of setp0lr */
        !           905: #if defined(vax)
        !           906:        change += u.u_pcb.pcb_p0lr &~ AST_CLR;
        !           907: #else
        !           908:        change += u.u_pcb.pcb_p0lr;
        !           909: #endif
        !           910:        setp0lr(change);
        !           911: #endif
        !           912:        return(0);
        !           913: }
        !           914: 
        !           915: mmrange(mp, lap, hap)
        !           916:        register struct mapmem *mp;
        !           917:        caddr_t *lap, *hap;
        !           918: {
        !           919:        register caddr_t low, high, top;
        !           920: 
        !           921:        low = high = 0;
        !           922:        while (mp) {
        !           923:                if (low == 0 || mp->mm_uva < low)
        !           924:                        low = mp->mm_uva;
        !           925:                top = mp->mm_uva + mp->mm_size - 1;
        !           926:                if (high == 0 || top > high)
        !           927:                        high = top;
        !           928:                mp = mp->mm_next;
        !           929:        }
        !           930:        if (lap)
        !           931:                *lap = low;
        !           932:        if (hap)
        !           933:                *hap = high;
        !           934: }
        !           935: 
        !           936: mmclash(mp, la, ha)
        !           937:        register struct mapmem *mp;
        !           938:        caddr_t la, ha;
        !           939: {
        !           940:        while (mp) {
        !           941:                if (ha > mp->mm_uva && la < mp->mm_uva + mp->mm_size)
        !           942:                        return(1);
        !           943:                mp = mp->mm_next;
        !           944:        }
        !           945:        return(0);
        !           946: }
        !           947: 
        !           948: #endif /* MAPMEM */

unix.superglobalmegacorp.com

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