The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/powerpc/aim/mmu_oea64.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2001 The NetBSD Foundation, Inc.
    3  * All rights reserved.
    4  *
    5  * This code is derived from software contributed to The NetBSD Foundation
    6  * by Matt Thomas <matt@3am-software.com> of Allegro Networks, Inc.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   20  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   27  * POSSIBILITY OF SUCH DAMAGE.
   28  */
   29 /*-
   30  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
   31  * Copyright (C) 1995, 1996 TooLs GmbH.
   32  * All rights reserved.
   33  *
   34  * Redistribution and use in source and binary forms, with or without
   35  * modification, are permitted provided that the following conditions
   36  * are met:
   37  * 1. Redistributions of source code must retain the above copyright
   38  *    notice, this list of conditions and the following disclaimer.
   39  * 2. Redistributions in binary form must reproduce the above copyright
   40  *    notice, this list of conditions and the following disclaimer in the
   41  *    documentation and/or other materials provided with the distribution.
   42  * 3. All advertising materials mentioning features or use of this software
   43  *    must display the following acknowledgement:
   44  *      This product includes software developed by TooLs GmbH.
   45  * 4. The name of TooLs GmbH may not be used to endorse or promote products
   46  *    derived from this software without specific prior written permission.
   47  *
   48  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
   49  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   50  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   51  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   52  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   53  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   54  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   55  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   56  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   57  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   58  *
   59  * $NetBSD: pmap.c,v 1.28 2000/03/26 20:42:36 kleink Exp $
   60  */
   61 /*-
   62  * Copyright (C) 2001 Benno Rice.
   63  * All rights reserved.
   64  *
   65  * Redistribution and use in source and binary forms, with or without
   66  * modification, are permitted provided that the following conditions
   67  * are met:
   68  * 1. Redistributions of source code must retain the above copyright
   69  *    notice, this list of conditions and the following disclaimer.
   70  * 2. Redistributions in binary form must reproduce the above copyright
   71  *    notice, this list of conditions and the following disclaimer in the
   72  *    documentation and/or other materials provided with the distribution.
   73  *
   74  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
   75  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   76  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   77  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   78  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   79  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   80  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   81  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   82  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   83  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   84  */
   85 
   86 #include <sys/cdefs.h>
   87 __FBSDID("$FreeBSD$");
   88 
   89 /*
   90  * Manages physical address maps.
   91  *
   92  * In addition to hardware address maps, this module is called upon to
   93  * provide software-use-only maps which may or may not be stored in the
   94  * same form as hardware maps.  These pseudo-maps are used to store
   95  * intermediate results from copy operations to and from address spaces.
   96  *
   97  * Since the information managed by this module is also stored by the
   98  * logical address mapping module, this module may throw away valid virtual
   99  * to physical mappings at almost any time.  However, invalidations of
  100  * mappings must be done as requested.
  101  *
  102  * In order to cope with hardware architectures which make virtual to
  103  * physical map invalidates expensive, this module may delay invalidate
  104  * reduced protection operations until such time as they are actually
  105  * necessary.  This module is given full information as to which processors
  106  * are currently using which maps, and to when physical maps must be made
  107  * correct.
  108  */
  109 
  110 #include "opt_compat.h"
  111 #include "opt_kstack_pages.h"
  112 
  113 #include <sys/param.h>
  114 #include <sys/kernel.h>
  115 #include <sys/queue.h>
  116 #include <sys/cpuset.h>
  117 #include <sys/ktr.h>
  118 #include <sys/lock.h>
  119 #include <sys/msgbuf.h>
  120 #include <sys/mutex.h>
  121 #include <sys/proc.h>
  122 #include <sys/rwlock.h>
  123 #include <sys/sched.h>
  124 #include <sys/sysctl.h>
  125 #include <sys/systm.h>
  126 #include <sys/vmmeter.h>
  127 
  128 #include <sys/kdb.h>
  129 
  130 #include <dev/ofw/openfirm.h>
  131 
  132 #include <vm/vm.h>
  133 #include <vm/vm_param.h>
  134 #include <vm/vm_kern.h>
  135 #include <vm/vm_page.h>
  136 #include <vm/vm_map.h>
  137 #include <vm/vm_object.h>
  138 #include <vm/vm_extern.h>
  139 #include <vm/vm_pageout.h>
  140 #include <vm/vm_pager.h>
  141 #include <vm/uma.h>
  142 
  143 #include <machine/_inttypes.h>
  144 #include <machine/cpu.h>
  145 #include <machine/platform.h>
  146 #include <machine/frame.h>
  147 #include <machine/md_var.h>
  148 #include <machine/psl.h>
  149 #include <machine/bat.h>
  150 #include <machine/hid.h>
  151 #include <machine/pte.h>
  152 #include <machine/sr.h>
  153 #include <machine/trap.h>
  154 #include <machine/mmuvar.h>
  155 
  156 #include "mmu_oea64.h"
  157 #include "mmu_if.h"
  158 #include "moea64_if.h"
  159 
  160 void moea64_release_vsid(uint64_t vsid);
  161 uintptr_t moea64_get_unique_vsid(void); 
  162 
  163 #define DISABLE_TRANS(msr)      msr = mfmsr(); mtmsr(msr & ~PSL_DR)
  164 #define ENABLE_TRANS(msr)       mtmsr(msr)
  165 
  166 #define VSID_MAKE(sr, hash)     ((sr) | (((hash) & 0xfffff) << 4))
  167 #define VSID_TO_HASH(vsid)      (((vsid) >> 4) & 0xfffff)
  168 #define VSID_HASH_MASK          0x0000007fffffffffULL
  169 
  170 /*
  171  * Locking semantics:
  172  * -- Read lock: if no modifications are being made to either the PVO lists
  173  *    or page table or if any modifications being made result in internal
  174  *    changes (e.g. wiring, protection) such that the existence of the PVOs
  175  *    is unchanged and they remain associated with the same pmap (in which
  176  *    case the changes should be protected by the pmap lock)
  177  * -- Write lock: required if PTEs/PVOs are being inserted or removed.
  178  */
  179 
  180 #define LOCK_TABLE_RD() rw_rlock(&moea64_table_lock)
  181 #define UNLOCK_TABLE_RD() rw_runlock(&moea64_table_lock)
  182 #define LOCK_TABLE_WR() rw_wlock(&moea64_table_lock)
  183 #define UNLOCK_TABLE_WR() rw_wunlock(&moea64_table_lock)
  184 
  185 struct ofw_map {
  186         cell_t  om_va;
  187         cell_t  om_len;
  188         cell_t  om_pa_hi;
  189         cell_t  om_pa_lo;
  190         cell_t  om_mode;
  191 };
  192 
  193 /*
  194  * Map of physical memory regions.
  195  */
  196 static struct   mem_region *regions;
  197 static struct   mem_region *pregions;
  198 static u_int    phys_avail_count;
  199 static int      regions_sz, pregions_sz;
  200 
  201 extern void bs_remap_earlyboot(void);
  202 
  203 /*
  204  * Lock for the pteg and pvo tables.
  205  */
  206 struct rwlock   moea64_table_lock;
  207 struct mtx      moea64_slb_mutex;
  208 
  209 /*
  210  * PTEG data.
  211  */
  212 u_int           moea64_pteg_count;
  213 u_int           moea64_pteg_mask;
  214 
  215 /*
  216  * PVO data.
  217  */
  218 struct  pvo_head *moea64_pvo_table;             /* pvo entries by pteg index */
  219 struct  pvo_head moea64_pvo_kunmanaged =        /* list of unmanaged pages */
  220     LIST_HEAD_INITIALIZER(moea64_pvo_kunmanaged);
  221 
  222 uma_zone_t      moea64_upvo_zone; /* zone for pvo entries for unmanaged pages */
  223 uma_zone_t      moea64_mpvo_zone; /* zone for pvo entries for managed pages */
  224 
  225 #define BPVO_POOL_SIZE  327680
  226 static struct   pvo_entry *moea64_bpvo_pool;
  227 static int      moea64_bpvo_pool_index = 0;
  228 
  229 #define VSID_NBPW       (sizeof(u_int32_t) * 8)
  230 #ifdef __powerpc64__
  231 #define NVSIDS          (NPMAPS * 16)
  232 #define VSID_HASHMASK   0xffffffffUL
  233 #else
  234 #define NVSIDS          NPMAPS
  235 #define VSID_HASHMASK   0xfffffUL
  236 #endif
  237 static u_int    moea64_vsid_bitmap[NVSIDS / VSID_NBPW];
  238 
  239 static boolean_t moea64_initialized = FALSE;
  240 
  241 /*
  242  * Statistics.
  243  */
  244 u_int   moea64_pte_valid = 0;
  245 u_int   moea64_pte_overflow = 0;
  246 u_int   moea64_pvo_entries = 0;
  247 u_int   moea64_pvo_enter_calls = 0;
  248 u_int   moea64_pvo_remove_calls = 0;
  249 SYSCTL_INT(_machdep, OID_AUTO, moea64_pte_valid, CTLFLAG_RD, 
  250     &moea64_pte_valid, 0, "");
  251 SYSCTL_INT(_machdep, OID_AUTO, moea64_pte_overflow, CTLFLAG_RD,
  252     &moea64_pte_overflow, 0, "");
  253 SYSCTL_INT(_machdep, OID_AUTO, moea64_pvo_entries, CTLFLAG_RD, 
  254     &moea64_pvo_entries, 0, "");
  255 SYSCTL_INT(_machdep, OID_AUTO, moea64_pvo_enter_calls, CTLFLAG_RD,
  256     &moea64_pvo_enter_calls, 0, "");
  257 SYSCTL_INT(_machdep, OID_AUTO, moea64_pvo_remove_calls, CTLFLAG_RD,
  258     &moea64_pvo_remove_calls, 0, "");
  259 
  260 vm_offset_t     moea64_scratchpage_va[2];
  261 struct pvo_entry *moea64_scratchpage_pvo[2];
  262 uintptr_t       moea64_scratchpage_pte[2];
  263 struct  mtx     moea64_scratchpage_mtx;
  264 
  265 uint64_t        moea64_large_page_mask = 0;
  266 int             moea64_large_page_size = 0;
  267 int             moea64_large_page_shift = 0;
  268 
  269 /*
  270  * PVO calls.
  271  */
  272 static int      moea64_pvo_enter(mmu_t, pmap_t, uma_zone_t, struct pvo_head *,
  273                     vm_offset_t, vm_offset_t, uint64_t, int);
  274 static void     moea64_pvo_remove(mmu_t, struct pvo_entry *);
  275 static struct   pvo_entry *moea64_pvo_find_va(pmap_t, vm_offset_t);
  276 
  277 /*
  278  * Utility routines.
  279  */
  280 static boolean_t        moea64_query_bit(mmu_t, vm_page_t, u_int64_t);
  281 static u_int            moea64_clear_bit(mmu_t, vm_page_t, u_int64_t);
  282 static void             moea64_kremove(mmu_t, vm_offset_t);
  283 static void             moea64_syncicache(mmu_t, pmap_t pmap, vm_offset_t va, 
  284                             vm_offset_t pa, vm_size_t sz);
  285 
  286 /*
  287  * Kernel MMU interface
  288  */
  289 void moea64_change_wiring(mmu_t, pmap_t, vm_offset_t, boolean_t);
  290 void moea64_clear_modify(mmu_t, vm_page_t);
  291 void moea64_clear_reference(mmu_t, vm_page_t);
  292 void moea64_copy_page(mmu_t, vm_page_t, vm_page_t);
  293 void moea64_copy_pages(mmu_t mmu, vm_page_t *ma, vm_offset_t a_offset,
  294     vm_page_t *mb, vm_offset_t b_offset, int xfersize);
  295 void moea64_enter(mmu_t, pmap_t, vm_offset_t, vm_page_t, vm_prot_t, boolean_t);
  296 void moea64_enter_object(mmu_t, pmap_t, vm_offset_t, vm_offset_t, vm_page_t,
  297     vm_prot_t);
  298 void moea64_enter_quick(mmu_t, pmap_t, vm_offset_t, vm_page_t, vm_prot_t);
  299 vm_paddr_t moea64_extract(mmu_t, pmap_t, vm_offset_t);
  300 vm_page_t moea64_extract_and_hold(mmu_t, pmap_t, vm_offset_t, vm_prot_t);
  301 void moea64_init(mmu_t);
  302 boolean_t moea64_is_modified(mmu_t, vm_page_t);
  303 boolean_t moea64_is_prefaultable(mmu_t, pmap_t, vm_offset_t);
  304 boolean_t moea64_is_referenced(mmu_t, vm_page_t);
  305 boolean_t moea64_ts_referenced(mmu_t, vm_page_t);
  306 vm_offset_t moea64_map(mmu_t, vm_offset_t *, vm_offset_t, vm_offset_t, int);
  307 boolean_t moea64_page_exists_quick(mmu_t, pmap_t, vm_page_t);
  308 int moea64_page_wired_mappings(mmu_t, vm_page_t);
  309 void moea64_pinit(mmu_t, pmap_t);
  310 void moea64_pinit0(mmu_t, pmap_t);
  311 void moea64_protect(mmu_t, pmap_t, vm_offset_t, vm_offset_t, vm_prot_t);
  312 void moea64_qenter(mmu_t, vm_offset_t, vm_page_t *, int);
  313 void moea64_qremove(mmu_t, vm_offset_t, int);
  314 void moea64_release(mmu_t, pmap_t);
  315 void moea64_remove(mmu_t, pmap_t, vm_offset_t, vm_offset_t);
  316 void moea64_remove_pages(mmu_t, pmap_t);
  317 void moea64_remove_all(mmu_t, vm_page_t);
  318 void moea64_remove_write(mmu_t, vm_page_t);
  319 void moea64_zero_page(mmu_t, vm_page_t);
  320 void moea64_zero_page_area(mmu_t, vm_page_t, int, int);
  321 void moea64_zero_page_idle(mmu_t, vm_page_t);
  322 void moea64_activate(mmu_t, struct thread *);
  323 void moea64_deactivate(mmu_t, struct thread *);
  324 void *moea64_mapdev(mmu_t, vm_offset_t, vm_size_t);
  325 void *moea64_mapdev_attr(mmu_t, vm_offset_t, vm_size_t, vm_memattr_t);
  326 void moea64_unmapdev(mmu_t, vm_offset_t, vm_size_t);
  327 vm_offset_t moea64_kextract(mmu_t, vm_offset_t);
  328 void moea64_page_set_memattr(mmu_t, vm_page_t m, vm_memattr_t ma);
  329 void moea64_kenter_attr(mmu_t, vm_offset_t, vm_offset_t, vm_memattr_t ma);
  330 void moea64_kenter(mmu_t, vm_offset_t, vm_offset_t);
  331 boolean_t moea64_dev_direct_mapped(mmu_t, vm_offset_t, vm_size_t);
  332 static void moea64_sync_icache(mmu_t, pmap_t, vm_offset_t, vm_size_t);
  333 
  334 static mmu_method_t moea64_methods[] = {
  335         MMUMETHOD(mmu_change_wiring,    moea64_change_wiring),
  336         MMUMETHOD(mmu_clear_modify,     moea64_clear_modify),
  337         MMUMETHOD(mmu_clear_reference,  moea64_clear_reference),
  338         MMUMETHOD(mmu_copy_page,        moea64_copy_page),
  339         MMUMETHOD(mmu_copy_pages,       moea64_copy_pages),
  340         MMUMETHOD(mmu_enter,            moea64_enter),
  341         MMUMETHOD(mmu_enter_object,     moea64_enter_object),
  342         MMUMETHOD(mmu_enter_quick,      moea64_enter_quick),
  343         MMUMETHOD(mmu_extract,          moea64_extract),
  344         MMUMETHOD(mmu_extract_and_hold, moea64_extract_and_hold),
  345         MMUMETHOD(mmu_init,             moea64_init),
  346         MMUMETHOD(mmu_is_modified,      moea64_is_modified),
  347         MMUMETHOD(mmu_is_prefaultable,  moea64_is_prefaultable),
  348         MMUMETHOD(mmu_is_referenced,    moea64_is_referenced),
  349         MMUMETHOD(mmu_ts_referenced,    moea64_ts_referenced),
  350         MMUMETHOD(mmu_map,              moea64_map),
  351         MMUMETHOD(mmu_page_exists_quick,moea64_page_exists_quick),
  352         MMUMETHOD(mmu_page_wired_mappings,moea64_page_wired_mappings),
  353         MMUMETHOD(mmu_pinit,            moea64_pinit),
  354         MMUMETHOD(mmu_pinit0,           moea64_pinit0),
  355         MMUMETHOD(mmu_protect,          moea64_protect),
  356         MMUMETHOD(mmu_qenter,           moea64_qenter),
  357         MMUMETHOD(mmu_qremove,          moea64_qremove),
  358         MMUMETHOD(mmu_release,          moea64_release),
  359         MMUMETHOD(mmu_remove,           moea64_remove),
  360         MMUMETHOD(mmu_remove_pages,     moea64_remove_pages),
  361         MMUMETHOD(mmu_remove_all,       moea64_remove_all),
  362         MMUMETHOD(mmu_remove_write,     moea64_remove_write),
  363         MMUMETHOD(mmu_sync_icache,      moea64_sync_icache),
  364         MMUMETHOD(mmu_zero_page,        moea64_zero_page),
  365         MMUMETHOD(mmu_zero_page_area,   moea64_zero_page_area),
  366         MMUMETHOD(mmu_zero_page_idle,   moea64_zero_page_idle),
  367         MMUMETHOD(mmu_activate,         moea64_activate),
  368         MMUMETHOD(mmu_deactivate,       moea64_deactivate),
  369         MMUMETHOD(mmu_page_set_memattr, moea64_page_set_memattr),
  370 
  371         /* Internal interfaces */
  372         MMUMETHOD(mmu_mapdev,           moea64_mapdev),
  373         MMUMETHOD(mmu_mapdev_attr,      moea64_mapdev_attr),
  374         MMUMETHOD(mmu_unmapdev,         moea64_unmapdev),
  375         MMUMETHOD(mmu_kextract,         moea64_kextract),
  376         MMUMETHOD(mmu_kenter,           moea64_kenter),
  377         MMUMETHOD(mmu_kenter_attr,      moea64_kenter_attr),
  378         MMUMETHOD(mmu_dev_direct_mapped,moea64_dev_direct_mapped),
  379 
  380         { 0, 0 }
  381 };
  382 
  383 MMU_DEF(oea64_mmu, "mmu_oea64_base", moea64_methods, 0);
  384 
  385 static __inline u_int
  386 va_to_pteg(uint64_t vsid, vm_offset_t addr, int large)
  387 {
  388         uint64_t hash;
  389         int shift;
  390 
  391         shift = large ? moea64_large_page_shift : ADDR_PIDX_SHFT;
  392         hash = (vsid & VSID_HASH_MASK) ^ (((uint64_t)addr & ADDR_PIDX) >>
  393             shift);
  394         return (hash & moea64_pteg_mask);
  395 }
  396 
  397 static __inline struct pvo_head *
  398 vm_page_to_pvoh(vm_page_t m)
  399 {
  400 
  401         return (&m->md.mdpg_pvoh);
  402 }
  403 
  404 static __inline void
  405 moea64_pte_create(struct lpte *pt, uint64_t vsid, vm_offset_t va, 
  406     uint64_t pte_lo, int flags)
  407 {
  408 
  409         /*
  410          * Construct a PTE.  Default to IMB initially.  Valid bit only gets
  411          * set when the real pte is set in memory.
  412          *
  413          * Note: Don't set the valid bit for correct operation of tlb update.
  414          */
  415         pt->pte_hi = (vsid << LPTE_VSID_SHIFT) |
  416             (((uint64_t)(va & ADDR_PIDX) >> ADDR_API_SHFT64) & LPTE_API);
  417 
  418         if (flags & PVO_LARGE)
  419                 pt->pte_hi |= LPTE_BIG;
  420 
  421         pt->pte_lo = pte_lo;
  422 }
  423 
  424 static __inline uint64_t
  425 moea64_calc_wimg(vm_offset_t pa, vm_memattr_t ma)
  426 {
  427         uint64_t pte_lo;
  428         int i;
  429 
  430         if (ma != VM_MEMATTR_DEFAULT) {
  431                 switch (ma) {
  432                 case VM_MEMATTR_UNCACHEABLE:
  433                         return (LPTE_I | LPTE_G);
  434                 case VM_MEMATTR_WRITE_COMBINING:
  435                 case VM_MEMATTR_WRITE_BACK:
  436                 case VM_MEMATTR_PREFETCHABLE:
  437                         return (LPTE_I);
  438                 case VM_MEMATTR_WRITE_THROUGH:
  439                         return (LPTE_W | LPTE_M);
  440                 }
  441         }
  442 
  443         /*
  444          * Assume the page is cache inhibited and access is guarded unless
  445          * it's in our available memory array.
  446          */
  447         pte_lo = LPTE_I | LPTE_G;
  448         for (i = 0; i < pregions_sz; i++) {
  449                 if ((pa >= pregions[i].mr_start) &&
  450                     (pa < (pregions[i].mr_start + pregions[i].mr_size))) {
  451                         pte_lo &= ~(LPTE_I | LPTE_G);
  452                         pte_lo |= LPTE_M;
  453                         break;
  454                 }
  455         }
  456 
  457         return pte_lo;
  458 }
  459 
  460 /*
  461  * Quick sort callout for comparing memory regions.
  462  */
  463 static int      om_cmp(const void *a, const void *b);
  464 
  465 static int
  466 om_cmp(const void *a, const void *b)
  467 {
  468         const struct    ofw_map *mapa;
  469         const struct    ofw_map *mapb;
  470 
  471         mapa = a;
  472         mapb = b;
  473         if (mapa->om_pa_hi < mapb->om_pa_hi)
  474                 return (-1);
  475         else if (mapa->om_pa_hi > mapb->om_pa_hi)
  476                 return (1);
  477         else if (mapa->om_pa_lo < mapb->om_pa_lo)
  478                 return (-1);
  479         else if (mapa->om_pa_lo > mapb->om_pa_lo)
  480                 return (1);
  481         else
  482                 return (0);
  483 }
  484 
  485 static void
  486 moea64_add_ofw_mappings(mmu_t mmup, phandle_t mmu, size_t sz)
  487 {
  488         struct ofw_map  translations[sz/sizeof(struct ofw_map)];
  489         register_t      msr;
  490         vm_offset_t     off;
  491         vm_paddr_t      pa_base;
  492         int             i;
  493 
  494         bzero(translations, sz);
  495         if (OF_getprop(mmu, "translations", translations, sz) == -1)
  496                 panic("moea64_bootstrap: can't get ofw translations");
  497 
  498         CTR0(KTR_PMAP, "moea64_add_ofw_mappings: translations");
  499         sz /= sizeof(*translations);
  500         qsort(translations, sz, sizeof (*translations), om_cmp);
  501 
  502         for (i = 0; i < sz; i++) {
  503                 CTR3(KTR_PMAP, "translation: pa=%#x va=%#x len=%#x",
  504                     (uint32_t)(translations[i].om_pa_lo), translations[i].om_va,
  505                     translations[i].om_len);
  506 
  507                 if (translations[i].om_pa_lo % PAGE_SIZE)
  508                         panic("OFW translation not page-aligned!");
  509 
  510                 pa_base = translations[i].om_pa_lo;
  511 
  512               #ifdef __powerpc64__
  513                 pa_base += (vm_offset_t)translations[i].om_pa_hi << 32;
  514               #else
  515                 if (translations[i].om_pa_hi)
  516                         panic("OFW translations above 32-bit boundary!");
  517               #endif
  518 
  519                 /* Now enter the pages for this mapping */
  520 
  521                 DISABLE_TRANS(msr);
  522                 for (off = 0; off < translations[i].om_len; off += PAGE_SIZE) {
  523                         if (moea64_pvo_find_va(kernel_pmap,
  524                             translations[i].om_va + off) != NULL)
  525                                 continue;
  526 
  527                         moea64_kenter(mmup, translations[i].om_va + off,
  528                             pa_base + off);
  529                 }
  530                 ENABLE_TRANS(msr);
  531         }
  532 }
  533 
  534 #ifdef __powerpc64__
  535 static void
  536 moea64_probe_large_page(void)
  537 {
  538         uint16_t pvr = mfpvr() >> 16;
  539 
  540         switch (pvr) {
  541         case IBM970:
  542         case IBM970FX:
  543         case IBM970MP:
  544                 powerpc_sync(); isync();
  545                 mtspr(SPR_HID4, mfspr(SPR_HID4) & ~HID4_970_DISABLE_LG_PG);
  546                 powerpc_sync(); isync();
  547                 
  548                 /* FALLTHROUGH */
  549         case IBMCELLBE:
  550                 moea64_large_page_size = 0x1000000; /* 16 MB */
  551                 moea64_large_page_shift = 24;
  552                 break;
  553         default:
  554                 moea64_large_page_size = 0;
  555         }
  556 
  557         moea64_large_page_mask = moea64_large_page_size - 1;
  558 }
  559 
  560 static void
  561 moea64_bootstrap_slb_prefault(vm_offset_t va, int large)
  562 {
  563         struct slb *cache;
  564         struct slb entry;
  565         uint64_t esid, slbe;
  566         uint64_t i;
  567 
  568         cache = PCPU_GET(slb);
  569         esid = va >> ADDR_SR_SHFT;
  570         slbe = (esid << SLBE_ESID_SHIFT) | SLBE_VALID;
  571 
  572         for (i = 0; i < 64; i++) {
  573                 if (cache[i].slbe == (slbe | i))
  574                         return;
  575         }
  576 
  577         entry.slbe = slbe;
  578         entry.slbv = KERNEL_VSID(esid) << SLBV_VSID_SHIFT;
  579         if (large)
  580                 entry.slbv |= SLBV_L;
  581 
  582         slb_insert_kernel(entry.slbe, entry.slbv);
  583 }
  584 #endif
  585 
  586 static void
  587 moea64_setup_direct_map(mmu_t mmup, vm_offset_t kernelstart,
  588     vm_offset_t kernelend)
  589 {
  590         register_t msr;
  591         vm_paddr_t pa;
  592         vm_offset_t size, off;
  593         uint64_t pte_lo;
  594         int i;
  595 
  596         if (moea64_large_page_size == 0) 
  597                 hw_direct_map = 0;
  598 
  599         DISABLE_TRANS(msr);
  600         if (hw_direct_map) {
  601                 LOCK_TABLE_WR();
  602                 PMAP_LOCK(kernel_pmap);
  603                 for (i = 0; i < pregions_sz; i++) {
  604                   for (pa = pregions[i].mr_start; pa < pregions[i].mr_start +
  605                      pregions[i].mr_size; pa += moea64_large_page_size) {
  606                         pte_lo = LPTE_M;
  607 
  608                         /*
  609                          * Set memory access as guarded if prefetch within
  610                          * the page could exit the available physmem area.
  611                          */
  612                         if (pa & moea64_large_page_mask) {
  613                                 pa &= moea64_large_page_mask;
  614                                 pte_lo |= LPTE_G;
  615                         }
  616                         if (pa + moea64_large_page_size >
  617                             pregions[i].mr_start + pregions[i].mr_size)
  618                                 pte_lo |= LPTE_G;
  619 
  620                         moea64_pvo_enter(mmup, kernel_pmap, moea64_upvo_zone,
  621                                     &moea64_pvo_kunmanaged, pa, pa,
  622                                     pte_lo, PVO_WIRED | PVO_LARGE);
  623                   }
  624                 }
  625                 PMAP_UNLOCK(kernel_pmap);
  626                 UNLOCK_TABLE_WR();
  627         } else {
  628                 size = sizeof(struct pvo_head) * moea64_pteg_count;
  629                 off = (vm_offset_t)(moea64_pvo_table);
  630                 for (pa = off; pa < off + size; pa += PAGE_SIZE) 
  631                         moea64_kenter(mmup, pa, pa);
  632                 size = BPVO_POOL_SIZE*sizeof(struct pvo_entry);
  633                 off = (vm_offset_t)(moea64_bpvo_pool);
  634                 for (pa = off; pa < off + size; pa += PAGE_SIZE) 
  635                 moea64_kenter(mmup, pa, pa);
  636 
  637                 /*
  638                  * Map certain important things, like ourselves.
  639                  *
  640                  * NOTE: We do not map the exception vector space. That code is
  641                  * used only in real mode, and leaving it unmapped allows us to
  642                  * catch NULL pointer deferences, instead of making NULL a valid
  643                  * address.
  644                  */
  645 
  646                 for (pa = kernelstart & ~PAGE_MASK; pa < kernelend;
  647                     pa += PAGE_SIZE) 
  648                         moea64_kenter(mmup, pa, pa);
  649         }
  650         ENABLE_TRANS(msr);
  651 
  652         /*
  653          * Allow user to override unmapped_buf_allowed for testing.
  654          * XXXKIB Only direct map implementation was tested.
  655          */
  656         if (!TUNABLE_INT_FETCH("vfs.unmapped_buf_allowed",
  657             &unmapped_buf_allowed))
  658                 unmapped_buf_allowed = hw_direct_map;
  659 }
  660 
  661 void
  662 moea64_early_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
  663 {
  664         int             i, j;
  665         vm_size_t       physsz, hwphyssz;
  666 
  667 #ifndef __powerpc64__
  668         /* We don't have a direct map since there is no BAT */
  669         hw_direct_map = 0;
  670 
  671         /* Make sure battable is zero, since we have no BAT */
  672         for (i = 0; i < 16; i++) {
  673                 battable[i].batu = 0;
  674                 battable[i].batl = 0;
  675         }
  676 #else
  677         moea64_probe_large_page();
  678 
  679         /* Use a direct map if we have large page support */
  680         if (moea64_large_page_size > 0)
  681                 hw_direct_map = 1;
  682         else
  683                 hw_direct_map = 0;
  684 #endif
  685 
  686         /* Get physical memory regions from firmware */
  687         mem_regions(&pregions, &pregions_sz, &regions, &regions_sz);
  688         CTR0(KTR_PMAP, "moea64_bootstrap: physical memory");
  689 
  690         if (sizeof(phys_avail)/sizeof(phys_avail[0]) < regions_sz)
  691                 panic("moea64_bootstrap: phys_avail too small");
  692 
  693         phys_avail_count = 0;
  694         physsz = 0;
  695         hwphyssz = 0;
  696         TUNABLE_ULONG_FETCH("hw.physmem", (u_long *) &hwphyssz);
  697         for (i = 0, j = 0; i < regions_sz; i++, j += 2) {
  698                 CTR3(KTR_PMAP, "region: %#x - %#x (%#x)", regions[i].mr_start,
  699                     regions[i].mr_start + regions[i].mr_size,
  700                     regions[i].mr_size);
  701                 if (hwphyssz != 0 &&
  702                     (physsz + regions[i].mr_size) >= hwphyssz) {
  703                         if (physsz < hwphyssz) {
  704                                 phys_avail[j] = regions[i].mr_start;
  705                                 phys_avail[j + 1] = regions[i].mr_start +
  706                                     hwphyssz - physsz;
  707                                 physsz = hwphyssz;
  708                                 phys_avail_count++;
  709                         }
  710                         break;
  711                 }
  712                 phys_avail[j] = regions[i].mr_start;
  713                 phys_avail[j + 1] = regions[i].mr_start + regions[i].mr_size;
  714                 phys_avail_count++;
  715                 physsz += regions[i].mr_size;
  716         }
  717 
  718         /* Check for overlap with the kernel and exception vectors */
  719         for (j = 0; j < 2*phys_avail_count; j+=2) {
  720                 if (phys_avail[j] < EXC_LAST)
  721                         phys_avail[j] += EXC_LAST;
  722 
  723                 if (kernelstart >= phys_avail[j] &&
  724                     kernelstart < phys_avail[j+1]) {
  725                         if (kernelend < phys_avail[j+1]) {
  726                                 phys_avail[2*phys_avail_count] =
  727                                     (kernelend & ~PAGE_MASK) + PAGE_SIZE;
  728                                 phys_avail[2*phys_avail_count + 1] =
  729                                     phys_avail[j+1];
  730                                 phys_avail_count++;
  731                         }
  732 
  733                         phys_avail[j+1] = kernelstart & ~PAGE_MASK;
  734                 }
  735 
  736                 if (kernelend >= phys_avail[j] &&
  737                     kernelend < phys_avail[j+1]) {
  738                         if (kernelstart > phys_avail[j]) {
  739                                 phys_avail[2*phys_avail_count] = phys_avail[j];
  740                                 phys_avail[2*phys_avail_count + 1] =
  741                                     kernelstart & ~PAGE_MASK;
  742                                 phys_avail_count++;
  743                         }
  744 
  745                         phys_avail[j] = (kernelend & ~PAGE_MASK) + PAGE_SIZE;
  746                 }
  747         }
  748 
  749         physmem = btoc(physsz);
  750 
  751 #ifdef PTEGCOUNT
  752         moea64_pteg_count = PTEGCOUNT;
  753 #else
  754         moea64_pteg_count = 0x1000;
  755 
  756         while (moea64_pteg_count < physmem)
  757                 moea64_pteg_count <<= 1;
  758 
  759         moea64_pteg_count >>= 1;
  760 #endif /* PTEGCOUNT */
  761 }
  762 
  763 void
  764 moea64_mid_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
  765 {
  766         vm_size_t       size;
  767         register_t      msr;
  768         int             i;
  769 
  770         /*
  771          * Set PTEG mask
  772          */
  773         moea64_pteg_mask = moea64_pteg_count - 1;
  774 
  775         /*
  776          * Allocate pv/overflow lists.
  777          */
  778         size = sizeof(struct pvo_head) * moea64_pteg_count;
  779 
  780         moea64_pvo_table = (struct pvo_head *)moea64_bootstrap_alloc(size,
  781             PAGE_SIZE);
  782         CTR1(KTR_PMAP, "moea64_bootstrap: PVO table at %p", moea64_pvo_table);
  783 
  784         DISABLE_TRANS(msr);
  785         for (i = 0; i < moea64_pteg_count; i++)
  786                 LIST_INIT(&moea64_pvo_table[i]);
  787         ENABLE_TRANS(msr);
  788 
  789         /*
  790          * Initialize the lock that synchronizes access to the pteg and pvo
  791          * tables.
  792          */
  793         rw_init_flags(&moea64_table_lock, "pmap tables", RW_RECURSE);
  794         mtx_init(&moea64_slb_mutex, "SLB table", NULL, MTX_DEF);
  795 
  796         /*
  797          * Initialise the unmanaged pvo pool.
  798          */
  799         moea64_bpvo_pool = (struct pvo_entry *)moea64_bootstrap_alloc(
  800                 BPVO_POOL_SIZE*sizeof(struct pvo_entry), 0);
  801         moea64_bpvo_pool_index = 0;
  802 
  803         /*
  804          * Make sure kernel vsid is allocated as well as VSID 0.
  805          */
  806         #ifndef __powerpc64__
  807         moea64_vsid_bitmap[(KERNEL_VSIDBITS & (NVSIDS - 1)) / VSID_NBPW]
  808                 |= 1 << (KERNEL_VSIDBITS % VSID_NBPW);
  809         moea64_vsid_bitmap[0] |= 1;
  810         #endif
  811 
  812         /*
  813          * Initialize the kernel pmap (which is statically allocated).
  814          */
  815         #ifdef __powerpc64__
  816         for (i = 0; i < 64; i++) {
  817                 pcpup->pc_slb[i].slbv = 0;
  818                 pcpup->pc_slb[i].slbe = 0;
  819         }
  820         #else
  821         for (i = 0; i < 16; i++) 
  822                 kernel_pmap->pm_sr[i] = EMPTY_SEGMENT + i;
  823         #endif
  824 
  825         kernel_pmap->pmap_phys = kernel_pmap;
  826         CPU_FILL(&kernel_pmap->pm_active);
  827         LIST_INIT(&kernel_pmap->pmap_pvo);
  828 
  829         PMAP_LOCK_INIT(kernel_pmap);
  830 
  831         /*
  832          * Now map in all the other buffers we allocated earlier
  833          */
  834 
  835         moea64_setup_direct_map(mmup, kernelstart, kernelend);
  836 }
  837 
  838 void
  839 moea64_late_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
  840 {
  841         ihandle_t       mmui;
  842         phandle_t       chosen;
  843         phandle_t       mmu;
  844         size_t          sz;
  845         int             i;
  846         vm_offset_t     pa, va;
  847         void            *dpcpu;
  848 
  849         /*
  850          * Set up the Open Firmware pmap and add its mappings if not in real
  851          * mode.
  852          */
  853 
  854         chosen = OF_finddevice("/chosen");
  855         if (chosen != -1 && OF_getprop(chosen, "mmu", &mmui, 4) != -1) {
  856             mmu = OF_instance_to_package(mmui);
  857             if (mmu == -1 || (sz = OF_getproplen(mmu, "translations")) == -1)
  858                 sz = 0;
  859             if (sz > 6144 /* tmpstksz - 2 KB headroom */)
  860                 panic("moea64_bootstrap: too many ofw translations");
  861 
  862             if (sz > 0)
  863                 moea64_add_ofw_mappings(mmup, mmu, sz);
  864         }
  865 
  866         /*
  867          * Calculate the last available physical address.
  868          */
  869         for (i = 0; phys_avail[i + 2] != 0; i += 2)
  870                 ;
  871         Maxmem = powerpc_btop(phys_avail[i + 1]);
  872 
  873         /*
  874          * Initialize MMU and remap early physical mappings
  875          */
  876         MMU_CPU_BOOTSTRAP(mmup,0);
  877         mtmsr(mfmsr() | PSL_DR | PSL_IR);
  878         pmap_bootstrapped++;
  879         bs_remap_earlyboot();
  880 
  881         /*
  882          * Set the start and end of kva.
  883          */
  884         virtual_avail = VM_MIN_KERNEL_ADDRESS;
  885         virtual_end = VM_MAX_SAFE_KERNEL_ADDRESS; 
  886 
  887         /*
  888          * Map the entire KVA range into the SLB. We must not fault there.
  889          */
  890         #ifdef __powerpc64__
  891         for (va = virtual_avail; va < virtual_end; va += SEGMENT_LENGTH)
  892                 moea64_bootstrap_slb_prefault(va, 0);
  893         #endif
  894 
  895         /*
  896          * Figure out how far we can extend virtual_end into segment 16
  897          * without running into existing mappings. Segment 16 is guaranteed
  898          * to contain neither RAM nor devices (at least on Apple hardware),
  899          * but will generally contain some OFW mappings we should not
  900          * step on.
  901          */
  902 
  903         #ifndef __powerpc64__   /* KVA is in high memory on PPC64 */
  904         PMAP_LOCK(kernel_pmap);
  905         while (virtual_end < VM_MAX_KERNEL_ADDRESS &&
  906             moea64_pvo_find_va(kernel_pmap, virtual_end+1) == NULL)
  907                 virtual_end += PAGE_SIZE;
  908         PMAP_UNLOCK(kernel_pmap);
  909         #endif
  910 
  911         /*
  912          * Allocate a kernel stack with a guard page for thread0 and map it
  913          * into the kernel page map.
  914          */
  915         pa = moea64_bootstrap_alloc(KSTACK_PAGES * PAGE_SIZE, PAGE_SIZE);
  916         va = virtual_avail + KSTACK_GUARD_PAGES * PAGE_SIZE;
  917         virtual_avail = va + KSTACK_PAGES * PAGE_SIZE;
  918         CTR2(KTR_PMAP, "moea64_bootstrap: kstack0 at %#x (%#x)", pa, va);
  919         thread0.td_kstack = va;
  920         thread0.td_kstack_pages = KSTACK_PAGES;
  921         for (i = 0; i < KSTACK_PAGES; i++) {
  922                 moea64_kenter(mmup, va, pa);
  923                 pa += PAGE_SIZE;
  924                 va += PAGE_SIZE;
  925         }
  926 
  927         /*
  928          * Allocate virtual address space for the message buffer.
  929          */
  930         pa = msgbuf_phys = moea64_bootstrap_alloc(msgbufsize, PAGE_SIZE);
  931         msgbufp = (struct msgbuf *)virtual_avail;
  932         va = virtual_avail;
  933         virtual_avail += round_page(msgbufsize);
  934         while (va < virtual_avail) {
  935                 moea64_kenter(mmup, va, pa);
  936                 pa += PAGE_SIZE;
  937                 va += PAGE_SIZE;
  938         }
  939 
  940         /*
  941          * Allocate virtual address space for the dynamic percpu area.
  942          */
  943         pa = moea64_bootstrap_alloc(DPCPU_SIZE, PAGE_SIZE);
  944         dpcpu = (void *)virtual_avail;
  945         va = virtual_avail;
  946         virtual_avail += DPCPU_SIZE;
  947         while (va < virtual_avail) {
  948                 moea64_kenter(mmup, va, pa);
  949                 pa += PAGE_SIZE;
  950                 va += PAGE_SIZE;
  951         }
  952         dpcpu_init(dpcpu, 0);
  953 
  954         /*
  955          * Allocate some things for page zeroing. We put this directly
  956          * in the page table, marked with LPTE_LOCKED, to avoid any
  957          * of the PVO book-keeping or other parts of the VM system
  958          * from even knowing that this hack exists.
  959          */
  960 
  961         if (!hw_direct_map) {
  962                 mtx_init(&moea64_scratchpage_mtx, "pvo zero page", NULL,
  963                     MTX_DEF);
  964                 for (i = 0; i < 2; i++) {
  965                         moea64_scratchpage_va[i] = (virtual_end+1) - PAGE_SIZE;
  966                         virtual_end -= PAGE_SIZE;
  967 
  968                         moea64_kenter(mmup, moea64_scratchpage_va[i], 0);
  969 
  970                         moea64_scratchpage_pvo[i] = moea64_pvo_find_va(
  971                             kernel_pmap, (vm_offset_t)moea64_scratchpage_va[i]);
  972                         LOCK_TABLE_RD();
  973                         moea64_scratchpage_pte[i] = MOEA64_PVO_TO_PTE(
  974                             mmup, moea64_scratchpage_pvo[i]);
  975                         moea64_scratchpage_pvo[i]->pvo_pte.lpte.pte_hi
  976                             |= LPTE_LOCKED;
  977                         MOEA64_PTE_CHANGE(mmup, moea64_scratchpage_pte[i],
  978                             &moea64_scratchpage_pvo[i]->pvo_pte.lpte,
  979                             moea64_scratchpage_pvo[i]->pvo_vpn);
  980                         UNLOCK_TABLE_RD();
  981                 }
  982         }
  983 }
  984 
  985 /*
  986  * Activate a user pmap.  The pmap must be activated before its address
  987  * space can be accessed in any way.
  988  */
  989 void
  990 moea64_activate(mmu_t mmu, struct thread *td)
  991 {
  992         pmap_t  pm;
  993 
  994         pm = &td->td_proc->p_vmspace->vm_pmap;
  995         CPU_SET(PCPU_GET(cpuid), &pm->pm_active);
  996 
  997         #ifdef __powerpc64__
  998         PCPU_SET(userslb, pm->pm_slb);
  999         #else
 1000         PCPU_SET(curpmap, pm->pmap_phys);
 1001         #endif
 1002 }
 1003 
 1004 void
 1005 moea64_deactivate(mmu_t mmu, struct thread *td)
 1006 {
 1007         pmap_t  pm;
 1008 
 1009         pm = &td->td_proc->p_vmspace->vm_pmap;
 1010         CPU_CLR(PCPU_GET(cpuid), &pm->pm_active);
 1011         #ifdef __powerpc64__
 1012         PCPU_SET(userslb, NULL);
 1013         #else
 1014         PCPU_SET(curpmap, NULL);
 1015         #endif
 1016 }
 1017 
 1018 void
 1019 moea64_change_wiring(mmu_t mmu, pmap_t pm, vm_offset_t va, boolean_t wired)
 1020 {
 1021         struct  pvo_entry *pvo;
 1022         uintptr_t pt;
 1023         uint64_t vsid;
 1024         int     i, ptegidx;
 1025 
 1026         LOCK_TABLE_WR();
 1027         PMAP_LOCK(pm);
 1028         pvo = moea64_pvo_find_va(pm, va & ~ADDR_POFF);
 1029 
 1030         if (pvo != NULL) {
 1031                 pt = MOEA64_PVO_TO_PTE(mmu, pvo);
 1032 
 1033                 if (wired) {
 1034                         if ((pvo->pvo_vaddr & PVO_WIRED) == 0)
 1035                                 pm->pm_stats.wired_count++;
 1036                         pvo->pvo_vaddr |= PVO_WIRED;
 1037                         pvo->pvo_pte.lpte.pte_hi |= LPTE_WIRED;
 1038                 } else {
 1039                         if ((pvo->pvo_vaddr & PVO_WIRED) != 0)
 1040                                 pm->pm_stats.wired_count--;
 1041                         pvo->pvo_vaddr &= ~PVO_WIRED;
 1042                         pvo->pvo_pte.lpte.pte_hi &= ~LPTE_WIRED;
 1043                 }
 1044 
 1045                 if (pt != -1) {
 1046                         /* Update wiring flag in page table. */
 1047                         MOEA64_PTE_CHANGE(mmu, pt, &pvo->pvo_pte.lpte,
 1048                             pvo->pvo_vpn);
 1049                 } else if (wired) {
 1050                         /*
 1051                          * If we are wiring the page, and it wasn't in the
 1052                          * page table before, add it.
 1053                          */
 1054                         vsid = PVO_VSID(pvo);
 1055                         ptegidx = va_to_pteg(vsid, PVO_VADDR(pvo),
 1056                             pvo->pvo_vaddr & PVO_LARGE);
 1057 
 1058                         i = MOEA64_PTE_INSERT(mmu, ptegidx, &pvo->pvo_pte.lpte);
 1059                         
 1060                         if (i >= 0) {
 1061                                 PVO_PTEGIDX_CLR(pvo);
 1062                                 PVO_PTEGIDX_SET(pvo, i);
 1063                         }
 1064                 }
 1065                         
 1066         }
 1067         UNLOCK_TABLE_WR();
 1068         PMAP_UNLOCK(pm);
 1069 }
 1070 
 1071 /*
 1072  * This goes through and sets the physical address of our
 1073  * special scratch PTE to the PA we want to zero or copy. Because
 1074  * of locking issues (this can get called in pvo_enter() by
 1075  * the UMA allocator), we can't use most other utility functions here
 1076  */
 1077 
 1078 static __inline
 1079 void moea64_set_scratchpage_pa(mmu_t mmup, int which, vm_offset_t pa) {
 1080 
 1081         KASSERT(!hw_direct_map, ("Using OEA64 scratchpage with a direct map!"));
 1082         mtx_assert(&moea64_scratchpage_mtx, MA_OWNED);
 1083 
 1084         moea64_scratchpage_pvo[which]->pvo_pte.lpte.pte_lo &=
 1085             ~(LPTE_WIMG | LPTE_RPGN);
 1086         moea64_scratchpage_pvo[which]->pvo_pte.lpte.pte_lo |=
 1087             moea64_calc_wimg(pa, VM_MEMATTR_DEFAULT) | (uint64_t)pa;
 1088         MOEA64_PTE_CHANGE(mmup, moea64_scratchpage_pte[which],
 1089             &moea64_scratchpage_pvo[which]->pvo_pte.lpte,
 1090             moea64_scratchpage_pvo[which]->pvo_vpn);
 1091         isync();
 1092 }
 1093 
 1094 void
 1095 moea64_copy_page(mmu_t mmu, vm_page_t msrc, vm_page_t mdst)
 1096 {
 1097         vm_offset_t     dst;
 1098         vm_offset_t     src;
 1099 
 1100         dst = VM_PAGE_TO_PHYS(mdst);
 1101         src = VM_PAGE_TO_PHYS(msrc);
 1102 
 1103         if (hw_direct_map) {
 1104                 bcopy((void *)src, (void *)dst, PAGE_SIZE);
 1105         } else {
 1106                 mtx_lock(&moea64_scratchpage_mtx);
 1107 
 1108                 moea64_set_scratchpage_pa(mmu, 0, src);
 1109                 moea64_set_scratchpage_pa(mmu, 1, dst);
 1110 
 1111                 bcopy((void *)moea64_scratchpage_va[0], 
 1112                     (void *)moea64_scratchpage_va[1], PAGE_SIZE);
 1113 
 1114                 mtx_unlock(&moea64_scratchpage_mtx);
 1115         }
 1116 }
 1117 
 1118 static inline void
 1119 moea64_copy_pages_dmap(mmu_t mmu, vm_page_t *ma, vm_offset_t a_offset,
 1120     vm_page_t *mb, vm_offset_t b_offset, int xfersize)
 1121 {
 1122         void *a_cp, *b_cp;
 1123         vm_offset_t a_pg_offset, b_pg_offset;
 1124         int cnt;
 1125 
 1126         while (xfersize > 0) {
 1127                 a_pg_offset = a_offset & PAGE_MASK;
 1128                 cnt = min(xfersize, PAGE_SIZE - a_pg_offset);
 1129                 a_cp = (char *)VM_PAGE_TO_PHYS(ma[a_offset >> PAGE_SHIFT]) +
 1130                     a_pg_offset;
 1131                 b_pg_offset = b_offset & PAGE_MASK;
 1132                 cnt = min(cnt, PAGE_SIZE - b_pg_offset);
 1133                 b_cp = (char *)VM_PAGE_TO_PHYS(mb[b_offset >> PAGE_SHIFT]) +
 1134                     b_pg_offset;
 1135                 bcopy(a_cp, b_cp, cnt);
 1136                 a_offset += cnt;
 1137                 b_offset += cnt;
 1138                 xfersize -= cnt;
 1139         }
 1140 }
 1141 
 1142 static inline void
 1143 moea64_copy_pages_nodmap(mmu_t mmu, vm_page_t *ma, vm_offset_t a_offset,
 1144     vm_page_t *mb, vm_offset_t b_offset, int xfersize)
 1145 {
 1146         void *a_cp, *b_cp;
 1147         vm_offset_t a_pg_offset, b_pg_offset;
 1148         int cnt;
 1149 
 1150         mtx_lock(&moea64_scratchpage_mtx);
 1151         while (xfersize > 0) {
 1152                 a_pg_offset = a_offset & PAGE_MASK;
 1153                 cnt = min(xfersize, PAGE_SIZE - a_pg_offset);
 1154                 moea64_set_scratchpage_pa(mmu, 0,
 1155                     VM_PAGE_TO_PHYS(ma[a_offset >> PAGE_SHIFT]));
 1156                 a_cp = (char *)moea64_scratchpage_va[0] + a_pg_offset;
 1157                 b_pg_offset = b_offset & PAGE_MASK;
 1158                 cnt = min(cnt, PAGE_SIZE - b_pg_offset);
 1159                 moea64_set_scratchpage_pa(mmu, 1,
 1160                     VM_PAGE_TO_PHYS(mb[b_offset >> PAGE_SHIFT]));
 1161                 b_cp = (char *)moea64_scratchpage_va[1] + b_pg_offset;
 1162                 bcopy(a_cp, b_cp, cnt);
 1163                 a_offset += cnt;
 1164                 b_offset += cnt;
 1165                 xfersize -= cnt;
 1166         }
 1167         mtx_unlock(&moea64_scratchpage_mtx);
 1168 }
 1169 
 1170 void
 1171 moea64_copy_pages(mmu_t mmu, vm_page_t *ma, vm_offset_t a_offset,
 1172     vm_page_t *mb, vm_offset_t b_offset, int xfersize)
 1173 {
 1174 
 1175         if (hw_direct_map) {
 1176                 moea64_copy_pages_dmap(mmu, ma, a_offset, mb, b_offset,
 1177                     xfersize);
 1178         } else {
 1179                 moea64_copy_pages_nodmap(mmu, ma, a_offset, mb, b_offset,
 1180                     xfersize);
 1181         }
 1182 }
 1183 
 1184 void
 1185 moea64_zero_page_area(mmu_t mmu, vm_page_t m, int off, int size)
 1186 {
 1187         vm_offset_t pa = VM_PAGE_TO_PHYS(m);
 1188 
 1189         if (size + off > PAGE_SIZE)
 1190                 panic("moea64_zero_page: size + off > PAGE_SIZE");
 1191 
 1192         if (hw_direct_map) {
 1193                 bzero((caddr_t)pa + off, size);
 1194         } else {
 1195                 mtx_lock(&moea64_scratchpage_mtx);
 1196                 moea64_set_scratchpage_pa(mmu, 0, pa);
 1197                 bzero((caddr_t)moea64_scratchpage_va[0] + off, size);
 1198                 mtx_unlock(&moea64_scratchpage_mtx);
 1199         }
 1200 }
 1201 
 1202 /*
 1203  * Zero a page of physical memory by temporarily mapping it
 1204  */
 1205 void
 1206 moea64_zero_page(mmu_t mmu, vm_page_t m)
 1207 {
 1208         vm_offset_t pa = VM_PAGE_TO_PHYS(m);
 1209         vm_offset_t va, off;
 1210 
 1211         if (!hw_direct_map) {
 1212                 mtx_lock(&moea64_scratchpage_mtx);
 1213 
 1214                 moea64_set_scratchpage_pa(mmu, 0, pa);
 1215                 va = moea64_scratchpage_va[0];
 1216         } else {
 1217                 va = pa;
 1218         }
 1219 
 1220         for (off = 0; off < PAGE_SIZE; off += cacheline_size)
 1221                 __asm __volatile("dcbz 0,%0" :: "r"(va + off));
 1222 
 1223         if (!hw_direct_map)
 1224                 mtx_unlock(&moea64_scratchpage_mtx);
 1225 }
 1226 
 1227 void
 1228 moea64_zero_page_idle(mmu_t mmu, vm_page_t m)
 1229 {
 1230 
 1231         moea64_zero_page(mmu, m);
 1232 }
 1233 
 1234 /*
 1235  * Map the given physical page at the specified virtual address in the
 1236  * target pmap with the protection requested.  If specified the page
 1237  * will be wired down.
 1238  */
 1239 
 1240 void
 1241 moea64_enter(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_page_t m, 
 1242     vm_prot_t prot, boolean_t wired)
 1243 {
 1244         struct          pvo_head *pvo_head;
 1245         uma_zone_t      zone;
 1246         vm_page_t       pg;
 1247         uint64_t        pte_lo;
 1248         u_int           pvo_flags;
 1249         int             error;
 1250 
 1251         if (!moea64_initialized) {
 1252                 pvo_head = &moea64_pvo_kunmanaged;
 1253                 pg = NULL;
 1254                 zone = moea64_upvo_zone;
 1255                 pvo_flags = 0;
 1256         } else {
 1257                 pvo_head = vm_page_to_pvoh(m);
 1258                 pg = m;
 1259                 zone = moea64_mpvo_zone;
 1260                 pvo_flags = PVO_MANAGED;
 1261         }
 1262 
 1263         KASSERT((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) != 0 ||
 1264             VM_OBJECT_LOCKED(m->object),
 1265             ("moea64_enter: page %p is not busy", m));
 1266 
 1267         /* XXX change the pvo head for fake pages */
 1268         if ((m->oflags & VPO_UNMANAGED) != 0) {
 1269                 pvo_flags &= ~PVO_MANAGED;
 1270                 pvo_head = &moea64_pvo_kunmanaged;
 1271                 zone = moea64_upvo_zone;
 1272         }
 1273 
 1274         pte_lo = moea64_calc_wimg(VM_PAGE_TO_PHYS(m), pmap_page_get_memattr(m));
 1275 
 1276         if (prot & VM_PROT_WRITE) {
 1277                 pte_lo |= LPTE_BW;
 1278                 if (pmap_bootstrapped &&
 1279                     (m->oflags & VPO_UNMANAGED) == 0)
 1280                         vm_page_aflag_set(m, PGA_WRITEABLE);
 1281         } else
 1282                 pte_lo |= LPTE_BR;
 1283 
 1284         if ((prot & VM_PROT_EXECUTE) == 0)
 1285                 pte_lo |= LPTE_NOEXEC;
 1286 
 1287         if (wired)
 1288                 pvo_flags |= PVO_WIRED;
 1289 
 1290         LOCK_TABLE_WR();
 1291         PMAP_LOCK(pmap);
 1292         error = moea64_pvo_enter(mmu, pmap, zone, pvo_head, va,
 1293             VM_PAGE_TO_PHYS(m), pte_lo, pvo_flags);
 1294         PMAP_UNLOCK(pmap);
 1295         UNLOCK_TABLE_WR();
 1296 
 1297         /*
 1298          * Flush the page from the instruction cache if this page is
 1299          * mapped executable and cacheable.
 1300          */
 1301         if (pmap != kernel_pmap && !(m->aflags & PGA_EXECUTABLE) &&
 1302             (pte_lo & (LPTE_I | LPTE_G | LPTE_NOEXEC)) == 0) {
 1303                 vm_page_aflag_set(m, PGA_EXECUTABLE);
 1304                 moea64_syncicache(mmu, pmap, va, VM_PAGE_TO_PHYS(m), PAGE_SIZE);
 1305         }
 1306 }
 1307 
 1308 static void
 1309 moea64_syncicache(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_offset_t pa,
 1310     vm_size_t sz)
 1311 {
 1312 
 1313         /*
 1314          * This is much trickier than on older systems because
 1315          * we can't sync the icache on physical addresses directly
 1316          * without a direct map. Instead we check a couple of cases
 1317          * where the memory is already mapped in and, failing that,
 1318          * use the same trick we use for page zeroing to create
 1319          * a temporary mapping for this physical address.
 1320          */
 1321 
 1322         if (!pmap_bootstrapped) {
 1323                 /*
 1324                  * If PMAP is not bootstrapped, we are likely to be
 1325                  * in real mode.
 1326                  */
 1327                 __syncicache((void *)pa, sz);
 1328         } else if (pmap == kernel_pmap) {
 1329                 __syncicache((void *)va, sz);
 1330         } else if (hw_direct_map) {
 1331                 __syncicache((void *)pa, sz);
 1332         } else {
 1333                 /* Use the scratch page to set up a temp mapping */
 1334 
 1335                 mtx_lock(&moea64_scratchpage_mtx);
 1336 
 1337                 moea64_set_scratchpage_pa(mmu, 1, pa & ~ADDR_POFF);
 1338                 __syncicache((void *)(moea64_scratchpage_va[1] + 
 1339                     (va & ADDR_POFF)), sz);
 1340 
 1341                 mtx_unlock(&moea64_scratchpage_mtx);
 1342         }
 1343 }
 1344 
 1345 /*
 1346  * Maps a sequence of resident pages belonging to the same object.
 1347  * The sequence begins with the given page m_start.  This page is
 1348  * mapped at the given virtual address start.  Each subsequent page is
 1349  * mapped at a virtual address that is offset from start by the same
 1350  * amount as the page is offset from m_start within the object.  The
 1351  * last page in the sequence is the page with the largest offset from
 1352  * m_start that can be mapped at a virtual address less than the given
 1353  * virtual address end.  Not every virtual page between start and end
 1354  * is mapped; only those for which a resident page exists with the
 1355  * corresponding offset from m_start are mapped.
 1356  */
 1357 void
 1358 moea64_enter_object(mmu_t mmu, pmap_t pm, vm_offset_t start, vm_offset_t end,
 1359     vm_page_t m_start, vm_prot_t prot)
 1360 {
 1361         vm_page_t m;
 1362         vm_pindex_t diff, psize;
 1363 
 1364         psize = atop(end - start);
 1365         m = m_start;
 1366         while (m != NULL && (diff = m->pindex - m_start->pindex) < psize) {
 1367                 moea64_enter(mmu, pm, start + ptoa(diff), m, prot &
 1368                     (VM_PROT_READ | VM_PROT_EXECUTE), FALSE);
 1369                 m = TAILQ_NEXT(m, listq);
 1370         }
 1371 }
 1372 
 1373 void
 1374 moea64_enter_quick(mmu_t mmu, pmap_t pm, vm_offset_t va, vm_page_t m,
 1375     vm_prot_t prot)
 1376 {
 1377 
 1378         moea64_enter(mmu, pm, va, m,
 1379             prot & (VM_PROT_READ | VM_PROT_EXECUTE), FALSE);
 1380 }
 1381 
 1382 vm_paddr_t
 1383 moea64_extract(mmu_t mmu, pmap_t pm, vm_offset_t va)
 1384 {
 1385         struct  pvo_entry *pvo;
 1386         vm_paddr_t pa;
 1387 
 1388         LOCK_TABLE_RD();
 1389         PMAP_LOCK(pm);
 1390         pvo = moea64_pvo_find_va(pm, va);
 1391         if (pvo == NULL)
 1392                 pa = 0;
 1393         else
 1394                 pa = (pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN) |
 1395                     (va - PVO_VADDR(pvo));
 1396         UNLOCK_TABLE_RD();
 1397         PMAP_UNLOCK(pm);
 1398         return (pa);
 1399 }
 1400 
 1401 /*
 1402  * Atomically extract and hold the physical page with the given
 1403  * pmap and virtual address pair if that mapping permits the given
 1404  * protection.
 1405  */
 1406 
 1407 extern int pa_tryrelock_restart;
 1408 
 1409 static int
 1410 vm_page_pa_tryrelock_moea64(pmap_t pmap, vm_paddr_t pa, vm_paddr_t *locked)
 1411 {
 1412         /*
 1413          * This is a duplicate of vm_page_pa_tryrelock(), but with proper
 1414          * handling of the table lock
 1415          */
 1416         vm_paddr_t lockpa;
 1417 
 1418         lockpa = *locked;
 1419         *locked = pa;
 1420         if (lockpa) {
 1421                 PA_LOCK_ASSERT(lockpa, MA_OWNED);
 1422                 if (PA_LOCKPTR(pa) == PA_LOCKPTR(lockpa))
 1423                         return (0);
 1424                 PA_UNLOCK(lockpa);
 1425         }
 1426         if (PA_TRYLOCK(pa))
 1427                 return (0);
 1428         UNLOCK_TABLE_RD();
 1429         PMAP_UNLOCK(pmap);
 1430         atomic_add_int(&pa_tryrelock_restart, 1);
 1431         PA_LOCK(pa);
 1432         LOCK_TABLE_RD();
 1433         PMAP_LOCK(pmap);
 1434         return (EAGAIN);
 1435 }
 1436 
 1437 vm_page_t
 1438 moea64_extract_and_hold(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_prot_t prot)
 1439 {
 1440         struct  pvo_entry *pvo;
 1441         vm_page_t m;
 1442         vm_paddr_t pa;
 1443         
 1444         m = NULL;
 1445         pa = 0;
 1446         LOCK_TABLE_RD();
 1447         PMAP_LOCK(pmap);
 1448 retry:
 1449         pvo = moea64_pvo_find_va(pmap, va & ~ADDR_POFF);
 1450         if (pvo != NULL && (pvo->pvo_pte.lpte.pte_hi & LPTE_VALID) &&
 1451             ((pvo->pvo_pte.lpte.pte_lo & LPTE_PP) == LPTE_RW ||
 1452              (prot & VM_PROT_WRITE) == 0)) {
 1453                 if (vm_page_pa_tryrelock_moea64(pmap,
 1454                         pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN, &pa))
 1455                         goto retry;
 1456                 m = PHYS_TO_VM_PAGE(pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN);
 1457                 vm_page_hold(m);
 1458         }
 1459         PA_UNLOCK_COND(pa);
 1460         UNLOCK_TABLE_RD();
 1461         PMAP_UNLOCK(pmap);
 1462         return (m);
 1463 }
 1464 
 1465 static mmu_t installed_mmu;
 1466 
 1467 static void *
 1468 moea64_uma_page_alloc(uma_zone_t zone, int bytes, u_int8_t *flags, int wait) 
 1469 {
 1470         /*
 1471          * This entire routine is a horrible hack to avoid bothering kmem
 1472          * for new KVA addresses. Because this can get called from inside
 1473          * kmem allocation routines, calling kmem for a new address here
 1474          * can lead to multiply locking non-recursive mutexes.
 1475          */
 1476         static vm_pindex_t color;
 1477         vm_offset_t va;
 1478 
 1479         vm_page_t m;
 1480         int pflags, needed_lock;
 1481 
 1482         *flags = UMA_SLAB_PRIV;
 1483         needed_lock = !PMAP_LOCKED(kernel_pmap);
 1484 
 1485         if ((wait & (M_NOWAIT|M_USE_RESERVE)) == M_NOWAIT)
 1486                 pflags = VM_ALLOC_INTERRUPT | VM_ALLOC_WIRED;
 1487         else
 1488                 pflags = VM_ALLOC_SYSTEM | VM_ALLOC_WIRED;
 1489         if (wait & M_ZERO)
 1490                 pflags |= VM_ALLOC_ZERO;
 1491 
 1492         for (;;) {
 1493                 m = vm_page_alloc(NULL, color++, pflags | VM_ALLOC_NOOBJ);
 1494                 if (m == NULL) {
 1495                         if (wait & M_NOWAIT)
 1496                                 return (NULL);
 1497                         VM_WAIT;
 1498                 } else
 1499                         break;
 1500         }
 1501 
 1502         va = VM_PAGE_TO_PHYS(m);
 1503 
 1504         LOCK_TABLE_WR();
 1505         if (needed_lock)
 1506                 PMAP_LOCK(kernel_pmap);
 1507 
 1508         moea64_pvo_enter(installed_mmu, kernel_pmap, moea64_upvo_zone,
 1509             &moea64_pvo_kunmanaged, va, VM_PAGE_TO_PHYS(m), LPTE_M,
 1510             PVO_WIRED | PVO_BOOTSTRAP);
 1511 
 1512         if (needed_lock)
 1513                 PMAP_UNLOCK(kernel_pmap);
 1514         UNLOCK_TABLE_WR();
 1515         
 1516         if ((wait & M_ZERO) && (m->flags & PG_ZERO) == 0)
 1517                 bzero((void *)va, PAGE_SIZE);
 1518 
 1519         return (void *)va;
 1520 }
 1521 
 1522 extern int elf32_nxstack;
 1523 
 1524 void
 1525 moea64_init(mmu_t mmu)
 1526 {
 1527 
 1528         CTR0(KTR_PMAP, "moea64_init");
 1529 
 1530         moea64_upvo_zone = uma_zcreate("UPVO entry", sizeof (struct pvo_entry),
 1531             NULL, NULL, NULL, NULL, UMA_ALIGN_PTR,
 1532             UMA_ZONE_VM | UMA_ZONE_NOFREE);
 1533         moea64_mpvo_zone = uma_zcreate("MPVO entry", sizeof(struct pvo_entry),
 1534             NULL, NULL, NULL, NULL, UMA_ALIGN_PTR,
 1535             UMA_ZONE_VM | UMA_ZONE_NOFREE);
 1536 
 1537         if (!hw_direct_map) {
 1538                 installed_mmu = mmu;
 1539                 uma_zone_set_allocf(moea64_upvo_zone,moea64_uma_page_alloc);
 1540                 uma_zone_set_allocf(moea64_mpvo_zone,moea64_uma_page_alloc);
 1541         }
 1542 
 1543 #ifdef COMPAT_FREEBSD32
 1544         elf32_nxstack = 1;
 1545 #endif
 1546 
 1547         moea64_initialized = TRUE;
 1548 }
 1549 
 1550 boolean_t
 1551 moea64_is_referenced(mmu_t mmu, vm_page_t m)
 1552 {
 1553 
 1554         KASSERT((m->oflags & VPO_UNMANAGED) == 0,
 1555             ("moea64_is_referenced: page %p is not managed", m));
 1556         return (moea64_query_bit(mmu, m, PTE_REF));
 1557 }
 1558 
 1559 boolean_t
 1560 moea64_is_modified(mmu_t mmu, vm_page_t m)
 1561 {
 1562 
 1563         KASSERT((m->oflags & VPO_UNMANAGED) == 0,
 1564             ("moea64_is_modified: page %p is not managed", m));
 1565 
 1566         /*
 1567          * If the page is not VPO_BUSY, then PGA_WRITEABLE cannot be
 1568          * concurrently set while the object is locked.  Thus, if PGA_WRITEABLE
 1569          * is clear, no PTEs can have LPTE_CHG set.
 1570          */
 1571         VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
 1572         if ((m->oflags & VPO_BUSY) == 0 &&
 1573             (m->aflags & PGA_WRITEABLE) == 0)
 1574                 return (FALSE);
 1575         return (moea64_query_bit(mmu, m, LPTE_CHG));
 1576 }
 1577 
 1578 boolean_t
 1579 moea64_is_prefaultable(mmu_t mmu, pmap_t pmap, vm_offset_t va)
 1580 {
 1581         struct pvo_entry *pvo;
 1582         boolean_t rv;
 1583 
 1584         LOCK_TABLE_RD();
 1585         PMAP_LOCK(pmap);
 1586         pvo = moea64_pvo_find_va(pmap, va & ~ADDR_POFF);
 1587         rv = pvo == NULL || (pvo->pvo_pte.lpte.pte_hi & LPTE_VALID) == 0;
 1588         PMAP_UNLOCK(pmap);
 1589         UNLOCK_TABLE_RD();
 1590         return (rv);
 1591 }
 1592 
 1593 void
 1594 moea64_clear_reference(mmu_t mmu, vm_page_t m)
 1595 {
 1596 
 1597         KASSERT((m->oflags & VPO_UNMANAGED) == 0,
 1598             ("moea64_clear_reference: page %p is not managed", m));
 1599         moea64_clear_bit(mmu, m, LPTE_REF);
 1600 }
 1601 
 1602 void
 1603 moea64_clear_modify(mmu_t mmu, vm_page_t m)
 1604 {
 1605 
 1606         KASSERT((m->oflags & VPO_UNMANAGED) == 0,
 1607             ("moea64_clear_modify: page %p is not managed", m));
 1608         VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
 1609         KASSERT((m->oflags & VPO_BUSY) == 0,
 1610             ("moea64_clear_modify: page %p is busy", m));
 1611 
 1612         /*
 1613          * If the page is not PGA_WRITEABLE, then no PTEs can have LPTE_CHG
 1614          * set.  If the object containing the page is locked and the page is
 1615          * not VPO_BUSY, then PGA_WRITEABLE cannot be concurrently set.
 1616          */
 1617         if ((m->aflags & PGA_WRITEABLE) == 0)
 1618                 return;
 1619         moea64_clear_bit(mmu, m, LPTE_CHG);
 1620 }
 1621 
 1622 /*
 1623  * Clear the write and modified bits in each of the given page's mappings.
 1624  */
 1625 void
 1626 moea64_remove_write(mmu_t mmu, vm_page_t m)
 1627 {
 1628         struct  pvo_entry *pvo;
 1629         uintptr_t pt;
 1630         pmap_t  pmap;
 1631         uint64_t lo = 0;
 1632 
 1633         KASSERT((m->oflags & VPO_UNMANAGED) == 0,
 1634             ("moea64_remove_write: page %p is not managed", m));
 1635 
 1636         /*
 1637          * If the page is not VPO_BUSY, then PGA_WRITEABLE cannot be set by
 1638          * another thread while the object is locked.  Thus, if PGA_WRITEABLE
 1639          * is clear, no page table entries need updating.
 1640          */
 1641         VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
 1642         if ((m->oflags & VPO_BUSY) == 0 &&
 1643             (m->aflags & PGA_WRITEABLE) == 0)
 1644                 return;
 1645         powerpc_sync();
 1646         LOCK_TABLE_RD();
 1647         LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
 1648                 pmap = pvo->pvo_pmap;
 1649                 PMAP_LOCK(pmap);
 1650                 if ((pvo->pvo_pte.lpte.pte_lo & LPTE_PP) != LPTE_BR) {
 1651                         pt = MOEA64_PVO_TO_PTE(mmu, pvo);
 1652                         pvo->pvo_pte.lpte.pte_lo &= ~LPTE_PP;
 1653                         pvo->pvo_pte.lpte.pte_lo |= LPTE_BR;
 1654                         if (pt != -1) {
 1655                                 MOEA64_PTE_SYNCH(mmu, pt, &pvo->pvo_pte.lpte);
 1656                                 lo |= pvo->pvo_pte.lpte.pte_lo;
 1657                                 pvo->pvo_pte.lpte.pte_lo &= ~LPTE_CHG;
 1658                                 MOEA64_PTE_CHANGE(mmu, pt,
 1659                                     &pvo->pvo_pte.lpte, pvo->pvo_vpn);
 1660                                 if (pvo->pvo_pmap == kernel_pmap)
 1661                                         isync();
 1662                         }
 1663                 }
 1664                 if ((lo & LPTE_CHG) != 0) 
 1665                         vm_page_dirty(m);
 1666                 PMAP_UNLOCK(pmap);
 1667         }
 1668         UNLOCK_TABLE_RD();
 1669         vm_page_aflag_clear(m, PGA_WRITEABLE);
 1670 }
 1671 
 1672 /*
 1673  *      moea64_ts_referenced:
 1674  *
 1675  *      Return a count of reference bits for a page, clearing those bits.
 1676  *      It is not necessary for every reference bit to be cleared, but it
 1677  *      is necessary that 0 only be returned when there are truly no
 1678  *      reference bits set.
 1679  *
 1680  *      XXX: The exact number of bits to check and clear is a matter that
 1681  *      should be tested and standardized at some point in the future for
 1682  *      optimal aging of shared pages.
 1683  */
 1684 boolean_t
 1685 moea64_ts_referenced(mmu_t mmu, vm_page_t m)
 1686 {
 1687 
 1688         KASSERT((m->oflags & VPO_UNMANAGED) == 0,
 1689             ("moea64_ts_referenced: page %p is not managed", m));
 1690         return (moea64_clear_bit(mmu, m, LPTE_REF));
 1691 }
 1692 
 1693 /*
 1694  * Modify the WIMG settings of all mappings for a page.
 1695  */
 1696 void
 1697 moea64_page_set_memattr(mmu_t mmu, vm_page_t m, vm_memattr_t ma)
 1698 {
 1699         struct  pvo_entry *pvo;
 1700         struct  pvo_head *pvo_head;
 1701         uintptr_t pt;
 1702         pmap_t  pmap;
 1703         uint64_t lo;
 1704 
 1705         if ((m->oflags & VPO_UNMANAGED) != 0) {
 1706                 m->md.mdpg_cache_attrs = ma;
 1707                 return;
 1708         }
 1709 
 1710         pvo_head = vm_page_to_pvoh(m);
 1711         lo = moea64_calc_wimg(VM_PAGE_TO_PHYS(m), ma);
 1712         LOCK_TABLE_RD();
 1713         LIST_FOREACH(pvo, pvo_head, pvo_vlink) {
 1714                 pmap = pvo->pvo_pmap;
 1715                 PMAP_LOCK(pmap);
 1716                 pt = MOEA64_PVO_TO_PTE(mmu, pvo);
 1717                 pvo->pvo_pte.lpte.pte_lo &= ~LPTE_WIMG;
 1718                 pvo->pvo_pte.lpte.pte_lo |= lo;
 1719                 if (pt != -1) {
 1720                         MOEA64_PTE_CHANGE(mmu, pt, &pvo->pvo_pte.lpte,
 1721                             pvo->pvo_vpn);
 1722                         if (pvo->pvo_pmap == kernel_pmap)
 1723                                 isync();
 1724                 }
 1725                 PMAP_UNLOCK(pmap);
 1726         }
 1727         UNLOCK_TABLE_RD();
 1728         m->md.mdpg_cache_attrs = ma;
 1729 }
 1730 
 1731 /*
 1732  * Map a wired page into kernel virtual address space.
 1733  */
 1734 void
 1735 moea64_kenter_attr(mmu_t mmu, vm_offset_t va, vm_offset_t pa, vm_memattr_t ma)
 1736 {
 1737         uint64_t        pte_lo;
 1738         int             error;  
 1739 
 1740         pte_lo = moea64_calc_wimg(pa, ma);
 1741 
 1742         LOCK_TABLE_WR();
 1743         PMAP_LOCK(kernel_pmap);
 1744         error = moea64_pvo_enter(mmu, kernel_pmap, moea64_upvo_zone,
 1745             &moea64_pvo_kunmanaged, va, pa, pte_lo, PVO_WIRED);
 1746         PMAP_UNLOCK(kernel_pmap);
 1747         UNLOCK_TABLE_WR();
 1748 
 1749         if (error != 0 && error != ENOENT)
 1750                 panic("moea64_kenter: failed to enter va %#zx pa %#zx: %d", va,
 1751                     pa, error);
 1752 }
 1753 
 1754 void
 1755 moea64_kenter(mmu_t mmu, vm_offset_t va, vm_offset_t pa)
 1756 {
 1757 
 1758         moea64_kenter_attr(mmu, va, pa, VM_MEMATTR_DEFAULT);
 1759 }
 1760 
 1761 /*
 1762  * Extract the physical page address associated with the given kernel virtual
 1763  * address.
 1764  */
 1765 vm_offset_t
 1766 moea64_kextract(mmu_t mmu, vm_offset_t va)
 1767 {
 1768         struct          pvo_entry *pvo;
 1769         vm_paddr_t pa;
 1770 
 1771         /*
 1772          * Shortcut the direct-mapped case when applicable.  We never put
 1773          * anything but 1:1 mappings below VM_MIN_KERNEL_ADDRESS.
 1774          */
 1775         if (va < VM_MIN_KERNEL_ADDRESS)
 1776                 return (va);
 1777 
 1778         LOCK_TABLE_RD();
 1779         PMAP_LOCK(kernel_pmap);
 1780         pvo = moea64_pvo_find_va(kernel_pmap, va);
 1781         KASSERT(pvo != NULL, ("moea64_kextract: no addr found for %#" PRIxPTR,
 1782             va));
 1783         pa = (pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN) | (va - PVO_VADDR(pvo));
 1784         UNLOCK_TABLE_RD();
 1785         PMAP_UNLOCK(kernel_pmap);
 1786         return (pa);
 1787 }
 1788 
 1789 /*
 1790  * Remove a wired page from kernel virtual address space.
 1791  */
 1792 void
 1793 moea64_kremove(mmu_t mmu, vm_offset_t va)
 1794 {
 1795         moea64_remove(mmu, kernel_pmap, va, va + PAGE_SIZE);
 1796 }
 1797 
 1798 /*
 1799  * Map a range of physical addresses into kernel virtual address space.
 1800  *
 1801  * The value passed in *virt is a suggested virtual address for the mapping.
 1802  * Architectures which can support a direct-mapped physical to virtual region
 1803  * can return the appropriate address within that region, leaving '*virt'
 1804  * unchanged.  We cannot and therefore do not; *virt is updated with the
 1805  * first usable address after the mapped region.
 1806  */
 1807 vm_offset_t
 1808 moea64_map(mmu_t mmu, vm_offset_t *virt, vm_offset_t pa_start,
 1809     vm_offset_t pa_end, int prot)
 1810 {
 1811         vm_offset_t     sva, va;
 1812 
 1813         sva = *virt;
 1814         va = sva;
 1815         for (; pa_start < pa_end; pa_start += PAGE_SIZE, va += PAGE_SIZE)
 1816                 moea64_kenter(mmu, va, pa_start);
 1817         *virt = va;
 1818 
 1819         return (sva);
 1820 }
 1821 
 1822 /*
 1823  * Returns true if the pmap's pv is one of the first
 1824  * 16 pvs linked to from this page.  This count may
 1825  * be changed upwards or downwards in the future; it
 1826  * is only necessary that true be returned for a small
 1827  * subset of pmaps for proper page aging.
 1828  */
 1829 boolean_t
 1830 moea64_page_exists_quick(mmu_t mmu, pmap_t pmap, vm_page_t m)
 1831 {
 1832         int loops;
 1833         struct pvo_entry *pvo;
 1834         boolean_t rv;
 1835 
 1836         KASSERT((m->oflags & VPO_UNMANAGED) == 0,
 1837             ("moea64_page_exists_quick: page %p is not managed", m));
 1838         loops = 0;
 1839         rv = FALSE;
 1840         LOCK_TABLE_RD();
 1841         LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
 1842                 if (pvo->pvo_pmap == pmap) {
 1843                         rv = TRUE;
 1844                         break;
 1845                 }
 1846                 if (++loops >= 16)
 1847                         break;
 1848         }
 1849         UNLOCK_TABLE_RD();
 1850         return (rv);
 1851 }
 1852 
 1853 /*
 1854  * Return the number of managed mappings to the given physical page
 1855  * that are wired.
 1856  */
 1857 int
 1858 moea64_page_wired_mappings(mmu_t mmu, vm_page_t m)
 1859 {
 1860         struct pvo_entry *pvo;
 1861         int count;
 1862 
 1863         count = 0;
 1864         if ((m->oflags & VPO_UNMANAGED) != 0)
 1865                 return (count);
 1866         LOCK_TABLE_RD();
 1867         LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink)
 1868                 if ((pvo->pvo_vaddr & PVO_WIRED) != 0)
 1869                         count++;
 1870         UNLOCK_TABLE_RD();
 1871         return (count);
 1872 }
 1873 
 1874 static uintptr_t        moea64_vsidcontext;
 1875 
 1876 uintptr_t
 1877 moea64_get_unique_vsid(void) {
 1878         u_int entropy;
 1879         register_t hash;
 1880         uint32_t mask;
 1881         int i;
 1882 
 1883         entropy = 0;
 1884         __asm __volatile("mftb %0" : "=r"(entropy));
 1885 
 1886         mtx_lock(&moea64_slb_mutex);
 1887         for (i = 0; i < NVSIDS; i += VSID_NBPW) {
 1888                 u_int   n;
 1889 
 1890                 /*
 1891                  * Create a new value by mutiplying by a prime and adding in
 1892                  * entropy from the timebase register.  This is to make the
 1893                  * VSID more random so that the PT hash function collides
 1894                  * less often.  (Note that the prime casues gcc to do shifts
 1895                  * instead of a multiply.)
 1896                  */
 1897                 moea64_vsidcontext = (moea64_vsidcontext * 0x1105) + entropy;
 1898                 hash = moea64_vsidcontext & (NVSIDS - 1);
 1899                 if (hash == 0)          /* 0 is special, avoid it */
 1900                         continue;
 1901                 n = hash >> 5;
 1902                 mask = 1 << (hash & (VSID_NBPW - 1));
 1903                 hash = (moea64_vsidcontext & VSID_HASHMASK);
 1904                 if (moea64_vsid_bitmap[n] & mask) {     /* collision? */
 1905                         /* anything free in this bucket? */
 1906                         if (moea64_vsid_bitmap[n] == 0xffffffff) {
 1907                                 entropy = (moea64_vsidcontext >> 20);
 1908                                 continue;
 1909                         }
 1910                         i = ffs(~moea64_vsid_bitmap[n]) - 1;
 1911                         mask = 1 << i;
 1912                         hash &= VSID_HASHMASK & ~(VSID_NBPW - 1);
 1913                         hash |= i;
 1914                 }
 1915                 KASSERT(!(moea64_vsid_bitmap[n] & mask),
 1916                     ("Allocating in-use VSID %#zx\n", hash));
 1917                 moea64_vsid_bitmap[n] |= mask;
 1918                 mtx_unlock(&moea64_slb_mutex);
 1919                 return (hash);
 1920         }
 1921 
 1922         mtx_unlock(&moea64_slb_mutex);
 1923         panic("%s: out of segments",__func__);
 1924 }
 1925 
 1926 #ifdef __powerpc64__
 1927 void
 1928 moea64_pinit(mmu_t mmu, pmap_t pmap)
 1929 {
 1930         PMAP_LOCK_INIT(pmap);
 1931         LIST_INIT(&pmap->pmap_pvo);
 1932 
 1933         pmap->pm_slb_tree_root = slb_alloc_tree();
 1934         pmap->pm_slb = slb_alloc_user_cache();
 1935         pmap->pm_slb_len = 0;
 1936 }
 1937 #else
 1938 void
 1939 moea64_pinit(mmu_t mmu, pmap_t pmap)
 1940 {
 1941         int     i;
 1942         uint32_t hash;
 1943 
 1944         PMAP_LOCK_INIT(pmap);
 1945         LIST_INIT(&pmap->pmap_pvo);
 1946 
 1947         if (pmap_bootstrapped)
 1948                 pmap->pmap_phys = (pmap_t)moea64_kextract(mmu,
 1949                     (vm_offset_t)pmap);
 1950         else
 1951                 pmap->pmap_phys = pmap;
 1952 
 1953         /*
 1954          * Allocate some segment registers for this pmap.
 1955          */
 1956         hash = moea64_get_unique_vsid();
 1957 
 1958         for (i = 0; i < 16; i++) 
 1959                 pmap->pm_sr[i] = VSID_MAKE(i, hash);
 1960 
 1961         KASSERT(pmap->pm_sr[0] != 0, ("moea64_pinit: pm_sr[0] = 0"));
 1962 }
 1963 #endif
 1964 
 1965 /*
 1966  * Initialize the pmap associated with process 0.
 1967  */
 1968 void
 1969 moea64_pinit0(mmu_t mmu, pmap_t pm)
 1970 {
 1971         moea64_pinit(mmu, pm);
 1972         bzero(&pm->pm_stats, sizeof(pm->pm_stats));
 1973 }
 1974 
 1975 /*
 1976  * Set the physical protection on the specified range of this map as requested.
 1977  */
 1978 static void
 1979 moea64_pvo_protect(mmu_t mmu,  pmap_t pm, struct pvo_entry *pvo, vm_prot_t prot)
 1980 {
 1981         uintptr_t pt;
 1982         struct  vm_page *pg;
 1983         uint64_t oldlo;
 1984 
 1985         PMAP_LOCK_ASSERT(pm, MA_OWNED);
 1986 
 1987         /*
 1988          * Grab the PTE pointer before we diddle with the cached PTE
 1989          * copy.
 1990          */
 1991         pt = MOEA64_PVO_TO_PTE(mmu, pvo);
 1992 
 1993         /*
 1994          * Change the protection of the page.
 1995          */
 1996         oldlo = pvo->pvo_pte.lpte.pte_lo;
 1997         pvo->pvo_pte.lpte.pte_lo &= ~LPTE_PP;
 1998         pvo->pvo_pte.lpte.pte_lo &= ~LPTE_NOEXEC;
 1999         if ((prot & VM_PROT_EXECUTE) == 0) 
 2000                 pvo->pvo_pte.lpte.pte_lo |= LPTE_NOEXEC;
 2001         if (prot & VM_PROT_WRITE) 
 2002                 pvo->pvo_pte.lpte.pte_lo |= LPTE_BW;
 2003         else
 2004                 pvo->pvo_pte.lpte.pte_lo |= LPTE_BR;
 2005 
 2006         pg = PHYS_TO_VM_PAGE(pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN);
 2007 
 2008         /*
 2009          * If the PVO is in the page table, update that pte as well.
 2010          */
 2011         if (pt != -1)
 2012                 MOEA64_PTE_CHANGE(mmu, pt, &pvo->pvo_pte.lpte,
 2013                     pvo->pvo_vpn);
 2014         if (pm != kernel_pmap && pg != NULL && !(pg->aflags & PGA_EXECUTABLE) &&
 2015             (pvo->pvo_pte.lpte.pte_lo & (LPTE_I | LPTE_G | LPTE_NOEXEC)) == 0) {
 2016                 if ((pg->oflags & VPO_UNMANAGED) == 0)
 2017                         vm_page_aflag_set(pg, PGA_EXECUTABLE);
 2018                 moea64_syncicache(mmu, pm, PVO_VADDR(pvo),
 2019                     pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN, PAGE_SIZE);
 2020         }
 2021 
 2022         /*
 2023          * Update vm about the REF/CHG bits if the page is managed and we have
 2024          * removed write access.
 2025          */
 2026         if ((pvo->pvo_vaddr & PVO_MANAGED) == PVO_MANAGED && 
 2027             (oldlo & LPTE_PP) != LPTE_BR && !(prot && VM_PROT_WRITE)) {
 2028                 if (pg != NULL) {
 2029                         if (pvo->pvo_pte.lpte.pte_lo & LPTE_CHG)
 2030                                 vm_page_dirty(pg);
 2031                         if (pvo->pvo_pte.lpte.pte_lo & LPTE_REF)
 2032                                 vm_page_aflag_set(pg, PGA_REFERENCED);
 2033                 }
 2034         }
 2035 }
 2036 
 2037 void
 2038 moea64_protect(mmu_t mmu, pmap_t pm, vm_offset_t sva, vm_offset_t eva,
 2039     vm_prot_t prot)
 2040 {
 2041         struct  pvo_entry *pvo, *tpvo;
 2042 
 2043         CTR4(KTR_PMAP, "moea64_protect: pm=%p sva=%#x eva=%#x prot=%#x", pm,
 2044             sva, eva, prot);
 2045 
 2046         KASSERT(pm == &curproc->p_vmspace->vm_pmap || pm == kernel_pmap,
 2047             ("moea64_protect: non current pmap"));
 2048 
 2049         if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
 2050                 moea64_remove(mmu, pm, sva, eva);
 2051                 return;
 2052         }
 2053 
 2054         LOCK_TABLE_RD();
 2055         PMAP_LOCK(pm);
 2056         if ((eva - sva)/PAGE_SIZE < pm->pm_stats.resident_count) {
 2057                 while (sva < eva) {
 2058                         #ifdef __powerpc64__
 2059                         if (pm != kernel_pmap &&
 2060                             user_va_to_slb_entry(pm, sva) == NULL) {
 2061                                 sva = roundup2(sva + 1, SEGMENT_LENGTH);
 2062                                 continue;
 2063                         }
 2064                         #endif
 2065                         pvo = moea64_pvo_find_va(pm, sva);
 2066                         if (pvo != NULL)
 2067                                 moea64_pvo_protect(mmu, pm, pvo, prot);
 2068                         sva += PAGE_SIZE;
 2069                 }
 2070         } else {
 2071                 LIST_FOREACH_SAFE(pvo, &pm->pmap_pvo, pvo_plink, tpvo) {
 2072                         if (PVO_VADDR(pvo) < sva || PVO_VADDR(pvo) >= eva)
 2073                                 continue;
 2074                         moea64_pvo_protect(mmu, pm, pvo, prot);
 2075                 }
 2076         }
 2077         UNLOCK_TABLE_RD();
 2078         PMAP_UNLOCK(pm);
 2079 }
 2080 
 2081 /*
 2082  * Map a list of wired pages into kernel virtual address space.  This is
 2083  * intended for temporary mappings which do not need page modification or
 2084  * references recorded.  Existing mappings in the region are overwritten.
 2085  */
 2086 void
 2087 moea64_qenter(mmu_t mmu, vm_offset_t va, vm_page_t *m, int count)
 2088 {
 2089         while (count-- > 0) {
 2090                 moea64_kenter(mmu, va, VM_PAGE_TO_PHYS(*m));
 2091                 va += PAGE_SIZE;
 2092                 m++;
 2093         }
 2094 }
 2095 
 2096 /*
 2097  * Remove page mappings from kernel virtual address space.  Intended for
 2098  * temporary mappings entered by moea64_qenter.
 2099  */
 2100 void
 2101 moea64_qremove(mmu_t mmu, vm_offset_t va, int count)
 2102 {
 2103         while (count-- > 0) {
 2104                 moea64_kremove(mmu, va);
 2105                 va += PAGE_SIZE;
 2106         }
 2107 }
 2108 
 2109 void
 2110 moea64_release_vsid(uint64_t vsid)
 2111 {
 2112         int idx, mask;
 2113 
 2114         mtx_lock(&moea64_slb_mutex);
 2115         idx = vsid & (NVSIDS-1);
 2116         mask = 1 << (idx % VSID_NBPW);
 2117         idx /= VSID_NBPW;
 2118         KASSERT(moea64_vsid_bitmap[idx] & mask,
 2119             ("Freeing unallocated VSID %#jx", vsid));
 2120         moea64_vsid_bitmap[idx] &= ~mask;
 2121         mtx_unlock(&moea64_slb_mutex);
 2122 }
 2123         
 2124 
 2125 void
 2126 moea64_release(mmu_t mmu, pmap_t pmap)
 2127 {
 2128         
 2129         /*
 2130          * Free segment registers' VSIDs
 2131          */
 2132     #ifdef __powerpc64__
 2133         slb_free_tree(pmap);
 2134         slb_free_user_cache(pmap->pm_slb);
 2135     #else
 2136         KASSERT(pmap->pm_sr[0] != 0, ("moea64_release: pm_sr[0] = 0"));
 2137 
 2138         moea64_release_vsid(VSID_TO_HASH(pmap->pm_sr[0]));
 2139     #endif
 2140 
 2141         PMAP_LOCK_DESTROY(pmap);
 2142 }
 2143 
 2144 /*
 2145  * Remove all pages mapped by the specified pmap
 2146  */
 2147 void
 2148 moea64_remove_pages(mmu_t mmu, pmap_t pm)
 2149 {
 2150         struct  pvo_entry *pvo, *tpvo;
 2151 
 2152         LOCK_TABLE_WR();
 2153         PMAP_LOCK(pm);
 2154         LIST_FOREACH_SAFE(pvo, &pm->pmap_pvo, pvo_plink, tpvo) {
 2155                 if (!(pvo->pvo_vaddr & PVO_WIRED))
 2156                         moea64_pvo_remove(mmu, pvo);
 2157         }
 2158         UNLOCK_TABLE_WR();
 2159         PMAP_UNLOCK(pm);
 2160 }
 2161 
 2162 /*
 2163  * Remove the given range of addresses from the specified map.
 2164  */
 2165 void
 2166 moea64_remove(mmu_t mmu, pmap_t pm, vm_offset_t sva, vm_offset_t eva)
 2167 {
 2168         struct  pvo_entry *pvo, *tpvo;
 2169 
 2170         /*
 2171          * Perform an unsynchronized read.  This is, however, safe.
 2172          */
 2173         if (pm->pm_stats.resident_count == 0)
 2174                 return;
 2175 
 2176         LOCK_TABLE_WR();
 2177         PMAP_LOCK(pm);
 2178         if ((eva - sva)/PAGE_SIZE < pm->pm_stats.resident_count) {
 2179                 while (sva < eva) {
 2180                         #ifdef __powerpc64__
 2181                         if (pm != kernel_pmap &&
 2182                             user_va_to_slb_entry(pm, sva) == NULL) {
 2183                                 sva = roundup2(sva + 1, SEGMENT_LENGTH);
 2184                                 continue;
 2185                         }
 2186                         #endif
 2187                         pvo = moea64_pvo_find_va(pm, sva);
 2188                         if (pvo != NULL)
 2189                                 moea64_pvo_remove(mmu, pvo);
 2190                         sva += PAGE_SIZE;
 2191                 }
 2192         } else {
 2193                 LIST_FOREACH_SAFE(pvo, &pm->pmap_pvo, pvo_plink, tpvo) {
 2194                         if (PVO_VADDR(pvo) < sva || PVO_VADDR(pvo) >= eva)
 2195                                 continue;
 2196                         moea64_pvo_remove(mmu, pvo);
 2197                 }
 2198         }
 2199         UNLOCK_TABLE_WR();
 2200         PMAP_UNLOCK(pm);
 2201 }
 2202 
 2203 /*
 2204  * Remove physical page from all pmaps in which it resides. moea64_pvo_remove()
 2205  * will reflect changes in pte's back to the vm_page.
 2206  */
 2207 void
 2208 moea64_remove_all(mmu_t mmu, vm_page_t m)
 2209 {
 2210         struct  pvo_entry *pvo, *next_pvo;
 2211         pmap_t  pmap;
 2212 
 2213         LOCK_TABLE_WR();
 2214         LIST_FOREACH_SAFE(pvo, vm_page_to_pvoh(m), pvo_vlink, next_pvo) {
 2215                 pmap = pvo->pvo_pmap;
 2216                 PMAP_LOCK(pmap);
 2217                 moea64_pvo_remove(mmu, pvo);
 2218                 PMAP_UNLOCK(pmap);
 2219         }
 2220         UNLOCK_TABLE_WR();
 2221         if ((m->aflags & PGA_WRITEABLE) && moea64_is_modified(mmu, m))
 2222                 vm_page_dirty(m);
 2223         vm_page_aflag_clear(m, PGA_WRITEABLE);
 2224         vm_page_aflag_clear(m, PGA_EXECUTABLE);
 2225 }
 2226 
 2227 /*
 2228  * Allocate a physical page of memory directly from the phys_avail map.
 2229  * Can only be called from moea64_bootstrap before avail start and end are
 2230  * calculated.
 2231  */
 2232 vm_offset_t
 2233 moea64_bootstrap_alloc(vm_size_t size, u_int align)
 2234 {
 2235         vm_offset_t     s, e;
 2236         int             i, j;
 2237 
 2238         size = round_page(size);
 2239         for (i = 0; phys_avail[i + 1] != 0; i += 2) {
 2240                 if (align != 0)
 2241                         s = (phys_avail[i] + align - 1) & ~(align - 1);
 2242                 else
 2243                         s = phys_avail[i];
 2244                 e = s + size;
 2245 
 2246                 if (s < phys_avail[i] || e > phys_avail[i + 1])
 2247                         continue;
 2248 
 2249                 if (s + size > platform_real_maxaddr())
 2250                         continue;
 2251 
 2252                 if (s == phys_avail[i]) {
 2253                         phys_avail[i] += size;
 2254                 } else if (e == phys_avail[i + 1]) {
 2255                         phys_avail[i + 1] -= size;
 2256                 } else {
 2257                         for (j = phys_avail_count * 2; j > i; j -= 2) {
 2258                                 phys_avail[j] = phys_avail[j - 2];
 2259                                 phys_avail[j + 1] = phys_avail[j - 1];
 2260                         }
 2261 
 2262                         phys_avail[i + 3] = phys_avail[i + 1];
 2263                         phys_avail[i + 1] = s;
 2264                         phys_avail[i + 2] = e;
 2265                         phys_avail_count++;
 2266                 }
 2267 
 2268                 return (s);
 2269         }
 2270         panic("moea64_bootstrap_alloc: could not allocate memory");
 2271 }
 2272 
 2273 static int
 2274 moea64_pvo_enter(mmu_t mmu, pmap_t pm, uma_zone_t zone,
 2275     struct pvo_head *pvo_head, vm_offset_t va, vm_offset_t pa,
 2276     uint64_t pte_lo, int flags)
 2277 {
 2278         struct   pvo_entry *pvo;
 2279         uint64_t vsid;
 2280         int      first;
 2281         u_int    ptegidx;
 2282         int      i;
 2283         int      bootstrap;
 2284 
 2285         /*
 2286          * One nasty thing that can happen here is that the UMA calls to
 2287          * allocate new PVOs need to map more memory, which calls pvo_enter(),
 2288          * which calls UMA...
 2289          *
 2290          * We break the loop by detecting recursion and allocating out of
 2291          * the bootstrap pool.
 2292          */
 2293 
 2294         first = 0;
 2295         bootstrap = (flags & PVO_BOOTSTRAP);
 2296 
 2297         if (!moea64_initialized)
 2298                 bootstrap = 1;
 2299 
 2300         PMAP_LOCK_ASSERT(pm, MA_OWNED);
 2301         rw_assert(&moea64_table_lock, RA_WLOCKED);
 2302 
 2303         /*
 2304          * Compute the PTE Group index.
 2305          */
 2306         va &= ~ADDR_POFF;
 2307         vsid = va_to_vsid(pm, va);
 2308         ptegidx = va_to_pteg(vsid, va, flags & PVO_LARGE);
 2309 
 2310         /*
 2311          * Remove any existing mapping for this page.  Reuse the pvo entry if
 2312          * there is a mapping.
 2313          */
 2314         moea64_pvo_enter_calls++;
 2315 
 2316         LIST_FOREACH(pvo, &moea64_pvo_table[ptegidx], pvo_olink) {
 2317                 if (pvo->pvo_pmap == pm && PVO_VADDR(pvo) == va) {
 2318                         if ((pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN) == pa &&
 2319                             (pvo->pvo_pte.lpte.pte_lo & (LPTE_NOEXEC | LPTE_PP))
 2320                             == (pte_lo & (LPTE_NOEXEC | LPTE_PP))) {
 2321                                 if (!(pvo->pvo_pte.lpte.pte_hi & LPTE_VALID)) {
 2322                                         /* Re-insert if spilled */
 2323                                         i = MOEA64_PTE_INSERT(mmu, ptegidx,
 2324                                             &pvo->pvo_pte.lpte);
 2325                                         if (i >= 0)
 2326                                                 PVO_PTEGIDX_SET(pvo, i);
 2327                                         moea64_pte_overflow--;
 2328                                 }
 2329                                 return (0);
 2330                         }
 2331                         moea64_pvo_remove(mmu, pvo);
 2332                         break;
 2333                 }
 2334         }
 2335 
 2336         /*
 2337          * If we aren't overwriting a mapping, try to allocate.
 2338          */
 2339         if (bootstrap) {
 2340                 if (moea64_bpvo_pool_index >= BPVO_POOL_SIZE) {
 2341                         panic("moea64_enter: bpvo pool exhausted, %d, %d, %zd",
 2342                               moea64_bpvo_pool_index, BPVO_POOL_SIZE, 
 2343                               BPVO_POOL_SIZE * sizeof(struct pvo_entry));
 2344                 }
 2345                 pvo = &moea64_bpvo_pool[moea64_bpvo_pool_index];
 2346                 moea64_bpvo_pool_index++;
 2347                 bootstrap = 1;
 2348         } else {
 2349                 /*
 2350                  * Note: drop the table lock around the UMA allocation in
 2351                  * case the UMA allocator needs to manipulate the page
 2352                  * table. The mapping we are working with is already
 2353                  * protected by the PMAP lock.
 2354                  */
 2355                 pvo = uma_zalloc(zone, M_NOWAIT);
 2356         }
 2357 
 2358         if (pvo == NULL)
 2359                 return (ENOMEM);
 2360 
 2361         moea64_pvo_entries++;
 2362         pvo->pvo_vaddr = va;
 2363         pvo->pvo_vpn = (uint64_t)((va & ADDR_PIDX) >> ADDR_PIDX_SHFT)
 2364             | (vsid << 16);
 2365         pvo->pvo_pmap = pm;
 2366         LIST_INSERT_HEAD(&moea64_pvo_table[ptegidx], pvo, pvo_olink);
 2367         pvo->pvo_vaddr &= ~ADDR_POFF;
 2368 
 2369         if (flags & PVO_WIRED)
 2370                 pvo->pvo_vaddr |= PVO_WIRED;
 2371         if (pvo_head != &moea64_pvo_kunmanaged)
 2372                 pvo->pvo_vaddr |= PVO_MANAGED;
 2373         if (bootstrap)
 2374                 pvo->pvo_vaddr |= PVO_BOOTSTRAP;
 2375         if (flags & PVO_LARGE)
 2376                 pvo->pvo_vaddr |= PVO_LARGE;
 2377 
 2378         moea64_pte_create(&pvo->pvo_pte.lpte, vsid, va, 
 2379             (uint64_t)(pa) | pte_lo, flags);
 2380 
 2381         /*
 2382          * Add to pmap list
 2383          */
 2384         LIST_INSERT_HEAD(&pm->pmap_pvo, pvo, pvo_plink);
 2385 
 2386         /*
 2387          * Remember if the list was empty and therefore will be the first
 2388          * item.
 2389          */
 2390         if (LIST_FIRST(pvo_head) == NULL)
 2391                 first = 1;
 2392         LIST_INSERT_HEAD(pvo_head, pvo, pvo_vlink);
 2393 
 2394         if (pvo->pvo_vaddr & PVO_WIRED) {
 2395                 pvo->pvo_pte.lpte.pte_hi |= LPTE_WIRED;
 2396                 pm->pm_stats.wired_count++;
 2397         }
 2398         pm->pm_stats.resident_count++;
 2399 
 2400         /*
 2401          * We hope this succeeds but it isn't required.
 2402          */
 2403         i = MOEA64_PTE_INSERT(mmu, ptegidx, &pvo->pvo_pte.lpte);
 2404         if (i >= 0) {
 2405                 PVO_PTEGIDX_SET(pvo, i);
 2406         } else {
 2407                 panic("moea64_pvo_enter: overflow");
 2408                 moea64_pte_overflow++;
 2409         }
 2410 
 2411         if (pm == kernel_pmap)
 2412                 isync();
 2413 
 2414 #ifdef __powerpc64__
 2415         /*
 2416          * Make sure all our bootstrap mappings are in the SLB as soon
 2417          * as virtual memory is switched on.
 2418          */
 2419         if (!pmap_bootstrapped)
 2420                 moea64_bootstrap_slb_prefault(va, flags & PVO_LARGE);
 2421 #endif
 2422 
 2423         return (first ? ENOENT : 0);
 2424 }
 2425 
 2426 static void
 2427 moea64_pvo_remove(mmu_t mmu, struct pvo_entry *pvo)
 2428 {
 2429         struct  vm_page *pg;
 2430         uintptr_t pt;
 2431 
 2432         PMAP_LOCK_ASSERT(pvo->pvo_pmap, MA_OWNED);
 2433         rw_assert(&moea64_table_lock, RA_WLOCKED);
 2434 
 2435         /*
 2436          * If there is an active pte entry, we need to deactivate it (and
 2437          * save the ref & cfg bits).
 2438          */
 2439         pt = MOEA64_PVO_TO_PTE(mmu, pvo);
 2440         if (pt != -1) {
 2441                 MOEA64_PTE_UNSET(mmu, pt, &pvo->pvo_pte.lpte, pvo->pvo_vpn);
 2442                 PVO_PTEGIDX_CLR(pvo);
 2443         } else {
 2444                 moea64_pte_overflow--;
 2445         }
 2446 
 2447         /*
 2448          * Update our statistics.
 2449          */
 2450         pvo->pvo_pmap->pm_stats.resident_count--;
 2451         if (pvo->pvo_vaddr & PVO_WIRED)
 2452                 pvo->pvo_pmap->pm_stats.wired_count--;
 2453 
 2454         /*
 2455          * Remove this PVO from the PV and pmap lists.
 2456          */
 2457         LIST_REMOVE(pvo, pvo_vlink);
 2458         LIST_REMOVE(pvo, pvo_plink);
 2459 
 2460         /*
 2461          * Remove this from the overflow list and return it to the pool
 2462          * if we aren't going to reuse it.
 2463          */
 2464         LIST_REMOVE(pvo, pvo_olink);
 2465 
 2466         /*
 2467          * Update vm about the REF/CHG bits if the page is managed.
 2468          */
 2469         pg = PHYS_TO_VM_PAGE(pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN);
 2470 
 2471         if ((pvo->pvo_vaddr & PVO_MANAGED) == PVO_MANAGED && pg != NULL) {
 2472                 if ((pvo->pvo_pte.lpte.pte_lo & LPTE_PP) != LPTE_BR) {
 2473                         if (pvo->pvo_pte.lpte.pte_lo & LPTE_CHG)
 2474                                 vm_page_dirty(pg);
 2475                         if (pvo->pvo_pte.lpte.pte_lo & LPTE_REF)
 2476                                 vm_page_aflag_set(pg, PGA_REFERENCED);
 2477                         if (LIST_EMPTY(vm_page_to_pvoh(pg)))
 2478                                 vm_page_aflag_clear(pg, PGA_WRITEABLE);
 2479                 }
 2480                 if (LIST_EMPTY(vm_page_to_pvoh(pg)))
 2481                         vm_page_aflag_clear(pg, PGA_EXECUTABLE);
 2482         }
 2483 
 2484         moea64_pvo_entries--;
 2485         moea64_pvo_remove_calls++;
 2486 
 2487         if (!(pvo->pvo_vaddr & PVO_BOOTSTRAP))
 2488                 uma_zfree((pvo->pvo_vaddr & PVO_MANAGED) ? moea64_mpvo_zone :
 2489                     moea64_upvo_zone, pvo);
 2490 }
 2491 
 2492 static struct pvo_entry *
 2493 moea64_pvo_find_va(pmap_t pm, vm_offset_t va)
 2494 {
 2495         struct          pvo_entry *pvo;
 2496         int             ptegidx;
 2497         uint64_t        vsid;
 2498         #ifdef __powerpc64__
 2499         uint64_t        slbv;
 2500 
 2501         if (pm == kernel_pmap) {
 2502                 slbv = kernel_va_to_slbv(va);
 2503         } else {
 2504                 struct slb *slb;
 2505                 slb = user_va_to_slb_entry(pm, va);
 2506                 /* The page is not mapped if the segment isn't */
 2507                 if (slb == NULL)
 2508                         return NULL;
 2509                 slbv = slb->slbv;
 2510         }
 2511 
 2512         vsid = (slbv & SLBV_VSID_MASK) >> SLBV_VSID_SHIFT;
 2513         if (slbv & SLBV_L)
 2514                 va &= ~moea64_large_page_mask;
 2515         else
 2516                 va &= ~ADDR_POFF;
 2517         ptegidx = va_to_pteg(vsid, va, slbv & SLBV_L);
 2518         #else
 2519         va &= ~ADDR_POFF;
 2520         vsid = va_to_vsid(pm, va);
 2521         ptegidx = va_to_pteg(vsid, va, 0);
 2522         #endif
 2523 
 2524         LIST_FOREACH(pvo, &moea64_pvo_table[ptegidx], pvo_olink) {
 2525                 if (pvo->pvo_pmap == pm && PVO_VADDR(pvo) == va)
 2526                         break;
 2527         }
 2528 
 2529         return (pvo);
 2530 }
 2531 
 2532 static boolean_t
 2533 moea64_query_bit(mmu_t mmu, vm_page_t m, u_int64_t ptebit)
 2534 {
 2535         struct  pvo_entry *pvo;
 2536         uintptr_t pt;
 2537 
 2538         LOCK_TABLE_RD();
 2539         LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
 2540                 /*
 2541                  * See if we saved the bit off.  If so, return success.
 2542                  */
 2543                 if (pvo->pvo_pte.lpte.pte_lo & ptebit) {
 2544                         UNLOCK_TABLE_RD();
 2545                         return (TRUE);
 2546                 }
 2547         }
 2548 
 2549         /*
 2550          * No luck, now go through the hard part of looking at the PTEs
 2551          * themselves.  Sync so that any pending REF/CHG bits are flushed to
 2552          * the PTEs.
 2553          */
 2554         powerpc_sync();
 2555         LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
 2556 
 2557                 /*
 2558                  * See if this pvo has a valid PTE.  if so, fetch the
 2559                  * REF/CHG bits from the valid PTE.  If the appropriate
 2560                  * ptebit is set, return success.
 2561                  */
 2562                 PMAP_LOCK(pvo->pvo_pmap);
 2563                 pt = MOEA64_PVO_TO_PTE(mmu, pvo);
 2564                 if (pt != -1) {
 2565                         MOEA64_PTE_SYNCH(mmu, pt, &pvo->pvo_pte.lpte);
 2566                         if (pvo->pvo_pte.lpte.pte_lo & ptebit) {
 2567                                 PMAP_UNLOCK(pvo->pvo_pmap);
 2568                                 UNLOCK_TABLE_RD();
 2569                                 return (TRUE);
 2570                         }
 2571                 }
 2572                 PMAP_UNLOCK(pvo->pvo_pmap);
 2573         }
 2574 
 2575         UNLOCK_TABLE_RD();
 2576         return (FALSE);
 2577 }
 2578 
 2579 static u_int
 2580 moea64_clear_bit(mmu_t mmu, vm_page_t m, u_int64_t ptebit)
 2581 {
 2582         u_int   count;
 2583         struct  pvo_entry *pvo;
 2584         uintptr_t pt;
 2585 
 2586         /*
 2587          * Sync so that any pending REF/CHG bits are flushed to the PTEs (so
 2588          * we can reset the right ones).  note that since the pvo entries and
 2589          * list heads are accessed via BAT0 and are never placed in the page
 2590          * table, we don't have to worry about further accesses setting the
 2591          * REF/CHG bits.
 2592          */
 2593         powerpc_sync();
 2594 
 2595         /*
 2596          * For each pvo entry, clear the pvo's ptebit.  If this pvo has a
 2597          * valid pte clear the ptebit from the valid pte.
 2598          */
 2599         count = 0;
 2600         LOCK_TABLE_RD();
 2601         LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
 2602                 PMAP_LOCK(pvo->pvo_pmap);
 2603                 pt = MOEA64_PVO_TO_PTE(mmu, pvo);
 2604                 if (pt != -1) {
 2605                         MOEA64_PTE_SYNCH(mmu, pt, &pvo->pvo_pte.lpte);
 2606                         if (pvo->pvo_pte.lpte.pte_lo & ptebit) {
 2607                                 count++;
 2608                                 MOEA64_PTE_CLEAR(mmu, pt, &pvo->pvo_pte.lpte,
 2609                                     pvo->pvo_vpn, ptebit);
 2610                         }
 2611                 }
 2612                 pvo->pvo_pte.lpte.pte_lo &= ~ptebit;
 2613                 PMAP_UNLOCK(pvo->pvo_pmap);
 2614         }
 2615 
 2616         UNLOCK_TABLE_RD();
 2617         return (count);
 2618 }
 2619 
 2620 boolean_t
 2621 moea64_dev_direct_mapped(mmu_t mmu, vm_offset_t pa, vm_size_t size)
 2622 {
 2623         struct pvo_entry *pvo;
 2624         vm_offset_t ppa;
 2625         int error = 0;
 2626 
 2627         LOCK_TABLE_RD();
 2628         PMAP_LOCK(kernel_pmap);
 2629         for (ppa = pa & ~ADDR_POFF; ppa < pa + size; ppa += PAGE_SIZE) {
 2630                 pvo = moea64_pvo_find_va(kernel_pmap, ppa);
 2631                 if (pvo == NULL ||
 2632                     (pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN) != ppa) {
 2633                         error = EFAULT;
 2634                         break;
 2635                 }
 2636         }
 2637         UNLOCK_TABLE_RD();
 2638         PMAP_UNLOCK(kernel_pmap);
 2639 
 2640         return (error);
 2641 }
 2642 
 2643 /*
 2644  * Map a set of physical memory pages into the kernel virtual
 2645  * address space. Return a pointer to where it is mapped. This
 2646  * routine is intended to be used for mapping device memory,
 2647  * NOT real memory.
 2648  */
 2649 void *
 2650 moea64_mapdev_attr(mmu_t mmu, vm_offset_t pa, vm_size_t size, vm_memattr_t ma)
 2651 {
 2652         vm_offset_t va, tmpva, ppa, offset;
 2653 
 2654         ppa = trunc_page(pa);
 2655         offset = pa & PAGE_MASK;
 2656         size = roundup2(offset + size, PAGE_SIZE);
 2657 
 2658         va = kmem_alloc_nofault(kernel_map, size);
 2659 
 2660         if (!va)
 2661                 panic("moea64_mapdev: Couldn't alloc kernel virtual memory");
 2662 
 2663         for (tmpva = va; size > 0;) {
 2664                 moea64_kenter_attr(mmu, tmpva, ppa, ma);
 2665                 size -= PAGE_SIZE;
 2666                 tmpva += PAGE_SIZE;
 2667                 ppa += PAGE_SIZE;
 2668         }
 2669 
 2670         return ((void *)(va + offset));
 2671 }
 2672 
 2673 void *
 2674 moea64_mapdev(mmu_t mmu, vm_offset_t pa, vm_size_t size)
 2675 {
 2676 
 2677         return moea64_mapdev_attr(mmu, pa, size, VM_MEMATTR_DEFAULT);
 2678 }
 2679 
 2680 void
 2681 moea64_unmapdev(mmu_t mmu, vm_offset_t va, vm_size_t size)
 2682 {
 2683         vm_offset_t base, offset;
 2684 
 2685         base = trunc_page(va);
 2686         offset = va & PAGE_MASK;
 2687         size = roundup2(offset + size, PAGE_SIZE);
 2688 
 2689         kmem_free(kernel_map, base, size);
 2690 }
 2691 
 2692 void
 2693 moea64_sync_icache(mmu_t mmu, pmap_t pm, vm_offset_t va, vm_size_t sz)
 2694 {
 2695         struct pvo_entry *pvo;
 2696         vm_offset_t lim;
 2697         vm_paddr_t pa;
 2698         vm_size_t len;
 2699 
 2700         LOCK_TABLE_RD();
 2701         PMAP_LOCK(pm);
 2702         while (sz > 0) {
 2703                 lim = round_page(va);
 2704                 len = MIN(lim - va, sz);
 2705                 pvo = moea64_pvo_find_va(pm, va & ~ADDR_POFF);
 2706                 if (pvo != NULL && !(pvo->pvo_pte.lpte.pte_lo & LPTE_I)) {
 2707                         pa = (pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN) |
 2708                             (va & ADDR_POFF);
 2709                         moea64_syncicache(mmu, pm, va, pa, len);
 2710                 }
 2711                 va += len;
 2712                 sz -= len;
 2713         }
 2714         UNLOCK_TABLE_RD();
 2715         PMAP_UNLOCK(pm);
 2716 }

Cache object: ebfe923fdfe72fdacb2316d377e4838a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.