Annotation of researchv9/sys/sun3/vm_machdep.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char sccsid[] = "@(#)vm_machdep.c 1.1 86/02/03 Copyr 1985 Sun Micro";
        !             3: #endif
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 1985 by Sun Microsystems, Inc.
        !             7:  */
        !             8: 
        !             9: /*
        !            10:  * Machine dependent virtual memory support.
        !            11:  * Context and segment and page map support for the Sun-3.
        !            12:  */
        !            13: 
        !            14: #include "../h/param.h"
        !            15: #include "../h/systm.h"
        !            16: #include "../h/buf.h"
        !            17: #include "../h/dir.h"
        !            18: #include "../h/user.h"
        !            19: #include "../h/proc.h"
        !            20: #include "../h/vm.h"
        !            21: #include "../h/cmap.h"
        !            22: #include "../h/text.h"
        !            23: #include "../h/mount.h"
        !            24: 
        !            25: #include "../machine/pte.h"
        !            26: #include "../machine/mmu.h"
        !            27: #include "../machine/cpu.h"
        !            28: #include "../machine/reg.h"
        !            29: #include "../machine/buserr.h"
        !            30: #include "../machine/scb.h"
        !            31: #include "../machine/mbvar.h"
        !            32: 
        !            33: u_char getsegmap();
        !            34: long   getpgmap();
        !            35: 
        !            36: struct context context[NCONTEXT];      /* contexts */
        !            37: int    ctxtime = 0;                    /* pseudo-time for ctx lru */
        !            38: 
        !            39: struct pmeg pmeg[NPMEG];               /* all the pmegs in the world */
        !            40: struct pmeg pmeghead;                  /* pmeg free list */
        !            41: 
        !            42: int    kernpmeg = 0;                   /* how many pmegs the kernel has */
        !            43: 
        !            44: /*
        !            45:  * Initialize pmeg allocation list.
        !            46:  */
        !            47: pmeginit()
        !            48: {
        !            49:        register int i;
        !            50: 
        !            51:        pmeghead.pm_forw = pmeghead.pm_back = &pmeghead;
        !            52:        for (i = 0; i < NPMEG; i++)             /* add all entries to queue */
        !            53:                insque(&pmeg[i], &pmeghead);
        !            54: }
        !            55: 
        !            56: /*
        !            57:  * Take care of common pmeg release code for pmegalloc() and pmegallocres(),
        !            58:  * called only when pmp->pm_procp is non-zero.
        !            59:  */
        !            60: pmegrelease(pmp)
        !            61:        register struct pmeg *pmp;
        !            62: {
        !            63:        register struct context *cp;
        !            64:        int ctx;
        !            65: 
        !            66:        pmegunload(pmp);
        !            67:        cp = pmp->pm_procp->p_ctx;
        !            68:        cp->ctx_pmeg[pmp->pm_seg] = 0;
        !            69:        ctx = getcontext();
        !            70:        setcontext((int)cp->ctx_context);
        !            71:        setsegmap((u_int)pmp->pm_seg, (u_char)SEGINV);
        !            72:        setcontext(ctx);
        !            73: }
        !            74: 
        !            75: /*
        !            76:  * Allocate a page map entry group.
        !            77:  */
        !            78: u_char
        !            79: pmegalloc(p)
        !            80:        register struct proc *p;        /* process to allocate it for */
        !            81: {
        !            82:        register struct pmeg *pmp;
        !            83:        extern int potime;
        !            84: 
        !            85:        pmp = pmeghead.pm_forw;         /* get pmeg off head of chain */
        !            86:        if (pmp->pm_procp)
        !            87:                pmegrelease(pmp);
        !            88:        remque(pmp);
        !            89:        pmp->pm_procp = p;              /* set process pointer */
        !            90:        pmp->pm_count = 0;              /* no valid pages yet */
        !            91:        pmp->pm_seg = -1;               /* no segments yet */
        !            92:        pmp->pm_time = potime - 1;      /* reset time */
        !            93:        if (p)
        !            94:                insque(pmp, pmeghead.pm_back);  /* put back on queue */
        !            95:        else
        !            96:                pmp->pm_forw = pmp->pm_back = 0;/* wanted by kernel */
        !            97: 
        !            98:        return ((u_char)(pmp - pmeg));  /* return index to pmeg in pmeg list */
        !            99: }
        !           100: 
        !           101: /*
        !           102:  * Free a pmeg.
        !           103:  */
        !           104: pmegfree(pmx)
        !           105:        u_char pmx;             /* index of pmeg in pmeg list */
        !           106: {
        !           107:        register struct pmeg *pmp = &pmeg[pmx];
        !           108: 
        !           109:        if (pmp->pm_procp)      /* is there a process with this one? */
        !           110:                remque(pmp);    /* take if off the queue its on */
        !           111:        pmp->pm_procp = 0;      /* reset process number */
        !           112:        insque(pmp, &pmeghead); /* put back on free list */
        !           113: }
        !           114: 
        !           115: /*
        !           116:  * Reserve named pmeg for use by kernel and monitor.
        !           117:  */
        !           118: pmegreserve(n)
        !           119:        u_char n;
        !           120: {
        !           121:        register struct pmeg *pmp = &pmeg[n];
        !           122: 
        !           123:        remque(pmp);
        !           124:        pmp->pm_forw = pmp->pm_back = 0;
        !           125:        pmp->pm_count = NPAGSEG;
        !           126:        pmp->pm_procp = (struct proc *)0;
        !           127:        pmp->pm_seg = 0;
        !           128:        kernpmeg++;
        !           129: }
        !           130: 
        !           131: /*
        !           132:  * Allocate and reserve kernel pmeg
        !           133:  */
        !           134: u_char
        !           135: pmegallocres()
        !           136: {
        !           137:        struct pmeg *pmp;
        !           138:        u_char pm;
        !           139: 
        !           140:        pmp = pmeghead.pm_forw;
        !           141:        if (pmp->pm_procp)
        !           142:                pmegrelease(pmp);
        !           143:        pm = (u_char)(pmp - pmeg);
        !           144:        pmegreserve(pm);
        !           145:        return (pm);
        !           146: }
        !           147: 
        !           148: /*
        !           149:  * Load all hardware page map entries for the specified
        !           150:  * pmeg from the software page table entries.
        !           151:  */
        !           152: pmegload(seg, need)
        !           153:        int seg;                /* segment we are loading */
        !           154:        int need;               /* need a segment */
        !           155: {
        !           156:        register struct pte *pte;
        !           157:        register struct pmeg *pmp;
        !           158:        register int v, num, k, new = 0;
        !           159:        register int i;
        !           160:        register struct proc *p = u.u_procp;
        !           161:        int pm, last, tse, dse, sss;
        !           162:        struct context *cp = p->p_ctx;          /* process context number */
        !           163:        u_char *pmxp = &cp->ctx_pmeg[seg];      /* which segments pmeg */
        !           164:        int s = splimp();
        !           165: 
        !           166:        if (getcontext() == KCONTEXT) {
        !           167:                printf("NO CONTEXT IN PMEGLOAD\n");
        !           168:                (void) splx(s);
        !           169:                return;
        !           170:        }
        !           171:        if (*pmxp == 0) {                       /* is there a pmeg already */
        !           172:                if (!need) {
        !           173:                        setsegmap((u_int)seg, (u_char)SEGINV);
        !           174:                        (void) splx(s);
        !           175:                        return;
        !           176:                }
        !           177:                *pmxp = pmegalloc(p);           /* get one */
        !           178:                pmeg[*pmxp].pm_seg = seg;       /* assign it in context */
        !           179:                new = 1;
        !           180:        }
        !           181:        pmp = &pmeg[*pmxp];                     /* get pointer to pmeg */
        !           182:        if (pmp->pm_procp != p)                 /* better be same process */
        !           183:                panic("dup alloc pmeg");
        !           184:        if (pmp->pm_seg != seg)                 /* better be same segment */
        !           185:                panic("pmeg changed seg");
        !           186:        pm = pmp - pmeg;        /* make pmeg index based on pmeg addr */
        !           187:        v = seg * NPAGSEG;      /* make index based on segment number */
        !           188:        /*
        !           189:         * Decide which of the text|data|stack
        !           190:         * segments the virtual segment seg is in.
        !           191:         *
        !           192:         * Lots of assumptions about the layout
        !           193:         * of virtual memory here.  Should be
        !           194:         * more parameterized.
        !           195:         */
        !           196:        last = ptos(btop(USRSTACK));    /* find bottom of user stack seg */
        !           197:        /* find end of text segment */
        !           198:        tse = p->p_tsize ? ptos(tptov(p, 0) + p->p_tsize - 1) : 0;
        !           199:        /* find end of data segment */
        !           200:        dse = ptos(dptov(p, 0) + p->p_dsize - 1);
        !           201:        /* compute start of stack segment */
        !           202:        sss = last - ptos(p->p_ssize + NPAGSEG - 1);
        !           203:        
        !           204:        setsegmap((u_int)seg, (u_char)pm);      /* set the seg map */
        !           205:        if (seg <= tse) {
        !           206:                if (seg == 0) {
        !           207:                        setpgmap((caddr_t)0, (long)0);/* first page invalid */
        !           208:                        v = LOWPAGES;                 /* set addr in map */
        !           209:                        num = MIN((p->p_tsize ? p->p_tsize : p->p_dsize),
        !           210:                            NPAGSEG - LOWPAGES);
        !           211:                        i = 0;
        !           212:                } else {
        !           213:                        i = v - tptov(p, 0);    /* compute index in text */
        !           214:                        num = MIN(p->p_tsize - i, NPAGSEG);
        !           215:                }
        !           216:                pte = tptopte(p, i);            /* get pointer ptes */
        !           217:                pmp->pm_pte = pte;
        !           218:                pmp->pm_count = num;
        !           219:                for (k = num; k--; v++, pte++)
        !           220:                        loadpgmap((u_int)v, pte, new);
        !           221:                for (k = NPAGSEG - num - ((seg == 0)? LOWPAGES : 0); k--; v++)
        !           222:                        setpgmap((caddr_t)ctob(v), (long)0);
        !           223:                if (seg > cp->ctx_tdmax)
        !           224:                        cp->ctx_tdmax = seg;
        !           225:        } else if (seg > tse && seg <= dse) {
        !           226:                i = v - dptov(p, 0);            /* compute index in data */
        !           227:                pte = dptopte(p, i);            /* get pointer ptes */
        !           228:                num = MIN(p->p_dsize - i, NPAGSEG);
        !           229:                pmp->pm_pte = pte;
        !           230:                pmp->pm_count = num;
        !           231:                for (k = num; k--; v++, pte++)
        !           232:                        loadpgmap((u_int)v, pte, new);
        !           233:                for (k = NPAGSEG - num; k--; v++)
        !           234:                        setpgmap((caddr_t)ctob(v), (long)0);
        !           235:                if (seg > cp->ctx_tdmax)
        !           236:                        cp->ctx_tdmax = seg;
        !           237:        } else if (seg >= sss && seg < last) {
        !           238:                i = btop(USRSTACK)-NPAGSEG - v; /* compute index in stack */
        !           239:                pte = sptopte(p, i);            /* get pointer ptes */
        !           240:                num = MIN(p->p_ssize - i, NPAGSEG);
        !           241:                pte -= num - 1;
        !           242:                pmp->pm_pte = pte;
        !           243:                pmp->pm_count = -num;
        !           244:                for (k = NPAGSEG - num; k--; v++)
        !           245:                        setpgmap((caddr_t)ctob(v), (long)0);
        !           246:                for (k = num; k--; v++, pte++)
        !           247:                        loadpgmap((u_int)v, pte, new);
        !           248:                if (seg < cp->ctx_smin)
        !           249:                        cp->ctx_smin = seg;
        !           250:        } else {
        !           251:                if (need)
        !           252:                        panic("need pmeg in hole");
        !           253:                pmegfree(*pmxp);
        !           254:                *pmxp = 0;
        !           255:                setsegmap((u_int)seg, (u_char)SEGINV);
        !           256:        }
        !           257:        (void) splx(s);
        !           258: }
        !           259: 
        !           260: /*
        !           261:  * Unload bits for specified pmeg.
        !           262:  */
        !           263: pmegunload(pmp)
        !           264:        register struct pmeg *pmp;      /* pointer to pmeg */
        !           265: {
        !           266:        register struct pte *pte;
        !           267:        register int num, k, v;
        !           268: 
        !           269:        if (pmp->pm_procp == 0)
        !           270:                panic("pmegunload");
        !           271:        setsegmap(CSEG, (u_char)(pmp - pmeg));
        !           272:        v = NPAGSEG * CSEG;
        !           273:        num = pmp->pm_count;
        !           274:        pte = pmp->pm_pte;
        !           275:        if (num < 0) {
        !           276:                num = -num;
        !           277:                v += NPAGSEG - num;
        !           278:        }
        !           279:        if (pmp->pm_seg == 0)           /* special case seg zero */
        !           280:                v += LOWPAGES;
        !           281:        for (k = num; k--; v++, pte++)
        !           282:                unloadpgmap((u_int)v, pte);
        !           283:        setsegmap(CSEG, (u_char)SEGINV);
        !           284: }
        !           285: 
        !           286: /*
        !           287:  * Get referenced and modified bits for
        !           288:  * the pmeg containing page v.  Called
        !           289:  * only by pageout.
        !           290:  */
        !           291: ptesync(p, v)
        !           292:        register struct proc *p;
        !           293:        register unsigned v;
        !           294: {
        !           295:        register struct context *cp;
        !           296:        register struct pmeg *pmp;
        !           297:        register int pm, s;
        !           298: 
        !           299:        s = splimp();
        !           300:        if ((cp = p->p_ctx) == NULL)
        !           301:                goto out;
        !           302:        if ((pm = cp->ctx_pmeg[ptos(v)]) == 0)
        !           303:                goto out;
        !           304:        pmp = &pmeg[pm];
        !           305:        if (pmp->pm_procp != p)
        !           306:                panic("ptesync procp");
        !           307:        if (pmp->pm_time != potime) {           /* check mod time, done? */
        !           308:                pmegunload(pmp);
        !           309:                pmp->pm_time = potime;
        !           310:        }
        !           311: out:
        !           312:        (void) splx(s);
        !           313: }
        !           314: 
        !           315: /*
        !           316:  * get a kernel page map entry given an address
        !           317:  */
        !           318: getkpgmap(addr)
        !           319:        caddr_t addr;
        !           320: {
        !           321: 
        !           322:        return ((int)getpgmap(addr));
        !           323: }
        !           324: 
        !           325: /*
        !           326:  * Initialize the context structures.
        !           327:  */
        !           328: ctxinit()
        !           329: {
        !           330:        register int i;
        !           331: 
        !           332:        for (i = 0; i < NCONTEXT; i++) {
        !           333:                if (i == KCONTEXT)
        !           334:                        continue;
        !           335:                context[i].ctx_context = i;
        !           336:        }
        !           337: }
        !           338: 
        !           339: /*
        !           340:  * Allocate a context and corresponding
        !           341:  * page map entries for the current process.
        !           342:  * If no free context must take one away
        !           343:  * from someone.
        !           344:  */
        !           345: ctxalloc()
        !           346: {
        !           347:        register struct proc *p = u.u_procp;    /* process this is for */
        !           348:        register struct context *cp, *scp = 0;
        !           349:        register int ct, i;
        !           350: 
        !           351:        /* find a free context or an old one */
        !           352:        for (cp = context; cp < &context[NCONTEXT]; cp++) {
        !           353:                if (cp == &context[KCONTEXT])
        !           354:                        continue;
        !           355:                if (cp->ctx_procp == 0)         /* if no process use this one */
        !           356:                        goto found;
        !           357:                if (scp == 0) {                 /* otherwise find the oldest */
        !           358:                        scp = cp;
        !           359:                        ct = cp->ctx_time;
        !           360:                } else if (cp->ctx_time <= ct) {
        !           361:                        scp = cp;
        !           362:                        ct = cp->ctx_time;
        !           363:                }
        !           364:        }
        !           365:        cp = scp;               /* reset pointer to save context pointer */
        !           366:        if (cp->ctx_procp)      /* if in use free it up before using */
        !           367:                ctxfree(cp->ctx_procp);
        !           368: found:
        !           369:        p->p_ctx = cp;          /* set context pointer in proc entry */
        !           370:        cp->ctx_procp = p;      /* set proc pointer in context table */
        !           371:        cp->ctx_time = ctxtime++;
        !           372:        setcontext((int)cp->ctx_context);
        !           373:        for (i = 0; i <= cp->ctx_tdmax; i++)
        !           374:                setsegmap((u_int)i, (u_char)SEGINV);
        !           375:        for (i = cp->ctx_smin; i < ptos(btop(USRSTACK)); i++)
        !           376:                setsegmap((u_int)i, (u_char)SEGINV);
        !           377:        cp->ctx_tdmax = 0;
        !           378:        cp->ctx_smin = (ptos(btop(USRSTACK)));
        !           379:        p->p_flag &= ~SPTECHG;
        !           380: }
        !           381: 
        !           382: /*
        !           383:  * Free the context and page map entries
        !           384:  * of the specified process.
        !           385:  */
        !           386: ctxfree(p)
        !           387:        register struct proc *p;
        !           388: {
        !           389:        register struct context *cp;
        !           390:        register u_char *pmxp;
        !           391:        register int s;
        !           392: 
        !           393:        if ((cp = p->p_ctx) == 0)       /* no context */
        !           394:                return;
        !           395:        if (p != cp->ctx_procp)         /* not the same process */
        !           396:                panic("ctxfree");
        !           397:        if ((p->p_flag&SWEXIT) == 0)    /* don't bother if dieing */
        !           398:                ctxunload(p);
        !           399:        s = splimp();
        !           400: 
        !           401:        /* free the pmegs for this context */
        !           402:        for (pmxp = cp->ctx_pmeg; pmxp < &cp->ctx_pmeg[ptos(btop(USRSTACK))];
        !           403:            pmxp++) {
        !           404:                if (*pmxp) {            /* is there a pmeg for this segment */
        !           405:                        pmegfree(*pmxp);
        !           406:                        *pmxp = 0;
        !           407:                }
        !           408:        }
        !           409:        (void) splx(s);                 /* back to normal */
        !           410:        setcontext(KCONTEXT);           /* paranoid */
        !           411:        cp->ctx_procp = 0;              /* reset proc pointer */
        !           412:        p->p_ctx = 0;                   /* reset context pointer */
        !           413: }
        !           414: 
        !           415: /*
        !           416:  * Set up the segment and page map entries for
        !           417:  * the current process.
        !           418:  */
        !           419: ctxsetup()
        !           420: {
        !           421:        register int i;
        !           422:        register int last = ptos(btop(USRSTACK));       /* last segment */
        !           423:        register struct context *cp = u.u_procp->p_ctx;
        !           424: 
        !           425:        /*
        !           426:         * Initialize all segments.
        !           427:         */
        !           428:        for (i = 0; i <= cp->ctx_tdmax; i++)    /* load pmegs for text/data */
        !           429:                pmegload(i, 0);
        !           430:        for (i = cp->ctx_smin; i < last; i++)   /* load pmegs for stack */
        !           431:                pmegload(i, 0);
        !           432: 
        !           433:        u.u_procp->p_flag &= ~SPTECHG;
        !           434: }
        !           435: 
        !           436: /*
        !           437:  * Unload the referenced and modified bits
        !           438:  * for the specified process.
        !           439:  */
        !           440: ctxunload(p)
        !           441:        struct proc *p;
        !           442: {
        !           443:        register int last = ptos(btop(USRSTACK));       /* last segment */
        !           444:        register int i, s = splimp();
        !           445:        register u_char *pmxp;
        !           446: 
        !           447:        /*
        !           448:         * Unload bits from all allocated pmegs.
        !           449:         */
        !           450:        pmxp = p->p_ctx->ctx_pmeg;      /* get pointer to pte's */
        !           451:        for (i = 0; i < last; i++, pmxp++)
        !           452:                if (*pmxp)              /* is it set */
        !           453:                        pmegunload(&pmeg[*pmxp]);
        !           454:        (void) splx(s);
        !           455: }
        !           456: 
        !           457: /*
        !           458:  * Pass all resources associated with a context
        !           459:  * from process p to process q.  Used by vfork.
        !           460:  */
        !           461: ctxpass(p, q)
        !           462:        register struct proc *p, *q;
        !           463: {
        !           464:        register struct context *cp = p->p_ctx;
        !           465:        register u_char *pmxp;
        !           466:        register int last = ptos(btop(USRSTACK));       /* last segment */
        !           467:        register int i;
        !           468: 
        !           469:        if (cp == 0)
        !           470:                return;
        !           471:        /*
        !           472:         * Pass the context from p to q.
        !           473:         */
        !           474:        q->p_ctx = cp;          /* q gets p's context */
        !           475:        p->p_ctx = 0;           /* p loses the context */
        !           476:        cp->ctx_procp = q;      /* context get q's proc id */
        !           477:        q->p_flag |= SPTECHG;   /* conservative */
        !           478:        setcontext(KCONTEXT);   /* paranoid */
        !           479:        
        !           480:        /*
        !           481:         * Change all pmegs to refer to q.
        !           482:         */
        !           483:        pmxp = cp->ctx_pmeg;
        !           484:        for (i = 0; i < last; i++, pmxp++)
        !           485:                if (*pmxp)
        !           486:                        pmeg[*pmxp].pm_procp = q;
        !           487: }
        !           488: 
        !           489: /*
        !           490:  * Handle a page fault on a 68020.
        !           491:  */
        !           492: pagefault(accaddr)
        !           493:        register int accaddr;
        !           494: {
        !           495:        register struct proc *p = u.u_procp;
        !           496:        register int v = btop(accaddr);
        !           497:        struct pte *addrtopte();
        !           498:        int i, seg;
        !           499:        int s;
        !           500: 
        !           501:        /*
        !           502:         * If user has no context, allocate one for him.
        !           503:         */
        !           504:        if (getcontext() == KCONTEXT) {
        !           505:                usetup();
        !           506:                return (1);
        !           507:        }
        !           508: 
        !           509:        if (addrtopte((caddr_t)accaddr, 1) == NULL)
        !           510:                return (0);
        !           511: 
        !           512:        seg = ptos(v);
        !           513:        if (p->p_ctx->ctx_pmeg[seg]) {
        !           514:                if (getpgmap((caddr_t)accaddr) & PG_V)
        !           515:                        return (0);
        !           516:                i = u.u_error;
        !           517:                pagein((u_int)accaddr, &u, 0);
        !           518:                u.u_error = i;
        !           519:        }
        !           520:        s = splimp();
        !           521:        if (p->p_ctx && p->p_ctx->ctx_pmeg[seg] == 0)
        !           522:                pmegload(seg, 1);
        !           523:        (void) splx(s);
        !           524:        return (1);
        !           525: }
        !           526: 
        !           527: /*
        !           528:  * Set up everything the user program might need.
        !           529:  * If we need a context, allocate it.  If we need
        !           530:  * to set up hardware segment and page maps, do it.
        !           531:  */
        !           532: usetup()
        !           533: {
        !           534:        register struct proc *p = u.u_procp;
        !           535: 
        !           536:        if (p->p_ctx == 0)                      /* do we need a context */
        !           537:                ctxalloc();
        !           538:        else {
        !           539:                p->p_ctx->ctx_time = ctxtime++;         /* update time */
        !           540:                setcontext((int)p->p_ctx->ctx_context); /* set to user */
        !           541:                if (p->p_flag & SPTECHG)                /* are we changing? */
        !           542:                        ctxsetup();
        !           543:        }
        !           544: }
        !           545: 
        !           546: /*
        !           547:  * Set a red zone below the kernel stack.
        !           548:  * NO LONGER USED, startup() SETS THE REDZONE.
        !           549:  */
        !           550: /*ARGSUSED*/
        !           551: setredzone(pte, vaddr)
        !           552:        struct pte *pte;
        !           553:        caddr_t vaddr;
        !           554: {
        !           555: }
        !           556: 
        !           557: /*
        !           558:  * Map a physical address range into kernel virtual addresses.
        !           559:  * Since the kernel appears in all contexts any new pmegs are
        !           560:  * mapped in all contexts.
        !           561:  */
        !           562: mapin(ppte, v, paddr, size, access)
        !           563:        register struct pte *ppte;      /* pointer to pte's */
        !           564:        u_int v;                        /* page number to map in */
        !           565:        register u_int paddr;           /* physical address */
        !           566:        register int size, access;      /* size in pages and access rights */
        !           567: {
        !           568:        register caddr_t vaddr = (caddr_t)ctob(v);
        !           569:        register u_char pm;
        !           570:        register int c, i;
        !           571:        int s = splimp();
        !           572: 
        !           573:        while (size--) {
        !           574:                if ((pm = getsegmap((u_int)ptos(v))) == SEGINV) {
        !           575:                        caddr_t va, vs;
        !           576: 
        !           577:                        pm = pmegalloc((struct proc *)0);
        !           578:                        kernpmeg++;
        !           579:                        c = getcontext();
        !           580:                        /* need to map in new seg across all contexts */
        !           581:                        for (i = 0; i < NCONTEXT; i++) { 
        !           582:                                setcontext(i);
        !           583:                                setsegmap(ptos(v), pm);
        !           584:                        }
        !           585:                        setcontext(c);
        !           586:                        vs = (caddr_t)(ptos(v)<<SGSHIFT);
        !           587:                        for (va = vs; va < vs + NBSG; va += NBPG)
        !           588:                                setpgmap(va, (long)0);
        !           589:                }
        !           590:                /*
        !           591:                 * Increment count of number of pme's used in this pmeg.
        !           592:                 * Allow it to go one past the number of pme's in a pmeg;
        !           593:                 * this indicates someone is doing a mapin without
        !           594:                 * corresponding mapout's and will be noticed in mapout
        !           595:                 * who will prevent the reference count from changing.
        !           596:                 */
        !           597:                if (pmeg[pm].pm_count <= NPAGSEG)
        !           598:                        pmeg[pm].pm_count++;
        !           599:                *((int *)ppte) = (paddr & PG_PFNUM) | access;
        !           600:                setpgmap(vaddr, *(long *)ppte);
        !           601:                ppte++;
        !           602:                paddr++;
        !           603:                v++;
        !           604:                vaddr += NBPG;
        !           605:        }
        !           606:        (void) splx(s);
        !           607: }
        !           608: 
        !           609: /*
        !           610:  * Release mapping for kernel.
        !           611:  * This frees pmegs, which are the most critical resource.
        !           612:  * Since the kernel appears in all contexts the pmeg has to be mapped 
        !           613:  * out for all contexts.  Assumes that ppte is a pointer
        !           614:  * to a pte within Sysmap.
        !           615:  */
        !           616: mapout(ppte, size)
        !           617:        register struct pte *ppte;
        !           618: {
        !           619:        register int vaddr = ctob(ppte - Sysmap) + KERNELBASE;
        !           620:        register u_char pm;
        !           621:        register int c, i;
        !           622:        int s = splimp();
        !           623: 
        !           624:        while (size--) {
        !           625:                if (!ppte->pg_v)
        !           626:                        panic("mapout: invalid pte");
        !           627:                ppte->pg_v = 0;
        !           628:                if ((pm = getsegmap((u_int)ptos(btop(vaddr)))) == SEGINV)
        !           629:                        panic("mapout: invalid segment");
        !           630:                if ((getpgmap((caddr_t)vaddr)&PG_V) == 0)
        !           631:                        panic("mapout: invalid page");
        !           632:                if (pmeg[pm].pm_count <= 0)
        !           633:                        panic("mapout: pmeg count");
        !           634:                setpgmap((caddr_t)vaddr, (long)0);
        !           635:                if (pmeg[pm].pm_count <= NPAGSEG)
        !           636:                        if (--pmeg[pm].pm_count == 0) { /* done with all ptes */
        !           637:                                c = getcontext();
        !           638:                                /* need to map out seg across all contexts */
        !           639:                                for (i = 0; i < NCONTEXT; i++) { 
        !           640:                                        setcontext(i);
        !           641:                                        setsegmap((u_int)ptos(btop(vaddr)),
        !           642:                                                (u_char)SEGINV);
        !           643:                                }
        !           644:                                setcontext(c);          /* reset context */
        !           645:                                pmegfree(pm);
        !           646:                                kernpmeg--;
        !           647:                        }
        !           648:                ppte++;                                 /* do next pte */
        !           649:                vaddr += NBPG;
        !           650:        }
        !           651:        (void) splx(s);
        !           652: }
        !           653: 
        !           654: /*
        !           655:  * Check user accessibility to a given address.
        !           656:  */
        !           657: useracc(vaddr, count, access)
        !           658:        caddr_t vaddr;
        !           659:        u_int count;
        !           660:        int access;
        !           661: {
        !           662:        register struct pte *pte;
        !           663:        struct pte *addrtopte();
        !           664: 
        !           665:        pte = addrtopte(vaddr, count);
        !           666:        if (pte == NULL)
        !           667:                return (0);
        !           668: 
        !           669:        count = btop((int)(vaddr + count - 1)) - btop((int)vaddr) + 1;
        !           670:        access = access == B_READ ? 0 : PG_W;
        !           671:        while (count--) {
        !           672:                if (((*(int *)pte) & PG_S) ||
        !           673:                    (((*(int *)pte) & PG_W)) < access)
        !           674:                        return (0);
        !           675:                pte++;
        !           676:        }
        !           677:        return (1);
        !           678: }
        !           679: 
        !           680: /*
        !           681:  * Check kernel accessibility to a given address.
        !           682:  * Unlike the vax, vaddr is checked against the range of Sysmap only!
        !           683:  */
        !           684: kernacc(vaddr, count, access)
        !           685:        caddr_t vaddr;
        !           686:        u_int count;
        !           687:        int access;
        !           688: {
        !           689:        register struct pte *ppte = &Sysmap[btop((int)vaddr - KERNELBASE)];
        !           690:        extern struct pte ESysmap[];
        !           691: 
        !           692:        count = btoc((int)vaddr + count) - btop(vaddr);
        !           693:        if (ppte + count > ESysmap || ppte < Sysmap)
        !           694:                return (0);
        !           695:        access = access == B_READ ? 0 : PG_W;
        !           696:        while (count--) {
        !           697:                if (!ppte->pg_v || ((((*(int *)ppte) & PG_W)) < access))
        !           698:                        return (0);
        !           699:                ppte++;
        !           700:        }
        !           701:        return (1);
        !           702: }
        !           703: 
        !           704: /*
        !           705:  * Check for valid program size
        !           706:  */
        !           707: chksize(ts, ds, ss)
        !           708:        unsigned ts, ds, ss;
        !           709: {
        !           710:        static int maxdmap = 0;
        !           711: 
        !           712:        if (ts > MAXTSIZ || ds > MAXDSIZ || ss > MAXSSIZ) {
        !           713:                u.u_error = ENOMEM;
        !           714:                return (1);
        !           715:        }
        !           716:        /* check for swap map overflow */
        !           717:        if (maxdmap == 0) {
        !           718:                register int i, blk;
        !           719: 
        !           720:                blk = DMMIN;
        !           721:                for (i = 0; i < NDMAP; i++) {
        !           722:                        maxdmap += blk;
        !           723:                        if (blk < DMMAX)
        !           724:                                blk *= 2;
        !           725:                }
        !           726:        }
        !           727:        if (ctod(ts) > NXDAD*DMTEXT ||
        !           728:            ctod(ds) > maxdmap || ctod(ss) > maxdmap) {
        !           729:                u.u_error = ENOMEM;
        !           730:                return (1);
        !           731:        }
        !           732:        /*
        !           733:         * Make sure the process isn't bigger than our
        !           734:         * virtual memory limit.
        !           735:         *
        !           736:         * THERE SHOULD BE A CONSTANT FOR THIS.
        !           737:         */
        !           738:        if (ctos(ts + LOWPAGES) + ctos(ds) + ctos(ss + HIGHPAGES) >
        !           739:            ctos(btop(USRSTACK))) {
        !           740:                u.u_error = ENOMEM;
        !           741:                return (1);
        !           742:        }
        !           743:        return (0);
        !           744: }
        !           745: 
        !           746: /*
        !           747:  * Change the translation for the current proc
        !           748:  * to reflect the change made in software ptes
        !           749:  * starting at ppte for size ptes.
        !           750:  */
        !           751: newptes(ppte, v, size)
        !           752:        register struct pte *ppte;
        !           753:        u_int v;
        !           754:        int size;
        !           755: {
        !           756:        register int i, fs, ls, need;
        !           757: 
        !           758:        if (getcontext() == KCONTEXT) {
        !           759:                if (u.u_procp->p_ctx)
        !           760:                        usetup();
        !           761:                else
        !           762:                        return;
        !           763:        }
        !           764:        fs = ptos(v);                   /* convert page pointer for 1st seg */
        !           765:        ls = ptos(v + size - 1);        /* convert page pointer for last seg */
        !           766:        need = ppte->pg_v;
        !           767:        for (i = fs; i <= ls; i++)      /* go through list and set ptes */
        !           768:                pmegload(i, need);
        !           769: }
        !           770: 
        !           771: /*
        !           772:  * Move pages from one kernel virtual address to another.
        !           773:  * Both addresses are assumed to reside in the Sysmap,
        !           774:  * and size must be a multiple of CLSIZE.
        !           775:  */
        !           776: pagemove(from, to, size)
        !           777:        register caddr_t from, to;
        !           778:        int size;
        !           779: {
        !           780:        register struct pte *fpte, *tpte;
        !           781: 
        !           782:        if (size % CLBYTES)
        !           783:                panic("pagemove");
        !           784:        fpte = &Sysmap[btop((int)from - KERNELBASE)];
        !           785:        tpte = &Sysmap[btop((int)to - KERNELBASE)];
        !           786:        while (size > 0) {
        !           787:                *tpte++ = *fpte;
        !           788:                setpgmap(to, *(long *)fpte);
        !           789:                *(int *)fpte++ = 0;
        !           790:                setpgmap(from, (long)0);
        !           791:                from += NBPG;
        !           792:                to += NBPG;
        !           793:                size -= NBPG;
        !           794:        }
        !           795: }
        !           796: 
        !           797: /*
        !           798:  * Check the validity of a user address range and return NULL
        !           799:  * on error or a pointer to the first pte for these addresses.
        !           800:  */
        !           801: struct pte *
        !           802: addrtopte(vaddr, count)
        !           803:        caddr_t vaddr;
        !           804:        u_int count;
        !           805: {
        !           806:        register struct proc *p = u.u_procp;
        !           807:        register int fv, lv;
        !           808:        int tss, dss, sss;
        !           809: 
        !           810:        fv = btop((int)vaddr);
        !           811:        lv = btop((int)(vaddr + count - 1));
        !           812: 
        !           813:        if (lv < fv || fv < btop(USRTEXT) || lv >= btop(USRSTACK))
        !           814:                return (NULL);
        !           815: 
        !           816:        /*
        !           817:         * Check that the request was within the
        !           818:         * user's valid address space.  Can't use
        !           819:         * isa[tds]sv because they don't check the holes.
        !           820:         */
        !           821:        tss = tptov(p, 0);
        !           822:        dss = dptov(p, 0);
        !           823:        sss = sptov(p, p->p_ssize - 1);
        !           824: 
        !           825:        if (fv >= tss && lv < tss + p->p_tsize)
        !           826:                return (tptopte(p, vtotp(p, fv)));
        !           827:        else if (fv >= dss && lv < dss + p->p_dsize)
        !           828:                return (dptopte(p, vtodp(p, fv)));
        !           829:        else if (fv >= sss && lv < sss + p->p_ssize)
        !           830:                return (sptopte(p, vtosp(p, fv)));
        !           831: 
        !           832:        return (NULL);
        !           833: }
        !           834: 
        !           835: #define        ONBPG           2048    /* old page size */
        !           836: #define        ONBSG           32768   /* old segment size */
        !           837: 
        !           838: /*
        !           839:  * Routine used to check to see if an a.out can be executed
        !           840:  * by the current machine/architecture.
        !           841:  */
        !           842: chkaout()
        !           843: {
        !           844: 
        !           845:        if ((u.u_exdata.ux_mach == M_68010) ||
        !           846:            (u.u_exdata.ux_mach == M_68020))
        !           847:                return (0);
        !           848:        else 
        !           849:                return (ENOEXEC);
        !           850: }
        !           851: 
        !           852: /* 
        !           853:  * The following functions return information about an a.out
        !           854:  * which is used when a program is executed.
        !           855:  */
        !           856: 
        !           857: /* 
        !           858:  * Return the size of the text segment adjusted for the type of a.out.
        !           859:  */
        !           860: size_t
        !           861: getts()
        !           862: {
        !           863:        return (clrnd(btoc(u.u_exdata.ux_tsize)));
        !           864: }
        !           865: 
        !           866: /* 
        !           867:  * Return the size of the data segment depending on the type of a.out.
        !           868:  * For the case of an old a.out we need to allow for the old segment
        !           869:  * alignment and the fact that the text segment starts at 32k and not 8k.
        !           870:  * To do this we calculate the size of the text segment and round
        !           871:  * it to the next old Sun-2 segment boundary.
        !           872:  */
        !           873: size_t
        !           874: getds()
        !           875: {
        !           876: 
        !           877:        return (clrnd(btoc(u.u_exdata.ux_dsize + u.u_exdata.ux_bsize)));
        !           878: }
        !           879: 
        !           880: /* 
        !           881:  * Return the load memory address for the data segment.
        !           882:  */
        !           883: caddr_t
        !           884: getdmem()
        !           885: {
        !           886: 
        !           887:        return ((caddr_t)ctob(dptov(u.u_procp, 0)));
        !           888: }
        !           889: 
        !           890: /* 
        !           891:  * Return the starting disk address for the data segment.
        !           892:  */
        !           893: getdfile()
        !           894: {
        !           895: 
        !           896:        if (u.u_exdata.ux_mag == ZMAGIC)
        !           897:                return (u.u_exdata.ux_tsize);
        !           898:        else
        !           899:                return (sizeof (u.u_exdata) + u.u_exdata.ux_tsize);
        !           900: }
        !           901: 
        !           902: /* 
        !           903:  * Return the load memory address for the text segment.
        !           904:  */
        !           905: caddr_t
        !           906: gettmem()
        !           907: {
        !           908: 
        !           909:        return ((caddr_t)USRTEXT);
        !           910: }
        !           911: 
        !           912: /* 
        !           913:  * Return the file byte offset for the text segment.
        !           914:  */
        !           915: gettfile()
        !           916: {
        !           917: 
        !           918:        if (u.u_exdata.ux_mag == ZMAGIC)
        !           919:                return (0);
        !           920:        else
        !           921:                return (sizeof (u.u_exdata));
        !           922: }

unix.superglobalmegacorp.com

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