Module Name: src Committed By: ad Date: Sat Mar 21 18:47:54 UTC 2020
Modified Files: src/sys/arch/vax/include: pmap.h src/sys/arch/vax/vax: pmap.c Log Message: PR port-vax/55094: vax pmap needs locking adjustments Make the adjustments noted in the PR and don't call uvm_wait() or do WAITOK ever - UVM takes care of that. To generate a diff of this commit: cvs rdiff -u -r1.81 -r1.82 src/sys/arch/vax/include/pmap.h cvs rdiff -u -r1.189 -r1.190 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.81 src/sys/arch/vax/include/pmap.h:1.82 --- src/sys/arch/vax/include/pmap.h:1.81 Sat Mar 14 14:05:44 2020 +++ src/sys/arch/vax/include/pmap.h Sat Mar 21 18:47:54 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.h,v 1.81 2020/03/14 14:05:44 ad Exp $ */ +/* $NetBSD: pmap.h,v 1.82 2020/03/21 18:47:54 ad Exp $ */ /* * Copyright (c) 1991 Regents of the University of California. @@ -189,9 +189,6 @@ pmap_extract(pmap_t pmap, vaddr_t va, pa return (false); } -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); @@ -209,38 +206,6 @@ pmap_is_referenced(struct vm_page *pg) return (pv->pv_attr & PG_V) != 0; } -static __inline bool -pmap_clear_reference(struct vm_page *pg) -{ - struct pv_entry * const pv = pmap_pg_to_pv(pg); - bool rv = (pv->pv_attr & PG_V) != 0; - - pv->pv_attr &= ~PG_V; - if (pv->pv_pmap != NULL || pv->pv_next != NULL) - rv |= pmap_clear_reference_long(pv); - return rv; -} - -static __inline bool -pmap_clear_modify(struct vm_page *pg) -{ - struct pv_entry * const pv = pmap_pg_to_pv(pg); - bool rv = (pv->pv_attr & PG_M) != 0; - - pv->pv_attr &= ~PG_M; - if (pv->pv_pmap != NULL || pv->pv_next != NULL) - rv |= pmap_clear_modify_long(pv); - return rv; -} - -static __inline bool -pmap_is_modified(struct vm_page *pg) -{ - const struct pv_entry * const pv = pmap_pg_to_pv(pg); - - return (pv->pv_attr & PG_M) != 0 || pmap_is_modified_long_p(pv); -} - static __inline void pmap_page_protect(struct vm_page *pg, vm_prot_t prot) { Index: src/sys/arch/vax/vax/pmap.c diff -u src/sys/arch/vax/vax/pmap.c:1.189 src/sys/arch/vax/vax/pmap.c:1.190 --- src/sys/arch/vax/vax/pmap.c:1.189 Sat Feb 15 18:12:14 2020 +++ src/sys/arch/vax/vax/pmap.c Sat Mar 21 18:47:54 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.c,v 1.189 2020/02/15 18:12:14 ad Exp $ */ +/* $NetBSD: pmap.c,v 1.190 2020/03/21 18:47:54 ad Exp $ */ /* * Copyright (c) 1994, 1998, 1999, 2003 Ludd, University of Lule}, Sweden. * All rights reserved. @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.189 2020/02/15 18:12:14 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.190 2020/03/21 18:47:54 ad Exp $"); #include "opt_ddb.h" #include "opt_cputype.h" @@ -114,29 +114,9 @@ extern void *msgbufaddr; 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 } /* @@ -171,27 +151,18 @@ ptpinuse(void *pte) } #ifdef PMAPDEBUG -volatile int recurse; -#define RECURSESTART { \ - if (recurse) \ - printf("enter at %d, previous %d\n", __LINE__, recurse);\ - recurse = __LINE__; \ -} -#define RECURSEEND {recurse = 0; } #define PMDEBUG(x) if (startpmapdebug)printf x #else -#define RECURSESTART -#define RECURSEEND #define PMDEBUG(x) #endif #if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) -static kmutex_t pvtable_lock; -#define PVTABLE_LOCK mutex_spin_enter(&pvtable_lock); -#define PVTABLE_UNLOCK mutex_spin_enter(&pvtable_lock); +static kmutex_t pmap_lock; +#define PMAP_LOCK mutex_spin_enter(&pmap_lock); +#define PMAP_UNLOCK mutex_spin_enter(&pmap_lock); #else -#define PVTABLE_LOCK -#define PVTABLE_UNLOCK +#define PMAP_LOCK +#define PMAP_UNLOCK #endif #ifdef PMAPDEBUG @@ -204,7 +175,7 @@ vaddr_t virtual_avail, virtual_end; /* struct pv_entry *get_pventry(void); void free_pventry(struct pv_entry *); void more_pventries(void); -vaddr_t get_ptp(bool); +vaddr_t get_ptp(void); void free_ptp(paddr_t); /* @@ -434,7 +405,7 @@ pmap_bootstrap(void) SIMPLEQ_FIRST(&cpus) = ci; #endif #if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) - mutex_init(&pvtable_lock, MUTEX_DEFAULT, IPL_VM); + mutex_init(&pmap_lock, MUTEX_DEFAULT, IPL_VM); #endif /* @@ -606,18 +577,13 @@ update_pcbs(struct pmap *pm) * Allocate a page through direct-mapped segment. */ static vaddr_t -getpage(bool wait) +getpage(void) { struct vm_page *pg; - for (;;) { - pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO); - if (pg != NULL) - break; - if (!wait) - return 0; - uvm_wait("getpage"); - } + pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO); + if (pg == NULL) + return 0; return (VM_PAGE_TO_PHYS(pg)|KERNBASE); } @@ -813,9 +779,9 @@ grow_p0(struct pmap *pm, int reqlen) p0lr = pm->pm_p0lr; inuse = p0lr != 0; len = round_page((reqlen+1) * PPTESZ); - RECURSEEND; + PMAP_UNLOCK; nptespc = pmap_getusrptes(pm, len); - RECURSESTART; + PMAP_LOCK; if (nptespc == 0) return 0; @@ -856,9 +822,9 @@ grow_p1(struct pmap *pm, int len) /* Get new pte space */ nlen = (NPTEPERREG*PPTESZ) - trunc_page(len * PPTESZ); - RECURSEEND; + PMAP_UNLOCK; nptespc = pmap_getusrptes(pm, nlen); - RECURSESTART; + PMAP_LOCK; if (nptespc == 0) return 0; @@ -1086,7 +1052,7 @@ pmap_enter(pmap_t pmap, vaddr_t v, paddr PMDEBUG(("pmap_enter: pmap %p v %lx p %lx prot %x wired %d access %x\n", pmap, v, p, prot, (flags & PMAP_WIRED) != 0, flags & VM_PROT_ALL)); - RECURSESTART; + PMAP_LOCK; /* Find address of correct pte */ switch (SEGTYPE(v)) { @@ -1124,10 +1090,12 @@ pmap_enter(pmap_t pmap, vaddr_t v, paddr if (*ptpptr == 0) { paddr_t phys; - phys = get_ptp((flags & PMAP_CANFAIL) != 0); + phys = get_ptp(); if (phys == 0) { - RECURSEEND; - return ENOMEM; + PMAP_UNLOCK; + if ((flags & PMAP_CANFAIL) != 0) + return ENOMEM; + panic("pmap_enter: out of memory"); } *ptpptr = PG_V | PG_KW | PG_PFNUM(phys); } @@ -1138,7 +1106,7 @@ pmap_enter(pmap_t pmap, vaddr_t v, paddr */ if (IOSPACE_P(p)) { mapin8(pteptr, newpte); - RECURSEEND; + PMAP_UNLOCK; return 0; } @@ -1152,13 +1120,13 @@ pmap_enter(pmap_t pmap, vaddr_t v, paddr if (newpte == (oldpte | PG_W)) { *pteptr |= PG_W; pmap->pm_stats.wired_count++; - RECURSEEND; + PMAP_UNLOCK; return 0; } /* mapping unchanged? just return. */ if (newpte == oldpte) { - RECURSEEND; + PMAP_UNLOCK; return 0; } @@ -1174,15 +1142,14 @@ pmap_enter(pmap_t pmap, vaddr_t v, paddr */ if (oldpte & PG_FRAME) { - RECURSEEND; if ((oldpte & PG_SREF) == 0) rmpage(pmap, pteptr); - else + else { + PMAP_UNLOCK; panic("pmap_enter on PG_SREF page"); - RECURSESTART; + } } - PVTABLE_LOCK; if (pv->pv_pmap == NULL) { pv->pv_vaddr = v; pv->pv_pmap = pmap; @@ -1193,28 +1160,28 @@ pmap_enter(pmap_t pmap, vaddr_t v, paddr tmp->pv_next = pv->pv_next; pv->pv_next = tmp; } - PVTABLE_UNLOCK; } - pmap_increment_stats(pmap, (flags & PMAP_WIRED) != 0); + pmap->pm_stats.resident_count++; + if ((flags & PMAP_WIRED) != 0) + pmap->pm_stats.wired_count++; - PVTABLE_LOCK; if (flags & (VM_PROT_READ|VM_PROT_WRITE)) { pv->pv_attr |= PG_V; newpte |= PG_V; } if (flags & VM_PROT_WRITE) pv->pv_attr |= PG_M; - PVTABLE_UNLOCK; if (flags & PMAP_WIRED) newpte |= PG_V; /* Not allowed to be invalid */ mapin8(pteptr, newpte); - RECURSEEND; if (pventries < 10) more_pventries(); + PMAP_UNLOCK; + mtpr(0, PR_TBIA); /* Always; safety belt */ return 0; @@ -1294,7 +1261,7 @@ pmap_protect_long(pmap_t pmap, vaddr_t s PMDEBUG(("pmap_protect: pmap %p, start %lx, end %lx, prot %x\n", pmap, start, end,prot)); - RECURSESTART; + PMAP_LOCK; switch (SEGTYPE(start)) { case SYSSEG: @@ -1310,7 +1277,7 @@ pmap_protect_long(pmap_t pmap, vaddr_t s case P1SEG: if (vax_btop(end - 0x40000000) <= pmap->pm_p1lr) { - RECURSEEND; + PMAP_UNLOCK; return; } if (vax_btop(start - 0x40000000) < pmap->pm_p1lr) @@ -1326,7 +1293,7 @@ pmap_protect_long(pmap_t pmap, vaddr_t s /* Anything to care about at all? */ if (vax_btop(start) > lr) { - RECURSEEND; + PMAP_UNLOCK; return; } if (vax_btop(end) > lr) @@ -1350,14 +1317,14 @@ pmap_protect_long(pmap_t pmap, vaddr_t s while (pts < ptd) { if (kvtopte(pts)->pg_pfn && *(int *)pts) { if (prot == VM_PROT_NONE) { - RECURSEEND; if ((*(int *)pts & PG_SREF) == 0) rmpage(pmap, (u_int *)pts); #ifdef DEBUG - else + else { + PMAP_UNLOCK; panic("pmap_remove PG_SREF page"); + } #endif - RECURSESTART; memset(pts, 0, sizeof(struct pte) * LTOHPN); if (pt != Sysmap) { if (ptpinuse(pts) == 0) @@ -1376,7 +1343,7 @@ pmap_protect_long(pmap_t pmap, vaddr_t s } pts += LTOHPN; } - RECURSEEND; + PMAP_UNLOCK; #ifdef MULTIPROCESSOR cpu_send_ipi(IPI_DEST_ALL, IPI_TBIA); #endif @@ -1433,12 +1400,12 @@ pmap_simulref(int bits, int addr) pte[6] |= PG_V; pte[7] |= PG_V; if (!IOSPACE_P(pa)) { /* No pv_table fiddling in iospace */ - PVTABLE_LOCK; + PMAP_LOCK; pv = pv_table + (pa >> PGSHIFT); pv->pv_attr |= PG_V; /* Referenced */ if (bits & 4) /* (will be) modified. XXX page tables */ pv->pv_attr |= PG_M; - PVTABLE_UNLOCK; + PMAP_UNLOCK; } return 0; } @@ -1447,15 +1414,17 @@ pmap_simulref(int bits, int addr) * Clears valid bit in all ptes referenced to this physical page. */ bool -pmap_clear_reference_long(const struct pv_entry *pv) +pmap_clear_reference(struct vm_page *pg) { + struct pv_entry *pv = pmap_pg_to_pv(pg); struct pte *pte; - int ref = 0; + bool ref; PMDEBUG(("pmap_clear_reference: pv_entry %p\n", pv)); - RECURSESTART; - PVTABLE_LOCK; + PMAP_LOCK; + ref = ISSET(pv->pv_attr, PG_V); + CLR(pv->pv_attr, PG_V); if (pv->pv_pmap != NULL) do { pte = vaddrtopte(pv); if (pte[0].pg_w == 0) { @@ -1465,8 +1434,7 @@ pmap_clear_reference_long(const struct p pte[6].pg_v = 0; pte[7].pg_v = 0; } } while ((pv = pv->pv_next) != NULL); - PVTABLE_UNLOCK; - RECURSEEND; + PMAP_UNLOCK; #ifdef MULTIPROCESSOR cpu_send_ipi(IPI_DEST_ALL, IPI_TBIA); #endif @@ -1478,14 +1446,16 @@ pmap_clear_reference_long(const struct p * Checks if page is modified; returns true or false depending on result. */ bool -pmap_is_modified_long_p(const struct pv_entry *pv) +pmap_is_modified(struct vm_page *pg) { - bool rv = false; + struct pv_entry *pv = pmap_pg_to_pv(pg); + bool rv; PMDEBUG(("pmap_is_modified: pv_entry %p ", pv)); - PVTABLE_LOCK; - if (pv->pv_pmap != NULL) do { + PMAP_LOCK; + rv = ISSET(pv->pv_attr, PG_M); + if (rv == false && 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) { @@ -1493,7 +1463,7 @@ pmap_is_modified_long_p(const struct pv_ break; } } while ((pv = pv->pv_next) != NULL); - PVTABLE_UNLOCK; + PMAP_UNLOCK; return rv; } @@ -1501,13 +1471,16 @@ pmap_is_modified_long_p(const struct pv_ * Clears modify bit in all ptes referenced to this physical page. */ bool -pmap_clear_modify_long(const struct pv_entry *pv) +pmap_clear_modify(struct vm_page *pg) { + struct pv_entry *pv = pmap_pg_to_pv(pg); bool rv = false; PMDEBUG(("pmap_clear_modify: pv_entry %p\n", pv)); - PVTABLE_LOCK; + PMAP_LOCK; + rv = ISSET(pv->pv_attr, PG_M); + CLR(pv->pv_attr, PG_M); 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 | @@ -1517,7 +1490,7 @@ pmap_clear_modify_long(const struct pv_e 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; + PMAP_UNLOCK; return rv; } @@ -1538,8 +1511,7 @@ pmap_page_protect_long(struct pv_entry * if (prot == VM_PROT_ALL) /* 'cannot happen' */ return; - RECURSESTART; - PVTABLE_LOCK; + PMAP_LOCK; if (prot == VM_PROT_NONE) { g = (int *)vaddrtopte(pv); if (g) { @@ -1586,8 +1558,7 @@ pmap_page_protect_long(struct pv_entry * pt[6].pg_prot = pr; pt[7].pg_prot = pr; } while ((pv = pv->pv_next)); } - PVTABLE_UNLOCK; - RECURSEEND; + PMAP_UNLOCK; #ifdef MULTIPROCESSOR cpu_send_ipi(IPI_DEST_ALL, IPI_TBIA); #endif @@ -1682,7 +1653,7 @@ pmap_unwire(pmap_t pmap, vaddr_t v) PMDEBUG(("pmap_unwire: pmap %p v %lx\n", pmap, v)); - RECURSESTART; + PMAP_LOCK; if (v & KERNBASE) { pte = (int *)kvtopte(v); } else { @@ -1692,8 +1663,8 @@ pmap_unwire(pmap_t pmap, vaddr_t v) pte = (int *)&pmap->pm_p1br[PG_PFNUM(v)]; } pte[0] &= ~PG_W; - RECURSEEND; pmap->pm_stats.wired_count--; + PMAP_UNLOCK; } /* @@ -1735,15 +1706,15 @@ free_pventry(struct pv_entry *pv) /* * more_pventries(). - * The pv_table lock must _not_ be held before calling this. + * The pmap_lock must be held before calling this. */ void more_pventries(void) { struct pv_entry *pv; - int s, i, count; + int i, count; - pv = (struct pv_entry *)getpage(false); + pv = (struct pv_entry *)getpage(); if (pv == NULL) return; count = PAGE_SIZE/sizeof(struct pv_entry); @@ -1751,13 +1722,9 @@ more_pventries(void) for (i = 0; i < count - 1; i++) pv[i].pv_next = &pv[i + 1]; - s = splvm(); - PVTABLE_LOCK; pv[count - 1].pv_next = pv_list; pv_list = pv; pventries += count; - PVTABLE_UNLOCK; - splx(s); } static int *ptpp; @@ -1766,7 +1733,7 @@ static int *ptpp; * Get a (vax-size) page, to use for page tables. */ vaddr_t -get_ptp(bool wait) +get_ptp(void) { int *a; @@ -1775,7 +1742,7 @@ get_ptp(bool wait) memset(a, 0, VAX_NBPG); return (vaddr_t)a; } - a = (int *)getpage(wait); + a = (int *)getpage(); if (a != NULL) { a[128] = (int)&a[256]; a[256] = (int)&a[384];