Changeset View
Changeset View
Standalone View
Standalone View
head/sys/amd64/amd64/pmap.c
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show First 20 Lines • Show All 7,438 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
struct rwlock *lock; | struct rwlock *lock; | ||||
pml4_entry_t *pml4e; | pml4_entry_t *pml4e; | ||||
pdp_entry_t *pdpe; | pdp_entry_t *pdpe; | ||||
pd_entry_t oldpde, *pde; | pd_entry_t oldpde, *pde; | ||||
pt_entry_t *pte, PG_A, PG_G, PG_M, PG_RW, PG_V; | pt_entry_t *pte, PG_A, PG_G, PG_M, PG_RW, PG_V; | ||||
vm_offset_t va, va_next; | vm_offset_t va, va_next; | ||||
vm_page_t m; | vm_page_t m; | ||||
boolean_t anychanged; | bool anychanged; | ||||
if (advice != MADV_DONTNEED && advice != MADV_FREE) | if (advice != MADV_DONTNEED && advice != MADV_FREE) | ||||
return; | return; | ||||
/* | /* | ||||
* A/D bit emulation requires an alternate code path when clearing | * A/D bit emulation requires an alternate code path when clearing | ||||
* the modified and accessed bits below. Since this function is | * the modified and accessed bits below. Since this function is | ||||
* advisory in nature we skip it entirely for pmaps that require | * advisory in nature we skip it entirely for pmaps that require | ||||
* A/D bit emulation. | * A/D bit emulation. | ||||
*/ | */ | ||||
if (pmap_emulate_ad_bits(pmap)) | if (pmap_emulate_ad_bits(pmap)) | ||||
return; | return; | ||||
PG_A = pmap_accessed_bit(pmap); | PG_A = pmap_accessed_bit(pmap); | ||||
PG_G = pmap_global_bit(pmap); | PG_G = pmap_global_bit(pmap); | ||||
PG_M = pmap_modified_bit(pmap); | PG_M = pmap_modified_bit(pmap); | ||||
PG_V = pmap_valid_bit(pmap); | PG_V = pmap_valid_bit(pmap); | ||||
PG_RW = pmap_rw_bit(pmap); | PG_RW = pmap_rw_bit(pmap); | ||||
anychanged = FALSE; | anychanged = false; | ||||
pmap_delayed_invl_start(); | pmap_delayed_invl_start(); | ||||
PMAP_LOCK(pmap); | PMAP_LOCK(pmap); | ||||
for (; sva < eva; sva = va_next) { | for (; sva < eva; sva = va_next) { | ||||
pml4e = pmap_pml4e(pmap, sva); | pml4e = pmap_pml4e(pmap, sva); | ||||
if ((*pml4e & PG_V) == 0) { | if ((*pml4e & PG_V) == 0) { | ||||
va_next = (sva + NBPML4) & ~PML4MASK; | va_next = (sva + NBPML4) & ~PML4MASK; | ||||
if (va_next < sva) | if (va_next < sva) | ||||
va_next = eva; | va_next = eva; | ||||
Show All 25 Lines | else if ((oldpde & PG_PS) != 0) { | ||||
* 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(va_next, 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_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, | KASSERT((*pte & PG_V) != 0, | ||||
("pmap_advise: invalid PTE")); | ("pmap_advise: invalid PTE")); | ||||
pmap_remove_pte(pmap, pte, sva, *pde, NULL, | pmap_remove_pte(pmap, pte, va, *pde, NULL, | ||||
&lock); | &lock); | ||||
anychanged = TRUE; | anychanged = true; | ||||
} | } | ||||
if (lock != NULL) | if (lock != NULL) | ||||
rw_wunlock(lock); | rw_wunlock(lock); | ||||
} | } | ||||
if (va_next > eva) | if (va_next > eva) | ||||
va_next = eva; | va_next = eva; | ||||
va = va_next; | va = va_next; | ||||
for (pte = pmap_pde_to_pte(pde, sva); sva != va_next; pte++, | for (pte = pmap_pde_to_pte(pde, sva); sva != va_next; pte++, | ||||
Show All 15 Lines | for (pte = pmap_pde_to_pte(pde, sva); sva != va_next; pte++, | ||||
atomic_clear_long(pte, PG_A); | atomic_clear_long(pte, PG_A); | ||||
else | else | ||||
goto maybe_invlrng; | goto maybe_invlrng; | ||||
if ((*pte & PG_G) != 0) { | if ((*pte & PG_G) != 0) { | ||||
if (va == va_next) | if (va == va_next) | ||||
va = sva; | va = sva; | ||||
} else | } else | ||||
anychanged = TRUE; | anychanged = true; | ||||
continue; | continue; | ||||
maybe_invlrng: | maybe_invlrng: | ||||
if (va != va_next) { | if (va != va_next) { | ||||
pmap_invalidate_range(pmap, va, sva); | pmap_invalidate_range(pmap, va, sva); | ||||
va = va_next; | va = va_next; | ||||
} | } | ||||
} | } | ||||
if (va != va_next) | if (va != va_next) | ||||
▲ Show 20 Lines • Show All 2,381 Lines • Show Last 20 Lines |