diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 1999-12-07 15:32:31 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 1999-12-07 15:32:31 +0000 |
commit | 7f2d0a3482201118fd71a2d42ff60adae87aba1b (patch) | |
tree | 0cbe75a4560f31b5ea16eb0bb8cfe2e3942c6ac8 | |
parent | 744f8d214880ff3eb7e4115d2ccd1e88c5155e41 (diff) |
Use pool to allocate page tables. This has the nice effect that we can uncache
them on allocation instead of flushing cache every time we fiddle with them.
Some parts from NetBSD.
-rw-r--r-- | sys/arch/sparc/sparc/pmap.c | 136 |
1 files changed, 128 insertions, 8 deletions
diff --git a/sys/arch/sparc/sparc/pmap.c b/sys/arch/sparc/sparc/pmap.c index c0ffc86c0c7..e57381cde82 100644 --- a/sys/arch/sparc/sparc/pmap.c +++ b/sys/arch/sparc/sparc/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.45 1999/11/24 16:07:15 art Exp $ */ +/* $OpenBSD: pmap.c,v 1.46 1999/12/07 15:32:30 art Exp $ */ /* $NetBSD: pmap.c,v 1.118 1998/05/19 19:00:18 thorpej Exp $ */ /* @@ -75,6 +75,7 @@ #if defined(UVM) #include <uvm/uvm.h> +#include <sys/pool.h> #endif #include <machine/autoconf.h> @@ -175,6 +176,10 @@ static __inline int *pt23_alloc __P((void)); static __inline void pt1_free __P((int *)); static __inline void pt23_free __P((int *)); +#if defined(SUN4M) +static u_int VA2PA __P((caddr_t)); +#endif + /* * Given a page number, return the head of its pvlist. */ @@ -209,6 +214,88 @@ pvfree(pv) free(pv, M_VMPVENT); } +#if defined(SUN4M) +#if defined(UVM) /* We can only use pool with uvm */ +/* + * Memory pools and back-end supplier for SRMMU page tables. + * Share a pool between the level 2 and level 3 page tables, + * since these are equal in size. + */ +static struct pool L1_pool; +static struct pool L23_pool; +void *pgt_page_alloc __P((unsigned long, int, int)); +void pgt_page_free __P((void *, unsigned long, int)); + +void pcache_flush __P((caddr_t, caddr_t, int)); +void +pcache_flush(va, pa, n) + caddr_t va, pa; + int n; +{ + void (*f)__P((int,int)) = cpuinfo.pcache_flush_line; + + while ((n -= 4) >= 0) + (*f)((u_int)va+n, (u_int)pa+n); +} + +/* + * Page table pool back-end. + */ +void * +pgt_page_alloc(sz, flags, mtype) + unsigned long sz; + int flags; + int mtype; +{ + caddr_t p; + + p = (caddr_t)uvm_km_kmemalloc(kernel_map, uvm.kernel_object, + (vsize_t)sz, UVM_KMF_NOWAIT); + + if ((cpuinfo.flags & CPUFLG_CACHEPAGETABLES) == 0) { + pcache_flush(p, (caddr_t)VA2PA(p), sz); + kvm_uncache(p, sz/NBPG); + } + return (p); +} + +void +pgt_page_free(v, sz, mtype) + void *v; + unsigned long sz; + int mtype; +{ + uvm_km_free(kernel_map, (vaddr_t)v, sz); +} + +static __inline int * +pt1_alloc() +{ + return pool_get(&L1_pool, PR_WAITOK); +} + +static __inline void +pt1_free(pt) + int *pt; +{ + pool_put(&L1_pool, pt); +} + +static __inline int * +pt23_alloc() +{ + return pool_get(&L23_pool, PR_WAITOK); +} + +static __inline void +pt23_free(pt) + int *pt; +{ + pool_put(&L23_pool, pt); +} + +#else + static __inline int * pt1_alloc() { @@ -235,6 +322,9 @@ pt23_free(pt) free(pt, M_VMPMAP); } +#endif /* !UVM */ +#endif /* SUN4M */ + /* * XXX - horrible kludge to let us use "managed" pages to map the pv lists. * We check this in pmap_enter to see if it's safe to use pvhead. @@ -354,7 +444,6 @@ char *ctxbusyvector; /* [4m] tells what contexts are busy (XXX)*/ #endif caddr_t vpage[2]; /* two reserved MD virtual pages */ -caddr_t vdumppages; /* 32KB worth of reserved dump pages */ smeg_t tregion; /* [4/3mmu] Region for temporary mappings */ @@ -549,8 +638,6 @@ void (*pmap_rmu_p) __P((struct pmap *, vaddr_t, vaddr_t, int, int)); #define tlb_flush_context() sta(ASI_SRMMUFP_L1, ASI_SRMMUFP, 0) #define tlb_flush_all() sta(ASI_SRMMUFP_LN, ASI_SRMMUFP, 0) -static u_int VA2PA __P((caddr_t)); - /* * VA2PA(addr) -- converts a virtual address to a physical address using * the MMU's currently-installed page tables. As a side effect, the address @@ -560,7 +647,7 @@ static u_int VA2PA __P((caddr_t)); * This routine should work with any level of mapping, as it is used * during bootup to interact with the ROM's initial L1 mapping of the kernel. */ -static __inline u_int +static u_int VA2PA(addr) caddr_t addr; { @@ -632,7 +719,7 @@ setpgt4m(ptep, pte) int pte; { swap(ptep, pte); -#if 1 +#if 0 if ((cpuinfo.flags & CPUFLG_CACHEPAGETABLES) == 0) cpuinfo.pcache_flush_line((int)ptep, VA2PA((caddr_t)ptep)); #endif @@ -2662,6 +2749,14 @@ pmap_bootstrap4_4c(nctx, nregion, nsegment) } } +#if defined(UVM) + uvmexp.pagesize = NBPG; + uvm_setpagesize(); +#else + cnt.v_page_size = NBPG; + vm_set_page_size(); +#endif + #if defined(SUN4) /* * set up the segfixmask to mask off invalid bits @@ -3380,7 +3475,30 @@ pmap_init() sizeof(struct pvlist); } + /* + * We can set it here since it's only used in pmap_enter to see + * if pv lists have been mapped. + */ pmap_initialized = 1; + +#if defined(SUN4M) && defined(UVM) + if (CPU_ISSUN4M) { + /* + * The SRMMU only ever needs chunks in one of two sizes: + * 1024 (for region level tables) and 256 (for segment + * and page level tables). + */ + int n; + + n = SRMMU_L1SIZE * sizeof(int); + pool_init(&L1_pool, n, n, 0, 0, "L1 pagetable", 0, + pgt_page_alloc, pgt_page_free, 0); + + n = SRMMU_L2SIZE * sizeof(int); + pool_init(&L23_pool, n, n, 0, 0, "L2/L3 pagetable", 0, + pgt_page_alloc, pgt_page_free, 0); + } +#endif } @@ -5965,7 +6083,8 @@ pmap_zero_page4_4c(pa) struct pvlist *pv; pv = pvhead(atop(pa)); - if (((pa & (PMAP_TNC_4 & ~PMAP_NC)) == 0) && pv) { + if (((pa & (PMAP_TNC_4 & ~PMAP_NC)) == 0) && pv && + pmap_initialized) { /* * The following might not be necessary since the page * is being cleared because it is about to be allocated, @@ -6039,7 +6158,8 @@ pmap_zero_page4m(pa) pv = pvhead(atop(pa)); if (((pa & (PMAP_TNC_SRMMU & ~PMAP_NC)) == 0) && pv && - CACHEINFO.c_vactype != VAC_NONE) + CACHEINFO.c_vactype != VAC_NONE && + pmap_initialized) /* * The following might not be necessary since the page * is being cleared because it is about to be allocated, |