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