summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2004-09-22 05:01:48 +0000
committeralc <alc@FreeBSD.org>2004-09-22 05:01:48 +0000
commita6bec8ad06399f6bbb0400f2687dcbcf9194bcaa (patch)
treee61fba398388d4bbe050157107a9f6404efd8940 /sys/amd64
parent5015e1ce1f752bcd12077a0c593c58e8085710df (diff)
downloadFreeBSD-src-a6bec8ad06399f6bbb0400f2687dcbcf9194bcaa.zip
FreeBSD-src-a6bec8ad06399f6bbb0400f2687dcbcf9194bcaa.tar.gz
Correct a long-standing error in _pmap_unwire_pte_hold() affecting
multiprocessors. Specifically, the error is conditioning the call to pmap_invalidate_page() on whether the pmap is active on the current CPU. This call must be unconditional. Regardless of whether the pmap is active on the CPU performing _pmap_unwire_pte_hold(), it could be active on another CPU. For example, a call to pmap_remove_all() by the page daemon could result in a call to _pmap_unwire_pte_hold() with the pmap inactive on the current CPU and active on another CPU. In such circumstances, failing to call pmap_invalidate_page() results in a stale TLB entry on the other CPU that still maps the now deallocated page table page. What happens next is typically a mysterious panic in pmap_enter() by the other CPU, either "pmap_enter: attempted pmap_enter on 4MB page" or "pmap_enter: pte vanished, va: 0x%lx". Both occur because the former page table page has been recycled and allocated to a new purpose. Consequently, it no longer contains zeroes. See also Peter's i386/i386/pmap.c revision 1.448 and the related e-mail thread last year. Many thanks to the engineers at Sandvine for providing clear and concise information until all of the pieces of the puzzle fell into place and for testing an earlier patch. MT5 Candidate
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/amd64/pmap.c13
1 files changed, 6 insertions, 7 deletions
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index d3ce849..0af74de 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -1014,13 +1014,12 @@ _pmap_unwire_pte_hold(pmap_t pmap, vm_offset_t va, vm_page_t m)
pdppg = PHYS_TO_VM_PAGE(*pmap_pml4e(pmap, va) & PG_FRAME);
pmap_unwire_pte_hold(pmap, va, pdppg);
}
- if (pmap_is_current(pmap)) {
- /*
- * Do an invltlb to make the invalidated mapping
- * take effect immediately.
- */
- pmap_invalidate_page(pmap, pteva);
- }
+
+ /*
+ * Do an invltlb to make the invalidated mapping
+ * take effect immediately.
+ */
+ pmap_invalidate_page(pmap, pteva);
vm_page_free_zero(m);
atomic_subtract_int(&cnt.v_wire_count, 1);
OpenPOWER on IntegriCloud