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

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution is only permitted until one year after the first shipment
        !             6:  * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
        !             7:  * binary forms are permitted provided that: (1) source distributions retain
        !             8:  * this entire copyright notice and comment, and (2) distributions including
        !             9:  * binaries display the following acknowledgement:  This product includes
        !            10:  * software developed by the University of California, Berkeley and its
        !            11:  * contributors'' in the documentation or other materials provided with the
        !            12:  * distribution and in all advertising materials mentioning features or use
        !            13:  * of this software.  Neither the name of the University nor the names of
        !            14:  * its contributors may be used to endorse or promote products derived from
        !            15:  * this software without specific prior written permission.
        !            16:  * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
        !            17:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
        !            18:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            19:  *
        !            20:  *     @(#)vm_pt.c     7.14 (Berkeley) 6/30/90
        !            21:  */
        !            22: #include "machine/pte.h"
        !            23: #include "machine/mtpr.h"
        !            24: 
        !            25: #include "param.h"
        !            26: #include "systm.h"
        !            27: #include "user.h"
        !            28: #include "proc.h"
        !            29: #include "map.h"
        !            30: #include "cmap.h"
        !            31: #include "vm.h"
        !            32: #include "buf.h"
        !            33: #include "text.h"
        !            34: #include "vnode.h"
        !            35: #include "kernel.h"
        !            36: 
        !            37: /*
        !            38:  * Get page tables for process p.  Allocator
        !            39:  * for memory is argument; process must be locked
        !            40:  * from swapping if vmemall is used; if memall is
        !            41:  * used, call will return w/o waiting for memory.
        !            42:  * In any case an error return results if no user
        !            43:  * page table space is available.
        !            44:  */
        !            45: vgetpt(p, pmemall)
        !            46:        register struct proc *p;
        !            47:        int (*pmemall)();
        !            48: {
        !            49:        register long a;
        !            50:        register int szpt = p->p_szpt;
        !            51: 
        !            52:        if (szpt == 0)
        !            53:                panic("vgetpt");
        !            54: #if defined(hp300) || defined(i386)
        !            55:        /*
        !            56:         * Allocate a single page segment/paage directory table as well
        !            57:         * as page tables.
        !            58:         */
        !            59:        szpt++;
        !            60: #endif
        !            61:        /*
        !            62:         * Allocate space in the kernel map for this process.
        !            63:         * Then allocate page table pages, and initialize the
        !            64:         * process' p0br and addr pointer to be the kernel
        !            65:         * virtual addresses of the base of the page tables and
        !            66:         * the pte for the process pcb (at the base of the u.).
        !            67:         */
        !            68:        a = rmalloc(kernelmap, (long)szpt);
        !            69:        if (a == 0)
        !            70:                return (0);
        !            71:        if ((*pmemall)(&Usrptmap[a], szpt, p, CSYS) == 0) {
        !            72:                rmfree(kernelmap, (long)szpt, a);
        !            73:                return (0);
        !            74:        }
        !            75:        p->p_p0br = kmxtob(a);
        !            76:        p->p_addr = uaddr(p);
        !            77:        /*
        !            78:         * Now validate the system page table entries for the
        !            79:         * user page table pages, flushing old translations
        !            80:         * for these kernel virtual addresses.  Clear the new
        !            81:         * page table pages for clean post-mortems.
        !            82:         */
        !            83:        vmaccess(&Usrptmap[a], (caddr_t)p->p_p0br, szpt);
        !            84:        bzero((caddr_t) p->p_p0br, (unsigned) (szpt * NBPG));
        !            85: #if defined(hp300)
        !            86:        /* cache inhibit page tables pages so HW set bits are always valid */
        !            87:        for (szpt = a + szpt - 1; szpt >= a; --szpt)
        !            88:                Usrptmap[szpt].pg_ci = 1;
        !            89:        initsegt(p);
        !            90: #endif
        !            91: #if defined(i386)
        !            92:        initpdt(p);
        !            93: #endif
        !            94:        return (1);
        !            95: }
        !            96: 
        !            97: /*
        !            98:  * Initialize text portion of page table.
        !            99:  */
        !           100: vinitpt(p)
        !           101:        struct proc *p;
        !           102: {
        !           103:        register struct text *xp;
        !           104:        register struct proc *q;
        !           105:        register struct pte *pte;
        !           106:        register int i;
        !           107:        struct pte proto;
        !           108: 
        !           109:        xp = p->p_textp;
        !           110:        if (xp == 0)
        !           111:                return;
        !           112:        pte = tptopte(p, 0);
        !           113:        /*
        !           114:         * If there is another instance of same text in core
        !           115:         * then just copy page tables from other process.
        !           116:         */
        !           117:        if (q = xp->x_caddr) {
        !           118:                bcopy((caddr_t)tptopte(q, 0), (caddr_t)pte,
        !           119:                    (unsigned) (sizeof(struct pte) * xp->x_size));
        !           120:                goto done;
        !           121:        }
        !           122:        if (xp->x_flag & XLOAD || (xp->x_flag & XPAGV) == 0) {
        !           123:                /*
        !           124:                 * Initialize text page tables, zfod if we are loading
        !           125:                 * the text now; unless the process is demand loaded,
        !           126:                 * this will suffice as the text will henceforth either be
        !           127:                 * read from a file or demand paged in.
        !           128:                 */
        !           129:                *(int *)&proto = PG_URKR;
        !           130:                if (xp->x_flag & XLOAD) {
        !           131:                        proto.pg_fod = 1;
        !           132:                        ((struct fpte *)&proto)->pg_fileno = PG_FZERO;
        !           133:                }
        !           134:                for (i = 0; i < xp->x_size; i++)
        !           135:                        *pte++ = proto;
        !           136:                if ((xp->x_flag & XPAGV) == 0)
        !           137:                        goto done;
        !           138:        }
        !           139:        /*
        !           140:         * Text is demand loaded.  If process is not loaded (i.e. being
        !           141:         * swapped in) then retrieve page tables from swap area.  Otherwise
        !           142:         * this is the first time and we must initialize the page tables
        !           143:         * from the blocks in the file system.
        !           144:         */
        !           145:        if (xp->x_flag & XLOAD)
        !           146:                vinifod(p, (struct fpte *)tptopte(p, 0), PG_FTEXT, xp->x_vptr,
        !           147:                    (daddr_t)1, xp->x_size);
        !           148:        else
        !           149:                (void) swap(p, xp->x_ptdaddr, (caddr_t)tptopte(p, 0),
        !           150:                    (int)(xp->x_size * sizeof (struct pte)), B_READ,
        !           151:                    B_PAGET, swapdev_vp, 0);
        !           152: done:
        !           153:        /*
        !           154:         * In the case where we are overlaying ourself with new page
        !           155:         * table entries, old user-space translations should be flushed.
        !           156:         */
        !           157:        if (p == u.u_procp)
        !           158:                newptes(tptopte(p, 0), tptov(p, 0), (int)xp->x_size);
        !           159:        else
        !           160:                p->p_flag |= SPTECHG;
        !           161: }
        !           162: 
        !           163: /*
        !           164:  * Update the page tables of all processes linked
        !           165:  * to a particular text segment, by distributing
        !           166:  * dpte to the the text page at virtual frame v.
        !           167:  *
        !           168:  * Note that invalidation in the translation buffer for
        !           169:  * the current process is the responsibility of the caller.
        !           170:  */
        !           171: distpte(xp, tp, dpte)
        !           172:        struct text *xp;
        !           173:        register unsigned tp;
        !           174:        register struct pte *dpte;
        !           175: {
        !           176:        register struct proc *p;
        !           177:        register struct pte *pte;
        !           178:        register int i;
        !           179: 
        !           180:        for (p = xp->x_caddr; p; p = p->p_xlink) {
        !           181:                pte = tptopte(p, tp);
        !           182:                p->p_flag |= SPTECHG;
        !           183:                if (pte != dpte)
        !           184:                        for (i = 0; i < CLSIZE; i++)
        !           185:                                pte[i] = dpte[i];
        !           186:        }
        !           187: }
        !           188: 
        !           189: /*
        !           190:  * Release page tables of process p.
        !           191:  */
        !           192: vrelpt(p)
        !           193:        register struct proc *p;
        !           194: {
        !           195:        register int a;
        !           196:        register int szpt = p->p_szpt;
        !           197: 
        !           198:        if (szpt == 0)
        !           199:                return;
        !           200:        a = btokmx(p->p_p0br);
        !           201: #if defined(hp300)
        !           202:        flushustp(initustp(p));
        !           203:        /* don't forget the segment table */
        !           204:        szpt++;
        !           205: #endif
        !           206: #if defined(i386)
        !           207:        /* don't forget the page directory table */
        !           208:        szpt++;
        !           209: #endif
        !           210:        (void) vmemfree(&Usrptmap[a], szpt);
        !           211:        rmfree(kernelmap, (long)szpt, (long)a);
        !           212: }
        !           213: 
        !           214: #define        Xu(a)   t = up->u_pcb.a; up->u_pcb.a = uq ->u_pcb.a; uq->u_pcb.a = t;
        !           215: #define        Xup(a)  tp = up->u_pcb.a; up->u_pcb.a = uq ->u_pcb.a; uq->u_pcb.a = tp;
        !           216: #define        Xp(a)   t = p->a; p->a = q->a; q->a = t;
        !           217: #define        Xpp(a)  tp = p->a; p->a = q->a; q->a = tp;
        !           218: 
        !           219: /*
        !           220:  * Pass the page tables of process p to process q.
        !           221:  * Used during vfork().  P and q are not symmetric;
        !           222:  * p is the giver and q the receiver; after calling vpasspt
        !           223:  * p will be ``cleaned out''.  Thus before vfork() we call vpasspt
        !           224:  * with the child as q and give it our resources; after vfork() we
        !           225:  * call vpasspt with the child as p to steal our resources back.
        !           226:  * We are cognizant of whether we are p or q because we have to
        !           227:  * be careful to keep our u. area and restore the other u. area from
        !           228:  * umap after we temporarily put our u. area in both p and q's page tables.
        !           229:  */
        !           230: vpasspt(p, q, up, uq, umap)
        !           231:        register struct proc *p, *q;
        !           232:        register struct user *up, *uq;
        !           233:        struct pte *umap;
        !           234: {
        !           235:        int t;
        !           236:        int s;
        !           237:        struct pte *tp;
        !           238:        register int i;
        !           239: 
        !           240:        s = splhigh();  /* conservative, and slightly paranoid */
        !           241:        Xu(pcb_szpt); Xu(pcb_p0lr); Xu(pcb_p1lr);
        !           242: #if defined(tahoe)
        !           243:        Xu(pcb_p2lr);
        !           244: #endif
        !           245:        Xup(pcb_p0br); Xup(pcb_p1br);
        !           246: #if defined(tahoe)
        !           247:        Xup(pcb_p2br);
        !           248: #endif
        !           249: #if defined(hp300)
        !           250:        Xu(pcb_ustp); Xu(pcb_flags);
        !           251: #endif
        !           252: #if defined(i386)
        !           253:        Xu(pcb_cr3); Xu(pcb_flags);
        !           254: #endif
        !           255: 
        !           256:        /*
        !           257:         * The u. area is contained in the process' p1 region.
        !           258:         * Thus we map the current u. area into the process virtual space
        !           259:         * of both sets of page tables we will deal with so that it
        !           260:         * will stay with us as we rearrange memory management.
        !           261:         */
        !           262:        for (i = 0; i < UPAGES; i++)
        !           263:                if (up == &u)
        !           264:                        q->p_addr[i] = p->p_addr[i];
        !           265:                else
        !           266:                        p->p_addr[i] = q->p_addr[i];
        !           267: #if defined(vax) || defined(tahoe)
        !           268:        mtpr(TBIA, 0);
        !           269: #endif
        !           270:        /*
        !           271:         * Now have u. double mapped, and have flushed
        !           272:         * any stale translations to new u. area.
        !           273:         * Switch the page tables.
        !           274:         */
        !           275:        Xpp(p_p0br); Xp(p_szpt); Xpp(p_addr);
        !           276: #if defined(vax) || defined(tahoe)
        !           277:        mtpr(P0BR, u.u_pcb.pcb_p0br);
        !           278: #if defined(vax)
        !           279:        mtpr(P0LR, u.u_pcb.pcb_p0lr &~ AST_CLR);
        !           280: #else
        !           281:        mtpr(P0LR, u.u_pcb.pcb_p0lr);
        !           282: #endif
        !           283:        mtpr(P1BR, u.u_pcb.pcb_p1br);
        !           284:        mtpr(P1LR, u.u_pcb.pcb_p1lr);
        !           285: #if defined(tahoe)
        !           286:        mtpr(P2BR, u.u_pcb.pcb_p2br);
        !           287:        mtpr(P2LR, u.u_pcb.pcb_p2lr);
        !           288: #endif
        !           289: #endif
        !           290: #if defined(hp300)
        !           291:        loadustp(u.u_pcb.pcb_ustp);
        !           292: #endif
        !           293: #if defined(i386)
        !           294:        load_cr3(u.u_pcb.pcb_cr3);
        !           295: #endif
        !           296:        /*
        !           297:         * Now running on the ``other'' set of page tables.
        !           298:         * Flush translation to insure that we get correct u.
        !           299:         * Resurrect the u. for the other process in the other
        !           300:         * (our old) set of page tables.  Thus the other u. has moved
        !           301:         * from its old (our current) set of page tables to our old
        !           302:         * (its current) set of page tables, while we have kept our
        !           303:         * u. by mapping it into the other page table and then keeping
        !           304:         * the other page table.
        !           305:         */
        !           306: #if defined(vax) || defined(tahoe)
        !           307:        mtpr(TBIA, 0);
        !           308: #endif
        !           309:        for (i = 0; i < UPAGES; i++) {
        !           310:                int pf;
        !           311:                struct pte *pte;
        !           312:                if (up == &u) {
        !           313:                        pf = umap[i].pg_pfnum;
        !           314:                        pte = &q->p_addr[i];
        !           315:                        pte->pg_pfnum = pf;
        !           316:                } else {
        !           317:                        pf = umap[i].pg_pfnum;
        !           318:                        pte = &p->p_addr[i];
        !           319:                        pte->pg_pfnum = pf;
        !           320:                }
        !           321:        }
        !           322: #if defined(vax) || defined(tahoe)
        !           323:        mtpr(TBIA, 0);
        !           324: #endif
        !           325: #if defined(hp300)
        !           326:        TBIA();
        !           327: #endif
        !           328: #if defined(i386)
        !           329:        tlbflush();
        !           330: #endif
        !           331:        splx(s);
        !           332: }
        !           333: 
        !           334: /*
        !           335:  * Compute number of pages to be allocated to the u. area
        !           336:  * and data and stack area page tables, which are stored on the
        !           337:  * disk immediately after the u. area.
        !           338:  */
        !           339: /*ARGSUSED*/
        !           340: vusize(p, utl)
        !           341:        register struct proc *p;
        !           342:        struct user *utl;
        !           343: {
        !           344:        register int tsz = p->p_tsize / NPTEPG;
        !           345: 
        !           346:        /*
        !           347:         * We do not need page table space on the disk for page
        !           348:         * table pages wholly containing text.  This is well
        !           349:         * understood in the code in vmswap.c.
        !           350:         */
        !           351:        return (clrnd(UPAGES + ptsize(p) - tsz));
        !           352: }
        !           353: 
        !           354: /*
        !           355:  * Get u area for process p.  If a old u area is given,
        !           356:  * then copy the new area from the old, else
        !           357:  * swap in as specified in the proc structure.
        !           358:  *
        !           359:  * Since argument map/newu is potentially shared
        !           360:  * when an old u. is provided we have to be careful not
        !           361:  * to block after beginning to use them in this case.
        !           362:  * (This is not true when called from swapin() with no old u.)
        !           363:  */
        !           364: vgetu(p, palloc, map, newu, oldu)
        !           365:        register struct proc *p;
        !           366:        int (*palloc)();
        !           367:        register struct pte *map;
        !           368:        register struct user *newu;
        !           369:        struct user *oldu;
        !           370: {
        !           371:        register int i;
        !           372: 
        !           373:        if ((*palloc)(p->p_addr, clrnd(UPAGES), p, CSYS) == 0)
        !           374:                return (0);
        !           375:        /*
        !           376:         * New u. pages are to be accessible in map/newu as well
        !           377:         * as in process p's virtual memory.
        !           378:         */
        !           379:        for (i = 0; i < UPAGES; i++) {
        !           380:                map[i] = p->p_addr[i];
        !           381:                *(int *)(p->p_addr + i) |= PG_URKW | PG_V;
        !           382:        }
        !           383:        setredzone(p->p_addr, (caddr_t)0);
        !           384:        vmaccess(map, (caddr_t)newu, UPAGES);
        !           385:        /*
        !           386:         * New u.'s come from forking or inswap.
        !           387:         */
        !           388:        if (oldu) {
        !           389:                bcopy((caddr_t)oldu, (caddr_t)newu, (unsigned) UPAGES * NBPG);
        !           390:                newu->u_procp = p;
        !           391:        } else {
        !           392: #if defined(vax) || defined(hp300) || defined(i386)
        !           393:                (void) swap(p, p->p_swaddr, (caddr_t)0, ctob(UPAGES),
        !           394: #else
        !           395:                (void) swap(p, p->p_swaddr, (caddr_t)&u, ctob(UPAGES),
        !           396: #endif
        !           397:                   B_READ, B_UAREA, swapdev_vp, 0);
        !           398:                if (
        !           399: #if defined(vax)
        !           400:                    newu->u_pcb.pcb_ssp != -1 || newu->u_pcb.pcb_esp != -1 ||
        !           401: #endif
        !           402:                    newu->u_tsize != p->p_tsize || newu->u_dsize != p->p_dsize ||
        !           403:                    newu->u_ssize != p->p_ssize || newu->u_procp != p)
        !           404:                        panic("vgetu");
        !           405:        }
        !           406:        /*
        !           407:         * Initialize the pcb copies of the p0 and p1 region bases and
        !           408:         * software page table size from the information in the proc structure.
        !           409:         */
        !           410:        newu->u_pcb.pcb_p0br = p->p_p0br;
        !           411: #if defined(vax)
        !           412:        newu->u_pcb.pcb_p1br = initp1br(p->p_p0br + p->p_szpt * NPTEPG);
        !           413: #endif
        !           414: #if defined(tahoe)
        !           415:        newu->u_pcb.pcb_p2br = initp2br(p->p_p0br + p->p_szpt * NPTEPG);
        !           416: #endif
        !           417: #if defined(hp300)
        !           418:        newu->u_pcb.pcb_p1br = initp1br(p->p_p0br + p->p_szpt * NPTEPG);
        !           419:        newu->u_pcb.pcb_ustp = initustp(p);
        !           420: #endif
        !           421: #if defined(i386)
        !           422:        newu->u_pcb.pcb_p1br = initp1br(p->p_p0br + p->p_szpt * NPTEPG);
        !           423:        newu->u_pcb.pcb_cr3 = initpdt(p);
        !           424: #endif
        !           425:        newu->u_pcb.pcb_szpt = p->p_szpt;
        !           426:        return (1);
        !           427: }
        !           428: 
        !           429: /*
        !           430:  * Release swap space for a u. area.
        !           431:  */
        !           432: vrelswu(p, utl)
        !           433:        struct proc *p;
        !           434:        struct user *utl;
        !           435: {
        !           436: 
        !           437:        rmfree(swapmap, (long)ctod(vusize(p, utl)), p->p_swaddr);
        !           438:        /* p->p_swaddr = 0; */  /* leave for post-mortems */
        !           439: }
        !           440: 
        !           441: /*
        !           442:  * Get swap space for a u. area.
        !           443:  */
        !           444: vgetswu(p, utl)
        !           445:        struct proc *p;
        !           446:        struct user *utl;
        !           447: {
        !           448: 
        !           449:        p->p_swaddr = rmalloc(swapmap, (long)ctod(vusize(p, utl)));
        !           450:        return (p->p_swaddr);
        !           451: }
        !           452: 
        !           453: /*
        !           454:  * Release u. area, swapping it out if desired.
        !           455:  */
        !           456: vrelu(p, swapu)
        !           457:        register struct proc *p;
        !           458: {
        !           459:        register int i;
        !           460:        struct pte uu[UPAGES];
        !           461: 
        !           462:        if (swapu)
        !           463: #if defined(vax) || defined(hp300) || defined(i386)
        !           464:                (void) swap(p, p->p_swaddr, (caddr_t)0, ctob(UPAGES),
        !           465: #else
        !           466:                (void) swap(p, p->p_swaddr, (caddr_t)&u, ctob(UPAGES),
        !           467: #endif
        !           468:                    B_WRITE, B_UAREA, swapdev_vp, 0);
        !           469:        for (i = 0; i < UPAGES; i++)
        !           470:                uu[i] = p->p_addr[i];
        !           471:        /*
        !           472:         * If freeing the user structure and kernel stack
        !           473:         * for the current process, have to run a bit longer
        !           474:         * using the pages which have already been freed...
        !           475:         * block memory allocation from the network by raising ipl.
        !           476:         */
        !           477:        if (p == u.u_procp)
        !           478:                (void) splimp();                /* XXX */
        !           479:        (void) vmemfree(uu, clrnd(UPAGES));
        !           480: }
        !           481: 
        !           482: #ifdef DIAGNOSTIC
        !           483: int    ptforceswap;
        !           484: #endif
        !           485: /*
        !           486:  * Expand a page table, assigning new kernel virtual
        !           487:  * space and copying the page table entries over both
        !           488:  * in the system map and as necessary in the user page table space.
        !           489:  * IMPORTANT NOTE:
        !           490:  *
        !           491:  * On the HPs, excess PTEs will *always* be zero.  This is critical
        !           492:  * since we don't have length registers.  We guarentee this for
        !           493:  * expansion here by zeroing new PT pages, and for shrinking in
        !           494:  * setptlr() which zeroes excess PTEs.
        !           495:  *
        !           496:  * On the VAX and TAHOE, the state of excess PTEs is less important
        !           497:  * as the length registers dictate the actual bounds.  As a result
        !           498:  * the state of these PTEs is random.  New pages are zeroed unless
        !           499:  * they come about due to a PT expansion swap in which case they
        !           500:  * have garbage.  Page table splitting (either here or as part of
        !           501:  * an expansion swap) can lead to duplicate PTEs.  When shrinking,
        !           502:  * expand() sets excess PTEs to PG_UW (not zero).
        !           503:  */
        !           504: ptexpand(change, ods, omms, oss)
        !           505:        register int change;
        !           506:        segsz_t ods, omms, oss;
        !           507: {
        !           508:        register struct pte *p1, *p2;
        !           509:        register int i;
        !           510: #if defined(vax) || defined(hp300) || defined(i386)
        !           511:        register int spages, ss = P1PAGES - u.u_pcb.pcb_p1lr;
        !           512: #endif
        !           513: #if defined(tahoe)
        !           514:        register int spages, ss = P2PAGES - u.u_pcb.pcb_p2lr;
        !           515: #endif
        !           516:        register int kold = btokmx(u.u_pcb.pcb_p0br);
        !           517:        int knew, tdpages;
        !           518:        int szpt = u.u_pcb.pcb_szpt;
        !           519:        caddr_t a;
        !           520:        int s;
        !           521: 
        !           522:        if (change <= 0 || change % CLSIZE)
        !           523:                panic("ptexpand");
        !           524: #if defined(hp300) || defined(i386)
        !           525:        /*
        !           526:         * ++ to account for segment/page directory table.  We reallocate
        !           527:         * a segment table PTE so that it is virtually contiguous with
        !           528:         * the page tables.
        !           529:         * This way we can locate it relative to p_p0br (see initustp()).
        !           530:         * Reallocation also reduces fragmentation of Usrptmap.
        !           531:         */
        !           532:        szpt++;
        !           533: #endif
        !           534:        /*
        !           535:         * Change is the number of new page table pages needed.
        !           536:         * Kold is the old index in the kernelmap of the page tables.
        !           537:         * Allocate a new kernel map segment of size szpt+change for
        !           538:         * the page tables, and the new page table pages in the
        !           539:         * middle of this new region.
        !           540:         */
        !           541: top:
        !           542: #if defined(hp300) || defined(i386)
        !           543:        /*
        !           544:         * Consider segment/page directory table as part of stack ptes
        !           545:         * Note we use ctopt() since we don't pack page tables
        !           546:         */
        !           547:        spages = ctopt(ss) + 1;
        !           548: #else
        !           549:        spages = ss/NPTEPG;
        !           550: #endif
        !           551:        tdpages = szpt - spages;
        !           552: #ifdef DIAGNOSTIC
        !           553:        if (ptforceswap)
        !           554:                goto bad;
        !           555: #endif
        !           556:        if ((knew=rmalloc(kernelmap, (long)(szpt+change))) == 0)
        !           557:                goto bad;
        !           558:        if (memall(&Usrptmap[knew+tdpages], change, u.u_procp, CSYS) == 0) {
        !           559:                rmfree(kernelmap, (long)(szpt+change), (long)knew);
        !           560:                goto bad;
        !           561:        }
        !           562: 
        !           563:        /*
        !           564:         * Spages pages of u.+stack page tables go over unchanged.
        !           565:         * Tdpages of text+data page table may contain a few stack
        !           566:         * pages which need to go in one of the newly allocated pages;
        !           567:         * this is a rough cut.
        !           568:         *
        !           569:         * NOTE: The last statement is not true on HPs, text/data and
        !           570:         * stack are seperate page tables.  We really cannot "pack" page
        !           571:         * tables since we have no length register, and packing would
        !           572:         * result in some pages being accessible at two different addrs.
        !           573:         */
        !           574:        kmcopy(knew, kold, tdpages);
        !           575:        kmcopy(knew+tdpages+change, kold+tdpages, spages);
        !           576: 
        !           577:        /*
        !           578:         * Validate and clear the newly allocated page table pages in the
        !           579:         * center of the new region of the kernelmap.
        !           580:         */
        !           581:        i = knew + tdpages;
        !           582:        p1 = &Usrptmap[i];
        !           583:        a = (caddr_t) kmxtob(i);
        !           584:        p2 = p1 + change;
        !           585:        while (p1 < p2) {
        !           586: #if defined(hp300)
        !           587:                /* mapin is overkill */
        !           588:                *(u_int *)p1 |= PG_V|PG_KW|PG_CI;
        !           589: #else
        !           590:                mapin(p1, (u_int) a, p1->pg_pfnum, (int)(PG_V|PG_KW));
        !           591: #endif
        !           592:                bzero(a, NBPG);
        !           593:                a += NBPG;
        !           594:                p1++;
        !           595:        }
        !           596: 
        !           597: #if !defined(hp300) && !defined(i386)
        !           598:        /*
        !           599:         * Move the stack and u. pte's which are before the newly
        !           600:         * allocated pages into the last of the newly allocated pages.
        !           601:         * They are taken from the end of the current p1 region,
        !           602:         * and moved to the end of the new p1 region.
        !           603:         */
        !           604: #if defined(vax)
        !           605:        p1 = u.u_pcb.pcb_p1br + u.u_pcb.pcb_p1lr;
        !           606:        p2 = initp1br(kmxtob(knew+szpt+change)) + u.u_pcb.pcb_p1lr;
        !           607: #endif
        !           608: #if defined(tahoe)
        !           609:        p1 = u.u_pcb.pcb_p2br + u.u_pcb.pcb_p2lr;
        !           610:        p2 = initp2br(kmxtob(knew+szpt+change)) + u.u_pcb.pcb_p2lr;
        !           611: #endif
        !           612:        bcopy((caddr_t) p1, (caddr_t) p2,
        !           613:            (unsigned)((caddr_t)kmxtob(kold + tdpages) - (caddr_t)p1));
        !           614: #endif
        !           615: 
        !           616:        /*
        !           617:         * Now switch to the new page tables.
        !           618:         */
        !           619:        s = splhigh();  /* conservative */
        !           620:        u.u_procp->p_p0br = kmxtob(knew);
        !           621:        setp0br(u.u_procp->p_p0br);
        !           622: #if defined(vax)
        !           623:        u.u_pcb.pcb_p1br = initp1br(kmxtob(knew+szpt+change));
        !           624:        setp1br(u.u_pcb.pcb_p1br);
        !           625: #endif
        !           626: #if defined(tahoe)
        !           627:        u.u_pcb.pcb_p1br = kmxtob(knew);
        !           628:        setp1br(u.u_pcb.pcb_p1br);
        !           629:        u.u_pcb.pcb_p2br = initp2br(kmxtob(knew+szpt+change));
        !           630:        setp2br(u.u_pcb.pcb_p2br);
        !           631: #endif
        !           632: #if defined(hp300) || defined(i386)
        !           633:        u.u_pcb.pcb_p1br = initp1br(kmxtob(knew+szpt-1+change));
        !           634:        setp1br(u.u_pcb.pcb_p1br);
        !           635: #endif
        !           636:        u.u_pcb.pcb_szpt += change;
        !           637:        u.u_procp->p_szpt += change;
        !           638:        u.u_procp->p_addr = uaddr(u.u_procp);
        !           639: #if defined(vax) || defined(tahoe)
        !           640:        mtpr(TBIA, 0);
        !           641: #endif
        !           642: #if defined(hp300)
        !           643:        u.u_pcb.pcb_ustp = initustp(u.u_procp);
        !           644:        initsegt(u.u_procp);
        !           645:        TBIA();
        !           646: #endif
        !           647: #if defined(i386)
        !           648:        u.u_pcb.pcb_cr3 = initpdt(u.u_procp);
        !           649:        tlbflush();
        !           650: #endif
        !           651:        splx(s);
        !           652: 
        !           653:        /*
        !           654:         * Finally, free old kernelmap.
        !           655:         */
        !           656:        if (szpt)
        !           657:                rmfree(kernelmap, (long)szpt, (long)kold);
        !           658:        return;
        !           659: 
        !           660: bad:
        !           661:        /*
        !           662:         * Swap out the process so that the unavailable 
        !           663:         * resource will be allocated upon swapin.
        !           664:         *
        !           665:         * When resume is executed for the process, 
        !           666:         * here is where it will resume.
        !           667:         */
        !           668:        resume(pcbb(u.u_procp));
        !           669:        if (savectx(&u.u_ssave)) {
        !           670: #if defined(hp300) || defined(i386)
        !           671:                /*
        !           672:                 * New page table pages will contain garbage since
        !           673:                 * the page table was expanded on disk without the
        !           674:                 * new pages being zeroed.
        !           675:                 */
        !           676:                bzero((caddr_t)u.u_procp->p_p0br+tdpages*NBPG, change*NBPG);
        !           677: #endif
        !           678:                return;
        !           679:        }
        !           680:        if (swapout(u.u_procp, ods, omms, oss) == 0) {
        !           681:                /*
        !           682:                 * No space to swap... it is inconvenient to try
        !           683:                 * to exit, so just wait a bit and hope something
        !           684:                 * turns up.  Could deadlock here.
        !           685:                 *
        !           686:                 * SOMEDAY REFLECT ERROR BACK THROUGH expand TO CALLERS
        !           687:                 * (grow, sbreak) SO CAN'T DEADLOCK HERE.
        !           688:                 */
        !           689:                sleep((caddr_t)&lbolt, PRIBIO);
        !           690:                goto top;
        !           691:        }
        !           692:        /*
        !           693:         * Set SSWAP bit, so that when process is swapped back in
        !           694:         * swapin will set u.u_pcb.pcb_sswap to u_sswap and force a
        !           695:         * return from the savectx() above.
        !           696:         */
        !           697:        u.u_procp->p_flag |= SSWAP;
        !           698:        swtch();
        !           699:        /* NOTREACHED */
        !           700: }
        !           701: 
        !           702: kmcopy(to, from, count)
        !           703:        int to;
        !           704:        int from;
        !           705:        register int count;
        !           706: {
        !           707:        register struct pte *tp = &Usrptmap[to];
        !           708:        register struct pte *fp = &Usrptmap[from];
        !           709:        u_int a;
        !           710: 
        !           711:        a = (u_int) kmxtob(to);
        !           712:        while (count != 0) {
        !           713: #if defined(hp300)
        !           714:                mapin(tp, a, fp->pg_pfnum,
        !           715:                    (int)(*((int *)fp) & (PG_V|PG_PROT|PG_CI)));
        !           716: #else
        !           717:                mapin(tp, a, fp->pg_pfnum,
        !           718:                    (int)(*((int *)fp) & (PG_V|PG_PROT)));
        !           719: #endif
        !           720: #if defined(tahoe)
        !           721:                mtpr(P1DC, a);
        !           722: #endif
        !           723:                tp++;
        !           724:                fp++;
        !           725:                a += NBPG;
        !           726:                count--;
        !           727:        }
        !           728: }

unix.superglobalmegacorp.com

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