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

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
1.1.1.2 ! root      906: gettmem(up)
        !           907: struct user *up;
1.1       root      908: {
                    909: 
                    910:        return ((caddr_t)USRTEXT);
                    911: }
                    912: 
                    913: /* 
                    914:  * Return the file byte offset for the text segment.
                    915:  */
1.1.1.2 ! root      916: gettfile(up)
        !           917: struct user *up;
1.1       root      918: {
                    919: 
1.1.1.2 ! root      920:        if (up->u_exdata.ux_mag == ZMAGIC)
1.1       root      921:                return (0);
                    922:        else
                    923:                return (sizeof (u.u_exdata));
                    924: }

unix.superglobalmegacorp.com

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