summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/sun4v/sun4v/pmap.c168
-rw-r--r--sys/sun4v/sun4v/tte.c43
2 files changed, 78 insertions, 133 deletions
diff --git a/sys/sun4v/sun4v/pmap.c b/sys/sun4v/sun4v/pmap.c
index e277a08..653166c 100644
--- a/sys/sun4v/sun4v/pmap.c
+++ b/sys/sun4v/sun4v/pmap.c
@@ -317,7 +317,6 @@ get_pv_entry(pmap_t locked_pmap)
vpq = &vm_page_queues[PQ_INACTIVE];
retry:
- sched_pin();
TAILQ_FOREACH(m, &vpq->pl, pageq) {
if (m->hold_count || m->busy)
continue;
@@ -359,7 +358,6 @@ retry:
free_pv_entry(pv);
}
}
- sched_unpin();
if (allocated_pv == NULL) {
if (vpq == &vm_page_queues[PQ_INACTIVE]) {
vpq = &vm_page_queues[PQ_ACTIVE];
@@ -990,7 +988,6 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr,
PMAP_LOCK(src_pmap);
PMAP_LOCK(dst_pmap);
}
- sched_pin();
for (addr = src_addr; addr < end_addr; addr += PAGE_SIZE) {
tte_t tte_data;
vm_page_t m;
@@ -1001,20 +998,15 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr,
if (tte_hash_lookup(dst_pmap->pm_hash, addr) == 0) {
m = PHYS_TO_VM_PAGE(TTE_GET_PA(tte_data));
- tte_hash_insert(dst_pmap->pm_hash, addr, tte_data & ~(VTD_W|VTD_REF));
+ tte_hash_insert(dst_pmap->pm_hash, addr, tte_data & ~(VTD_W|VTD_REF|VTD_WIRED));
dst_pmap->pm_stats.resident_count++;
pmap_insert_entry(dst_pmap, addr, m);
}
}
}
- sched_unpin();
vm_page_unlock_queues();
PMAP_UNLOCK(src_pmap);
PMAP_UNLOCK(dst_pmap);
-
-
-
-
}
void
@@ -1064,24 +1056,22 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
vm_page_lock_queues();
PMAP_LOCK(pmap);
- sched_pin();
tte_data = pa = VM_PAGE_TO_PHYS(m);
otte_data = tte_hash_delete(pmap->pm_hash, va);
opa = TTE_GET_PA(otte_data);
- /*
- * Mapping has not changed, must be protection or wiring change.
- */
-
if (opa == 0) {
+ /*
+ * This is a new mapping
+ */
pmap->pm_stats.resident_count++;
pmap_add_tte(pmap, va, m, &tte_data, wired);
} else if (pa != opa) {
/*
- * Mapping has changed, invalidate old range and fall through to
- * handle validating new mapping.
+ * Mapping has changed, handle validating new mapping.
+ *
*/
if (otte_data & VTD_WIRED)
pmap->pm_stats.wired_count--;
@@ -1095,6 +1085,10 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
} else /* (pa == opa) */ {
/*
+ * Mapping has not changed, must be protection or wiring change.
+ */
+
+ /*
* Wiring change, just update stats. We don't worry about
* wiring PT pages as they remain resident as long as there
* are valid mappings in them. Hence, if a user page is wired,
@@ -1127,7 +1121,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
if (wired)
tte_data |= VTD_WIRED;
if (pmap == kernel_pmap)
- tte_data |= TTE_KERNEL_MINFLAGS;
+ tte_data |= VTD_P;
invlva = FALSE;
if ((otte_data & ~(VTD_W|VTD_REF)) != tte_data) {
@@ -1135,19 +1129,25 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
if (otte_data & VTD_REF) {
if (otte_data & VTD_MANAGED)
vm_page_flag_set(om, PG_REFERENCED);
- if (opa != pa)
+ if ((opa != pa) || ((opa & VTD_X) != (pa & VTD_X)))
invlva = TRUE;
}
if (otte_data & VTD_W) {
if (otte_data & VTD_MANAGED)
vm_page_dirty(om);
- if ((prot & VM_PROT_WRITE) == 0)
+ if ((pa & VTD_SW_W) != 0)
invlva = TRUE;
}
+ if (invlva)
+ pmap_invalidate_page(pmap, va, TRUE);
}
}
+
tte_hash_insert(pmap->pm_hash, va, tte_data|TTE_MINFLAGS|VTD_REF);
+ /*
+ * XXX this needs to be locked for the threaded / kernel case
+ */
tsb_set_tte(&pmap->pm_tsb, va, tte_data|TTE_MINFLAGS|VTD_REF,
pmap->pm_context);
@@ -1160,13 +1160,8 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
if (0 && pmap->pm_context != 0 && pmap->pm_tsb_miss_count > 512)
pmap_tsb_resize(pmap);
-
vm_page_unlock_queues();
-
- if (invlva)
- pmap_invalidate_page(pmap, va, TRUE);
- sched_unpin();
PMAP_UNLOCK(pmap);
}
@@ -1186,17 +1181,15 @@ void
pmap_enter_object(pmap_t pmap, vm_offset_t start, vm_offset_t end,
vm_page_t m_start, vm_prot_t prot)
{
- vm_page_t m, mpte;
+ vm_page_t m;
vm_pindex_t diff, psize;
VM_OBJECT_LOCK_ASSERT(m_start->object, MA_OWNED);
psize = atop(end - start);
- mpte = NULL;
m = m_start;
PMAP_LOCK(pmap);
while (m != NULL && (diff = m->pindex - m_start->pindex) < psize) {
- pmap_enter_quick_locked(pmap, start + ptoa(diff), m,
- prot);
+ pmap_enter_quick_locked(pmap, start + ptoa(diff), m, prot);
m = TAILQ_NEXT(m, listq);
}
PMAP_UNLOCK(pmap);
@@ -1208,7 +1201,6 @@ pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot)
PMAP_LOCK(pmap);
pmap_enter_quick_locked(pmap, va, m, prot);
PMAP_UNLOCK(pmap);
-
}
static void
@@ -1241,11 +1233,7 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot
if ((prot & VM_PROT_EXECUTE) != 0)
tte_data |= VTD_X;
- if (pmap == kernel_pmap)
- tte_data |= TTE_KERNEL_MINFLAGS;
-
tte_hash_insert(pmap->pm_hash, va, tte_data | TTE_MINFLAGS);
-
}
/*
@@ -1278,14 +1266,12 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
m = NULL;
vm_page_lock_queues();
PMAP_LOCK(pmap);
- sched_pin();
tte_data = tte_hash_lookup(pmap->pm_hash, va);
if (tte_data != 0 &&
((tte_data & VTD_SW_W) || (prot & VM_PROT_WRITE) == 0)) {
m = PHYS_TO_VM_PAGE(TTE_GET_PA(tte_data));
vm_page_hold(m);
}
- sched_unpin();
vm_page_unlock_queues();
PMAP_UNLOCK(pmap);
@@ -1595,16 +1581,6 @@ pmap_is_prefaultable(pmap_t pmap, vm_offset_t va)
}
/*
- * Map a wired page into kernel virtual address space.
- */
-static void
-pmap_kenter(vm_offset_t va, vm_paddr_t pa)
-{
- tte_hash_update(kernel_pmap->pm_hash, va, pa | TTE_KERNEL | VTD_8K);
- tsb_set_tte(&kernel_td[TSB8K_INDEX], va, pa | TTE_KERNEL | VTD_8K, 0);
-}
-
-/*
* Extract the physical page address associated with the given kernel virtual
* address.
*/
@@ -1630,12 +1606,6 @@ pmap_kextract(vm_offset_t va)
return pa;
}
-static void
-pmap_kremove(vm_offset_t va)
-{
- tte_hash_delete(kernel_pmap->pm_hash, va);
-}
-
/*
* Map a range of physical addresses into kernel virtual address space.
*
@@ -1689,7 +1659,6 @@ pmap_page_exists_quick(pmap_t pmap, vm_page_t m)
if (loops >= 16)
break;
}
-
return (FALSE);
}
@@ -1709,8 +1678,11 @@ pmap_page_init(vm_page_t m)
void
pmap_remove_write(vm_page_t m)
{
-
- tte_clear_phys_bit(m, VTD_SW_W);
+ if ((m->flags & PG_WRITEABLE) == 0)
+ return;
+ mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ tte_clear_phys_bit(m, VTD_SW_W|VTD_W);
+ vm_page_flag_clear(m, PG_WRITEABLE);
}
/*
* Initialize the pmap associated with process 0.
@@ -1765,6 +1737,7 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
int anychanged;
vm_offset_t tva;
+ uint64_t clearbits;
DPRINTF("pmap_protect(0x%lx, 0x%lx, %d)\n", sva, eva, prot);
@@ -1773,23 +1746,30 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
return;
}
- if (prot & VM_PROT_WRITE)
+ if ((prot & (VM_PROT_WRITE|VM_PROT_EXECUTE)) ==
+ (VM_PROT_WRITE|VM_PROT_EXECUTE))
return;
- anychanged = 0;
+ clearbits = anychanged = 0;
+
+ if ((prot & VM_PROT_WRITE) == 0)
+ clearbits |= (VTD_W|VTD_SW_W);
+ if ((prot & VM_PROT_EXECUTE) == 0)
+ clearbits |= VTD_X;
vm_page_lock_queues();
PMAP_LOCK(pmap);
- sched_pin();
-
for (tva = sva; tva < eva; tva += PAGE_SIZE) {
uint64_t otte_data;
vm_page_t m;
if ((otte_data = tte_hash_clear_bits(pmap->pm_hash, tva,
- (VTD_SW_W|VTD_W))) == 0)
+ clearbits)) == 0)
continue;
-
+ /*
+ * XXX technically we should do a shootdown if it
+ * was referenced and was executable - but is not now
+ */
if (!anychanged && (otte_data & VTD_W))
anychanged = 1;
@@ -1808,10 +1788,8 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
}
vm_page_unlock_queues();
-
if (anychanged)
pmap_invalidate_range(pmap, sva, eva, TRUE);
- sched_unpin();
PMAP_UNLOCK(pmap);
}
@@ -1824,19 +1802,19 @@ void
pmap_qenter(vm_offset_t sva, vm_page_t *m, int count)
{
vm_offset_t va;
-
+ tte_t otte_data;
+
+ otte_data = 0;
va = sva;
while (count-- > 0) {
- /*
- * If we make explicit calls to tte_hash_update
- * we can determine if any of the pages have been mapped
- * before - this can save us a pmap_invalidate_range
- */
- pmap_kenter(va, VM_PAGE_TO_PHYS(*m));
+ otte |= tte_hash_update(kernel_pmap->pm_hash, va,
+ VM_PAGE_TO_PHYS(*m),
+ pa | TTE_KERNEL | VTD_8K);
va += PAGE_SIZE;
m++;
}
- pmap_invalidate_range(kernel_pmap, sva, va, FALSE);
+ if ((otte & VTD_REF) != 0)
+ pmap_invalidate_range(kernel_pmap, sva, va, FALSE);
}
/*
@@ -1847,18 +1825,17 @@ void
pmap_qremove(vm_offset_t sva, int count)
{
vm_offset_t va;
+ tte_t otte;
va = sva;
-#ifndef NFS_NOT_BROKEN
- if (count == 0)
- count = 1;
-#endif
+ otte = 0;
while (count-- > 0) {
- pmap_kremove(va);
+ otte |= tte_hash_delete(kernel_pmap->pm_hash, va);
va += PAGE_SIZE;
}
- pmap_invalidate_range(kernel_pmap, sva, va, TRUE);
+ if ((otte & VTD_REF) != 0)
+ pmap_invalidate_range(kernel_pmap, sva, va, TRUE);
}
/*
@@ -1898,23 +1875,18 @@ pmap_remove(pmap_t pmap, vm_offset_t start, vm_offset_t end)
start, end);
invlva = 0;
vm_page_lock_queues();
- sched_pin();
PMAP_LOCK(pmap);
for (tva = start; tva < end; tva += PAGE_SIZE) {
if ((tte_data = tte_hash_delete(pmap->pm_hash, tva)) == 0)
continue;
pmap_remove_tte(pmap, tte_data, tva);
- if (!invlva && (tte_data & (VTD_REF|VTD_W)))
+ if (tte_data & (VTD_REF|VTD_W))
invlva = 1;
}
vm_page_unlock_queues();
-
if (invlva)
pmap_invalidate_range(pmap, start, end, TRUE);
-
- sched_unpin();
PMAP_UNLOCK(pmap);
-
}
/*
@@ -1938,7 +1910,6 @@ pmap_remove_all(vm_page_t m)
DPRINTF("pmap_remove_all 0x%lx\n", VM_PAGE_TO_PHYS(m));
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
- sched_pin();
while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) {
PMAP_LOCK(pv->pv_pmap);
pv->pv_pmap->pm_stats.resident_count--;
@@ -1968,7 +1939,6 @@ pmap_remove_all(vm_page_t m)
free_pv_entry(pv);
}
vm_page_flag_clear(m, PG_WRITEABLE);
- sched_unpin();
}
static void
@@ -2011,24 +1981,17 @@ pmap_remove_pages(pmap_t pmap)
DPRINTF("pmap_remove_pages(ctx=0x%lx)\n", pmap->pm_context);
vm_page_lock_queues();
PMAP_LOCK(pmap);
- sched_pin();
for (pv = TAILQ_FIRST(&pmap->pm_pvlist); pv; pv = npv) {
tte_data = tte_hash_delete(pmap->pm_hash, pv->pv_va);
-
+
if (tte_data == 0) {
- membar(Sync);
- DELAY(100);
- membar(Sync);
- tte_data = tte_hash_delete(pmap->pm_hash, pv->pv_va);
- if (tte_data == 0) {
- printf("TTE IS ZERO @ VA %016lx\n", pv->pv_va);
- panic("bad tte");
- }
+ printf("TTE IS ZERO @ VA %016lx\n", pv->pv_va);
+ panic("bad tte");
}
-
- if (tte_data & VTD_WIRED)
+ if (tte_data & VTD_WIRED) {
+ panic("wired page in process not handled correctly");
pmap->pm_stats.wired_count--;
-
+ }
m = PHYS_TO_VM_PAGE(TTE_GET_PA(tte_data));
pmap->pm_stats.resident_count--;
@@ -2052,9 +2015,7 @@ pmap_remove_pages(pmap_t pmap)
pmap_tsb_reset(pmap);
vm_page_unlock_queues();
-
pmap_invalidate_all(pmap);
- sched_unpin();
PMAP_UNLOCK(pmap);
}
@@ -2209,7 +2170,6 @@ pmap_ts_referenced(vm_page_t m)
if (m->flags & PG_FICTITIOUS)
return (rv);
- sched_pin();
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
if ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) {
@@ -2238,8 +2198,6 @@ pmap_ts_referenced(vm_page_t m)
PMAP_UNLOCK(pmap);
} while ((pv = pvn) != NULL && pv != pvf);
}
- sched_unpin();
-
return (rv);
}
@@ -2257,8 +2215,10 @@ pmap_zero_page_area(vm_page_t m, int off, int size)
pa = VM_PAGE_TO_PHYS(m);
va = TLB_PHYS_TO_DIRECT(pa);
-
- bzero((char *)(va + off), size);
+ if (off == 0 && size == PAGE_SIZE)
+ hwblkclr((void *)TLB_PHYS_TO_DIRECT(VM_PAGE_TO_PHYS(m)), PAGE_SIZE);
+ else
+ bzero((char *)(va + off), size);
}
diff --git a/sys/sun4v/sun4v/tte.c b/sys/sun4v/sun4v/tte.c
index 389b97d..4fb3d3e 100644
--- a/sys/sun4v/sun4v/tte.c
+++ b/sys/sun4v/sun4v/tte.c
@@ -56,36 +56,30 @@ void
tte_clear_phys_bit(vm_page_t m, uint64_t flags)
{
pv_entry_t pv;
+ tte_t active_flags = (flags & ~VTD_SW_W);
- if ((m->flags & PG_FICTITIOUS) ||
- (flags == VTD_SW_W && (m->flags & PG_WRITEABLE) == 0))
+ if (m->flags & PG_FICTITIOUS)
return;
- sched_pin();
+
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
/*
* Loop over all current mappings setting/clearing as appropos If
* setting RO do we need to clear the VAC?
*/
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
- tte_t otte_data;
-
- if (flags == VTD_SW_W)
- flags = (VTD_SW_W|VTD_W);
+ tte_t otte_data, matchbits;
+ pmap_t pmap;
- otte_data = tte_hash_clear_bits(pv->pv_pmap->pm_hash, pv->pv_va, flags);
-
- if (otte_data & flags) {
- if (otte_data & VTD_W)
+ pmap = pv->pv_pmap;
+ PMAP_LOCK(pmap);
+ otte_data = tte_hash_clear_bits(pmap->pm_hash, pv->pv_va, flags);
+ if ((matchbits = (otte_data & active_flags)) != 0) {
+ if (matchbits == VTD_W)
vm_page_dirty(m);
-
- pmap_invalidate_page(pv->pv_pmap, pv->pv_va, TRUE);
+ pmap_invalidate_page(pmap, pv->pv_va, TRUE);
}
-
-
+ PMAP_UNLOCK(pmap);
}
- if (flags & VTD_SW_W)
- vm_page_flag_clear(m, PG_WRITEABLE);
- sched_unpin();
}
boolean_t
@@ -106,8 +100,7 @@ tte_get_phys_bit(vm_page_t m, uint64_t flags)
pmap = pv->pv_pmap;
otte_data = tte_hash_lookup(pmap->pm_hash, pv->pv_va);
- rv = ((otte_data & flags) != 0);
- if (rv)
+ if ((rv = ((otte_data & flags) != 0)))
break;
}
@@ -117,15 +110,7 @@ tte_get_phys_bit(vm_page_t m, uint64_t flags)
void
tte_clear_virt_bit(struct pmap *pmap, vm_offset_t va, uint64_t flags)
{
- tte_t otte_data;
-
- if (flags == VTD_SW_W)
- flags = (VTD_SW_W|VTD_W);
-
- otte_data = tte_hash_clear_bits(pmap->pm_hash, va, flags);
-
- if (otte_data & flags)
- pmap_invalidate_page(pmap, va, TRUE);
+ (void)tte_hash_clear_bits(pmap->pm_hash, va, flags);
}
void
OpenPOWER on IntegriCloud