| 2164 | } |
| 2165 | |
| 2166 | static vm_page_t |
| 2167 | pmap_allocpte(pmap_t pmap, vm_offset_t va, u_int flags) |
| 2168 | { |
| 2169 | u_int ptepindex; |
| 2170 | pd_entry_t ptepa; |
| 2171 | vm_page_t m; |
| 2172 | |
| 2173 | /* |
| 2174 | * Calculate pagetable page index |
| 2175 | */ |
| 2176 | ptepindex = va >> PDRSHIFT; |
| 2177 | retry: |
| 2178 | /* |
| 2179 | * Get the page directory entry |
| 2180 | */ |
| 2181 | ptepa = pmap->pm_pdir[ptepindex]; |
| 2182 | |
| 2183 | /* |
| 2184 | * This supports switching from a 4MB page to a |
| 2185 | * normal 4K page. |
| 2186 | */ |
| 2187 | if (ptepa & PG_PS) { |
| 2188 | (void)pmap_demote_pde(pmap, &pmap->pm_pdir[ptepindex], va); |
| 2189 | ptepa = pmap->pm_pdir[ptepindex]; |
| 2190 | } |
| 2191 | |
| 2192 | /* |
| 2193 | * If the page table page is mapped, we just increment the |
| 2194 | * hold count, and activate it. |
| 2195 | */ |
| 2196 | if (ptepa) { |
| 2197 | m = PHYS_TO_VM_PAGE(ptepa & PG_FRAME); |
| 2198 | m->ref_count++; |
| 2199 | } else { |
| 2200 | /* |
| 2201 | * Here if the pte page isn't mapped, or if it has |
| 2202 | * been deallocated. |
| 2203 | */ |
| 2204 | m = _pmap_allocpte(pmap, ptepindex, flags); |
| 2205 | if (m == NULL && (flags & PMAP_ENTER_NOSLEEP) == 0) |
| 2206 | goto retry; |
| 2207 | } |
| 2208 | return (m); |
| 2209 | } |
| 2210 | |
| 2211 | /*************************************************** |
| 2212 | * Pmap allocation/deallocation routines. |
no test coverage detected