Annotation of 43BSDReno/sys/kern/kern_mman.c, revision 1.1.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.