* We are in a serious low memory condition. Resort to * drastic measures to free some pages so we can allocate * another pv entry chunk. * * Returns NULL if PV entries were reclaimed from the specified pmap. * * We do not, however, unmap 2mpages because subsequent accesses will * allocate per-page pv entries until repromotion occurs, thereby * exacerbating the shortage of free pv entries.
| 2287 | * exacerbating the shortage of free pv entries. |
| 2288 | */ |
| 2289 | static vm_page_t |
| 2290 | reclaim_pv_chunk(pmap_t locked_pmap, struct rwlock **lockp) |
| 2291 | { |
| 2292 | struct pv_chunk *pc, *pc_marker, *pc_marker_end; |
| 2293 | struct pv_chunk_header pc_marker_b, pc_marker_end_b; |
| 2294 | struct md_page *pvh; |
| 2295 | pd_entry_t *pde; |
| 2296 | pmap_t next_pmap, pmap; |
| 2297 | pt_entry_t *pte, tpte; |
| 2298 | pv_entry_t pv; |
| 2299 | vm_offset_t va; |
| 2300 | vm_page_t m, m_pc; |
| 2301 | struct spglist free; |
| 2302 | uint64_t inuse; |
| 2303 | int bit, field, freed, lvl; |
| 2304 | static int active_reclaims = 0; |
| 2305 | |
| 2306 | PMAP_LOCK_ASSERT(locked_pmap, MA_OWNED); |
| 2307 | KASSERT(lockp != NULL, ("reclaim_pv_chunk: lockp is NULL")); |
| 2308 | |
| 2309 | pmap = NULL; |
| 2310 | m_pc = NULL; |
| 2311 | SLIST_INIT(&free); |
| 2312 | bzero(&pc_marker_b, sizeof(pc_marker_b)); |
| 2313 | bzero(&pc_marker_end_b, sizeof(pc_marker_end_b)); |
| 2314 | pc_marker = (struct pv_chunk *)&pc_marker_b; |
| 2315 | pc_marker_end = (struct pv_chunk *)&pc_marker_end_b; |
| 2316 | |
| 2317 | mtx_lock(&pv_chunks_mutex); |
| 2318 | active_reclaims++; |
| 2319 | TAILQ_INSERT_HEAD(&pv_chunks, pc_marker, pc_lru); |
| 2320 | TAILQ_INSERT_TAIL(&pv_chunks, pc_marker_end, pc_lru); |
| 2321 | while ((pc = TAILQ_NEXT(pc_marker, pc_lru)) != pc_marker_end && |
| 2322 | SLIST_EMPTY(&free)) { |
| 2323 | next_pmap = pc->pc_pmap; |
| 2324 | if (next_pmap == NULL) { |
| 2325 | /* |
| 2326 | * The next chunk is a marker. However, it is |
| 2327 | * not our marker, so active_reclaims must be |
| 2328 | * > 1. Consequently, the next_chunk code |
| 2329 | * will not rotate the pv_chunks list. |
| 2330 | */ |
| 2331 | goto next_chunk; |
| 2332 | } |
| 2333 | mtx_unlock(&pv_chunks_mutex); |
| 2334 | |
| 2335 | /* |
| 2336 | * A pv_chunk can only be removed from the pc_lru list |
| 2337 | * when both pv_chunks_mutex is owned and the |
| 2338 | * corresponding pmap is locked. |
| 2339 | */ |
| 2340 | if (pmap != next_pmap) { |
| 2341 | if (pmap != NULL && pmap != locked_pmap) |
| 2342 | PMAP_UNLOCK(pmap); |
| 2343 | pmap = next_pmap; |
| 2344 | /* Avoid deadlock and lock recursion. */ |
| 2345 | if (pmap > locked_pmap) { |
| 2346 | RELEASE_PV_LIST_LOCK(lockp); |
no test coverage detected