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

Annotation of sys/arch/amd64/amd64/pmap.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: pmap.c,v 1.27 2007/06/01 20:10:04 tedu Exp $  */
        !             2: /*     $NetBSD: pmap.c,v 1.3 2003/05/08 18:13:13 thorpej Exp $ */
        !             3:
        !             4: /*
        !             5:  *
        !             6:  * Copyright (c) 1997 Charles D. Cranor and Washington University.
        !             7:  * All rights reserved.
        !             8:  *
        !             9:  * Redistribution and use in source and binary forms, with or without
        !            10:  * modification, are permitted provided that the following conditions
        !            11:  * are met:
        !            12:  * 1. Redistributions of source code must retain the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer.
        !            14:  * 2. Redistributions in binary form must reproduce the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer in the
        !            16:  *    documentation and/or other materials provided with the distribution.
        !            17:  * 3. All advertising materials mentioning features or use of this software
        !            18:  *    must display the following acknowledgement:
        !            19:  *      This product includes software developed by Charles D. Cranor and
        !            20:  *      Washington University.
        !            21:  * 4. The name of the author may not be used to endorse or promote products
        !            22:  *    derived from this software without specific prior written permission.
        !            23:  *
        !            24:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            25:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            26:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            27:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            28:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            29:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            30:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            31:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            32:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            33:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            34:  */
        !            35:
        !            36: /*
        !            37:  * Copyright 2001 (c) Wasabi Systems, Inc.
        !            38:  * All rights reserved.
        !            39:  *
        !            40:  * Written by Frank van der Linden for Wasabi Systems, Inc.
        !            41:  *
        !            42:  * Redistribution and use in source and binary forms, with or without
        !            43:  * modification, are permitted provided that the following conditions
        !            44:  * are met:
        !            45:  * 1. Redistributions of source code must retain the above copyright
        !            46:  *    notice, this list of conditions and the following disclaimer.
        !            47:  * 2. Redistributions in binary form must reproduce the above copyright
        !            48:  *    notice, this list of conditions and the following disclaimer in the
        !            49:  *    documentation and/or other materials provided with the distribution.
        !            50:  * 3. All advertising materials mentioning features or use of this software
        !            51:  *    must display the following acknowledgement:
        !            52:  *      This product includes software developed for the NetBSD Project by
        !            53:  *      Wasabi Systems, Inc.
        !            54:  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
        !            55:  *    or promote products derived from this software without specific prior
        !            56:  *    written permission.
        !            57:  *
        !            58:  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
        !            59:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            60:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            61:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
        !            62:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            63:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            64:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            65:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            66:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            67:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            68:  * POSSIBILITY OF SUCH DAMAGE.
        !            69:  */
        !            70:
        !            71: /*
        !            72:  * This is the i386 pmap modified and generalized to support x86-64
        !            73:  * as well. The idea is to hide the upper N levels of the page tables
        !            74:  * inside pmap_get_ptp, pmap_free_ptp and pmap_growkernel. The rest
        !            75:  * is mostly untouched, except that it uses some more generalized
        !            76:  * macros and interfaces.
        !            77:  *
        !            78:  * This pmap has been tested on the i386 as well, and it can be easily
        !            79:  * adapted to PAE.
        !            80:  *
        !            81:  * fvdl@wasabisystems.com 18-Jun-2001
        !            82:  */
        !            83:
        !            84: /*
        !            85:  * pmap.c: i386 pmap module rewrite
        !            86:  * Chuck Cranor <chuck@ccrc.wustl.edu>
        !            87:  * 11-Aug-97
        !            88:  *
        !            89:  * history of this pmap module: in addition to my own input, i used
        !            90:  *    the following references for this rewrite of the i386 pmap:
        !            91:  *
        !            92:  * [1] the NetBSD i386 pmap.   this pmap appears to be based on the
        !            93:  *     BSD hp300 pmap done by Mike Hibler at University of Utah.
        !            94:  *     it was then ported to the i386 by William Jolitz of UUNET
        !            95:  *     Technologies, Inc.   Then Charles M. Hannum of the NetBSD
        !            96:  *     project fixed some bugs and provided some speed ups.
        !            97:  *
        !            98:  * [2] the FreeBSD i386 pmap.   this pmap seems to be the
        !            99:  *     Hibler/Jolitz pmap, as modified for FreeBSD by John S. Dyson
        !           100:  *     and David Greenman.
        !           101:  *
        !           102:  * [3] the Mach pmap.   this pmap, from CMU, seems to have migrated
        !           103:  *     between several processors.   the VAX version was done by
        !           104:  *     Avadis Tevanian, Jr., and Michael Wayne Young.    the i386
        !           105:  *     version was done by Lance Berc, Mike Kupfer, Bob Baron,
        !           106:  *     David Golub, and Richard Draves.    the alpha version was
        !           107:  *     done by Alessandro Forin (CMU/Mach) and Chris Demetriou
        !           108:  *     (NetBSD/alpha).
        !           109:  */
        !           110:
        !           111: #include <sys/param.h>
        !           112: #include <sys/systm.h>
        !           113: #include <sys/proc.h>
        !           114: #include <sys/malloc.h>
        !           115: #include <sys/pool.h>
        !           116: #include <sys/user.h>
        !           117: #include <sys/kernel.h>
        !           118: #include <sys/mutex.h>
        !           119: #include <sys/sched.h>
        !           120:
        !           121: #include <uvm/uvm.h>
        !           122:
        !           123: #include <machine/atomic.h>
        !           124: #include <machine/cpu.h>
        !           125: #include <machine/specialreg.h>
        !           126: #include <machine/gdt.h>
        !           127:
        !           128: #include <dev/isa/isareg.h>
        !           129: #include <machine/isa_machdep.h>
        !           130:
        !           131: /*
        !           132:  * general info:
        !           133:  *
        !           134:  *  - for an explanation of how the i386 MMU hardware works see
        !           135:  *    the comments in <machine/pte.h>.
        !           136:  *
        !           137:  *  - for an explanation of the general memory structure used by
        !           138:  *    this pmap (including the recursive mapping), see the comments
        !           139:  *    in <machine/pmap.h>.
        !           140:  *
        !           141:  * this file contains the code for the "pmap module."   the module's
        !           142:  * job is to manage the hardware's virtual to physical address mappings.
        !           143:  * note that there are two levels of mapping in the VM system:
        !           144:  *
        !           145:  *  [1] the upper layer of the VM system uses vm_map's and vm_map_entry's
        !           146:  *      to map ranges of virtual address space to objects/files.  for
        !           147:  *      example, the vm_map may say: "map VA 0x1000 to 0x22000 read-only
        !           148:  *      to the file /bin/ls starting at offset zero."   note that
        !           149:  *      the upper layer mapping is not concerned with how individual
        !           150:  *      vm_pages are mapped.
        !           151:  *
        !           152:  *  [2] the lower layer of the VM system (the pmap) maintains the mappings
        !           153:  *      from virtual addresses.   it is concerned with which vm_page is
        !           154:  *      mapped where.   for example, when you run /bin/ls and start
        !           155:  *      at page 0x1000 the fault routine may lookup the correct page
        !           156:  *      of the /bin/ls file and then ask the pmap layer to establish
        !           157:  *      a mapping for it.
        !           158:  *
        !           159:  * note that information in the lower layer of the VM system can be
        !           160:  * thrown away since it can easily be reconstructed from the info
        !           161:  * in the upper layer.
        !           162:  *
        !           163:  * data structures we use include:
        !           164:  *
        !           165:  *  - struct pmap: describes the address space of one thread
        !           166:  *  - struct pv_entry: describes one <PMAP,VA> mapping of a PA
        !           167:  * - pmap_remove_record: a list of virtual addresses whose mappings
        !           168:  *     have been changed.   used for TLB flushing.
        !           169:  */
        !           170:
        !           171: /*
        !           172:  * memory allocation
        !           173:  *
        !           174:  *  - there are three data structures that we must dynamically allocate:
        !           175:  *
        !           176:  * [A] new process' page directory page (PDP)
        !           177:  *     - plan 1: done at pmap_create() we use
        !           178:  *       uvm_km_alloc(kernel_map, PAGE_SIZE)  [fka kmem_alloc] to do this
        !           179:  *       allocation.
        !           180:  *
        !           181:  * if we are low in free physical memory then we sleep in
        !           182:  * uvm_km_alloc -- in this case this is ok since we are creating
        !           183:  * a new pmap and should not be holding any locks.
        !           184:  *
        !           185:  * if the kernel is totally out of virtual space
        !           186:  * (i.e. uvm_km_alloc returns NULL), then we panic.
        !           187:  *
        !           188:  * XXX: the fork code currently has no way to return an "out of
        !           189:  * memory, try again" error code since uvm_fork [fka vm_fork]
        !           190:  * is a void function.
        !           191:  *
        !           192:  * [B] new page tables pages (PTP)
        !           193:  *     call uvm_pagealloc()
        !           194:  *             => success: zero page, add to pm_pdir
        !           195:  *             => failure: we are out of free vm_pages, let pmap_enter()
        !           196:  *                tell UVM about it.
        !           197:  *
        !           198:  * note: for kernel PTPs, we start with NKPTP of them.   as we map
        !           199:  * kernel memory (at uvm_map time) we check to see if we've grown
        !           200:  * the kernel pmap.   if so, we call the optional function
        !           201:  * pmap_growkernel() to grow the kernel PTPs in advance.
        !           202:  *
        !           203:  * [C] pv_entry structures
        !           204:  *     - try to allocate one from the pool.
        !           205:  *     If we fail, we simply let pmap_enter() tell UVM about it.
        !           206:  */
        !           207:
        !           208: /*
        !           209:  * locking
        !           210:  *
        !           211:  * we have the following locks that we must contend with:
        !           212:  *
        !           213:  * "simple" locks:
        !           214:  *
        !           215:  * - pmap lock (per pmap, part of uvm_object)
        !           216:  *   this lock protects the fields in the pmap structure including
        !           217:  *   the non-kernel PDEs in the PDP, and the PTEs.  it also locks
        !           218:  *   in the alternate PTE space (since that is determined by the
        !           219:  *   entry in the PDP).
        !           220:  *
        !           221:  * - pmaps_lock
        !           222:  *   this lock protects the list of active pmaps (headed by "pmaps").
        !           223:  *   we lock it when adding or removing pmaps from this list.
        !           224:  *
        !           225:  * XXX: would be nice to have per-CPU VAs for the above 4
        !           226:  */
        !           227:
        !           228: /*
        !           229:  * locking data structures
        !           230:  */
        !           231:
        !           232: vaddr_t ptp_masks[] = PTP_MASK_INITIALIZER;
        !           233: int ptp_shifts[] = PTP_SHIFT_INITIALIZER;
        !           234: long nkptp[] = NKPTP_INITIALIZER;
        !           235: long nkptpmax[] = NKPTPMAX_INITIALIZER;
        !           236: long nbpd[] = NBPD_INITIALIZER;
        !           237: pd_entry_t *normal_pdes[] = PDES_INITIALIZER;
        !           238: pd_entry_t *alternate_pdes[] = APDES_INITIALIZER;
        !           239:
        !           240: /* int nkpde = NKPTP; */
        !           241:
        !           242: struct simplelock pmaps_lock;
        !           243:
        !           244: #define PMAP_MAP_TO_HEAD_LOCK()                /* null */
        !           245: #define PMAP_MAP_TO_HEAD_UNLOCK()      /* null */
        !           246:
        !           247: #define PMAP_HEAD_TO_MAP_LOCK()                /* null */
        !           248: #define PMAP_HEAD_TO_MAP_UNLOCK()      /* null */
        !           249:
        !           250: #define COUNT(x)       /* nothing */
        !           251:
        !           252: /*
        !           253:  * global data structures
        !           254:  */
        !           255:
        !           256: struct pmap kernel_pmap_store; /* the kernel's pmap (proc0) */
        !           257:
        !           258: /*
        !           259:  * pmap_pg_g: if our processor supports PG_G in the PTE then we
        !           260:  * set pmap_pg_g to PG_G (otherwise it is zero).
        !           261:  */
        !           262:
        !           263: int pmap_pg_g = 0;
        !           264:
        !           265: /*
        !           266:  * i386 physical memory comes in a big contig chunk with a small
        !           267:  * hole toward the front of it...  the following 4 paddr_t's
        !           268:  * (shared with machdep.c) describe the physical address space
        !           269:  * of this machine.
        !           270:  */
        !           271: paddr_t avail_start;   /* PA of first available physical page */
        !           272: paddr_t avail_end;     /* PA of last available physical page */
        !           273:
        !           274: /*
        !           275:  * other data structures
        !           276:  */
        !           277:
        !           278: pt_entry_t protection_codes[8];     /* maps MI prot to i386 prot code */
        !           279: boolean_t pmap_initialized = FALSE; /* pmap_init done yet? */
        !           280:
        !           281: /*
        !           282:  * pv management structures.
        !           283:  */
        !           284: struct pool pmap_pv_pool;
        !           285:
        !           286: /*
        !           287:  * linked list of all non-kernel pmaps
        !           288:  */
        !           289:
        !           290: struct pmap_head pmaps;
        !           291:
        !           292: /*
        !           293:  * pool that pmap structures are allocated from
        !           294:  */
        !           295:
        !           296: struct pool pmap_pmap_pool;
        !           297:
        !           298: /*
        !           299:  * When we're freeing a ptp, we need to delay the freeing until all
        !           300:  * tlb shootdown has been done. This is the list of the to-be-freed pages.
        !           301:  */
        !           302: TAILQ_HEAD(pg_to_free, vm_page);
        !           303:
        !           304: /*
        !           305:  * pool and cache that PDPs are allocated from
        !           306:  */
        !           307:
        !           308: struct pool pmap_pdp_pool;
        !           309: struct pool_cache pmap_pdp_cache;
        !           310: u_int pmap_pdp_cache_generation;
        !           311:
        !           312: int    pmap_pdp_ctor(void *, void *, int);
        !           313:
        !           314: extern vaddr_t msgbuf_vaddr;
        !           315: extern paddr_t msgbuf_paddr;
        !           316:
        !           317: extern vaddr_t idt_vaddr;                      /* we allocate IDT early */
        !           318: extern paddr_t idt_paddr;
        !           319:
        !           320: #ifdef _LP64
        !           321: extern vaddr_t lo32_vaddr;
        !           322: extern vaddr_t lo32_paddr;
        !           323: #endif
        !           324:
        !           325: vaddr_t virtual_avail;
        !           326: extern int end;
        !           327:
        !           328: /*
        !           329:  * local prototypes
        !           330:  */
        !           331:
        !           332: void  pmap_enter_pv(struct vm_page *, struct pv_entry *, struct pmap *,
        !           333:     vaddr_t, struct vm_page *);
        !           334: struct vm_page *pmap_get_ptp(struct pmap *, vaddr_t, pd_entry_t **);
        !           335: struct vm_page *pmap_find_ptp(struct pmap *, vaddr_t, paddr_t, int);
        !           336: void pmap_free_ptp(struct pmap *, struct vm_page *,
        !           337:     vaddr_t, pt_entry_t *, pd_entry_t **, struct pg_to_free *);
        !           338: void pmap_freepage(struct pmap *, struct vm_page *, int, struct pg_to_free *);
        !           339: static boolean_t pmap_is_active(struct pmap *, int);
        !           340: void pmap_map_ptes(struct pmap *, pt_entry_t **, pd_entry_t ***);
        !           341: struct pv_entry *pmap_remove_pv(struct vm_page *, struct pmap *, vaddr_t);
        !           342: void pmap_do_remove(struct pmap *, vaddr_t, vaddr_t, int);
        !           343: boolean_t pmap_remove_pte(struct pmap *, struct vm_page *, pt_entry_t *,
        !           344:     vaddr_t, int);
        !           345: void pmap_remove_ptes(struct pmap *, struct vm_page *, vaddr_t,
        !           346:     vaddr_t, vaddr_t, int);
        !           347: #define PMAP_REMOVE_ALL                0       /* remove all mappings */
        !           348: #define PMAP_REMOVE_SKIPWIRED  1       /* skip wired mappings */
        !           349:
        !           350: void pmap_unmap_ptes(struct pmap *);
        !           351: boolean_t pmap_get_physpage(vaddr_t, int, paddr_t *);
        !           352: boolean_t pmap_pdes_valid(vaddr_t, pd_entry_t **, pd_entry_t *);
        !           353: void pmap_alloc_level(pd_entry_t **, vaddr_t, int, long *);
        !           354: void pmap_apte_flush(struct pmap *pmap);
        !           355:
        !           356: void pmap_sync_flags_pte(struct vm_page *, u_long);
        !           357:
        !           358: /*
        !           359:  * p m a p   i n l i n e   h e l p e r   f u n c t i o n s
        !           360:  */
        !           361:
        !           362: /*
        !           363:  * pmap_is_curpmap: is this pmap the one currently loaded [in %cr3]?
        !           364:  *             of course the kernel is always loaded
        !           365:  */
        !           366:
        !           367: static __inline boolean_t
        !           368: pmap_is_curpmap(struct pmap *pmap)
        !           369: {
        !           370:        return((pmap == pmap_kernel()) ||
        !           371:               (pmap->pm_pdirpa == (paddr_t) rcr3()));
        !           372: }
        !           373:
        !           374: /*
        !           375:  * pmap_is_active: is this pmap loaded into the specified processor's %cr3?
        !           376:  */
        !           377:
        !           378: static __inline boolean_t
        !           379: pmap_is_active(struct pmap *pmap, int cpu_id)
        !           380: {
        !           381:        return (pmap == pmap_kernel() ||
        !           382:            (pmap->pm_cpus & (1U << cpu_id)) != 0);
        !           383: }
        !           384:
        !           385: static __inline u_int
        !           386: pmap_pte2flags(u_long pte)
        !           387: {
        !           388:        return (((pte & PG_U) ? PG_PMAP_REF : 0) |
        !           389:            ((pte & PG_M) ? PG_PMAP_MOD : 0));
        !           390: }
        !           391:
        !           392: void
        !           393: pmap_sync_flags_pte(struct vm_page *pg, u_long pte)
        !           394: {
        !           395:        if (pte & (PG_U|PG_M)) {
        !           396:                atomic_setbits_int(&pg->pg_flags, pmap_pte2flags(pte));
        !           397:        }
        !           398: }
        !           399:
        !           400: void
        !           401: pmap_apte_flush(struct pmap *pmap)
        !           402: {
        !           403:        pmap_tlb_shoottlb();
        !           404:        pmap_tlb_shootwait();
        !           405: }
        !           406:
        !           407: /*
        !           408:  * pmap_map_ptes: map a pmap's PTEs into KVM and lock them in
        !           409:  *
        !           410:  * => we lock enough pmaps to keep things locked in
        !           411:  * => must be undone with pmap_unmap_ptes before returning
        !           412:  */
        !           413:
        !           414: void
        !           415: pmap_map_ptes(struct pmap *pmap, pt_entry_t **ptepp, pd_entry_t ***pdeppp)
        !           416: {
        !           417:        pd_entry_t opde, npde;
        !           418:
        !           419:        /* the kernel's pmap is always accessible */
        !           420:        if (pmap == pmap_kernel()) {
        !           421:                *ptepp = PTE_BASE;
        !           422:                *pdeppp = normal_pdes;
        !           423:                return;
        !           424:        }
        !           425:
        !           426:        /* if curpmap then we are always mapped */
        !           427:        if (pmap_is_curpmap(pmap)) {
        !           428:                simple_lock(&pmap->pm_lock);
        !           429:                *ptepp = PTE_BASE;
        !           430:                *pdeppp = normal_pdes;
        !           431:                return;
        !           432:        }
        !           433:
        !           434:        /* need to lock both curpmap and pmap: use ordered locking */
        !           435:        if ((unsigned long) pmap < (unsigned long) curpcb->pcb_pmap) {
        !           436:                simple_lock(&pmap->pm_lock);
        !           437:                simple_lock(&curpcb->pcb_pmap->pm_lock);
        !           438:        } else {
        !           439:                simple_lock(&curpcb->pcb_pmap->pm_lock);
        !           440:                simple_lock(&pmap->pm_lock);
        !           441:        }
        !           442:
        !           443:        /* need to load a new alternate pt space into curpmap? */
        !           444:        opde = *APDP_PDE;
        !           445:        if (!pmap_valid_entry(opde) || (opde & PG_FRAME) != pmap->pm_pdirpa) {
        !           446:                npde = (pd_entry_t) (pmap->pm_pdirpa | PG_RW | PG_V);
        !           447:                *APDP_PDE = npde;
        !           448:                if (pmap_valid_entry(opde))
        !           449:                        pmap_apte_flush(curpcb->pcb_pmap);
        !           450:        }
        !           451:        *ptepp = APTE_BASE;
        !           452:        *pdeppp = alternate_pdes;
        !           453: }
        !           454:
        !           455: /*
        !           456:  * pmap_unmap_ptes: unlock the PTE mapping of "pmap"
        !           457:  */
        !           458:
        !           459: void
        !           460: pmap_unmap_ptes(struct pmap *pmap)
        !           461: {
        !           462:        if (pmap == pmap_kernel()) {
        !           463:                return;
        !           464:        }
        !           465:        if (pmap_is_curpmap(pmap)) {
        !           466:                simple_unlock(&pmap->pm_lock);
        !           467:        } else {
        !           468: #if defined(MULTIPROCESSOR)
        !           469:                *APDP_PDE = 0;
        !           470:                pmap_apte_flush(curpcb->pcb_pmap);
        !           471: #endif
        !           472:                COUNT(apdp_pde_unmap);
        !           473:                simple_unlock(&pmap->pm_lock);
        !           474:                simple_unlock(&curpcb->pcb_pmap->pm_lock);
        !           475:        }
        !           476: }
        !           477:
        !           478: /*
        !           479:  * p m a p   k e n t e r   f u n c t i o n s
        !           480:  *
        !           481:  * functions to quickly enter/remove pages from the kernel address
        !           482:  * space.   pmap_kremove is exported to MI kernel.  we make use of
        !           483:  * the recursive PTE mappings.
        !           484:  */
        !           485:
        !           486: /*
        !           487:  * pmap_kenter_pa: enter a kernel mapping without R/M (pv_entry) tracking
        !           488:  *
        !           489:  * => no need to lock anything, assume va is already allocated
        !           490:  * => should be faster than normal pmap enter function
        !           491:  */
        !           492:
        !           493: void
        !           494: pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot)
        !           495: {
        !           496:        pt_entry_t *pte, opte, npte;
        !           497:
        !           498:        pte = kvtopte(va);
        !           499:
        !           500:        npte = pa | ((prot & VM_PROT_WRITE) ? PG_RW : PG_RO) |
        !           501:             PG_V | pmap_pg_g;
        !           502:        if ((cpu_feature & CPUID_NXE) && !(prot & VM_PROT_EXECUTE))
        !           503:                npte |= PG_NX;
        !           504:        opte = pmap_pte_set(pte, npte);
        !           505: #ifdef LARGEPAGES
        !           506:        /* XXX For now... */
        !           507:        if (opte & PG_PS)
        !           508:                panic("pmap_kenter_pa: PG_PS");
        !           509: #endif
        !           510:        if (pmap_valid_entry(opte)) {
        !           511:                /* This shouldn't happen */
        !           512:                pmap_tlb_shootpage(pmap_kernel(), va);
        !           513:                pmap_tlb_shootwait();
        !           514:        }
        !           515: }
        !           516:
        !           517: /*
        !           518:  * pmap_kremove: remove a kernel mapping(s) without R/M (pv_entry) tracking
        !           519:  *
        !           520:  * => no need to lock anything
        !           521:  * => caller must dispose of any vm_page mapped in the va range
        !           522:  * => note: not an inline function
        !           523:  * => we assume the va is page aligned and the len is a multiple of PAGE_SIZE
        !           524:  * => we assume kernel only unmaps valid addresses and thus don't bother
        !           525:  *    checking the valid bit before doing TLB flushing
        !           526:  */
        !           527:
        !           528: void
        !           529: pmap_kremove(vaddr_t sva, vsize_t len)
        !           530: {
        !           531:        pt_entry_t *pte, opte;
        !           532:        vaddr_t va, eva;
        !           533:
        !           534:        eva = sva + len;
        !           535:
        !           536:        for (va = sva; va != eva; va += PAGE_SIZE) {
        !           537:                pte = kvtopte(va);
        !           538:
        !           539:                opte = pmap_pte_set(pte, 0);
        !           540: #ifdef LARGEPAGES
        !           541:                KASSERT((opte & PG_PS) == 0);
        !           542: #endif
        !           543:                KASSERT((opte & PG_PVLIST) == 0);
        !           544:        }
        !           545:
        !           546:        pmap_tlb_shootrange(pmap_kernel(), sva, eva);
        !           547:        pmap_tlb_shootwait();
        !           548: }
        !           549:
        !           550: /*
        !           551:  * p m a p   i n i t   f u n c t i o n s
        !           552:  *
        !           553:  * pmap_bootstrap and pmap_init are called during system startup
        !           554:  * to init the pmap module.   pmap_bootstrap() does a low level
        !           555:  * init just to get things rolling.   pmap_init() finishes the job.
        !           556:  */
        !           557:
        !           558: /*
        !           559:  * pmap_bootstrap: get the system in a state where it can run with VM
        !           560:  *     properly enabled (called before main()).   the VM system is
        !           561:  *      fully init'd later...
        !           562:  *
        !           563:  * => on i386, locore.s has already enabled the MMU by allocating
        !           564:  *     a PDP for the kernel, and nkpde PTP's for the kernel.
        !           565:  * => kva_start is the first free virtual address in kernel space
        !           566:  */
        !           567:
        !           568: void
        !           569: pmap_bootstrap(vaddr_t kva_start, paddr_t max_pa)
        !           570: {
        !           571:        vaddr_t kva, kva_end;
        !           572:        struct pmap *kpm;
        !           573:        int i;
        !           574:        unsigned long p1i;
        !           575:        pt_entry_t pg_nx = (cpu_feature & CPUID_NXE? PG_NX : 0);
        !           576:        long ndmpdp;
        !           577:        paddr_t dmpd, dmpdp;
        !           578:
        !           579:        /*
        !           580:         * define the voundaries of the managed kernel virtual address
        !           581:         * space.
        !           582:         */
        !           583:
        !           584:        virtual_avail = kva_start;              /* first free KVA */
        !           585:
        !           586:        /*
        !           587:         * set up protection_codes: we need to be able to convert from
        !           588:         * a MI protection code (some combo of VM_PROT...) to something
        !           589:         * we can jam into a i386 PTE.
        !           590:         */
        !           591:
        !           592:        protection_codes[VM_PROT_NONE] = pg_nx;                 /* --- */
        !           593:        protection_codes[VM_PROT_EXECUTE] = PG_RO;              /* --x */
        !           594:        protection_codes[VM_PROT_READ] = PG_RO | pg_nx;         /* -r- */
        !           595:        protection_codes[VM_PROT_READ|VM_PROT_EXECUTE] = PG_RO; /* -rx */
        !           596:        protection_codes[VM_PROT_WRITE] = PG_RW | pg_nx;        /* w-- */
        !           597:        protection_codes[VM_PROT_WRITE|VM_PROT_EXECUTE] = PG_RW;/* w-x */
        !           598:        protection_codes[VM_PROT_WRITE|VM_PROT_READ] = PG_RW | pg_nx;
        !           599:                                                                /* wr- */
        !           600:        protection_codes[VM_PROT_ALL] = PG_RW;                  /* wrx */
        !           601:
        !           602:        /*
        !           603:         * now we init the kernel's pmap
        !           604:         *
        !           605:         * the kernel pmap's pm_obj is not used for much.   however, in
        !           606:         * user pmaps the pm_obj contains the list of active PTPs.
        !           607:         * the pm_obj currently does not have a pager.   it might be possible
        !           608:         * to add a pager that would allow a process to read-only mmap its
        !           609:         * own page tables (fast user level vtophys?).   this may or may not
        !           610:         * be useful.
        !           611:         */
        !           612:
        !           613:        kpm = pmap_kernel();
        !           614:        for (i = 0; i < PTP_LEVELS - 1; i++) {
        !           615:                simple_lock_init(&kpm->pm_obj[i].vmobjlock);
        !           616:                kpm->pm_obj[i].pgops = NULL;
        !           617:                TAILQ_INIT(&kpm->pm_obj[i].memq);
        !           618:                kpm->pm_obj[i].uo_npages = 0;
        !           619:                kpm->pm_obj[i].uo_refs = 1;
        !           620:                kpm->pm_ptphint[i] = NULL;
        !           621:        }
        !           622:        memset(&kpm->pm_list, 0, sizeof(kpm->pm_list));  /* pm_list not used */
        !           623:        kpm->pm_pdir = (pd_entry_t *)(proc0.p_addr->u_pcb.pcb_cr3 + KERNBASE);
        !           624:        kpm->pm_pdirpa = (u_int32_t) proc0.p_addr->u_pcb.pcb_cr3;
        !           625:        kpm->pm_stats.wired_count = kpm->pm_stats.resident_count =
        !           626:                atop(kva_start - VM_MIN_KERNEL_ADDRESS);
        !           627:
        !           628:        /*
        !           629:         * the above is just a rough estimate and not critical to the proper
        !           630:         * operation of the system.
        !           631:         */
        !           632:
        !           633:        curpcb->pcb_pmap = kpm; /* proc0's pcb */
        !           634:
        !           635:        /*
        !           636:         * enable global TLB entries.
        !           637:         */
        !           638:        pmap_pg_g = PG_G;               /* enable software */
        !           639:
        !           640:        /* add PG_G attribute to already mapped kernel pages */
        !           641: #if KERNBASE == VM_MIN_KERNEL_ADDRESS
        !           642:        for (kva = VM_MIN_KERNEL_ADDRESS ; kva < virtual_avail ;
        !           643: #else
        !           644:        kva_end = roundup((vaddr_t)&end, PAGE_SIZE);
        !           645:        for (kva = KERNBASE; kva < kva_end ;
        !           646: #endif
        !           647:             kva += PAGE_SIZE) {
        !           648:                p1i = pl1_i(kva);
        !           649:                if (pmap_valid_entry(PTE_BASE[p1i]))
        !           650:                        PTE_BASE[p1i] |= PG_G;
        !           651:        }
        !           652:
        !           653:        /*
        !           654:         * Map the direct map. The first 4GB were mapped in locore, here
        !           655:         * we map the rest if it exists. We actually use the direct map
        !           656:         * here to set up the page tables, we're assuming that we're still
        !           657:         * operating in the lower 4GB of memory.
        !           658:         */
        !           659:        ndmpdp = (max_pa + NBPD_L3 - 1) >> L3_SHIFT;
        !           660:        if (ndmpdp < NDML2_ENTRIES)
        !           661:                ndmpdp = NDML2_ENTRIES;         /* At least 4GB */
        !           662:
        !           663:        dmpdp = kpm->pm_pdir[PDIR_SLOT_DIRECT] & PG_FRAME;
        !           664:
        !           665:        dmpd = avail_start; avail_start += ndmpdp * PAGE_SIZE;
        !           666:
        !           667:        for (i = NDML2_ENTRIES; i < NPDPG * ndmpdp; i++) {
        !           668:                paddr_t pdp;
        !           669:                vaddr_t va;
        !           670:
        !           671:                pdp = (paddr_t)&(((pd_entry_t *)dmpd)[i]);
        !           672:                va = PMAP_DIRECT_MAP(pdp);
        !           673:
        !           674:                *((pd_entry_t *)va) = ((paddr_t)i << L2_SHIFT);
        !           675:                *((pd_entry_t *)va) |= PG_RW | PG_V | PG_PS | PG_G | PG_U |
        !           676:                    PG_M;
        !           677:        }
        !           678:
        !           679:        for (i = NDML2_ENTRIES; i < ndmpdp; i++) {
        !           680:                paddr_t pdp;
        !           681:                vaddr_t va;
        !           682:
        !           683:                pdp = (paddr_t)&(((pd_entry_t *)dmpdp)[i]);
        !           684:                va = PMAP_DIRECT_MAP(pdp);
        !           685:
        !           686:                *((pd_entry_t *)va) = dmpd + (i << PAGE_SHIFT);
        !           687:                *((pd_entry_t *)va) |= PG_RW | PG_V | PG_U | PG_M;
        !           688:        }
        !           689:
        !           690:        kpm->pm_pdir[PDIR_SLOT_DIRECT] = dmpdp | PG_V | PG_KW | PG_U |
        !           691:            PG_M;
        !           692:
        !           693:        /*
        !           694:         * Now do the same thing, but for the direct uncached map.
        !           695:         */
        !           696:        ndmpdp = (max_pa + NBPD_L3 - 1) >> L3_SHIFT;
        !           697:        if (ndmpdp < NDML2_ENTRIES)
        !           698:                ndmpdp = NDML2_ENTRIES;         /* At least 4GB */
        !           699:
        !           700:        dmpdp = avail_start;    avail_start += PAGE_SIZE;
        !           701:        dmpd = avail_start;     avail_start += ndmpdp * PAGE_SIZE;
        !           702:
        !           703:        for (i = 0; i < NPDPG * ndmpdp; i++) {
        !           704:                paddr_t pdp;
        !           705:                vaddr_t va;
        !           706:
        !           707:                pdp = (paddr_t)&(((pd_entry_t *)dmpd)[i]);
        !           708:                va = PMAP_DIRECT_MAP(pdp);
        !           709:
        !           710:                *((pd_entry_t *)va) = (paddr_t)i << L2_SHIFT;
        !           711:                *((pd_entry_t *)va) |= PG_RW | PG_V | PG_PS | PG_G | PG_N |
        !           712:                    PG_U | PG_M;
        !           713:        }
        !           714:
        !           715:        for (i = 0; i < ndmpdp; i++) {
        !           716:                paddr_t pdp;
        !           717:                vaddr_t va;
        !           718:
        !           719:                pdp = (paddr_t)&(((pd_entry_t *)dmpdp)[i]);
        !           720:                va = PMAP_DIRECT_MAP(pdp);
        !           721:
        !           722:                *((pd_entry_t *)va) = dmpd + (i << PAGE_SHIFT);
        !           723:                *((pd_entry_t *)va) |= PG_RW | PG_V | PG_U | PG_M;
        !           724:        }
        !           725:
        !           726:        kpm->pm_pdir[PDIR_SLOT_DIRECT_NC] = dmpdp | PG_V | PG_KW | PG_U |
        !           727:            PG_M;
        !           728:
        !           729:        tlbflush();
        !           730:
        !           731:        msgbuf_vaddr = virtual_avail;
        !           732:        virtual_avail += round_page(MSGBUFSIZE);
        !           733:
        !           734:        idt_vaddr = virtual_avail;
        !           735:        virtual_avail += 2 * PAGE_SIZE;
        !           736:        idt_paddr = avail_start;                        /* steal a page */
        !           737:        avail_start += 2 * PAGE_SIZE;
        !           738:
        !           739: #ifdef _LP64
        !           740:        /*
        !           741:         * Grab a page below 4G for things that need it (i.e.
        !           742:         * having an initial %cr3 for the MP trampoline).
        !           743:         */
        !           744:        lo32_vaddr = virtual_avail;
        !           745:        virtual_avail += PAGE_SIZE;
        !           746:        lo32_paddr = avail_start;
        !           747:        avail_start += PAGE_SIZE;
        !           748: #endif
        !           749:
        !           750:        /*
        !           751:         * now we reserve some VM for mapping pages when doing a crash dump
        !           752:         */
        !           753:
        !           754:        virtual_avail = reserve_dumppages(virtual_avail);
        !           755:
        !           756:        /*
        !           757:         * init the static-global locks and global lists.
        !           758:         */
        !           759:
        !           760:        simple_lock_init(&pmaps_lock);
        !           761:        LIST_INIT(&pmaps);
        !           762:
        !           763:        /*
        !           764:         * initialize the pmap pool.
        !           765:         */
        !           766:
        !           767:        pool_init(&pmap_pmap_pool, sizeof(struct pmap), 0, 0, 0, "pmappl",
        !           768:            &pool_allocator_nointr);
        !           769:        pool_init(&pmap_pv_pool, sizeof(struct pv_entry), 0, 0, 0, "pvpl",
        !           770:            &pool_allocator_nointr);
        !           771:        pool_sethiwat(&pmap_pv_pool, 32 * 1024);
        !           772:
        !           773:        /*
        !           774:         * initialize the PDE pool and cache.
        !           775:         */
        !           776:
        !           777:        pool_init(&pmap_pdp_pool, PAGE_SIZE, 0, 0, 0, "pdppl",
        !           778:                  &pool_allocator_nointr);
        !           779:        pool_cache_init(&pmap_pdp_cache, &pmap_pdp_pool,
        !           780:                        pmap_pdp_ctor, NULL, NULL);
        !           781:
        !           782:        /*
        !           783:         * ensure the TLB is sync'd with reality by flushing it...
        !           784:         */
        !           785:
        !           786:        tlbflush();
        !           787: }
        !           788:
        !           789: /*
        !           790:  * Pre-allocate PTPs for low memory, so that 1:1 mappings for various
        !           791:  * trampoline code can be entered.
        !           792:  */
        !           793: void
        !           794: pmap_prealloc_lowmem_ptps(void)
        !           795: {
        !           796:        pd_entry_t *pdes;
        !           797:        int level;
        !           798:        paddr_t newp;
        !           799:
        !           800:        pdes = pmap_kernel()->pm_pdir;
        !           801:        level = PTP_LEVELS;
        !           802:        for (;;) {
        !           803:                newp = avail_start;
        !           804:                avail_start += PAGE_SIZE;
        !           805:                memset((void *)PMAP_DIRECT_MAP(newp), 0, PAGE_SIZE);
        !           806:                pdes[pl_i(0, level)] = (newp & PG_FRAME) | PG_V | PG_RW;
        !           807:                level--;
        !           808:                if (level <= 1)
        !           809:                        break;
        !           810:                pdes = normal_pdes[level - 2];
        !           811:        }
        !           812: }
        !           813:
        !           814: /*
        !           815:  * pmap_init: called from uvm_init, our job is to get the pmap
        !           816:  * system ready to manage mappings... this mainly means initing
        !           817:  * the pv_entry stuff.
        !           818:  */
        !           819:
        !           820: void
        !           821: pmap_init(void)
        !           822: {
        !           823:        /*
        !           824:         * done: pmap module is up (and ready for business)
        !           825:         */
        !           826:
        !           827:        pmap_initialized = TRUE;
        !           828: }
        !           829:
        !           830: /*
        !           831:  * p v _ e n t r y   f u n c t i o n s
        !           832:  */
        !           833:
        !           834: /*
        !           835:  * main pv_entry manipulation functions:
        !           836:  *   pmap_enter_pv: enter a mapping onto a pv list
        !           837:  *   pmap_remove_pv: remove a mapping from a pv list
        !           838:  */
        !           839:
        !           840: /*
        !           841:  * pmap_enter_pv: enter a mapping onto a pv list
        !           842:  *
        !           843:  * => caller should have pmap locked
        !           844:  * => caller should adjust ptp's wire_count before calling
        !           845:  *
        !           846:  * pve: preallocated pve for us to use
        !           847:  * ptp: PTP in pmap that maps this VA
        !           848:  */
        !           849:
        !           850: void
        !           851: pmap_enter_pv(struct vm_page *pg, struct pv_entry *pve, struct pmap *pmap,
        !           852:     vaddr_t va, struct vm_page *ptp)
        !           853: {
        !           854:        pve->pv_pmap = pmap;
        !           855:        pve->pv_va = va;
        !           856:        pve->pv_ptp = ptp;                      /* NULL for kernel pmap */
        !           857:        pve->pv_next = pg->mdpage.pv_list;      /* add to ... */
        !           858:        pg->mdpage.pv_list = pve;               /* ... list */
        !           859: }
        !           860:
        !           861: /*
        !           862:  * pmap_remove_pv: try to remove a mapping from a pv_list
        !           863:  *
        !           864:  * => pmap should be locked
        !           865:  * => caller should adjust ptp's wire_count and free PTP if needed
        !           866:  * => we return the removed pve
        !           867:  */
        !           868:
        !           869: struct pv_entry *
        !           870: pmap_remove_pv(struct vm_page *pg, struct pmap *pmap, vaddr_t va)
        !           871: {
        !           872:        struct pv_entry *pve, **prevptr;
        !           873:
        !           874:        prevptr = &pg->mdpage.pv_list;
        !           875:        while ((pve = *prevptr) != NULL) {
        !           876:                if (pve->pv_pmap == pmap && pve->pv_va == va) { /* match? */
        !           877:                        *prevptr = pve->pv_next;                /* remove it! */
        !           878:                        break;
        !           879:                }
        !           880:                prevptr = &pve->pv_next;                /* previous pointer */
        !           881:        }
        !           882:        return(pve);                            /* return removed pve */
        !           883: }
        !           884:
        !           885: /*
        !           886:  * p t p   f u n c t i o n s
        !           887:  */
        !           888:
        !           889: struct vm_page *
        !           890: pmap_find_ptp(struct pmap *pmap, vaddr_t va, paddr_t pa, int level)
        !           891: {
        !           892:        int lidx = level - 1;
        !           893:        struct vm_page *pg;
        !           894:
        !           895:        if (pa != (paddr_t)-1 && pmap->pm_ptphint[lidx] &&
        !           896:            pa == VM_PAGE_TO_PHYS(pmap->pm_ptphint[lidx])) {
        !           897:                return (pmap->pm_ptphint[lidx]);
        !           898:        }
        !           899:        if (lidx == 0)
        !           900:                pg = uvm_pagelookup(&pmap->pm_obj[lidx], ptp_va2o(va, level));
        !           901:        else {
        !           902:                simple_lock(&pmap->pm_obj[lidx].vmobjlock);
        !           903:                pg = uvm_pagelookup(&pmap->pm_obj[lidx], ptp_va2o(va, level));
        !           904:                simple_unlock(&pmap->pm_obj[lidx].vmobjlock);
        !           905:        }
        !           906:        return pg;
        !           907: }
        !           908:
        !           909: void
        !           910: pmap_freepage(struct pmap *pmap, struct vm_page *ptp, int level,
        !           911:     struct pg_to_free *pagelist)
        !           912: {
        !           913:        int lidx;
        !           914:        struct uvm_object *obj;
        !           915:
        !           916:        lidx = level - 1;
        !           917:
        !           918:        obj = &pmap->pm_obj[lidx];
        !           919:        pmap->pm_stats.resident_count--;
        !           920:        if (pmap->pm_ptphint[lidx] == ptp)
        !           921:                pmap->pm_ptphint[lidx] = TAILQ_FIRST(&obj->memq);
        !           922:        ptp->wire_count = 0;
        !           923:        uvm_pagerealloc(ptp, NULL, 0);
        !           924:        TAILQ_INSERT_TAIL(pagelist, ptp, listq);
        !           925: }
        !           926:
        !           927: void
        !           928: pmap_free_ptp(struct pmap *pmap, struct vm_page *ptp, vaddr_t va,
        !           929:     pt_entry_t *ptes, pd_entry_t **pdes, struct pg_to_free *pagelist)
        !           930: {
        !           931:        unsigned long index;
        !           932:        int level;
        !           933:        vaddr_t invaladdr;
        !           934:        pd_entry_t opde;
        !           935:
        !           936:        level = 1;
        !           937:        do {
        !           938:                pmap_freepage(pmap, ptp, level, pagelist);
        !           939:                index = pl_i(va, level + 1);
        !           940:                opde = pmap_pte_set(&pdes[level - 1][index], 0);
        !           941:                invaladdr = level == 1 ? (vaddr_t)ptes :
        !           942:                    (vaddr_t)pdes[level - 2];
        !           943:                pmap_tlb_shootpage(curpcb->pcb_pmap,
        !           944:                    invaladdr + index * PAGE_SIZE);
        !           945: #if defined(MULTIPROCESSOR)
        !           946:                invaladdr = level == 1 ? (vaddr_t)PTE_BASE :
        !           947:                    (vaddr_t)normal_pdes[level - 2];
        !           948:                pmap_tlb_shootpage(pmap, invaladdr + index * PAGE_SIZE);
        !           949: #endif
        !           950:                if (level < PTP_LEVELS - 1) {
        !           951:                        ptp = pmap_find_ptp(pmap, va, (paddr_t)-1, level + 1);
        !           952:                        ptp->wire_count--;
        !           953:                        if (ptp->wire_count > 1)
        !           954:                                break;
        !           955:                }
        !           956:        } while (++level < PTP_LEVELS);
        !           957: }
        !           958:
        !           959: /*
        !           960:  * pmap_get_ptp: get a PTP (if there isn't one, allocate a new one)
        !           961:  *
        !           962:  * => pmap should NOT be pmap_kernel()
        !           963:  * => pmap should be locked
        !           964:  */
        !           965:
        !           966:
        !           967: struct vm_page *
        !           968: pmap_get_ptp(struct pmap *pmap, vaddr_t va, pd_entry_t **pdes)
        !           969: {
        !           970:        struct vm_page *ptp, *pptp;
        !           971:        int i;
        !           972:        unsigned long index;
        !           973:        pd_entry_t *pva;
        !           974:        paddr_t ppa, pa;
        !           975:        struct uvm_object *obj;
        !           976:
        !           977:        ptp = NULL;
        !           978:        pa = (paddr_t)-1;
        !           979:
        !           980:        /*
        !           981:         * Loop through all page table levels seeing if we need to
        !           982:         * add a new page to that level.
        !           983:         */
        !           984:        for (i = PTP_LEVELS; i > 1; i--) {
        !           985:                /*
        !           986:                 * Save values from previous round.
        !           987:                 */
        !           988:                pptp = ptp;
        !           989:                ppa = pa;
        !           990:
        !           991:                index = pl_i(va, i);
        !           992:                pva = pdes[i - 2];
        !           993:
        !           994:                if (pmap_valid_entry(pva[index])) {
        !           995:                        ppa = pva[index] & PG_FRAME;
        !           996:                        ptp = NULL;
        !           997:                        continue;
        !           998:                }
        !           999:
        !          1000:                obj = &pmap->pm_obj[i-2];
        !          1001:                /*
        !          1002:                 * XXX pm_obj[0] is pm_lock, which is already locked.
        !          1003:                 */
        !          1004:                if (i != 2)
        !          1005:                        simple_lock(&obj->vmobjlock);
        !          1006:                ptp = uvm_pagealloc(obj, ptp_va2o(va, i - 1), NULL,
        !          1007:                    UVM_PGA_USERESERVE|UVM_PGA_ZERO);
        !          1008:                if (i != 2)
        !          1009:                        simple_unlock(&obj->vmobjlock);
        !          1010:
        !          1011:                if (ptp == NULL)
        !          1012:                        return NULL;
        !          1013:
        !          1014:                atomic_clearbits_int(&ptp->pg_flags, PG_BUSY);
        !          1015:                ptp->wire_count = 1;
        !          1016:                pmap->pm_ptphint[i - 2] = ptp;
        !          1017:                pa = VM_PAGE_TO_PHYS(ptp);
        !          1018:                pva[index] = (pd_entry_t) (pa | PG_u | PG_RW | PG_V);
        !          1019:                pmap->pm_stats.resident_count++;
        !          1020:                /*
        !          1021:                 * If we're not in the top level, increase the
        !          1022:                 * wire count of the parent page.
        !          1023:                 */
        !          1024:                if (i < PTP_LEVELS) {
        !          1025:                        if (pptp == NULL)
        !          1026:                                pptp = pmap_find_ptp(pmap, va, ppa, i);
        !          1027: #ifdef DIAGNOSTIC
        !          1028:                        if (pptp == NULL)
        !          1029:                                panic("pde page disappeared");
        !          1030: #endif
        !          1031:                        pptp->wire_count++;
        !          1032:                }
        !          1033:        }
        !          1034:
        !          1035:        /*
        !          1036:         * ptp is not NULL if we just allocated a new ptp. If it's
        !          1037:         * still NULL, we must look up the existing one.
        !          1038:         */
        !          1039:        if (ptp == NULL) {
        !          1040:                ptp = pmap_find_ptp(pmap, va, ppa, 1);
        !          1041: #ifdef DIAGNOSTIC
        !          1042:                if (ptp == NULL) {
        !          1043:                        printf("va %lx ppa %lx\n", (unsigned long)va,
        !          1044:                            (unsigned long)ppa);
        !          1045:                        panic("pmap_get_ptp: unmanaged user PTP");
        !          1046:                }
        !          1047: #endif
        !          1048:        }
        !          1049:
        !          1050:        pmap->pm_ptphint[0] = ptp;
        !          1051:        return(ptp);
        !          1052: }
        !          1053:
        !          1054: /*
        !          1055:  * p m a p  l i f e c y c l e   f u n c t i o n s
        !          1056:  */
        !          1057:
        !          1058: /*
        !          1059:  * pmap_pdp_ctor: constructor for the PDP cache.
        !          1060:  */
        !          1061:
        !          1062: int
        !          1063: pmap_pdp_ctor(void *arg, void *object, int flags)
        !          1064: {
        !          1065:        pd_entry_t *pdir = object;
        !          1066:        paddr_t pdirpa;
        !          1067:        int npde;
        !          1068:
        !          1069:        /*
        !          1070:         * NOTE: The `pmap_lock' is held when the PDP is allocated.
        !          1071:         * WE MUST NOT BLOCK!
        !          1072:         */
        !          1073:
        !          1074:        /* fetch the physical address of the page directory. */
        !          1075:        (void) pmap_extract(pmap_kernel(), (vaddr_t) pdir, &pdirpa);
        !          1076:
        !          1077:        /* zero init area */
        !          1078:        memset(pdir, 0, PDIR_SLOT_PTE * sizeof(pd_entry_t));
        !          1079:
        !          1080:        /* put in recursive PDE to map the PTEs */
        !          1081:        pdir[PDIR_SLOT_PTE] = pdirpa | PG_V | PG_KW;
        !          1082:
        !          1083:        npde = nkptp[PTP_LEVELS - 1];
        !          1084:
        !          1085:        /* put in kernel VM PDEs */
        !          1086:        memcpy(&pdir[PDIR_SLOT_KERN], &PDP_BASE[PDIR_SLOT_KERN],
        !          1087:            npde * sizeof(pd_entry_t));
        !          1088:
        !          1089:        /* zero the rest */
        !          1090:        memset(&pdir[PDIR_SLOT_KERN + npde], 0,
        !          1091:            (NTOPLEVEL_PDES - (PDIR_SLOT_KERN + npde)) * sizeof(pd_entry_t));
        !          1092:
        !          1093:        pdir[PDIR_SLOT_DIRECT] = pmap_kernel()->pm_pdir[PDIR_SLOT_DIRECT];
        !          1094:        pdir[PDIR_SLOT_DIRECT_NC] = pmap_kernel()->pm_pdir[PDIR_SLOT_DIRECT_NC];
        !          1095:
        !          1096: #if VM_MIN_KERNEL_ADDRESS != KERNBASE
        !          1097:        pdir[pl4_pi(KERNBASE)] = PDP_BASE[pl4_pi(KERNBASE)];
        !          1098: #endif
        !          1099:
        !          1100:        return (0);
        !          1101: }
        !          1102:
        !          1103: /*
        !          1104:  * pmap_create: create a pmap
        !          1105:  *
        !          1106:  * => note: old pmap interface took a "size" args which allowed for
        !          1107:  *     the creation of "software only" pmaps (not in bsd).
        !          1108:  */
        !          1109:
        !          1110: struct pmap *
        !          1111: pmap_create(void)
        !          1112: {
        !          1113:        struct pmap *pmap;
        !          1114:        int i;
        !          1115:        u_int gen;
        !          1116:
        !          1117:        pmap = pool_get(&pmap_pmap_pool, PR_WAITOK);
        !          1118:
        !          1119:        /* init uvm_object */
        !          1120:        for (i = 0; i < PTP_LEVELS - 1; i++) {
        !          1121:                simple_lock_init(&pmap->pm_obj[i].vmobjlock);
        !          1122:                pmap->pm_obj[i].pgops = NULL;   /* not a mappable object */
        !          1123:                TAILQ_INIT(&pmap->pm_obj[i].memq);
        !          1124:                pmap->pm_obj[i].uo_npages = 0;
        !          1125:                pmap->pm_obj[i].uo_refs = 1;
        !          1126:                pmap->pm_ptphint[i] = NULL;
        !          1127:        }
        !          1128:        pmap->pm_stats.wired_count = 0;
        !          1129:        pmap->pm_stats.resident_count = 1;      /* count the PDP allocd below */
        !          1130:        pmap->pm_flags = 0;
        !          1131:
        !          1132:        /* init the LDT */
        !          1133:        pmap->pm_ldt = NULL;
        !          1134:        pmap->pm_ldt_len = 0;
        !          1135:        pmap->pm_ldt_sel = GSYSSEL(GLDT_SEL, SEL_KPL);
        !          1136:
        !          1137:        /* allocate PDP */
        !          1138:
        !          1139:        /*
        !          1140:         * we need to lock pmaps_lock to prevent nkpde from changing on
        !          1141:         * us.  note that there is no need to splvm to protect us from
        !          1142:         * malloc since malloc allocates out of a submap and we should
        !          1143:         * have already allocated kernel PTPs to cover the range...
        !          1144:         *
        !          1145:         * NOTE: WE MUST NOT BLOCK WHILE HOLDING THE `pmap_lock', nor
        !          1146:         * ust we call pmap_growkernel() while holding it!
        !          1147:         */
        !          1148:
        !          1149: try_again:
        !          1150:        gen = pmap_pdp_cache_generation;
        !          1151:        pmap->pm_pdir = pool_cache_get(&pmap_pdp_cache, PR_WAITOK);
        !          1152:
        !          1153:        simple_lock(&pmaps_lock);
        !          1154:
        !          1155:        if (gen != pmap_pdp_cache_generation) {
        !          1156:                simple_unlock(&pmaps_lock);
        !          1157:                pool_cache_destruct_object(&pmap_pdp_cache, pmap->pm_pdir);
        !          1158:                goto try_again;
        !          1159:        }
        !          1160:
        !          1161:        pmap->pm_pdirpa = pmap->pm_pdir[PDIR_SLOT_PTE] & PG_FRAME;
        !          1162:
        !          1163:        LIST_INSERT_HEAD(&pmaps, pmap, pm_list);
        !          1164:
        !          1165:        simple_unlock(&pmaps_lock);
        !          1166:
        !          1167:        return (pmap);
        !          1168: }
        !          1169:
        !          1170: /*
        !          1171:  * pmap_destroy: drop reference count on pmap.   free pmap if
        !          1172:  *     reference count goes to zero.
        !          1173:  */
        !          1174:
        !          1175: void
        !          1176: pmap_destroy(struct pmap *pmap)
        !          1177: {
        !          1178:        struct vm_page *pg;
        !          1179:        int refs;
        !          1180:        int i;
        !          1181:
        !          1182:        /*
        !          1183:         * drop reference count
        !          1184:         */
        !          1185:
        !          1186:        simple_lock(&pmap->pm_lock);
        !          1187:        refs = --pmap->pm_obj[0].uo_refs;
        !          1188:        simple_unlock(&pmap->pm_lock);
        !          1189:        if (refs > 0) {
        !          1190:                return;
        !          1191:        }
        !          1192:
        !          1193:        /*
        !          1194:         * reference count is zero, free pmap resources and then free pmap.
        !          1195:         */
        !          1196:
        !          1197:        /*
        !          1198:         * remove it from global list of pmaps
        !          1199:         */
        !          1200:
        !          1201:        simple_lock(&pmaps_lock);
        !          1202:        LIST_REMOVE(pmap, pm_list);
        !          1203:        simple_unlock(&pmaps_lock);
        !          1204:
        !          1205:        /*
        !          1206:         * free any remaining PTPs
        !          1207:         */
        !          1208:
        !          1209:        for (i = 0; i < PTP_LEVELS - 1; i++) {
        !          1210:                while ((pg = TAILQ_FIRST(&pmap->pm_obj[i].memq)) != NULL) {
        !          1211:                        KASSERT((pg->pg_flags & PG_BUSY) == 0);
        !          1212:
        !          1213:                        pg->wire_count = 0;
        !          1214:                        uvm_pagefree(pg);
        !          1215:                }
        !          1216:        }
        !          1217:
        !          1218:        /*
        !          1219:         * MULTIPROCESSOR -- no need to flush out of other processors'
        !          1220:         * APTE space because we do that in pmap_unmap_ptes().
        !          1221:         */
        !          1222:        /* XXX: need to flush it out of other processor's APTE space? */
        !          1223:        pool_cache_put(&pmap_pdp_cache, pmap->pm_pdir);
        !          1224:
        !          1225: #ifdef USER_LDT
        !          1226:        if (pmap->pm_flags & PMF_USER_LDT) {
        !          1227:                /*
        !          1228:                 * no need to switch the LDT; this address space is gone,
        !          1229:                 * nothing is using it.
        !          1230:                 *
        !          1231:                 * No need to lock the pmap for ldt_free (or anything else),
        !          1232:                 * we're the last one to use it.
        !          1233:                 */
        !          1234:                ldt_free(pmap);
        !          1235:                uvm_km_free(kernel_map, (vaddr_t)pmap->pm_ldt,
        !          1236:                            pmap->pm_ldt_len);
        !          1237:        }
        !          1238: #endif
        !          1239:
        !          1240:        pool_put(&pmap_pmap_pool, pmap);
        !          1241: }
        !          1242:
        !          1243: /*
        !          1244:  *     Add a reference to the specified pmap.
        !          1245:  */
        !          1246:
        !          1247: void
        !          1248: pmap_reference(struct pmap *pmap)
        !          1249: {
        !          1250:        simple_lock(&pmap->pm_lock);
        !          1251:        pmap->pm_obj[0].uo_refs++;
        !          1252:        simple_unlock(&pmap->pm_lock);
        !          1253: }
        !          1254:
        !          1255: #if defined(PMAP_FORK)
        !          1256: /*
        !          1257:  * pmap_fork: perform any necessary data structure manipulation when
        !          1258:  * a VM space is forked.
        !          1259:  */
        !          1260:
        !          1261: void
        !          1262: pmap_fork(struct pmap *pmap1, struct pmap *pmap2)
        !          1263: {
        !          1264:        simple_lock(&pmap1->pm_lock);
        !          1265:        simple_lock(&pmap2->pm_lock);
        !          1266:
        !          1267: #ifdef USER_LDT
        !          1268:        /* Copy the LDT, if necessary. */
        !          1269:        if (pmap1->pm_flags & PMF_USER_LDT) {
        !          1270:                char *new_ldt;
        !          1271:                size_t len;
        !          1272:
        !          1273:                len = pmap1->pm_ldt_len;
        !          1274:                new_ldt = (char *)uvm_km_alloc(kernel_map, len);
        !          1275:                memcpy(new_ldt, pmap1->pm_ldt, len);
        !          1276:                pmap2->pm_ldt = new_ldt;
        !          1277:                pmap2->pm_ldt_len = pmap1->pm_ldt_len;
        !          1278:                pmap2->pm_flags |= PMF_USER_LDT;
        !          1279:                ldt_alloc(pmap2, new_ldt, len);
        !          1280:        }
        !          1281: #endif /* USER_LDT */
        !          1282:
        !          1283:        simple_unlock(&pmap2->pm_lock);
        !          1284:        simple_unlock(&pmap1->pm_lock);
        !          1285: }
        !          1286: #endif /* PMAP_FORK */
        !          1287:
        !          1288: #ifdef USER_LDT
        !          1289: /*
        !          1290:  * pmap_ldt_cleanup: if the pmap has a local LDT, deallocate it, and
        !          1291:  * restore the default.
        !          1292:  */
        !          1293:
        !          1294: void
        !          1295: pmap_ldt_cleanup(struct proc *p)
        !          1296: {
        !          1297:        struct pcb *pcb = &p->p_addr->u_pcb;
        !          1298:        pmap_t pmap = p->->p_vmspace->vm_map.pmap;
        !          1299:        char *old_ldt = NULL;
        !          1300:        size_t len = 0;
        !          1301:
        !          1302:        simple_lock(&pmap->pm_lock);
        !          1303:
        !          1304:        if (pmap->pm_flags & PMF_USER_LDT) {
        !          1305:                ldt_free(pmap);
        !          1306:                pmap->pm_ldt_sel = GSYSSEL(GLDT_SEL, SEL_KPL);
        !          1307:                pcb->pcb_ldt_sel = pmap->pm_ldt_sel;
        !          1308:                if (pcb == curpcb)
        !          1309:                        lldt(pcb->pcb_ldt_sel);
        !          1310:                old_ldt = pmap->pm_ldt;
        !          1311:                len = pmap->pm_ldt_len;
        !          1312:                pmap->pm_ldt = NULL;
        !          1313:                pmap->pm_ldt_len = 0;
        !          1314:                pmap->pm_flags &= ~PMF_USER_LDT;
        !          1315:        }
        !          1316:
        !          1317:        simple_unlock(&pmap->pm_lock);
        !          1318:
        !          1319:        if (old_ldt != NULL)
        !          1320:                uvm_km_free(kernel_map, (vaddr_t)old_ldt, len);
        !          1321: }
        !          1322: #endif /* USER_LDT */
        !          1323:
        !          1324: /*
        !          1325:  * pmap_activate: activate a process' pmap (fill in %cr3 and LDT info)
        !          1326:  *
        !          1327:  * => called from cpu_switch()
        !          1328:  * => if p is the curproc, then load it into the MMU
        !          1329:  */
        !          1330:
        !          1331: void
        !          1332: pmap_activate(struct proc *p)
        !          1333: {
        !          1334:        struct pcb *pcb = &p->p_addr->u_pcb;
        !          1335:        struct pmap *pmap = p->p_vmspace->vm_map.pmap;
        !          1336:
        !          1337:        pcb->pcb_pmap = pmap;
        !          1338:        pcb->pcb_ldt_sel = pmap->pm_ldt_sel;
        !          1339:        pcb->pcb_cr3 = pmap->pm_pdirpa;
        !          1340:        if (p == curproc)
        !          1341:                lcr3(pcb->pcb_cr3);
        !          1342:        if (pcb == curpcb)
        !          1343:                lldt(pcb->pcb_ldt_sel);
        !          1344:
        !          1345:        /*
        !          1346:         * mark the pmap in use by this processor.
        !          1347:         */
        !          1348:        x86_atomic_setbits_ul(&pmap->pm_cpus, (1U << cpu_number()));
        !          1349: }
        !          1350:
        !          1351: /*
        !          1352:  * pmap_deactivate: deactivate a process' pmap
        !          1353:  */
        !          1354:
        !          1355: void
        !          1356: pmap_deactivate(struct proc *p)
        !          1357: {
        !          1358:        struct pmap *pmap = p->p_vmspace->vm_map.pmap;
        !          1359:
        !          1360:        /*
        !          1361:         * mark the pmap no longer in use by this processor.
        !          1362:         */
        !          1363:        x86_atomic_clearbits_ul(&pmap->pm_cpus, (1U << cpu_number()));
        !          1364:
        !          1365: }
        !          1366:
        !          1367: /*
        !          1368:  * end of lifecycle functions
        !          1369:  */
        !          1370:
        !          1371: /*
        !          1372:  * some misc. functions
        !          1373:  */
        !          1374:
        !          1375: boolean_t
        !          1376: pmap_pdes_valid(vaddr_t va, pd_entry_t **pdes, pd_entry_t *lastpde)
        !          1377: {
        !          1378:        int i;
        !          1379:        unsigned long index;
        !          1380:        pd_entry_t pde;
        !          1381:
        !          1382:        for (i = PTP_LEVELS; i > 1; i--) {
        !          1383:                index = pl_i(va, i);
        !          1384:                pde = pdes[i - 2][index];
        !          1385:                if ((pde & PG_V) == 0)
        !          1386:                        return FALSE;
        !          1387:        }
        !          1388:        if (lastpde != NULL)
        !          1389:                *lastpde = pde;
        !          1390:        return TRUE;
        !          1391: }
        !          1392:
        !          1393: /*
        !          1394:  * pmap_extract: extract a PA for the given VA
        !          1395:  */
        !          1396:
        !          1397: boolean_t
        !          1398: pmap_extract(struct pmap *pmap, vaddr_t va, paddr_t *pap)
        !          1399: {
        !          1400:        pt_entry_t *ptes, pte;
        !          1401:        pd_entry_t pde, **pdes;
        !          1402:
        !          1403:        if (pmap == pmap_kernel() && va >= PMAP_DIRECT_BASE &&
        !          1404:            va < PMAP_DIRECT_END) {
        !          1405:                *pap = va - PMAP_DIRECT_BASE;
        !          1406:                return (TRUE);
        !          1407:        }
        !          1408:
        !          1409:        if (pmap == pmap_kernel() && va >= PMAP_DIRECT_BASE_NC &&
        !          1410:            va < PMAP_DIRECT_END_NC) {
        !          1411:                *pap = va - PMAP_DIRECT_BASE_NC;
        !          1412:                return (TRUE);
        !          1413:        }
        !          1414:
        !          1415:        pmap_map_ptes(pmap, &ptes, &pdes);
        !          1416:        if (pmap_pdes_valid(va, pdes, &pde) == FALSE) {
        !          1417:                return FALSE;
        !          1418:        }
        !          1419:
        !          1420:        if (pde & PG_PS) {
        !          1421:                if (pap != NULL)
        !          1422:                        *pap = (pde & PG_LGFRAME) | (va & 0x1fffff);
        !          1423:                pmap_unmap_ptes(pmap);
        !          1424:                return (TRUE);
        !          1425:        }
        !          1426:
        !          1427:        pte = ptes[pl1_i(va)];
        !          1428:        pmap_unmap_ptes(pmap);
        !          1429:
        !          1430:        if (__predict_true((pte & PG_V) != 0)) {
        !          1431:                if (pap != NULL)
        !          1432:                        *pap = (pte & PG_FRAME) | (va & 0xfff);
        !          1433:                return (TRUE);
        !          1434:        }
        !          1435:
        !          1436:        return FALSE;
        !          1437: }
        !          1438:
        !          1439: /*
        !          1440:  * pmap_map: map a range of PAs into kvm
        !          1441:  *
        !          1442:  * => used during crash dump
        !          1443:  * => XXX: pmap_map() should be phased out?
        !          1444:  */
        !          1445:
        !          1446: vaddr_t
        !          1447: pmap_map(vaddr_t va, paddr_t spa, paddr_t epa, vm_prot_t prot)
        !          1448: {
        !          1449:        while (spa < epa) {
        !          1450:                pmap_enter(pmap_kernel(), va, spa, prot, 0);
        !          1451:                va += PAGE_SIZE;
        !          1452:                spa += PAGE_SIZE;
        !          1453:        }
        !          1454:        pmap_update(pmap_kernel());
        !          1455:        return va;
        !          1456: }
        !          1457:
        !          1458:
        !          1459: /*
        !          1460:  * pmap_zero_page: zero a page
        !          1461:  */
        !          1462:
        !          1463: void
        !          1464: pmap_zero_page(struct vm_page *pg)
        !          1465: {
        !          1466:        pagezero(pmap_map_direct(pg));
        !          1467: }
        !          1468:
        !          1469: /*
        !          1470:  * pmap_pagezeroidle: the same, for the idle loop page zero'er.
        !          1471:  * Returns TRUE if the page was zero'd, FALSE if we aborted for
        !          1472:  * some reason.
        !          1473:  */
        !          1474:
        !          1475: boolean_t
        !          1476: pmap_pageidlezero(struct vm_page *pg)
        !          1477: {
        !          1478:        vaddr_t va = pmap_map_direct(pg);
        !          1479:        boolean_t rv = TRUE;
        !          1480:        long *ptr;
        !          1481:        int i;
        !          1482:
        !          1483:        /*
        !          1484:         * XXX - We'd really like to do this uncached. But at this moment
        !          1485:         *       we're never called, so just pretend that this works.
        !          1486:         *       It shouldn't be too hard to create a second direct map
        !          1487:         *       with uncached mappings.
        !          1488:         */
        !          1489:        for (i = 0, ptr = (long *) va; i < PAGE_SIZE / sizeof(long); i++) {
        !          1490:                if (!sched_is_idle()) {
        !          1491:
        !          1492:                        /*
        !          1493:                         * A process has become ready.  Abort now,
        !          1494:                         * so we don't keep it waiting while we
        !          1495:                         * do slow memory access to finish this
        !          1496:                         * page.
        !          1497:                         */
        !          1498:
        !          1499:                        rv = FALSE;
        !          1500:                        break;
        !          1501:                }
        !          1502:                *ptr++ = 0;
        !          1503:        }
        !          1504:
        !          1505:        return (rv);
        !          1506: }
        !          1507:
        !          1508: /*
        !          1509:  * pmap_copy_page: copy a page
        !          1510:  */
        !          1511:
        !          1512: void
        !          1513: pmap_copy_page(struct vm_page *srcpg, struct vm_page *dstpg)
        !          1514: {
        !          1515:        vaddr_t srcva = pmap_map_direct(srcpg);
        !          1516:        vaddr_t dstva = pmap_map_direct(dstpg);
        !          1517:
        !          1518:        memcpy((void *)dstva, (void *)srcva, PAGE_SIZE);
        !          1519: }
        !          1520:
        !          1521: /*
        !          1522:  * p m a p   r e m o v e   f u n c t i o n s
        !          1523:  *
        !          1524:  * functions that remove mappings
        !          1525:  */
        !          1526:
        !          1527: /*
        !          1528:  * pmap_remove_ptes: remove PTEs from a PTP
        !          1529:  *
        !          1530:  * => must have proper locking on pmap_master_lock
        !          1531:  * => caller must hold pmap's lock
        !          1532:  * => PTP must be mapped into KVA
        !          1533:  * => PTP should be null if pmap == pmap_kernel()
        !          1534:  */
        !          1535:
        !          1536: void
        !          1537: pmap_remove_ptes(struct pmap *pmap, struct vm_page *ptp, vaddr_t ptpva,
        !          1538:     vaddr_t startva, vaddr_t endva, int flags)
        !          1539: {
        !          1540:        struct pv_entry *pve;
        !          1541:        pt_entry_t *pte = (pt_entry_t *) ptpva;
        !          1542:        struct vm_page *pg;
        !          1543:        pt_entry_t opte;
        !          1544:
        !          1545:        /*
        !          1546:         * note that ptpva points to the PTE that maps startva.   this may
        !          1547:         * or may not be the first PTE in the PTP.
        !          1548:         *
        !          1549:         * we loop through the PTP while there are still PTEs to look at
        !          1550:         * and the wire_count is greater than 1 (because we use the wire_count
        !          1551:         * to keep track of the number of real PTEs in the PTP).
        !          1552:         */
        !          1553:
        !          1554:        for (/*null*/; startva < endva && (ptp == NULL || ptp->wire_count > 1)
        !          1555:                             ; pte++, startva += PAGE_SIZE) {
        !          1556:                if (!pmap_valid_entry(*pte))
        !          1557:                        continue;                       /* VA not mapped */
        !          1558:                if ((flags & PMAP_REMOVE_SKIPWIRED) && (*pte & PG_W)) {
        !          1559:                        continue;
        !          1560:                }
        !          1561:
        !          1562:                /* atomically save the old PTE and zap! it */
        !          1563:                opte = pmap_pte_set(pte, 0);
        !          1564:
        !          1565:                if (opte & PG_W)
        !          1566:                        pmap->pm_stats.wired_count--;
        !          1567:                pmap->pm_stats.resident_count--;
        !          1568:
        !          1569:                if (ptp)
        !          1570:                        ptp->wire_count--;              /* dropping a PTE */
        !          1571:
        !          1572:                pg = PHYS_TO_VM_PAGE(opte & PG_FRAME);
        !          1573:
        !          1574:                /*
        !          1575:                 * if we are not on a pv list we are done.
        !          1576:                 */
        !          1577:
        !          1578:                if ((opte & PG_PVLIST) == 0) {
        !          1579: #ifdef DIAGNOSTIC
        !          1580:                        if (pg != NULL)
        !          1581:                                panic("pmap_remove_ptes: managed page without "
        !          1582:                                      "PG_PVLIST for 0x%lx", startva);
        !          1583: #endif
        !          1584:                        continue;
        !          1585:                }
        !          1586:
        !          1587: #ifdef DIAGNOSTIC
        !          1588:                if (pg == NULL)
        !          1589:                        panic("pmap_remove_ptes: unmanaged page marked "
        !          1590:                              "PG_PVLIST, va = 0x%lx, pa = 0x%lx",
        !          1591:                              startva, (u_long)(opte & PG_FRAME));
        !          1592: #endif
        !          1593:
        !          1594:                /* sync R/M bits */
        !          1595:                pmap_sync_flags_pte(pg, opte);
        !          1596:                pve = pmap_remove_pv(pg, pmap, startva);
        !          1597:
        !          1598:                if (pve) {
        !          1599:                        pool_put(&pmap_pv_pool, pve);
        !          1600:                }
        !          1601:
        !          1602:                /* end of "for" loop: time for next pte */
        !          1603:        }
        !          1604: }
        !          1605:
        !          1606:
        !          1607: /*
        !          1608:  * pmap_remove_pte: remove a single PTE from a PTP
        !          1609:  *
        !          1610:  * => must have proper locking on pmap_master_lock
        !          1611:  * => caller must hold pmap's lock
        !          1612:  * => PTP must be mapped into KVA
        !          1613:  * => PTP should be null if pmap == pmap_kernel()
        !          1614:  * => returns true if we removed a mapping
        !          1615:  */
        !          1616:
        !          1617: boolean_t
        !          1618: pmap_remove_pte(struct pmap *pmap, struct vm_page *ptp, pt_entry_t *pte,
        !          1619:     vaddr_t va, int flags)
        !          1620: {
        !          1621:        struct pv_entry *pve;
        !          1622:        struct vm_page *pg;
        !          1623:        pt_entry_t opte;
        !          1624:
        !          1625:        if (!pmap_valid_entry(*pte))
        !          1626:                return(FALSE);          /* VA not mapped */
        !          1627:        if ((flags & PMAP_REMOVE_SKIPWIRED) && (*pte & PG_W)) {
        !          1628:                return(FALSE);
        !          1629:        }
        !          1630:
        !          1631:        /* atomically save the old PTE and zap! it */
        !          1632:        opte = pmap_pte_set(pte, 0);
        !          1633:
        !          1634:        if (opte & PG_W)
        !          1635:                pmap->pm_stats.wired_count--;
        !          1636:        pmap->pm_stats.resident_count--;
        !          1637:
        !          1638:        if (ptp)
        !          1639:                ptp->wire_count--;              /* dropping a PTE */
        !          1640:
        !          1641:        pg = PHYS_TO_VM_PAGE(opte & PG_FRAME);
        !          1642:
        !          1643:        /*
        !          1644:         * if we are not on a pv list we are done.
        !          1645:         */
        !          1646:        if ((opte & PG_PVLIST) == 0) {
        !          1647: #ifdef DIAGNOSTIC
        !          1648:                if (pg != NULL)
        !          1649:                        panic("pmap_remove_pte: managed page without "
        !          1650:                              "PG_PVLIST for 0x%lx", va);
        !          1651: #endif
        !          1652:                return(TRUE);
        !          1653:        }
        !          1654:
        !          1655: #ifdef DIAGNOSTIC
        !          1656:        if (pg == NULL)
        !          1657:                panic("pmap_remove_pte: unmanaged page marked "
        !          1658:                    "PG_PVLIST, va = 0x%lx, pa = 0x%lx", va,
        !          1659:                    (u_long)(opte & PG_FRAME));
        !          1660: #endif
        !          1661:
        !          1662:        /* sync R/M bits */
        !          1663:        pmap_sync_flags_pte(pg, opte);
        !          1664:        pve = pmap_remove_pv(pg, pmap, va);
        !          1665:        if (pve)
        !          1666:                pool_put(&pmap_pv_pool, pve);
        !          1667:        return(TRUE);
        !          1668: }
        !          1669:
        !          1670: /*
        !          1671:  * pmap_remove: top level mapping removal function
        !          1672:  *
        !          1673:  * => caller should not be holding any pmap locks
        !          1674:  */
        !          1675:
        !          1676: void
        !          1677: pmap_remove(struct pmap *pmap, vaddr_t sva, vaddr_t eva)
        !          1678: {
        !          1679:        pmap_do_remove(pmap, sva, eva, PMAP_REMOVE_ALL);
        !          1680: }
        !          1681:
        !          1682: /*
        !          1683:  * pmap_do_remove: mapping removal guts
        !          1684:  *
        !          1685:  * => caller should not be holding any pmap locks
        !          1686:  */
        !          1687:
        !          1688: void
        !          1689: pmap_do_remove(struct pmap *pmap, vaddr_t sva, vaddr_t eva, int flags)
        !          1690: {
        !          1691:        pt_entry_t *ptes;
        !          1692:        pd_entry_t **pdes, pde;
        !          1693:        boolean_t result;
        !          1694:        paddr_t ptppa;
        !          1695:        vaddr_t blkendva;
        !          1696:        struct vm_page *ptp;
        !          1697:        vaddr_t va;
        !          1698:        int shootall = 0;
        !          1699:        struct pg_to_free empty_ptps;
        !          1700:
        !          1701:        TAILQ_INIT(&empty_ptps);
        !          1702:
        !          1703:        PMAP_MAP_TO_HEAD_LOCK();
        !          1704:        pmap_map_ptes(pmap, &ptes, &pdes);      /* locks pmap */
        !          1705:
        !          1706:        /*
        !          1707:         * removing one page?  take shortcut function.
        !          1708:         */
        !          1709:
        !          1710:        if (sva + PAGE_SIZE == eva) {
        !          1711:                if (pmap_pdes_valid(sva, pdes, &pde)) {
        !          1712:
        !          1713:                        /* PA of the PTP */
        !          1714:                        ptppa = pde & PG_FRAME;
        !          1715:
        !          1716:                        /* get PTP if non-kernel mapping */
        !          1717:
        !          1718:                        if (pmap == pmap_kernel()) {
        !          1719:                                /* we never free kernel PTPs */
        !          1720:                                ptp = NULL;
        !          1721:                        } else {
        !          1722:                                ptp = pmap_find_ptp(pmap, sva, ptppa, 1);
        !          1723: #ifdef DIAGNOSTIC
        !          1724:                                if (ptp == NULL)
        !          1725:                                        panic("pmap_remove: unmanaged "
        !          1726:                                              "PTP detected");
        !          1727: #endif
        !          1728:                        }
        !          1729:
        !          1730:                        /* do it! */
        !          1731:                        result = pmap_remove_pte(pmap, ptp,
        !          1732:                            &ptes[pl1_i(sva)], sva, flags);
        !          1733:
        !          1734:                        /*
        !          1735:                         * if mapping removed and the PTP is no longer
        !          1736:                         * being used, free it!
        !          1737:                         */
        !          1738:
        !          1739:                        if (result && ptp && ptp->wire_count <= 1)
        !          1740:                                pmap_free_ptp(pmap, ptp, sva, ptes, pdes,
        !          1741:                                    &empty_ptps);
        !          1742:                        pmap_tlb_shootpage(pmap, sva);
        !          1743:                }
        !          1744:
        !          1745:                pmap_tlb_shootwait();
        !          1746:                pmap_unmap_ptes(pmap);          /* unlock pmap */
        !          1747:                PMAP_MAP_TO_HEAD_UNLOCK();
        !          1748:
        !          1749:                while ((ptp = TAILQ_FIRST(&empty_ptps)) != NULL) {
        !          1750:                        TAILQ_REMOVE(&empty_ptps, ptp, listq);
        !          1751:                        uvm_pagefree(ptp);
        !          1752:                 }
        !          1753:
        !          1754:                return;
        !          1755:        }
        !          1756:
        !          1757:        if ((eva - sva > 32 * PAGE_SIZE) && pmap != pmap_kernel())
        !          1758:                shootall = 1;
        !          1759:
        !          1760:        for (va = sva; va < eva; va = blkendva) {
        !          1761:                /* determine range of block */
        !          1762:                blkendva = x86_round_pdr(va + 1);
        !          1763:                if (blkendva > eva)
        !          1764:                        blkendva = eva;
        !          1765:
        !          1766:                /*
        !          1767:                 * XXXCDC: our PTE mappings should never be removed
        !          1768:                 * with pmap_remove!  if we allow this (and why would
        !          1769:                 * we?) then we end up freeing the pmap's page
        !          1770:                 * directory page (PDP) before we are finished using
        !          1771:                 * it when we hit in in the recursive mapping.  this
        !          1772:                 * is BAD.
        !          1773:                 *
        !          1774:                 * long term solution is to move the PTEs out of user
        !          1775:                 * address space.  and into kernel address space (up
        !          1776:                 * with APTE).  then we can set VM_MAXUSER_ADDRESS to
        !          1777:                 * be VM_MAX_ADDRESS.
        !          1778:                 */
        !          1779:
        !          1780:                if (pl_i(va, PTP_LEVELS) == PDIR_SLOT_PTE)
        !          1781:                        /* XXXCDC: ugly hack to avoid freeing PDP here */
        !          1782:                        continue;
        !          1783:
        !          1784:                if (!pmap_pdes_valid(va, pdes, &pde))
        !          1785:                        continue;
        !          1786:
        !          1787:                /* PA of the PTP */
        !          1788:                ptppa = pde & PG_FRAME;
        !          1789:
        !          1790:                /* get PTP if non-kernel mapping */
        !          1791:                if (pmap == pmap_kernel()) {
        !          1792:                        /* we never free kernel PTPs */
        !          1793:                        ptp = NULL;
        !          1794:                } else {
        !          1795:                        ptp = pmap_find_ptp(pmap, va, ptppa, 1);
        !          1796: #ifdef DIAGNOSTIC
        !          1797:                        if (ptp == NULL)
        !          1798:                                panic("pmap_remove: unmanaged PTP "
        !          1799:                                      "detected");
        !          1800: #endif
        !          1801:                }
        !          1802:                pmap_remove_ptes(pmap, ptp,
        !          1803:                    (vaddr_t)&ptes[pl1_i(va)], va, blkendva, flags);
        !          1804:
        !          1805:                /* if PTP is no longer being used, free it! */
        !          1806:                if (ptp && ptp->wire_count <= 1) {
        !          1807:                        pmap_free_ptp(pmap, ptp, va, ptes, pdes, &empty_ptps);
        !          1808:                }
        !          1809:        }
        !          1810:
        !          1811:        if (shootall)
        !          1812:                pmap_tlb_shoottlb();
        !          1813:        else
        !          1814:                pmap_tlb_shootrange(pmap, sva, eva);
        !          1815:
        !          1816:        pmap_tlb_shootwait();
        !          1817:
        !          1818:        pmap_unmap_ptes(pmap);
        !          1819:        PMAP_MAP_TO_HEAD_UNLOCK();
        !          1820:
        !          1821:        while ((ptp = TAILQ_FIRST(&empty_ptps)) != NULL) {
        !          1822:                TAILQ_REMOVE(&empty_ptps, ptp, listq);
        !          1823:                uvm_pagefree(ptp);
        !          1824:        }
        !          1825: }
        !          1826:
        !          1827: /*
        !          1828:  * pmap_page_remove: remove a managed vm_page from all pmaps that map it
        !          1829:  *
        !          1830:  * => R/M bits are sync'd back to attrs
        !          1831:  */
        !          1832:
        !          1833: void
        !          1834: pmap_page_remove(struct vm_page *pg)
        !          1835: {
        !          1836:        struct pv_entry *pve;
        !          1837:        pt_entry_t *ptes, opte;
        !          1838:        pd_entry_t **pdes;
        !          1839: #ifdef DIAGNOSTIC
        !          1840:        pd_entry_t pde;
        !          1841: #endif
        !          1842:        struct pg_to_free empty_ptps;
        !          1843:        struct vm_page *ptp;
        !          1844:
        !          1845:        TAILQ_INIT(&empty_ptps);
        !          1846:
        !          1847:        PMAP_HEAD_TO_MAP_LOCK();
        !          1848:
        !          1849:        while ((pve = pg->mdpage.pv_list) != NULL) {
        !          1850:                pg->mdpage.pv_list = pve->pv_next;
        !          1851:
        !          1852:                pmap_map_ptes(pve->pv_pmap, &ptes, &pdes);      /* locks pmap */
        !          1853:
        !          1854: #ifdef DIAGNOSTIC
        !          1855:                if (pve->pv_ptp && pmap_pdes_valid(pve->pv_va, pdes, &pde) &&
        !          1856:                   (pde & PG_FRAME) != VM_PAGE_TO_PHYS(pve->pv_ptp)) {
        !          1857:                        printf("pmap_page_remove: pg=%p: va=%lx, pv_ptp=%p\n",
        !          1858:                               pg, pve->pv_va, pve->pv_ptp);
        !          1859:                        printf("pmap_page_remove: PTP's phys addr: "
        !          1860:                               "actual=%lx, recorded=%lx\n",
        !          1861:                               (unsigned long)(pde & PG_FRAME),
        !          1862:                                VM_PAGE_TO_PHYS(pve->pv_ptp));
        !          1863:                        panic("pmap_page_remove: mapped managed page has "
        !          1864:                              "invalid pv_ptp field");
        !          1865:                }
        !          1866: #endif
        !          1867:
        !          1868:                /* atomically save the old PTE and zap it */
        !          1869:                opte = pmap_pte_set(&ptes[pl1_i(pve->pv_va)], 0);
        !          1870:
        !          1871:                if (opte & PG_W)
        !          1872:                        pve->pv_pmap->pm_stats.wired_count--;
        !          1873:                pve->pv_pmap->pm_stats.resident_count--;
        !          1874:
        !          1875:                pmap_tlb_shootpage(pve->pv_pmap, pve->pv_va);
        !          1876:
        !          1877:                pmap_sync_flags_pte(pg, opte);
        !          1878:
        !          1879:                /* update the PTP reference count.  free if last reference. */
        !          1880:                if (pve->pv_ptp) {
        !          1881:                        pve->pv_ptp->wire_count--;
        !          1882:                        if (pve->pv_ptp->wire_count <= 1) {
        !          1883:                                pmap_free_ptp(pve->pv_pmap, pve->pv_ptp,
        !          1884:                                    pve->pv_va, ptes, pdes, &empty_ptps);
        !          1885:                        }
        !          1886:                }
        !          1887:                pmap_unmap_ptes(pve->pv_pmap);          /* unlocks pmap */
        !          1888:                pool_put(&pmap_pv_pool, pve);
        !          1889:        }
        !          1890:
        !          1891:        PMAP_HEAD_TO_MAP_UNLOCK();
        !          1892:        pmap_tlb_shootwait();
        !          1893:
        !          1894:        while ((ptp = TAILQ_FIRST(&empty_ptps)) != NULL) {
        !          1895:                TAILQ_REMOVE(&empty_ptps, ptp, listq);
        !          1896:                uvm_pagefree(ptp);
        !          1897:        }
        !          1898: }
        !          1899:
        !          1900: /*
        !          1901:  * p m a p   a t t r i b u t e  f u n c t i o n s
        !          1902:  * functions that test/change managed page's attributes
        !          1903:  * since a page can be mapped multiple times we must check each PTE that
        !          1904:  * maps it by going down the pv lists.
        !          1905:  */
        !          1906:
        !          1907: /*
        !          1908:  * pmap_test_attrs: test a page's attributes
        !          1909:  */
        !          1910:
        !          1911: boolean_t
        !          1912: pmap_test_attrs(struct vm_page *pg, unsigned int testbits)
        !          1913: {
        !          1914:        struct pv_entry *pve;
        !          1915:        pt_entry_t *ptes, pte;
        !          1916:        pd_entry_t **pdes;
        !          1917:        u_long mybits, testflags;
        !          1918:
        !          1919:        testflags = pmap_pte2flags(testbits);
        !          1920:
        !          1921:        if (pg->pg_flags & testflags)
        !          1922:                return (TRUE);
        !          1923:
        !          1924:        PMAP_HEAD_TO_MAP_LOCK();
        !          1925:        mybits = 0;
        !          1926:        for (pve = pg->mdpage.pv_list; pve != NULL && mybits == 0;
        !          1927:            pve = pve->pv_next) {
        !          1928:                pmap_map_ptes(pve->pv_pmap, &ptes, &pdes);
        !          1929:                pte = ptes[pl1_i(pve->pv_va)];
        !          1930:                pmap_unmap_ptes(pve->pv_pmap);
        !          1931:                mybits |= (pte & testbits);
        !          1932:        }
        !          1933:        PMAP_HEAD_TO_MAP_UNLOCK();
        !          1934:
        !          1935:        if (mybits == 0)
        !          1936:                return (FALSE);
        !          1937:
        !          1938:        atomic_setbits_int(&pg->pg_flags, pmap_pte2flags(mybits));
        !          1939:
        !          1940:        return (TRUE);
        !          1941: }
        !          1942:
        !          1943: /*
        !          1944:  * pmap_clear_attrs: change a page's attributes
        !          1945:  *
        !          1946:  * => we return TRUE if we cleared one of the bits we were asked to
        !          1947:  */
        !          1948:
        !          1949: boolean_t
        !          1950: pmap_clear_attrs(struct vm_page *pg, unsigned long clearbits)
        !          1951: {
        !          1952:        struct pv_entry *pve;
        !          1953:        pt_entry_t *ptes, opte;
        !          1954:        pd_entry_t **pdes;
        !          1955:        u_long clearflags;
        !          1956:        int result;
        !          1957:
        !          1958:        clearflags = pmap_pte2flags(clearbits);
        !          1959:
        !          1960:        PMAP_HEAD_TO_MAP_LOCK();
        !          1961:
        !          1962:        result = pg->pg_flags & clearflags;
        !          1963:        if (result)
        !          1964:                atomic_clearbits_int(&pg->pg_flags, clearflags);
        !          1965:
        !          1966:        for (pve = pg->mdpage.pv_list; pve != NULL; pve = pve->pv_next) {
        !          1967:                pmap_map_ptes(pve->pv_pmap, &ptes, &pdes);      /* locks pmap */
        !          1968: #ifdef DIAGNOSTIC
        !          1969:                if (!pmap_pdes_valid(pve->pv_va, pdes, NULL))
        !          1970:                        panic("pmap_change_attrs: mapping without PTP "
        !          1971:                              "detected");
        !          1972: #endif
        !          1973:
        !          1974:                opte = ptes[pl1_i(pve->pv_va)];
        !          1975:                if (opte & clearbits) {
        !          1976:                        result = 1;
        !          1977:                        pmap_pte_clearbits(&ptes[pl1_i(pve->pv_va)],
        !          1978:                            (opte & clearbits));
        !          1979:                        pmap_tlb_shootpage(pve->pv_pmap, pve->pv_va);
        !          1980:                }
        !          1981:                pmap_unmap_ptes(pve->pv_pmap);          /* unlocks pmap */
        !          1982:        }
        !          1983:
        !          1984:        PMAP_HEAD_TO_MAP_UNLOCK();
        !          1985:
        !          1986:        pmap_tlb_shootwait();
        !          1987:
        !          1988:        return (result != 0);
        !          1989: }
        !          1990:
        !          1991: /*
        !          1992:  * p m a p   p r o t e c t i o n   f u n c t i o n s
        !          1993:  */
        !          1994:
        !          1995: /*
        !          1996:  * pmap_page_protect: change the protection of all recorded mappings
        !          1997:  *     of a managed page
        !          1998:  *
        !          1999:  * => NOTE: this is an inline function in pmap.h
        !          2000:  */
        !          2001:
        !          2002: /* see pmap.h */
        !          2003:
        !          2004: /*
        !          2005:  * pmap_protect: set the protection in of the pages in a pmap
        !          2006:  *
        !          2007:  * => NOTE: this is an inline function in pmap.h
        !          2008:  */
        !          2009:
        !          2010: /* see pmap.h */
        !          2011:
        !          2012: /*
        !          2013:  * pmap_write_protect: write-protect pages in a pmap
        !          2014:  */
        !          2015:
        !          2016: void
        !          2017: pmap_write_protect(struct pmap *pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot)
        !          2018: {
        !          2019:        pt_entry_t nx, opte, *ptes, *spte, *epte;
        !          2020:        pd_entry_t **pdes;
        !          2021:        vaddr_t blockend;
        !          2022:        int shootall = 0;
        !          2023:        vaddr_t va;
        !          2024:
        !          2025:        pmap_map_ptes(pmap, &ptes, &pdes);              /* locks pmap */
        !          2026:
        !          2027:        /* should be ok, but just in case ... */
        !          2028:        sva &= PG_FRAME;
        !          2029:        eva &= PG_FRAME;
        !          2030:
        !          2031:        nx = 0;
        !          2032:        if ((cpu_feature & CPUID_NXE) && !(prot & VM_PROT_EXECUTE))
        !          2033:                nx = PG_NX;
        !          2034:
        !          2035:        if ((eva - sva > 32 * PAGE_SIZE) && pmap != pmap_kernel())
        !          2036:                shootall = 1;
        !          2037:
        !          2038:        for (va = sva; va < eva ; va = blockend) {
        !          2039:                blockend = (va & L2_FRAME) + NBPD_L2;
        !          2040:                if (blockend > eva)
        !          2041:                        blockend = eva;
        !          2042:
        !          2043:                /*
        !          2044:                 * XXXCDC: our PTE mappings should never be write-protected!
        !          2045:                 *
        !          2046:                 * long term solution is to move the PTEs out of user
        !          2047:                 * address space.  and into kernel address space (up
        !          2048:                 * with APTE).  then we can set VM_MAXUSER_ADDRESS to
        !          2049:                 * be VM_MAX_ADDRESS.
        !          2050:                 */
        !          2051:
        !          2052:                /* XXXCDC: ugly hack to avoid freeing PDP here */
        !          2053:                if (pl_i(va, PTP_LEVELS) == PDIR_SLOT_PTE)
        !          2054:                        continue;
        !          2055:
        !          2056:                /* empty block? */
        !          2057:                if (!pmap_pdes_valid(va, pdes, NULL))
        !          2058:                        continue;
        !          2059:
        !          2060: #ifdef DIAGNOSTIC
        !          2061:                if (va >= VM_MAXUSER_ADDRESS && va < VM_MAX_ADDRESS)
        !          2062:                        panic("pmap_write_protect: PTE space");
        !          2063: #endif
        !          2064:
        !          2065:                spte = &ptes[pl1_i(va)];
        !          2066:                epte = &ptes[pl1_i(blockend)];
        !          2067:
        !          2068:                for (/*null */; spte < epte ; spte++) {
        !          2069:                        if (!(*spte & PG_V))
        !          2070:                                continue;
        !          2071:                        opte = *spte;
        !          2072:                        pmap_pte_clearbits(spte, PG_RW);
        !          2073:                        pmap_pte_setbits(spte, nx);
        !          2074:                }
        !          2075:        }
        !          2076:
        !          2077:        if (shootall)
        !          2078:                pmap_tlb_shoottlb();
        !          2079:        else
        !          2080:                pmap_tlb_shootrange(pmap, sva, eva);
        !          2081:
        !          2082:        pmap_tlb_shootwait();
        !          2083:
        !          2084:        pmap_unmap_ptes(pmap);          /* unlocks pmap */
        !          2085: }
        !          2086:
        !          2087: /*
        !          2088:  * end of protection functions
        !          2089:  */
        !          2090:
        !          2091: /*
        !          2092:  * pmap_unwire: clear the wired bit in the PTE
        !          2093:  *
        !          2094:  * => mapping should already be in map
        !          2095:  */
        !          2096:
        !          2097: void
        !          2098: pmap_unwire(struct pmap *pmap, vaddr_t va)
        !          2099: {
        !          2100:        pt_entry_t *ptes;
        !          2101:        pd_entry_t **pdes;
        !          2102:
        !          2103:        pmap_map_ptes(pmap, &ptes, &pdes);              /* locks pmap */
        !          2104:
        !          2105:        if (pmap_pdes_valid(va, pdes, NULL)) {
        !          2106:
        !          2107: #ifdef DIAGNOSTIC
        !          2108:                if (!pmap_valid_entry(ptes[pl1_i(va)]))
        !          2109:                        panic("pmap_unwire: invalid (unmapped) va 0x%lx", va);
        !          2110: #endif
        !          2111:                if ((ptes[pl1_i(va)] & PG_W) != 0) {
        !          2112:                        ptes[pl1_i(va)] &= ~PG_W;
        !          2113:                        pmap->pm_stats.wired_count--;
        !          2114:                }
        !          2115: #ifdef DIAGNOSTIC
        !          2116:                else {
        !          2117:                        printf("pmap_unwire: wiring for pmap %p va 0x%lx "
        !          2118:                               "didn't change!\n", pmap, va);
        !          2119:                }
        !          2120: #endif
        !          2121:                pmap_unmap_ptes(pmap);          /* unlocks map */
        !          2122:        }
        !          2123: #ifdef DIAGNOSTIC
        !          2124:        else {
        !          2125:                panic("pmap_unwire: invalid PDE");
        !          2126:        }
        !          2127: #endif
        !          2128: }
        !          2129:
        !          2130: /*
        !          2131:  * pmap_collect: free resources held by a pmap
        !          2132:  *
        !          2133:  * => optional function.
        !          2134:  * => called when a process is swapped out to free memory.
        !          2135:  */
        !          2136:
        !          2137: void
        !          2138: pmap_collect(struct pmap *pmap)
        !          2139: {
        !          2140:        /*
        !          2141:         * free all of the pt pages by removing the physical mappings
        !          2142:         * for its entire address space.
        !          2143:         */
        !          2144:
        !          2145: /*     pmap_do_remove(pmap, VM_MIN_ADDRESS, VM_MAX_ADDRESS,
        !          2146:            PMAP_REMOVE_SKIPWIRED);
        !          2147: */
        !          2148: }
        !          2149:
        !          2150: /*
        !          2151:  * pmap_copy: copy mappings from one pmap to another
        !          2152:  *
        !          2153:  * => optional function
        !          2154:  * void pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr)
        !          2155:  */
        !          2156:
        !          2157: /*
        !          2158:  * defined as macro in pmap.h
        !          2159:  */
        !          2160:
        !          2161: /*
        !          2162:  * pmap_enter: enter a mapping into a pmap
        !          2163:  *
        !          2164:  * => must be done "now" ... no lazy-evaluation
        !          2165:  */
        !          2166:
        !          2167: int
        !          2168: pmap_enter(struct pmap *pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
        !          2169: {
        !          2170:        pt_entry_t *ptes, opte, npte;
        !          2171:        pd_entry_t **pdes;
        !          2172:        struct vm_page *ptp, *pg = NULL;
        !          2173:        struct pv_entry *pve = NULL;
        !          2174:        int ptpdelta, wireddelta, resdelta;
        !          2175:        boolean_t wired = (flags & PMAP_WIRED) != 0;
        !          2176:        int error;
        !          2177:
        !          2178: #ifdef DIAGNOSTIC
        !          2179:        /* sanity check: totally out of range? */
        !          2180:        if (va >= VM_MAX_KERNEL_ADDRESS)
        !          2181:                panic("pmap_enter: too big");
        !          2182:
        !          2183:        if (va == (vaddr_t) PDP_BASE || va == (vaddr_t) APDP_BASE)
        !          2184:                panic("pmap_enter: trying to map over PDP/APDP!");
        !          2185:
        !          2186:        /* sanity check: kernel PTPs should already have been pre-allocated */
        !          2187:        if (va >= VM_MIN_KERNEL_ADDRESS &&
        !          2188:            !pmap_valid_entry(pmap->pm_pdir[pl_i(va, PTP_LEVELS)]))
        !          2189:                panic("pmap_enter: missing kernel PTP for va %lx!", va);
        !          2190:
        !          2191: #endif
        !          2192:
        !          2193:        /* get lock */
        !          2194:        PMAP_MAP_TO_HEAD_LOCK();
        !          2195:
        !          2196:        /*
        !          2197:         * map in ptes and get a pointer to our PTP (unless we are the kernel)
        !          2198:         */
        !          2199:
        !          2200:        pmap_map_ptes(pmap, &ptes, &pdes);              /* locks pmap */
        !          2201:        if (pmap == pmap_kernel()) {
        !          2202:                ptp = NULL;
        !          2203:        } else {
        !          2204:                ptp = pmap_get_ptp(pmap, va, pdes);
        !          2205:                if (ptp == NULL) {
        !          2206:                        if (flags & PMAP_CANFAIL) {
        !          2207:                                error = ENOMEM;
        !          2208:                                goto out;
        !          2209:                        }
        !          2210:                        panic("pmap_enter: get ptp failed");
        !          2211:                }
        !          2212:        }
        !          2213:        opte = ptes[pl1_i(va)];         /* old PTE */
        !          2214:
        !          2215:        /*
        !          2216:         * is there currently a valid mapping at our VA?
        !          2217:         */
        !          2218:
        !          2219:        if (pmap_valid_entry(opte)) {
        !          2220:                /*
        !          2221:                 * first, calculate pm_stats updates.  resident count will not
        !          2222:                 * change since we are replacing/changing a valid mapping.
        !          2223:                 * wired count might change...
        !          2224:                 */
        !          2225:
        !          2226:                resdelta = 0;
        !          2227:                if (wired && (opte & PG_W) == 0)
        !          2228:                        wireddelta = 1;
        !          2229:                else if (!wired && (opte & PG_W) != 0)
        !          2230:                        wireddelta = -1;
        !          2231:                else
        !          2232:                        wireddelta = 0;
        !          2233:                ptpdelta = 0;
        !          2234:
        !          2235:                /*
        !          2236:                 * is the currently mapped PA the same as the one we
        !          2237:                 * want to map?
        !          2238:                 */
        !          2239:
        !          2240:                if ((opte & PG_FRAME) == pa) {
        !          2241:
        !          2242:                        /* if this is on the PVLIST, sync R/M bit */
        !          2243:                        if (opte & PG_PVLIST) {
        !          2244:                                pg = PHYS_TO_VM_PAGE(pa);
        !          2245: #ifdef DIAGNOSTIC
        !          2246:                                if (pg == NULL)
        !          2247:                                        panic("pmap_enter: same pa PG_PVLIST "
        !          2248:                                              "mapping with unmanaged page "
        !          2249:                                              "pa = 0x%lx (0x%lx)", pa,
        !          2250:                                              atop(pa));
        !          2251: #endif
        !          2252:                                pmap_sync_flags_pte(pg, opte);
        !          2253:                        } else {
        !          2254: #ifdef DIAGNOSTIC
        !          2255:                                if (PHYS_TO_VM_PAGE(pa) != NULL)
        !          2256:                                        panic("pmap_enter: same pa, managed "
        !          2257:                                            "page, no PG_VLIST pa: 0x%lx\n",
        !          2258:                                            pa);
        !          2259: #endif
        !          2260:                        }
        !          2261:                        goto enter_now;
        !          2262:                }
        !          2263:
        !          2264:                /*
        !          2265:                 * changing PAs: we must remove the old one first
        !          2266:                 */
        !          2267:
        !          2268:                /*
        !          2269:                 * if current mapping is on a pvlist,
        !          2270:                 * remove it (sync R/M bits)
        !          2271:                 */
        !          2272:
        !          2273:                if (opte & PG_PVLIST) {
        !          2274:                        pg = PHYS_TO_VM_PAGE(opte & PG_FRAME);
        !          2275: #ifdef DIAGNOSTIC
        !          2276:                        if (pg == NULL)
        !          2277:                                panic("pmap_enter: PG_PVLIST mapping with "
        !          2278:                                      "unmanaged page "
        !          2279:                                      "pa = 0x%lx (0x%lx)", pa, atop(pa));
        !          2280: #endif
        !          2281:                        pmap_sync_flags_pte(pg, opte);
        !          2282:                        pve = pmap_remove_pv(pg, pmap, va);
        !          2283:                        pg = NULL; /* This is not the page we are looking for */
        !          2284:                }
        !          2285:        } else {        /* opte not valid */
        !          2286:                pve = NULL;
        !          2287:                resdelta = 1;
        !          2288:                if (wired)
        !          2289:                        wireddelta = 1;
        !          2290:                else
        !          2291:                        wireddelta = 0;
        !          2292:                if (ptp)
        !          2293:                        ptpdelta = 1;
        !          2294:                else
        !          2295:                        ptpdelta = 0;
        !          2296:        }
        !          2297:
        !          2298:        /*
        !          2299:         * pve is either NULL or points to a now-free pv_entry structure
        !          2300:         * (the latter case is if we called pmap_remove_pv above).
        !          2301:         *
        !          2302:         * if this entry is to be on a pvlist, enter it now.
        !          2303:         */
        !          2304:
        !          2305:        if (pmap_initialized)
        !          2306:                pg = PHYS_TO_VM_PAGE(pa);
        !          2307:
        !          2308:        if (pg != NULL) {
        !          2309:                if (pve == NULL) {
        !          2310:                        pve = pool_get(&pmap_pv_pool, PR_NOWAIT);
        !          2311:                        if (pve == NULL) {
        !          2312:                                if (flags & PMAP_CANFAIL) {
        !          2313:                                        error = ENOMEM;
        !          2314:                                        goto out;
        !          2315:                                }
        !          2316:                                panic("pmap_enter: no pv entries available");
        !          2317:                        }
        !          2318:                }
        !          2319:                pmap_enter_pv(pg, pve, pmap, va, ptp);
        !          2320:        } else {
        !          2321:                /* new mapping is not PG_PVLIST.   free pve if we've got one */
        !          2322:                if (pve)
        !          2323:                        pool_put(&pmap_pv_pool, pve);
        !          2324:        }
        !          2325:
        !          2326: enter_now:
        !          2327:        /*
        !          2328:         * at this point pg is !NULL if we want the PG_PVLIST bit set
        !          2329:         */
        !          2330:
        !          2331:        pmap->pm_stats.resident_count += resdelta;
        !          2332:        pmap->pm_stats.wired_count += wireddelta;
        !          2333:        if (ptp)
        !          2334:                ptp->wire_count += ptpdelta;
        !          2335:
        !          2336:        if (pg != PHYS_TO_VM_PAGE(pa))
        !          2337:                panic("wtf?");
        !          2338:
        !          2339:        npte = pa | protection_codes[prot] | PG_V;
        !          2340:        if (pg != NULL)
        !          2341:                npte |= PG_PVLIST;
        !          2342:        if (wired)
        !          2343:                npte |= PG_W;
        !          2344:        if (va < VM_MAXUSER_ADDRESS)
        !          2345:                npte |= PG_u;
        !          2346:        else if (va < VM_MAX_ADDRESS)
        !          2347:                npte |= (PG_u | PG_RW); /* XXXCDC: no longer needed? */
        !          2348:        if (pmap == pmap_kernel())
        !          2349:                npte |= pmap_pg_g;
        !          2350:
        !          2351:        ptes[pl1_i(va)] = npte;         /* zap! */
        !          2352:
        !          2353:        /*
        !          2354:         * If we changed anything other than modified/used bits,
        !          2355:         * flush the TLB.  (is this overkill?)
        !          2356:         */
        !          2357:        if (opte & PG_V) {
        !          2358:                pmap_tlb_shootpage(pmap, va);
        !          2359:                pmap_tlb_shootwait();
        !          2360:        }
        !          2361:
        !          2362:        error = 0;
        !          2363:
        !          2364: out:
        !          2365:        pmap_unmap_ptes(pmap);
        !          2366:        PMAP_MAP_TO_HEAD_UNLOCK();
        !          2367:
        !          2368:        return error;
        !          2369: }
        !          2370:
        !          2371: boolean_t
        !          2372: pmap_get_physpage(vaddr_t va, int level, paddr_t *paddrp)
        !          2373: {
        !          2374:        struct vm_page *ptp;
        !          2375:        struct pmap *kpm = pmap_kernel();
        !          2376:
        !          2377:        if (uvm.page_init_done == FALSE) {
        !          2378:                vaddr_t va;
        !          2379:
        !          2380:                /*
        !          2381:                 * we're growing the kernel pmap early (from
        !          2382:                 * uvm_pageboot_alloc()).  this case must be
        !          2383:                 * handled a little differently.
        !          2384:                 */
        !          2385:
        !          2386:                va = pmap_steal_memory(PAGE_SIZE, NULL, NULL);
        !          2387:                *paddrp = PMAP_DIRECT_UNMAP(va);
        !          2388:        } else {
        !          2389:                ptp = uvm_pagealloc(&kpm->pm_obj[level - 1],
        !          2390:                                    ptp_va2o(va, level), NULL,
        !          2391:                                    UVM_PGA_USERESERVE|UVM_PGA_ZERO);
        !          2392:                if (ptp == NULL)
        !          2393:                        panic("pmap_get_physpage: out of memory");
        !          2394:                atomic_clearbits_int(&ptp->pg_flags, PG_BUSY);
        !          2395:                ptp->wire_count = 1;
        !          2396:                *paddrp = VM_PAGE_TO_PHYS(ptp);
        !          2397:        }
        !          2398:        kpm->pm_stats.resident_count++;
        !          2399:        return TRUE;
        !          2400: }
        !          2401:
        !          2402: /*
        !          2403:  * Allocate the amount of specified ptps for a ptp level, and populate
        !          2404:  * all levels below accordingly, mapping virtual addresses starting at
        !          2405:  * kva.
        !          2406:  *
        !          2407:  * Used by pmap_growkernel.
        !          2408:  */
        !          2409: void
        !          2410: pmap_alloc_level(pd_entry_t **pdes, vaddr_t kva, int lvl, long *needed_ptps)
        !          2411: {
        !          2412:        unsigned long i;
        !          2413:        vaddr_t va;
        !          2414:        paddr_t pa;
        !          2415:        unsigned long index, endindex;
        !          2416:        int level;
        !          2417:        pd_entry_t *pdep;
        !          2418:
        !          2419:        for (level = lvl; level > 1; level--) {
        !          2420:                if (level == PTP_LEVELS)
        !          2421:                        pdep = pmap_kernel()->pm_pdir;
        !          2422:                else
        !          2423:                        pdep = pdes[level - 2];
        !          2424:                va = kva;
        !          2425:                index = pl_i(kva, level);
        !          2426:                endindex = index + needed_ptps[level - 1];
        !          2427:                /*
        !          2428:                 * XXX special case for first time call.
        !          2429:                 */
        !          2430:                if (nkptp[level - 1] != 0)
        !          2431:                        index++;
        !          2432:                else
        !          2433:                        endindex--;
        !          2434:
        !          2435:                for (i = index; i <= endindex; i++) {
        !          2436:                        pmap_get_physpage(va, level - 1, &pa);
        !          2437:                        pdep[i] = pa | PG_RW | PG_V;
        !          2438:                        nkptp[level - 1]++;
        !          2439:                        va += nbpd[level - 1];
        !          2440:                }
        !          2441:        }
        !          2442: }
        !          2443:
        !          2444: /*
        !          2445:  * pmap_growkernel: increase usage of KVM space
        !          2446:  *
        !          2447:  * => we allocate new PTPs for the kernel and install them in all
        !          2448:  *     the pmaps on the system.
        !          2449:  */
        !          2450:
        !          2451: static vaddr_t pmap_maxkvaddr = VM_MIN_KERNEL_ADDRESS;
        !          2452:
        !          2453: vaddr_t
        !          2454: pmap_growkernel(vaddr_t maxkvaddr)
        !          2455: {
        !          2456:        struct pmap *kpm = pmap_kernel(), *pm;
        !          2457:        int s, i;
        !          2458:        unsigned newpdes;
        !          2459:        long needed_kptp[PTP_LEVELS], target_nptp, old;
        !          2460:
        !          2461:        if (maxkvaddr <= pmap_maxkvaddr)
        !          2462:                return pmap_maxkvaddr;
        !          2463:
        !          2464:        maxkvaddr = x86_round_pdr(maxkvaddr);
        !          2465:        old = nkptp[PTP_LEVELS - 1];
        !          2466:        /*
        !          2467:         * This loop could be optimized more, but pmap_growkernel()
        !          2468:         * is called infrequently.
        !          2469:         */
        !          2470:        for (i = PTP_LEVELS - 1; i >= 1; i--) {
        !          2471:                target_nptp = pl_i(maxkvaddr, i + 1) -
        !          2472:                    pl_i(VM_MIN_KERNEL_ADDRESS, i + 1);
        !          2473:                /*
        !          2474:                 * XXX only need to check toplevel.
        !          2475:                 */
        !          2476:                if (target_nptp > nkptpmax[i])
        !          2477:                        panic("out of KVA space");
        !          2478:                needed_kptp[i] = target_nptp - nkptp[i] + 1;
        !          2479:        }
        !          2480:
        !          2481:
        !          2482:        s = splhigh();  /* to be safe */
        !          2483:        simple_lock(&kpm->pm_lock);
        !          2484:        pmap_alloc_level(normal_pdes, pmap_maxkvaddr, PTP_LEVELS,
        !          2485:            needed_kptp);
        !          2486:
        !          2487:        /*
        !          2488:         * If the number of top level entries changed, update all
        !          2489:         * pmaps.
        !          2490:         */
        !          2491:        if (needed_kptp[PTP_LEVELS - 1] != 0) {
        !          2492:                newpdes = nkptp[PTP_LEVELS - 1] - old;
        !          2493:                simple_lock(&pmaps_lock);
        !          2494:                LIST_FOREACH(pm, &pmaps, pm_list) {
        !          2495:                        memcpy(&pm->pm_pdir[PDIR_SLOT_KERN + old],
        !          2496:                               &kpm->pm_pdir[PDIR_SLOT_KERN + old],
        !          2497:                               newpdes * sizeof (pd_entry_t));
        !          2498:                }
        !          2499:
        !          2500:                /* Invalidate the PDP cache. */
        !          2501:                pool_cache_invalidate(&pmap_pdp_cache);
        !          2502:                pmap_pdp_cache_generation++;
        !          2503:
        !          2504:                simple_unlock(&pmaps_lock);
        !          2505:        }
        !          2506:        pmap_maxkvaddr = maxkvaddr;
        !          2507:        simple_unlock(&kpm->pm_lock);
        !          2508:        splx(s);
        !          2509:
        !          2510:        return maxkvaddr;
        !          2511: }
        !          2512:
        !          2513: vaddr_t
        !          2514: pmap_steal_memory(vsize_t size, vaddr_t *start, vaddr_t *end)
        !          2515: {
        !          2516:        int segno;
        !          2517:        u_int npg;
        !          2518:        vaddr_t va;
        !          2519:        paddr_t pa;
        !          2520:        struct vm_physseg *seg;
        !          2521:
        !          2522:        size = round_page(size);
        !          2523:        npg = atop(size);
        !          2524:
        !          2525:        for (segno = 0, seg = vm_physmem; segno < vm_nphysseg; segno++, seg++) {
        !          2526:                if (seg->avail_end - seg->avail_start < npg)
        !          2527:                        continue;
        !          2528:                /*
        !          2529:                 * We can only steal at an ``unused'' segment boundary,
        !          2530:                 * i.e. either at the start or at the end.
        !          2531:                 */
        !          2532:                if (seg->avail_start == seg->start ||
        !          2533:                    seg->avail_end == seg->end)
        !          2534:                        break;
        !          2535:        }
        !          2536:        if (segno == vm_nphysseg) {
        !          2537:                panic("pmap_steal_memory: out of memory");
        !          2538:        } else {
        !          2539:                if (seg->avail_start == seg->start) {
        !          2540:                        pa = ptoa(seg->avail_start);
        !          2541:                        seg->avail_start += npg;
        !          2542:                        seg->start += npg;
        !          2543:                } else {
        !          2544:                        pa = ptoa(seg->avail_end) - size;
        !          2545:                        seg->avail_end -= npg;
        !          2546:                        seg->end -= npg;
        !          2547:                }
        !          2548:                /*
        !          2549:                 * If all the segment has been consumed now, remove it.
        !          2550:                 * Note that the crash dump code still knows about it
        !          2551:                 * and will dump it correctly.
        !          2552:                 */
        !          2553:                if (seg->start == seg->end) {
        !          2554:                        if (vm_nphysseg-- == 1)
        !          2555:                                panic("pmap_steal_memory: out of memory");
        !          2556:                        while (segno < vm_nphysseg) {
        !          2557:                                seg[0] = seg[1]; /* struct copy */
        !          2558:                                seg++;
        !          2559:                                segno++;
        !          2560:                        }
        !          2561:                }
        !          2562:
        !          2563:                va = PMAP_DIRECT_MAP(pa);
        !          2564:                memset((void *)va, 0, size);
        !          2565:        }
        !          2566:
        !          2567:        if (start != NULL)
        !          2568:                *start = virtual_avail;
        !          2569:        if (end != NULL)
        !          2570:                *end = VM_MAX_KERNEL_ADDRESS;
        !          2571:
        !          2572:        return (va);
        !          2573: }
        !          2574:
        !          2575: #ifdef DEBUG
        !          2576: void pmap_dump(struct pmap *, vaddr_t, vaddr_t);
        !          2577:
        !          2578: /*
        !          2579:  * pmap_dump: dump all the mappings from a pmap
        !          2580:  *
        !          2581:  * => caller should not be holding any pmap locks
        !          2582:  */
        !          2583:
        !          2584: void
        !          2585: pmap_dump(struct pmap *pmap, vaddr_t sva, vaddr_t eva)
        !          2586: {
        !          2587:        pt_entry_t *ptes, *pte;
        !          2588:        pd_entry_t **pdes;
        !          2589:        vaddr_t blkendva;
        !          2590:
        !          2591:        /*
        !          2592:         * if end is out of range truncate.
        !          2593:         * if (end == start) update to max.
        !          2594:         */
        !          2595:
        !          2596:        if (eva > VM_MAXUSER_ADDRESS || eva <= sva)
        !          2597:                eva = VM_MAXUSER_ADDRESS;
        !          2598:
        !          2599:
        !          2600:        PMAP_MAP_TO_HEAD_LOCK();
        !          2601:        pmap_map_ptes(pmap, &ptes, &pdes);      /* locks pmap */
        !          2602:
        !          2603:        /*
        !          2604:         * dumping a range of pages: we dump in PTP sized blocks (4MB)
        !          2605:         */
        !          2606:
        !          2607:        for (/* null */ ; sva < eva ; sva = blkendva) {
        !          2608:
        !          2609:                /* determine range of block */
        !          2610:                blkendva = x86_round_pdr(sva+1);
        !          2611:                if (blkendva > eva)
        !          2612:                        blkendva = eva;
        !          2613:
        !          2614:                /* valid block? */
        !          2615:                if (!pmap_pdes_valid(sva, pdes, NULL))
        !          2616:                        continue;
        !          2617:
        !          2618:                pte = &ptes[pl1_i(sva)];
        !          2619:                for (/* null */; sva < blkendva ; sva += PAGE_SIZE, pte++) {
        !          2620:                        if (!pmap_valid_entry(*pte))
        !          2621:                                continue;
        !          2622:                        printf("va %#lx -> pa %#lx (pte=%#lx)\n",
        !          2623:                               sva, *pte, *pte & PG_FRAME);
        !          2624:                }
        !          2625:        }
        !          2626:        pmap_unmap_ptes(pmap);
        !          2627:        PMAP_MAP_TO_HEAD_UNLOCK();
        !          2628: }
        !          2629: #endif
        !          2630:
        !          2631: void
        !          2632: pmap_virtual_space(vaddr_t *vstartp, vaddr_t *vendp)
        !          2633: {
        !          2634:        *vstartp = virtual_avail;
        !          2635:        *vendp = VM_MAX_KERNEL_ADDRESS;
        !          2636: }
        !          2637:
        !          2638: #ifdef MULTIPROCESSOR
        !          2639: /*
        !          2640:  * Locking for tlb shootdown.
        !          2641:  *
        !          2642:  * We lock by setting tlb_shoot_wait to the number of cpus that will
        !          2643:  * receive our tlb shootdown. After sending the IPIs, we don't need to
        !          2644:  * worry about locking order or interrupts spinning for the lock because
        !          2645:  * the call that grabs the "lock" isn't the one that releases it. And
        !          2646:  * there is nothing that can block the IPI that releases the lock.
        !          2647:  *
        !          2648:  * The functions are organized so that we first count the number of
        !          2649:  * cpus we need to send the IPI to, then we grab the counter, then
        !          2650:  * we send the IPIs, then we finally do our own shootdown.
        !          2651:  *
        !          2652:  * Our shootdown is last to make it parallell with the other cpus
        !          2653:  * to shorten the spin time.
        !          2654:  *
        !          2655:  * Notice that we depend on failures to send IPIs only being able to
        !          2656:  * happen during boot. If they happen later, the above assumption
        !          2657:  * doesn't hold since we can end up in situations where noone will
        !          2658:  * release the lock if we get an interrupt in a bad moment.
        !          2659:  */
        !          2660:
        !          2661: volatile long tlb_shoot_wait;
        !          2662:
        !          2663: volatile vaddr_t tlb_shoot_addr1;
        !          2664: volatile vaddr_t tlb_shoot_addr2;
        !          2665:
        !          2666: /* XXX */
        !          2667: #define SPINLOCK_SPIN_HOOK __asm __volatile("pause": : :"memory")
        !          2668:
        !          2669: void
        !          2670: pmap_tlb_shootpage(struct pmap *pm, vaddr_t va)
        !          2671: {
        !          2672:        struct cpu_info *ci, *self = curcpu();
        !          2673:        CPU_INFO_ITERATOR cii;
        !          2674:        long wait = 0;
        !          2675:        int mask = 0;
        !          2676:
        !          2677:        CPU_INFO_FOREACH(cii, ci) {
        !          2678:                if (ci == self || !pmap_is_active(pm, ci->ci_cpuid) ||
        !          2679:                    !(ci->ci_flags & CPUF_RUNNING))
        !          2680:                        continue;
        !          2681:                mask |= 1 << ci->ci_cpuid;
        !          2682:                wait++;
        !          2683:        }
        !          2684:
        !          2685:        if (wait > 0) {
        !          2686:                int s = splvm();
        !          2687:
        !          2688:                while (x86_atomic_cas_ul(&tlb_shoot_wait, 0, wait) != 0) {
        !          2689:                        while (tlb_shoot_wait != 0)
        !          2690:                                SPINLOCK_SPIN_HOOK;
        !          2691:                }
        !          2692:                tlb_shoot_addr1 = va;
        !          2693:                CPU_INFO_FOREACH(cii, ci) {
        !          2694:                        if ((mask & 1 << ci->ci_cpuid) == 0)
        !          2695:                                continue;
        !          2696:                        if (x86_fast_ipi(ci, LAPIC_IPI_INVLPG) != 0)
        !          2697:                                panic("pmap_tlb_shootpage: ipi failed");
        !          2698:                }
        !          2699:                splx(s);
        !          2700:        }
        !          2701:
        !          2702:        if (pmap_is_curpmap(pm))
        !          2703:                pmap_update_pg(va);
        !          2704: }
        !          2705:
        !          2706: void
        !          2707: pmap_tlb_shootrange(struct pmap *pm, vaddr_t sva, vaddr_t eva)
        !          2708: {
        !          2709:        struct cpu_info *ci, *self = curcpu();
        !          2710:        CPU_INFO_ITERATOR cii;
        !          2711:        long wait = 0;
        !          2712:        int mask = 0;
        !          2713:        vaddr_t va;
        !          2714:
        !          2715:        CPU_INFO_FOREACH(cii, ci) {
        !          2716:                if (ci == self || !pmap_is_active(pm, ci->ci_cpuid) ||
        !          2717:                    !(ci->ci_flags & CPUF_RUNNING))
        !          2718:                        continue;
        !          2719:                mask |= 1 << ci->ci_cpuid;
        !          2720:                wait++;
        !          2721:        }
        !          2722:
        !          2723:        if (wait > 0) {
        !          2724:                int s = splvm();
        !          2725:
        !          2726:                while (x86_atomic_cas_ul(&tlb_shoot_wait, 0, wait) != 0) {
        !          2727:                        while (tlb_shoot_wait != 0)
        !          2728:                                SPINLOCK_SPIN_HOOK;
        !          2729:                }
        !          2730:                tlb_shoot_addr1 = sva;
        !          2731:                tlb_shoot_addr2 = eva;
        !          2732:                CPU_INFO_FOREACH(cii, ci) {
        !          2733:                        if ((mask & 1 << ci->ci_cpuid) == 0)
        !          2734:                                continue;
        !          2735:                        if (x86_fast_ipi(ci, LAPIC_IPI_INVLRANGE) != 0)
        !          2736:                                panic("pmap_tlb_shootrange: ipi failed");
        !          2737:                }
        !          2738:                splx(s);
        !          2739:        }
        !          2740:
        !          2741:        if (pmap_is_curpmap(pm))
        !          2742:                for (va = sva; va < eva; va += PAGE_SIZE)
        !          2743:                        pmap_update_pg(va);
        !          2744: }
        !          2745:
        !          2746: void
        !          2747: pmap_tlb_shoottlb(void)
        !          2748: {
        !          2749:        struct cpu_info *ci, *self = curcpu();
        !          2750:        CPU_INFO_ITERATOR cii;
        !          2751:        long wait = 0;
        !          2752:        int mask = 0;
        !          2753:
        !          2754:        CPU_INFO_FOREACH(cii, ci) {
        !          2755:                if (ci == self || !(ci->ci_flags & CPUF_RUNNING))
        !          2756:                        continue;
        !          2757:                mask |= 1 << ci->ci_cpuid;
        !          2758:                wait++;
        !          2759:        }
        !          2760:
        !          2761:        if (wait) {
        !          2762:                int s = splvm();
        !          2763:
        !          2764:                while (x86_atomic_cas_ul(&tlb_shoot_wait, 0, wait) != 0) {
        !          2765:                        while (tlb_shoot_wait != 0)
        !          2766:                                SPINLOCK_SPIN_HOOK;
        !          2767:                }
        !          2768:
        !          2769:                CPU_INFO_FOREACH(cii, ci) {
        !          2770:                        if ((mask & 1 << ci->ci_cpuid) == 0)
        !          2771:                                continue;
        !          2772:                        if (x86_fast_ipi(ci, LAPIC_IPI_INVLTLB) != 0)
        !          2773:                                panic("pmap_tlb_shoottlb: ipi failed");
        !          2774:                }
        !          2775:                splx(s);
        !          2776:        }
        !          2777:
        !          2778:        tlbflush();
        !          2779: }
        !          2780:
        !          2781: void
        !          2782: pmap_tlb_shootwait(void)
        !          2783: {
        !          2784:        while (tlb_shoot_wait != 0)
        !          2785:                SPINLOCK_SPIN_HOOK;
        !          2786: }
        !          2787:
        !          2788: #else
        !          2789:
        !          2790: void
        !          2791: pmap_tlb_shootpage(struct pmap *pm, vaddr_t va)
        !          2792: {
        !          2793:        if (pmap_is_curpmap(pm))
        !          2794:                pmap_update_pg(va);
        !          2795:
        !          2796: }
        !          2797:
        !          2798: void
        !          2799: pmap_tlb_shootrange(struct pmap *pm, vaddr_t sva, vaddr_t eva)
        !          2800: {
        !          2801:        vaddr_t va;
        !          2802:
        !          2803:        for (va = sva; va < eva; va += PAGE_SIZE)
        !          2804:                pmap_update_pg(va);
        !          2805:
        !          2806: }
        !          2807:
        !          2808: void
        !          2809: pmap_tlb_shoottlb(void)
        !          2810: {
        !          2811:        tlbflush();
        !          2812: }
        !          2813: #endif /* MULTIPROCESSOR */

CVSweb