Simplify the handling of superpages in pmap_clear_modify(). Specifically,
if a demotion succeeds, then all of the 4KB page mappings within the superpage-sized region must be valid, so there is no point in testing the validity of the 4KB page mapping that is going to be write protected. Deindent the nearby code. Reviewed by: kib, markj Tested by: pho (amd64, i386) X-MFC after: r350004 (this change depends on arm64 dirty bit emulation) Differential Revision: https://reviews.freebsd.org/D21027
This commit is contained in:
parent
08a607e0f3
commit
5d18382b72
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=350335
@ -7574,7 +7574,7 @@ pmap_clear_modify(vm_page_t m)
|
|||||||
pmap_t pmap;
|
pmap_t pmap;
|
||||||
pv_entry_t next_pv, pv;
|
pv_entry_t next_pv, pv;
|
||||||
pd_entry_t oldpde, *pde;
|
pd_entry_t oldpde, *pde;
|
||||||
pt_entry_t oldpte, *pte, PG_M, PG_RW, PG_V;
|
pt_entry_t *pte, PG_M, PG_RW;
|
||||||
struct rwlock *lock;
|
struct rwlock *lock;
|
||||||
vm_offset_t va;
|
vm_offset_t va;
|
||||||
int md_gen, pvh_gen;
|
int md_gen, pvh_gen;
|
||||||
@ -7610,33 +7610,23 @@ pmap_clear_modify(vm_page_t m)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
PG_M = pmap_modified_bit(pmap);
|
PG_M = pmap_modified_bit(pmap);
|
||||||
PG_V = pmap_valid_bit(pmap);
|
|
||||||
PG_RW = pmap_rw_bit(pmap);
|
PG_RW = pmap_rw_bit(pmap);
|
||||||
va = pv->pv_va;
|
va = pv->pv_va;
|
||||||
pde = pmap_pde(pmap, va);
|
pde = pmap_pde(pmap, va);
|
||||||
oldpde = *pde;
|
oldpde = *pde;
|
||||||
if ((oldpde & PG_RW) != 0) {
|
/* If oldpde has PG_RW set, then it also has PG_M set. */
|
||||||
if (pmap_demote_pde_locked(pmap, pde, va, &lock)) {
|
if ((oldpde & PG_RW) != 0 &&
|
||||||
if ((oldpde & PG_W) == 0) {
|
pmap_demote_pde_locked(pmap, pde, va, &lock) &&
|
||||||
/*
|
(oldpde & PG_W) == 0) {
|
||||||
* Write protect the mapping to a
|
/*
|
||||||
* single page so that a subsequent
|
* Write protect the mapping to a single page so that
|
||||||
* write access may repromote.
|
* a subsequent write access may repromote.
|
||||||
*/
|
*/
|
||||||
va += VM_PAGE_TO_PHYS(m) - (oldpde &
|
va += VM_PAGE_TO_PHYS(m) - (oldpde & PG_PS_FRAME);
|
||||||
PG_PS_FRAME);
|
pte = pmap_pde_to_pte(pde, va);
|
||||||
pte = pmap_pde_to_pte(pde, va);
|
atomic_clear_long(pte, PG_M | PG_RW);
|
||||||
oldpte = *pte;
|
vm_page_dirty(m);
|
||||||
if ((oldpte & PG_V) != 0) {
|
pmap_invalidate_page(pmap, va);
|
||||||
while (!atomic_cmpset_long(pte,
|
|
||||||
oldpte,
|
|
||||||
oldpte & ~(PG_M | PG_RW)))
|
|
||||||
oldpte = *pte;
|
|
||||||
vm_page_dirty(m);
|
|
||||||
pmap_invalidate_page(pmap, va);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
PMAP_UNLOCK(pmap);
|
PMAP_UNLOCK(pmap);
|
||||||
}
|
}
|
||||||
|
@ -4889,28 +4889,22 @@ pmap_clear_modify(vm_page_t m)
|
|||||||
va = pv->pv_va;
|
va = pv->pv_va;
|
||||||
l2 = pmap_l2(pmap, va);
|
l2 = pmap_l2(pmap, va);
|
||||||
oldl2 = pmap_load(l2);
|
oldl2 = pmap_load(l2);
|
||||||
if ((oldl2 & ATTR_SW_DBM) != 0) {
|
/* If oldl2 has ATTR_SW_DBM set, then it is also dirty. */
|
||||||
if (pmap_demote_l2_locked(pmap, l2, va, &lock)) {
|
if ((oldl2 & ATTR_SW_DBM) != 0 &&
|
||||||
if ((oldl2 & ATTR_SW_WIRED) == 0) {
|
pmap_demote_l2_locked(pmap, l2, va, &lock) &&
|
||||||
/*
|
(oldl2 & ATTR_SW_WIRED) == 0) {
|
||||||
* Write protect the mapping to a
|
/*
|
||||||
* single page so that a subsequent
|
* Write protect the mapping to a single page so that
|
||||||
* write access may repromote.
|
* a subsequent write access may repromote.
|
||||||
*/
|
*/
|
||||||
va += VM_PAGE_TO_PHYS(m) -
|
va += VM_PAGE_TO_PHYS(m) - (oldl2 & ~ATTR_MASK);
|
||||||
(oldl2 & ~ATTR_MASK);
|
l3 = pmap_l2_to_l3(l2, va);
|
||||||
l3 = pmap_l2_to_l3(l2, va);
|
oldl3 = pmap_load(l3);
|
||||||
oldl3 = pmap_load(l3);
|
while (!atomic_fcmpset_long(l3, &oldl3,
|
||||||
if (pmap_l3_valid(oldl3)) {
|
(oldl3 & ~ATTR_SW_DBM) | ATTR_AP(ATTR_AP_RO)))
|
||||||
while (!atomic_fcmpset_long(l3,
|
cpu_spinwait();
|
||||||
&oldl3, (oldl3 & ~ATTR_SW_DBM) |
|
vm_page_dirty(m);
|
||||||
ATTR_AP(ATTR_AP_RO)))
|
pmap_invalidate_page(pmap, va);
|
||||||
cpu_spinwait();
|
|
||||||
vm_page_dirty(m);
|
|
||||||
pmap_invalidate_page(pmap, va);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
PMAP_UNLOCK(pmap);
|
PMAP_UNLOCK(pmap);
|
||||||
}
|
}
|
||||||
|
@ -5280,7 +5280,7 @@ __CONCAT(PMTYPE, clear_modify)(vm_page_t m)
|
|||||||
pv_entry_t next_pv, pv;
|
pv_entry_t next_pv, pv;
|
||||||
pmap_t pmap;
|
pmap_t pmap;
|
||||||
pd_entry_t oldpde, *pde;
|
pd_entry_t oldpde, *pde;
|
||||||
pt_entry_t oldpte, *pte;
|
pt_entry_t *pte;
|
||||||
vm_offset_t va;
|
vm_offset_t va;
|
||||||
|
|
||||||
KASSERT((m->oflags & VPO_UNMANAGED) == 0,
|
KASSERT((m->oflags & VPO_UNMANAGED) == 0,
|
||||||
@ -5307,34 +5307,24 @@ __CONCAT(PMTYPE, clear_modify)(vm_page_t m)
|
|||||||
PMAP_LOCK(pmap);
|
PMAP_LOCK(pmap);
|
||||||
pde = pmap_pde(pmap, va);
|
pde = pmap_pde(pmap, va);
|
||||||
oldpde = *pde;
|
oldpde = *pde;
|
||||||
if ((oldpde & PG_RW) != 0) {
|
/* If oldpde has PG_RW set, then it also has PG_M set. */
|
||||||
if (pmap_demote_pde(pmap, pde, va)) {
|
if ((oldpde & PG_RW) != 0 &&
|
||||||
if ((oldpde & PG_W) == 0) {
|
pmap_demote_pde(pmap, pde, va) &&
|
||||||
/*
|
(oldpde & PG_W) == 0) {
|
||||||
* Write protect the mapping to a
|
/*
|
||||||
* single page so that a subsequent
|
* Write protect the mapping to a single page so that
|
||||||
* write access may repromote.
|
* a subsequent write access may repromote.
|
||||||
*/
|
*/
|
||||||
va += VM_PAGE_TO_PHYS(m) - (oldpde &
|
va += VM_PAGE_TO_PHYS(m) - (oldpde & PG_PS_FRAME);
|
||||||
PG_PS_FRAME);
|
pte = pmap_pte_quick(pmap, va);
|
||||||
pte = pmap_pte_quick(pmap, va);
|
/*
|
||||||
oldpte = *pte;
|
* Regardless of whether a pte is 32 or 64 bits
|
||||||
if ((oldpte & PG_V) != 0) {
|
* in size, PG_RW and PG_M are among the least
|
||||||
/*
|
* significant 32 bits.
|
||||||
* Regardless of whether a pte is 32 or 64 bits
|
*/
|
||||||
* in size, PG_RW and PG_M are among the least
|
atomic_clear_int((u_int *)pte, PG_M | PG_RW);
|
||||||
* significant 32 bits.
|
vm_page_dirty(m);
|
||||||
*/
|
pmap_invalidate_page_int(pmap, va);
|
||||||
while (!atomic_cmpset_int((u_int *)pte,
|
|
||||||
oldpte,
|
|
||||||
oldpte & ~(PG_M | PG_RW)))
|
|
||||||
oldpte = *pte;
|
|
||||||
vm_page_dirty(m);
|
|
||||||
pmap_invalidate_page_int(pmap,
|
|
||||||
va);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
PMAP_UNLOCK(pmap);
|
PMAP_UNLOCK(pmap);
|
||||||
}
|
}
|
||||||
|
@ -4105,7 +4105,7 @@ pmap_clear_modify(vm_page_t m)
|
|||||||
pmap_t pmap;
|
pmap_t pmap;
|
||||||
pv_entry_t next_pv, pv;
|
pv_entry_t next_pv, pv;
|
||||||
pd_entry_t *l2, oldl2;
|
pd_entry_t *l2, oldl2;
|
||||||
pt_entry_t *l3, oldl3;
|
pt_entry_t *l3;
|
||||||
vm_offset_t va;
|
vm_offset_t va;
|
||||||
int md_gen, pvh_gen;
|
int md_gen, pvh_gen;
|
||||||
|
|
||||||
@ -4143,28 +4143,19 @@ pmap_clear_modify(vm_page_t m)
|
|||||||
va = pv->pv_va;
|
va = pv->pv_va;
|
||||||
l2 = pmap_l2(pmap, va);
|
l2 = pmap_l2(pmap, va);
|
||||||
oldl2 = pmap_load(l2);
|
oldl2 = pmap_load(l2);
|
||||||
if ((oldl2 & PTE_W) != 0) {
|
/* If oldl2 has PTE_W set, then it also has PTE_D set. */
|
||||||
if (pmap_demote_l2_locked(pmap, l2, va, &lock)) {
|
if ((oldl2 & PTE_W) != 0 &&
|
||||||
if ((oldl2 & PTE_SW_WIRED) == 0) {
|
pmap_demote_l2_locked(pmap, l2, va, &lock) &&
|
||||||
/*
|
(oldl2 & PTE_SW_WIRED) == 0) {
|
||||||
* Write protect the mapping to a
|
/*
|
||||||
* single page so that a subsequent
|
* Write protect the mapping to a single page so that
|
||||||
* write access may repromote.
|
* a subsequent write access may repromote.
|
||||||
*/
|
*/
|
||||||
va += VM_PAGE_TO_PHYS(m) -
|
va += VM_PAGE_TO_PHYS(m) - PTE_TO_PHYS(oldl2);
|
||||||
PTE_TO_PHYS(oldl2);
|
l3 = pmap_l2_to_l3(l2, va);
|
||||||
l3 = pmap_l2_to_l3(l2, va);
|
pmap_clear_bits(l3, PTE_D | PTE_W);
|
||||||
oldl3 = pmap_load(l3);
|
vm_page_dirty(m);
|
||||||
if ((oldl3 & PTE_V) != 0) {
|
pmap_invalidate_page(pmap, va);
|
||||||
while (!atomic_fcmpset_long(l3,
|
|
||||||
&oldl3, oldl3 & ~(PTE_D |
|
|
||||||
PTE_W)))
|
|
||||||
cpu_spinwait();
|
|
||||||
vm_page_dirty(m);
|
|
||||||
pmap_invalidate_page(pmap, va);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
PMAP_UNLOCK(pmap);
|
PMAP_UNLOCK(pmap);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user