Annotation of cci/sys/tahoe/vm_machdep.c, revision 1.1

1.1     ! root        1: /*     vm_machdep.c    6.1     83/07/29        */
        !             2: 
        !             3: #include "../machine/pte.h"
        !             4: 
        !             5: #include "../h/param.h"
        !             6: #include "../h/systm.h"
        !             7: #include "../h/dir.h"
        !             8: #include "../h/user.h"
        !             9: #include "../h/proc.h"
        !            10: #include "../h/cmap.h"
        !            11: #include "../h/mount.h"
        !            12: #include "../h/vm.h"
        !            13: #include "../h/text.h"
        !            14: 
        !            15: #include "../machine/mtpr.h"
        !            16: 
        !            17: /*
        !            18:  * Set a red zone in the kernel stack after the u. area.
        !            19:  */
        !            20: setredzone(pte, vaddr)
        !            21:        register struct pte *pte;
        !            22:        caddr_t vaddr;
        !            23: {
        !            24: 
        !            25:        pte += (sizeof (struct user) + NBPG - 1) / NBPG;
        !            26:        *(int *)pte &= ~PG_PROT;
        !            27:        *(int *)pte |= PG_URKR;
        !            28:        if (vaddr)
        !            29:                mtpr(vaddr + sizeof (struct user) + NBPG - 1, TBIS);
        !            30: }
        !            31: 
        !            32: #ifndef mapin
        !            33: mapin(pte, v, pfnum, count, prot)
        !            34:        struct pte *pte;
        !            35:        u_int v, pfnum;
        !            36:        int count, prot;
        !            37: {
        !            38: 
        !            39:        while (count > 0) {
        !            40:                *(int *)pte++ = pfnum | prot;
        !            41:                mtpr(ptob(v), TBIS);
        !            42:                v++;
        !            43:                pfnum++;
        !            44:                count--;
        !            45:        }
        !            46: }
        !            47: #endif
        !            48: 
        !            49: #ifdef notdef
        !            50: /*ARGSUSED*/
        !            51: mapout(pte, size)
        !            52:        register struct pte *pte;
        !            53:        int size;
        !            54: {
        !            55: 
        !            56:        panic("mapout");
        !            57: }
        !            58: #endif
        !            59: 
        !            60: /*
        !            61:  * Check for valid program size
        !            62:  */
        !            63: chksize(ts, ds, ss)
        !            64:        register unsigned ts, ds, ss;
        !            65: {
        !            66:        static int maxdmap = 0;
        !            67: 
        !            68:        if (ts > MAXTSIZ || ds > MAXDSIZ || ss > MAXSSIZ) {
        !            69:                u.u_error = ENOMEM;
        !            70:                return (1);
        !            71:        }
        !            72:        /* check for swap map overflow */
        !            73:        if (maxdmap == 0) {
        !            74:                register int i, blk;
        !            75: 
        !            76:                blk = dmmin;
        !            77:                for (i = 0; i < NDMAP; i++) {
        !            78:                        maxdmap += blk;
        !            79:                        if (blk < dmmax)
        !            80:                                blk *= 2;
        !            81:                }
        !            82:        }
        !            83:        if (ctod(ts) > NXDAD * dmtext ||
        !            84:            ctod(ds) > maxdmap || ctod(ss) > maxdmap) {
        !            85:                u.u_error = ENOMEM;
        !            86:                return (1);
        !            87:        }
        !            88:        /*
        !            89:         * Make sure the process isn't bigger than our
        !            90:         * virtual memory limit.
        !            91:         *
        !            92:         * THERE SHOULD BE A CONSTANT FOR THIS.
        !            93:         */
        !            94:        if (ts + ds + ss + LOWPAGES + HIGHPAGES > btoc(USRSTACK)) {
        !            95:                u.u_error = ENOMEM;
        !            96:                return (1);
        !            97:        }
        !            98:        return (0);
        !            99: }
        !           100: 
        !           101: /*ARGSUSED*/
        !           102: newptes(pte, v, size)
        !           103:        register struct pte *pte;
        !           104:        u_int v;
        !           105:        register int size;
        !           106: {
        !           107:        register caddr_t a = ptob(v);
        !           108: 
        !           109: #ifdef lint
        !           110:        pte = pte;
        !           111: #endif
        !           112:        if (size >= 8) {
        !           113:                mtpr(0, TBIA);
        !           114:                return;
        !           115:        }
        !           116:        while (size > 0) {
        !           117:                mtpr(a, TBIS);
        !           118:                a += NBPG;
        !           119:                size--;
        !           120:        }
        !           121: }
        !           122: 
        !           123: /*
        !           124:  * Change protection codes of text segment.
        !           125:  * Have to flush translation buffer since this
        !           126:  * affect virtual memory mapping of current process.
        !           127:  */
        !           128: chgprot(addr, tprot)
        !           129:        caddr_t addr;
        !           130:        long tprot;
        !           131: {
        !           132:        unsigned v;
        !           133:        int tp;
        !           134:        register struct pte *pte;
        !           135:        register struct cmap *c;
        !           136: 
        !           137:        v = clbase(btop(addr));
        !           138:        if (!isatsv(u.u_procp, v)) {
        !           139:                u.u_error = EFAULT;
        !           140:                return (0);
        !           141:        }
        !           142:        tp = vtotp(u.u_procp, v);
        !           143:        pte = tptopte(u.u_procp, tp);
        !           144:        if (pte->pg_fod == 0 && pte->pg_pfnum) {
        !           145:                c = &cmap[pgtocm(pte->pg_pfnum)];
        !           146:                if (c->c_blkno && c->c_mdev != MSWAPX)
        !           147:                        munhash(mount[c->c_mdev].m_dev,
        !           148:                            (daddr_t)(u_long)c->c_blkno);
        !           149:        }
        !           150:        *(int *)pte &= ~PG_PROT;
        !           151:        *(int *)pte |= tprot;
        !           152:        distcl(pte);
        !           153:        tbiscl(v);
        !           154:        return (1);
        !           155: }
        !           156: 
        !           157: settprot(tprot)
        !           158:        long tprot;
        !           159: {
        !           160:        register int *ptaddr, i;
        !           161: 
        !           162:        ptaddr = (int *)mfpr(P0BR);
        !           163:        for (i = 0; i < u.u_tsize; i++) {
        !           164:                ptaddr[i] &= ~PG_PROT;
        !           165:                ptaddr[i] |= tprot;
        !           166:        }
        !           167:        mtpr(0, TBIA);
        !           168: }
        !           169: 
        !           170: /*
        !           171:  * Rest are machine-dependent
        !           172:  */
        !           173: 
        !           174: getmemc(addr)
        !           175:        caddr_t addr;
        !           176: {
        !           177:        register int c;
        !           178:        struct pte savemap;
        !           179: 
        !           180:        savemap = mmap[0];
        !           181:        *(int *)mmap = PG_V | PG_KR | btop(addr);
        !           182:        mtpr(vmmap, TBIS);
        !           183:        uncache (&vmmap[(int)addr & PGOFSET]);
        !           184:        c = *(char *)&vmmap[(int)addr & PGOFSET];
        !           185:        mmap[0] = savemap;
        !           186:        mtpr(vmmap, TBIS);
        !           187:        return (c & 0377);
        !           188: }
        !           189: 
        !           190: putmemc(addr, val)
        !           191:        caddr_t addr;
        !           192: {
        !           193:        struct pte savemap;
        !           194: 
        !           195:        savemap = mmap[0];
        !           196:        *(int *)mmap = PG_V | PG_KW | btop(addr);
        !           197:        mtpr(vmmap, TBIS);
        !           198:        *(char *)&vmmap[(int)addr & PGOFSET] = val;
        !           199: 
        !           200:        mtpr (0, PADC);
        !           201:        mtpr (0, PACC);
        !           202: 
        !           203:        mmap[0] = savemap;
        !           204:        mtpr(vmmap, TBIS);
        !           205: }
        !           206: 
        !           207: /*
        !           208:  * Move pages from one kernel virtual address to another.
        !           209:  * Both addresses are assumed to reside in the Sysmap,
        !           210:  * and size must be a multiple of CLSIZE.
        !           211:  */
        !           212: pagemove(from, to, size)
        !           213:        register caddr_t from, to;
        !           214:        int size;
        !           215: {
        !           216:        register struct pte *fpte, *tpte;
        !           217: 
        !           218:        if (size % CLBYTES)
        !           219:                panic("pagemove");
        !           220:        fpte = &Sysmap[btop(from - 0xC0000000)];
        !           221:        tpte = &Sysmap[btop(to - 0xC0000000)];
        !           222:        while (size > 0) {
        !           223:                *tpte++ = *fpte;
        !           224:                *(int *)fpte++ = 0;
        !           225:                mtpr(from, TBIS);
        !           226:                mtpr(to, TBIS);
        !           227:                mtpr(to, P1DC);         /* purge !! */
        !           228:                from += NBPG;
        !           229:                to += NBPG;
        !           230:                size -= NBPG;
        !           231:        }
        !           232: }
        !           233: 
        !           234: /*
        !           235:  * Some code and data key management routines.
        !           236:  * The arrays ckey_cnt and ckey_cache are allways kept in such a way
        !           237:  *     that the following invariant holds:
        !           238:  *     (ckey_cnt > 0) ==> (ckey_cache == 1)
        !           239:  * meaning as long as a code key is used by at least one process, it's
        !           240:  * marked as being 'in the cache'. Of course, the following invariant
        !           241:  * also holds:
        !           242:  *     (ckey_cache==0) ==> (ckey_cnt==0)
        !           243:  * which is just the reciprocal of the 1'st invariant.
        !           244:  * Equivalent invariants hold for the data key arrays.
        !           245:  */
        !           246: 
        !           247: 
        !           248: int    dbg_gck,
        !           249:        dbg_gck1,
        !           250:        dbg_gck2,
        !           251:        dbg_gck3,
        !           252:        dbg_gck4,
        !           253:        dbg_gdk,
        !           254:        dbg_gdk1,
        !           255:        dbg_gdk2,
        !           256:        dbg_gdk3;
        !           257: 
        !           258: /* 
        !           259:  * ckeyrelease -- release a code key.
        !           260:  */
        !           261: ckeyrelease (key)
        !           262: int    key;
        !           263: {
        !           264:        register int ipl;
        !           265: 
        !           266:        ipl = spl8();
        !           267:        if (--ckey_cnt[key] < 0) {
        !           268:                printf ("ckeyrelease: key = %d\n", key);
        !           269:                ckey_cnt[key] = 0;
        !           270:        }
        !           271:        splx (ipl);
        !           272: }
        !           273: 
        !           274: 
        !           275: /* 
        !           276:  * dkeyrelease -- release a data key.
        !           277:  */
        !           278: dkeyrelease (key)
        !           279: int    key;
        !           280: {
        !           281:        register int ipl;
        !           282: 
        !           283:        ipl = spl8();
        !           284:        if (--dkey_cnt[key] != 0) {
        !           285:                printf ("dkeyrelease: key = %d\n", key);
        !           286:                dkey_cnt[key] = 0;
        !           287:        }
        !           288:        splx (ipl);     
        !           289: }
        !           290: 
        !           291: 
        !           292: /* 
        !           293:  * getcodekey -- get a code key.
        !           294:  */
        !           295: getcodekey()
        !           296: {
        !           297:        register int i,
        !           298:                ipl,
        !           299:                allocated,      /* number of non-zero ckey_cnt's */
        !           300:                shared_key,
        !           301:                return_key;
        !           302:        register struct proc *p;
        !           303: 
        !           304:        dbg_gck++;
        !           305: 
        !           306:        ipl = spl8();
        !           307:        allocated = 0;
        !           308: 
        !           309:        for (i = 1; i <= MAXCKEY; i++) {
        !           310:                if ((int) ckey_cache[i] == 0) {         /* Bingo */
        !           311:                        ckey_cache[i] = 1;
        !           312:                        ckey_cnt[i] = 1;
        !           313:                        splx (ipl);
        !           314:                        dbg_gck1++;
        !           315:                        return (i);
        !           316:                }
        !           317: 
        !           318:                if (ckey_cnt[i] != 0)
        !           319:                        allocated++;
        !           320:                if (ckey_cnt[i] > 1 && i != MAXCKEY)
        !           321:                        shared_key = i;
        !           322:        }
        !           323: 
        !           324:        /*
        !           325:         * If we are here, all code keys were marked as being in cache.
        !           326:         * Moreover, we are assured that 'shared_key' has a meaningful value,
        !           327:         * since we know that the 'init' process and the 'shell' are around
        !           328:         * and they have shared text!
        !           329:         *
        !           330:         * Two cases: some of them are free for re-allocation, or all of
        !           331:         * them are currently allocated. In this (second) case, a more
        !           332:         * drastic procedure will follow - i.e. we strip some processes of
        !           333:         * their keys and let them get new ones whenever they need it.
        !           334:         */
        !           335:        if (allocated < MAXCKEY) {
        !           336:                /*
        !           337:                 * This is the easy case.
        !           338:                 */
        !           339:                for (i = 1; i <= MAXCKEY; i++) {
        !           340:                        if (ckey_cnt[i] == 0) {
        !           341:                                ckey_cache[i] = 0;
        !           342:                                return_key = i;
        !           343:                        }
        !           344:                }
        !           345: 
        !           346:                ckey_cnt[return_key] = 1;
        !           347:                ckey_cache[return_key] = 1;
        !           348:                mtpr (0, PACC);
        !           349:                splx (ipl);
        !           350:                dbg_gck2++;
        !           351:                return (return_key);
        !           352:        }
        !           353: 
        !           354:        /*
        !           355:         * Now we have to get nasty.
        !           356:         * Strip some of them of the code key. First time,
        !           357:         * 1) Try hard not to do that to kernel processes !!
        !           358:         * 2) Try hard NOT to strip shared text processes of
        !           359:         *    their (shared) key, because then they'll run
        !           360:         *    with different keys from now on, i.e. less efficient
        !           361:         *    cache utilization.
        !           362:         */
        !           363:        for (p = proc; p < procNPROC; p++) {
        !           364:                /*
        !           365:                 * Look for a meaningful key but not
        !           366:                 * used and not shared text.
        !           367:                 */
        !           368:                if (p->p_ckey && p->p_ckey!=MAXCKEY && ckey_cnt[p->p_ckey]<2) {
        !           369:                        i = p->p_ckey;
        !           370:                        p->p_ckey = 0;
        !           371:                        ckey_cnt[i] = 1;
        !           372:                        ckey_cache[i] = 1;
        !           373:                        mtpr (0, PACC);
        !           374:                        splx (ipl);
        !           375:                        dbg_gck3++;
        !           376:                        return (i);
        !           377:                }
        !           378:        }
        !           379: 
        !           380:        /*
        !           381:         * Second time around!
        !           382:         * Highly unlikely situation. It means that all keys are
        !           383:         * allocated AND shared (i.e. we have at least 510 active
        !           384:         * processes).
        !           385:         * Strip some of them. We pick some key (known to be shared
        !           386:         * by several processes) and strip the poor process group.
        !           387:         * At least 2 processes will loose but we gain one key to be reused.
        !           388:         * The way 'shared_key' was produced (above) virtually assures
        !           389:         * us that this key isn't the 'init' group key (1) nor the
        !           390:         * 'shell' group key (2 or 3). It's probably something like 254.
        !           391:         * Could be more straightforward to strip all processes, but it's
        !           392:         * better to invest in one more loop here and keep the cache
        !           393:         * utilization to a maximum.
        !           394:         */
        !           395:        for (p = proc; p < procNPROC; p++) {
        !           396:                if (p->p_ckey == shared_key) {
        !           397:                        p->p_ckey = 0;
        !           398:                        ckey_cnt[shared_key]--;
        !           399:                }
        !           400:        }
        !           401: 
        !           402:        if (ckey_cnt[shared_key] != 0)
        !           403:                printf("getcodekey: key = %d cnt = %d\n",
        !           404:                        shared_key, ckey_cnt[shared_key]);
        !           405: 
        !           406:        ckey_cnt[shared_key] = 1;
        !           407:        ckey_cache[shared_key] = 1;
        !           408:        mtpr (0, PACC);
        !           409:        splx (ipl);
        !           410:        dbg_gck4++;
        !           411:        return (shared_key);
        !           412: }
        !           413: 
        !           414: 
        !           415: /* 
        !           416:  * getdatakey -- get a data key.
        !           417:  *
        !           418:  * General strategy:
        !           419:  * 1) Try to find a data key that isn't in the cache. Allocate it.
        !           420:  * 2) If all data keys are in the cache, find one which isn't
        !           421:  *    allocated. Clear all status and allocate this one.
        !           422:  * 3) If all of them are allocated, pick some process, strip him
        !           423:  *    of the data key and allocate it. We (cold-bloodedly) pick
        !           424:  *    one process to be the poor looser because that's the
        !           425:  *    easiest way to do it and because this extreme situation
        !           426:  *    ( >255 active processes ) is expected to be temporary,
        !           427:  *    after which 1) or 2) above should be the usual case.
        !           428:  * The poor looser is the first process which has a data key.
        !           429:  * However, we try to spare known kernel processes and daemons
        !           430:  * (fired at bootstrap time), by searching from proc[LOOSER] and on.
        !           431:  */
        !           432: getdatakey()
        !           433: {
        !           434:        register int i,
        !           435:                ipl,
        !           436:                allocated,      /* number of non-zero dkey_cnt's */
        !           437:                return_key;
        !           438:        register struct proc *p;
        !           439: 
        !           440: #define LOOSER 20
        !           441: 
        !           442:        dbg_gdk++;
        !           443:        
        !           444:        ipl = spl8();
        !           445:        allocated = 0;
        !           446:        for (i = 1; i <= MAXDKEY; i++) {
        !           447:                if ((int) dkey_cache[i] == 0) {
        !           448:                        /*
        !           449:                         * Case 1. The best case.
        !           450:                         */
        !           451:                        dkey_cache[i] = 1;
        !           452:                        dkey_cnt[i] = 1;
        !           453:                        splx (ipl);
        !           454:                        dbg_gdk1++;
        !           455:                        return (i);
        !           456:                }
        !           457:                if (dkey_cnt[i] > 0)
        !           458:                        allocated++;
        !           459:        }
        !           460: 
        !           461:        if (allocated < MAXDKEY) {
        !           462:                /*
        !           463:                 * Case 2. This is the easy case.
        !           464:                 */
        !           465:                for (i = 1; i <= MAXDKEY; i++) {
        !           466:                        if (dkey_cnt[i] == 0) {
        !           467:                                dkey_cache[i] = 0;
        !           468:                                return_key = i;
        !           469:                        }
        !           470:                }
        !           471: 
        !           472:                dkey_cnt[return_key] = 1;
        !           473:                dkey_cache[return_key] = 1;
        !           474:                mtpr (0, PADC);
        !           475:                splx (ipl);
        !           476:                dbg_gdk2++;
        !           477:                return (return_key);
        !           478:        }
        !           479: 
        !           480:        /*
        !           481:         * Now, we have to take a code from someone.
        !           482:         */
        !           483:        for (p = &proc[LOOSER]; p < procNPROC; p++) {
        !           484:                if (p->p_dkey != 0) {
        !           485:                        i = p->p_dkey;
        !           486:                        p->p_dkey = 0;
        !           487:                        dkey_cnt[i] = 1;
        !           488:                        dkey_cache[i] = 1;
        !           489:                        mtpr (0, PADC);
        !           490:                        splx (ipl);
        !           491:                        dbg_gdk3++;
        !           492:                        return (i);
        !           493:                }
        !           494:        }
        !           495: 
        !           496:        panic ("getdatakey");
        !           497: }
        !           498: 
        !           499: 
        !           500: /* General (includes system) virtual address to physical */
        !           501: vtoph(p, v)
        !           502: register struct proc *p;
        !           503: register unsigned v;
        !           504: {
        !           505:        register struct pte *thispte;
        !           506: 
        !           507:        thispte = vtopte (p, btop(v));
        !           508:        return ( (thispte->pg_pfnum << PGSHIFT) + (v & PGOFSET));
        !           509: }
        !           510:                

unix.superglobalmegacorp.com

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