Annotation of 43BSDTahoe/sys/tahoe/vm_machdep.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1988 Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * This code is derived from software contributed to Berkeley by
        !             6:  * Computer Consoles Inc.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms are permitted
        !             9:  * provided that the above copyright notice and this paragraph are
        !            10:  * duplicated in all such forms and that any documentation,
        !            11:  * advertising materials, and other materials related to such
        !            12:  * distribution and use acknowledge that the software was developed
        !            13:  * by the University of California, Berkeley.  The name of the
        !            14:  * University may not be used to endorse or promote products derived
        !            15:  * from this software without specific prior written permission.
        !            16:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
        !            17:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
        !            18:  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            19:  *
        !            20:  *     @(#)vm_machdep.c        7.2 (Berkeley) 7/9/88
        !            21:  */
        !            22: 
        !            23: #include "param.h"
        !            24: #include "systm.h"
        !            25: #include "dir.h"
        !            26: #include "user.h"
        !            27: #include "proc.h"
        !            28: #include "cmap.h"
        !            29: #include "mount.h"
        !            30: #include "vm.h"
        !            31: #include "text.h"
        !            32: #include "kernel.h"
        !            33: 
        !            34: #include "pte.h"
        !            35: #include "cpu.h"
        !            36: #include "mtpr.h"
        !            37: 
        !            38: /*
        !            39:  * Set a red zone in the kernel stack after the u. area.
        !            40:  */
        !            41: setredzone(pte, vaddr)
        !            42:        register struct pte *pte;
        !            43:        caddr_t vaddr;
        !            44: {
        !            45: 
        !            46:        pte += (sizeof (struct user) + NBPG - 1) / NBPG;
        !            47:        *(int *)pte &= ~PG_PROT;
        !            48:        *(int *)pte |= PG_URKR;
        !            49:        if (vaddr)
        !            50:                mtpr(TBIS, vaddr + sizeof (struct user) + NBPG - 1);
        !            51: }
        !            52: 
        !            53: /*
        !            54:  * Check for valid program size
        !            55:  * NB - Check data and data growth separately as they may overflow 
        !            56:  * when summed together.
        !            57:  */
        !            58: chksize(ts, ids, uds, ss)
        !            59:        register unsigned ts, ids, uds, ss;
        !            60: {
        !            61:        extern unsigned maxtsize;
        !            62: 
        !            63:        if (ctob(ts) > maxtsize ||
        !            64:            ctob(ids) > u.u_rlimit[RLIMIT_DATA].rlim_cur ||
        !            65:            ctob(uds) > u.u_rlimit[RLIMIT_DATA].rlim_cur ||
        !            66:            ctob(ids + uds) > u.u_rlimit[RLIMIT_DATA].rlim_cur ||
        !            67:            ctob(ss) > u.u_rlimit[RLIMIT_STACK].rlim_cur) {
        !            68:                u.u_error = ENOMEM;
        !            69:                return (1);
        !            70:        }
        !            71:        return (0);
        !            72: }
        !            73: 
        !            74: /*ARGSUSED*/
        !            75: newptes(pte, v, size)
        !            76:        register struct pte *pte;
        !            77:        u_int v;
        !            78:        register int size;
        !            79: {
        !            80:        register caddr_t a = ptob(v);
        !            81: 
        !            82: #ifdef lint
        !            83:        pte = pte;
        !            84: #endif
        !            85:        if (size >= 8) {
        !            86:                mtpr(TBIA, 0);
        !            87:                return;
        !            88:        }
        !            89:        while (size > 0) {
        !            90:                mtpr(TBIS, a);
        !            91:                a += NBPG;
        !            92:                size--;
        !            93:        }
        !            94: }
        !            95: 
        !            96: /*
        !            97:  * Change protection codes of text segment.
        !            98:  * Have to flush translation buffer since this
        !            99:  * affect virtual memory mapping of current process.
        !           100:  */
        !           101: chgprot(addr, tprot)
        !           102:        caddr_t addr;
        !           103:        long tprot;
        !           104: {
        !           105:        unsigned v;
        !           106:        int tp;
        !           107:        register struct pte *pte;
        !           108:        register struct cmap *c;
        !           109: 
        !           110:        v = clbase(btop(addr));
        !           111:        if (!isatsv(u.u_procp, v)) {
        !           112:                u.u_error = EFAULT;
        !           113:                return (0);
        !           114:        }
        !           115:        tp = vtotp(u.u_procp, v);
        !           116:        pte = tptopte(u.u_procp, tp);
        !           117:        if (pte->pg_fod == 0 && pte->pg_pfnum) {
        !           118:                c = &cmap[pgtocm(pte->pg_pfnum)];
        !           119:                if (c->c_blkno && c->c_mdev != MSWAPX)
        !           120:                        munhash(mount[c->c_mdev].m_dev,
        !           121:                            (daddr_t)(u_long)c->c_blkno);
        !           122:        }
        !           123:        *(int *)pte &= ~PG_PROT;
        !           124:        *(int *)pte |= tprot;
        !           125:        distcl(pte);
        !           126:        tbiscl(v);
        !           127:        return (1);
        !           128: }
        !           129: 
        !           130: settprot(tprot)
        !           131:        long tprot;
        !           132: {
        !           133:        register int *ptaddr, i;
        !           134: 
        !           135:        ptaddr = (int *)mfpr(P0BR);
        !           136:        for (i = 0; i < u.u_tsize; i++) {
        !           137:                ptaddr[i] &= ~PG_PROT;
        !           138:                ptaddr[i] |= tprot;
        !           139:        }
        !           140:        mtpr(TBIA, 0);
        !           141: }
        !           142: 
        !           143: #ifdef notdef
        !           144: /*
        !           145:  * Rest are machine-dependent
        !           146:  */
        !           147: getmemc(addr)
        !           148:        caddr_t addr;
        !           149: {
        !           150:        register int c;
        !           151:        struct pte savemap;
        !           152: 
        !           153:        savemap = mmap[0];
        !           154:        *(int *)mmap = PG_V | PG_KR | btop(addr);
        !           155:        mtpr(TBIS, vmmap);
        !           156:        uncache(&vmmap[(int)addr & PGOFSET]);
        !           157:        c = *(char *)&vmmap[(int)addr & PGOFSET];
        !           158:        mmap[0] = savemap;
        !           159:        mtpr(TBIS, vmmap);
        !           160:        return (c & 0377);
        !           161: }
        !           162: 
        !           163: putmemc(addr, val)
        !           164:        caddr_t addr;
        !           165: {
        !           166:        struct pte savemap;
        !           167: 
        !           168:        savemap = mmap[0];
        !           169:        *(int *)mmap = PG_V | PG_KW | btop(addr);
        !           170:        mtpr(TBIS, vmmap);
        !           171:        *(char *)&vmmap[(int)addr & PGOFSET] = val;
        !           172: 
        !           173:        mtpr(PADC, 0);
        !           174:        mtpr(PACC, 0);
        !           175: 
        !           176:        mmap[0] = savemap;
        !           177:        mtpr(TBIS, vmmap);
        !           178: }
        !           179: #endif
        !           180: 
        !           181: /*
        !           182:  * Move pages from one kernel virtual address to another.
        !           183:  * Both addresses are assumed to reside in the Sysmap,
        !           184:  * and size must be a multiple of CLSIZE.
        !           185:  */
        !           186: pagemove(from, to, size)
        !           187:        register caddr_t from, to;
        !           188:        int size;
        !           189: {
        !           190:        register struct pte *fpte, *tpte;
        !           191: 
        !           192:        if (size % CLBYTES)
        !           193:                panic("pagemove");
        !           194:        fpte = kvtopte(from);
        !           195:        tpte = kvtopte(to);
        !           196:        while (size > 0) {
        !           197:                *tpte++ = *fpte;
        !           198:                *(int *)fpte++ = 0;
        !           199:                mtpr(TBIS, from);
        !           200:                mtpr(TBIS, to);
        !           201:                mtpr(P1DC, to);         /* purge !! */
        !           202:                from += NBPG;
        !           203:                to += NBPG;
        !           204:                size -= NBPG;
        !           205:        }
        !           206: }
        !           207: 
        !           208: /*
        !           209:  * Code and data key management routines.
        !           210:  *
        !           211:  * The array ckey_cnt maintains the count of processes currently
        !           212:  * sharing each code key.  The array ckey_cache maintains a record
        !           213:  * of all code keys used since the last flush of the code cache.
        !           214:  * Such keys may not be reused, even if unreferenced, until
        !           215:  * the cache is flushed.  The data cache key handling is analogous.
        !           216:  * The arrays ckey_cnt and ckey_cache are allways kept in such a way
        !           217:  * that the following invariant holds:
        !           218:  *     ckey_cnt > 0    =>'s    ckey_cache == 1
        !           219:  * meaning as long as a code key is used by at least one process, it's
        !           220:  * marked as being 'in the cache'. Of course, the following invariant
        !           221:  * also holds:
        !           222:  *     ckey_cache == 0 =>'s    ckey_cnt == 0
        !           223:  * which is just the reciprocal of the 1'st invariant.
        !           224:  * Equivalent invariants hold for the data key arrays.
        !           225:  */
        !           226: struct keystats ckeystats = { NCKEY - 1 };
        !           227: struct keystats dkeystats = { NDKEY - 1 };
        !           228: 
        !           229: /* 
        !           230:  * Release a code key.
        !           231:  */
        !           232: ckeyrelease(key)
        !           233:        int key;
        !           234: {
        !           235:        register int s;
        !           236: 
        !           237:        s = spl8();
        !           238:        if (--ckey_cnt[key] < 0) {
        !           239:                printf("ckeyrelease: key = %d\n", key);
        !           240:                ckey_cnt[key] = 0;
        !           241:        }
        !           242:        if (ckey_cnt[key] == 0)
        !           243:                ckeystats.ks_dirty++;
        !           244:        splx(s);
        !           245: }
        !           246: 
        !           247: /* 
        !           248:  * Release a data key.
        !           249:  */
        !           250: dkeyrelease(key)
        !           251:        int key;
        !           252: {
        !           253:        register int s;
        !           254: 
        !           255:        s = spl8();
        !           256:        if (--dkey_cnt[key] != 0) {
        !           257:                printf("dkeyrelease: key = %d\n", key);
        !           258:                dkey_cnt[key] = 0;
        !           259:        }
        !           260:        splx(s);        
        !           261:        dkeystats.ks_dirty++;
        !           262: }
        !           263: 
        !           264: /*
        !           265:  * Invalidate the data cache for a process
        !           266:  * by exchanging cache keys.
        !           267:  */
        !           268: dkeyinval(p)
        !           269:        register struct proc *p;
        !           270: {
        !           271:        int s;
        !           272: 
        !           273:        dkeystats.ks_inval++;
        !           274:        s = spl8();
        !           275:        if (--dkey_cnt[p->p_dkey] != 0)
        !           276:                dkey_cnt[p->p_dkey] = 0;
        !           277:        if (p == u.u_procp && !noproc) {
        !           278:                p->p_dkey = getdatakey();
        !           279:                mtpr(DCK, p->p_dkey);
        !           280:        } else
        !           281:                p->p_dkey = 0;
        !           282:        splx(s);        
        !           283: }
        !           284: 
        !           285: /* 
        !           286:  * Get a code key.
        !           287:  * Strategy: try each of the following in turn
        !           288:  * until a key is allocated.
        !           289:  *
        !           290:  * 1) Find an unreferenced key not yet in the cache.
        !           291:  *    If this fails, a code cache purge will be necessary.
        !           292:  * 2) Find an unreferenced key.  Mark all unreferenced keys
        !           293:  *    as available and purge the cache.
        !           294:  * 3) Free the keys from all processes not sharing keys.
        !           295:  * 4) Free the keys from all processes.
        !           296:  */
        !           297: getcodekey()
        !           298: {
        !           299:        register int i, s, freekey;
        !           300:        register struct proc *p;
        !           301:        int desparate = 0;
        !           302:        static int lastkey = MAXCKEY;
        !           303: 
        !           304:        ckeystats.ks_allocs++;
        !           305:        s = spl8();
        !           306:        freekey = 0;
        !           307:        for (i = lastkey + 1; ; i++) {
        !           308:                if (i > MAXCKEY)
        !           309:                        i = 1;
        !           310:                if ((int)ckey_cache[i] == 0) {  /* free key, take it */
        !           311:                        ckey_cache[i] = 1, ckey_cnt[i] = 1;
        !           312:                        splx(s);
        !           313:                        ckeystats.ks_allocfree++;
        !           314:                        ckeystats.ks_avail--;
        !           315:                        lastkey = i;
        !           316:                        return (i);
        !           317:                }
        !           318:                if (ckey_cnt[i] == 0)           /* save for potential use */
        !           319:                        freekey = i;
        !           320:                if (i == lastkey)
        !           321:                        break;
        !           322:        }
        !           323:        /*
        !           324:         * All code keys were marked as being in cache.
        !           325:         * If a key was in the cache, but not in use, grab it.
        !           326:         */
        !           327:        if (freekey != 0) {
        !           328: purge:
        !           329:                /*
        !           330:                 * If we've run out of free keys,
        !           331:                 * try and free up some other keys to avoid
        !           332:                 * future cache purges.
        !           333:                 */
        !           334:                ckey_cnt[freekey] = 1, ckey_cache[freekey] = 1;
        !           335:                for (i = 1; i <= MAXCKEY; i++)
        !           336:                        if (ckey_cnt[i] == 0) {
        !           337:                                ckey_cache[i] = 0;
        !           338:                                ckeystats.ks_avail++;
        !           339:                        }
        !           340:                mtpr(PACC, 0);
        !           341:                splx(s);
        !           342:                ckeystats.ks_dirty = 0;
        !           343:                ckeystats.ks_norefs++;
        !           344:                return (freekey);
        !           345:        }
        !           346: 
        !           347:        /*
        !           348:         * All keys are marked as in the cache and in use.
        !           349:         * Release all unshared keys, or, on second pass,
        !           350:         * release all keys.
        !           351:         */
        !           352: steal:
        !           353:        for (p = allproc; p; p = p->p_nxt)
        !           354:                if (p->p_ckey != 0 && (p->p_flag & SSYS) == 0) {
        !           355:                        i = p->p_ckey;
        !           356:                        if (ckey_cnt[i] == 1 || desparate) {
        !           357:                                p->p_ckey = 0;
        !           358:                                if (--ckey_cnt[i] == 0) {
        !           359:                                        freekey = i;
        !           360:                                        if (p->p_textp)
        !           361:                                                p->p_textp->x_ckey = 0;
        !           362:                                }
        !           363:                        }
        !           364:                }
        !           365: 
        !           366:        if (freekey) {
        !           367:                ckeystats.ks_taken++;
        !           368:                goto purge;
        !           369:        } else {
        !           370:                desparate++;
        !           371:                goto steal;
        !           372:        }
        !           373: }
        !           374: 
        !           375: /* 
        !           376:  * Get a data key.
        !           377:  *
        !           378:  * General strategy:
        !           379:  * 1) Try to find a data key that isn't in the cache. Allocate it.
        !           380:  * 2) If all data keys are in the cache, find one which isn't
        !           381:  *    allocated.  Mark all unallocated keys as not in cache,
        !           382:  *    purge the cache, and allocate this one.
        !           383:  * 3) If all of them are allocated, free all process' keys
        !           384:  *    and let them reclaim then as they run.
        !           385:  */
        !           386: getdatakey()
        !           387: {
        !           388:        register int i, freekey;
        !           389:        register struct proc *p;
        !           390:        int s;
        !           391:        static int lastkey = MAXDKEY;
        !           392: 
        !           393:        dkeystats.ks_allocs++;
        !           394:        s = spl8();
        !           395:        freekey = 0;
        !           396:        for (i = lastkey + 1; ; i++) {
        !           397:                if (i > MAXDKEY)
        !           398:                        i = 1;
        !           399:                if ((int)dkey_cache[i] == 0) {  /* free key, take it */
        !           400:                        dkey_cache[i] = 1, dkey_cnt[i] = 1;
        !           401:                        splx(s);
        !           402:                        dkeystats.ks_allocfree++;
        !           403:                        dkeystats.ks_avail--;
        !           404:                        lastkey = i;
        !           405:                        return (i);
        !           406:                }
        !           407:                if (dkey_cnt[i] == 0)
        !           408:                        freekey = i;
        !           409:                if (i == lastkey)
        !           410:                        break;
        !           411:        }
        !           412: purge:
        !           413:        if (freekey) {
        !           414:                /*
        !           415:                 * Try and free up some more keys to avoid
        !           416:                 * future allocations causing a cache purge.
        !           417:                 */
        !           418:                dkey_cnt[freekey] = 1, dkey_cache[freekey] = 1;
        !           419:                for (i = 1; i <= MAXDKEY; i++)
        !           420:                        if (dkey_cnt[i] == 0) {
        !           421:                                dkey_cache[i] = 0;
        !           422:                                dkeystats.ks_avail++;
        !           423:                        }
        !           424:                mtpr(PADC, 0);
        !           425:                splx(s);
        !           426:                dkeystats.ks_norefs++;
        !           427:                dkeystats.ks_dirty = 0;
        !           428:                return (freekey);
        !           429:        }
        !           430: 
        !           431:        /*
        !           432:         * Now, we have to take a key from someone.
        !           433:         * May as well take them all, so we get them
        !           434:         * from all of the idle procs.
        !           435:         */
        !           436:        for (p = allproc; p; p = p->p_nxt)
        !           437:                if (p->p_dkey != 0 && (p->p_flag & SSYS) == 0) {
        !           438:                        freekey = p->p_dkey;
        !           439:                        dkey_cnt[freekey] = 0;
        !           440:                        p->p_dkey = 0;
        !           441:                }
        !           442:        dkeystats.ks_taken++;
        !           443:        goto purge;
        !           444: }
        !           445: 
        !           446: /*VARGARGS1*/
        !           447: vtoph(p, v)
        !           448:        register struct proc *p;
        !           449:        unsigned v;
        !           450: {
        !           451:        register struct pte *pte;
        !           452:        register unsigned pg;
        !           453: 
        !           454:        pg = btop(v);
        !           455:        if (pg >= BTOPKERNBASE)
        !           456:                pte = &Sysmap[pg - BTOPKERNBASE];
        !           457:        else
        !           458:                pte = vtopte(p, pg);
        !           459:        return ((pte->pg_pfnum << PGSHIFT) + (v & PGOFSET));
        !           460: }

unix.superglobalmegacorp.com

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