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

unix.superglobalmegacorp.com

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