Implement pmap_page_is_mapped() correctly on arm64 and riscv.

We must also check for large mappings.  pmap_page_is_mapped() is
mostly used in assertions, so the problem was not very noticeable.

Reviewed by:	alc
MFC after:	1 week
Differential Revision:	https://reviews.freebsd.org/D21824
This commit is contained in:
Mark Johnston 2019-09-27 23:37:01 +00:00
parent d3588766e1
commit d4586dd328
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=352826
4 changed files with 44 additions and 4 deletions

View File

@ -4240,6 +4240,27 @@ pmap_page_wired_mappings(vm_page_t m)
return (count);
}
/*
* Returns true if the given page is mapped individually or as part of
* a 2mpage. Otherwise, returns false.
*/
bool
pmap_page_is_mapped(vm_page_t m)
{
struct rwlock *lock;
bool rv;
if ((m->oflags & VPO_UNMANAGED) != 0)
return (false);
lock = VM_PAGE_TO_PV_LIST_LOCK(m);
rw_rlock(lock);
rv = !TAILQ_EMPTY(&m->md.pv_list) ||
((m->flags & PG_FICTITIOUS) == 0 &&
!TAILQ_EMPTY(&pa_to_pvh(VM_PAGE_TO_PHYS(m))->pv_list));
rw_runlock(lock);
return (rv);
}
/*
* Destroy all managed, non-wired mappings in the given user-space
* pmap. This pmap cannot be active on any processor besides the

View File

@ -150,6 +150,7 @@ vm_paddr_t pmap_kextract(vm_offset_t va);
void pmap_kremove(vm_offset_t);
void pmap_kremove_device(vm_offset_t, vm_size_t);
void *pmap_mapdev_attr(vm_offset_t pa, vm_size_t size, vm_memattr_t ma);
bool pmap_page_is_mapped(vm_page_t m);
bool pmap_ps_enabled(pmap_t pmap);
void *pmap_mapdev(vm_offset_t, vm_size_t);
@ -167,8 +168,6 @@ int pmap_fault(pmap_t, uint64_t, uint64_t);
struct pcb *pmap_switch(struct thread *, struct thread *);
#define pmap_page_is_mapped(m) (!TAILQ_EMPTY(&(m)->md.pv_list))
static inline int
pmap_vmspace_copy(pmap_t dst_pmap __unused, pmap_t src_pmap __unused)
{

View File

@ -146,6 +146,7 @@ void pmap_kenter_device(vm_offset_t, vm_size_t, vm_paddr_t);
vm_paddr_t pmap_kextract(vm_offset_t va);
void pmap_kremove(vm_offset_t);
void pmap_kremove_device(vm_offset_t, vm_size_t);
bool pmap_page_is_mapped(vm_page_t m);
bool pmap_ps_enabled(pmap_t);
void *pmap_mapdev(vm_offset_t, vm_size_t);
@ -159,8 +160,6 @@ void pmap_unmap_io_transient(vm_page_t *, vm_offset_t *, int, boolean_t);
bool pmap_get_tables(pmap_t, vm_offset_t, pd_entry_t **, pd_entry_t **,
pt_entry_t **);
#define pmap_page_is_mapped(m) (!TAILQ_EMPTY(&(m)->md.pv_list))
int pmap_fault_fixup(pmap_t, vm_offset_t, vm_prot_t);
static inline int

View File

@ -3541,6 +3541,27 @@ pmap_page_wired_mappings(vm_page_t m)
return (count);
}
/*
* Returns true if the given page is mapped individually or as part of
* a 2mpage. Otherwise, returns false.
*/
bool
pmap_page_is_mapped(vm_page_t m)
{
struct rwlock *lock;
bool rv;
if ((m->oflags & VPO_UNMANAGED) != 0)
return (false);
lock = VM_PAGE_TO_PV_LIST_LOCK(m);
rw_rlock(lock);
rv = !TAILQ_EMPTY(&m->md.pv_list) ||
((m->flags & PG_FICTITIOUS) == 0 &&
!TAILQ_EMPTY(&pa_to_pvh(VM_PAGE_TO_PHYS(m))->pv_list));
rw_runlock(lock);
return (rv);
}
static void
pmap_remove_pages_pv(pmap_t pmap, vm_page_t m, pv_entry_t pv,
struct spglist *free, bool superpage)