diff options
author | Philip Guenther <guenther@cvs.openbsd.org> | 2018-09-12 06:09:40 +0000 |
---|---|---|
committer | Philip Guenther <guenther@cvs.openbsd.org> | 2018-09-12 06:09:40 +0000 |
commit | 83942f081d5efe5b6e55bcf4d891645c7df2d13b (patch) | |
tree | 856a78be6998204ad843fef643ee763be1372ba3 /sys/arch | |
parent | e55f253f4f87913ac139b207d8d23303fe86a63a (diff) |
When shooting pages in the KVA range, all pmaps have the page mapped,
not just pmap_kernel() and this CPUs pmap. Meanwhile, when mapping
another pmap's tables, order the locking so that we don't need IPIs
specific to the temp pmap.
tested in snaps for a bit
ok mlarkin@
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/amd64/amd64/pmap.c | 48 |
1 files changed, 26 insertions, 22 deletions
diff --git a/sys/arch/amd64/amd64/pmap.c b/sys/arch/amd64/amd64/pmap.c index 3b13d45d2fa..ded25b56bcf 100644 --- a/sys/arch/amd64/amd64/pmap.c +++ b/sys/arch/amd64/amd64/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.118 2018/09/09 22:46:54 guenther Exp $ */ +/* $OpenBSD: pmap.c,v 1.119 2018/09/12 06:09:39 guenther Exp $ */ /* $NetBSD: pmap.c,v 1.3 2003/05/08 18:13:13 thorpej Exp $ */ /* @@ -375,28 +375,28 @@ pmap_sync_flags_pte(struct vm_page *pg, u_long pte) paddr_t pmap_map_ptes(struct pmap *pmap) { - paddr_t cr3 = rcr3(); + paddr_t cr3; KASSERT(pmap->pm_type != PMAP_TYPE_EPT); /* the kernel's pmap is always accessible */ - if (pmap == pmap_kernel() || pmap->pm_pdirpa == cr3) { - cr3 = 0; - } else { - /* - * Not sure if we need this, but better be safe. - * We don't have the current pmap in order to unset its - * active bit, but this just means that we may receive - * an unneccessary cross-CPU TLB flush now and then. - */ - x86_atomic_setbits_u64(&pmap->pm_cpus, (1ULL << cpu_number())); + if (pmap == pmap_kernel()) + return 0; + /* + * Lock the target map before switching to its page tables to + * guarantee other CPUs have finished changing the tables before + * we potentially start caching table and TLB entries. + */ + mtx_enter(&pmap->pm_mtx); + + cr3 = rcr3(); + if (pmap->pm_pdirpa == cr3) + cr3 = 0; + else { lcr3(pmap->pm_pdirpa); } - if (pmap != pmap_kernel()) - mtx_enter(&pmap->pm_mtx); - return cr3; } @@ -406,10 +406,8 @@ pmap_unmap_ptes(struct pmap *pmap, paddr_t save_cr3) if (pmap != pmap_kernel()) mtx_leave(&pmap->pm_mtx); - if (save_cr3 != 0) { - x86_atomic_clearbits_u64(&pmap->pm_cpus, (1ULL << cpu_number())); + if (save_cr3 != 0) lcr3(save_cr3); - } } int @@ -2864,10 +2862,12 @@ pmap_tlb_shootpage(struct pmap *pm, vaddr_t va, int shootself) CPU_INFO_ITERATOR cii; long wait = 0; u_int64_t mask = 0; + int is_kva = va >= VM_MIN_KERNEL_ADDRESS; CPU_INFO_FOREACH(cii, ci) { - if (ci == self || !pmap_is_active(pm, ci->ci_cpuid) || - !(ci->ci_flags & CPUF_RUNNING)) + if (ci == self || !(ci->ci_flags & CPUF_RUNNING)) + continue; + if (!is_kva && !pmap_is_active(pm, ci->ci_cpuid)) continue; mask |= (1ULL << ci->ci_cpuid); wait++; @@ -2913,11 +2913,13 @@ pmap_tlb_shootrange(struct pmap *pm, vaddr_t sva, vaddr_t eva, int shootself) CPU_INFO_ITERATOR cii; long wait = 0; u_int64_t mask = 0; + int is_kva = sva >= VM_MIN_KERNEL_ADDRESS; vaddr_t va; CPU_INFO_FOREACH(cii, ci) { - if (ci == self || !pmap_is_active(pm, ci->ci_cpuid) || - !(ci->ci_flags & CPUF_RUNNING)) + if (ci == self || !(ci->ci_flags & CPUF_RUNNING)) + continue; + if (!is_kva && !pmap_is_active(pm, ci->ci_cpuid)) continue; mask |= (1ULL << ci->ci_cpuid); wait++; @@ -2966,6 +2968,8 @@ pmap_tlb_shoottlb(struct pmap *pm, int shootself) long wait = 0; u_int64_t mask = 0; + KASSERT(pm != pmap_kernel()); + CPU_INFO_FOREACH(cii, ci) { if (ci == self || !pmap_is_active(pm, ci->ci_cpuid) || !(ci->ci_flags & CPUF_RUNNING)) |