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

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution is only permitted until one year after the first shipment
                      6:  * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
                      7:  * binary forms are permitted provided that: (1) source distributions retain
                      8:  * this entire copyright notice and comment, and (2) distributions including
                      9:  * binaries display the following acknowledgement:  This product includes
                     10:  * software developed by the University of California, Berkeley and its
                     11:  * contributors'' in the documentation or other materials provided with the
                     12:  * distribution and in all advertising materials mentioning features or use
                     13:  * of this software.  Neither the name of the University nor the names of
                     14:  * its contributors may be used to endorse or promote products derived from
                     15:  * this software without specific prior written permission.
                     16:  * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     17:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     18:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     19:  *
                     20:  *     @(#)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.