Changeset View
Changeset View
Standalone View
Standalone View
head/sys/i386/i386/pmap.c
Show First 20 Lines • Show All 1,703 Lines • ▼ Show 20 Lines | |||||
/*************************************************** | /*************************************************** | ||||
* Page table page management routines..... | * Page table page management routines..... | ||||
***************************************************/ | ***************************************************/ | ||||
static __inline void | static __inline void | ||||
pmap_free_zero_pages(struct spglist *free) | pmap_free_zero_pages(struct spglist *free) | ||||
{ | { | ||||
vm_page_t m; | vm_page_t m; | ||||
int count; | |||||
while ((m = SLIST_FIRST(free)) != NULL) { | for (count = 0; (m = SLIST_FIRST(free)) != NULL; count++) { | ||||
SLIST_REMOVE_HEAD(free, plinks.s.ss); | SLIST_REMOVE_HEAD(free, plinks.s.ss); | ||||
/* Preserve the page's PG_ZERO setting. */ | /* Preserve the page's PG_ZERO setting. */ | ||||
vm_page_free_toq(m); | 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 | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | _pmap_unwire_ptp(pmap_t pmap, vm_page_t m, struct spglist *free) | ||||
/* | /* | ||||
* unmap the page table page | * unmap the page table page | ||||
*/ | */ | ||||
pmap->pm_pdir[m->pindex] = 0; | pmap->pm_pdir[m->pindex] = 0; | ||||
--pmap->pm_stats.resident_count; | --pmap->pm_stats.resident_count; | ||||
/* | /* | ||||
* This is a release store so that the ordinary store unmapping | |||||
* the page table page is globally performed before TLB shoot- | |||||
* down is begun. | |||||
*/ | |||||
atomic_subtract_rel_int(&vm_cnt.v_wire_count, 1); | |||||
/* | |||||
* Do an invltlb to make the invalidated mapping | * Do an invltlb to make the invalidated mapping | ||||
* take effect immediately. | * take effect immediately. | ||||
*/ | */ | ||||
pteva = VM_MAXUSER_ADDRESS + i386_ptob(m->pindex); | pteva = VM_MAXUSER_ADDRESS + i386_ptob(m->pindex); | ||||
pmap_invalidate_page(pmap, pteva); | pmap_invalidate_page(pmap, pteva); | ||||
/* | /* | ||||
* Put page on a list so that it is released after | * Put page on a list so that it is released after | ||||
▲ Show 20 Lines • Show All 246 Lines • ▼ Show 20 Lines | pmap_release(pmap_t pmap) | ||||
for (i = 0; i < NPGPTD; i++) { | for (i = 0; i < NPGPTD; i++) { | ||||
m = ptdpg[i]; | m = ptdpg[i]; | ||||
#if defined(PAE) || defined(PAE_TABLES) | #if defined(PAE) || defined(PAE_TABLES) | ||||
KASSERT(VM_PAGE_TO_PHYS(m) == (pmap->pm_pdpt[i] & PG_FRAME), | KASSERT(VM_PAGE_TO_PHYS(m) == (pmap->pm_pdpt[i] & PG_FRAME), | ||||
("pmap_release: got wrong ptd page")); | ("pmap_release: got wrong ptd page")); | ||||
#endif | #endif | ||||
m->wire_count--; | m->wire_count--; | ||||
atomic_subtract_int(&vm_cnt.v_wire_count, 1); | |||||
vm_page_free_zero(m); | vm_page_free_zero(m); | ||||
} | } | ||||
atomic_subtract_int(&vm_cnt.v_wire_count, NPGPTD); | |||||
} | } | ||||
␌ | |||||
static int | static int | ||||
kvm_size(SYSCTL_HANDLER_ARGS) | kvm_size(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
unsigned long ksize = VM_MAX_KERNEL_ADDRESS - KERNBASE; | unsigned long ksize = VM_MAX_KERNEL_ADDRESS - KERNBASE; | ||||
return (sysctl_handle_long(oidp, &ksize, 0, req)); | return (sysctl_handle_long(oidp, &ksize, 0, req)); | ||||
} | } | ||||
SYSCTL_PROC(_vm, OID_AUTO, kvm_size, CTLTYPE_LONG|CTLFLAG_RD, | SYSCTL_PROC(_vm, OID_AUTO, kvm_size, CTLTYPE_LONG|CTLFLAG_RD, | ||||
▲ Show 20 Lines • Show All 242 Lines • ▼ Show 20 Lines | if (pmap != NULL) { | ||||
if (pmap != locked_pmap) | 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; | ||||
atomic_add_int(&vm_cnt.v_wire_count, 1); | |||||
} | } | ||||
pmap_free_zero_pages(&free); | pmap_free_zero_pages(&free); | ||||
return (m_pc); | return (m_pc); | ||||
} | } | ||||
/* | /* | ||||
* free the pv_entry back to the free list | * free the pv_entry back to the free list | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 532 Lines • ▼ Show 20 Lines | pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva, | ||||
} else { | } else { | ||||
mpte = pmap_remove_pt_page(pmap, sva); | mpte = pmap_remove_pt_page(pmap, sva); | ||||
if (mpte != NULL) { | if (mpte != NULL) { | ||||
pmap->pm_stats.resident_count--; | pmap->pm_stats.resident_count--; | ||||
KASSERT(mpte->wire_count == NPTEPG, | KASSERT(mpte->wire_count == NPTEPG, | ||||
("pmap_remove_pde: pte page wire count error")); | ("pmap_remove_pde: pte page wire count error")); | ||||
mpte->wire_count = 0; | mpte->wire_count = 0; | ||||
pmap_add_delayed_free_list(mpte, free, FALSE); | pmap_add_delayed_free_list(mpte, free, FALSE); | ||||
atomic_subtract_int(&vm_cnt.v_wire_count, 1); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* pmap_remove_pte: do the things to unmap a page in a process | * pmap_remove_pte: do the things to unmap a page in a process | ||||
*/ | */ | ||||
static int | static int | ||||
▲ Show 20 Lines • Show All 1,703 Lines • ▼ Show 20 Lines | */ | ||||
} | } | ||||
mpte = pmap_remove_pt_page(pmap, pv->pv_va); | mpte = pmap_remove_pt_page(pmap, pv->pv_va); | ||||
if (mpte != NULL) { | if (mpte != NULL) { | ||||
pmap->pm_stats.resident_count--; | pmap->pm_stats.resident_count--; | ||||
KASSERT(mpte->wire_count == NPTEPG, | KASSERT(mpte->wire_count == NPTEPG, | ||||
("pmap_remove_pages: pte page wire count error")); | ("pmap_remove_pages: pte page wire count error")); | ||||
mpte->wire_count = 0; | mpte->wire_count = 0; | ||||
pmap_add_delayed_free_list(mpte, &free, FALSE); | pmap_add_delayed_free_list(mpte, &free, FALSE); | ||||
atomic_subtract_int(&vm_cnt.v_wire_count, 1); | |||||
} | } | ||||
} else { | } else { | ||||
pmap->pm_stats.resident_count--; | pmap->pm_stats.resident_count--; | ||||
TAILQ_REMOVE(&m->md.pv_list, pv, pv_next); | TAILQ_REMOVE(&m->md.pv_list, pv, pv_next); | ||||
if (TAILQ_EMPTY(&m->md.pv_list) && | if (TAILQ_EMPTY(&m->md.pv_list) && | ||||
(m->flags & PG_FICTITIOUS) == 0) { | (m->flags & PG_FICTITIOUS) == 0) { | ||||
pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m)); | pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m)); | ||||
if (TAILQ_EMPTY(&pvh->pv_list)) | if (TAILQ_EMPTY(&pvh->pv_list)) | ||||
▲ Show 20 Lines • Show All 1,082 Lines • Show Last 20 Lines |