[BACK]Return to pmap.c CVS log [TXT][DIR] Up to [local] / sys / arch / mips64 / mips64

Annotation of sys/arch/mips64/mips64/pmap.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: pmap.c,v 1.29 2007/07/18 20:06:07 miod Exp $  */
                      2:
                      3: /*
                      4:  * Copyright (c) 2001-2004 Opsycon AB  (www.opsycon.se / www.opsycon.com)
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  *
                     15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
                     16:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     18:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
                     19:  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     20:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     21:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     22:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     23:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     24:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     25:  * SUCH DAMAGE.
                     26:  *
                     27:  *     XXX This code needs some major rewriting.
                     28:  */
                     29:
                     30: #include <sys/param.h>
                     31: #include <sys/systm.h>
                     32: #include <sys/proc.h>
                     33: #include <sys/malloc.h>
                     34: #include <sys/user.h>
                     35: #include <sys/buf.h>
                     36: #include <sys/pool.h>
                     37: #ifdef SYSVSHM
                     38: #include <sys/shm.h>
                     39: #endif
                     40:
                     41: #include <machine/pte.h>
                     42: #include <machine/cpu.h>
                     43: #include <machine/autoconf.h>
                     44: #include <machine/memconf.h>
                     45: #include <machine/vmparam.h>
                     46: #include <mips64/archtype.h>
                     47:
                     48: #include <uvm/uvm.h>
                     49:
                     50: extern void mem_zero_page(vaddr_t);
                     51:
                     52: struct pool pmap_pmap_pool;
                     53: struct pool pmap_pv_pool;
                     54:
                     55: #define pmap_pv_alloc()                (pv_entry_t)pool_get(&pmap_pv_pool, PR_NOWAIT)
                     56: #define pmap_pv_free(pv)       pool_put(&pmap_pv_pool, (pv))
                     57:
                     58: #ifndef PMAP_PV_LOWAT
                     59: #define PMAP_PV_LOWAT   16
                     60: #endif
                     61: int    pmap_pv_lowat = PMAP_PV_LOWAT;
                     62:
                     63: int    pmap_alloc_tlbpid(struct proc *);
                     64: int    pmap_enter_pv(pmap_t, vaddr_t, vm_page_t, u_int *);
                     65: int    pmap_page_alloc(vaddr_t *);
                     66: void   pmap_page_free(vaddr_t);
                     67: void   pmap_page_cache(vm_page_t, int);
                     68: void   pmap_remove_pv(pmap_t, vaddr_t, paddr_t);
                     69:
                     70: #ifdef PMAPDEBUG
                     71: struct {
                     72:        int kernel;     /* entering kernel mapping */
                     73:        int user;       /* entering user mapping */
                     74:        int ptpneeded;  /* needed to allocate a PT page */
                     75:        int pwchange;   /* no mapping change, just wiring or protection */
                     76:        int wchange;    /* no mapping change, just wiring */
                     77:        int mchange;    /* was mapped but mapping to different page */
                     78:        int managed;    /* a managed page */
                     79:        int firstpv;    /* first mapping for this PA */
                     80:        int secondpv;   /* second mapping for this PA */
                     81:        int ci;         /* cache inhibited */
                     82:        int unmanaged;  /* not a managed page */
                     83:        int flushes;    /* cache flushes */
                     84:        int cachehit;   /* new entry forced valid entry out */
                     85: } enter_stats;
                     86: struct {
                     87:        int calls;
                     88:        int removes;
                     89:        int flushes;
                     90:        int pidflushes; /* HW pid stolen */
                     91:        int pvfirst;
                     92:        int pvsearch;
                     93: } remove_stats;
                     94:
                     95: #define PDB_FOLLOW     0x0001
                     96: #define PDB_INIT       0x0002
                     97: #define PDB_ENTER      0x0004
                     98: #define PDB_REMOVE     0x0008
                     99: #define PDB_CREATE     0x0010
                    100: #define PDB_PTPAGE     0x0020
                    101: #define PDB_PVENTRY    0x0040
                    102: #define PDB_BITS       0x0080
                    103: #define PDB_COLLECT    0x0100
                    104: #define PDB_PROTECT    0x0200
                    105: #define PDB_TLBPID     0x0400
                    106: #define PDB_PARANOIA   0x2000
                    107: #define PDB_WIRING     0x4000
                    108: #define PDB_PVDUMP     0x8000
                    109:
                    110: #define DPRINTF(flag, printdata)       \
                    111:        if (pmapdebug & (flag))         \
                    112:                printf printdata;
                    113:
                    114: #define stat_count(what)       (what)++
                    115: int pmapdebug = PDB_ENTER|PDB_FOLLOW;
                    116:
                    117: #else
                    118:
                    119: #define DPRINTF(flag, printdata)
                    120: #define stat_count(what)
                    121:
                    122: #endif /* PMAPDEBUG */
                    123:
                    124:
                    125: struct pmap    kernel_pmap_store;
                    126:
                    127: psize_t        mem_size;       /* memory size in bytes */
                    128: vaddr_t        virtual_start;  /* VA of first avail page (after kernel bss)*/
                    129: vaddr_t        virtual_end;    /* VA of last avail page (end of kernel AS) */
                    130:
                    131: u_int          tlbpid_gen = 1;         /* TLB PID generation count */
                    132: int            tlbpid_cnt = 2;         /* next available TLB PID */
                    133:
                    134: pt_entry_t     *Sysmap;                /* kernel pte table */
                    135: u_int          Sysmapsize;             /* number of pte's in Sysmap */
                    136:
                    137:
                    138: /*
                    139:  *     Bootstrap the system enough to run with virtual memory.
                    140:  */
                    141: void
                    142: pmap_bootstrap()
                    143: {
                    144:        u_int i;
                    145:        pt_entry_t *spte;
                    146:
                    147:        /*
                    148:         * Create a mapping table for kernel virtual memory. This
                    149:         * table is a linear table in contrast to the user process
                    150:         * mapping tables which are built with segment/page tables.
                    151:         * Create 1GB of map (this will only use 1MB of memory).
                    152:         */
                    153:        virtual_start = VM_MIN_KERNEL_ADDRESS;
                    154:        virtual_end = VM_MAX_KERNEL_ADDRESS;
                    155:
                    156:        Sysmapsize = (VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS) /
                    157:            PAGE_SIZE;
                    158:        if (Sysmapsize & 1)
                    159:                Sysmapsize++;   /* force even number of pages */
                    160:
                    161:        Sysmap = (pt_entry_t *)
                    162:            uvm_pageboot_alloc(sizeof(pt_entry_t) * Sysmapsize);
                    163:
                    164:        pool_init(&pmap_pmap_pool, sizeof(struct pmap), 0, 0, 0,"pmappl", NULL);
                    165:        pool_init(&pmap_pv_pool, sizeof(struct pv_entry), 0, 0, 0,"pvpl", NULL);
                    166:
                    167:        simple_lock_init(&pmap_kernel()->pm_lock);
                    168:        pmap_kernel()->pm_count = 1;
                    169:
                    170:        /*
                    171:         * The 64 bit Mips architecture stores the AND result
                    172:         * of the Global bits in the pte pair in the on chip
                    173:         * translation lookaside buffer. Thus invalid entries
                    174:         * must have the Global bit set so when Entry LO and
                    175:         * Entry HI G bits are ANDed together they will produce
                    176:         * a global bit to store in the tlb.
                    177:         */
                    178:        for (i = 0, spte = Sysmap; i < Sysmapsize; i++, spte++)
                    179:                spte->pt_entry = PG_G;
                    180: }
                    181:
                    182: /*
                    183:  *  Page steal allocator used during bootup.
                    184:  */
                    185: vaddr_t
                    186: pmap_steal_memory(vsize_t size, vaddr_t *vstartp, vaddr_t *vendp)
                    187: {
                    188:        int i, j, x;
                    189:        int npg;
                    190:        vaddr_t va;
                    191:        paddr_t pa;
                    192:
                    193: #ifdef DIAGNOSTIC
                    194:        if (uvm.page_init_done) {
                    195:                panic("pmap_steal_memory: too late, vm is running!");
                    196:        }
                    197: #endif
                    198:
                    199:        size = round_page(size);
                    200:        npg = atop(size);
                    201:        va = 0;
                    202:
                    203:        for(i = 0; i < vm_nphysseg && va == 0; i++) {
                    204:                if (vm_physmem[i].avail_start != vm_physmem[i].start ||
                    205:                    vm_physmem[i].avail_start >= vm_physmem[i].avail_end) {
                    206:                        continue;
                    207:                }
                    208:
                    209:                if ((vm_physmem[i].avail_end - vm_physmem[i].avail_start) < npg)
                    210:                        continue;
                    211:
                    212:                pa = ptoa(vm_physmem[i].avail_start);
                    213:                vm_physmem[i].avail_start += npg;
                    214:                vm_physmem[i].start += npg;
                    215:
                    216:                if (vm_physmem[i].avail_start == vm_physmem[i].end) {
                    217:                        if (vm_nphysseg == 1)
                    218:                                panic("pmap_steal_memory: out of memory!");
                    219:
                    220:                        vm_nphysseg--;
                    221:                        for (j = i; j < vm_nphysseg; x++)
                    222:                                vm_physmem[x] = vm_physmem[x + 1];
                    223:                }
                    224:                if (vstartp)
                    225:                        *vstartp = round_page(virtual_start);
                    226:                if (vendp)
                    227:                        *vendp = virtual_end;
                    228:
                    229:                /*
                    230:                 * Prefer KSEG0 addresses for now, whenever possible.
                    231:                 */
                    232:                if (pa + size < KSEG_SIZE)
                    233:                        va = PHYS_TO_KSEG0(pa);
                    234:                else
                    235:                        va = PHYS_TO_XKPHYS(pa, CCA_NONCOHERENT);
                    236:
                    237:                bzero((void *)va, size);
                    238:                return (va);
                    239:        }
                    240:
                    241:        panic("pmap_steal_memory: no memory to steal");
                    242: }
                    243:
                    244: /*
                    245:  *     Initialize the pmap module.
                    246:  *     Called by vm_init, to initialize any structures that the pmap
                    247:  *     system needs to map virtual memory.
                    248:  */
                    249: void
                    250: pmap_init()
                    251: {
                    252:
                    253:        DPRINTF(PDB_FOLLOW|PDB_INIT, ("pmap_init()\n"));
                    254:
                    255: #if 0 /* too early */
                    256:        pool_setlowat(&pmap_pv_pool, pmap_pv_lowat);
                    257: #endif
                    258: }
                    259:
                    260: static pv_entry_t pg_to_pvh(struct vm_page *);
                    261: static __inline pv_entry_t
                    262: pg_to_pvh(struct vm_page *pg)
                    263: {
                    264:        return &pg->mdpage.pv_ent;
                    265: }
                    266:
                    267: /*
                    268:  *     Create and return a physical map.
                    269:  */
                    270: pmap_t
                    271: pmap_create()
                    272: {
                    273:        pmap_t pmap;
                    274:        vaddr_t va;
                    275:        int s;
                    276:
                    277: extern struct vmspace vmspace0;
                    278: extern struct user *proc0paddr;
                    279:
                    280:        DPRINTF(PDB_FOLLOW|PDB_CREATE, ("pmap_create()\n"));
                    281:
                    282:        s = splvm();
                    283:        pmap = pool_get(&pmap_pmap_pool, PR_WAITOK);
                    284:        splx(s);
                    285:        bzero(pmap, sizeof(*pmap));
                    286:
                    287:        simple_lock_init(&pmap->pm_lock);
                    288:        pmap->pm_count = 1;
                    289:
                    290:        while (pmap_page_alloc(&va) != 0) {
                    291:                /* XXX What else can we do?  Deadlocks?  */
                    292:                uvm_wait("pmap_create");
                    293:        }
                    294:
                    295:        pmap->pm_segtab = (struct segtab *)va;
                    296:
                    297:        if (pmap == vmspace0.vm_map.pmap) {
                    298:                /*
                    299:                 * The initial process has already been allocated a TLBPID
                    300:                 * in mach_init().
                    301:                 */
                    302:                pmap->pm_tlbpid = 1;
                    303:                pmap->pm_tlbgen = tlbpid_gen;
                    304:                proc0paddr->u_pcb.pcb_segtab = pmap->pm_segtab;
                    305:        } else {
                    306:                pmap->pm_tlbpid = 0;
                    307:                pmap->pm_tlbgen = 0;
                    308:        }
                    309:
                    310:        return (pmap);
                    311: }
                    312:
                    313: /*
                    314:  *     Retire the given physical map from service.
                    315:  *     Should only be called if the map contains
                    316:  *     no valid mappings.
                    317:  */
                    318: void
                    319: pmap_destroy(pmap_t pmap)
                    320: {
                    321:        int s, count;
                    322:
                    323:        DPRINTF(PDB_FOLLOW|PDB_CREATE, ("pmap_destroy(%x)\n", pmap));
                    324:
                    325:        simple_lock(&pmap->pm_lock);
                    326:        count = --pmap->pm_count;
                    327:        simple_unlock(&pmap->pm_lock);
                    328:        if (count > 0)
                    329:                return;
                    330:
                    331:        if (pmap->pm_segtab) {
                    332:                pt_entry_t *pte;
                    333:                int i;
                    334: #ifdef PARANOIA
                    335:                int j;
                    336: #endif
                    337:
                    338:                for (i = 0; i < PMAP_SEGTABSIZE; i++) {
                    339:                        /* get pointer to segment map */
                    340:                        pte = pmap->pm_segtab->seg_tab[i];
                    341:                        if (!pte)
                    342:                                continue;
                    343: #ifdef PARANOIA
                    344:                        for (j = 0; j < NPTEPG; j++) {
                    345:                                if ((pte+j)->pt_entry)
                    346:                                        panic("pmap_destroy: segmap not empty");
                    347:                        }
                    348: #endif
                    349:                        Mips_HitInvalidateDCache((vaddr_t)pte, PAGE_SIZE);
                    350:                        pmap_page_free((vaddr_t)pte);
                    351: #ifdef PARANOIA
                    352:                        pmap->pm_segtab->seg_tab[i] = NULL;
                    353: #endif
                    354:                }
                    355:                pmap_page_free((vaddr_t)pmap->pm_segtab);
                    356: #ifdef PARANOIA
                    357:                pmap->pm_segtab = NULL;
                    358: #endif
                    359:        }
                    360:
                    361:        s = splvm();
                    362:        pool_put(&pmap_pmap_pool, pmap);
                    363:        splx(s);
                    364: }
                    365:
                    366: /*
                    367:  *     Add a reference to the specified pmap.
                    368:  */
                    369: void
                    370: pmap_reference(pmap_t pmap)
                    371: {
                    372:
                    373:        DPRINTF(PDB_FOLLOW, ("pmap_reference(%x)\n", pmap));
                    374:
                    375:        if (pmap) {
                    376:                simple_lock(&pmap->pm_lock);
                    377:                pmap->pm_count++;
                    378:                simple_unlock(&pmap->pm_lock);
                    379:        }
                    380: }
                    381:
                    382: /*
                    383:  *      Make a new pmap (vmspace) active for the given process.
                    384:  */
                    385: void
                    386: pmap_activate(struct proc *p)
                    387: {
                    388:        pmap_t pmap = p->p_vmspace->vm_map.pmap;
                    389:        p->p_addr->u_pcb.pcb_segtab = pmap->pm_segtab;
                    390:        pmap_alloc_tlbpid(p);
                    391: }
                    392:
                    393: /*
                    394:  *      Make a previously active pmap (vmspace) inactive.
                    395:  */
                    396: void
                    397: pmap_deactivate(struct proc *p)
                    398: {
                    399:        /* Empty */
                    400: }
                    401:
                    402: /*
                    403:  *     Remove the given range of addresses from the specified map.
                    404:  *
                    405:  *     It is assumed that the start and end are properly
                    406:  *     rounded to the page size.
                    407:  */
                    408: void
                    409: pmap_remove(pmap_t pmap, vaddr_t sva, vaddr_t eva)
                    410: {
                    411:        vaddr_t nssva;
                    412:        pt_entry_t *pte;
                    413:        unsigned entry;
                    414:
                    415:        DPRINTF(PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT,
                    416:                ("pmap_remove(%x, %x, %x)\n", pmap, sva, eva));
                    417:
                    418:        stat_count(remove_stats.calls);
                    419:
                    420:        if (pmap == NULL)
                    421:                return;
                    422:
                    423:        if (pmap == pmap_kernel()) {
                    424:                pt_entry_t *pte;
                    425:
                    426:                /* remove entries from kernel pmap */
                    427: #ifdef DIAGNOSTIC
                    428:                if (sva < VM_MIN_KERNEL_ADDRESS || eva < sva)
                    429:                        panic("pmap_remove: kva not in range");
                    430: #endif
                    431:                pte = kvtopte(sva);
                    432:                for(; sva < eva; sva += NBPG, pte++) {
                    433:                        entry = pte->pt_entry;
                    434:                        if (!(entry & PG_V))
                    435:                                continue;
                    436:                        pmap->pm_stats.resident_count--;
                    437:                        pmap_remove_pv(pmap, sva, pfn_to_pad(entry));
                    438:                        pte->pt_entry = PG_NV | PG_G;
                    439:                        /*
                    440:                         * Flush the TLB for the given address.
                    441:                         */
                    442:                        tlb_flush_addr(sva);
                    443:                        stat_count(remove_stats.flushes);
                    444:                }
                    445:                return;
                    446:        }
                    447:
                    448: #ifdef DIAGNOSTIC
                    449:        if (eva > VM_MAXUSER_ADDRESS)
                    450:                panic("pmap_remove: uva not in range");
                    451: #endif
                    452:        while (sva < eva) {
                    453:                nssva = mips_trunc_seg(sva) + NBSEG;
                    454:                if (nssva == 0 || nssva > eva)
                    455:                        nssva = eva;
                    456:                /*
                    457:                 * If VA belongs to an unallocated segment,
                    458:                 * skip to the next segment boundary.
                    459:                 */
                    460:                if (!(pte = pmap_segmap(pmap, sva))) {
                    461:                        sva = nssva;
                    462:                        continue;
                    463:                }
                    464:                /*
                    465:                 * Invalidate every valid mapping within this segment.
                    466:                 */
                    467:                pte += uvtopte(sva);
                    468:                for (; sva < nssva; sva += NBPG, pte++) {
                    469:                        entry = pte->pt_entry;
                    470:                        if (!(entry & PG_V))
                    471:                                continue;
                    472:                        pmap->pm_stats.resident_count--;
                    473:                        pmap_remove_pv(pmap, sva, pfn_to_pad(entry));
                    474:                        pte->pt_entry = PG_NV;
                    475:                        /*
                    476:                         * Flush the TLB for the given address.
                    477:                         */
                    478:                        if (pmap->pm_tlbgen == tlbpid_gen) {
                    479:                                tlb_flush_addr(sva | (pmap->pm_tlbpid <<
                    480:                                        VMTLB_PID_SHIFT));
                    481:                                stat_count(remove_stats.flushes);
                    482:                        }
                    483:                }
                    484:        }
                    485: }
                    486:
                    487: /*
                    488:  *     pmap_page_protect:
                    489:  *
                    490:  *     Lower the permission for all mappings to a given page.
                    491:  */
                    492: void
                    493: pmap_page_protect(struct vm_page *pg, vm_prot_t prot)
                    494: {
                    495:        pv_entry_t pv;
                    496:        vaddr_t va;
                    497:        int s;
                    498:
                    499:        if (prot == VM_PROT_NONE) {
                    500:                DPRINTF(PDB_REMOVE, ("pmap_page_protect(%p, %p)\n", pg, prot));
                    501:        } else {
                    502:                DPRINTF(PDB_FOLLOW|PDB_PROTECT,
                    503:                        ("pmap_page_protect(%p, %p)\n", pg, prot));
                    504:        }
                    505:
                    506:        switch (prot) {
                    507:        case VM_PROT_READ|VM_PROT_WRITE:
                    508:        case VM_PROT_ALL:
                    509:                break;
                    510:
                    511:        /* copy_on_write */
                    512:        case VM_PROT_READ:
                    513:        case VM_PROT_READ|VM_PROT_EXECUTE:
                    514:                pv = pg_to_pvh(pg);
                    515:                s = splvm();
                    516:                /*
                    517:                 * Loop over all current mappings setting/clearing as apropos.
                    518:                 */
                    519:                if (pv->pv_pmap != NULL) {
                    520:                        for (; pv; pv = pv->pv_next) {
                    521:                                va = pv->pv_va;
                    522:                                pmap_protect(pv->pv_pmap, va, va + PAGE_SIZE,
                    523:                                    prot);
                    524:                        }
                    525:                }
                    526:                splx(s);
                    527:                break;
                    528:
                    529:        /* remove_all */
                    530:        default:
                    531:                pv = pg_to_pvh(pg);
                    532:                s = splvm();
                    533:                while (pv->pv_pmap != NULL) {
                    534:                        va = pv->pv_va;
                    535:                        pmap_remove(pv->pv_pmap, va, va + PAGE_SIZE);
                    536:                }
                    537:                splx(s);
                    538:        }
                    539: }
                    540:
                    541: /*
                    542:  *     Set the physical protection on the
                    543:  *     specified range of this map as requested.
                    544:  */
                    545: void
                    546: pmap_protect(pmap_t pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot)
                    547: {
                    548:        vaddr_t nssva;
                    549:        pt_entry_t *pte;
                    550:        u_int entry;
                    551:        u_int p;
                    552:
                    553:        DPRINTF(PDB_FOLLOW|PDB_PROTECT,
                    554:                ("pmap_protect(%p, %p, %p, %p)\n", pmap, sva, eva, prot));
                    555:
                    556:        if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
                    557:                pmap_remove(pmap, sva, eva);
                    558:                return;
                    559:        }
                    560:
                    561:        p = (prot & VM_PROT_WRITE) ? PG_M : PG_RO;
                    562:
                    563:        if (pmap == pmap_kernel()) {
                    564:                /*
                    565:                 * Change entries in kernel pmap.
                    566:                 * This will trap if the page is writeable (in order to set
                    567:                 * the dirty bit) even if the dirty bit is already set. The
                    568:                 * optimization isn't worth the effort since this code isn't
                    569:                 * executed much. The common case is to make a user page
                    570:                 * read-only.
                    571:                 */
                    572: #ifdef DIAGNOSTIC
                    573:                if (sva < VM_MIN_KERNEL_ADDRESS || eva < sva)
                    574:                        panic("pmap_protect: kva not in range");
                    575: #endif
                    576:                pte = kvtopte(sva);
                    577:                for (; sva < eva; sva += NBPG, pte++) {
                    578:                        entry = pte->pt_entry;
                    579:                        if (!(entry & PG_V))
                    580:                                continue;
                    581:                        entry = (entry & ~(PG_M | PG_RO)) | p;
                    582:                        pte->pt_entry = entry;
                    583:                        /*
                    584:                         * Update the TLB if the given address is in the cache.
                    585:                         */
                    586:                        tlb_update(sva, entry);
                    587:                }
                    588:                return;
                    589:        }
                    590:
                    591: #ifdef DIAGNOSTIC
                    592:        if (eva > VM_MAXUSER_ADDRESS)
                    593:                panic("pmap_protect: uva not in range");
                    594: #endif
                    595:        while (sva < eva) {
                    596:                nssva = mips_trunc_seg(sva) + NBSEG;
                    597:                if (nssva == 0 || nssva > eva)
                    598:                        nssva = eva;
                    599:                /*
                    600:                 * If VA belongs to an unallocated segment,
                    601:                 * skip to the next segment boundary.
                    602:                 */
                    603:                if (!(pte = pmap_segmap(pmap, sva))) {
                    604:                        sva = nssva;
                    605:                        continue;
                    606:                }
                    607:                /*
                    608:                 * Change protection on every valid mapping within this segment.
                    609:                 */
                    610:                pte += uvtopte(sva);
                    611:                for (; sva < nssva; sva += NBPG, pte++) {
                    612:                        entry = pte->pt_entry;
                    613:                        if (!(entry & PG_V))
                    614:                                continue;
                    615:                        entry = (entry & ~(PG_M | PG_RO)) | p;
                    616:                        pte->pt_entry = entry;
                    617:                        if (pmap->pm_tlbgen == tlbpid_gen)
                    618:                                tlb_update(sva | (pmap->pm_tlbpid <<
                    619:                                        VMTLB_PID_SHIFT), entry);
                    620:                }
                    621:        }
                    622: }
                    623:
                    624: /*
                    625:  *     Insert the given physical page (p) at
                    626:  *     the specified virtual address (v) in the
                    627:  *     target physical map with the protection requested.
                    628:  *
                    629:  *     NB:  This is the only routine which MAY NOT lazy-evaluate
                    630:  *     or lose information.  That is, this routine must actually
                    631:  *     insert this page into the given map NOW.
                    632:  */
                    633: int
                    634: pmap_enter(pmap_t pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
                    635: {
                    636:        pt_entry_t *pte;
                    637:        u_int npte;
                    638:        vm_page_t pg;
                    639:
                    640:        DPRINTF(PDB_FOLLOW|PDB_ENTER,
                    641:                ("pmap_enter(%p, %p, %p, %p, %p)\n", pmap, va, pa, prot, flags));
                    642:
                    643: #ifdef DIAGNOSTIC
                    644:        if (pmap == pmap_kernel()) {
                    645:                stat_count(enter_stats.kernel);
                    646:                if (va < VM_MIN_KERNEL_ADDRESS)
                    647:                        panic("pmap_enter: kva %p", va);
                    648:        } else {
                    649:                stat_count(enter_stats.user);
                    650:                if (va >= VM_MAXUSER_ADDRESS)
                    651:                        panic("pmap_enter: uva %p", va);
                    652:        }
                    653: #endif
                    654:
                    655:        pg = PHYS_TO_VM_PAGE(pa);
                    656:
                    657:        if (pg != NULL) {
                    658:                if (!(prot & VM_PROT_WRITE)) {
                    659:                        npte = PG_ROPAGE;
                    660:                } else {
                    661:                        if (pmap == pmap_kernel()) {
                    662:                                /*
                    663:                                 * Don't bother to trap on kernel writes,
                    664:                                 * just record page as dirty.
                    665:                                 */
                    666:                                npte = PG_RWPAGE;
                    667:                        } else {
                    668:                                if (pg->pg_flags & PV_ATTR_MOD) {
                    669:                                        npte = PG_RWPAGE;
                    670:                                } else {
                    671:                                        npte = PG_CWPAGE;
                    672:                                }
                    673:                        }
                    674:                }
                    675:
                    676:                /* Set page referenced/modified status based on flags */
                    677:                if (flags & VM_PROT_WRITE)
                    678:                        atomic_setbits_int(&pg->pg_flags,
                    679:                            PV_ATTR_MOD | PV_ATTR_REF);
                    680:                else if (flags & VM_PROT_ALL)
                    681:                        atomic_setbits_int(&pg->pg_flags, PV_ATTR_REF);
                    682:
                    683:                stat_count(enter_stats.managed);
                    684:        } else {
                    685:                /*
                    686:                 * Assumption: if it is not part of our managed memory
                    687:                 * then it must be device memory which may be volatile.
                    688:                 */
                    689:                stat_count(enter_stats.unmanaged);
                    690:                if (prot & VM_PROT_WRITE) {
                    691:                        npte = PG_IOPAGE & ~PG_G;
                    692:                } else {
                    693:                        npte = (PG_IOPAGE | PG_RO) & ~(PG_G | PG_M);
                    694:                }
                    695:        }
                    696:
                    697:        if (pmap == pmap_kernel()) {
                    698:                if (pg != NULL) {
                    699:                        if (pmap_enter_pv(pmap, va, pg, &npte) != 0) {
                    700:                                if (flags & PMAP_CANFAIL)
                    701:                                        return ENOMEM;
                    702:                                panic("pmap_enter: pmap_enter_pv() failed");
                    703:                        }
                    704:                }
                    705:
                    706:                pte = kvtopte(va);
                    707:                npte |= vad_to_pfn(pa) | PG_G;
                    708:                if (!(pte->pt_entry & PG_V)) {
                    709:                        pmap->pm_stats.resident_count++;
                    710:                }
                    711:                if ((pte->pt_entry & PG_V) && pa != pfn_to_pad(pte->pt_entry)) {
                    712:                        pmap_remove(pmap, va, va + NBPG);
                    713:                        stat_count(enter_stats.mchange);
                    714:                }
                    715:
                    716:                /*
                    717:                 * Update the same virtual address entry.
                    718:                 */
                    719:                pte->pt_entry = npte;
                    720:                tlb_update(va, npte);
                    721:                return 0;
                    722:        }
                    723:
                    724:        /*
                    725:         *  User space mapping. Do table build.
                    726:         */
                    727:        if (!(pte = pmap_segmap(pmap, va))) {
                    728:                vaddr_t nva;
                    729:
                    730:                while (pmap_page_alloc(&nva) != 0) {
                    731:                        if (flags & PMAP_CANFAIL)
                    732:                                return ENOMEM;
                    733:                        uvm_wait("pmap_enter");
                    734:                }
                    735:
                    736:                pmap_segmap(pmap, va) = pte = (pt_entry_t *)nva;
                    737:        }
                    738:
                    739:        if (pg != NULL) {
                    740:                if (pmap_enter_pv(pmap, va, pg, &npte) != 0) {
                    741:                        if (flags & PMAP_CANFAIL)
                    742:                                return ENOMEM;
                    743:                        panic("pmap_enter: pmap_enter_pv() failed");
                    744:                }
                    745:        }
                    746:
                    747:        pte += uvtopte(va);
                    748:
                    749:        /*
                    750:         * Now validate mapping with desired protection/wiring.
                    751:         * Assume uniform modified and referenced status for all
                    752:         * MIPS pages in a OpenBSD page.
                    753:         */
                    754:        npte |= vad_to_pfn(pa);
                    755:        if (pmap->pm_tlbgen == tlbpid_gen) {
                    756:                DPRINTF(PDB_ENTER, ("pmap_enter: new pte %x tlbpid %d\n",
                    757:                        npte, pmap->pm_tlbpid));
                    758:        } else {
                    759:                DPRINTF(PDB_ENTER, ("pmap_enter: new pte 0x%08x\n", npte));
                    760:        }
                    761:
                    762:        if ((pte->pt_entry & PG_V) && pa != pfn_to_pad(pte->pt_entry)) {
                    763:                pmap_remove(pmap, va, va + NBPG);
                    764:                stat_count(enter_stats.mchange);
                    765:        }
                    766:
                    767:        if (!(pte->pt_entry & PG_V)) {
                    768:                pmap->pm_stats.resident_count++;
                    769:        }
                    770:        pte->pt_entry = npte;
                    771:        if (pmap->pm_tlbgen == tlbpid_gen) {
                    772:                tlb_update(va | (pmap->pm_tlbpid << VMTLB_PID_SHIFT), npte);
                    773:        }
                    774:
                    775:        /*
                    776:         *  If mapping a memory space address invalidate ICache.
                    777:         */
                    778:        if (pg != NULL && (prot & VM_PROT_EXECUTE))
                    779:                Mips_InvalidateICache(va, PAGE_SIZE);
                    780:
                    781:        return 0;
                    782: }
                    783:
                    784: void
                    785: pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot)
                    786: {
                    787:        pt_entry_t *pte;
                    788:        u_int npte;
                    789:
                    790:        DPRINTF(PDB_FOLLOW|PDB_ENTER,
                    791:                ("pmap_kenter_pa(%p, %p, 0x%x)\n", va, pa, prot));
                    792:
                    793:        npte = vad_to_pfn(pa) | PG_G;
                    794:        if (prot & VM_PROT_WRITE)
                    795:                npte |= PG_RWPAGE;
                    796:        else
                    797:                npte |= PG_ROPAGE;
                    798:        pte = kvtopte(va);
                    799:        pte->pt_entry = npte;
                    800:        tlb_update(va, npte);
                    801: }
                    802:
                    803: /*
                    804:  *  Remove a mapping from the kernel map table. When doing this
                    805:  *  the cache must be synced for the VA mapped since we mapped
                    806:  *  pages behind the back of the VP tracking system.
                    807:  */
                    808: void
                    809: pmap_kremove(vaddr_t va, vsize_t len)
                    810: {
                    811:        pt_entry_t *pte;
                    812:        vaddr_t eva;
                    813:        u_int entry;
                    814:
                    815:        DPRINTF(PDB_FOLLOW|PDB_REMOVE, ("pmap_kremove(%p, %p)\n", va, len));
                    816:
                    817:        pte = kvtopte(va);
                    818:        eva = va + len;
                    819:        for (; va < eva; va += PAGE_SIZE, pte++) {
                    820:                entry = pte->pt_entry;
                    821:                if (!(entry & PG_V))
                    822:                        continue;
                    823:                Mips_HitSyncDCache(va, PAGE_SIZE);
                    824:                pte->pt_entry = PG_NV | PG_G;
                    825:                tlb_flush_addr(va);
                    826:        }
                    827: }
                    828:
                    829: void
                    830: pmap_unwire(pmap_t pmap, vaddr_t va)
                    831: {
                    832:        /* XXX this pmap does not handle wired mappings yet... */
                    833: }
                    834:
                    835: /*
                    836:  *     Routine:        pmap_extract
                    837:  *     Function:
                    838:  *             Extract the physical page address associated
                    839:  *             with the given map/virtual_address pair.
                    840:  */
                    841: boolean_t
                    842: pmap_extract(pmap_t pmap, vaddr_t va, paddr_t *pap)
                    843: {
                    844:        boolean_t rv = TRUE;
                    845:        paddr_t pa;
                    846:        pt_entry_t *pte;
                    847:
                    848:        if (pmap == pmap_kernel()) {
                    849:                if (IS_XKPHYS(va))
                    850:                        pa = XKPHYS_TO_PHYS(va);
                    851:                else if (va >= (vaddr_t)KSEG0_BASE &&
                    852:                    va < (vaddr_t)KSEG0_BASE + KSEG_SIZE)
                    853:                        pa = KSEG0_TO_PHYS(va);
                    854:                else if (va >= (vaddr_t)KSEG1_BASE &&
                    855:                    va < (vaddr_t)KSEG1_BASE + KSEG_SIZE)
                    856:                        pa = KSEG1_TO_PHYS(va);
                    857:                else {
                    858: #ifdef DIAGNOSTIC
                    859:                        if (va < VM_MIN_KERNEL_ADDRESS ||
                    860:                            va >= VM_MAX_KERNEL_ADDRESS)
                    861:                                panic("pmap_extract(%p, %p)", pmap, va);
                    862: #endif
                    863:                        pte = kvtopte(va);
                    864:                        if (pte->pt_entry & PG_V)
                    865:                                pa = pfn_to_pad(pte->pt_entry) |
                    866:                                    (va & PAGE_MASK);
                    867:                        else
                    868:                                rv = FALSE;
                    869:                }
                    870:        } else {
                    871:                if (!(pte = pmap_segmap(pmap, va)))
                    872:                        rv = FALSE;
                    873:                else {
                    874:                        pte += uvtopte(va);
                    875:                        pa = pfn_to_pad(pte->pt_entry) | (va & PAGE_MASK);
                    876:                }
                    877:        }
                    878:        if (rv != FALSE)
                    879:                *pap = pa;
                    880:
                    881:        DPRINTF(PDB_FOLLOW, ("pmap_extract(%p, %p)=%p(%d)", pmap, va, pa, rv));
                    882:
                    883:        return (rv);
                    884: }
                    885:
                    886: /*
                    887:  * Find first virtual address >= *vap that
                    888:  * will not cause cache aliases.
                    889:  */
                    890: void
                    891: pmap_prefer(paddr_t foff, vaddr_t *vap)
                    892: {
                    893: #if 1
                    894:        *vap += (foff - *vap) & (CpuCacheAliasMask | PAGE_MASK);
                    895: #else
                    896:        *vap += (*vap ^ foff) & CpuCacheAliasMask;
                    897: #endif
                    898: }
                    899:
                    900: /*
                    901:  *     Copy the range specified by src_addr/len
                    902:  *     from the source map to the range dst_addr/len
                    903:  *     in the destination map.
                    904:  *
                    905:  *     This routine is only advisory and need not do anything.
                    906:  */
                    907: void
                    908: pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr)
                    909:        pmap_t dst_pmap;
                    910:        pmap_t src_pmap;
                    911:        vaddr_t dst_addr;
                    912:        vsize_t len;
                    913:        vaddr_t src_addr;
                    914: {
                    915:
                    916:        DPRINTF(PDB_FOLLOW, ("pmap_copy(%p, %p, %p, %p, %p)\n",
                    917:               dst_pmap, src_pmap, dst_addr, len, src_addr));
                    918: }
                    919:
                    920: /*
                    921:  *     pmap_zero_page zeros the specified (machine independent) page.
                    922:  */
                    923: void
                    924: pmap_zero_page(struct vm_page *pg)
                    925: {
                    926:        paddr_t phys = VM_PAGE_TO_PHYS(pg);
                    927:        vaddr_t va;
                    928:        pv_entry_t pv;
                    929:
                    930:        DPRINTF(PDB_FOLLOW, ("pmap_zero_page(%p)\n", phys));
                    931:
                    932:        va = (vaddr_t)PHYS_TO_XKPHYS(phys, CCA_NONCOHERENT);
                    933:        pv = pg_to_pvh(pg);
                    934:        if ((pg->pg_flags & PV_CACHED) &&
                    935:            ((pv->pv_va ^ va) & CpuCacheAliasMask) != 0) {
                    936:                Mips_SyncDCachePage(pv->pv_va);
                    937:        }
                    938:        mem_zero_page(va);
                    939:        Mips_HitSyncDCache(va, PAGE_SIZE);
                    940: }
                    941:
                    942: /*
                    943:  *     pmap_copy_page copies the specified (machine independent) page.
                    944:  *
                    945:  *     We do the copy phys to phys and need to check if there may be
                    946:  *     a virtual coherence problem. If so flush the cache for the
                    947:  *     areas before copying, and flush afterwards.
                    948:  */
                    949: void
                    950: pmap_copy_page(struct vm_page *srcpg, struct vm_page *dstpg)
                    951: {
                    952:        paddr_t src, dst;
                    953:        vaddr_t s, d;
                    954:        int df = 1;
                    955:        int sf = 1;
                    956:        pv_entry_t pv;
                    957:
                    958:        src = VM_PAGE_TO_PHYS(srcpg);
                    959:        dst = VM_PAGE_TO_PHYS(dstpg);
                    960:        s = (vaddr_t)PHYS_TO_XKPHYS(src, CCA_NONCOHERENT);
                    961:        d = (vaddr_t)PHYS_TO_XKPHYS(dst, CCA_NONCOHERENT);
                    962:
                    963:        DPRINTF(PDB_FOLLOW, ("pmap_copy_page(%p, %p)\n", src, dst));
                    964:
                    965:        pv = pg_to_pvh(srcpg);
                    966:        if ((srcpg->pg_flags & PV_CACHED) &&
                    967:            (sf = ((pv->pv_va ^ (long)s) & CpuCacheAliasMask) != 0)) {
                    968:                Mips_SyncDCachePage(pv->pv_va);
                    969:        }
                    970:        pv = pg_to_pvh(dstpg);
                    971:        if ((dstpg->pg_flags & PV_CACHED) &&
                    972:            (df = ((pv->pv_va ^ (long)d) & CpuCacheAliasMask) != 0)) {
                    973:                Mips_SyncDCachePage(pv->pv_va);
                    974:        }
                    975:
                    976:        memcpy((void *)d, (void *)s, PAGE_SIZE);
                    977:
                    978:        if (sf) {
                    979:                Mips_HitSyncDCache(s, PAGE_SIZE);
                    980:        }
                    981:        Mips_HitSyncDCache(d, PAGE_SIZE);
                    982: }
                    983:
                    984: /*
                    985:  *  Clear the modify bits on the specified physical page.
                    986:  *  Also sync the cache so it reflects the new clean state of the page.
                    987:  */
                    988: boolean_t
                    989: pmap_clear_modify(struct vm_page *pg)
                    990: {
                    991:        pv_entry_t pv;
                    992:        pt_entry_t *pte;
                    993:        unsigned entry;
                    994:        boolean_t rv = FALSE;
                    995:        int s;
                    996:
                    997:        DPRINTF(PDB_FOLLOW, ("pmap_clear_modify(%p)\n", VM_PAGE_TO_PHYS(pg)));
                    998:
                    999:        pv = pg_to_pvh(pg);
                   1000:        s = splvm();
                   1001:        if (pg->pg_flags & PV_ATTR_MOD) {
                   1002:                atomic_clearbits_int(&pg->pg_flags, PV_ATTR_MOD);
                   1003:                rv = TRUE;
                   1004:        }
                   1005:        if (pg->pg_flags & PV_CACHED)
                   1006:                Mips_SyncDCachePage(pv->pv_va);
                   1007:
                   1008:        for (; pv != NULL; pv = pv->pv_next) {
                   1009:                if (pv->pv_pmap == pmap_kernel()) {
                   1010:                        pte = kvtopte(pv->pv_va);
                   1011:                        entry = pte->pt_entry;
                   1012:                        if ((entry & PG_V) != 0 && (entry & PG_M) != 0) {
                   1013:                                rv = TRUE;
                   1014:                                entry &= ~PG_M;
                   1015:                                pte->pt_entry = entry;
                   1016:                                tlb_update(pv->pv_va, entry);
                   1017:                        }
                   1018:                } else if (pv->pv_pmap != NULL) {
                   1019:                        if ((pte = pmap_segmap(pv->pv_pmap, pv->pv_va)) == NULL)
                   1020:                                continue;
                   1021:                        pte += uvtopte(pv->pv_va);
                   1022:                        entry = pte->pt_entry;
                   1023:                        if ((entry & PG_V) != 0 && (entry & PG_M) != 0) {
                   1024:                                rv = TRUE;
                   1025:                                entry &= ~PG_M;
                   1026:                                pte->pt_entry = entry;
                   1027:                                if (pv->pv_pmap->pm_tlbgen == tlbpid_gen)
                   1028:                                        tlb_update(pv->pv_va | (pv->pv_pmap->pm_tlbpid <<
                   1029:                                                VMTLB_PID_SHIFT), entry);
                   1030:                        }
                   1031:                }
                   1032:        }
                   1033:        splx(s);
                   1034:
                   1035:        return rv;
                   1036: }
                   1037:
                   1038: void
                   1039: pmap_set_modify(struct vm_page *pg)
                   1040: {
                   1041:        atomic_setbits_int(&pg->pg_flags, PV_ATTR_MOD | PV_ATTR_REF);
                   1042: }
                   1043:
                   1044: /*
                   1045:  *     pmap_clear_reference:
                   1046:  *
                   1047:  *     Clear the reference bit on the specified physical page.
                   1048:  */
                   1049: boolean_t
                   1050: pmap_clear_reference(struct vm_page *pg)
                   1051: {
                   1052:        boolean_t rv;
                   1053:
                   1054:        DPRINTF(PDB_FOLLOW, ("pmap_clear_reference(%p)\n", VM_PAGE_TO_PHYS(pg)));
                   1055:
                   1056:        rv = (pg->pg_flags & PV_ATTR_REF) != 0;
                   1057:        atomic_clearbits_int(&pg->pg_flags, PV_ATTR_REF);
                   1058:        return rv;
                   1059: }
                   1060:
                   1061: /*
                   1062:  *     pmap_is_referenced:
                   1063:  *
                   1064:  *     Return whether or not the specified physical page is referenced
                   1065:  *     by any physical maps.
                   1066:  */
                   1067: boolean_t
                   1068: pmap_is_referenced(struct vm_page *pg)
                   1069: {
                   1070:        return (pg->pg_flags & PV_ATTR_REF) != 0;
                   1071: }
                   1072:
                   1073: /*
                   1074:  *     pmap_is_modified:
                   1075:  *
                   1076:  *     Return whether or not the specified physical page is modified
                   1077:  *     by any physical maps.
                   1078:  */
                   1079: boolean_t
                   1080: pmap_is_modified(struct vm_page *pg)
                   1081: {
                   1082:        return (pg->pg_flags & PV_ATTR_MOD) != 0;
                   1083: }
                   1084:
                   1085: /*
                   1086:  * Miscellaneous support routines not part of the pmap API
                   1087:  */
                   1088:
                   1089: /*
                   1090:  *     Return RO protection of page.
                   1091:  */
                   1092: int
                   1093: pmap_is_page_ro(pmap_t pmap, vaddr_t va, int entry)
                   1094: {
                   1095:        return (entry & PG_RO);
                   1096: }
                   1097:
                   1098:
                   1099: /*
                   1100:  *  Walk the PV tree for a physical page and change all its
                   1101:  *  mappings to cached or uncached.
                   1102:  */
                   1103: void
                   1104: pmap_page_cache(vm_page_t pg, int mode)
                   1105: {
                   1106:        pv_entry_t pv;
                   1107:        pt_entry_t *pte;
                   1108:        u_int entry;
                   1109:        u_int newmode;
                   1110:        int s;
                   1111:
                   1112:        DPRINTF(PDB_FOLLOW|PDB_ENTER, ("pmap_page_uncache(%p)\n", pg));
                   1113:
                   1114:        newmode = mode & PV_UNCACHED ? PG_UNCACHED : PG_CACHED;
                   1115:        pv = pg_to_pvh(pg);
                   1116:
                   1117:        s = splvm();
                   1118:        for (; pv != NULL; pv = pv->pv_next) {
                   1119:                if (pv->pv_pmap == pmap_kernel()) {
                   1120:                        pte = kvtopte(pv->pv_va);
                   1121:                        entry = pte->pt_entry;
                   1122:                        if (entry & PG_V) {
                   1123:                                entry = (entry & ~PG_CACHEMODE) | newmode;
                   1124:                                pte->pt_entry = entry;
                   1125:                                tlb_update(pv->pv_va, entry);
                   1126:                        }
                   1127:                } else {
                   1128:                        if ((pte = pmap_segmap(pv->pv_pmap, pv->pv_va))) {
                   1129:                                pte += uvtopte(pv->pv_va);
                   1130:                                entry = pte->pt_entry;
                   1131:                                if (entry & PG_V) {
                   1132:                                        entry = (entry & ~PG_CACHEMODE) | newmode;
                   1133:                                        pte->pt_entry = entry;
                   1134:                                        if (pv->pv_pmap->pm_tlbgen == tlbpid_gen)
                   1135:                                                tlb_update(pv->pv_va | (pv->pv_pmap->pm_tlbpid <<
                   1136:                                                        VMTLB_PID_SHIFT), entry);
                   1137:                                }
                   1138:                        }
                   1139:                }
                   1140:        }
                   1141:        atomic_clearbits_int(&pg->pg_flags, PV_CACHED | PV_UNCACHED);
                   1142:        atomic_setbits_int(&pg->pg_flags, mode);
                   1143:        splx(s);
                   1144: }
                   1145:
                   1146: /*
                   1147:  *  Use this function to allocate pages for the mapping tables.
                   1148:  *  Mapping tables are walked by the TLB miss code and are mapped in
                   1149:  *  XKPHYS to avoid additional page faults when servicing a TLB miss.
                   1150:  */
                   1151: int
                   1152: pmap_page_alloc(vaddr_t *ret)
                   1153: {
                   1154:        vm_page_t pg;
                   1155:
                   1156:        pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_USERESERVE | UVM_PGA_ZERO);
                   1157:        if (pg == NULL)
                   1158:                return ENOMEM;
                   1159:
                   1160:        *ret = PHYS_TO_XKPHYS(VM_PAGE_TO_PHYS(pg), CCA_NONCOHERENT);
                   1161:        return 0;
                   1162: }
                   1163:
                   1164: void
                   1165: pmap_page_free(vaddr_t va)
                   1166: {
                   1167:        vm_page_t pg;
                   1168:
                   1169:        pg = PHYS_TO_VM_PAGE(XKPHYS_TO_PHYS(va));
                   1170:        uvm_pagefree(pg);
                   1171: }
                   1172:
                   1173: /*
                   1174:  * Allocate a hardware PID and return it.
                   1175:  * It takes almost as much or more time to search the TLB for a
                   1176:  * specific PID and flush those entries as it does to flush the entire TLB.
                   1177:  * Therefore, when we allocate a new PID, we just take the next number. When
                   1178:  * we run out of numbers, we flush the TLB, increment the generation count
                   1179:  * and start over. PID zero is reserved for kernel use.
                   1180:  * This is called only by switch().
                   1181:  */
                   1182: int
                   1183: pmap_alloc_tlbpid(struct proc *p)
                   1184: {
                   1185:        pmap_t pmap;
                   1186:        int id;
                   1187:
                   1188:        pmap = p->p_vmspace->vm_map.pmap;
                   1189:        if (pmap->pm_tlbgen != tlbpid_gen) {
                   1190:                id = tlbpid_cnt;
                   1191:                if (id >= VMNUM_PIDS) {
                   1192:                        tlb_flush(sys_config.cpu[0].tlbsize);
                   1193:                        /* reserve tlbpid_gen == 0 to alway mean invalid */
                   1194:                        if (++tlbpid_gen == 0)
                   1195:                                tlbpid_gen = 1;
                   1196:                        id = 1;
                   1197:                }
                   1198:                tlbpid_cnt = id + 1;
                   1199:                pmap->pm_tlbpid = id;
                   1200:                pmap->pm_tlbgen = tlbpid_gen;
                   1201:        } else {
                   1202:                id = pmap->pm_tlbpid;
                   1203:        }
                   1204:
                   1205:        if (curproc) {
                   1206:                DPRINTF(PDB_FOLLOW|PDB_TLBPID,
                   1207:                        ("pmap_alloc_tlbpid: curproc %d '%s' ",
                   1208:                                curproc->p_pid, curproc->p_comm));
                   1209:        } else {
                   1210:                DPRINTF(PDB_FOLLOW|PDB_TLBPID,
                   1211:                        ("pmap_alloc_tlbpid: curproc <none> "));
                   1212:        }
                   1213:        DPRINTF(PDB_FOLLOW|PDB_TLBPID, ("segtab %p tlbpid %d pid %d '%s'\n",
                   1214:                        pmap->pm_segtab, id, p->p_pid, p->p_comm));
                   1215:
                   1216:        return (id);
                   1217: }
                   1218:
                   1219: /*
                   1220:  * Enter the pmap and virtual address into the physical to virtual map table.
                   1221:  */
                   1222: int
                   1223: pmap_enter_pv(pmap_t pmap, vaddr_t va, vm_page_t pg, u_int *npte)
                   1224: {
                   1225:        pv_entry_t pv, npv;
                   1226:        int s;
                   1227:
                   1228:        pv = pg_to_pvh(pg);
                   1229:
                   1230:        s = splvm();
                   1231:        if (pv->pv_pmap == NULL) {
                   1232:                /*
                   1233:                 * No entries yet, use header as the first entry
                   1234:                 */
                   1235:
                   1236:                DPRINTF(PDB_PVENTRY,
                   1237:                        ("pmap_enter: first pv: pmap %p va %p pa %p\n",
                   1238:                                pmap, va, VM_PAGE_TO_PHYS(pg)));
                   1239:
                   1240:                stat_count(enter_stats.firstpv);
                   1241:
                   1242:                pv->pv_va = va;
                   1243:                atomic_setbits_int(&pg->pg_flags, PV_CACHED);
                   1244:                pv->pv_pmap = pmap;
                   1245:                pv->pv_next = NULL;
                   1246:        } else {
                   1247:                if (pg->pg_flags & PV_UNCACHED) {
                   1248:                        /*
                   1249:                         * If page is mapped uncached it's either because
                   1250:                         * an uncached mapping was requested or we have a
                   1251:                         * VAC situation. Map this page uncached as well.
                   1252:                         */
                   1253:                        *npte = (*npte & ~PG_CACHEMODE) | PG_UNCACHED;
                   1254:                } else if (CpuCacheAliasMask != 0) {
                   1255:                        /*
                   1256:                         * We have a VAC possibility.  Check if virtual
                   1257:                         * address of current mappings are compatible
                   1258:                         * with this new mapping. Only need to check first
                   1259:                         * since all others have been checked compatible
                   1260:                         * when added. If they are incompatible, remove
                   1261:                         * all mappings, flush the cache and set page
                   1262:                         * to be mapped uncached.
                   1263:                         */
                   1264:                        if (((pv->pv_va ^ va) & CpuCacheAliasMask) != 0) {
                   1265: #ifdef PMAP_DEBUG
                   1266:                                printf("pmap_enter: VAC for pa %p, %p !=  %p\n",
                   1267:                                    VM_PAGE_TO_PHYS(pg), npv->pv_va, va);
                   1268: #endif
                   1269:                                pmap_page_cache(pg, PV_UNCACHED);
                   1270:                                Mips_SyncDCachePage(pv->pv_va);
                   1271:                                *npte = (*npte & ~PG_CACHEMODE) | PG_UNCACHED;
                   1272:                        }
                   1273:                }
                   1274:
                   1275:                /*
                   1276:                 * There is at least one other VA mapping this page.
                   1277:                 * Place this entry after the header.
                   1278:                 *
                   1279:                 * Note: the entry may already be in the table if
                   1280:                 * we are only changing the protection bits.
                   1281:                 */
                   1282:                for (npv = pv; npv; npv = npv->pv_next) {
                   1283:                        if (pmap == npv->pv_pmap && va == npv->pv_va) {
                   1284:                                return 0;
                   1285:                        }
                   1286:                }
                   1287:
                   1288:                DPRINTF(PDB_PVENTRY,
                   1289:                        ("pmap_enter: new pv: pmap %x va %x pg %p\n",
                   1290:                            pmap, va, VM_PAGE_TO_PHYS(pg)));
                   1291:
                   1292:                npv = pmap_pv_alloc();
                   1293:                if (npv == NULL) {
                   1294:                        splx(s);
                   1295:                        return ENOMEM;
                   1296:                }
                   1297:                npv->pv_va = va;
                   1298:                npv->pv_pmap = pmap;
                   1299:                npv->pv_next = pv->pv_next;
                   1300:                pv->pv_next = npv;
                   1301:
                   1302:                if (!npv->pv_next)
                   1303:                        stat_count(enter_stats.secondpv);
                   1304:        }
                   1305:
                   1306:        splx(s);
                   1307:        return 0;
                   1308: }
                   1309:
                   1310: /*
                   1311:  * Remove a physical to virtual address translation from the PV table.
                   1312:  */
                   1313: void
                   1314: pmap_remove_pv(pmap_t pmap, vaddr_t va, paddr_t pa)
                   1315: {
                   1316:        pv_entry_t pv, npv;
                   1317:        vm_page_t pg;
                   1318:        int s;
                   1319:
                   1320:        DPRINTF(PDB_FOLLOW|PDB_PVENTRY,
                   1321:                ("pmap_remove_pv(%p, %p, %p)\n", pmap, va, pa));
                   1322:
                   1323:        /*
                   1324:         * Remove page from the PV table
                   1325:         */
                   1326:        pg = PHYS_TO_VM_PAGE(pa);
                   1327:        if (pg == NULL)
                   1328:                return;
                   1329:
                   1330:        pv = pg_to_pvh(pg);
                   1331:        s = splvm();
                   1332:        /*
                   1333:         * If we are removing the first entry on the list, copy up
                   1334:         * the next entry, if any, and free that pv item since the
                   1335:         * first root item can't be freed. Else walk the list.
                   1336:         */
                   1337:        if (pmap == pv->pv_pmap && va == pv->pv_va) {
                   1338:                npv = pv->pv_next;
                   1339:                if (npv) {
                   1340:                        *pv = *npv;
                   1341:                        pmap_pv_free(npv);
                   1342:                } else {
                   1343:                        pv->pv_pmap = NULL;
                   1344:                        atomic_clearbits_int(&pg->pg_flags,
                   1345:                            (PG_PMAP0 | PG_PMAP1 | PG_PMAP2 | PG_PMAP3) &
                   1346:                            ~PV_PRESERVE);
                   1347:                        Mips_SyncDCachePage(va);
                   1348:                }
                   1349:                stat_count(remove_stats.pvfirst);
                   1350:        } else {
                   1351:                for (npv = pv->pv_next; npv; pv = npv, npv = npv->pv_next) {
                   1352:                        stat_count(remove_stats.pvsearch);
                   1353:                        if (pmap == npv->pv_pmap && va == npv->pv_va)
                   1354:                                break;
                   1355:                }
                   1356:                if (npv != NULL) {
                   1357:                        pv->pv_next = npv->pv_next;
                   1358:                        pmap_pv_free(npv);
                   1359:                } else {
                   1360: #ifdef DIAGNOSTIC
                   1361:                        panic("pmap_remove_pv(%x, %x, %x) not found",
                   1362:                            pmap, va, pa);
                   1363: #endif
                   1364:                }
                   1365:        }
                   1366:        splx(s);
                   1367: }
                   1368:
                   1369: /*==================================================================*/
                   1370: /* Bus space map utility functions */
                   1371:
                   1372: int
                   1373: bus_mem_add_mapping(bus_addr_t bpa, bus_size_t size, int cacheable,
                   1374:                        bus_space_handle_t *bshp)
                   1375: {
                   1376:        bus_addr_t vaddr;
                   1377:        bus_addr_t spa, epa;
                   1378:        bus_size_t off;
                   1379:        int len;
                   1380:
                   1381:        spa = trunc_page(bpa);
                   1382:        epa = bpa + size;
                   1383:        off = bpa - spa;
                   1384:        len = size+off;
                   1385:
                   1386:        vaddr = uvm_km_valloc_wait(kernel_map, len);
                   1387:        *bshp = vaddr + off;
                   1388: #ifdef DEBUG_BUS_MEM_ADD_MAPPING
                   1389:        printf("map bus %x size %x to %x vbase %x\n", bpa, size, *bshp, spa);
                   1390: #endif
                   1391:        for (; len > 0; len -= NBPG) {
                   1392:                pt_entry_t *pte;
                   1393:                u_int npte;
                   1394:
                   1395:                npte = vad_to_pfn(spa) | PG_G;
                   1396:                npte |= PG_V | PG_M | PG_IOPAGE;
                   1397:                pte = kvtopte(vaddr);
                   1398:                pte->pt_entry = npte;
                   1399:                tlb_update(vaddr, npte);
                   1400:
                   1401:                spa += NBPG;
                   1402:                vaddr += NBPG;
                   1403:        }
                   1404:        return 0;
                   1405: }

CVSweb