Changeset View
Changeset View
Standalone View
Standalone View
head/sys/i386/i386/pmap.c
Show First 20 Lines • Show All 5,161 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
__CONCAT(PMTYPE, advise)(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, | __CONCAT(PMTYPE, advise)(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, | ||||
int advice) | int advice) | ||||
{ | { | ||||
pd_entry_t oldpde, *pde; | pd_entry_t oldpde, *pde; | ||||
pt_entry_t *pte; | pt_entry_t *pte; | ||||
vm_offset_t va, pdnxt; | vm_offset_t va, pdnxt; | ||||
vm_page_t m; | vm_page_t m; | ||||
boolean_t anychanged, pv_lists_locked; | bool anychanged, pv_lists_locked; | ||||
if (advice != MADV_DONTNEED && advice != MADV_FREE) | if (advice != MADV_DONTNEED && advice != MADV_FREE) | ||||
return; | return; | ||||
if (pmap_is_current(pmap)) | if (pmap_is_current(pmap)) | ||||
pv_lists_locked = FALSE; | pv_lists_locked = false; | ||||
else { | else { | ||||
pv_lists_locked = TRUE; | pv_lists_locked = true; | ||||
resume: | resume: | ||||
rw_wlock(&pvh_global_lock); | rw_wlock(&pvh_global_lock); | ||||
sched_pin(); | sched_pin(); | ||||
} | } | ||||
anychanged = FALSE; | anychanged = false; | ||||
PMAP_LOCK(pmap); | PMAP_LOCK(pmap); | ||||
for (; sva < eva; sva = pdnxt) { | for (; sva < eva; sva = pdnxt) { | ||||
pdnxt = (sva + NBPDR) & ~PDRMASK; | pdnxt = (sva + NBPDR) & ~PDRMASK; | ||||
if (pdnxt < sva) | if (pdnxt < sva) | ||||
pdnxt = eva; | pdnxt = eva; | ||||
pde = pmap_pde(pmap, sva); | pde = pmap_pde(pmap, sva); | ||||
oldpde = *pde; | oldpde = *pde; | ||||
if ((oldpde & PG_V) == 0) | if ((oldpde & PG_V) == 0) | ||||
continue; | continue; | ||||
else if ((oldpde & PG_PS) != 0) { | else if ((oldpde & PG_PS) != 0) { | ||||
if ((oldpde & PG_MANAGED) == 0) | if ((oldpde & PG_MANAGED) == 0) | ||||
continue; | continue; | ||||
if (!pv_lists_locked) { | if (!pv_lists_locked) { | ||||
pv_lists_locked = TRUE; | pv_lists_locked = true; | ||||
if (!rw_try_wlock(&pvh_global_lock)) { | if (!rw_try_wlock(&pvh_global_lock)) { | ||||
if (anychanged) | if (anychanged) | ||||
pmap_invalidate_all_int(pmap); | pmap_invalidate_all_int(pmap); | ||||
PMAP_UNLOCK(pmap); | PMAP_UNLOCK(pmap); | ||||
goto resume; | goto resume; | ||||
} | } | ||||
sched_pin(); | sched_pin(); | ||||
} | } | ||||
if (!pmap_demote_pde(pmap, pde, sva)) { | if (!pmap_demote_pde(pmap, pde, sva)) { | ||||
/* | /* | ||||
* The large page mapping was destroyed. | * The large page mapping was destroyed. | ||||
*/ | */ | ||||
continue; | continue; | ||||
} | } | ||||
/* | /* | ||||
* Unless the page mappings are wired, remove the | * Unless the page mappings are wired, remove the | ||||
* mapping to a single page so that a subsequent | * mapping to a single page so that a subsequent | ||||
* access may repromote. Since the underlying page | * access may repromote. Choosing the last page | ||||
* table page is fully populated, this removal never | * within the address range [sva, min(pdnxt, eva)) | ||||
* frees a page table page. | * 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) { | 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, | KASSERT((*pte & PG_V) != 0, | ||||
("pmap_advise: invalid PTE")); | ("pmap_advise: invalid PTE")); | ||||
pmap_remove_pte(pmap, pte, sva, NULL); | pmap_remove_pte(pmap, pte, va, NULL); | ||||
anychanged = TRUE; | anychanged = true; | ||||
} | } | ||||
} | } | ||||
if (pdnxt > eva) | if (pdnxt > eva) | ||||
pdnxt = eva; | pdnxt = eva; | ||||
va = pdnxt; | va = pdnxt; | ||||
for (pte = pmap_pte_quick(pmap, sva); sva != pdnxt; pte++, | for (pte = pmap_pte_quick(pmap, sva); sva != pdnxt; pte++, | ||||
sva += PAGE_SIZE) { | sva += PAGE_SIZE) { | ||||
if ((*pte & (PG_MANAGED | PG_V)) != (PG_MANAGED | PG_V)) | if ((*pte & (PG_MANAGED | PG_V)) != (PG_MANAGED | PG_V)) | ||||
Show All 12 Lines | for (pte = pmap_pte_quick(pmap, sva); sva != pdnxt; pte++, | ||||
} else if ((*pte & PG_A) != 0) | } else if ((*pte & PG_A) != 0) | ||||
atomic_clear_int((u_int *)pte, PG_A); | atomic_clear_int((u_int *)pte, PG_A); | ||||
else | else | ||||
goto maybe_invlrng; | goto maybe_invlrng; | ||||
if ((*pte & PG_G) != 0) { | if ((*pte & PG_G) != 0) { | ||||
if (va == pdnxt) | if (va == pdnxt) | ||||
va = sva; | va = sva; | ||||
} else | } else | ||||
anychanged = TRUE; | anychanged = true; | ||||
continue; | continue; | ||||
maybe_invlrng: | maybe_invlrng: | ||||
if (va != pdnxt) { | if (va != pdnxt) { | ||||
pmap_invalidate_range_int(pmap, va, sva); | pmap_invalidate_range_int(pmap, va, sva); | ||||
va = pdnxt; | va = pdnxt; | ||||
} | } | ||||
} | } | ||||
if (va != pdnxt) | if (va != pdnxt) | ||||
▲ Show 20 Lines • Show All 893 Lines • Show Last 20 Lines |