* Insert the given physical page (p) at * the specified virtual address (v) in the * target physical map with the protection requested. * * If specified, the page will be wired down, meaning * that the related pte can not be reclaimed. * * NB: This is the only routine which MAY NOT lazy-evaluate * or lose information. That is, this routine must actually * insert this page into the given
| 2114 | * insert this page into the given map NOW. |
| 2115 | */ |
| 2116 | int |
| 2117 | pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, |
| 2118 | u_int flags, int8_t psind __unused) |
| 2119 | { |
| 2120 | vm_paddr_t pa, opa; |
| 2121 | pt_entry_t *pte; |
| 2122 | pt_entry_t origpte, newpte; |
| 2123 | pv_entry_t pv; |
| 2124 | vm_page_t mpte, om; |
| 2125 | |
| 2126 | va &= ~PAGE_MASK; |
| 2127 | KASSERT(va <= VM_MAX_KERNEL_ADDRESS, ("pmap_enter: toobig")); |
| 2128 | KASSERT((m->oflags & VPO_UNMANAGED) != 0 || va < kmi.clean_sva || |
| 2129 | va >= kmi.clean_eva, |
| 2130 | ("pmap_enter: managed mapping within the clean submap")); |
| 2131 | if ((m->oflags & VPO_UNMANAGED) == 0) |
| 2132 | VM_PAGE_OBJECT_BUSY_ASSERT(m); |
| 2133 | pa = VM_PAGE_TO_PHYS(m); |
| 2134 | newpte = TLBLO_PA_TO_PFN(pa) | init_pte_prot(m, flags, prot); |
| 2135 | if ((flags & PMAP_ENTER_WIRED) != 0) |
| 2136 | newpte |= PTE_W; |
| 2137 | if (is_kernel_pmap(pmap)) |
| 2138 | newpte |= PTE_G; |
| 2139 | PMAP_PTE_SET_CACHE_BITS(newpte, pa, m); |
| 2140 | if ((m->oflags & VPO_UNMANAGED) == 0) |
| 2141 | newpte |= PTE_MANAGED; |
| 2142 | |
| 2143 | mpte = NULL; |
| 2144 | |
| 2145 | rw_wlock(&pvh_global_lock); |
| 2146 | PMAP_LOCK(pmap); |
| 2147 | |
| 2148 | /* |
| 2149 | * In the case that a page table page is not resident, we are |
| 2150 | * creating it here. |
| 2151 | */ |
| 2152 | if (va < VM_MAXUSER_ADDRESS) { |
| 2153 | mpte = pmap_allocpte(pmap, va, flags); |
| 2154 | if (mpte == NULL) { |
| 2155 | KASSERT((flags & PMAP_ENTER_NOSLEEP) != 0, |
| 2156 | ("pmap_allocpte failed with sleep allowed")); |
| 2157 | rw_wunlock(&pvh_global_lock); |
| 2158 | PMAP_UNLOCK(pmap); |
| 2159 | return (KERN_RESOURCE_SHORTAGE); |
| 2160 | } |
| 2161 | } |
| 2162 | pte = pmap_pte(pmap, va); |
| 2163 | |
| 2164 | /* |
| 2165 | * Page Directory table entry not valid, we need a new PT page |
| 2166 | */ |
| 2167 | if (pte == NULL) { |
| 2168 | panic("pmap_enter: invalid page directory, pdir=%p, va=%p", |
| 2169 | (void *)pmap->pm_segtab, (void *)va); |
| 2170 | } |
| 2171 | |
| 2172 | origpte = *pte; |
| 2173 | KASSERT(!pte_test(&origpte, PTE_D | PTE_RO | PTE_V), |
no test coverage detected