Page MenuHomeFreeBSD

D18864.id52910.diff
No OneTemporary

D18864.id52910.diff

Index: sys/riscv/riscv/pmap.c
===================================================================
--- sys/riscv/riscv/pmap.c
+++ sys/riscv/riscv/pmap.c
@@ -2261,10 +2261,12 @@
void
pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
{
- pd_entry_t *l1, *l2;
+ pd_entry_t *l1, *l2, l2e;
pt_entry_t *l3, l3e, mask;
vm_page_t m;
- vm_offset_t va_next;
+ vm_paddr_t pa;
+ vm_offset_t va, va_next;
+ bool anychanged, pv_lists_locked;
if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
pmap_remove(pmap, sva, eva);
@@ -2275,12 +2277,14 @@
(VM_PROT_WRITE | VM_PROT_EXECUTE))
return;
+ anychanged = false;
+ pv_lists_locked = false;
mask = 0;
if ((prot & VM_PROT_WRITE) == 0)
mask |= PTE_W | PTE_D;
if ((prot & VM_PROT_EXECUTE) == 0)
mask |= PTE_X;
-
+resume:
PMAP_LOCK(pmap);
for (; sva < eva; sva = va_next) {
l1 = pmap_l1(pmap, sva);
@@ -2296,10 +2300,41 @@
va_next = eva;
l2 = pmap_l1_to_l2(l1, sva);
- if (l2 == NULL || pmap_load(l2) == 0)
- continue;
- if ((pmap_load(l2) & PTE_RX) != 0)
+ if (l2 == NULL || (l2e = pmap_load(l2)) == 0)
continue;
+ if ((l2e & PTE_RWX) != 0) {
+ if (sva + L2_SIZE == va_next && eva >= va_next) {
+retryl2:
+ if ((l2e & (PTE_SW_MANAGED | PTE_D)) ==
+ (PTE_SW_MANAGED | PTE_D)) {
+ pa = PTE_TO_PHYS(l2e);
+ for (va = sva, m = PHYS_TO_VM_PAGE(pa);
+ va < va_next; m++, va += PAGE_SIZE)
+ vm_page_dirty(m);
+ }
+ if (!atomic_fcmpset_long(l2, &l2e, l2e & ~mask))
+ goto retryl2;
+ anychanged = true;
+ } else {
+ if (!pv_lists_locked) {
+ pv_lists_locked = true;
+ if (!rw_try_rlock(&pvh_global_lock)) {
+ if (anychanged)
+ pmap_invalidate_all(
+ pmap);
+ PMAP_UNLOCK(pmap);
+ rw_rlock(&pvh_global_lock);
+ goto resume;
+ }
+ }
+ if (!pmap_demote_l2(pmap, l2, sva)) {
+ /*
+ * The large page mapping was destroyed.
+ */
+ continue;
+ }
+ }
+ }
if (va_next > eva)
va_next = eva;
@@ -2307,7 +2342,7 @@
for (l3 = pmap_l2_to_l3(l2, sva); sva != va_next; l3++,
sva += L3_SIZE) {
l3e = pmap_load(l3);
-retry:
+retryl3:
if ((l3e & PTE_V) == 0)
continue;
if ((prot & VM_PROT_WRITE) == 0 &&
@@ -2317,11 +2352,14 @@
vm_page_dirty(m);
}
if (!atomic_fcmpset_long(l3, &l3e, l3e & ~mask))
- goto retry;
- /* XXX: Use pmap_invalidate_range */
- pmap_invalidate_page(pmap, sva);
+ goto retryl3;
+ anychanged = true;
}
}
+ if (anychanged)
+ pmap_invalidate_all(pmap);
+ if (pv_lists_locked)
+ rw_runlock(&pvh_global_lock);
PMAP_UNLOCK(pmap);
}
@@ -3178,11 +3216,12 @@
pmap_unwire(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
{
vm_offset_t va_next;
- pd_entry_t *l1, *l2;
- pt_entry_t *l3;
- boolean_t pv_lists_locked;
+ pd_entry_t *l1, *l2, l2e;
+ pt_entry_t *l3, l3e;
+ bool pv_lists_locked;
- pv_lists_locked = FALSE;
+ pv_lists_locked = false;
+retry:
PMAP_LOCK(pmap);
for (; sva < eva; sva = va_next) {
l1 = pmap_l1(pmap, sva);
@@ -3198,25 +3237,46 @@
va_next = eva;
l2 = pmap_l1_to_l2(l1, sva);
- if (pmap_load(l2) == 0)
+ if ((l2e = pmap_load(l2)) == 0)
continue;
+ if ((l2e & PTE_RWX) != 0) {
+ if (sva + L2_SIZE == va_next && eva >= va_next) {
+ if ((l2e & PTE_SW_WIRED) == 0)
+ panic("pmap_unwire: l2 %#jx is missing "
+ "PTE_SW_WIRED", (uintmax_t)l2e);
+ pmap_clear_bits(l2, PTE_SW_WIRED);
+ continue;
+ } else {
+ if (!pv_lists_locked) {
+ pv_lists_locked = true;
+ if (!rw_try_rlock(&pvh_global_lock)) {
+ PMAP_UNLOCK(pmap);
+ rw_rlock(&pvh_global_lock);
+ /* Repeat sva. */
+ goto retry;
+ }
+ }
+ if (!pmap_demote_l2(pmap, l2, sva))
+ panic("pmap_unwire: demotion failed");
+ }
+ }
if (va_next > eva)
va_next = eva;
for (l3 = pmap_l2_to_l3(l2, sva); sva != va_next; l3++,
sva += L3_SIZE) {
- if (pmap_load(l3) == 0)
+ if ((l3e = pmap_load(l3)) == 0)
continue;
- if ((pmap_load(l3) & PTE_SW_WIRED) == 0)
+ if ((l3e & PTE_SW_WIRED) == 0)
panic("pmap_unwire: l3 %#jx is missing "
- "PTE_SW_WIRED", (uintmax_t)*l3);
+ "PTE_SW_WIRED", (uintmax_t)l3e);
/*
* PG_W must be cleared atomically. Although the pmap
* lock synchronizes access to PG_W, another processor
* could be setting PG_M and/or PG_A concurrently.
*/
- atomic_clear_long(l3, PTE_SW_WIRED);
+ pmap_clear_bits(l3, PTE_SW_WIRED);
pmap->pm_stats.wired_count--;
}
}
@@ -3619,13 +3679,21 @@
static boolean_t
pmap_page_test_mappings(vm_page_t m, boolean_t accessed, boolean_t modified)
{
+ struct md_page *pvh;
struct rwlock *lock;
+ pd_entry_t *l2;
+ pt_entry_t *l3, mask;
pv_entry_t pv;
- pt_entry_t *l3, mask, value;
pmap_t pmap;
- int md_gen;
+ int md_gen, pvh_gen;
boolean_t rv;
+ mask = 0;
+ if (modified)
+ mask |= PTE_D;
+ if (accessed)
+ mask |= PTE_A;
+
rv = FALSE;
rw_rlock(&pvh_global_lock);
lock = VM_PAGE_TO_PV_LIST_LOCK(m);
@@ -3644,33 +3712,34 @@
}
}
l3 = pmap_l3(pmap, pv->pv_va);
- mask = 0;
- value = 0;
- if (modified) {
- mask |= PTE_D;
- value |= PTE_D;
- }
- if (accessed) {
- mask |= PTE_A;
- value |= PTE_A;
- }
-
-#if 0
- if (modified) {
- mask |= ATTR_AP_RW_BIT;
- value |= ATTR_AP(ATTR_AP_RW);
- }
- if (accessed) {
- mask |= ATTR_AF | ATTR_DESCR_MASK;
- value |= ATTR_AF | L3_PAGE;
- }
-#endif
-
- rv = (pmap_load(l3) & mask) == value;
+ rv = (pmap_load(l3) & mask) == mask;
PMAP_UNLOCK(pmap);
if (rv)
goto out;
}
+ if ((m->flags & PG_FICTITIOUS) == 0) {
+ pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
+ TAILQ_FOREACH(pv, &pvh->pv_list, pv_next) {
+ pmap = PV_PMAP(pv);
+ if (!PMAP_TRYLOCK(pmap)) {
+ md_gen = m->md.pv_gen;
+ pvh_gen = pvh->pv_gen;
+ rw_runlock(lock);
+ PMAP_LOCK(pmap);
+ rw_rlock(lock);
+ if (md_gen != m->md.pv_gen ||
+ pvh_gen != pvh->pv_gen) {
+ PMAP_UNLOCK(pmap);
+ goto restart;
+ }
+ }
+ l2 = pmap_l2(pmap, pv->pv_va);
+ rv = (pmap_load(l2) & mask) == mask;
+ PMAP_UNLOCK(pmap);
+ if (rv)
+ goto out;
+ }
+ }
out:
rw_runlock(lock);
rw_runlock(&pvh_global_lock);

File Metadata

Mime Type
text/plain
Expires
Tue, Feb 11, 10:50 PM (11 h, 15 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16602481
Default Alt Text
D18864.id52910.diff (6 KB)

Event Timeline