Eliminate pmap_install(), which was used to wrap pmap_switch() and

grab sched_lock. This would serialize calls to pmap_switch from
cpu_switch(). With the introduction of thread_lock, this is not
possible anymore, because thread_lock is not a single lock. It
varies.  Secondly and most importantly, it's not needed at all. The
only requirement for pmap_switch() is that it's not preempted
while in the middle of updating the CPU and PCPU. In other words,
it's a critical region. No locking required.
This commit is contained in:
marcel 2007-06-07 16:04:23 +00:00
parent 229a009b9d
commit a137153bff

View File

@ -240,7 +240,6 @@ static pv_entry_t get_pv_entry(pmap_t locked_pmap);
static void pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va,
vm_page_t m, vm_prot_t prot);
static pmap_t pmap_install(pmap_t);
static void pmap_invalidate_all(pmap_t pmap);
static int pmap_remove_pte(pmap_t pmap, struct ia64_lpte *pte,
vm_offset_t va, pv_entry_t pv, int freepte);
@ -565,9 +564,9 @@ pmap_invalidate_page_1(void *arg)
pmap_t oldpmap;
critical_enter();
oldpmap = pmap_install(args[0]);
oldpmap = pmap_switch(args[0]);
pmap_invalidate_page_locally(args[1]);
pmap_install(oldpmap);
pmap_switch(oldpmap);
critical_exit();
}
#endif
@ -844,11 +843,11 @@ get_pv_entry(pmap_t locked_pmap)
PMAP_LOCK(pmap);
else if (pmap != locked_pmap && !PMAP_TRYLOCK(pmap))
continue;
oldpmap = pmap_install(pmap);
oldpmap = pmap_switch(pmap);
pte = pmap_find_vhpt(va);
KASSERT(pte != NULL, ("pte"));
pmap_remove_pte(pmap, pte, va, pv, 1);
pmap_install(oldpmap);
pmap_switch(oldpmap);
if (pmap != locked_pmap)
PMAP_UNLOCK(pmap);
if (allocated_pv == NULL)
@ -1053,11 +1052,11 @@ pmap_extract(pmap_t pmap, vm_offset_t va)
pa = 0;
PMAP_LOCK(pmap);
oldpmap = pmap_install(pmap);
oldpmap = pmap_switch(pmap);
pte = pmap_find_vhpt(va);
if (pte != NULL && pmap_present(pte))
pa = pmap_ppn(pte);
pmap_install(oldpmap);
pmap_switch(oldpmap);
PMAP_UNLOCK(pmap);
return (pa);
}
@ -1079,7 +1078,7 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
m = NULL;
vm_page_lock_queues();
PMAP_LOCK(pmap);
oldpmap = pmap_install(pmap);
oldpmap = pmap_switch(pmap);
pte = pmap_find_vhpt(va);
if (pte != NULL && pmap_present(pte) &&
(pmap_prot(pte) & prot) == prot) {
@ -1087,7 +1086,7 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
vm_page_hold(m);
}
vm_page_unlock_queues();
pmap_install(oldpmap);
pmap_switch(oldpmap);
PMAP_UNLOCK(pmap);
return (m);
}
@ -1399,7 +1398,7 @@ pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
vm_page_lock_queues();
PMAP_LOCK(pmap);
oldpmap = pmap_install(pmap);
oldpmap = pmap_switch(pmap);
/*
* special handling of removing one page. a very
@ -1430,7 +1429,7 @@ pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
out:
vm_page_unlock_queues();
pmap_install(oldpmap);
pmap_switch(oldpmap);
PMAP_UNLOCK(pmap);
}
@ -1469,13 +1468,13 @@ pmap_remove_all(vm_page_t m)
vm_offset_t va = pv->pv_va;
PMAP_LOCK(pmap);
oldpmap = pmap_install(pmap);
oldpmap = pmap_switch(pmap);
pte = pmap_find_vhpt(va);
KASSERT(pte != NULL, ("pte"));
if (pmap_ppn(pte) != VM_PAGE_TO_PHYS(m))
panic("pmap_remove_all: pv_table for %lx is inconsistent", VM_PAGE_TO_PHYS(m));
pmap_remove_pte(pmap, pte, va, pv, 1);
pmap_install(oldpmap);
pmap_switch(oldpmap);
PMAP_UNLOCK(pmap);
}
vm_page_flag_clear(m, PG_WRITEABLE);
@ -1505,7 +1504,7 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
vm_page_lock_queues();
PMAP_LOCK(pmap);
oldpmap = pmap_install(pmap);
oldpmap = pmap_switch(pmap);
while (sva < eva) {
/*
* If page is invalid, skip this page
@ -1536,7 +1535,7 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
sva += PAGE_SIZE;
}
vm_page_unlock_queues();
pmap_install(oldpmap);
pmap_switch(oldpmap);
PMAP_UNLOCK(pmap);
}
@ -1565,7 +1564,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
vm_page_lock_queues();
PMAP_LOCK(pmap);
oldpmap = pmap_install(pmap);
oldpmap = pmap_switch(pmap);
va &= ~PAGE_MASK;
#ifdef DIAGNOSTIC
@ -1577,13 +1576,13 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
* Find (or create) a pte for the given mapping.
*/
while ((pte = pmap_find_pte(va)) == NULL) {
pmap_install(oldpmap);
pmap_switch(oldpmap);
PMAP_UNLOCK(pmap);
vm_page_unlock_queues();
VM_WAIT;
vm_page_lock_queues();
PMAP_LOCK(pmap);
oldpmap = pmap_install(pmap);
oldpmap = pmap_switch(pmap);
}
origpte = *pte;
if (!pmap_present(pte)) {
@ -1660,7 +1659,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
if ((prot & VM_PROT_WRITE) != 0)
vm_page_flag_set(m, PG_WRITEABLE);
vm_page_unlock_queues();
pmap_install(oldpmap);
pmap_switch(oldpmap);
PMAP_UNLOCK(pmap);
}
@ -1688,12 +1687,12 @@ pmap_enter_object(pmap_t pmap, vm_offset_t start, vm_offset_t end,
psize = atop(end - start);
m = m_start;
PMAP_LOCK(pmap);
oldpmap = pmap_install(pmap);
oldpmap = pmap_switch(pmap);
while (m != NULL && (diff = m->pindex - m_start->pindex) < psize) {
pmap_enter_quick_locked(pmap, start + ptoa(diff), m, prot);
m = TAILQ_NEXT(m, listq);
}
pmap_install(oldpmap);
pmap_switch(oldpmap);
PMAP_UNLOCK(pmap);
}
@ -1712,9 +1711,9 @@ pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot)
pmap_t oldpmap;
PMAP_LOCK(pmap);
oldpmap = pmap_install(pmap);
oldpmap = pmap_switch(pmap);
pmap_enter_quick_locked(pmap, va, m, prot);
pmap_install(oldpmap);
pmap_switch(oldpmap);
PMAP_UNLOCK(pmap);
}
@ -1789,7 +1788,7 @@ pmap_change_wiring(pmap, va, wired)
struct ia64_lpte *pte;
PMAP_LOCK(pmap);
oldpmap = pmap_install(pmap);
oldpmap = pmap_switch(pmap);
pte = pmap_find_vhpt(va);
KASSERT(pte != NULL, ("pte"));
@ -1801,7 +1800,7 @@ pmap_change_wiring(pmap, va, wired)
pmap_clear_wired(pte);
}
pmap_install(oldpmap);
pmap_switch(oldpmap);
PMAP_UNLOCK(pmap);
}
@ -1932,7 +1931,7 @@ pmap_remove_pages(pmap_t pmap)
vm_page_lock_queues();
PMAP_LOCK(pmap);
oldpmap = pmap_install(pmap);
oldpmap = pmap_switch(pmap);
for (pv = TAILQ_FIRST(&pmap->pm_pvlist); pv; pv = npv) {
struct ia64_lpte *pte;
@ -1945,7 +1944,7 @@ pmap_remove_pages(pmap_t pmap)
pmap_remove_pte(pmap, pte, pv->pv_va, pv, 1);
}
pmap_install(oldpmap);
pmap_switch(oldpmap);
PMAP_UNLOCK(pmap);
vm_page_unlock_queues();
}
@ -1975,7 +1974,7 @@ pmap_ts_referenced(vm_page_t m)
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
PMAP_LOCK(pv->pv_pmap);
oldpmap = pmap_install(pv->pv_pmap);
oldpmap = pmap_switch(pv->pv_pmap);
pte = pmap_find_vhpt(pv->pv_va);
KASSERT(pte != NULL, ("pte"));
if (pmap_accessed(pte)) {
@ -1983,7 +1982,7 @@ pmap_ts_referenced(vm_page_t m)
pmap_clear_accessed(pte);
pmap_invalidate_page(pv->pv_pmap, pv->pv_va);
}
pmap_install(oldpmap);
pmap_switch(oldpmap);
PMAP_UNLOCK(pv->pv_pmap);
}
@ -2010,9 +2009,9 @@ pmap_is_modified(vm_page_t m)
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
PMAP_LOCK(pv->pv_pmap);
oldpmap = pmap_install(pv->pv_pmap);
oldpmap = pmap_switch(pv->pv_pmap);
pte = pmap_find_vhpt(pv->pv_va);
pmap_install(oldpmap);
pmap_switch(oldpmap);
KASSERT(pte != NULL, ("pte"));
rv = pmap_dirty(pte) ? TRUE : FALSE;
PMAP_UNLOCK(pv->pv_pmap);
@ -2055,14 +2054,14 @@ pmap_clear_modify(vm_page_t m)
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
PMAP_LOCK(pv->pv_pmap);
oldpmap = pmap_install(pv->pv_pmap);
oldpmap = pmap_switch(pv->pv_pmap);
pte = pmap_find_vhpt(pv->pv_va);
KASSERT(pte != NULL, ("pte"));
if (pmap_dirty(pte)) {
pmap_clear_dirty(pte);
pmap_invalidate_page(pv->pv_pmap, pv->pv_va);
}
pmap_install(oldpmap);
pmap_switch(oldpmap);
PMAP_UNLOCK(pv->pv_pmap);
}
}
@ -2084,14 +2083,14 @@ pmap_clear_reference(vm_page_t m)
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
PMAP_LOCK(pv->pv_pmap);
oldpmap = pmap_install(pv->pv_pmap);
oldpmap = pmap_switch(pv->pv_pmap);
pte = pmap_find_vhpt(pv->pv_va);
KASSERT(pte != NULL, ("pte"));
if (pmap_accessed(pte)) {
pmap_clear_accessed(pte);
pmap_invalidate_page(pv->pv_pmap, pv->pv_va);
}
pmap_install(oldpmap);
pmap_switch(oldpmap);
PMAP_UNLOCK(pv->pv_pmap);
}
}
@ -2114,7 +2113,7 @@ pmap_remove_write(vm_page_t m)
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
pmap = pv->pv_pmap;
PMAP_LOCK(pmap);
oldpmap = pmap_install(pmap);
oldpmap = pmap_switch(pmap);
pte = pmap_find_vhpt(pv->pv_va);
KASSERT(pte != NULL, ("pte"));
prot = pmap_prot(pte);
@ -2127,7 +2126,7 @@ pmap_remove_write(vm_page_t m)
pmap_pte_prot(pmap, pte, prot);
pmap_invalidate_page(pmap, pv->pv_va);
}
pmap_install(oldpmap);
pmap_switch(oldpmap);
PMAP_UNLOCK(pmap);
}
vm_page_flag_clear(m, PG_WRITEABLE);
@ -2165,13 +2164,13 @@ pmap_mincore(pmap_t pmap, vm_offset_t addr)
int val = 0;
PMAP_LOCK(pmap);
oldpmap = pmap_install(pmap);
oldpmap = pmap_switch(pmap);
pte = pmap_find_vhpt(addr);
if (pte != NULL) {
tpte = *pte;
pte = &tpte;
}
pmap_install(oldpmap);
pmap_switch(oldpmap);
PMAP_UNLOCK(pmap);
if (pte == NULL)
@ -2226,7 +2225,7 @@ pmap_mincore(pmap_t pmap, vm_offset_t addr)
void
pmap_activate(struct thread *td)
{
pmap_install(vmspace_pmap(td->td_proc->p_vmspace));
pmap_switch(vmspace_pmap(td->td_proc->p_vmspace));
}
pmap_t
@ -2235,10 +2234,10 @@ pmap_switch(pmap_t pm)
pmap_t prevpm;
int i;
THREAD_LOCK_ASSERT(curthread, MA_OWNED);
critical_enter();
prevpm = PCPU_GET(current_pmap);
if (prevpm == pm)
return (prevpm);
goto out;
if (prevpm != NULL)
atomic_clear_32(&prevpm->pm_active, PCPU_GET(cpumask));
if (pm == NULL) {
@ -2255,20 +2254,9 @@ pmap_switch(pmap_t pm)
}
PCPU_SET(current_pmap, pm);
__asm __volatile("srlz.d");
return (prevpm);
}
static pmap_t
pmap_install(pmap_t pm)
{
pmap_t prevpm;
struct thread *td;
td = curthread;
thread_lock(td);
prevpm = pmap_switch(pm);
thread_unlock(td);
out:
critical_exit();
return (prevpm);
}