Module Name: src Committed By: ad Date: Fri Mar 20 19:06:14 UTC 2020
Modified Files: src/sys/arch/x86/x86: pmap.c Log Message: - pmap_extract(): This needs to take the pmap's lock, to allow for concurrent removal of pages (a new requirement). - pmap_remove_pv(): Keep hold time of pp_lock as short as possible. - pmap_get_ptp(): Don't re-init struct pmap_page for PD PTPs. Would have no ill effects but is wrong regardless. To generate a diff of this commit: cvs rdiff -u -r1.378 -r1.379 src/sys/arch/x86/x86/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/x86/x86/pmap.c diff -u src/sys/arch/x86/x86/pmap.c:1.378 src/sys/arch/x86/x86/pmap.c:1.379 --- src/sys/arch/x86/x86/pmap.c:1.378 Thu Mar 19 18:58:14 2020 +++ src/sys/arch/x86/x86/pmap.c Fri Mar 20 19:06:14 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.c,v 1.378 2020/03/19 18:58:14 ad Exp $ */ +/* $NetBSD: pmap.c,v 1.379 2020/03/20 19:06:14 ad Exp $ */ /* * Copyright (c) 2008, 2010, 2016, 2017, 2019, 2020 The NetBSD Foundation, Inc. @@ -130,7 +130,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.378 2020/03/19 18:58:14 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.379 2020/03/20 19:06:14 ad Exp $"); #include "opt_user_ldt.h" #include "opt_lockdebug.h" @@ -2163,20 +2163,22 @@ pmap_remove_pv(struct pmap *pmap, struct pmap_check_pv(pmap, ptp, pp, va, true); - mutex_spin_enter(&pp->pp_lock); - pp->pp_attrs |= oattrs; if (pve == NULL) { + mutex_spin_enter(&pp->pp_lock); KASSERT(pp->pp_pte.pte_ptp == ptp); KASSERT(pp->pp_pte.pte_va == va); + pp->pp_attrs |= oattrs; pp->pp_pte.pte_ptp = NULL; pp->pp_pte.pte_va = 0; mutex_spin_exit(&pp->pp_lock); } else { + mutex_spin_enter(&pp->pp_lock); KASSERT(pp->pp_pte.pte_ptp != ptp || pp->pp_pte.pte_va != va); KASSERT(pve->pve_pte.pte_ptp == ptp); KASSERT(pve->pve_pte.pte_va == va); KASSERT(pve->pve_pp == pp); + pp->pp_attrs |= oattrs; LIST_REMOVE(pve, pve_list); mutex_spin_exit(&pp->pp_lock); @@ -2347,7 +2349,7 @@ pmap_get_ptp(struct pmap *pmap, struct p if (pt->pg[i] == NULL) { pmap_unget_ptp(pmap, pt); return ENOMEM; - } else { + } else if (pt->alloced[i]) { pt->pg[i]->uanon = (struct vm_anon *)(vaddr_t)~0L; rb_tree_init(&VM_PAGE_TO_PP(pt->pg[i])->pp_rb, &pmap_rbtree_ops); @@ -3427,10 +3429,8 @@ pmap_extract(struct pmap *pmap, vaddr_t pd_entry_t pde; pd_entry_t * const *pdes; struct pmap *pmap2; - struct cpu_info *ci; paddr_t pa; - lwp_t *l; - bool hard, rv; + bool rv; int lvl; if (__predict_false(pmap->pm_extract != NULL)) { @@ -3448,29 +3448,11 @@ pmap_extract(struct pmap *pmap, vaddr_t rv = false; pa = 0; - l = curlwp; - ci = l->l_cpu; - if (pmap == pmap_kernel() || - __predict_true(!ci->ci_want_pmapload && ci->ci_pmap == pmap)) { - /* - * no need to lock, because it's pmap_kernel() or our - * own pmap and is active. if a user pmap, the caller - * will hold the vm_map write/read locked and so prevent - * entries from disappearing while we are here. ptps - * can disappear via pmap_remove() and pmap_protect(), - * but they are called with the vm_map write locked. - */ - hard = false; - ptes = PTE_BASE; - pdes = normal_pdes; - kpreempt_disable(); - } else { - /* we lose, do it the hard way. */ - hard = true; + if (pmap != pmap_kernel()) { mutex_enter(&pmap->pm_lock); - pmap_map_ptes(pmap, &pmap2, &ptes, &pdes); } + pmap_map_ptes(pmap, &pmap2, &ptes, &pdes); if (pmap_pdes_valid(va, pdes, &pde, &lvl)) { if (lvl == 2) { pa = (pde & PTE_LGFRAME) | (va & (NBPD_L2 - 1)); @@ -3484,15 +3466,14 @@ pmap_extract(struct pmap *pmap, vaddr_t } } } - if (__predict_false(hard)) { - pmap_unmap_ptes(pmap, pmap2); + pmap_unmap_ptes(pmap, pmap2); + if (pmap != pmap_kernel()) { mutex_exit(&pmap->pm_lock); - } else { - kpreempt_enable(); } if (pap != NULL) { *pap = pa; } + return rv; }