Annotation of 43BSDReno/sys/hp300/vm_machdep.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1988 University of Utah.
                      3:  * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
                      4:  * All rights reserved.
                      5:  *
                      6:  * This code is derived from software contributed to Berkeley by
                      7:  * the Systems Programming Group of the University of Utah Computer
                      8:  * Science Department.
                      9:  *
                     10:  * Redistribution is only permitted until one year after the first shipment
                     11:  * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
                     12:  * binary forms are permitted provided that: (1) source distributions retain
                     13:  * this entire copyright notice and comment, and (2) distributions including
                     14:  * binaries display the following acknowledgement:  This product includes
                     15:  * software developed by the University of California, Berkeley and its
                     16:  * contributors'' in the documentation or other materials provided with the
                     17:  * distribution and in all advertising materials mentioning features or use
                     18:  * of this software.  Neither the name of the University nor the names of
                     19:  * its contributors may be used to endorse or promote products derived from
                     20:  * this software without specific prior written permission.
                     21:  * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     22:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     23:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     24:  *
                     25:  * from: Utah $Hdr: vm_machdep.c 1.18 89/08/23$
                     26:  *
                     27:  *     @(#)vm_machdep.c        7.5 (Berkeley) 6/21/90
                     28:  */
                     29: 
                     30: #include "param.h"
                     31: #include "systm.h"
                     32: #include "user.h"
                     33: #include "proc.h"
                     34: #include "cmap.h"
                     35: #include "vm.h"
                     36: #include "text.h"
                     37: #include "malloc.h"
                     38: #include "buf.h"
                     39: 
                     40: #include "cpu.h"
                     41: #include "pte.h"
                     42: 
                     43: /*
                     44:  * Set a red zone in the kernel stack after the u. area.
                     45:  * We don't support a redzone right now.  It really isn't clear
                     46:  * that it is a good idea since, if the kernel stack were to roll
                     47:  * into a write protected page, the processor would lock up (since
                     48:  * it cannot create an exception frame) and we would get no useful
                     49:  * post-mortem info.  Currently, under the DEBUG option, we just
                     50:  * check at every clock interrupt to see if the current k-stack has
                     51:  * gone too far (i.e. into the "redzone" page) and if so, panic.
                     52:  * Look at _lev6intr in locore.s for more details.
                     53:  */
                     54: /*ARGSUSED*/
                     55: setredzone(pte, vaddr)
                     56:        struct pte *pte;
                     57:        caddr_t vaddr;
                     58: {
                     59: }
                     60: 
                     61: /*
                     62:  * Check for valid program size
                     63:  * NB - Check data and data growth separately as they may overflow 
                     64:  * when summed together.
                     65:  */
                     66: chksize(ts, ids, uds, ss)
                     67:        unsigned ts, ids, uds, ss;
                     68: {
                     69:        extern unsigned maxtsize;
                     70: 
                     71:        if (ctob(ts) > maxtsize ||
                     72:            ctob(ids) > u.u_rlimit[RLIMIT_DATA].rlim_cur ||
                     73:            ctob(uds) > u.u_rlimit[RLIMIT_DATA].rlim_cur ||
                     74:            ctob(ids + uds) > u.u_rlimit[RLIMIT_DATA].rlim_cur ||
                     75:            ctob(ss) > u.u_rlimit[RLIMIT_STACK].rlim_cur) {
                     76:                return (ENOMEM);
                     77:        }
                     78:        return (0);
                     79: }
                     80: 
                     81: /*ARGSUSED*/
                     82: newptes(pte, v, size)
                     83:        struct pte *pte;
                     84:        u_int v;
                     85:        register int size;
                     86: {
                     87:        register caddr_t a;
                     88: 
                     89: #ifdef lint
                     90:        pte = pte;
                     91: #endif
                     92:        if (size >= 8)
                     93:                TBIAU();
                     94:        else {
                     95:                a = ptob(v);
                     96:                while (size > 0) {
                     97:                        TBIS(a);
                     98:                        a += NBPG;
                     99:                        size--;
                    100:                }
                    101:        }
                    102:        DCIU();
                    103: }
                    104: 
                    105: /*
                    106:  * Change protection codes of text segment.
                    107:  * Have to flush translation buffer since this
                    108:  * affect virtual memory mapping of current process.
                    109:  */
                    110: chgprot(addr, tprot)
                    111:        caddr_t addr;
                    112:        long tprot;
                    113: {
                    114:        unsigned v;
                    115:        int tp;
                    116:        register struct pte *pte;
                    117:        register struct cmap *c;
                    118: 
                    119:        v = clbase(btop(addr));
                    120:        if (!isatsv(u.u_procp, v))
                    121:                return (EFAULT);
                    122:        tp = vtotp(u.u_procp, v);
                    123:        pte = tptopte(u.u_procp, tp);
                    124:        if (pte->pg_fod == 0 && pte->pg_pfnum) {
                    125:                c = &cmap[pgtocm(pte->pg_pfnum)];
                    126:                if (c->c_blkno)
                    127:                        munhash(c->c_vp, (daddr_t)(u_long)c->c_blkno);
                    128:        }
                    129:        *(u_int *)pte &= ~PG_PROT;
                    130:        *(u_int *)pte |= tprot;
                    131:        TBIS(addr);
                    132:        return (0);
                    133: }
                    134: 
                    135: settprot(tprot)
                    136:        long tprot;
                    137: {
                    138:        register u_int *pte, i;
                    139: 
                    140:        pte = (u_int *)u.u_procp->p_p0br;
                    141:        for (i = 0; i < u.u_tsize; i++, pte++) {
                    142:                *pte &= ~PG_PROT;
                    143:                *pte |= tprot;
                    144:        }
                    145:        TBIAU();
                    146: }
                    147: 
                    148: /*
                    149:  * Simulate effect of VAX region length registers.
                    150:  * The one case where we must do anything is if a region has shrunk.
                    151:  * In that case we must invalidate all the PTEs for the no longer valid VAs.
                    152:  */
                    153: setptlr(region, nlen)
                    154:        int nlen;
                    155: {
                    156:        register struct pte *pte;
                    157:        register int change;
                    158:        int olen;
                    159: 
                    160:        if (region == 0) {
                    161:                olen = u.u_pcb.pcb_p0lr;
                    162:                u.u_pcb.pcb_p0lr = nlen;
                    163:        } else {
                    164:                olen = P1PAGES - u.u_pcb.pcb_p1lr;
                    165:                u.u_pcb.pcb_p1lr = nlen;
                    166:                nlen = P1PAGES - nlen;
                    167:        }
                    168:        if ((change = olen - nlen) <= 0)
                    169:                return;
                    170:        if (region == 0)
                    171:                pte = u.u_pcb.pcb_p0br + u.u_pcb.pcb_p0lr;
                    172:        else
                    173:                pte = u.u_pcb.pcb_p1br + u.u_pcb.pcb_p1lr - change;
                    174:        do {
                    175:                *(u_int *)pte++ = PG_NV;
                    176:        } while (--change);
                    177:        /* short cut newptes */
                    178:        TBIAU();
                    179:        DCIU();
                    180: }
                    181: 
                    182: /*
                    183:  * Map `size' bytes of physical memory starting at `paddr' into
                    184:  * kernel VA space using PTEs starting at `pte'.  Read/write and
                    185:  * cache-inhibit status are specified by `prot'.
                    186:  */ 
                    187: physaccess(pte, paddr, size, prot)
                    188:        register struct pte *pte;
                    189:        caddr_t paddr;
                    190:        register int size;
                    191: {
                    192:        register u_int page;
                    193: 
                    194:        page = (u_int)paddr & PG_FRAME;
                    195:        for (size = btoc(size); size; size--) {
                    196:                *(int *)pte = PG_V | prot | page;
                    197:                page += NBPG;
                    198:                pte++;
                    199:        }
                    200:        TBIAS();
                    201: }
                    202: 
                    203: /*
                    204:  * Move pages from one kernel virtual address to another.
                    205:  * Both addresses are assumed to reside in the Sysmap,
                    206:  * and size must be a multiple of CLSIZE.
                    207:  */
                    208: pagemove(from, to, size)
                    209:        register caddr_t from, to;
                    210:        int size;
                    211: {
                    212:        register struct pte *fpte, *tpte;
                    213: 
                    214:        if (size % CLBYTES)
                    215:                panic("pagemove");
                    216:        fpte = kvtopte(from);
                    217:        tpte = kvtopte(to);
                    218:        while (size > 0) {
                    219:                *tpte++ = *fpte;
                    220:                *(int *)fpte++ = PG_NV;
                    221:                TBIS(from);
                    222:                TBIS(to);
                    223:                from += NBPG;
                    224:                to += NBPG;
                    225:                size -= NBPG;
                    226:        }
                    227: }
                    228: 
                    229: #ifdef KGDB
                    230: /*
                    231:  * Change protections on kernel pages from addr to addr+size
                    232:  * (presumably so debugger can plant a breakpoint).
                    233:  * All addresses are assumed to reside in the Sysmap,
                    234:  */
                    235: chgkprot(addr, size, rw)
                    236:        register caddr_t addr;
                    237:        int size, rw;
                    238: {
                    239:        register struct pte *pte;
                    240: 
                    241:        pte = &Sysmap[btop(addr)];
                    242:        while (size > 0) {
                    243:                pte->pg_prot = rw == B_WRITE? 0 : 1;
                    244:                TBIS(addr);
                    245:                addr += NBPG;
                    246:                size -= NBPG;
                    247:                pte++;
                    248:        }
                    249: }
                    250: #endif
                    251: 
                    252: /*
                    253:  * The probe[rw] routines should probably be redone in assembler
                    254:  * for efficiency.
                    255:  */
                    256: prober(addr)
                    257:        register u_int addr;
                    258: {
                    259:        register int page;
                    260:        register struct proc *p;
                    261: 
                    262:        if (addr >= USRSTACK)
                    263:                return(0);
                    264: #ifdef HPUXCOMPAT
                    265:        if (ISHPMMADDR(addr))
                    266:                addr = HPMMBASEADDR(addr);
                    267: #endif
                    268:        page = btop(addr);
                    269:        p = u.u_procp;
                    270:        if (page < dptov(p, p->p_dsize) || page > sptov(p, p->p_ssize))
                    271:                return(1);
                    272: #ifdef MAPMEM
                    273:        if (page < dptov(p, p->p_dsize+p->p_mmsize) &&
                    274:            (*(int *)vtopte(p, page) & (PG_FOD|PG_V)) == (PG_FOD|PG_V))
                    275:                return(1);
                    276: #endif
                    277:        return(0);
                    278: }
                    279: 
                    280: probew(addr)
                    281:        register u_int addr;
                    282: {
                    283:        register int page;
                    284:        register struct proc *p;
                    285: 
                    286:        if (addr >= USRSTACK)
                    287:                return(0);
                    288: #ifdef HPUXCOMPAT
                    289:        if (ISHPMMADDR(addr))
                    290:                addr = HPMMBASEADDR(addr);
                    291: #endif
                    292:        page = btop(addr);
                    293:        p = u.u_procp;
                    294:        if (page < dptov(p, p->p_dsize) || page > sptov(p, p->p_ssize))
                    295:                return((*(int *)vtopte(p, page) & PG_PROT) == PG_RW);
                    296: #ifdef MAPMEM
                    297:        if (page < dptov(p, p->p_dsize+p->p_mmsize))
                    298:                return((*(int *)vtopte(p, page) & (PG_FOD|PG_V|PG_PROT))
                    299:                       == (PG_FOD|PG_V|PG_RW));
                    300: #endif
                    301:        return(0);
                    302: }
                    303: 
                    304: /*
                    305:  * NB: assumes a physically contiguous kernel page table
                    306:  *     (makes life a LOT simpler).
                    307:  */
                    308: kernacc(addr, count, rw)
                    309:        register caddr_t addr;
                    310:        int count, rw;
                    311: {
                    312:        register struct ste *ste;
                    313:        register struct pte *pte;
                    314:        register u_int ix, cnt;
                    315:        extern long Syssize;
                    316: 
                    317:        if (count <= 0)
                    318:                return(0);
                    319:        ix = ((int)addr & SG_IMASK) >> SG_ISHIFT;
                    320:        cnt = (((int)addr + count + (1<<SG_ISHIFT)-1) & SG_IMASK) >> SG_ISHIFT;
                    321:        cnt -= ix;
                    322:        for (ste = &Sysseg[ix]; cnt; cnt--, ste++)
                    323:                /* should check SG_PROT, but we have no RO segments now */
                    324:                if (ste->sg_v == 0)
                    325:                        return(0);
                    326:        ix = btop(addr);
                    327:        cnt = btop(addr+count+NBPG-1);
                    328:        if (cnt > (u_int)&Syssize)
                    329:                return(0);
                    330:        cnt -= ix;
                    331:        for (pte = &Sysmap[ix]; cnt; cnt--, pte++)
                    332:                if (pte->pg_v == 0 || (rw == B_WRITE && pte->pg_prot == 1))
                    333:                        return(0);
                    334:        return(1);
                    335: }
                    336: 
                    337: useracc(addr, count, rw)
                    338:        register caddr_t addr;
                    339:        unsigned count;
                    340: {
                    341:        register int (*func)();
                    342:        register u_int addr2;
                    343:        extern int prober(), probew();
                    344: 
                    345:        if (count <= 0)
                    346:                return(0);
                    347:        addr2 = (u_int) addr;
                    348:        addr += count;
                    349:        func = (rw == B_READ) ? prober : probew;
                    350:        do {
                    351:                if ((*func)(addr2) == 0)
                    352:                        return(0);
                    353:                addr2 = (addr2 + NBPG) & ~PGOFSET;
                    354:        } while (addr2 < (u_int)addr);
                    355:        return(1);
                    356: }
                    357: 
                    358: /*
                    359:  * Convert kernel VA to physical address
                    360:  */
                    361: kvtop(addr)
                    362:        register caddr_t addr;
                    363: {
                    364:        register int pf;
                    365: 
                    366:        pf = Sysmap[btop(addr)].pg_pfnum;
                    367:        if (pf == 0)
                    368:                panic("kvtop: zero page frame");
                    369:        return((u_int)ptob(pf) + ((int)addr & PGOFSET));
                    370: }
                    371: 
                    372: struct ste *
                    373: vtoste(p, va)
                    374:        register struct proc *p;
                    375:        register u_int va;
                    376: {
                    377:        register struct ste *ste;
                    378: 
                    379:        ste = (struct ste *)((u_int)p->p_p0br + p->p_szpt * NBPG);
                    380:        return(ste + ((va & SG_IMASK) >> SG_ISHIFT));
                    381: }
                    382: 
                    383: initustp(p)
                    384:        register struct proc *p;
                    385: {
                    386:        return((int)Usrptmap[btokmx(p->p_p0br) + p->p_szpt].pg_pfnum);
                    387: }
                    388: 
                    389: /*
                    390:  * Initialize segment table to reflect PTEs in Usrptmap.
                    391:  * Segment table address is given by Usrptmap index of p_szpt.
                    392:  */
                    393: initsegt(p)
                    394:        register struct proc *p;
                    395: {
                    396:        register int i, k, sz;
                    397:        register struct ste *ste;
                    398:        extern struct ste *vtoste();
                    399: 
                    400:        k = btokmx(p->p_p0br);
                    401:        ste = vtoste(p, 0);
                    402:        /* text and data */
                    403:        sz = ctopt(p->p_tsize + p->p_dsize + p->p_mmsize);
                    404:        for (i = 0; i < sz; i++, ste++) {
                    405:                *(int *)ste = SG_RW | SG_V;
                    406:                ste->sg_pfnum = Usrptmap[k++].pg_pfnum;
                    407:        }
                    408:        /*
                    409:         * Bogus!  The kernelmap may map unused PT pages
                    410:         * (since we don't shrink PTs) so we need to skip over
                    411:         * those STEs.  We should really free the unused PT
                    412:         * pages in expand().
                    413:         */
                    414:        sz += ctopt(p->p_ssize + HIGHPAGES);
                    415:        if (sz < p->p_szpt)
                    416:                k += p->p_szpt - sz;
                    417:        /* hole */
                    418:        sz = NPTEPG - ctopt(p->p_ssize + HIGHPAGES);
                    419:        for ( ; i < sz; i++, ste++)
                    420:                *(int *)ste = SG_NV;
                    421:        /* stack and u-area */
                    422:        sz = NPTEPG;
                    423:        for ( ; i < sz; i++, ste++) {
                    424:                *(int *)ste = SG_RW | SG_V;
                    425:                ste->sg_pfnum = Usrptmap[k++].pg_pfnum;
                    426:        }
                    427: }
                    428: 
                    429: /*
                    430:  * Allocate/free cache-inhibited physical memory.
                    431:  * Assumes that malloc returns page aligned memory for requests which are
                    432:  * a multiple of the page size.  Hence, size must be such a multiple.
                    433:  */
                    434: caddr_t
                    435: cialloc(sz)
                    436:        int sz;
                    437: {
                    438:        caddr_t kva;
                    439:        register int npg, *pte;
                    440: 
                    441:        if (sz & CLOFSET)
                    442:                return(NULL);
                    443:        kva = (caddr_t)malloc(sz, M_DEVBUF, M_NOWAIT);
                    444:        if (kva) {
                    445:                if (!claligned(kva))
                    446:                        panic("cialloc");
                    447:                pte = (int *)kvtopte(kva);
                    448:                npg = btoc(sz);
                    449:                while (--npg >= 0)
                    450:                        *pte++ |= PG_CI;
                    451:                TBIAS();
                    452:        }
                    453:        return(kva);
                    454: }
                    455: 
                    456: cifree(kva, sz)
                    457:        caddr_t kva;
                    458:        int sz;
                    459: {
                    460:        register int npg, *pte;
                    461: 
                    462:        if (sz & CLOFSET)
                    463:                panic("cifree");
                    464:        pte = (int *)kvtopte(kva);
                    465:        npg = btoc(sz);
                    466:        while (--npg >= 0)
                    467:                *pte++ &= ~PG_CI;
                    468:        TBIAS();
                    469:        free(kva, M_DEVBUF);
                    470: }
                    471: 
                    472: extern char usrio[];
                    473: extern struct pte Usriomap[];
                    474: struct map *useriomap;
                    475: int usriowanted;
                    476: 
                    477: /*
                    478:  * Map an IO request into kernel virtual address space.  Requests fall into
                    479:  * one of five catagories:
                    480:  *
                    481:  *     B_PHYS|B_UAREA: User u-area swap.
                    482:  *                     Address is relative to start of u-area (p_addr).
                    483:  *     B_PHYS|B_PAGET: User page table swap.
                    484:  *                     Address is a kernel VA in usrpt (Usrptmap).
                    485:  *     B_PHYS|B_DIRTY: Dirty page push.
                    486:  *                     Address is a VA in proc2's address space.
                    487:  *     B_PHYS|B_PGIN:  Kernel pagein of user pages.
                    488:  *                     Address is VA in user's address space.
                    489:  *     B_PHYS:         User "raw" IO request.
                    490:  *                     Address is VA in user's address space.
                    491:  *
                    492:  * All requests are (re)mapped into kernel VA space via the useriomap
                    493:  * (a name with only slightly more meaning than "kernelmap")
                    494:  */
                    495: vmapbuf(bp)
                    496:        register struct buf *bp;
                    497: {
                    498:        register int npf, a;
                    499:        register caddr_t addr;
                    500:        register struct pte *pte, *iopte;
                    501:        register long flags = bp->b_flags;
                    502:        struct proc *p;
                    503:        int off, s;
                    504: 
                    505:        if ((flags & B_PHYS) == 0)
                    506:                panic("vmapbuf");
                    507:        /*
                    508:         * Find PTEs for the area to be mapped
                    509:         */
                    510:        p = flags&B_DIRTY ? &proc[2] : bp->b_proc;
                    511:        addr = bp->b_un.b_addr;
                    512:        if (flags & B_UAREA)
                    513:                pte = &p->p_addr[btop(addr)];
                    514:        else if (flags & B_PAGET)
                    515:                pte = &Usrptmap[btokmx((struct pte *)addr)];
                    516:        else
                    517:                pte = vtopte(p, btop(addr));
                    518:        /*
                    519:         * Allocate some kernel PTEs and load them
                    520:         */
                    521:        off = (int)addr & PGOFSET;
                    522:        npf = btoc(bp->b_bcount + off);
                    523:        s = splbio();
                    524:        while ((a = rmalloc(useriomap, npf)) == 0) {
                    525:                usriowanted = 1;
                    526:                sleep((caddr_t)useriomap, PSWP);
                    527:        }
                    528:        splx(s);
                    529:        iopte = &Usriomap[a];
                    530:        bp->b_saveaddr = bp->b_un.b_addr;
                    531:        addr = bp->b_un.b_addr = (caddr_t)(usrio + (a << PGSHIFT)) + off;
                    532:        while (npf--) {
                    533:                mapin(iopte, (u_int)addr, pte->pg_pfnum, PG_CI|PG_RW|PG_V);
                    534:                iopte++, pte++;
                    535:                addr += NBPG;
                    536:        }
                    537: }
                    538: 
                    539: /*
                    540:  * Free the io map PTEs associated with this IO operation.
                    541:  * We also invalidate the TLB entries and restore the original b_addr.
                    542:  */
                    543: vunmapbuf(bp)
                    544:        register struct buf *bp;
                    545: {
                    546:        register int a, npf;
                    547:        register caddr_t addr = bp->b_un.b_addr;
                    548:        register struct pte *pte;
                    549:        int s;
                    550: 
                    551:        if ((bp->b_flags & B_PHYS) == 0)
                    552:                panic("vunmapbuf");
                    553:        a = (int)(addr - usrio) >> PGSHIFT;
                    554:        npf = btoc(bp->b_bcount + ((int)addr & PGOFSET));
                    555:        s = splbio();
                    556:        rmfree(useriomap, npf, a);
                    557:        if (usriowanted) {
                    558:                usriowanted = 0;
                    559:                wakeup((caddr_t)useriomap); 
                    560:        }
                    561:        splx(s);
                    562:        pte = &Usriomap[a];
                    563:        while (npf--) {
                    564:                *(int *)pte = PG_NV;
                    565:                TBIS((caddr_t)addr);
                    566:                addr += NBPG;
                    567:                pte++;
                    568:        }
                    569:        bp->b_un.b_addr = bp->b_saveaddr;
                    570:        bp->b_saveaddr = NULL;
                    571: }

unix.superglobalmegacorp.com

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