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

unix.superglobalmegacorp.com

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