* Apply the given advice to the specified range of addresses within the * given pmap. Depending on the advice, clear the referenced and/or * modified flags in each mapping and set the mapped page's dirty field. */
| 5576 | * modified flags in each mapping and set the mapped page's dirty field. |
| 5577 | */ |
| 5578 | void |
| 5579 | pmap_advise(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, int advice) |
| 5580 | { |
| 5581 | pt1_entry_t *pte1p, opte1; |
| 5582 | pt2_entry_t *pte2p, pte2; |
| 5583 | vm_offset_t pdnxt; |
| 5584 | vm_page_t m; |
| 5585 | boolean_t pv_lists_locked; |
| 5586 | |
| 5587 | if (advice != MADV_DONTNEED && advice != MADV_FREE) |
| 5588 | return; |
| 5589 | if (pmap_is_current(pmap)) |
| 5590 | pv_lists_locked = FALSE; |
| 5591 | else { |
| 5592 | pv_lists_locked = TRUE; |
| 5593 | resume: |
| 5594 | rw_wlock(&pvh_global_lock); |
| 5595 | sched_pin(); |
| 5596 | } |
| 5597 | PMAP_LOCK(pmap); |
| 5598 | for (; sva < eva; sva = pdnxt) { |
| 5599 | pdnxt = pte1_trunc(sva + PTE1_SIZE); |
| 5600 | if (pdnxt < sva) |
| 5601 | pdnxt = eva; |
| 5602 | pte1p = pmap_pte1(pmap, sva); |
| 5603 | opte1 = pte1_load(pte1p); |
| 5604 | if (!pte1_is_valid(opte1)) /* XXX */ |
| 5605 | continue; |
| 5606 | else if (pte1_is_section(opte1)) { |
| 5607 | if (!pte1_is_managed(opte1)) |
| 5608 | continue; |
| 5609 | if (!pv_lists_locked) { |
| 5610 | pv_lists_locked = TRUE; |
| 5611 | if (!rw_try_wlock(&pvh_global_lock)) { |
| 5612 | PMAP_UNLOCK(pmap); |
| 5613 | goto resume; |
| 5614 | } |
| 5615 | sched_pin(); |
| 5616 | } |
| 5617 | if (!pmap_demote_pte1(pmap, pte1p, sva)) { |
| 5618 | /* |
| 5619 | * The large page mapping was destroyed. |
| 5620 | */ |
| 5621 | continue; |
| 5622 | } |
| 5623 | |
| 5624 | /* |
| 5625 | * Unless the page mappings are wired, remove the |
| 5626 | * mapping to a single page so that a subsequent |
| 5627 | * access may repromote. Since the underlying L2 page |
| 5628 | * table is fully populated, this removal never |
| 5629 | * frees a L2 page table page. |
| 5630 | */ |
| 5631 | if (!pte1_is_wired(opte1)) { |
| 5632 | pte2p = pmap_pte2_quick(pmap, sva); |
| 5633 | KASSERT(pte2_is_valid(pte2_load(pte2p)), |
| 5634 | ("%s: invalid PTE2", __func__)); |
| 5635 | pmap_remove_pte2(pmap, pte2p, sva, NULL); |
nothing calls this directly
no test coverage detected