Annotation of cci/sys/tahoe/vm_machdep.c, revision 1.1.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.