Skip to content

Commit

Permalink
(6/6) Convert pmap to expect busy in write related operations now tha…
Browse files Browse the repository at this point in the history
…t all

callers hold it.

This simplifies pmap code and removes a dependency on the object lock.

Reviewed by:    kib, markj
Tested by:      pho
Sponsored by:   Netflix, Intel
Differential Revision:	https://reviews.freebsd.org/D21596
  • Loading branch information
Jeff Roberson authored and Jeff Roberson committed Oct 15, 2019
1 parent fff5403 commit 638f867
Show file tree
Hide file tree
Showing 11 changed files with 80 additions and 225 deletions.
28 changes: 7 additions & 21 deletions sys/amd64/amd64/pmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -7285,12 +7285,9 @@ pmap_is_modified(vm_page_t m)
("pmap_is_modified: page %p is not managed", m));

/*
* If the page is not exclusive busied, then PGA_WRITEABLE cannot be
* concurrently set while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no PTEs can have PG_M set.
* If the page is not busied then this check is racy.
*/
VM_OBJECT_ASSERT_WLOCKED(m->object);
if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
if (!pmap_page_is_write_mapped(m))
return (FALSE);
return (pmap_page_test_mappings(m, FALSE, TRUE));
}
Expand Down Expand Up @@ -7353,14 +7350,10 @@ pmap_remove_write(vm_page_t m)
KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_remove_write: page %p is not managed", m));

/*
* If the page is not exclusive busied, then PGA_WRITEABLE cannot be
* set by another thread while the object is locked. Thus,
* if PGA_WRITEABLE is clear, no page table entries need updating.
*/
VM_OBJECT_ASSERT_WLOCKED(m->object);
if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
vm_page_assert_busied(m);
if (!pmap_page_is_write_mapped(m))
return;

lock = VM_PAGE_TO_PV_LIST_LOCK(m);
pvh = (m->flags & PG_FICTITIOUS) != 0 ? &pv_dummy :
pa_to_pvh(VM_PAGE_TO_PHYS(m));
Expand Down Expand Up @@ -7833,16 +7826,9 @@ pmap_clear_modify(vm_page_t m)

KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_clear_modify: page %p is not managed", m));
VM_OBJECT_ASSERT_WLOCKED(m->object);
KASSERT(!vm_page_xbusied(m),
("pmap_clear_modify: page %p is exclusive busied", m));
vm_page_assert_busied(m);

/*
* If the page is not PGA_WRITEABLE, then no PTEs can have PG_M set.
* If the object containing the page is locked and the page is not
* exclusive busied, then PGA_WRITEABLE cannot be concurrently set.
*/
if ((m->aflags & PGA_WRITEABLE) == 0)
if (!pmap_page_is_write_mapped(m))
return;
pvh = (m->flags & PG_FICTITIOUS) != 0 ? &pv_dummy :
pa_to_pvh(VM_PAGE_TO_PHYS(m));
Expand Down
20 changes: 4 additions & 16 deletions sys/arm/arm/pmap-v4.c
Original file line number Diff line number Diff line change
Expand Up @@ -4095,16 +4095,9 @@ pmap_clear_modify(vm_page_t m)

KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_clear_modify: page %p is not managed", m));
VM_OBJECT_ASSERT_WLOCKED(m->object);
KASSERT(!vm_page_xbusied(m),
("pmap_clear_modify: page %p is exclusive busied", m));
vm_page_assert_busied(m);

/*
* If the page is not PGA_WRITEABLE, then no mappings can be modified.
* If the object containing the page is locked and the page is not
* exclusive busied, then PGA_WRITEABLE cannot be concurrently set.
*/
if ((m->aflags & PGA_WRITEABLE) == 0)
if (!pmap_page_is_write_mapped(m))
return;
if (m->md.pvh_attrs & PVF_MOD)
pmap_clearbit(m, PVF_MOD);
Expand Down Expand Up @@ -4136,14 +4129,9 @@ pmap_remove_write(vm_page_t m)

KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_remove_write: page %p is not managed", m));
vm_page_assert_busied(m);

/*
* If the page is not exclusive busied, then PGA_WRITEABLE cannot be
* set by another thread while the object is locked. Thus,
* if PGA_WRITEABLE is clear, no page table entries need updating.
*/
VM_OBJECT_ASSERT_WLOCKED(m->object);
if (vm_page_xbusied(m) || (m->aflags & PGA_WRITEABLE) != 0)
if (pmap_page_is_write_mapped(m))
pmap_clearbit(m, PVF_WRITE);
}

Expand Down
28 changes: 6 additions & 22 deletions sys/arm/arm/pmap-v6.c
Original file line number Diff line number Diff line change
Expand Up @@ -5192,12 +5192,9 @@ pmap_is_modified(vm_page_t m)
("%s: page %p is not managed", __func__, m));

/*
* If the page is not exclusive busied, then PGA_WRITEABLE cannot be
* concurrently set while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no PTE2s can have PG_M set.
* If the page is not busied then this check is racy.
*/
VM_OBJECT_ASSERT_WLOCKED(m->object);
if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
if (!pmap_page_is_write_mapped(m))
return (FALSE);
rw_wlock(&pvh_global_lock);
rv = pmap_is_modified_pvh(&m->md) ||
Expand Down Expand Up @@ -5533,14 +5530,9 @@ pmap_remove_write(vm_page_t m)

KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("%s: page %p is not managed", __func__, m));
vm_page_assert_busied(m);

/*
* If the page is not exclusive busied, then PGA_WRITEABLE cannot be
* set by another thread while the object is locked. Thus,
* if PGA_WRITEABLE is clear, no page table entries need updating.
*/
VM_OBJECT_ASSERT_WLOCKED(m->object);
if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
if (!pmap_page_is_write_mapped(m))
return;
rw_wlock(&pvh_global_lock);
sched_pin();
Expand Down Expand Up @@ -5691,17 +5683,9 @@ pmap_clear_modify(vm_page_t m)

KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("%s: page %p is not managed", __func__, m));
VM_OBJECT_ASSERT_WLOCKED(m->object);
KASSERT(!vm_page_xbusied(m),
("%s: page %p is exclusive busy", __func__, m));
vm_page_assert_busied(m);

/*
* If the page is not PGA_WRITEABLE, then no PTE2s can have PTE2_NM
* cleared. If the object containing the page is locked and the page
* is not exclusive busied, then PGA_WRITEABLE cannot be concurrently
* set.
*/
if ((m->flags & PGA_WRITEABLE) == 0)
if (!pmap_page_is_write_mapped(m))
return;
rw_wlock(&pvh_global_lock);
sched_pin();
Expand Down
27 changes: 6 additions & 21 deletions sys/arm64/arm64/pmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -4548,12 +4548,9 @@ pmap_is_modified(vm_page_t m)
("pmap_is_modified: page %p is not managed", m));

/*
* If the page is not exclusive busied, then PGA_WRITEABLE cannot be
* concurrently set while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no PTEs can have PG_M set.
* If the page is not busied then this check is racy.
*/
VM_OBJECT_ASSERT_WLOCKED(m->object);
if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
if (!pmap_page_is_write_mapped(m))
return (FALSE);
return (pmap_page_test_mappings(m, FALSE, TRUE));
}
Expand Down Expand Up @@ -4612,14 +4609,9 @@ pmap_remove_write(vm_page_t m)

KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_remove_write: page %p is not managed", m));
vm_page_assert_busied(m);

/*
* If the page is not exclusive busied, then PGA_WRITEABLE cannot be
* set by another thread while the object is locked. Thus,
* if PGA_WRITEABLE is clear, no page table entries need updating.
*/
VM_OBJECT_ASSERT_WLOCKED(m->object);
if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
if (!pmap_page_is_write_mapped(m))
return;
lock = VM_PAGE_TO_PV_LIST_LOCK(m);
pvh = (m->flags & PG_FICTITIOUS) != 0 ? &pv_dummy :
Expand Down Expand Up @@ -4987,16 +4979,9 @@ pmap_clear_modify(vm_page_t m)

KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_clear_modify: page %p is not managed", m));
VM_OBJECT_ASSERT_WLOCKED(m->object);
KASSERT(!vm_page_xbusied(m),
("pmap_clear_modify: page %p is exclusive busied", m));
vm_page_assert_busied(m);

/*
* If the page is not PGA_WRITEABLE, then no PTEs can have ATTR_SW_DBM
* set. If the object containing the page is locked and the page is not
* exclusive busied, then PGA_WRITEABLE cannot be concurrently set.
*/
if ((m->aflags & PGA_WRITEABLE) == 0)
if (!pmap_page_is_write_mapped(m))
return;
pvh = (m->flags & PG_FICTITIOUS) != 0 ? &pv_dummy :
pa_to_pvh(VM_PAGE_TO_PHYS(m));
Expand Down
27 changes: 6 additions & 21 deletions sys/i386/i386/pmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -4874,12 +4874,9 @@ __CONCAT(PMTYPE, is_modified)(vm_page_t m)
("pmap_is_modified: page %p is not managed", m));

/*
* If the page is not exclusive busied, then PGA_WRITEABLE cannot be
* concurrently set while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no PTEs can have PG_M set.
* If the page is not busied then this check is racy.
*/
VM_OBJECT_ASSERT_WLOCKED(m->object);
if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
if (!pmap_page_is_write_mapped(m))
return (FALSE);
rw_wlock(&pvh_global_lock);
rv = pmap_is_modified_pvh(&m->md) ||
Expand Down Expand Up @@ -5003,14 +5000,9 @@ __CONCAT(PMTYPE, remove_write)(vm_page_t m)

KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_remove_write: page %p is not managed", m));
vm_page_assert_busied(m);

/*
* If the page is not exclusive busied, then PGA_WRITEABLE cannot be
* set by another thread while the object is locked. Thus,
* if PGA_WRITEABLE is clear, no page table entries need updating.
*/
VM_OBJECT_ASSERT_WLOCKED(m->object);
if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
if (!pmap_page_is_write_mapped(m))
return;
rw_wlock(&pvh_global_lock);
sched_pin();
Expand Down Expand Up @@ -5313,16 +5305,9 @@ __CONCAT(PMTYPE, clear_modify)(vm_page_t m)

KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_clear_modify: page %p is not managed", m));
VM_OBJECT_ASSERT_WLOCKED(m->object);
KASSERT(!vm_page_xbusied(m),
("pmap_clear_modify: page %p is exclusive busied", m));
vm_page_assert_busied(m);

/*
* If the page is not PGA_WRITEABLE, then no PTEs can have PG_M set.
* If the object containing the page is locked and the page is not
* exclusive busied, then PGA_WRITEABLE cannot be concurrently set.
*/
if ((m->aflags & PGA_WRITEABLE) == 0)
if (!pmap_page_is_write_mapped(m))
return;
rw_wlock(&pvh_global_lock);
sched_pin();
Expand Down
27 changes: 7 additions & 20 deletions sys/mips/mips/pmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -2893,14 +2893,9 @@ pmap_remove_write(vm_page_t m)

KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_remove_write: page %p is not managed", m));
vm_page_assert_busied(m);

/*
* If the page is not exclusive busied, then PGA_WRITEABLE cannot be
* set by another thread while the object is locked. Thus,
* if PGA_WRITEABLE is clear, no page table entries need updating.
*/
VM_OBJECT_ASSERT_WLOCKED(m->object);
if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
if (!pmap_page_is_write_mapped(m))
return;
rw_wlock(&pvh_global_lock);
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
Expand Down Expand Up @@ -2960,13 +2955,11 @@ pmap_is_modified(vm_page_t m)
("pmap_is_modified: page %p is not managed", m));

/*
* If the page is not exclusive busied, then PGA_WRITEABLE cannot be
* concurrently set while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no PTEs can have PTE_D set.
* If the page is not busied then this check is racy.
*/
VM_OBJECT_ASSERT_WLOCKED(m->object);
if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
if (!pmap_page_is_write_mapped(m))
return (FALSE);

rw_wlock(&pvh_global_lock);
rv = pmap_testbit(m, PTE_D);
rw_wunlock(&pvh_global_lock);
Expand Down Expand Up @@ -3101,15 +3094,9 @@ pmap_clear_modify(vm_page_t m)
KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_clear_modify: page %p is not managed", m));
VM_OBJECT_ASSERT_WLOCKED(m->object);
KASSERT(!vm_page_xbusied(m),
("pmap_clear_modify: page %p is exclusive busied", m));
vm_page_assert_busied(m);

/*
* If the page is not PGA_WRITEABLE, then no PTEs can have PTE_D set.
* If the object containing the page is locked and the page is not
* write busied, then PGA_WRITEABLE cannot be concurrently set.
*/
if ((m->aflags & PGA_WRITEABLE) == 0)
if (!pmap_page_is_write_mapped(m))
return;
rw_wlock(&pvh_global_lock);
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
Expand Down
28 changes: 7 additions & 21 deletions sys/powerpc/aim/mmu_oea.c
Original file line number Diff line number Diff line change
Expand Up @@ -1314,13 +1314,11 @@ moea_is_modified(mmu_t mmu, vm_page_t m)
("moea_is_modified: page %p is not managed", m));

/*
* If the page is not exclusive busied, then PGA_WRITEABLE cannot be
* concurrently set while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no PTEs can have PTE_CHG set.
* If the page is not busied then this check is racy.
*/
VM_OBJECT_ASSERT_WLOCKED(m->object);
if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
if (!pmap_page_is_write_mapped(m))
return (FALSE);

rw_wlock(&pvh_global_lock);
rv = moea_query_bit(m, PTE_CHG);
rw_wunlock(&pvh_global_lock);
Expand All @@ -1346,16 +1344,9 @@ moea_clear_modify(mmu_t mmu, vm_page_t m)

KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("moea_clear_modify: page %p is not managed", m));
VM_OBJECT_ASSERT_WLOCKED(m->object);
KASSERT(!vm_page_xbusied(m),
("moea_clear_modify: page %p is exclusive busy", m));
vm_page_assert_busied(m);

/*
* If the page is not PGA_WRITEABLE, then no PTEs can have PTE_CHG
* set. If the object containing the page is locked and the page is
* not exclusive busied, then PGA_WRITEABLE cannot be concurrently set.
*/
if ((m->aflags & PGA_WRITEABLE) == 0)
if (!pmap_page_is_write_mapped(m))
return;
rw_wlock(&pvh_global_lock);
moea_clear_bit(m, PTE_CHG);
Expand All @@ -1375,14 +1366,9 @@ moea_remove_write(mmu_t mmu, vm_page_t m)

KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("moea_remove_write: page %p is not managed", m));
vm_page_assert_busied(m);

/*
* If the page is not exclusive busied, then PGA_WRITEABLE cannot be
* set by another thread while the object is locked. Thus,
* if PGA_WRITEABLE is clear, no page table entries need updating.
*/
VM_OBJECT_ASSERT_WLOCKED(m->object);
if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
if (!pmap_page_is_write_mapped(m))
return;
rw_wlock(&pvh_global_lock);
lo = moea_attr_fetch(m);
Expand Down
Loading

0 comments on commit 638f867

Please sign in to comment.