Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/arch/sparc64/sparc64/pmap.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/arch/sparc64/sparc64/pmap.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.107.2.1 retrieving revision 1.108 diff -u -p -r1.107.2.1 -r1.108 --- src/sys/arch/sparc64/sparc64/pmap.c 2001/10/01 12:42:39 1.107.2.1 +++ src/sys/arch/sparc64/sparc64/pmap.c 2001/09/10 21:19:26 1.108 @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.c,v 1.107.2.1 2001/10/01 12:42:39 fvdl Exp $ */ +/* $NetBSD: pmap.c,v 1.108 2001/09/10 21:19:26 chris Exp $ */ #undef NO_VCACHE /* Don't forget the locked TLB in dostart */ #define HWREF /* @@ -39,7 +39,6 @@ #include #include #include -#include #include @@ -172,6 +171,9 @@ static paddr_t pseg_find(struct pmap* pm #endif +extern struct vm_page *vm_page_alloc1 __P((void)); +extern void vm_page_free1 __P((struct vm_page *)); + #ifdef DEBUG #ifdef __STDC__ @@ -420,8 +422,7 @@ int numctx; #define CTXENTRY (sizeof(paddr_t)) #define CTXSIZE (numctx*CTXENTRY) -static int pmap_get_page(paddr_t *p, char *wait); -static void pmap_free_page(paddr_t pa); +#define pmap_get_page(p) uvm_page_physget((p)); /* @@ -478,11 +479,12 @@ pmap_enter_kpage(va, data) newp = NULL; while (pseg_set(pmap_kernel(), va, data, newp) == 1) { newp = NULL; - pmap_get_page(&newp, NULL); + pmap_get_page(&newp); if (!newp) { prom_printf("pmap_enter_kpage: out of pages\n"); panic("pmap_enter_kpage"); } + pmap_zero_page(newp); #ifdef DEBUG enter_stats.ptpneeded ++; #endif @@ -497,7 +499,7 @@ pmap_enter_kpage(va, data) } /* - * Check the bootargs to see if we need to enable bootdebug. + * See checp bootargs to see if we need to enable bootdebug. */ #ifdef DEBUG void pmap_bootdebug __P((void)); @@ -1270,7 +1272,8 @@ remap_data: paddr_t newp; do { - pmap_get_page(&newp, NULL); + pmap_get_page(&newp); + pmap_zero_page(newp); } while (!newp); /* Throw away page zero */ pmap_kernel()->pm_segs=(paddr_t *)(u_long)newp; pmap_kernel()->pm_physaddr = newp; @@ -1367,7 +1370,8 @@ remap_data: while (vmmap < u0[1]) { int64_t data; - pmap_get_page(&pa, NULL); + pmap_get_page(&pa); + pmap_zero_page(pa); prom_map_phys(pa, NBPG, vmmap, -1); data = TSB_DATA(0 /* global */, PGSZ_8K, @@ -1579,8 +1583,19 @@ pmap_growkernel(maxkvaddr) DPRINTF(PDB_GROW, ("pmap_growkernel: extending %lx\n", kbreak)); pg = 0; - if (!pmap_get_page(&pg, NULL)) - panic("pmap_grow_kernel: no pages"); + if (uvm.page_init_done || !uvm_page_physget(&pg)) { + struct vm_page *page; + DPRINTF(PDB_GROW, +("pmap_growkernel: need to alloc page\n")); + while ((page = + vm_page_alloc1()) == NULL) { + DPRINTF(PDB_GROW, +("pmap_growkernel: calling uvm_wait()\n")); + uvm_wait("pmap_growkernel"); + } + pg = (paddr_t)VM_PAGE_TO_PHYS(page); + } + pmap_zero_page((paddr_t)pg); #ifdef DEBUG enter_stats.ptpneeded ++; #endif @@ -1628,10 +1643,21 @@ pmap_pinit(pm) simple_lock(&pm->pm_lock); pm->pm_refs = 1; if(pm != pmap_kernel()) { + struct vm_page *page; #ifdef NOTDEF_DEBUG printf("pmap_pinit: need to alloc page\n"); #endif - pmap_get_page(&pm->pm_physaddr , "pmap_pinit"); + while ((page = vm_page_alloc1()) == NULL) { + /* + * Let the pager run a bit--however this may deadlock + */ +#ifdef NOTDEF_DEBUG + printf("pmap_pinit: calling uvm_wait()\n"); +#endif + uvm_wait("pmap_pinit"); + } + pm->pm_physaddr = (paddr_t)VM_PAGE_TO_PHYS(page); + pmap_zero_page(pm->pm_physaddr); pm->pm_segs = (paddr_t *)(u_long)pm->pm_physaddr; if (!pm->pm_physaddr) panic("pmap_pinit"); #ifdef NOTDEF_DEBUG @@ -1736,16 +1762,16 @@ pmap_release(pm) } } stxa(pdirentp, ASI_PHYS_CACHED, NULL); - pmap_free_page((paddr_t)(u_long)ptbl); + vm_page_free1(PHYS_TO_VM_PAGE((paddr_t)(u_long)ptbl)); } } stxa(psegentp, ASI_PHYS_CACHED, NULL); - pmap_free_page((paddr_t)(u_long)pdir); + vm_page_free1(PHYS_TO_VM_PAGE((paddr_t)(u_long)pdir)); } } tmp = (paddr_t)(u_long)pm->pm_segs; pm->pm_segs = NULL; - pmap_free_page(tmp); + vm_page_free1(PHYS_TO_VM_PAGE(tmp)); #ifdef NOTDEF_DEBUG for (i=0; ipm_segs[i], ASI_PHYS_CACHED, NULL); - pmap_free_page((paddr_t)(u_long)pdir); + vm_page_free1(PHYS_TO_VM_PAGE((paddr_t)(u_long)pdir)); } } } @@ -1961,8 +1986,24 @@ pmap_kenter_pa(va, pa, prot) pg = NULL; while ((i = pseg_set(pm, va, tte.data, pg)) == 1) { pg = NULL; - if (!pmap_get_page(&pg, NULL)) - panic("pmap_kenter_pa: no pages"); + if (uvm.page_init_done || !uvm_page_physget(&pg)) { + struct vm_page *page; +#ifdef NOTDEF_DEBUG + printf("pmap_kenter_pa: need to alloc page\n"); +#endif + while ((page = vm_page_alloc1()) == NULL) { + /* + * Let the pager run a bit--however this may deadlock + */ + panic("pmap_kenter_pa: no free pages"); +#ifdef NOTDEF_DEBUG + printf("pmap_kenter_pa: calling uvm_wait()\n"); +#endif + uvm_wait("pmap_kenter_pa"); + } + pg = (paddr_t)VM_PAGE_TO_PHYS(page); + } + pmap_zero_page((paddr_t)pg); #ifdef DEBUG enter_stats.ptpneeded ++; #endif @@ -1971,7 +2012,7 @@ pmap_kenter_pa(va, pa, prot) /* We allocated a spare page but didn't use it. Free it. */ printf("pmap_kenter_pa: freeing unused page %llx\n", (long long)pg); - pmap_free_page(pg); + vm_page_free1(PHYS_TO_VM_PAGE(pg)); } #ifdef DEBUG i = ptelookup_va(va); @@ -2208,20 +2249,26 @@ pmap_enter(pm, va, pa, prot, flags) (int)(tte.data>>32), (int)tte.data, (int)va); #endif while (pseg_set(pm, va, tte.data, pg) == 1) { - char *wmsg; - pg = NULL; - if ((flags & PMAP_CANFAIL) || (pm==pmap_kernel())) - wmsg = NULL; - else - wmsg = "pmap_enter"; - - if (!pmap_get_page(&pg, wmsg)) { - if (flags & PMAP_CANFAIL) - return (ENOMEM); - else - panic("pmap_enter: no pages"); - } + if (uvm.page_init_done || !uvm_page_physget(&pg)) { + struct vm_page *page; +#ifdef NOTDEF_DEBUG + printf("pmap_enter: need to alloc page\n"); +#endif + while ((page = vm_page_alloc1()) == NULL) { + /* + * Let the pager run a bit--however this may deadlock + */ + if (pm == pmap_kernel()) + panic("pmap_enter: no free pages"); +#ifdef NOTDEF_DEBUG + printf("pmap_enter: calling uvm_wait()\n"); +#endif + uvm_wait("pmap_enter"); + } + pg = (paddr_t)VM_PAGE_TO_PHYS(page); + } + pmap_zero_page((paddr_t)pg); #ifdef DEBUG enter_stats.ptpneeded ++; #endif @@ -2813,7 +2860,7 @@ pmap_clear_modify(pg) if (data & (TLB_MODIFY)) changed |= 1; #ifdef HWREF - data &= ~(TLB_MODIFY|TLB_W); + data &= ~(TLB_MODIFY); #else data &= ~(TLB_MODIFY|TLB_W|TLB_REAL_W); #endif @@ -3197,6 +3244,7 @@ pmap_page_protect(pg, prot) firstpv = pv = pa_to_pvh(pa); s = splvm(); + if (firstpv->pv_pmap) simple_lock(&firstpv->pv_pmap->pm_lock); /* First remove the entire list of continuation pv's*/ for (npv = pv->pv_next; npv; npv = pv->pv_next) { @@ -3265,7 +3313,6 @@ pmap_page_protect(pg, prot) } #endif if (pv->pv_pmap != NULL) { - simple_lock(&pv->pv_pmap->pm_lock); #ifdef DEBUG if (pmapdebug & (PDB_CHANGEPROT|PDB_REF|PDB_REMOVE)) { printf("pmap_page_protect: demap va %p of pa %lx from pm %p...\n", @@ -3351,39 +3398,6 @@ pmap_count_res(pm) } /* - * count wired pages in pmap -- this can be slow. - */ -int -pmap_count_wired(pm) - pmap_t pm; -{ - int i, j, k, n, s; - paddr_t *pdir, *ptbl; - /* Almost the same as pmap_collect() */ - - /* Don't want one of these pages reused while we're reading it. */ - s = splvm(); - simple_lock(&pm->pm_lock); - n = 0; - for (i = 0; i < STSZ; i++) { - if ((pdir = (paddr_t *)(u_long)ldxa((vaddr_t)&pm->pm_segs[i], ASI_PHYS_CACHED))) { - for (k = 0; k < PDSZ; k++) { - if ((ptbl = (paddr_t *)(u_long)ldxa((vaddr_t)&pdir[k], ASI_PHYS_CACHED))) { - for (j = 0; j < PTSZ; j++) { - int64_t data = (int64_t)ldxa((vaddr_t)&ptbl[j], ASI_PHYS_CACHED); - if (data & TLB_TSB_LOCK) - n++; - } - } - } - } - } - simple_unlock(&pm->pm_lock); - splx(s); - return n; -} - -/* * Allocate a context. If necessary, steal one from someone else. * Changes hardware context number and loads segment map. * @@ -3769,70 +3783,45 @@ pmap_page_cache(pm, pa, mode) splx(s); } - -static paddr_t leftovers = 0; - -static int -pmap_get_page(paddr_t *p, char *wait) +/* + * vm_page_alloc1: + * + * Allocate and return a memory cell with no associated object. + */ +struct vm_page * +vm_page_alloc1() { - struct vm_page *pg; - paddr_t pa; - - if ((pa = leftovers)) { - /* Use any leftover pages. */ - leftovers = ldxa(pa, ASI_PHYS_CACHED); - pmap_zero_page(pa); - } else if (uvm.page_init_done) { - while ((pg = uvm_pagealloc(NULL, 0, NULL, - UVM_PGA_ZERO|UVM_PGA_USERESERVE)) == NULL) { - if (!wait) return (0); - uvm_wait(wait); - } + struct vm_page *pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_USERESERVE); + if (pg) { pg->wire_count = 1; /* no mappings yet */ pg->flags &= ~PG_BUSY; /* never busy */ - pa = (paddr_t)VM_PAGE_TO_PHYS(pg); - } else { - if (!uvm_page_physget(&pa)) - return (0); - pmap_zero_page(pa); } - *p = pa; - return (1); + return pg; } -static void -pmap_free_page(paddr_t pa) +/* + * vm_page_free1: + * + * Returns the given page to the free list, + * disassociating it with any VM object. + * + * Object and page must be locked prior to entry. + */ +void +vm_page_free1(mem) + struct vm_page *mem; { - struct vm_page *pg = PHYS_TO_VM_PAGE(pa); - - if (pg) { - if (pg->flags != (PG_FAKE)) { - printf("Freeing invalid page %p\n", pg); - printf("pa = %llx (pg = %llx\n)", - (unsigned long long)pa, - (unsigned long long)VM_PAGE_TO_PHYS(pg)); -#ifdef DDB - Debugger(); -#endif - return; - } - pg->flags |= PG_BUSY; - pg->wire_count = 0; - uvm_pagefree(pg); - } else { - /* - * This is not a VM page. It must have been allocated before - * the VM system was initialized. We could hand it over to - * the VM system, but that involves extra overhead. Instead - * we'll just link them into a list of available pages for - * the next time pmap_get_page() is called. - */ - stxa(pa, ASI_PHYS_CACHED, leftovers); - leftovers = pa; + if (mem->flags != (PG_CLEAN|PG_FAKE)) { + printf("Freeing invalid page %p\n", mem); + printf("pa = %llx\n", (unsigned long long)VM_PAGE_TO_PHYS(mem)); + Debugger(); + return; } + mem->flags |= PG_BUSY; + mem->wire_count = 0; + uvm_pagefree(mem); } - #ifdef DDB void db_dump_pv __P((db_expr_t, int, db_expr_t, char *)); @@ -3861,7 +3850,8 @@ db_dump_pv(addr, have_addr, count, modif #ifdef DEBUG /* - * Test ref/modify handling. */ + * Test ref/modify handling. + */ void pmap_testout __P((void)); void pmap_testout() @@ -3878,8 +3868,8 @@ pmap_testout() ASSERT(va != NULL); loc = (int*)va; - pmap_get_page(&pa, NULL); - pg = PHYS_TO_VM_PAGE(pa); + pg = vm_page_alloc1(); + pa = (paddr_t)VM_PAGE_TO_PHYS(pg); pmap_enter(pmap_kernel(), va, pa, VM_PROT_ALL, VM_PROT_ALL); pmap_update(pmap_kernel()); @@ -4050,6 +4040,6 @@ pmap_testout() pmap_remove(pmap_kernel(), va, va+1); pmap_update(pmap_kernel()); - pmap_free_page(pa); + vm_page_free1(pg); } #endif