Changeset View
Changeset View
Standalone View
Standalone View
user/alc/PQ_LAUNDRY/sys/mips/mips/pmap.c
Show First 20 Lines • Show All 160 Lines • ▼ Show 20 Lines | |||||
static pv_entry_t get_pv_entry(pmap_t pmap, boolean_t try); | static pv_entry_t get_pv_entry(pmap_t pmap, boolean_t try); | ||||
static vm_page_t pmap_pv_reclaim(pmap_t locked_pmap); | static vm_page_t pmap_pv_reclaim(pmap_t locked_pmap); | ||||
static void pmap_pvh_free(struct md_page *pvh, pmap_t pmap, vm_offset_t va); | static void pmap_pvh_free(struct md_page *pvh, pmap_t pmap, vm_offset_t va); | ||||
static pv_entry_t pmap_pvh_remove(struct md_page *pvh, pmap_t pmap, | static pv_entry_t pmap_pvh_remove(struct md_page *pvh, pmap_t pmap, | ||||
vm_offset_t va); | vm_offset_t va); | ||||
static vm_page_t pmap_alloc_direct_page(unsigned int index, int req); | static vm_page_t pmap_alloc_direct_page(unsigned int index, int req); | ||||
static vm_page_t pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, | static vm_page_t pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, | ||||
vm_page_t m, vm_prot_t prot, vm_page_t mpte); | vm_page_t m, vm_prot_t prot, vm_page_t mpte); | ||||
static void pmap_grow_direct_page(int req); | |||||
static int pmap_remove_pte(struct pmap *pmap, pt_entry_t *ptq, vm_offset_t va, | static int pmap_remove_pte(struct pmap *pmap, pt_entry_t *ptq, vm_offset_t va, | ||||
pd_entry_t pde); | pd_entry_t pde); | ||||
static void pmap_remove_page(struct pmap *pmap, vm_offset_t va); | static void pmap_remove_page(struct pmap *pmap, vm_offset_t va); | ||||
static void pmap_remove_entry(struct pmap *pmap, vm_page_t m, vm_offset_t va); | static void pmap_remove_entry(struct pmap *pmap, vm_page_t m, vm_offset_t va); | ||||
static boolean_t pmap_try_insert_pv_entry(pmap_t pmap, vm_page_t mpte, | static boolean_t pmap_try_insert_pv_entry(pmap_t pmap, vm_page_t mpte, | ||||
vm_offset_t va, vm_page_t m); | vm_offset_t va, vm_page_t m); | ||||
static void pmap_update_page(pmap_t pmap, vm_offset_t va, pt_entry_t pte); | static void pmap_update_page(pmap_t pmap, vm_offset_t va, pt_entry_t pte); | ||||
static void pmap_invalidate_all(pmap_t pmap); | static void pmap_invalidate_all(pmap_t pmap); | ||||
▲ Show 20 Lines • Show All 858 Lines • ▼ Show 20 Lines | for (i = 0; i < MAXCPU; i++) { | ||||
pmap->pm_asid[i].asid = PMAP_ASID_RESERVED; | pmap->pm_asid[i].asid = PMAP_ASID_RESERVED; | ||||
pmap->pm_asid[i].gen = 0; | pmap->pm_asid[i].gen = 0; | ||||
} | } | ||||
PCPU_SET(curpmap, pmap); | PCPU_SET(curpmap, pmap); | ||||
TAILQ_INIT(&pmap->pm_pvchunk); | TAILQ_INIT(&pmap->pm_pvchunk); | ||||
bzero(&pmap->pm_stats, sizeof pmap->pm_stats); | bzero(&pmap->pm_stats, sizeof pmap->pm_stats); | ||||
} | } | ||||
void | static void | ||||
pmap_grow_direct_page_cache() | pmap_grow_direct_page(int req) | ||||
{ | { | ||||
#ifdef __mips_n64 | #ifdef __mips_n64 | ||||
VM_WAIT; | VM_WAIT; | ||||
#else | #else | ||||
vm_pageout_grow_cache(3, 0, MIPS_KSEG0_LARGEST_PHYS); | if (!vm_page_reclaim_contig(req, 1, 0, MIPS_KSEG0_LARGEST_PHYS, | ||||
PAGE_SIZE, 0)) | |||||
VM_WAIT; | |||||
#endif | #endif | ||||
} | } | ||||
static vm_page_t | static vm_page_t | ||||
pmap_alloc_direct_page(unsigned int index, int req) | pmap_alloc_direct_page(unsigned int index, int req) | ||||
{ | { | ||||
vm_page_t m; | vm_page_t m; | ||||
Show All 13 Lines | |||||
* Initialize a preallocated and zeroed pmap structure, | * Initialize a preallocated and zeroed pmap structure, | ||||
* such as one in a vmspace structure. | * such as one in a vmspace structure. | ||||
*/ | */ | ||||
int | int | ||||
pmap_pinit(pmap_t pmap) | pmap_pinit(pmap_t pmap) | ||||
{ | { | ||||
vm_offset_t ptdva; | vm_offset_t ptdva; | ||||
vm_page_t ptdpg; | vm_page_t ptdpg; | ||||
int i; | int i, req_class; | ||||
/* | /* | ||||
* allocate the page directory page | * allocate the page directory page | ||||
*/ | */ | ||||
while ((ptdpg = pmap_alloc_direct_page(NUSERPGTBLS, VM_ALLOC_NORMAL)) == NULL) | req_class = VM_ALLOC_NORMAL; | ||||
pmap_grow_direct_page_cache(); | while ((ptdpg = pmap_alloc_direct_page(NUSERPGTBLS, req_class)) == | ||||
NULL) | |||||
pmap_grow_direct_page(req_class); | |||||
ptdva = MIPS_PHYS_TO_DIRECT(VM_PAGE_TO_PHYS(ptdpg)); | ptdva = MIPS_PHYS_TO_DIRECT(VM_PAGE_TO_PHYS(ptdpg)); | ||||
pmap->pm_segtab = (pd_entry_t *)ptdva; | pmap->pm_segtab = (pd_entry_t *)ptdva; | ||||
CPU_ZERO(&pmap->pm_active); | CPU_ZERO(&pmap->pm_active); | ||||
for (i = 0; i < MAXCPU; i++) { | for (i = 0; i < MAXCPU; i++) { | ||||
pmap->pm_asid[i].asid = PMAP_ASID_RESERVED; | pmap->pm_asid[i].asid = PMAP_ASID_RESERVED; | ||||
pmap->pm_asid[i].gen = 0; | pmap->pm_asid[i].gen = 0; | ||||
} | } | ||||
TAILQ_INIT(&pmap->pm_pvchunk); | TAILQ_INIT(&pmap->pm_pvchunk); | ||||
bzero(&pmap->pm_stats, sizeof pmap->pm_stats); | bzero(&pmap->pm_stats, sizeof pmap->pm_stats); | ||||
return (1); | return (1); | ||||
} | } | ||||
/* | /* | ||||
* this routine is called if the page table page is not | * this routine is called if the page table page is not | ||||
* mapped correctly. | * mapped correctly. | ||||
*/ | */ | ||||
static vm_page_t | static vm_page_t | ||||
_pmap_allocpte(pmap_t pmap, unsigned ptepindex, u_int flags) | _pmap_allocpte(pmap_t pmap, unsigned ptepindex, u_int flags) | ||||
{ | { | ||||
vm_offset_t pageva; | vm_offset_t pageva; | ||||
vm_page_t m; | vm_page_t m; | ||||
int req_class; | |||||
/* | /* | ||||
* Find or fabricate a new pagetable page | * Find or fabricate a new pagetable page | ||||
*/ | */ | ||||
if ((m = pmap_alloc_direct_page(ptepindex, VM_ALLOC_NORMAL)) == NULL) { | req_class = VM_ALLOC_NORMAL; | ||||
if ((m = pmap_alloc_direct_page(ptepindex, req_class)) == NULL) { | |||||
if ((flags & PMAP_ENTER_NOSLEEP) == 0) { | if ((flags & PMAP_ENTER_NOSLEEP) == 0) { | ||||
PMAP_UNLOCK(pmap); | PMAP_UNLOCK(pmap); | ||||
rw_wunlock(&pvh_global_lock); | rw_wunlock(&pvh_global_lock); | ||||
pmap_grow_direct_page_cache(); | pmap_grow_direct_page(req_class); | ||||
rw_wlock(&pvh_global_lock); | rw_wlock(&pvh_global_lock); | ||||
PMAP_LOCK(pmap); | PMAP_LOCK(pmap); | ||||
} | } | ||||
/* | /* | ||||
* Indicate the need to retry. While waiting, the page | * Indicate the need to retry. While waiting, the page | ||||
* table page may have been allocated. | * table page may have been allocated. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | |||||
* grow the number of kernel page table entries, if needed | * grow the number of kernel page table entries, if needed | ||||
*/ | */ | ||||
void | void | ||||
pmap_growkernel(vm_offset_t addr) | pmap_growkernel(vm_offset_t addr) | ||||
{ | { | ||||
vm_page_t nkpg; | vm_page_t nkpg; | ||||
pd_entry_t *pde, *pdpe; | pd_entry_t *pde, *pdpe; | ||||
pt_entry_t *pte; | pt_entry_t *pte; | ||||
int i; | int i, req_class; | ||||
mtx_assert(&kernel_map->system_mtx, MA_OWNED); | mtx_assert(&kernel_map->system_mtx, MA_OWNED); | ||||
req_class = VM_ALLOC_INTERRUPT; | |||||
addr = roundup2(addr, NBSEG); | addr = roundup2(addr, NBSEG); | ||||
if (addr - 1 >= kernel_map->max_offset) | if (addr - 1 >= kernel_map->max_offset) | ||||
addr = kernel_map->max_offset; | addr = kernel_map->max_offset; | ||||
while (kernel_vm_end < addr) { | while (kernel_vm_end < addr) { | ||||
pdpe = pmap_segmap(kernel_pmap, kernel_vm_end); | pdpe = pmap_segmap(kernel_pmap, kernel_vm_end); | ||||
#ifdef __mips_n64 | #ifdef __mips_n64 | ||||
if (*pdpe == 0) { | if (*pdpe == 0) { | ||||
/* new intermediate page table entry */ | /* new intermediate page table entry */ | ||||
nkpg = pmap_alloc_direct_page(nkpt, VM_ALLOC_INTERRUPT); | nkpg = pmap_alloc_direct_page(nkpt, req_class); | ||||
if (nkpg == NULL) | if (nkpg == NULL) | ||||
panic("pmap_growkernel: no memory to grow kernel"); | panic("pmap_growkernel: no memory to grow kernel"); | ||||
*pdpe = (pd_entry_t)MIPS_PHYS_TO_DIRECT(VM_PAGE_TO_PHYS(nkpg)); | *pdpe = (pd_entry_t)MIPS_PHYS_TO_DIRECT(VM_PAGE_TO_PHYS(nkpg)); | ||||
continue; /* try again */ | continue; /* try again */ | ||||
} | } | ||||
#endif | #endif | ||||
pde = pmap_pdpe_to_pde(pdpe, kernel_vm_end); | pde = pmap_pdpe_to_pde(pdpe, kernel_vm_end); | ||||
if (*pde != 0) { | if (*pde != 0) { | ||||
kernel_vm_end = (kernel_vm_end + NBPDR) & ~PDRMASK; | kernel_vm_end = (kernel_vm_end + NBPDR) & ~PDRMASK; | ||||
if (kernel_vm_end - 1 >= kernel_map->max_offset) { | if (kernel_vm_end - 1 >= kernel_map->max_offset) { | ||||
kernel_vm_end = kernel_map->max_offset; | kernel_vm_end = kernel_map->max_offset; | ||||
break; | break; | ||||
} | } | ||||
continue; | continue; | ||||
} | } | ||||
/* | /* | ||||
* This index is bogus, but out of the way | * This index is bogus, but out of the way | ||||
*/ | */ | ||||
nkpg = pmap_alloc_direct_page(nkpt, VM_ALLOC_INTERRUPT); | nkpg = pmap_alloc_direct_page(nkpt, req_class); | ||||
if (!nkpg) | #ifndef __mips_n64 | ||||
if (nkpg == NULL && vm_page_reclaim_contig(req_class, 1, | |||||
0, MIPS_KSEG0_LARGEST_PHYS, PAGE_SIZE, 0)) | |||||
nkpg = pmap_alloc_direct_page(nkpt, req_class); | |||||
#endif | |||||
if (nkpg == NULL) | |||||
panic("pmap_growkernel: no memory to grow kernel"); | panic("pmap_growkernel: no memory to grow kernel"); | ||||
nkpt++; | nkpt++; | ||||
*pde = (pd_entry_t)MIPS_PHYS_TO_DIRECT(VM_PAGE_TO_PHYS(nkpg)); | *pde = (pd_entry_t)MIPS_PHYS_TO_DIRECT(VM_PAGE_TO_PHYS(nkpg)); | ||||
/* | /* | ||||
* The R[4-7]?00 stores only one copy of the Global bit in | * The R[4-7]?00 stores only one copy of the Global bit in | ||||
* the translation lookaside buffer for each 2 page entry. | * the translation lookaside buffer for each 2 page entry. | ||||
* Thus invalid entrys must have the Global bit set so when | * Thus invalid entrys must have the Global bit set so when | ||||
▲ Show 20 Lines • Show All 2,274 Lines • Show Last 20 Lines |