summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2016-06-20 09:15:03 +0000
committerkib <kib@FreeBSD.org>2016-06-20 09:15:03 +0000
commit25fbd815762f4ddb3da2c9e3e27efb7fa1b7c1bd (patch)
tree3a30a2c17ccda973b14161a14fdfa2a867b31f46 /sys/amd64
parent50fadd85447994b1c827933bfbb1691745909c94 (diff)
downloadFreeBSD-src-25fbd815762f4ddb3da2c9e3e27efb7fa1b7c1bd.zip
FreeBSD-src-25fbd815762f4ddb3da2c9e3e27efb7fa1b7c1bd.tar.gz
MFC r301853:
Do not access pv_table array for fictitious pages.
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/amd64/pmap.c25
1 files changed, 10 insertions, 15 deletions
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index 8136745..d7c5213 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -381,6 +381,7 @@ static TAILQ_HEAD(pch, pv_chunk) pv_chunks = TAILQ_HEAD_INITIALIZER(pv_chunks);
static struct mtx pv_chunks_mutex;
static struct rwlock pv_list_locks[NPV_LIST_LOCKS];
static struct md_page *pv_table;
+static struct md_page pv_dummy;
/*
* All those kernel PT submaps that BSD is so fond of
@@ -1100,6 +1101,7 @@ pmap_init(void)
M_WAITOK | M_ZERO);
for (i = 0; i < pv_npg; i++)
TAILQ_INIT(&pv_table[i].pv_list);
+ TAILQ_INIT(&pv_dummy.pv_list);
mtx_init(&cpage_lock, "cpage", NULL, MTX_DEF);
cpage_a = kva_alloc(PAGE_SIZE);
@@ -3808,9 +3810,8 @@ pmap_remove_all(vm_page_t m)
("pmap_remove_all: page %p is not managed", m));
SLIST_INIT(&free);
rw_wlock(&pvh_global_lock);
- if ((m->flags & PG_FICTITIOUS) != 0)
- goto small_mappings;
- pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
+ pvh = (m->flags & PG_FICTITIOUS) != 0 ? &pv_dummy :
+ pa_to_pvh(VM_PAGE_TO_PHYS(m));
while ((pv = TAILQ_FIRST(&pvh->pv_list)) != NULL) {
pmap = PV_PMAP(pv);
PMAP_LOCK(pmap);
@@ -3819,7 +3820,6 @@ pmap_remove_all(vm_page_t m)
(void)pmap_demote_pde(pmap, pde, va);
PMAP_UNLOCK(pmap);
}
-small_mappings:
while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) {
pmap = PV_PMAP(pv);
PMAP_LOCK(pmap);
@@ -5677,11 +5677,10 @@ pmap_remove_write(vm_page_t m)
return;
rw_rlock(&pvh_global_lock);
lock = VM_PAGE_TO_PV_LIST_LOCK(m);
- pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
+ pvh = (m->flags & PG_FICTITIOUS) != 0 ? &pv_dummy :
+ pa_to_pvh(VM_PAGE_TO_PHYS(m));
retry_pv_loop:
rw_wlock(lock);
- if ((m->flags & PG_FICTITIOUS) != 0)
- goto small_mappings;
TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_next, next_pv) {
pmap = PV_PMAP(pv);
if (!PMAP_TRYLOCK(pmap)) {
@@ -5705,7 +5704,6 @@ retry_pv_loop:
lock, VM_PAGE_TO_PV_LIST_LOCK(m), m));
PMAP_UNLOCK(pmap);
}
-small_mappings:
TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
pmap = PV_PMAP(pv);
if (!PMAP_TRYLOCK(pmap)) {
@@ -5807,13 +5805,12 @@ pmap_ts_referenced(vm_page_t m)
cleared = 0;
pa = VM_PAGE_TO_PHYS(m);
lock = PHYS_TO_PV_LIST_LOCK(pa);
- pvh = pa_to_pvh(pa);
+ pvh = (m->flags & PG_FICTITIOUS) != 0 ? &pv_dummy : pa_to_pvh(pa);
rw_rlock(&pvh_global_lock);
rw_wlock(lock);
retry:
not_cleared = 0;
- if ((m->flags & PG_FICTITIOUS) != 0 ||
- (pvf = TAILQ_FIRST(&pvh->pv_list)) == NULL)
+ if ((pvf = TAILQ_FIRST(&pvh->pv_list)) == NULL)
goto small_mappings;
pv = pvf;
do {
@@ -6139,13 +6136,12 @@ pmap_clear_modify(vm_page_t m)
*/
if ((m->aflags & PGA_WRITEABLE) == 0)
return;
- pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
+ pvh = (m->flags & PG_FICTITIOUS) != 0 ? &pv_dummy :
+ pa_to_pvh(VM_PAGE_TO_PHYS(m));
rw_rlock(&pvh_global_lock);
lock = VM_PAGE_TO_PV_LIST_LOCK(m);
rw_wlock(lock);
restart:
- if ((m->flags & PG_FICTITIOUS) != 0)
- goto small_mappings;
TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_next, next_pv) {
pmap = PV_PMAP(pv);
if (!PMAP_TRYLOCK(pmap)) {
@@ -6189,7 +6185,6 @@ restart:
}
PMAP_UNLOCK(pmap);
}
-small_mappings:
TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
pmap = PV_PMAP(pv);
if (!PMAP_TRYLOCK(pmap)) {
OpenPOWER on IntegriCloud