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

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

1.1       nbrk        1: /*     $OpenBSD: pmap.c,v 1.5 2007/04/13 18:57:49 art Exp $    */
                      2:
                      3: /*
                      4:  * Copyright (c) 2005 Michael Shalayeff
                      5:  * All rights reserved.
                      6:  *
                      7:  * Permission to use, copy, modify, and distribute this software for any
                      8:  * purpose with or without fee is hereby granted, provided that the above
                      9:  * copyright notice and this permission notice appear in all copies.
                     10:  *
                     11:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     12:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     13:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     14:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     15:  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
                     16:  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
                     17:  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     18:  */
                     19:
                     20: #define        PMAPDEBUG
                     21:
                     22: #include <sys/param.h>
                     23: #include <sys/systm.h>
                     24: #include <sys/lock.h>
                     25: #include <sys/user.h>
                     26: #include <sys/proc.h>
                     27: #include <sys/pool.h>
                     28: #include <sys/extent.h>
                     29:
                     30: #include <uvm/uvm.h>
                     31:
                     32: #include <machine/iomod.h>
                     33:
                     34: #include <dev/rndvar.h>
                     35:
                     36: #ifdef PMAPDEBUG
                     37: #define        DPRINTF(l,s)    do {            \
                     38:        if ((pmapdebug & (l)) == (l))   \
                     39:                printf s;               \
                     40: } while(0)
                     41: #define        PDB_FOLLOW      0x00000001
                     42: #define        PDB_INIT        0x00000002
                     43: #define        PDB_ENTER       0x00000004
                     44: #define        PDB_REMOVE      0x00000008
                     45: #define        PDB_CREATE      0x00000010
                     46: #define        PDB_PTPAGE      0x00000020
                     47: #define        PDB_CACHE       0x00000040
                     48: #define        PDB_BITS        0x00000080
                     49: #define        PDB_COLLECT     0x00000100
                     50: #define        PDB_PROTECT     0x00000200
                     51: #define        PDB_EXTRACT     0x00000400
                     52: #define        PDB_VP          0x00000800
                     53: #define        PDB_PV          0x00001000
                     54: #define        PDB_PARANOIA    0x00002000
                     55: #define        PDB_WIRING      0x00004000
                     56: #define        PDB_PMAP        0x00008000
                     57: #define        PDB_STEAL       0x00010000
                     58: #define        PDB_PHYS        0x00020000
                     59: #define        PDB_POOL        0x00040000
                     60: int pmapdebug = 0
                     61:        | PDB_INIT
                     62: /*     | PDB_FOLLOW */
                     63: /*     | PDB_VP */
                     64: /*     | PDB_PV */
                     65: /*     | PDB_ENTER */
                     66: /*     | PDB_REMOVE */
                     67: /*     | PDB_STEAL */
                     68: /*     | PDB_PROTECT */
                     69: /*     | PDB_PHYS */
                     70:        ;
                     71: #else
                     72: #define        DPRINTF(l,s)    /* */
                     73: #endif
                     74:
                     75: paddr_t physical_steal, physical_end;
                     76:
                     77: struct pmap    kernel_pmap_store;
                     78: struct pool    pmap_pmap_pool;
                     79: struct pool    pmap_pv_pool;
                     80: int            pmap_pvlowat = 252;
                     81: int            pmap_initialized;
                     82: int            pmap_nkpdes = 32;
                     83:
                     84: pt_entry_t     hppa_prot[8];
                     85: #define        pmap_prot(m,vp) (hppa_prot[(vp)] | ((m) == pmap_kernel()? 0 : PTE_USER))
                     86:
                     87: pt_entry_t     kernel_ptes[] = {
                     88:        PTE_EXEC  | PTE_ORDER | PTE_PREDICT | PTE_WIRED |
                     89:            TLB_PAGE(0x000000) | PTE_PG4M,
                     90:        PTE_WRITE | PTE_ORDER | PTE_DIRTY   | PTE_WIRED |
                     91:            TLB_PAGE(0x400000) | PTE_PG4M,
                     92:        PTE_WRITE | PTE_ORDER | PTE_DIRTY   | PTE_WIRED |
                     93:            TLB_PAGE(0x800000) | PTE_PG4M,
                     94:        PTE_WRITE | PTE_ORDER | PTE_DIRTY   | PTE_WIRED |
                     95:            TLB_PAGE(0xc00000) | PTE_PG4M
                     96: };
                     97:
                     98: #define        pmap_pvh_attrs(a) \
                     99:        (((a) & PTE_DIRTY) | ((a) ^ PTE_REFTRAP))
                    100:
                    101: struct vm_page *
                    102: pmap_pagealloc(int wait)
                    103: {
                    104:        struct vm_page *pg;
                    105:
                    106:        if ((pg = uvm_pagealloc(NULL, 0, NULL,
                    107:            UVM_PGA_USERESERVE | UVM_PGA_ZERO)) == NULL)
                    108:                printf("pmap_pagealloc fail\n");
                    109:
                    110:        return (pg);
                    111: }
                    112:
                    113: volatile pt_entry_t *
                    114: pmap_pde_get(volatile u_int32_t *pd, vaddr_t va)
                    115: {
                    116:        int i;
                    117:
                    118:        DPRINTF(PDB_FOLLOW|PDB_VP,
                    119:            ("pmap_pde_get(%p, 0x%lx)\n", pd, va));
                    120:
                    121:        i = (va & PIE_MASK) >> PIE_SHIFT;
                    122:        if (i) {
                    123:                pd = (volatile u_int32_t *)((u_int64_t)pd[i] << PAGE_SHIFT);
                    124:
                    125:                if (!pd)
                    126:                        return (NULL);
                    127:        } else
                    128:                pd += PAGE_SIZE / sizeof(*pd);
                    129:
                    130:        i = (va & PDE_MASK) >> PDE_SHIFT;
                    131:        return (pt_entry_t *)((u_int64_t)pd[i] << PAGE_SHIFT);
                    132: }
                    133:
                    134: void
                    135: pmap_pde_set(struct pmap *pm, vaddr_t va, paddr_t ptp)
                    136: {
                    137:        volatile u_int32_t *pd = pm->pm_pdir;
                    138:        int i;
                    139:
                    140:        DPRINTF(PDB_FOLLOW|PDB_VP,
                    141:            ("pmap_pde_set(%p, 0x%lx, 0x%lx)\n", pm, va, ptp));
                    142:
                    143:        i = (va & PIE_MASK) >> PIE_SHIFT;
                    144:        if (i)
                    145:                pd = (volatile u_int32_t *)((u_int64_t)pd[i] << PAGE_SHIFT);
                    146:        else
                    147:                pd += PAGE_SIZE / sizeof(*pd);
                    148:
                    149:        i = (va & PDE_MASK) >> PDE_SHIFT;
                    150:        pd[i] = ptp >> PAGE_SHIFT;
                    151: }
                    152:
                    153: pt_entry_t *
                    154: pmap_pde_alloc(struct pmap *pm, vaddr_t va, struct vm_page **pdep)
                    155: {
                    156:        struct vm_page *pg;
                    157:        paddr_t pa;
                    158:
                    159:        DPRINTF(PDB_FOLLOW|PDB_VP,
                    160:            ("pmap_pde_alloc(%p, 0x%lx, %p)\n", pm, va, pdep));
                    161:
                    162:        if ((pg = pmap_pagealloc(0)) == NULL)
                    163:                return (NULL);
                    164:
                    165:        pa = VM_PAGE_TO_PHYS(pg);
                    166:
                    167:        DPRINTF(PDB_FOLLOW|PDB_VP, ("pmap_pde_alloc: pde %lx\n", pa));
                    168:
                    169:        atomic_clearbits_int(&pg->pg_flags, PG_BUSY);
                    170:        pg->wire_count = 1;             /* no mappings yet */
                    171:        pmap_pde_set(pm, va, pa);
                    172:        pm->pm_stats.resident_count++;  /* count PTP as resident */
                    173:        pm->pm_ptphint = pg;
                    174:        if (pdep)
                    175:                *pdep = pg;
                    176:        return ((pt_entry_t *)pa);
                    177: }
                    178:
                    179: static __inline struct vm_page *
                    180: pmap_pde_ptp(struct pmap *pm, volatile pt_entry_t *pde)
                    181: {
                    182:        paddr_t pa = (paddr_t)pde;
                    183:
                    184:        DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_pde_ptp(%p, %p)\n", pm, pde));
                    185:
                    186:        if (pm->pm_ptphint && VM_PAGE_TO_PHYS(pm->pm_ptphint) == pa)
                    187:                return (pm->pm_ptphint);
                    188:
                    189:        DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_pde_ptp: lookup 0x%lx\n", pa));
                    190:
                    191:        return (PHYS_TO_VM_PAGE(pa));
                    192: }
                    193:
                    194: static __inline void
                    195: pmap_pde_release(struct pmap *pmap, vaddr_t va, struct vm_page *ptp)
                    196: {
                    197:        DPRINTF(PDB_FOLLOW|PDB_PV,
                    198:            ("pmap_pde_release(%p, 0x%lx, %p)\n", pmap, va, ptp));
                    199:
                    200:        if (pmap != pmap_kernel() && --ptp->wire_count <= 1) {
                    201:                DPRINTF(PDB_FOLLOW|PDB_PV,
                    202:                    ("pmap_pde_release: disposing ptp %p\n", ptp));
                    203:                pmap_pde_set(pmap, va, 0);
                    204:                pmap->pm_stats.resident_count--;
                    205:                if (pmap->pm_ptphint == ptp)
                    206:                        pmap->pm_ptphint = NULL;
                    207:                ptp->wire_count = 0;
                    208: #ifdef DIAGNOSTIC
                    209:                if (ptp->pg_flags & PG_BUSY)
                    210:                        panic("pmap_pde_release: busy page table page");
                    211: #endif
                    212:                pdcache(HPPA_SID_KERNEL, (vaddr_t)ptp, PAGE_SIZE);
                    213:                uvm_pagefree(ptp);
                    214:        }
                    215: }
                    216:
                    217: static __inline pt_entry_t
                    218: pmap_pte_get(volatile pt_entry_t *pde, vaddr_t va)
                    219: {
                    220:        DPRINTF(PDB_FOLLOW|PDB_VP,
                    221:            ("pmap_pte_get(%p, 0x%lx)\n", pde, va));
                    222:
                    223:        return (pde[(va & PTE_MASK) >> PTE_SHIFT]);
                    224: }
                    225:
                    226: static __inline void
                    227: pmap_pte_set(volatile pt_entry_t *pde, vaddr_t va, pt_entry_t pte)
                    228: {
                    229:        DPRINTF(PDB_FOLLOW|PDB_VP,
                    230:            ("pmap_pte_set(%p, 0x%lx, 0x%lx)\n", pde, va, pte));
                    231:
                    232:        pde[(va & PTE_MASK) >> PTE_SHIFT] = pte;
                    233: }
                    234:
                    235: void
                    236: pmap_pte_flush(struct pmap *pmap, vaddr_t va, pt_entry_t pte)
                    237: {
                    238:        if (pte & PTE_EXEC) {
                    239:                ficache(pmap->pm_space, va, PAGE_SIZE);
                    240:                pitlb(pmap->pm_space, va);
                    241:        }
                    242:        fdcache(pmap->pm_space, va, PAGE_SIZE);
                    243:        pdtlb(pmap->pm_space, va);
                    244: }
                    245:
                    246: static __inline pt_entry_t
                    247: pmap_vp_find(struct pmap *pm, vaddr_t va)
                    248: {
                    249:        volatile pt_entry_t *pde;
                    250:
                    251:        if (!(pde = pmap_pde_get(pm->pm_pdir, va)))
                    252:                return (0);
                    253:
                    254:        return (pmap_pte_get(pde, va));
                    255: }
                    256:
                    257: #ifdef DDB
                    258: void
                    259: pmap_dump_table(pa_space_t space, vaddr_t sva)
                    260: {
                    261:        pa_space_t sp;
                    262:        volatile pt_entry_t *pde;
                    263:        volatile u_int32_t *pd;
                    264:        pt_entry_t pte;
                    265:        vaddr_t va, pdemask;
                    266:
                    267:        if (space)
                    268:                pd = (u_int32_t *)mfctl(CR_VTOP);
                    269:        else
                    270:                pd = pmap_kernel()->pm_pdir;
                    271:
                    272:        for (pdemask = 1, va = sva ? sva : 0;
                    273:            va < VM_MAX_ADDRESS; va += PAGE_SIZE) {
                    274:                if (pdemask != (va & (PDE_MASK|PIE_MASK))) {
                    275:                        pdemask = va & (PDE_MASK|PIE_MASK);
                    276:                        if (!(pde = pmap_pde_get(pd, va))) {
                    277:                                va += ~PDE_MASK + 1 - PAGE_SIZE;
                    278:                                continue;
                    279:                        }
                    280:                        printf("%x:%8p:\n", sp, pde);
                    281:                }
                    282:
                    283:                if (!(pte = pmap_pte_get(pde, va)))
                    284:                        continue;
                    285:
                    286:                printf("0x%08lx-0x%08lx:%b\n",
                    287:                    va, PTE_PAGE(pte), PTE_GETBITS(pte), PTE_BITS);
                    288:        }
                    289: }
                    290:
                    291: void
                    292: pmap_dump_pv(paddr_t pa)
                    293: {
                    294:        struct vm_page *pg;
                    295:        struct pv_entry *pve;
                    296:
                    297:        pg = PHYS_TO_VM_PAGE(pa);
                    298:        simple_lock(&pg->mdpage.pvh_lock);
                    299:        for(pve = pg->mdpage.pvh_list; pve; pve = pve->pv_next)
                    300:                printf("%x:%lx\n", pve->pv_pmap->pm_space, pve->pv_va);
                    301:        simple_unlock(&pg->mdpage.pvh_lock);
                    302: }
                    303: #endif
                    304:
                    305: #ifdef PMAPDEBUG
                    306: int
                    307: pmap_check_alias(struct pv_entry *pve, vaddr_t va, pt_entry_t pte)
                    308: {
                    309:        int ret;
                    310:
                    311:        /* check for non-equ aliased mappings */
                    312:        for (ret = 0; pve; pve = pve->pv_next) {
                    313:                pte |= pmap_vp_find(pve->pv_pmap, pve->pv_va);
                    314:                if ((va & HPPA_PGAOFF) != (pve->pv_va & HPPA_PGAOFF) &&
                    315:                    (pte & PTE_WRITE)) {
                    316:                        printf("pmap_check_alias: "
                    317:                            "aliased writable mapping 0x%x:0x%lx\n",
                    318:                            pve->pv_pmap->pm_space, pve->pv_va);
                    319:                        ret++;
                    320:                }
                    321:        }
                    322:
                    323:        return (ret);
                    324: }
                    325: #endif
                    326:
                    327: static __inline struct pv_entry *
                    328: pmap_pv_alloc(void)
                    329: {
                    330:        struct pv_entry *pv;
                    331:
                    332:        DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_pv_alloc()\n"));
                    333:
                    334:        pv = pool_get(&pmap_pv_pool, PR_NOWAIT);
                    335:
                    336:        DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_pv_alloc: %p\n", pv));
                    337:
                    338:        return (pv);
                    339: }
                    340:
                    341: void
                    342: pmap_pv_free(struct pv_entry *pv)
                    343: {
                    344:        if (pv->pv_ptp)
                    345:                pmap_pde_release(pv->pv_pmap, pv->pv_va, pv->pv_ptp);
                    346:
                    347:        pool_put(&pmap_pv_pool, pv);
                    348: }
                    349:
                    350: void
                    351: pmap_pv_enter(struct vm_page *pg, struct pv_entry *pve, struct pmap *pm,
                    352:     vaddr_t va, struct vm_page *pdep)
                    353: {
                    354:        DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_pv_enter(%p, %p, %p, 0x%lx, %p)\n",
                    355:            pg, pve, pm, va, pdep));
                    356:        pve->pv_pmap    = pm;
                    357:        pve->pv_va      = va;
                    358:        pve->pv_ptp     = pdep;
                    359:        pve->pv_next    = pg->mdpage.pvh_list;
                    360:        pg->mdpage.pvh_list = pve;
                    361: #ifdef PMAPDEBUG
                    362:        if (pmap_check_alias(pve, va, 0))
                    363:                Debugger();
                    364: #endif
                    365: }
                    366:
                    367: struct pv_entry *
                    368: pmap_pv_remove(struct vm_page *pg, struct pmap *pmap, vaddr_t va)
                    369: {
                    370:        struct pv_entry **pve, *pv;
                    371:
                    372:        DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_pv_remove(%p, %p, 0x%lx)\n",
                    373:            pg, pmap, va));
                    374:
                    375:        simple_lock(&pg->mdpage.pvh_lock);      /* lock pv_head */
                    376:        for(pv = *(pve = &pg->mdpage.pvh_list);
                    377:            pv; pv = *(pve = &(*pve)->pv_next))
                    378:                if (pv->pv_pmap == pmap && pv->pv_va == va) {
                    379:                        *pve = pv->pv_next;
                    380:                        break;
                    381:                }
                    382:        simple_unlock(&pg->mdpage.pvh_lock);    /* unlock, done! */
                    383:        return (pv);
                    384: }
                    385:
                    386: const pt_entry_t hppa_pgs[] = {
                    387:        PTE_PG4K,
                    388:        PTE_PG16K,
                    389:        PTE_PG64K,
                    390:        PTE_PG256K,
                    391:        PTE_PG1M,
                    392:        PTE_PG4M,
                    393:        PTE_PG16M,
                    394:        PTE_PG64M
                    395: };
                    396: #define        nhppa_pgs       sizeof(hppa_pgs)/sizeof(hppa_pgs[0])
                    397:
                    398: void
                    399: pmap_maphys(paddr_t spa, paddr_t epa)
                    400: {
                    401:        volatile pt_entry_t *pde, *epde, pte;
                    402:        paddr_t pa, tpa;
                    403:        int s, e, i;
                    404:
                    405:        DPRINTF(PDB_INIT, ("pmap_maphys: mapping 0x%lx - 0x%lx\n", spa, epa));
                    406:
                    407:        s = ffs(spa) - 12;
                    408:        e = ffs(epa) - 12;
                    409:
                    410:        if (s < e || (s == e && s / 2 < nhppa_pgs)) {
                    411:                i = s / 2;
                    412:                if (i > nhppa_pgs)
                    413:                        i = nhppa_pgs;
                    414:                pa = spa;
                    415:                spa = tpa = 0x1000 << ((i + 1) * 2);
                    416:        } else if (s > e) {
                    417:                i = e / 2;
                    418:                if (i > nhppa_pgs)
                    419:                        i = nhppa_pgs;
                    420:                epa = pa = epa & (0xfffff000 << ((i + 1) * 2));
                    421:                tpa = epa;
                    422:        } else {
                    423:                i = s / 2;
                    424:                if (i > nhppa_pgs)
                    425:                        i = nhppa_pgs;
                    426:                pa = spa;
                    427:                spa = tpa = epa;
                    428:        }
                    429:
                    430: printf("pa 0x%lx tpa 0x%lx\n", pa, tpa);
                    431:        while (pa < tpa) {
                    432:                pte = TLB_PAGE(pa) | hppa_pgs[i - 1] |
                    433:                    PTE_WRITE | PTE_ORDER | PTE_DIRTY | PTE_WIRED;
                    434:                pde = pmap_pde_get(pmap_kernel()->pm_pdir, pa);
                    435:                epde = pde + (PTE_MASK >> PTE_SHIFT) + 1;
                    436:                if (pa + (PTE_MASK + (1 << PTE_SHIFT)) > tpa)
                    437:                        epde = pde + ((tpa & PTE_MASK) >> PTE_SHIFT);
                    438: printf("pde %p epde %p pte 0x%lx\n", pde, epde, pte);
                    439:                for (pde += (pa & PTE_MASK) >> PTE_SHIFT; pde < epde;)
                    440:                        *pde++ = pte;
                    441:                pa += PTE_MASK + (1 << PTE_SHIFT);
                    442:                pa &= ~(PTE_MASK | PAGE_MASK);
                    443:        }
                    444:
                    445:        if (spa < epa)
                    446:                pmap_maphys(spa, epa);
                    447: }
                    448:
                    449: void
                    450: pmap_bootstrap(vstart)
                    451:        vaddr_t vstart;
                    452: {
                    453:        extern int resvphysmem, __rodata_end, __data_start;
                    454:        vaddr_t va, eaddr, addr = round_page(vstart);
                    455:        struct pmap *kpm;
                    456:
                    457:        DPRINTF(PDB_FOLLOW|PDB_INIT, ("pmap_bootstrap(0x%lx)\n", vstart));
                    458:
                    459:        uvm_setpagesize();
                    460:
                    461:        hppa_prot[UVM_PROT_NONE]  = PTE_ORDER|PTE_ACC_NONE;
                    462:        hppa_prot[UVM_PROT_READ]  = PTE_ORDER|PTE_READ;
                    463:        hppa_prot[UVM_PROT_WRITE] = PTE_ORDER|PTE_WRITE;
                    464:        hppa_prot[UVM_PROT_RW]    = PTE_ORDER|PTE_READ|PTE_WRITE;
                    465:        hppa_prot[UVM_PROT_EXEC]  = PTE_ORDER|PTE_EXEC;
                    466:        hppa_prot[UVM_PROT_RX]    = PTE_ORDER|PTE_READ|PTE_EXEC;
                    467:        hppa_prot[UVM_PROT_WX]    = PTE_ORDER|PTE_WRITE|PTE_EXEC;
                    468:        hppa_prot[UVM_PROT_RWX]   = PTE_ORDER|PTE_READ|PTE_WRITE|PTE_EXEC;
                    469:
                    470:        /*
                    471:         * Initialize kernel pmap
                    472:         */
                    473:        kpm = &kernel_pmap_store;
                    474:        bzero(kpm, sizeof(*kpm));
                    475:        simple_lock_init(&kpm->pm_lock);
                    476:        kpm->pm_refcount = 1;
                    477:        kpm->pm_space = HPPA_SID_KERNEL;
                    478:        TAILQ_INIT(&kpm->pm_pglist);
                    479:        kpm->pm_pdir = (u_int32_t *)mfctl(CR_VTOP);
                    480:
                    481:        /*
                    482:         * Allocate various tables and structures.
                    483:         */
                    484:
                    485:        if (&__rodata_end < &__data_start) {
                    486:                physical_steal = (vaddr_t)&__rodata_end;
                    487:                physical_end = (vaddr_t)&__data_start;
                    488:                DPRINTF(PDB_INIT, ("physpool: 0x%lx @ 0x%lx\n",
                    489:                    physical_end - physical_steal, physical_steal));
                    490:        }
                    491:
                    492:        /* map enough PDEs to map initial physmem */
                    493:        for (va = 0x1000000, eaddr = ptoa(physmem);
                    494:            va < eaddr; addr += PAGE_SIZE, va += 1 << PDE_SHIFT) {
                    495:                bzero((void *)addr, PAGE_SIZE);
                    496:                pmap_pde_set(kpm, va, addr);
                    497:                kpm->pm_stats.resident_count++; /* count PTP as resident */
                    498:        }
                    499:
                    500:        /* map a little of initial kmem */
                    501:        for (va = VM_MIN_KERNEL_ADDRESS + ((pmap_nkpdes - 1) << PDE_SHIFT);
                    502:            va >= VM_MIN_KERNEL_ADDRESS;
                    503:            addr += PAGE_SIZE, va -= 1 << PDE_SHIFT) {
                    504:                bzero((void *)addr, PAGE_SIZE);
                    505:                pmap_pde_set(kpm, va, addr);
                    506:                kpm->pm_stats.resident_count++; /* count PTP as resident */
                    507:        }
                    508:
                    509:        pmap_maphys(0x1000000, ctob(physmem));
                    510:
                    511:        eaddr = physmem - atop(round_page(MSGBUFSIZE));
                    512:        resvphysmem = atop(addr);
                    513:        DPRINTF(PDB_INIT, ("physmem: 0x%lx - 0x%lx\n", resvphysmem, eaddr));
                    514:        uvm_page_physload(0, physmem,
                    515:            resvphysmem, eaddr, VM_FREELIST_DEFAULT);
                    516: }
                    517:
                    518: void
                    519: pmap_init()
                    520: {
                    521:        DPRINTF(PDB_FOLLOW|PDB_INIT, ("pmap_init()\n"));
                    522:
                    523:        pool_init(&pmap_pmap_pool, sizeof(struct pmap), 0, 0, 0, "pmappl",
                    524:            &pool_allocator_nointr);
                    525:        pool_init(&pmap_pv_pool, sizeof(struct pv_entry),0,0,0, "pmappv", NULL);
                    526:        pool_setlowat(&pmap_pv_pool, pmap_pvlowat);
                    527:        pool_sethiwat(&pmap_pv_pool, pmap_pvlowat * 32);
                    528:
                    529:        pmap_initialized = 1;
                    530:
                    531:        DPRINTF(PDB_FOLLOW|PDB_INIT, ("pmap_init(): done\n"));
                    532: }
                    533:
                    534: #ifdef PMAP_STEAL_MEMORY
                    535: vaddr_t
                    536: pmap_steal_memory(vsize_t size, vaddr_t *vstartp, vaddr_t *vendp)
                    537: {
                    538:        vaddr_t va;
                    539:        int npg;
                    540:
                    541:        DPRINTF(PDB_FOLLOW|PDB_PHYS,
                    542:            ("pmap_steal_memory(0x%lx, %p, %p)\n", size, vstartp, vendp));
                    543:
                    544:        size = round_page(size);
                    545:        npg = atop(size);
                    546:
                    547:        if (vm_physmem[0].avail_end - vm_physmem[0].avail_start < npg)
                    548:                panic("pmap_steal_memory: no more");
                    549:
                    550:        if (vstartp)
                    551:                *vstartp = VM_MIN_KERNEL_ADDRESS;
                    552:        if (vendp)
                    553:                *vendp = VM_MAX_KERNEL_ADDRESS;
                    554:
                    555:        vm_physmem[0].end -= npg;
                    556:        vm_physmem[0].avail_end -= npg;
                    557:        va = ptoa(vm_physmem[0].avail_end) - size;
                    558:        bzero((void *)va, size);
                    559:
                    560:        DPRINTF(PDB_FOLLOW|PDB_PHYS, ("pmap_steal_memory: 0x%lx\n", va));
                    561:
                    562:        return (va);
                    563: }
                    564: #else
                    565: void
                    566: pmap_virtual_space(vaddr_t *startp, vaddr_t *endp)
                    567: {
                    568:        *startp = VM_MIN_KERNEL_ADDRESS;
                    569:        *endp = VM_MAX_KERNEL_ADDRESS;
                    570: }
                    571: #endif /* PMAP_STEAL_MEMORY */
                    572:
                    573: #ifdef PMAP_GROWKERNEL
                    574: vaddr_t
                    575: pmap_growkernel(vaddr_t kva)
                    576: {
                    577:        vaddr_t va;
                    578:
                    579:        DPRINTF(PDB_FOLLOW|PDB_PHYS, ("pmap_growkernel(0x%lx)\n", kva));
                    580:
                    581:        va = VM_MIN_KERNEL_ADDRESS + (pmap_nkpdes << PDE_SHIFT);
                    582:        DPRINTF(PDB_PHYS, ("pmap_growkernel: was va 0x%lx\n", va));
                    583:        if (va < kva) {
                    584:                simple_lock(&pmap_kernel()->pm_obj.vmobjlock);
                    585:
                    586:                for ( ; va < kva ; pmap_nkpdes++, va += 1 << PDE_SHIFT)
                    587:                        if (uvm.page_init_done) {
                    588:                                if (!pmap_pde_alloc(pmap_kernel(), va, NULL))
                    589:                                        break;
                    590:                        } else {
                    591:                                paddr_t pa;
                    592:
                    593:                                pa = pmap_steal_memory(PAGE_SIZE, NULL, NULL);
                    594:                                if (pa)
                    595:                                        panic("pmap_growkernel: out of memory");
                    596:                                pmap_pde_set(pmap_kernel(), va, pa);
                    597:                                pmap_kernel()->pm_stats.resident_count++;
                    598:                        }
                    599:
                    600:                simple_unlock(&pmap_kernel()->pm_obj.vmobjlock);
                    601:        }
                    602:        DPRINTF(PDB_PHYS|PDB_VP, ("pmap_growkernel: now va 0x%lx\n", va));
                    603:        return (va);
                    604: }
                    605: #endif /* PMAP_GROWKERNEL */
                    606:
                    607: struct pmap *
                    608: pmap_create()
                    609: {
                    610:        struct pmap *pmap;
                    611:        struct vm_page *pg;
                    612:        pa_space_t space;
                    613:        paddr_t pa;
                    614:
                    615:        DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_create()\n"));
                    616:
                    617:        pmap = pool_get(&pmap_pmap_pool, PR_WAITOK);
                    618:
                    619:        simple_lock_init(&pmap->pm_lock);
                    620:        pmap->pm_refcount = 1;
                    621:        pmap->pm_ptphint = NULL;
                    622:
                    623:        TAILQ_INIT(&pmap->pm_pglist);
                    624:        if (uvm_pglistalloc(2 * PAGE_SIZE, 0, VM_MIN_KERNEL_ADDRESS,
                    625:            PAGE_SIZE, 2 * PAGE_SIZE, &pmap->pm_pglist, 1, 1))
                    626:                panic("pmap_create: no pages");
                    627:
                    628:        pg = TAILQ_FIRST(&pmap->pm_pglist);
                    629:        atomic_clearbits_int(&pg->pg_flags, PG_BUSY|PG_CLEAN);
                    630:        pmap->pm_pdir = (u_int32_t *)(pa = VM_PAGE_TO_PHYS(pg));
                    631:        bzero((void *)pa, PAGE_SIZE);
                    632:
                    633:        /* set the first PIE that's covering low 2g of the address space */
                    634:        pg = TAILQ_LAST(&pmap->pm_pglist, pglist);
                    635:        atomic_clearbits_int(&pg->pg_flags, PG_BUSY|PG_CLEAN);
                    636:        *pmap->pm_pdir = (pa = VM_PAGE_TO_PHYS(pg)) >> PAGE_SHIFT;
                    637:        bzero((void *)pa, PAGE_SIZE);
                    638:
                    639: /* TODO        for (space = 1 + (arc4random() & HPPA_SID_MAX);
                    640:            pmap_sdir_get(space); space = (space + 1) % HPPA_SID_MAX); */
                    641:        pmap->pm_space = space;
                    642:
                    643:        pmap->pm_stats.resident_count = 2;
                    644:        pmap->pm_stats.wired_count = 0;
                    645:
                    646:        return (pmap);
                    647: }
                    648:
                    649: void
                    650: pmap_destroy(pmap)
                    651:        struct pmap *pmap;
                    652: {
                    653:        int refs;
                    654:
                    655:        DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_destroy(%p)\n", pmap));
                    656:
                    657:        simple_lock(&pmap->pm_lock);
                    658:        refs = --pmap->pm_refcount;
                    659:        simple_unlock(&pmap->pm_lock);
                    660:
                    661:        if (refs > 0)
                    662:                return;
                    663:
                    664:        uvm_pglistfree(&pmap->pm_pglist);
                    665:        TAILQ_INIT(&pmap->pm_pglist);
                    666:        pool_put(&pmap_pmap_pool, pmap);
                    667: }
                    668:
                    669: /*
                    670:  * Add a reference to the specified pmap.
                    671:  */
                    672: void
                    673: pmap_reference(struct pmap *pmap)
                    674: {
                    675:        DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_reference(%p)\n", pmap));
                    676:
                    677:        simple_lock(&pmap->pm_lock);
                    678:        pmap->pm_refcount++;
                    679:        simple_unlock(&pmap->pm_lock);
                    680: }
                    681:
                    682: void
                    683: pmap_collect(struct pmap *pmap)
                    684: {
                    685:        DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_collect(%p)\n", pmap));
                    686:        /* nothing yet */
                    687: }
                    688:
                    689: int
                    690: pmap_enter(pmap, va, pa, prot, flags)
                    691:        struct pmap *pmap;
                    692:        vaddr_t va;
                    693:        paddr_t pa;
                    694:        vm_prot_t prot;
                    695:        int flags;
                    696: {
                    697:        volatile pt_entry_t *pde;
                    698:        pt_entry_t pte;
                    699:        struct vm_page *pg, *ptp = NULL;
                    700:        struct pv_entry *pve;
                    701:        boolean_t wired = (flags & PMAP_WIRED) != 0;
                    702:
                    703:        DPRINTF(PDB_FOLLOW|PDB_ENTER,
                    704:            ("pmap_enter(%p, 0x%lx, 0x%lx, 0x%x, 0x%x)\n",
                    705:            pmap, va, pa, prot, flags));
                    706:
                    707:        simple_lock(&pmap->pm_lock);
                    708:
                    709:        if (!(pde = pmap_pde_get(pmap->pm_pdir, va)) &&
                    710:            !(pde = pmap_pde_alloc(pmap, va, &ptp))) {
                    711:                if (flags & PMAP_CANFAIL) {
                    712:                        simple_unlock(&pmap->pm_lock);
                    713:                        return (ENOMEM);
                    714:                }
                    715:
                    716:                panic("pmap_enter: cannot allocate pde");
                    717:        }
                    718:
                    719:        if (!ptp)
                    720:                ptp = pmap_pde_ptp(pmap, pde);
                    721:
                    722:        if ((pte = pmap_pte_get(pde, va))) {
                    723:
                    724:                DPRINTF(PDB_ENTER,
                    725:                    ("pmap_enter: remapping 0x%lx -> 0x%lx\n", pte, pa));
                    726:
                    727:                pmap_pte_flush(pmap, va, pte);
                    728:                if (wired && !(pte & PTE_WIRED))
                    729:                        pmap->pm_stats.wired_count++;
                    730:                else if (!wired && (pte & PTE_WIRED))
                    731:                        pmap->pm_stats.wired_count--;
                    732:                pte &= PTE_UNCACHABLE|PTE_DIRTY|PTE_REFTRAP;
                    733:
                    734:                if (PTE_PAGE(pte) == pa) {
                    735:                        DPRINTF(PDB_FOLLOW|PDB_ENTER,
                    736:                            ("pmap_enter: same page\n"));
                    737:                        goto enter;
                    738:                }
                    739:
                    740:                pg = PHYS_TO_VM_PAGE(PTE_PAGE(pte));
                    741:                simple_lock(&pg->mdpage.pvh_lock);
                    742:                pve = pmap_pv_remove(pg, pmap, va);
                    743:                pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte);
                    744:        } else {
                    745:                DPRINTF(PDB_ENTER,
                    746:                    ("pmap_enter: new mapping 0x%lx -> 0x%lx\n", va, pa));
                    747:                pte = PTE_REFTRAP;
                    748:                pve = NULL;
                    749:                pmap->pm_stats.resident_count++;
                    750:                if (wired)
                    751:                        pmap->pm_stats.wired_count++;
                    752:                if (ptp)
                    753:                        ptp->wire_count++;
                    754:                simple_lock(&pg->mdpage.pvh_lock);
                    755:        }
                    756:
                    757:        if (pmap_initialized && (pg = PHYS_TO_VM_PAGE(pa))) {
                    758:                if (!pve && !(pve = pmap_pv_alloc())) {
                    759:                        if (flags & PMAP_CANFAIL) {
                    760:                                simple_unlock(&pg->mdpage.pvh_lock);
                    761:                                simple_unlock(&pmap->pm_lock);
                    762:                                return (ENOMEM);
                    763:                        }
                    764:                        panic("pmap_enter: no pv entries available");
                    765:                }
                    766:                pmap_pv_enter(pg, pve, pmap, va, ptp);
                    767:        } else if (pve)
                    768:                pmap_pv_free(pve);
                    769:        simple_unlock(&pg->mdpage.pvh_lock);
                    770:
                    771: enter:
                    772:        /* preserve old ref & mod */
                    773:        pte = TLB_PAGE(pa) | pmap_prot(pmap, prot);
                    774:        if (wired)
                    775:                pte |= PTE_WIRED;
                    776:        pmap_pte_set(pde, va, pte);
                    777:
                    778:        simple_unlock(&pmap->pm_lock);
                    779:
                    780:        DPRINTF(PDB_FOLLOW|PDB_ENTER, ("pmap_enter: leaving\n"));
                    781:
                    782:        return (0);
                    783: }
                    784:
                    785: void
                    786: pmap_remove(pmap, sva, eva)
                    787:        struct pmap *pmap;
                    788:        vaddr_t sva;
                    789:        vaddr_t eva;
                    790: {
                    791:        struct pv_entry *pve;
                    792:        volatile pt_entry_t *pde;
                    793:        pt_entry_t pte;
                    794:        struct vm_page *pg;
                    795:        vaddr_t pdemask;
                    796:        int batch;
                    797:
                    798:        DPRINTF(PDB_FOLLOW|PDB_REMOVE,
                    799:            ("pmap_remove(%p, 0x%lx, 0x%lx)\n", pmap, sva, eva));
                    800:
                    801:        simple_lock(&pmap->pm_lock);
                    802:
                    803:        for (batch = 0, pdemask = 1; sva < eva; sva += PAGE_SIZE) {
                    804:                if (pdemask != (sva & PDE_MASK)) {
                    805:                        pdemask = sva & PDE_MASK;
                    806:                        if (!(pde = pmap_pde_get(pmap->pm_pdir, sva))) {
                    807:                                sva += ~PDE_MASK + 1 - PAGE_SIZE;
                    808:                                continue;
                    809:                        }
                    810:                        batch = pdemask == sva && sva + ~PDE_MASK + 1 <= eva;
                    811:                }
                    812:
                    813:                if ((pte = pmap_pte_get(pde, sva))) {
                    814:
                    815:                        /* TODO measure here the speed tradeoff
                    816:                         * for flushing whole PT vs per-page
                    817:                         * in case of non-complete pde fill
                    818:                         */
                    819:                        pmap_pte_flush(pmap, sva, pte);
                    820:                        if (pte & PTE_WIRED)
                    821:                                pmap->pm_stats.wired_count--;
                    822:                        pmap->pm_stats.resident_count--;
                    823:
                    824:                        /* iff properly accounted pde will be dropped anyway */
                    825:                        if (!batch)
                    826:                                pmap_pte_set(pde, sva, 0);
                    827:
                    828:                        if (pmap_initialized &&
                    829:                            (pg = PHYS_TO_VM_PAGE(PTE_PAGE(pte)))) {
                    830:
                    831:                                simple_lock(&pg->mdpage.pvh_lock);
                    832:                                pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte);
                    833:                                if ((pve = pmap_pv_remove(pg, pmap, sva)))
                    834:                                        pmap_pv_free(pve);
                    835:                                simple_unlock(&pg->mdpage.pvh_lock);
                    836:                        }
                    837:                }
                    838:        }
                    839:
                    840:        simple_unlock(&pmap->pm_lock);
                    841:
                    842:        DPRINTF(PDB_FOLLOW|PDB_REMOVE, ("pmap_remove: leaving\n"));
                    843: }
                    844:
                    845: void
                    846: pmap_write_protect(pmap, sva, eva, prot)
                    847:        struct pmap *pmap;
                    848:        vaddr_t sva;
                    849:        vaddr_t eva;
                    850:        vm_prot_t prot;
                    851: {
                    852:        struct vm_page *pg;
                    853:        volatile pt_entry_t *pde;
                    854:        pt_entry_t pte;
                    855:        u_int tlbprot, pdemask;
                    856:
                    857:        DPRINTF(PDB_FOLLOW|PDB_PMAP,
                    858:            ("pmap_write_protect(%p, %lx, %lx, %x)\n", pmap, sva, eva, prot));
                    859:
                    860:        sva = trunc_page(sva);
                    861:        tlbprot = pmap_prot(pmap, prot);
                    862:
                    863:        simple_lock(&pmap->pm_lock);
                    864:
                    865:        for (pdemask = 1; sva < eva; sva += PAGE_SIZE) {
                    866:                if (pdemask != (sva & PDE_MASK)) {
                    867:                        pdemask = sva & PDE_MASK;
                    868:                        if (!(pde = pmap_pde_get(pmap->pm_pdir, sva))) {
                    869:                                sva += ~PDE_MASK + 1 - PAGE_SIZE;
                    870:                                continue;
                    871:                        }
                    872:                }
                    873:                if ((pte = pmap_pte_get(pde, sva))) {
                    874:
                    875:                        DPRINTF(PDB_PMAP,
                    876:                            ("pmap_write_protect: va=0x%lx pte=0x%lx\n",
                    877:                            sva,  pte));
                    878:                        /*
                    879:                         * Determine if mapping is changing.
                    880:                         * If not, nothing to do.
                    881:                         */
                    882:                        if ((pte & PTE_ACC_MASK) == tlbprot)
                    883:                                continue;
                    884:
                    885:                        pg = PHYS_TO_VM_PAGE(PTE_PAGE(pte));
                    886:                        simple_lock(&pg->mdpage.pvh_lock);
                    887:                        pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte);
                    888:                        simple_unlock(&pg->mdpage.pvh_lock);
                    889:
                    890:                        pmap_pte_flush(pmap, sva, pte);
                    891:                        pte &= ~PTE_ACC_MASK;
                    892:                        pte |= tlbprot;
                    893:                        pmap_pte_set(pde, sva, pte);
                    894:                }
                    895:        }
                    896:
                    897:        simple_unlock(&pmap->pm_lock);
                    898: }
                    899:
                    900: void
                    901: pmap_page_remove(pg)
                    902:        struct vm_page *pg;
                    903: {
                    904:        struct pv_entry *pve, *ppve;
                    905:
                    906:        DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_page_remove(%p)\n", pg));
                    907:
                    908:        if (pg->mdpage.pvh_list == NULL)
                    909:                return;
                    910:
                    911:        simple_lock(&pg->mdpage.pvh_lock);
                    912:        for (pve = pg->mdpage.pvh_list; pve;
                    913:             pve = (ppve = pve)->pv_next, pmap_pv_free(ppve)) {
                    914:                struct pmap *pmap = pve->pv_pmap;
                    915:                vaddr_t va = pve->pv_va;
                    916:                volatile pt_entry_t *pde;
                    917:                pt_entry_t pte;
                    918:
                    919:                simple_lock(&pmap->pm_lock);
                    920:
                    921:                pde = pmap_pde_get(pmap->pm_pdir, va);
                    922:                pte = pmap_pte_get(pde, va);
                    923:                pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte);
                    924:
                    925:                pmap_pte_flush(pmap, va, pte);
                    926:                if (pte & PTE_WIRED)
                    927:                        pmap->pm_stats.wired_count--;
                    928:                pmap->pm_stats.resident_count--;
                    929:
                    930:                pmap_pte_set(pde, va, 0);
                    931:                simple_unlock(&pmap->pm_lock);
                    932:        }
                    933:        pg->mdpage.pvh_list = NULL;
                    934:        simple_unlock(&pg->mdpage.pvh_lock);
                    935:
                    936:        DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_page_remove: leaving\n"));
                    937:
                    938: }
                    939:
                    940: void
                    941: pmap_unwire(pmap, va)
                    942:        struct pmap *pmap;
                    943:        vaddr_t va;
                    944: {
                    945:        volatile pt_entry_t *pde;
                    946:        pt_entry_t pte = 0;
                    947:
                    948:        DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_unwire(%p, 0x%lx)\n", pmap, va));
                    949:
                    950:        simple_lock(&pmap->pm_lock);
                    951:        if ((pde = pmap_pde_get(pmap->pm_pdir, va))) {
                    952:                pte = pmap_pte_get(pde, va);
                    953:
                    954:                if (pte & PTE_WIRED) {
                    955:                        pte &= ~PTE_WIRED;
                    956:                        pmap->pm_stats.wired_count--;
                    957:                        pmap_pte_set(pde, va, pte);
                    958:                }
                    959:        }
                    960:        simple_unlock(&pmap->pm_lock);
                    961:
                    962:        DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_unwire: leaving\n"));
                    963:
                    964: #ifdef DIAGNOSTIC
                    965:        if (!pte)
                    966:                panic("pmap_unwire: invalid va 0x%lx", va);
                    967: #endif
                    968: }
                    969:
                    970: boolean_t
                    971: pmap_changebit(struct vm_page *pg, pt_entry_t set, pt_entry_t clear)
                    972: {
                    973:        struct pv_entry *pve;
                    974:        pt_entry_t res;
                    975:
                    976:        DPRINTF(PDB_FOLLOW|PDB_BITS,
                    977:            ("pmap_changebit(%p, %lx, %lx)\n", pg, set, clear));
                    978:
                    979:        simple_lock(&pg->mdpage.pvh_lock);
                    980:        res = pg->mdpage.pvh_attrs = 0;
                    981:        for(pve = pg->mdpage.pvh_list; pve; pve = pve->pv_next) {
                    982:                struct pmap *pmap = pve->pv_pmap;
                    983:                vaddr_t va = pve->pv_va;
                    984:                volatile pt_entry_t *pde;
                    985:                pt_entry_t opte, pte;
                    986:
                    987:                simple_lock(&pmap->pm_lock);
                    988:                if ((pde = pmap_pde_get(pmap->pm_pdir, va))) {
                    989:                        opte = pte = pmap_pte_get(pde, va);
                    990: #ifdef PMAPDEBUG
                    991:                        if (!pte) {
                    992:                                printf("pmap_changebit: zero pte for 0x%lx\n",
                    993:                                    va);
                    994:                                continue;
                    995:                        }
                    996: #endif
                    997:                        pte &= ~clear;
                    998:                        pte |= set;
                    999:                        pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte);
                   1000:                        res |= pmap_pvh_attrs(opte);
                   1001:
                   1002:                        if (opte != pte) {
                   1003:                                pmap_pte_flush(pmap, va, opte);
                   1004:                                pmap_pte_set(pde, va, pte);
                   1005:                        }
                   1006:                }
                   1007:                simple_unlock(&pmap->pm_lock);
                   1008:        }
                   1009:        simple_unlock(&pg->mdpage.pvh_lock);
                   1010:
                   1011:        return ((res & (clear | set)) != 0);
                   1012: }
                   1013:
                   1014: boolean_t
                   1015: pmap_testbit(struct vm_page *pg, pt_entry_t bit)
                   1016: {
                   1017:        struct pv_entry *pve;
                   1018:        pt_entry_t pte;
                   1019:
                   1020:        DPRINTF(PDB_FOLLOW|PDB_BITS, ("pmap_testbit(%p, %lx)\n", pg, bit));
                   1021:
                   1022:        simple_lock(&pg->mdpage.pvh_lock);
                   1023:        for(pve = pg->mdpage.pvh_list; !(pg->mdpage.pvh_attrs & bit) && pve;
                   1024:            pve = pve->pv_next) {
                   1025:                simple_lock(&pve->pv_pmap->pm_lock);
                   1026:                pte = pmap_vp_find(pve->pv_pmap, pve->pv_va);
                   1027:                simple_unlock(&pve->pv_pmap->pm_lock);
                   1028:                pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte);
                   1029:        }
                   1030:        simple_unlock(&pg->mdpage.pvh_lock);
                   1031:
                   1032:        return ((pg->mdpage.pvh_attrs & bit) != 0);
                   1033: }
                   1034:
                   1035: boolean_t
                   1036: pmap_extract(pmap, va, pap)
                   1037:        struct pmap *pmap;
                   1038:        vaddr_t va;
                   1039:        paddr_t *pap;
                   1040: {
                   1041:        pt_entry_t pte;
                   1042:
                   1043:        DPRINTF(PDB_FOLLOW|PDB_EXTRACT, ("pmap_extract(%p, %lx)\n", pmap, va));
                   1044:
                   1045:        simple_lock(&pmap->pm_lock);
                   1046:        pte = pmap_vp_find(pmap, va);
                   1047:        simple_unlock(&pmap->pm_lock);
                   1048:
                   1049:        if (pte) {
                   1050:                if (pap)
                   1051:                        *pap = PTE_PAGE(pte) | (va & PAGE_MASK);
                   1052:                return (TRUE);
                   1053:        }
                   1054:
                   1055:        return (FALSE);
                   1056: }
                   1057:
                   1058: void
                   1059: pmap_activate(struct proc *p)
                   1060: {
                   1061:        struct pmap *pmap = p->p_vmspace->vm_map.pmap;
                   1062:        struct pcb *pcb = &p->p_addr->u_pcb;
                   1063:
                   1064:        pcb->pcb_space = pmap->pm_space;
                   1065:        pcb->pcb_uva = (vaddr_t)p->p_addr;
                   1066: }
                   1067:
                   1068: void
                   1069: pmap_deactivate(struct proc *p)
                   1070: {
                   1071:
                   1072: }
                   1073:
                   1074: static __inline void
                   1075: pmap_flush_page(struct vm_page *pg, int purge)
                   1076: {
                   1077:        struct pv_entry *pve;
                   1078:
                   1079:        /* purge cache for all possible mappings for the pa */
                   1080:        simple_lock(&pg->mdpage.pvh_lock);
                   1081:        for(pve = pg->mdpage.pvh_list; pve; pve = pve->pv_next)
                   1082:                if (purge)
                   1083:                        pdcache(pve->pv_pmap->pm_space, pve->pv_va, PAGE_SIZE);
                   1084:                else
                   1085:                        fdcache(pve->pv_pmap->pm_space, pve->pv_va, PAGE_SIZE);
                   1086:        simple_unlock(&pg->mdpage.pvh_lock);
                   1087: }
                   1088:
                   1089: void
                   1090: pmap_zero_page(struct vm_page *pg)
                   1091: {
                   1092:        paddr_t pa = VM_PAGE_TO_PHYS(pg);
                   1093:
                   1094:        DPRINTF(PDB_FOLLOW|PDB_PHYS, ("pmap_zero_page(%lx)\n", pa));
                   1095:
                   1096:        pmap_flush_page(pg, 1);
                   1097:        bzero((void *)pa, PAGE_SIZE);
                   1098:        fdcache(HPPA_SID_KERNEL, pa, PAGE_SIZE);
                   1099: }
                   1100:
                   1101: void
                   1102: pmap_copy_page(struct vm_page *srcpg, struct vm_page *dstpg)
                   1103: {
                   1104:        paddr_t spa = VM_PAGE_TO_PHYS(srcpg);
                   1105:        paddr_t dpa = VM_PAGE_TO_PHYS(dstpg);
                   1106:        DPRINTF(PDB_FOLLOW|PDB_PHYS, ("pmap_copy_page(%lx, %lx)\n", spa, dpa));
                   1107:
                   1108:        pmap_flush_page(srcpg, 0);
                   1109:        pmap_flush_page(dstpg, 1);
                   1110:        bcopy((void *)spa, (void *)dpa, PAGE_SIZE);
                   1111:        pdcache(HPPA_SID_KERNEL, spa, PAGE_SIZE);
                   1112:        fdcache(HPPA_SID_KERNEL, dpa, PAGE_SIZE);
                   1113: }
                   1114:
                   1115: void
                   1116: pmap_kenter_pa(va, pa, prot)
                   1117:        vaddr_t va;
                   1118:        paddr_t pa;
                   1119:        vm_prot_t prot;
                   1120: {
                   1121:        volatile pt_entry_t *pde;
                   1122:        pt_entry_t pte, opte;
                   1123:
                   1124:        DPRINTF(PDB_FOLLOW|PDB_ENTER,
                   1125:            ("pmap_kenter_pa(%lx, %lx, %x)\n", va, pa, prot));
                   1126:
                   1127:        simple_lock(&pmap->pm_lock);
                   1128:
                   1129:        if (!(pde = pmap_pde_get(pmap_kernel()->pm_pdir, va)) &&
                   1130:            !(pde = pmap_pde_alloc(pmap_kernel(), va, NULL)))
                   1131:                panic("pmap_kenter_pa: cannot allocate pde for va=0x%lx", va);
                   1132:        opte = pmap_pte_get(pde, va);
                   1133:        pte = TLB_PAGE(pa) | PTE_WIRED | PTE_REFTRAP |
                   1134:            pmap_prot(pmap_kernel(), prot);
                   1135:        if (pa >= 0xf0000000ULL /* TODO (HPPA_IOBEGIN & HPPA_PHYSMAP) */)
                   1136:                pte |= PTE_UNCACHABLE | PTE_ORDER;
                   1137:        DPRINTF(PDB_ENTER, ("pmap_kenter_pa: pde %p va %lx pte %lx\n",
                   1138:            pde, va, pte));
                   1139:        pmap_pte_set(pde, va, pte);
                   1140:        pmap_kernel()->pm_stats.wired_count++;
                   1141:        pmap_kernel()->pm_stats.resident_count++;
                   1142:        if (opte)
                   1143:                pmap_pte_flush(pmap_kernel(), va, opte);
                   1144:
                   1145: #ifdef PMAPDEBUG
                   1146:        {
                   1147:                struct vm_page *pg;
                   1148:
                   1149:                if (pmap_initialized && (pg = PHYS_TO_VM_PAGE(PTE_PAGE(pte)))) {
                   1150:
                   1151:                        simple_lock(&pg->mdpage.pvh_lock);
                   1152:                        if (pmap_check_alias(pg->mdpage.pvh_list, va, pte))
                   1153:                                Debugger();
                   1154:                        simple_unlock(&pg->mdpage.pvh_lock);
                   1155:                }
                   1156:        }
                   1157: #endif
                   1158:        simple_unlock(&pmap->pm_lock);
                   1159:
                   1160:        DPRINTF(PDB_FOLLOW|PDB_ENTER, ("pmap_kenter_pa: leaving\n"));
                   1161: }
                   1162:
                   1163: void
                   1164: pmap_kremove(va, size)
                   1165:        vaddr_t va;
                   1166:        vsize_t size;
                   1167: {
                   1168:        struct pv_entry *pve;
                   1169:        vaddr_t eva, pdemask;
                   1170:        volatile pt_entry_t *pde;
                   1171:        pt_entry_t pte;
                   1172:        struct vm_page *pg;
                   1173:
                   1174:        DPRINTF(PDB_FOLLOW|PDB_REMOVE,
                   1175:            ("pmap_kremove(%lx, %lx)\n", va, size));
                   1176: #ifdef PMAPDEBUG
                   1177:        if (va < ptoa(physmem)) {
                   1178:                printf("pmap_kremove(%lx, %lx): unmapping physmem\n", va, size);
                   1179:                return;
                   1180:        }
                   1181: #endif
                   1182:
                   1183:        simple_lock(&pmap->pm_lock);
                   1184:
                   1185:        for (pdemask = 1, eva = va + size; va < eva; va += PAGE_SIZE) {
                   1186:                if (pdemask != (va & PDE_MASK)) {
                   1187:                        pdemask = va & PDE_MASK;
                   1188:                        if (!(pde = pmap_pde_get(pmap_kernel()->pm_pdir, va))) {
                   1189:                                va += ~PDE_MASK + 1 - PAGE_SIZE;
                   1190:                                continue;
                   1191:                        }
                   1192:                }
                   1193:                if (!(pte = pmap_pte_get(pde, va))) {
                   1194: #ifdef DEBUG
                   1195:                        printf("pmap_kremove: unmapping unmapped 0x%lx\n", va);
                   1196: #endif
                   1197:                        continue;
                   1198:                }
                   1199:
                   1200:                pmap_pte_flush(pmap_kernel(), va, pte);
                   1201:                pmap_pte_set(pde, va, 0);
                   1202:                if (pmap_initialized && (pg = PHYS_TO_VM_PAGE(PTE_PAGE(pte)))) {
                   1203:
                   1204:                        simple_lock(&pg->mdpage.pvh_lock);
                   1205:                        pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte);
                   1206:                        /* just in case we have enter/kenter mismatch */
                   1207:                        if ((pve = pmap_pv_remove(pg, pmap_kernel(), va)))
                   1208:                                pmap_pv_free(pve);
                   1209:                        simple_unlock(&pg->mdpage.pvh_lock);
                   1210:                }
                   1211:        }
                   1212:
                   1213:        simple_unlock(&pmap->pm_lock);
                   1214:
                   1215:        DPRINTF(PDB_FOLLOW|PDB_REMOVE, ("pmap_kremove: leaving\n"));
                   1216: }

CVSweb