Annotation of researchv10no/sys/vm/vmpt.c, revision 1.1

1.1     ! root        1: /*     vmpt.c  4.11    81/04/15        */
        !             2: 
        !             3: #include "sys/param.h"
        !             4: #include "sys/systm.h"
        !             5: #include "sys/user.h"
        !             6: #include "sys/proc.h"
        !             7: #include "sys/map.h"
        !             8: #include "sys/mtpr.h"
        !             9: #include "sys/pte.h"
        !            10: #include "sys/cmap.h"
        !            11: #include "sys/vm.h"
        !            12: #include "sys/buf.h"
        !            13: #include "sys/text.h"
        !            14: 
        !            15: extern struct map kernelmap[], swapmap[];
        !            16: 
        !            17: /*
        !            18:  * Get page tables for process p.  Allocator
        !            19:  * for memory is argument; process must be locked
        !            20:  * from swapping if vmemall is used; if memall is
        !            21:  * used, call will return w/o waiting for memory.
        !            22:  * In any case an error return results if no user
        !            23:  * page table space is available.
        !            24:  */
        !            25: vgetpt(p, pmemall)
        !            26:        register struct proc *p;
        !            27:        int (*pmemall)();
        !            28: {
        !            29:        register int a;
        !            30:        register int i;
        !            31: 
        !            32:        if (p->p_szpt == 0)
        !            33:                panic("vgetpt");
        !            34:        /*
        !            35:         * Allocate space in the kernel map for this process.
        !            36:         * Then allocate page table pages, and initialize the
        !            37:         * process' p0br and addr pointer to be the kernel
        !            38:         * virtual addresses of the base of the page tables and
        !            39:         * the pte for the process pcb (at the base of the u.).
        !            40:         */
        !            41:        a = rmalloc(kernelmap, p->p_szpt);
        !            42:        if (a == 0)
        !            43:                return (0);
        !            44:        if ((*pmemall)(&Usrptmap[a], p->p_szpt, p, CSYS) == 0) {
        !            45:                kmfree(p->p_szpt, a);
        !            46:                return (0);
        !            47:        }
        !            48:        p->p_p0br = kmxtob(a);
        !            49:        p->p_addr = uaddr(p);
        !            50:        /*
        !            51:         * Now validate the system page table entries for the
        !            52:         * user page table pages, flushing old translations
        !            53:         * for these kernel virtual addresses.  Clear the new
        !            54:         * page table pages for clean post-mortems.
        !            55:         */
        !            56:        vmaccess(&Usrptmap[a], (caddr_t)p->p_p0br, p->p_szpt);
        !            57:        for (i = 0; i < p->p_szpt; i++)
        !            58:                clearseg(Usrptmap[a + i].pg_pfnum);
        !            59:        return (1);
        !            60: }
        !            61: 
        !            62: /*
        !            63:  * Initialize text portion of page table.
        !            64:  */
        !            65: vinitpt(p)
        !            66:        struct proc *p;
        !            67: {
        !            68:        register struct text *xp;
        !            69:        register struct proc *q;
        !            70:        register struct pte *pte;
        !            71:        register int i;
        !            72:        struct pte proto;
        !            73: 
        !            74:        xp = p->p_textp;
        !            75:        if (xp == 0)
        !            76:                return;
        !            77:        pte = tptopte(p, 0);
        !            78:        /*
        !            79:         * If there is another instance of same text in core
        !            80:         * then just copy page tables from other process.
        !            81:         */
        !            82:        if (q = xp->x_caddr) {
        !            83:                bcopy((caddr_t)tptopte(q, 0), (caddr_t)pte,
        !            84:                    (unsigned) (sizeof(struct pte) * xp->x_size));
        !            85:                goto done;
        !            86:        }
        !            87:        /*
        !            88:         * Initialize text page tables, zfod if we are loading
        !            89:         * the text now; unless the process is demand loaded,
        !            90:         * this will suffice as the text will henceforth either be
        !            91:         * read from a file or demand paged in.
        !            92:         */
        !            93:        *(int *)&proto = PG_URKR;
        !            94:        if (xp->x_flag & XLOAD) {
        !            95:                proto.pg_fod = 1;
        !            96:                ((struct fpte *)&proto)->pg_source = PG_FZERO;
        !            97:        }
        !            98:        for (i = 0; i < xp->x_size; i++)
        !            99:                *pte++ = proto;
        !           100:        if ((xp->x_flag & XPAGI) == 0)
        !           101:                goto done;
        !           102:        /*
        !           103:         * Text is demand loaded.  If process is not loaded (i.e. being
        !           104:         * swapped in) then retrieve page tables from swap area.  Otherwise
        !           105:         * this is the first time and we must initialize the page tables
        !           106:         * from the blocks in the file system.
        !           107:         */
        !           108:        if (xp->x_flag & XLOAD)
        !           109:                vinifod((struct fpte *)tptopte(p, 0), xp->x_iptr,
        !           110:                    (daddr_t)1, xp->x_size);
        !           111:        else
        !           112:                swap(p, xp->x_ptdaddr, (caddr_t)tptopte(p, 0),
        !           113:                    xp->x_size * sizeof (struct pte), B_READ,
        !           114:                    B_PAGET, swapdev, 0);
        !           115: done:
        !           116:        /*
        !           117:         * In the case where we are overlaying ourself with new page
        !           118:         * table entries, old user-space translations should be flushed.
        !           119:         */
        !           120:        if (p == u.u_procp)
        !           121:                mtpr(TBIA, 0);
        !           122: }
        !           123: 
        !           124: /*
        !           125:  * Update the page tables of all processes linked
        !           126:  * to a particular text segment, by distributing
        !           127:  * dpte to the the text page at virtual frame v.
        !           128:  *
        !           129:  * Note that invalidation in the translation buffer for
        !           130:  * the current process is the responsibility of the caller.
        !           131:  */
        !           132: distpte(xp, tp, dpte)
        !           133:        struct text *xp;
        !           134:        register clicks_t tp;
        !           135:        register struct pte *dpte;
        !           136: {
        !           137:        register struct proc *p;
        !           138:        register struct pte *pte;
        !           139:        register int i;
        !           140: 
        !           141:        for (p = xp->x_caddr; p; p = p->p_xlink) {
        !           142:                pte = tptopte(p, tp);
        !           143:                if (pte != dpte)
        !           144:                        for (i = 0; i < CLSIZE; i++)
        !           145:                                pte[i] = dpte[i];
        !           146:        }
        !           147: }
        !           148: 
        !           149: /*
        !           150:  * Release page tables of process p.
        !           151:  */
        !           152: vrelpt(p)
        !           153:        register struct proc *p;
        !           154: {
        !           155:        register int a;
        !           156: 
        !           157:        if (p->p_szpt == 0)
        !           158:                return;
        !           159:        a = btokmx(p->p_p0br);
        !           160:        (void) vmemfree(&Usrptmap[a], p->p_szpt);
        !           161:        kmfree(p->p_szpt, a);
        !           162: }
        !           163: 
        !           164: /*
        !           165:  * Compute number of pages to be allocated to the u. area
        !           166:  * and data and stack area page tables, which are stored on the
        !           167:  * disk immediately after the u. area.
        !           168:  */
        !           169: vusize(p)
        !           170:        register struct proc *p;
        !           171: {
        !           172:        register int tsz = p->p_tsize / NPTEPG;
        !           173: 
        !           174:        /*
        !           175:         * We do not need page table space on the disk for page
        !           176:         * table pages wholly containing text.  This is well
        !           177:         * understood in the code in vmswap.c.
        !           178:         */
        !           179:        return (clrnd(UPAGES +
        !           180:            clrnd(ctopt(p->p_tsize+p->p_dsize+p->p_ssize+UPAGES)) - tsz));
        !           181: }
        !           182: 
        !           183: /*
        !           184:  * Get u area for process p.  If a old u area is given,
        !           185:  * then copy the new area from the old, else
        !           186:  * swap in as specified in the proc structure.
        !           187:  *
        !           188:  * Since argument map/newu is potentially shared
        !           189:  * when an old u. is provided we have to be careful not
        !           190:  * to block after beginning to use them in this case.
        !           191:  * (This is not true when called from swapin() with no old u.)
        !           192:  */
        !           193: vgetu(p, palloc, map, newu, oldu)
        !           194:        register struct proc *p;
        !           195:        int (*palloc)();
        !           196:        register struct pte *map;
        !           197:        register struct user *newu;
        !           198:        struct user *oldu;
        !           199: {
        !           200:        register int i;
        !           201: 
        !           202:        if ((*palloc)(p->p_addr, clrnd(UPAGES), p, CSYS) == 0)
        !           203:                return (0);
        !           204:        /*
        !           205:         * New u. pages are to be accessible in map/newu as well
        !           206:         * as in process p's virtual memory.
        !           207:         */
        !           208:        for (i = 0; i < UPAGES; i++) {
        !           209:                map[i] = p->p_addr[i];
        !           210:                *(int *)(p->p_addr + i) |= PG_URKW | PG_V;
        !           211:        }
        !           212:        setredzone(p->p_addr, (caddr_t)0);
        !           213:        vmaccess(map, (caddr_t)newu, UPAGES);
        !           214:        /*
        !           215:         * New u.'s come from forking or inswap.
        !           216:         */
        !           217:        if (oldu) {
        !           218:                bcopy((caddr_t)oldu, (caddr_t)newu, UPAGES * NBPG);
        !           219:                newu->u_procp = p;
        !           220:        } else {        int tf = 0;
        !           221:                swap(p, p->p_swaddr, (caddr_t)0, ctob(UPAGES),
        !           222:                   B_READ, B_UAREA, swapdev, 0);
        !           223:                /*if (newu->u_pcb.pcb_ssp != -1 || newu->u_pcb.pcb_esp != -1 ||
        !           224:                    newu->u_tsize != p->p_tsize || newu->u_dsize != p->p_dsize ||
        !           225:                    newu->u_ssize != p->p_ssize || newu->u_procp != p)
        !           226:                        panic("vgetu");*/
        !           227:                if(newu->u_pcb.pcb_ssp != -1) tf |= 1;
        !           228:                if(newu->u_pcb.pcb_esp != -1) tf |= 2;
        !           229:                if(newu->u_tsize != p->p_tsize) tf |= 4;
        !           230:                if(newu->u_dsize != p->p_dsize) tf |= 8;
        !           231:                if(newu->u_ssize != p->p_ssize) tf |= 16;
        !           232:                if(newu->u_procp != p) tf |= 32;
        !           233:                if(tf) {
        !           234:                        printf("vgetu %d ", tf);
        !           235:                        panic("vgetu");
        !           236:                }
        !           237:        }
        !           238:        /*
        !           239:         * Initialize the pcb copies of the p0 and p1 region bases and
        !           240:         * software page table size from the information in the proc structure.
        !           241:         */
        !           242:        newu->u_pcb.pcb_p0br = p->p_p0br;
        !           243:        newu->u_pcb.pcb_p1br = p->p_p0br + p->p_szpt * NPTEPG - P1TOP;
        !           244:        newu->u_pcb.pcb_szpt = p->p_szpt;
        !           245:        return (1);
        !           246: }
        !           247: 
        !           248: /*
        !           249:  * Release swap space for a u. area.
        !           250:  */
        !           251: vrelswu(p)
        !           252:        struct proc *p;
        !           253: {
        !           254: 
        !           255:        rmfree(swapmap, ctod(vusize(p)), p->p_swaddr);
        !           256:        /* p->p_swaddr = 0; */  /* leave for post-mortems */
        !           257: }
        !           258: 
        !           259: /*
        !           260:  * Get swap space for a u. area.
        !           261:  */
        !           262: vgetswu(p)
        !           263:        struct proc *p;
        !           264: {
        !           265: 
        !           266:        p->p_swaddr = srmalloc(swapmap, ctod(vusize(p)));
        !           267:        return (p->p_swaddr);
        !           268: }
        !           269: 
        !           270: /*
        !           271:  * Release u. area, swapping it out if desired.
        !           272:  *
        !           273:  * Note: we run on the old u. after it is released into swtch(),
        !           274:  * and are safe because nothing can happen at interrupt time.
        !           275:  */
        !           276: vrelu(p, swapu)
        !           277:        register struct proc *p;
        !           278: {
        !           279:        register int i;
        !           280:        struct pte uu[UPAGES];
        !           281: 
        !           282:        if (swapu)
        !           283:                swap(p, p->p_swaddr, (caddr_t)0, ctob(UPAGES),
        !           284:                    B_WRITE, B_UAREA, swapdev, 0);
        !           285:        for (i = 0; i < UPAGES; i++)
        !           286:                uu[i] = p->p_addr[i];
        !           287:        (void) vmemfree(uu, clrnd(UPAGES));
        !           288: }
        !           289: 
        !           290: #ifdef unneeded
        !           291: int    ptforceswap;
        !           292: #endif
        !           293: /*
        !           294:  * Expand a page table, assigning new kernel virtual
        !           295:  * space and copying the page table entries over both
        !           296:  * in the system map and as necessary in the user page table space.
        !           297:  */
        !           298: ptexpand(change)
        !           299:        register int change;
        !           300: {
        !           301:        register struct pte *p1, *p2;
        !           302:        register int i;
        !           303:        register int spages, ss = P1TOP - mfpr(P1LR);
        !           304:        register int kold = btokmx((struct pte *)mfpr(P0BR));
        !           305:        int knew, tdpages;
        !           306:        int szpt = u.u_pcb.pcb_szpt;
        !           307:        int s;
        !           308: 
        !           309:        if (change <= 0 || change % CLSIZE)
        !           310:                panic("ptexpand 1");
        !           311:        /*
        !           312:         * Change is the number of new page table pages needed.
        !           313:         * Kold is the old index in the kernelmap of the page tables.
        !           314:         * Allocate a new kernel map segment of size szpt+change for
        !           315:         * the page tables, and the new page table pages in the
        !           316:         * middle of this new region.
        !           317:         */
        !           318: top:
        !           319:        if ((knew=rmalloc(kernelmap, szpt+change)) == 0)
        !           320:                goto bad;
        !           321:        spages = ss/NPTEPG;
        !           322:        tdpages = szpt - spages;
        !           323:        if (memall(&Usrptmap[knew+tdpages], change, u.u_procp, CSYS) == 0) {
        !           324:                kmfree(szpt+change, knew);
        !           325:                goto bad;
        !           326:        }
        !           327:        /*
        !           328:         * Spages pages of u.+stack page tables go over unchanged.
        !           329:         * Tdpages of text+data page table may contain a few stack
        !           330:         * pages which need to go in one of the newly allocated pages;
        !           331:         * this is a rough cut.
        !           332:         */
        !           333:        kmcopy(knew, kold, tdpages);
        !           334:        kmcopy(knew+tdpages+change, kold+tdpages, spages);
        !           335: 
        !           336:        /*
        !           337:         * Validate and clear the newly allocated page table pages in the
        !           338:         * center of the new region of the kernelmap.
        !           339:         * Then flush translation since we changed
        !           340:         * the kernel page tables.
        !           341:         */
        !           342:        i = knew + tdpages;
        !           343:        p1 = &Usrptmap[i];
        !           344:        p2 = p1 + change;
        !           345:        while (p1 < p2) {
        !           346:                *(int *)p1 |= PG_V | PG_KW;
        !           347:                clearseg(p1->pg_pfnum);
        !           348:                p1++;
        !           349:                i++;
        !           350:        }
        !           351:        mtpr(TBIA, 0);
        !           352: 
        !           353:        /*
        !           354:         * Move the stack or u. pte's which are before the newly
        !           355:         * allocated pages into the last of the newly allocated pages.
        !           356:         * They are taken from the end of the current p1 region,
        !           357:         * and moved to the end of the new p1 region.  There are
        !           358:         * ss % NPTEPG such pte's.
        !           359:         */
        !           360:        p1 = (struct pte *)mfpr(P1BR) + mfpr(P1LR);
        !           361:        p2 = kmxtob(knew+szpt+change) - ss;
        !           362:        for (i = ss - NPTEPG*spages; i != 0; i--)
        !           363:                *p2++ = *p1++;
        !           364: 
        !           365:        /*
        !           366:         * Now switch to the new page tables.
        !           367:         */
        !           368:        mtpr(TBIA, 0);  /* paranoid */
        !           369:        s = spl7();     /* conservative */
        !           370:        u.u_procp->p_p0br = kmxtob(knew);
        !           371:        u.u_pcb.pcb_p0br = kmxtob(knew);
        !           372:        u.u_pcb.pcb_p1br = kmxtob(knew+szpt+change) - P1TOP;
        !           373:        u.u_pcb.pcb_szpt += change;
        !           374:        u.u_procp->p_szpt += change;
        !           375:        u.u_procp->p_addr = uaddr(u.u_procp);
        !           376:        mtpr(P0BR, u.u_procp->p_p0br);
        !           377:        mtpr(P1BR, u.u_pcb.pcb_p1br);
        !           378:        mtpr(TBIA, 0);
        !           379:        splx(s);
        !           380: 
        !           381:        /*
        !           382:         * Finally, free old kernelmap.
        !           383:         */
        !           384:        if (szpt)
        !           385:                kmfree(szpt, kold);
        !           386:        return;
        !           387: 
        !           388: bad:
        !           389:        /*
        !           390:         * Swap out the process so that the unavailable 
        !           391:         * resource will be allocated upon swapin.
        !           392:         *
        !           393:         * When resume is executed for the process, 
        !           394:         * here is where it will resume.
        !           395:         */
        !           396:        resume(pcbb(u.u_procp));
        !           397:        if (savectx(u.u_ssav))
        !           398:                return;
        !           399:        if (swapout(u.u_procp, (clicks_t)(mfpr(P0LR) - u.u_tsize), ss - UPAGES) == 0) {
        !           400:                /*
        !           401:                 * No space to swap... it is inconvenient to try
        !           402:                 * to exit, so just wait a bit and hope something
        !           403:                 * turns up.  Could deadlock here.
        !           404:                 *
        !           405:                 * SOMEDAY REFLECT ERROR BACK THROUGH expand TO CALLERS
        !           406:                 * (grow, sbreak) SO CAN'T DEADLOCK HERE.
        !           407:                 */
        !           408: printf(":");
        !           409:                sleep((caddr_t)&lbolt, PRIBIO);
        !           410:                goto top;
        !           411:        }
        !           412:        /*
        !           413:         * Set SSWAP bit, so that when process is swapped back in
        !           414:         * swapin will set u.u_pcb.pcb_sswap to u_sswap and force a
        !           415:         * return from the setjmp() above.
        !           416:         */
        !           417:        u.u_procp->p_flag |= SSWAP;
        !           418:        swtch();
        !           419:        /* no return */
        !           420: }
        !           421: 
        !           422: kmcopy(to, from, count)
        !           423:        register int to;
        !           424:        int from;
        !           425:        register int count;
        !           426: {
        !           427:        register struct pte *tp = &Usrptmap[to];
        !           428:        register struct pte *fp = &Usrptmap[from];
        !           429: 
        !           430:        while (count != 0) {
        !           431:                *tp++ = *fp++;
        !           432:                to++;
        !           433:                count--;
        !           434:        }
        !           435: }
        !           436: 
        !           437: kmfree(addr, size)
        !           438: int addr, size;
        !           439: {
        !           440:        rmfree(kernelmap, addr, size);
        !           441:        if (kmapwnt) {
        !           442:                kmapwnt = 0;
        !           443:                wakeup((caddr_t)kernelmap);
        !           444:        }
        !           445: }
        !           446: 
        !           447: #if NOTDEF
        !           448: /* who calls this?? */
        !           449: /*
        !           450:  * Change protection codes of text segment.
        !           451:  * Have to flush translation buffer since this
        !           452:  * affect virtual memory mapping of current process.
        !           453:  */
        !           454: chgprot(p, addr, tprot)
        !           455:        struct proc *p;
        !           456:        caddr_t addr;
        !           457:        long tprot;
        !           458: {
        !           459:        unsigned v;
        !           460:        int tp;
        !           461:        register struct pte *pte;
        !           462:        register struct cmap *c;
        !           463: 
        !           464:        v = clbase(btop(addr));
        !           465:        if (!isatsv(p, v)) {
        !           466:                u.u_error = EFAULT;
        !           467:                return (0);
        !           468:        }
        !           469:        tp = vtotp(p, v);
        !           470:        pte = tptopte(p, tp);
        !           471:        if (pte->pg_fod == 0 && pte->pg_pfnum) {
        !           472:                c = &cmap[pgtocm(pte->pg_pfnum)];
        !           473:                if (c->c_blkno && c->c_mdev != MSWAPX)
        !           474:                        munhash(c->c_mdev, (daddr_t)c->c_blkno);
        !           475:        }
        !           476:        *(int *)pte &= ~PG_PROT;
        !           477:        *(int *)pte |= tprot;
        !           478:        distcl(pte);
        !           479:        tbiscl(v);
        !           480:        return (1);
        !           481: }
        !           482: #endif
        !           483: 
        !           484: settprot(okwrit)
        !           485:        int okwrit;
        !           486: {
        !           487:        register int *ptaddr, i, prot;
        !           488: 
        !           489:        prot = okwrit ? PG_UW : PG_URKR;
        !           490:        ptaddr = (int *)mfpr(P0BR);
        !           491:        for (i = 0; i < u.u_tsize; i++) {
        !           492:                ptaddr[i] &= ~PG_PROT;
        !           493:                ptaddr[i] |= prot;
        !           494:        }
        !           495:        mtpr(TBIA, 0);
        !           496: }

unix.superglobalmegacorp.com

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