summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/powerpc/aim/mmu_oea.c25
-rw-r--r--sys/powerpc/aim/mmu_oea64.c25
-rw-r--r--sys/powerpc/include/pmap.h36
3 files changed, 60 insertions, 26 deletions
diff --git a/sys/powerpc/aim/mmu_oea.c b/sys/powerpc/aim/mmu_oea.c
index 88ca0f7..bff5763 100644
--- a/sys/powerpc/aim/mmu_oea.c
+++ b/sys/powerpc/aim/mmu_oea.c
@@ -824,6 +824,7 @@ moea_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
for (i = 0; i < 16; i++)
kernel_pmap->pm_sr[i] = EMPTY_SEGMENT + i;
CPU_FILL(&kernel_pmap->pm_active);
+ LIST_INIT(&kernel_pmap->pmap_pvo);
/*
* Set up the Open Firmware mappings
@@ -1582,6 +1583,7 @@ moea_pinit(mmu_t mmu, pmap_t pmap)
KASSERT((int)pmap < VM_MIN_KERNEL_ADDRESS, ("moea_pinit: virt pmap"));
PMAP_LOCK_INIT(pmap);
+ LIST_INIT(&pmap->pmap_pvo);
entropy = 0;
__asm __volatile("mftb %0" : "=r"(entropy));
@@ -1765,10 +1767,17 @@ moea_remove(mmu_t mmu, pmap_t pm, vm_offset_t sva, vm_offset_t eva)
vm_page_lock_queues();
PMAP_LOCK(pm);
- for (; sva < eva; sva += PAGE_SIZE) {
- pvo = moea_pvo_find_va(pm, sva, &pteidx);
- if (pvo != NULL) {
- moea_pvo_remove(pvo, pteidx);
+ if ((eva - sva)/PAGE_SIZE < 10) {
+ for (; sva < eva; sva += PAGE_SIZE) {
+ pvo = moea_pvo_find_va(pm, sva, &pteidx);
+ if (pvo != NULL)
+ moea_pvo_remove(pvo, pteidx);
+ }
+ } else {
+ LIST_FOREACH(pvo, &pm->pmap_pvo, pvo_plink) {
+ if (PVO_VADDR(pvo) < sva || PVO_VADDR(pvo) >= eva)
+ continue;
+ moea_pvo_remove(pvo, -1);
}
}
PMAP_UNLOCK(pm);
@@ -1931,6 +1940,11 @@ moea_pvo_enter(pmap_t pm, uma_zone_t zone, struct pvo_head *pvo_head,
moea_pte_create(&pvo->pvo_pte.pte, sr, va, pa | pte_lo);
/*
+ * Add to pmap list
+ */
+ LIST_INSERT_HEAD(&pm->pmap_pvo, pvo, pvo_plink);
+
+ /*
* Remember if the list was empty and therefore will be the first
* item.
*/
@@ -1996,9 +2010,10 @@ moea_pvo_remove(struct pvo_entry *pvo, int pteidx)
}
/*
- * Remove this PVO from the PV list.
+ * Remove this PVO from the PV and pmap lists.
*/
LIST_REMOVE(pvo, pvo_vlink);
+ LIST_REMOVE(pvo, pvo_plink);
/*
* Remove this from the overflow list and return it to the pool
diff --git a/sys/powerpc/aim/mmu_oea64.c b/sys/powerpc/aim/mmu_oea64.c
index 7500462..4413780 100644
--- a/sys/powerpc/aim/mmu_oea64.c
+++ b/sys/powerpc/aim/mmu_oea64.c
@@ -831,6 +831,7 @@ moea64_mid_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
kernel_pmap->pmap_phys = kernel_pmap;
CPU_FILL(&kernel_pmap->pm_active);
+ LIST_INIT(&kernel_pmap->pmap_pvo);
PMAP_LOCK_INIT(kernel_pmap);
@@ -1855,6 +1856,7 @@ void
moea64_pinit(mmu_t mmu, pmap_t pmap)
{
PMAP_LOCK_INIT(pmap);
+ LIST_INIT(&pmap->pmap_pvo);
pmap->pm_slb_tree_root = slb_alloc_tree();
pmap->pm_slb = slb_alloc_user_cache();
@@ -1868,6 +1870,7 @@ moea64_pinit(mmu_t mmu, pmap_t pmap)
uint32_t hash;
PMAP_LOCK_INIT(pmap);
+ LIST_INIT(&pmap->pmap_pvo);
if (pmap_bootstrapped)
pmap->pmap_phys = (pmap_t)moea64_kextract(mmu,
@@ -2034,10 +2037,18 @@ moea64_remove(mmu_t mmu, pmap_t pm, vm_offset_t sva, vm_offset_t eva)
vm_page_lock_queues();
PMAP_LOCK(pm);
- for (; sva < eva; sva += PAGE_SIZE) {
- pvo = moea64_pvo_find_va(pm, sva);
- if (pvo != NULL)
+ if ((eva - sva)/PAGE_SIZE < 10) {
+ for (; sva < eva; sva += PAGE_SIZE) {
+ pvo = moea64_pvo_find_va(pm, sva);
+ if (pvo != NULL)
+ moea64_pvo_remove(mmu, pvo);
+ }
+ } else {
+ LIST_FOREACH(pvo, &pm->pmap_pvo, pvo_plink) {
+ if (PVO_VADDR(pvo) < sva || PVO_VADDR(pvo) >= eva)
+ continue;
moea64_pvo_remove(mmu, pvo);
+ }
}
vm_page_unlock_queues();
PMAP_UNLOCK(pm);
@@ -2231,6 +2242,11 @@ moea64_pvo_enter(mmu_t mmu, pmap_t pm, uma_zone_t zone,
(uint64_t)(pa) | pte_lo, flags);
/*
+ * Add to pmap list
+ */
+ LIST_INSERT_HEAD(&pm->pmap_pvo, pvo, pvo_plink);
+
+ /*
* Remember if the list was empty and therefore will be the first
* item.
*/
@@ -2311,9 +2327,10 @@ moea64_pvo_remove(mmu_t mmu, struct pvo_entry *pvo)
}
/*
- * Remove this PVO from the PV list.
+ * Remove this PVO from the PV and pmap lists.
*/
LIST_REMOVE(pvo, pvo_vlink);
+ LIST_REMOVE(pvo, pvo_plink);
/*
* Remove this from the overflow list and return it to the pool
diff --git a/sys/powerpc/include/pmap.h b/sys/powerpc/include/pmap.h
index 688975d..ca13c18 100644
--- a/sys/powerpc/include/pmap.h
+++ b/sys/powerpc/include/pmap.h
@@ -88,28 +88,13 @@ struct pmap_md {
#endif /* !defined(NPMAPS) */
struct slbtnode;
-
-struct pmap {
- struct mtx pm_mtx;
-
- #ifdef __powerpc64__
- struct slbtnode *pm_slb_tree_root;
- struct slb **pm_slb;
- int pm_slb_len;
- #else
- register_t pm_sr[16];
- #endif
- cpuset_t pm_active;
-
- struct pmap *pmap_phys;
- struct pmap_statistics pm_stats;
-};
-
+struct pmap;
typedef struct pmap *pmap_t;
struct pvo_entry {
LIST_ENTRY(pvo_entry) pvo_vlink; /* Link to common virt page */
LIST_ENTRY(pvo_entry) pvo_olink; /* Link to overflow entry */
+ LIST_ENTRY(pvo_entry) pvo_plink; /* Link to pmap entries */
union {
struct pte pte; /* 32 bit PTE */
struct lpte lpte; /* 64 bit PTE */
@@ -137,6 +122,23 @@ LIST_HEAD(pvo_head, pvo_entry);
((void)((pvo)->pvo_vaddr |= (i)|PVO_PTEGIDX_VALID))
#define PVO_VSID(pvo) ((pvo)->pvo_vpn >> 16)
+struct pmap {
+ struct mtx pm_mtx;
+
+ #ifdef __powerpc64__
+ struct slbtnode *pm_slb_tree_root;
+ struct slb **pm_slb;
+ int pm_slb_len;
+ #else
+ register_t pm_sr[16];
+ #endif
+ cpuset_t pm_active;
+
+ struct pmap *pmap_phys;
+ struct pmap_statistics pm_stats;
+ struct pvo_head pmap_pvo;
+};
+
struct md_page {
u_int64_t mdpg_attrs;
vm_memattr_t mdpg_cache_attrs;
OpenPOWER on IntegriCloud