Index: head/sys/amd64/amd64/pmap.c =================================================================== --- head/sys/amd64/amd64/pmap.c +++ head/sys/amd64/amd64/pmap.c @@ -7444,7 +7444,7 @@ pt_entry_t *pte, PG_A, PG_G, PG_M, PG_RW, PG_V; vm_offset_t va, va_next; vm_page_t m; - boolean_t anychanged; + bool anychanged; if (advice != MADV_DONTNEED && advice != MADV_FREE) return; @@ -7463,7 +7463,7 @@ PG_M = pmap_modified_bit(pmap); PG_V = pmap_valid_bit(pmap); PG_RW = pmap_rw_bit(pmap); - anychanged = FALSE; + anychanged = false; pmap_delayed_invl_start(); PMAP_LOCK(pmap); for (; sva < eva; sva = va_next) { @@ -7505,17 +7505,25 @@ /* * Unless the page mappings are wired, remove the * mapping to a single page so that a subsequent - * access may repromote. Since the underlying page - * table page is fully populated, this removal never - * frees a page table page. + * access may repromote. Choosing the last page + * within the address range [sva, min(va_next, eva)) + * generally results in more repromotions. Since the + * underlying page table page is fully populated, this + * removal never frees a page table page. */ if ((oldpde & PG_W) == 0) { - pte = pmap_pde_to_pte(pde, sva); + va = eva; + if (va > va_next) + va = va_next; + va -= PAGE_SIZE; + KASSERT(va >= sva, + ("pmap_advise: no address gap")); + pte = pmap_pde_to_pte(pde, va); KASSERT((*pte & PG_V) != 0, ("pmap_advise: invalid PTE")); - pmap_remove_pte(pmap, pte, sva, *pde, NULL, + pmap_remove_pte(pmap, pte, va, *pde, NULL, &lock); - anychanged = TRUE; + anychanged = true; } if (lock != NULL) rw_wunlock(lock); @@ -7547,7 +7555,7 @@ if (va == va_next) va = sva; } else - anychanged = TRUE; + anychanged = true; continue; maybe_invlrng: if (va != va_next) { Index: head/sys/arm64/arm64/pmap.c =================================================================== --- head/sys/arm64/arm64/pmap.c +++ head/sys/arm64/arm64/pmap.c @@ -4888,15 +4888,23 @@ /* * Unless the page mappings are wired, remove the * mapping to a single page so that a subsequent - * access may repromote. Since the underlying page - * table page is fully populated, this removal never - * frees a page table page. + * access may repromote. Choosing the last page + * within the address range [sva, min(va_next, eva)) + * generally results in more repromotions. Since the + * underlying page table page is fully populated, this + * removal never frees a page table page. */ if ((oldl2 & ATTR_SW_WIRED) == 0) { - l3 = pmap_l2_to_l3(l2, sva); + va = eva; + if (va > va_next) + va = va_next; + va -= PAGE_SIZE; + KASSERT(va >= sva, + ("pmap_advise: no address gap")); + l3 = pmap_l2_to_l3(l2, va); KASSERT(pmap_load(l3) != 0, ("pmap_advise: invalid PTE")); - pmap_remove_l3(pmap, l3, sva, pmap_load(l2), + pmap_remove_l3(pmap, l3, va, pmap_load(l2), NULL, &lock); } if (lock != NULL) Index: head/sys/i386/i386/pmap.c =================================================================== --- head/sys/i386/i386/pmap.c +++ head/sys/i386/i386/pmap.c @@ -5167,19 +5167,19 @@ pt_entry_t *pte; vm_offset_t va, pdnxt; vm_page_t m; - boolean_t anychanged, pv_lists_locked; + bool anychanged, pv_lists_locked; if (advice != MADV_DONTNEED && advice != MADV_FREE) return; if (pmap_is_current(pmap)) - pv_lists_locked = FALSE; + pv_lists_locked = false; else { - pv_lists_locked = TRUE; + pv_lists_locked = true; resume: rw_wlock(&pvh_global_lock); sched_pin(); } - anychanged = FALSE; + anychanged = false; PMAP_LOCK(pmap); for (; sva < eva; sva = pdnxt) { pdnxt = (sva + NBPDR) & ~PDRMASK; @@ -5193,7 +5193,7 @@ if ((oldpde & PG_MANAGED) == 0) continue; if (!pv_lists_locked) { - pv_lists_locked = TRUE; + pv_lists_locked = true; if (!rw_try_wlock(&pvh_global_lock)) { if (anychanged) pmap_invalidate_all_int(pmap); @@ -5212,16 +5212,24 @@ /* * Unless the page mappings are wired, remove the * mapping to a single page so that a subsequent - * access may repromote. Since the underlying page - * table page is fully populated, this removal never - * frees a page table page. + * access may repromote. Choosing the last page + * within the address range [sva, min(pdnxt, eva)) + * generally results in more repromotions. Since the + * underlying page table page is fully populated, this + * removal never frees a page table page. */ if ((oldpde & PG_W) == 0) { - pte = pmap_pte_quick(pmap, sva); + va = eva; + if (va > pdnxt) + va = pdnxt; + va -= PAGE_SIZE; + KASSERT(va >= sva, + ("pmap_advise: no address gap")); + pte = pmap_pte_quick(pmap, va); KASSERT((*pte & PG_V) != 0, ("pmap_advise: invalid PTE")); - pmap_remove_pte(pmap, pte, sva, NULL); - anychanged = TRUE; + pmap_remove_pte(pmap, pte, va, NULL); + anychanged = true; } } if (pdnxt > eva) @@ -5250,7 +5258,7 @@ if (va == pdnxt) va = sva; } else - anychanged = TRUE; + anychanged = true; continue; maybe_invlrng: if (va != pdnxt) {