Module Name: src Committed By: matt Date: Tue May 24 23:30:30 UTC 2011
Modified Files: src/sys/arch/vax/include: pmap.h src/sys/arch/vax/vax: pmap.c Log Message: Remove pmap's simple_lock; switch to atomic ops Change pvtable simple_lock to mutex Switch to kmem (goodbye malloc). To generate a diff of this commit: cvs rdiff -u -r1.79 -r1.80 src/sys/arch/vax/include/pmap.h cvs rdiff -u -r1.179 -r1.180 src/sys/arch/vax/vax/pmap.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/vax/include/pmap.h diff -u src/sys/arch/vax/include/pmap.h:1.79 src/sys/arch/vax/include/pmap.h:1.80 --- src/sys/arch/vax/include/pmap.h:1.79 Sun Nov 14 13:33:23 2010 +++ src/sys/arch/vax/include/pmap.h Tue May 24 23:30:30 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.h,v 1.79 2010/11/14 13:33:23 uebayasi Exp $ */ +/* $NetBSD: pmap.h,v 1.80 2011/05/24 23:30:30 matt Exp $ */ /* * Copyright (c) 1991 Regents of the University of California. @@ -81,7 +81,7 @@ #ifndef PMAP_H #define PMAP_H -#include <sys/simplelock.h> +#include <sys/atomic.h> #include <uvm/uvm_page.h> @@ -102,13 +102,12 @@ struct pmap { struct pte *pm_p1ap; /* Base of alloced p1 pte space */ - int pm_count; /* reference count */ + u_int pm_count; /* reference count */ struct pcb *pm_pcbs; /* PCBs using this pmap */ struct pte *pm_p0br; /* page 0 base register */ long pm_p0lr; /* page 0 length register */ struct pte *pm_p1br; /* page 1 base register */ long pm_p1lr; /* page 1 length register */ - struct simplelock pm_lock; /* Lock entry in MP environment */ struct pmap_statistics pm_stats; /* Some statistics */ }; @@ -149,7 +148,7 @@ /* * This is the by far most used pmap routine. Make it inline. */ -__inline static bool +static __inline bool pmap_extract(pmap_t pmap, vaddr_t va, paddr_t *pap) { int *pte, sva; @@ -190,25 +189,30 @@ return (false); } -bool pmap_clear_modify_long(struct pv_entry *); -bool pmap_clear_reference_long(struct pv_entry *); -bool pmap_is_modified_long(struct pv_entry *); +bool pmap_clear_modify_long(const struct pv_entry *); +bool pmap_clear_reference_long(const struct pv_entry *); +bool pmap_is_modified_long_p(const struct pv_entry *); void pmap_page_protect_long(struct pv_entry *, vm_prot_t); void pmap_protect_long(pmap_t, vaddr_t, vaddr_t, vm_prot_t); -__inline static bool +static __inline struct pv_entry * +pmap_pg_to_pv(const struct vm_page *pg) +{ + return pv_table + (VM_PAGE_TO_PHYS(pg) >> PGSHIFT); +} + +static __inline bool pmap_is_referenced(struct vm_page *pg) { - struct pv_entry *pv = pv_table + (VM_PAGE_TO_PHYS(pg) >> PGSHIFT); - bool rv = (pv->pv_attr & PG_V) != 0; + const struct pv_entry * const pv = pmap_pg_to_pv(pg); - return rv; + return (pv->pv_attr & PG_V) != 0; } -__inline static bool +static __inline bool pmap_clear_reference(struct vm_page *pg) { - struct pv_entry *pv = pv_table + (VM_PAGE_TO_PHYS(pg) >> PGSHIFT); + struct pv_entry * const pv = pmap_pg_to_pv(pg); bool rv = (pv->pv_attr & PG_V) != 0; pv->pv_attr &= ~PG_V; @@ -217,10 +221,10 @@ return rv; } -__inline static bool +static __inline bool pmap_clear_modify(struct vm_page *pg) { - struct pv_entry *pv = pv_table + (VM_PAGE_TO_PHYS(pg) >> PGSHIFT); + struct pv_entry * const pv = pmap_pg_to_pv(pg); bool rv = (pv->pv_attr & PG_M) != 0; pv->pv_attr &= ~PG_M; @@ -229,26 +233,24 @@ return rv; } -__inline static bool +static __inline bool pmap_is_modified(struct vm_page *pg) { - struct pv_entry *pv = pv_table + (VM_PAGE_TO_PHYS(pg) >> PGSHIFT); - if (pv->pv_attr & PG_M) - return 1; - else - return pmap_is_modified_long(pv); + const struct pv_entry * const pv = pmap_pg_to_pv(pg); + + return (pv->pv_attr & PG_M) != 0 || pmap_is_modified_long_p(pv); } -__inline static void +static __inline void pmap_page_protect(struct vm_page *pg, vm_prot_t prot) { - struct pv_entry *pv = pv_table + (VM_PAGE_TO_PHYS(pg) >> PGSHIFT); + struct pv_entry * const pv = pmap_pg_to_pv(pg); if (pv->pv_pmap != NULL || pv->pv_next != NULL) pmap_page_protect_long(pv, prot); } -__inline static void +static __inline void pmap_protect(pmap_t pmap, vaddr_t start, vaddr_t end, vm_prot_t prot) { if (pmap->pm_p0lr != 0 || pmap->pm_p1lr != 0x200000 || @@ -266,10 +268,10 @@ #define pmap_phys_address(phys) ((u_int)(phys) << PGSHIFT) #define pmap_copy(a,b,c,d,e) /* Dont do anything */ #define pmap_update(pmap) /* nothing (yet) */ -#define pmap_remove(pmap, start, slut) pmap_protect(pmap, start, slut, 0) +#define pmap_remove(pmap, start, end) pmap_protect(pmap, start, end, 0) #define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) #define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count) -#define pmap_reference(pmap) (pmap)->pm_count++ +#define pmap_reference(pmap) atomic_inc_uint(&(pmap)->pm_count) /* These can be done as efficient inline macros */ #define pmap_copy_page(src, dst) \ Index: src/sys/arch/vax/vax/pmap.c diff -u src/sys/arch/vax/vax/pmap.c:1.179 src/sys/arch/vax/vax/pmap.c:1.180 --- src/sys/arch/vax/vax/pmap.c:1.179 Tue Dec 14 23:44:49 2010 +++ src/sys/arch/vax/vax/pmap.c Tue May 24 23:30:30 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.c,v 1.179 2010/12/14 23:44:49 matt Exp $ */ +/* $NetBSD: pmap.c,v 1.180 2011/05/24 23:30:30 matt Exp $ */ /* * Copyright (c) 1994, 1998, 1999, 2003 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.179 2010/12/14 23:44:49 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.180 2011/05/24 23:30:30 matt Exp $"); #include "opt_ddb.h" #include "opt_cputype.h" @@ -45,8 +45,10 @@ #include <sys/cpu.h> #include <sys/device.h> #include <sys/extent.h> -#include <sys/malloc.h> #include <sys/proc.h> +#include <sys/atomic.h> +#include <sys/kmem.h> +#include <sys/mutex.h> #include <uvm/uvm.h> @@ -101,7 +103,7 @@ extern void *msgbufaddr; -#define IOSPACE(p) (((u_long)(p)) & 0xe0000000) +#define IOSPACE_P(p) (((u_long)(p) & 0xe0000000) != 0) #define NPTEPROCSPC 0x1000 /* # of virtual PTEs per process space */ #define NPTEPG 0x80 /* # of PTEs per page (logical or physical) */ #define PPTESZ sizeof(struct pte) @@ -115,6 +117,34 @@ #define P1SEG 1 #define SYSSEG 2 +static inline void +pmap_decrement_stats(struct pmap *pm, bool wired) +{ +#if defined(MULTIPROCESSOR) + atomic_dec_ulong(&pm->pm_stats.resident_count); + if (wired) + atomic_dec_ulong(&pm->pm_stats.wired_count); +#else + pm->pm_stats.resident_count--; + if (wired) + pm->pm_stats.wired_count--; +#endif +} + +static inline void +pmap_increment_stats(struct pmap *pm, bool wired) +{ +#if defined(MULTIPROCESSOR) + atomic_inc_ulong(&pm->pm_stats.resident_count); + if (wired) + atomic_inc_ulong(&pm->pm_stats.wired_count); +#else + pm->pm_stats.resident_count++; + if (wired) + pm->pm_stats.wired_count++; +#endif +} + /* * Map in a virtual page. */ @@ -162,9 +192,9 @@ #endif #if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) -static struct simplelock pvtable_lock; -#define PVTABLE_LOCK simple_lock(&pvtable_lock); -#define PVTABLE_UNLOCK simple_unlock(&pvtable_lock); +static kmutex_t pvtable_lock; +#define PVTABLE_LOCK mutex_spin_enter(&pvtable_lock); +#define PVTABLE_UNLOCK mutex_spin_enter(&pvtable_lock); #else #define PVTABLE_LOCK #define PVTABLE_UNLOCK @@ -180,7 +210,7 @@ struct pv_entry *get_pventry(void); void free_pventry(struct pv_entry *); void more_pventries(void); -vaddr_t get_ptp(int); +vaddr_t get_ptp(bool); void free_ptp(paddr_t); /* @@ -378,7 +408,6 @@ /* btop(virtual_avail - KERNBASE); */ pmap->pm_count = 1; - simple_lock_init(&pmap->pm_lock); /* Activate the kernel pmap. */ pcb->P1BR = pmap->pm_p1br; @@ -409,7 +438,7 @@ SIMPLEQ_FIRST(&cpus) = ci; #endif #if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - simple_lock_init(&pvtable_lock); + mutex_init(&pvtable_lock, MUTEX_DEFAULT, IPL_VM); #endif /* @@ -519,18 +548,14 @@ else vaddr = (br - (int *)pm->pm_p1br) * VAX_NBPG + 0x40000000; - if (IOSPACE((br[0] & PG_FRAME) << VAX_PGSHIFT)) + if (IOSPACE_P((br[0] & PG_FRAME) << VAX_PGSHIFT)) return; /* Forget mappings of IO space */ pv = pv_table + ((br[0] & PG_FRAME) >> LTOHPS); if (((br[0] & PG_PROT) == PG_RW) && ((pv->pv_attr & PG_M) != PG_M)) pv->pv_attr |= br[0]|br[1]|br[2]|br[3]|br[4]|br[5]|br[6]|br[7]; - simple_lock(&pm->pm_lock); - pm->pm_stats.resident_count--; - if (br[0] & PG_W) - pm->pm_stats.wired_count--; - simple_unlock(&pm->pm_lock); + pmap_decrement_stats(pm, (br[0] & PG_W) != 0); if (pv->pv_pmap == pm && pv->pv_vaddr == vaddr) { pv->pv_vaddr = NOVADDR; pv->pv_pmap = 0; @@ -584,7 +609,7 @@ * Allocate a page through direct-mapped segment. */ static vaddr_t -getpage(int w) +getpage(bool wait) { struct vm_page *pg; @@ -592,7 +617,7 @@ pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO); if (pg != NULL) break; - if (w == NOWAIT) + if (!wait) return 0; uvm_wait("getpage"); } @@ -886,17 +911,16 @@ /* * pmap_create() creates a pmap for a new task. - * If not already allocated, malloc space for one. + * If not already allocated, allocate space for one. */ struct pmap * pmap_create(void) { struct pmap *pmap; - pmap = malloc(sizeof(*pmap), M_VMPMAP, M_WAITOK|M_ZERO); + pmap = kmem_zalloc(sizeof(*pmap), KM_SLEEP); pmap_pinit(pmap); - simple_lock_init(&pmap->pm_lock); - return (pmap); + return pmap; } /* @@ -947,32 +971,25 @@ * pmap_destroy(pmap): Remove a reference from the pmap. * If the pmap is NULL then just return else decrese pm_count. * If this was the last reference we call's pmap_relaese to release this pmap. - * OBS! remember to set pm_lock */ void pmap_destroy(pmap_t pmap) { - int count; - PMDEBUG(("pmap_destroy: pmap %p\n",pmap)); - simple_lock(&pmap->pm_lock); - count = --pmap->pm_count; - simple_unlock(&pmap->pm_lock); - - if (count == 0) { + if (atomic_dec_uint_nv(&pmap->pm_count) == 0) { #ifdef DIAGNOSTIC if (pmap->pm_pcbs) panic("pmap_destroy used pmap"); #endif pmap_release(pmap); - free(pmap, M_VMPMAP); + kmem_free(pmap, sizeof(*pmap)); } } static struct pte * -vaddrtopte(struct pv_entry *pv) +vaddrtopte(const struct pv_entry *pv) { struct pmap *pm; if (pv->pv_pmap == NULL || pv->pv_vaddr == NOVADDR) @@ -1061,7 +1078,7 @@ pmap_enter(pmap_t pmap, vaddr_t v, paddr_t p, vm_prot_t prot, u_int flags) { struct pv_entry *pv, *tmp; - int s, newpte, oldpte; + int newpte, oldpte; int *pteptr; /* current pte to write mapping info to */ int *ptpptr; /* ptr to page table page */ @@ -1105,7 +1122,7 @@ if (*ptpptr == 0) { paddr_t phys; - phys = get_ptp(flags & PMAP_CANFAIL ? NOWAIT : WAITOK); + phys = get_ptp((flags & PMAP_CANFAIL) != 0); if (phys == 0) { RECURSEEND; return ENOMEM; @@ -1117,7 +1134,7 @@ /* * Do not keep track of anything if mapping IO space. */ - if (IOSPACE(p)) { + if (IOSPACE_P(p)) { mapin8(pteptr, newpte); RECURSEEND; return 0; @@ -1147,9 +1164,7 @@ if ((newpte & PG_FRAME) == (oldpte & PG_FRAME)) { /* prot change. resident_count will be increased later */ - pmap->pm_stats.resident_count--; - if (oldpte & PG_W) - pmap->pm_stats.wired_count--; + pmap_decrement_stats(pmap, (oldpte & PG_W) != 0); } else { /* @@ -1165,7 +1180,6 @@ RECURSESTART; } - s = splvm(); PVTABLE_LOCK; if (pv->pv_pmap == NULL) { pv->pv_vaddr = v; @@ -1178,11 +1192,8 @@ pv->pv_next = tmp; } PVTABLE_UNLOCK; - splx(s); } - pmap->pm_stats.resident_count++; - if (flags & PMAP_WIRED) - pmap->pm_stats.wired_count++; + pmap_increment_stats(pmap, (flags & PMAP_WIRED) != 0); PVTABLE_LOCK; if (flags & (VM_PROT_READ|VM_PROT_WRITE)) { @@ -1366,6 +1377,7 @@ } int pmap_simulref(int bits, int addr); + /* * Called from interrupt vector routines if we get a page invalid fault. * Note: the save mask must be or'ed with 0x3f for this function. @@ -1413,7 +1425,7 @@ pte[5] |= PG_V; pte[6] |= PG_V; pte[7] |= PG_V; - if (IOSPACE(pa) == 0) { /* No pv_table fiddling in iospace */ + if (!IOSPACE_P(pa)) { /* No pv_table fiddling in iospace */ PVTABLE_LOCK; pv = pv_table + (pa >> PGSHIFT); pv->pv_attr |= PG_V; /* Referenced */ @@ -1428,7 +1440,7 @@ * Clears valid bit in all ptes referenced to this physical page. */ bool -pmap_clear_reference_long(struct pv_entry *pv) +pmap_clear_reference_long(const struct pv_entry *pv) { struct pte *pte; int ref = 0; @@ -1437,17 +1449,7 @@ RECURSESTART; PVTABLE_LOCK; - if (pv->pv_pmap != NULL) { - pte = vaddrtopte(pv); - if (pte->pg_w == 0) { - pte[0].pg_v = 0; pte[1].pg_v = 0; - pte[2].pg_v = 0; pte[3].pg_v = 0; - pte[4].pg_v = 0; pte[5].pg_v = 0; - pte[6].pg_v = 0; pte[7].pg_v = 0; - } - } - - while ((pv = pv->pv_next)) { + if (pv->pv_pmap != NULL) do { pte = vaddrtopte(pv); if (pte[0].pg_w == 0) { pte[0].pg_v = 0; pte[1].pg_v = 0; @@ -1455,7 +1457,7 @@ pte[4].pg_v = 0; pte[5].pg_v = 0; pte[6].pg_v = 0; pte[7].pg_v = 0; } - } + } while ((pv = pv->pv_next) != NULL); PVTABLE_UNLOCK; RECURSEEND; #ifdef MULTIPROCESSOR @@ -1469,68 +1471,45 @@ * Checks if page is modified; returns true or false depending on result. */ bool -pmap_is_modified_long(struct pv_entry *pv) +pmap_is_modified_long_p(const struct pv_entry *pv) { - struct pte *pte; + bool rv = false; PMDEBUG(("pmap_is_modified: pv_entry %p ", pv)); PVTABLE_LOCK; - if (pv->pv_pmap != NULL) { - pte = vaddrtopte(pv); - if ((pte[0].pg_m | pte[1].pg_m | pte[2].pg_m | pte[3].pg_m | - pte[4].pg_m | pte[5].pg_m | pte[6].pg_m | pte[7].pg_m)) { - PMDEBUG(("Yes: (1)\n")); - PVTABLE_UNLOCK; - return 1; - } - } - - while ((pv = pv->pv_next)) { - pte = vaddrtopte(pv); - if ((pte[0].pg_m | pte[1].pg_m | pte[2].pg_m | pte[3].pg_m - | pte[4].pg_m | pte[5].pg_m | pte[6].pg_m | pte[7].pg_m)) { - PMDEBUG(("Yes: (2)\n")); - PVTABLE_UNLOCK; - return 1; + if (pv->pv_pmap != NULL) do { + const struct pte * const pte = vaddrtopte(pv); + if (pte[0].pg_m | pte[1].pg_m | pte[2].pg_m | pte[3].pg_m + | pte[4].pg_m | pte[5].pg_m | pte[6].pg_m | pte[7].pg_m) { + rv = true; + break; } - } + } while ((pv = pv->pv_next) != NULL); PVTABLE_UNLOCK; - PMDEBUG(("No\n")); - return 0; + return rv; } /* * Clears modify bit in all ptes referenced to this physical page. */ bool -pmap_clear_modify_long(struct pv_entry *pv) +pmap_clear_modify_long(const struct pv_entry *pv) { - struct pte *pte; bool rv = false; PMDEBUG(("pmap_clear_modify: pv_entry %p\n", pv)); PVTABLE_LOCK; - if (pv->pv_pmap != NULL) { - pte = vaddrtopte(pv); - if (pte[0].pg_m | pte[1].pg_m | pte[2].pg_m | pte[3].pg_m | - pte[4].pg_m | pte[5].pg_m | pte[6].pg_m | pte[7].pg_m) { - rv = true; - } - pte[0].pg_m = pte[1].pg_m = pte[2].pg_m = pte[3].pg_m = - pte[4].pg_m = pte[5].pg_m = pte[6].pg_m = pte[7].pg_m = 0; - } - - while ((pv = pv->pv_next)) { - pte = vaddrtopte(pv); + if (pv->pv_pmap != NULL) do { + struct pte * const pte = vaddrtopte(pv); if (pte[0].pg_m | pte[1].pg_m | pte[2].pg_m | pte[3].pg_m | pte[4].pg_m | pte[5].pg_m | pte[6].pg_m | pte[7].pg_m) { rv = true; } - pte[0].pg_m = pte[1].pg_m = pte[2].pg_m = pte[3].pg_m = - pte[4].pg_m = pte[5].pg_m = pte[6].pg_m = pte[7].pg_m = 0; - } + pte[0].pg_m = pte[1].pg_m = pte[2].pg_m = pte[3].pg_m = 0; + pte[4].pg_m = pte[5].pg_m = pte[6].pg_m = pte[7].pg_m = 0; + } while ((pv = pv->pv_next) != NULL); PVTABLE_UNLOCK; return rv; } @@ -1545,26 +1524,19 @@ { struct pte *pt; struct pv_entry *opv, *pl; - int s, *g; + int *g; PMDEBUG(("pmap_page_protect: pv %p, prot %x\n", pv, prot)); - if (prot == VM_PROT_ALL) /* 'cannot happen' */ return; RECURSESTART; PVTABLE_LOCK; if (prot == VM_PROT_NONE) { - s = splvm(); g = (int *)vaddrtopte(pv); if (g) { - simple_lock(&pv->pv_pmap->pm_lock); - pv->pv_pmap->pm_stats.resident_count--; - if (g[0] & PG_W) { - pv->pv_pmap->pm_stats.wired_count--; - } - simple_unlock(&pv->pv_pmap->pm_lock); + pmap_decrement_stats(pv->pv_pmap, (g[0] & PG_W) != 0); if ((pv->pv_attr & (PG_V|PG_M)) != (PG_V|PG_M)) pv->pv_attr |= g[0]|g[1]|g[2]|g[3]|g[4]|g[5]|g[6]|g[7]; @@ -1581,12 +1553,7 @@ pv->pv_next = 0; while (pl) { g = (int *)vaddrtopte(pl); - simple_lock(&pl->pv_pmap->pm_lock); - pl->pv_pmap->pm_stats.resident_count--; - if (g[0] & PG_W) { - pl->pv_pmap->pm_stats.wired_count--; - } - simple_unlock(&pl->pv_pmap->pm_lock); + pmap_decrement_stats(pl->pv_pmap, (g[0] & PG_W) != 0); if ((pv->pv_attr & (PG_V|PG_M)) != (PG_V|PG_M)) pv->pv_attr |= g[0]|g[1]|g[2]|g[3]|g[4]|g[5]|g[6]|g[7]; @@ -1599,7 +1566,6 @@ pl = pl->pv_next; free_pventry(opv); } - splx(s); } else { /* read-only */ do { int pr; @@ -1770,7 +1736,7 @@ struct pv_entry *pv; int s, i, count; - pv = (struct pv_entry *)getpage(NOWAIT); + pv = (struct pv_entry *)getpage(false); if (pv == NULL) return; count = PAGE_SIZE/sizeof(struct pv_entry); @@ -1793,7 +1759,7 @@ * Get a (vax-size) page, to use for page tables. */ vaddr_t -get_ptp(int w) +get_ptp(bool wait) { int *a; @@ -1802,7 +1768,7 @@ memset(a, 0, VAX_NBPG); return (vaddr_t)a; } - a = (int *)getpage(w); + a = (int *)getpage(wait); if (a != NULL) { a[128] = (int)&a[256]; a[256] = (int)&a[384];