Changeset View
Changeset View
Standalone View
Standalone View
sys/i386/i386/pmap.c
Show First 20 Lines • Show All 1,694 Lines • ▼ Show 20 Lines | while (count-- > 0) { | ||||
va += PAGE_SIZE; | va += PAGE_SIZE; | ||||
} | } | ||||
pmap_invalidate_range(kernel_pmap, sva, va); | pmap_invalidate_range(kernel_pmap, sva, va); | ||||
} | } | ||||
/*************************************************** | /*************************************************** | ||||
* Page table page management routines..... | * Page table page management routines..... | ||||
***************************************************/ | ***************************************************/ | ||||
static __inline void | |||||
pmap_free_zero_pages(struct spglist *free) | |||||
{ | |||||
vm_page_t m; | |||||
int count; | |||||
for (count = 0; (m = SLIST_FIRST(free)) != NULL; count++) { | |||||
SLIST_REMOVE_HEAD(free, plinks.s.ss); | |||||
/* Preserve the page's PG_ZERO setting. */ | |||||
vm_page_free_toq(m); | |||||
} | |||||
atomic_subtract_int(&vm_cnt.v_wire_count, count); | |||||
} | |||||
/* | /* | ||||
* Schedule the specified unused page table page to be freed. Specifically, | * Schedule the specified unused page table page to be freed. Specifically, | ||||
* add the page to the specified list of pages that will be released to the | * add the page to the specified list of pages that will be released to the | ||||
* physical memory manager after the TLB has been updated. | * physical memory manager after the TLB has been updated. | ||||
*/ | */ | ||||
static __inline void | static __inline void | ||||
pmap_add_delayed_free_list(vm_page_t m, struct spglist *free, | pmap_add_delayed_free_list(vm_page_t m, struct spglist *free, | ||||
boolean_t set_PG_ZERO) | boolean_t set_PG_ZERO) | ||||
▲ Show 20 Lines • Show All 585 Lines • ▼ Show 20 Lines | if (pmap != locked_pmap) | ||||
PMAP_UNLOCK(pmap); | PMAP_UNLOCK(pmap); | ||||
} | } | ||||
if (m_pc == NULL && pv_vafree != 0 && SLIST_EMPTY(&free)) { | if (m_pc == NULL && pv_vafree != 0 && SLIST_EMPTY(&free)) { | ||||
m_pc = SLIST_FIRST(&free); | m_pc = SLIST_FIRST(&free); | ||||
SLIST_REMOVE_HEAD(&free, plinks.s.ss); | SLIST_REMOVE_HEAD(&free, plinks.s.ss); | ||||
/* Recycle a freed page table page. */ | /* Recycle a freed page table page. */ | ||||
m_pc->wire_count = 1; | m_pc->wire_count = 1; | ||||
} | } | ||||
pmap_free_zero_pages(&free); | vm_page_free_zero_pages(&free, true); | ||||
return (m_pc); | return (m_pc); | ||||
} | } | ||||
/* | /* | ||||
* free the pv_entry back to the free list | * free the pv_entry back to the free list | ||||
*/ | */ | ||||
static void | static void | ||||
free_pv_entry(pmap_t pmap, pv_entry_t pv) | free_pv_entry(pmap_t pmap, pv_entry_t pv) | ||||
▲ Show 20 Lines • Show All 333 Lines • ▼ Show 20 Lines | if ((oldpde & PG_A) == 0 || (mpte = pmap_remove_pt_page(pmap, va)) == | ||||
if ((oldpde & PG_A) == 0 || (mpte = vm_page_alloc(NULL, | if ((oldpde & PG_A) == 0 || (mpte = vm_page_alloc(NULL, | ||||
va >> PDRSHIFT, VM_ALLOC_NOOBJ | VM_ALLOC_NORMAL | | va >> PDRSHIFT, VM_ALLOC_NOOBJ | VM_ALLOC_NORMAL | | ||||
VM_ALLOC_WIRED)) == NULL) { | VM_ALLOC_WIRED)) == NULL) { | ||||
SLIST_INIT(&free); | SLIST_INIT(&free); | ||||
sva = trunc_4mpage(va); | sva = trunc_4mpage(va); | ||||
pmap_remove_pde(pmap, pde, sva, &free); | pmap_remove_pde(pmap, pde, sva, &free); | ||||
if ((oldpde & PG_G) == 0) | if ((oldpde & PG_G) == 0) | ||||
pmap_invalidate_pde_page(pmap, sva, oldpde); | pmap_invalidate_pde_page(pmap, sva, oldpde); | ||||
pmap_free_zero_pages(&free); | vm_page_free_zero_pages(&free, true); | ||||
CTR2(KTR_PMAP, "pmap_demote_pde: failure for va %#x" | CTR2(KTR_PMAP, "pmap_demote_pde: failure for va %#x" | ||||
" in pmap %p", va, pmap); | " in pmap %p", va, pmap); | ||||
return (FALSE); | return (FALSE); | ||||
} | } | ||||
if (va < VM_MAXUSER_ADDRESS) | if (va < VM_MAXUSER_ADDRESS) | ||||
pmap->pm_stats.resident_count++; | pmap->pm_stats.resident_count++; | ||||
} | } | ||||
mptepa = VM_PAGE_TO_PHYS(mpte); | mptepa = VM_PAGE_TO_PHYS(mpte); | ||||
▲ Show 20 Lines • Show All 353 Lines • ▼ Show 20 Lines | for (; sva < eva; sva = pdnxt) { | ||||
} | } | ||||
} | } | ||||
out: | out: | ||||
sched_unpin(); | sched_unpin(); | ||||
if (anyvalid) | if (anyvalid) | ||||
pmap_invalidate_all(pmap); | pmap_invalidate_all(pmap); | ||||
rw_wunlock(&pvh_global_lock); | rw_wunlock(&pvh_global_lock); | ||||
PMAP_UNLOCK(pmap); | PMAP_UNLOCK(pmap); | ||||
pmap_free_zero_pages(&free); | vm_page_free_zero_pages(&free, true); | ||||
} | } | ||||
/* | /* | ||||
* Routine: pmap_remove_all | * Routine: pmap_remove_all | ||||
* Function: | * Function: | ||||
* Removes this physical page from | * Removes this physical page from | ||||
* all physical maps in which it resides. | * all physical maps in which it resides. | ||||
* Reflects back modify bits to the pager. | * Reflects back modify bits to the pager. | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) { | ||||
pmap_invalidate_page(pmap, pv->pv_va); | pmap_invalidate_page(pmap, pv->pv_va); | ||||
TAILQ_REMOVE(&m->md.pv_list, pv, pv_next); | TAILQ_REMOVE(&m->md.pv_list, pv, pv_next); | ||||
free_pv_entry(pmap, pv); | free_pv_entry(pmap, pv); | ||||
PMAP_UNLOCK(pmap); | PMAP_UNLOCK(pmap); | ||||
} | } | ||||
vm_page_aflag_clear(m, PGA_WRITEABLE); | vm_page_aflag_clear(m, PGA_WRITEABLE); | ||||
sched_unpin(); | sched_unpin(); | ||||
rw_wunlock(&pvh_global_lock); | rw_wunlock(&pvh_global_lock); | ||||
pmap_free_zero_pages(&free); | vm_page_free_zero_pages(&free, true); | ||||
} | } | ||||
/* | /* | ||||
* pmap_protect_pde: do the things to protect a 4mpage in a process | * pmap_protect_pde: do the things to protect a 4mpage in a process | ||||
*/ | */ | ||||
static boolean_t | static boolean_t | ||||
pmap_protect_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t sva, vm_prot_t prot) | pmap_protect_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t sva, vm_prot_t prot) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 751 Lines • ▼ Show 20 Lines | pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, | ||||
* Enter on the PV list if part of our managed memory. | * Enter on the PV list if part of our managed memory. | ||||
*/ | */ | ||||
if ((m->oflags & VPO_UNMANAGED) == 0 && | if ((m->oflags & VPO_UNMANAGED) == 0 && | ||||
!pmap_try_insert_pv_entry(pmap, va, m)) { | !pmap_try_insert_pv_entry(pmap, va, m)) { | ||||
if (mpte != NULL) { | if (mpte != NULL) { | ||||
SLIST_INIT(&free); | SLIST_INIT(&free); | ||||
if (pmap_unwire_ptp(pmap, mpte, &free)) { | if (pmap_unwire_ptp(pmap, mpte, &free)) { | ||||
pmap_invalidate_page(pmap, va); | pmap_invalidate_page(pmap, va); | ||||
pmap_free_zero_pages(&free); | vm_page_free_zero_pages(&free, true); | ||||
} | } | ||||
mpte = NULL; | mpte = NULL; | ||||
} | } | ||||
return (mpte); | return (mpte); | ||||
} | } | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 298 Lines • ▼ Show 20 Lines | while (addr < pdnxt) { | ||||
PG_A); | PG_A); | ||||
dst_pmap->pm_stats.resident_count++; | dst_pmap->pm_stats.resident_count++; | ||||
} else { | } else { | ||||
SLIST_INIT(&free); | SLIST_INIT(&free); | ||||
if (pmap_unwire_ptp(dst_pmap, dstmpte, | if (pmap_unwire_ptp(dst_pmap, dstmpte, | ||||
&free)) { | &free)) { | ||||
pmap_invalidate_page(dst_pmap, | pmap_invalidate_page(dst_pmap, | ||||
addr); | addr); | ||||
pmap_free_zero_pages(&free); | vm_page_free_zero_pages(&free, | ||||
true); | |||||
} | } | ||||
goto out; | goto out; | ||||
} | } | ||||
if (dstmpte->wire_count >= srcmpte->wire_count) | if (dstmpte->wire_count >= srcmpte->wire_count) | ||||
break; | break; | ||||
} | } | ||||
addr += PAGE_SIZE; | addr += PAGE_SIZE; | ||||
src_pte++; | src_pte++; | ||||
▲ Show 20 Lines • Show All 401 Lines • ▼ Show 20 Lines | if (allfree) { | ||||
TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list); | TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list); | ||||
free_pv_chunk(pc); | free_pv_chunk(pc); | ||||
} | } | ||||
} | } | ||||
sched_unpin(); | sched_unpin(); | ||||
pmap_invalidate_all(pmap); | pmap_invalidate_all(pmap); | ||||
rw_wunlock(&pvh_global_lock); | rw_wunlock(&pvh_global_lock); | ||||
PMAP_UNLOCK(pmap); | PMAP_UNLOCK(pmap); | ||||
pmap_free_zero_pages(&free); | vm_page_free_zero_pages(&free, true); | ||||
} | } | ||||
/* | /* | ||||
* pmap_is_modified: | * pmap_is_modified: | ||||
* | * | ||||
* Return whether or not the specified physical page was modified | * Return whether or not the specified physical page was modified | ||||
* in any physical maps. | * in any physical maps. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 1,058 Lines • Show Last 20 Lines |