* pmap_ts_referenced: * * Return a count of reference bits for a page, clearing those bits. * It is not necessary for every reference bit to be cleared, but it * is necessary that 0 only be returned when there are truly no * reference bits set. * * As an optimization, update the page's dirty field if a modified bit is * found while counting reference bits. This opportunistic update can be
| 5301 | * to pmap_is_modified(). |
| 5302 | */ |
| 5303 | int |
| 5304 | pmap_ts_referenced(vm_page_t m) |
| 5305 | { |
| 5306 | struct md_page *pvh; |
| 5307 | pv_entry_t pv, pvf; |
| 5308 | pmap_t pmap; |
| 5309 | pt1_entry_t *pte1p, opte1; |
| 5310 | pt2_entry_t *pte2p, opte2; |
| 5311 | vm_paddr_t pa; |
| 5312 | int rtval = 0; |
| 5313 | |
| 5314 | KASSERT((m->oflags & VPO_UNMANAGED) == 0, |
| 5315 | ("%s: page %p is not managed", __func__, m)); |
| 5316 | pa = VM_PAGE_TO_PHYS(m); |
| 5317 | pvh = pa_to_pvh(pa); |
| 5318 | rw_wlock(&pvh_global_lock); |
| 5319 | sched_pin(); |
| 5320 | if ((m->flags & PG_FICTITIOUS) != 0 || |
| 5321 | (pvf = TAILQ_FIRST(&pvh->pv_list)) == NULL) |
| 5322 | goto small_mappings; |
| 5323 | pv = pvf; |
| 5324 | do { |
| 5325 | pmap = PV_PMAP(pv); |
| 5326 | PMAP_LOCK(pmap); |
| 5327 | pte1p = pmap_pte1(pmap, pv->pv_va); |
| 5328 | opte1 = pte1_load(pte1p); |
| 5329 | if (pte1_is_dirty(opte1)) { |
| 5330 | /* |
| 5331 | * Although "opte1" is mapping a 1MB page, because |
| 5332 | * this function is called at a 4KB page granularity, |
| 5333 | * we only update the 4KB page under test. |
| 5334 | */ |
| 5335 | vm_page_dirty(m); |
| 5336 | } |
| 5337 | if ((opte1 & PTE1_A) != 0) { |
| 5338 | /* |
| 5339 | * Since this reference bit is shared by 256 4KB pages, |
| 5340 | * it should not be cleared every time it is tested. |
| 5341 | * Apply a simple "hash" function on the physical page |
| 5342 | * number, the virtual section number, and the pmap |
| 5343 | * address to select one 4KB page out of the 256 |
| 5344 | * on which testing the reference bit will result |
| 5345 | * in clearing that bit. This function is designed |
| 5346 | * to avoid the selection of the same 4KB page |
| 5347 | * for every 1MB page mapping. |
| 5348 | * |
| 5349 | * On demotion, a mapping that hasn't been referenced |
| 5350 | * is simply destroyed. To avoid the possibility of a |
| 5351 | * subsequent page fault on a demoted wired mapping, |
| 5352 | * always leave its reference bit set. Moreover, |
| 5353 | * since the section is wired, the current state of |
| 5354 | * its reference bit won't affect page replacement. |
| 5355 | */ |
| 5356 | if ((((pa >> PAGE_SHIFT) ^ (pv->pv_va >> PTE1_SHIFT) ^ |
| 5357 | (uintptr_t)pmap) & (NPTE2_IN_PG - 1)) == 0 && |
| 5358 | !pte1_is_wired(opte1)) { |
| 5359 | pte1_clear_bit(pte1p, PTE1_A); |
| 5360 | pmap_tlb_flush(pmap, pv->pv_va); |
nothing calls this directly
no test coverage detected