summaryrefslogtreecommitdiffstats
path: root/sys/i386/xen/pmap.c
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2012-10-08 16:57:05 +0000
committeralc <alc@FreeBSD.org>2012-10-08 16:57:05 +0000
commit41b1f8207c32e613f4f60a6b4e70ff2fb877a32e (patch)
treec9d5fbd978bf6d11a9da39e1dcf430dca7c9ea8e /sys/i386/xen/pmap.c
parentea2e90dbb4d21d52967a0d5a48c7c68205b80759 (diff)
downloadFreeBSD-src-41b1f8207c32e613f4f60a6b4e70ff2fb877a32e.zip
FreeBSD-src-41b1f8207c32e613f4f60a6b4e70ff2fb877a32e.tar.gz
In a few places, like the implementation of ptrace(), a thread may call
upon pmap_enter() to create a mapping within a different address space, i.e., not the thread's own address space. On i386, this entails the creation of a temporary mapping to the affected page table page (PTP). In general, pmap_enter() will read from this PTP, allocate a PV entry, and write to this PTP. The trouble comes when the system is short of memory. In order to allocate a new PV entry, an older PV entry has to be reclaimed. Reclaiming a PV entry involves destroying a mapping, which requires access to the affected PTP. Thus, the PTP mapped at the beginning of pmap_enter() is no longer mapped at the end of pmap_enter(), which leads to pmap_enter() modifying the wrong PTP. To address this problem, pmap_pv_reclaim() is changed to use an alternate method of mapping PTPs. Update a related comment. Reported by: pho Diagnosed by: kib MFC after: 5 days
Diffstat (limited to 'sys/i386/xen/pmap.c')
-rw-r--r--sys/i386/xen/pmap.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c
index 46cb43c..2eea8c6 100644
--- a/sys/i386/xen/pmap.c
+++ b/sys/i386/xen/pmap.c
@@ -429,7 +429,8 @@ pmap_bootstrap(vm_paddr_t firstaddr)
SYSMAP(struct msgbuf *, unused, msgbufp, atop(round_page(msgbufsize)))
/*
- * ptemap is used for pmap_pte_quick
+ * PADDR1 and PADDR2 are used by pmap_pte_quick() and pmap_pte(),
+ * respectively.
*/
SYSMAP(pt_entry_t *, PMAP1, PADDR1, 1)
SYSMAP(pt_entry_t *, PMAP2, PADDR2, 1)
@@ -1976,7 +1977,6 @@ pmap_pv_reclaim(pmap_t locked_pmap)
pmap = NULL;
free = m_pc = NULL;
TAILQ_INIT(&newtail);
- sched_pin();
while ((pc = TAILQ_FIRST(&pv_chunks)) != NULL && (pv_vafree == 0 ||
free == NULL)) {
TAILQ_REMOVE(&pv_chunks, pc, pc_lru);
@@ -2007,10 +2007,13 @@ pmap_pv_reclaim(pmap_t locked_pmap)
bit = bsfl(inuse);
pv = &pc->pc_pventry[field * 32 + bit];
va = pv->pv_va;
- pte = pmap_pte_quick(pmap, va);
- if ((*pte & PG_W) != 0)
+ pte = pmap_pte(pmap, va);
+ tpte = *pte;
+ if ((tpte & PG_W) == 0)
+ tpte = pte_load_clear(pte);
+ pmap_pte_release(pte);
+ if ((tpte & PG_W) != 0)
continue;
- tpte = pte_load_clear(pte);
if ((tpte & PG_G) != 0)
pmap_invalidate_page(pmap, va);
m = PHYS_TO_VM_PAGE(tpte & PG_FRAME);
@@ -2062,7 +2065,6 @@ pmap_pv_reclaim(pmap_t locked_pmap)
}
}
out:
- sched_unpin();
TAILQ_CONCAT(&pv_chunks, &newtail, pc_lru);
if (pmap != NULL) {
pmap_invalidate_all(pmap);
OpenPOWER on IntegriCloud