summaryrefslogtreecommitdiffstats
path: root/sys/powerpc/aim
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2014-08-01 01:48:41 +0000
committeralc <alc@FreeBSD.org>2014-08-01 01:48:41 +0000
commit2672e2483d20f935efb79ece09f8f9d347372198 (patch)
treefbb0131a21c6eb56d9769a19e48e894068620cc0 /sys/powerpc/aim
parenta2ddf5904ecb2ad1817d80799104e33536032d6b (diff)
downloadFreeBSD-src-2672e2483d20f935efb79ece09f8f9d347372198.zip
FreeBSD-src-2672e2483d20f935efb79ece09f8f9d347372198.tar.gz
Correct a long-standing problem in moea{,64}_pvo_enter() that was revealed
by the combination of r268591 and r269134: When we attempt to add the wired attribute to an existing mapping, moea{,64}_pvo_enter() do nothing. (They only set the wired attribute on newly created mappings.) Tested by: andreast
Diffstat (limited to 'sys/powerpc/aim')
-rw-r--r--sys/powerpc/aim/mmu_oea.c14
-rw-r--r--sys/powerpc/aim/mmu_oea64.c30
2 files changed, 44 insertions, 0 deletions
diff --git a/sys/powerpc/aim/mmu_oea.c b/sys/powerpc/aim/mmu_oea.c
index 14de67f..b6ba066 100644
--- a/sys/powerpc/aim/mmu_oea.c
+++ b/sys/powerpc/aim/mmu_oea.c
@@ -1951,7 +1951,21 @@ moea_pvo_enter(pmap_t pm, uma_zone_t zone, struct pvo_head *pvo_head,
if ((pvo->pvo_pte.pte.pte_lo & PTE_RPGN) == pa &&
(pvo->pvo_pte.pte.pte_lo & PTE_PP) ==
(pte_lo & PTE_PP)) {
+ /*
+ * The PTE is not changing. Instead, this may
+ * be a request to change the mapping's wired
+ * attribute.
+ */
mtx_unlock(&moea_table_mutex);
+ if ((flags & PVO_WIRED) != 0 &&
+ (pvo->pvo_vaddr & PVO_WIRED) == 0) {
+ pvo->pvo_vaddr |= PVO_WIRED;
+ pm->pm_stats.wired_count++;
+ } else if ((flags & PVO_WIRED) == 0 &&
+ (pvo->pvo_vaddr & PVO_WIRED) != 0) {
+ pvo->pvo_vaddr &= ~PVO_WIRED;
+ pm->pm_stats.wired_count--;
+ }
return (0);
}
moea_pvo_remove(pvo, -1);
diff --git a/sys/powerpc/aim/mmu_oea64.c b/sys/powerpc/aim/mmu_oea64.c
index fae2d0e..39f5b9d 100644
--- a/sys/powerpc/aim/mmu_oea64.c
+++ b/sys/powerpc/aim/mmu_oea64.c
@@ -2234,6 +2234,7 @@ moea64_pvo_enter(mmu_t mmu, pmap_t pm, uma_zone_t zone,
uint64_t pte_lo, int flags)
{
struct pvo_entry *pvo;
+ uintptr_t pt;
uint64_t vsid;
int first;
u_int ptegidx;
@@ -2276,13 +2277,42 @@ moea64_pvo_enter(mmu_t mmu, pmap_t pm, uma_zone_t zone,
if ((pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN) == pa &&
(pvo->pvo_pte.lpte.pte_lo & (LPTE_NOEXEC | LPTE_PP))
== (pte_lo & (LPTE_NOEXEC | LPTE_PP))) {
+ /*
+ * The physical page and protection are not
+ * changing. Instead, this may be a request
+ * to change the mapping's wired attribute.
+ */
+ pt = -1;
+ if ((flags & PVO_WIRED) != 0 &&
+ (pvo->pvo_vaddr & PVO_WIRED) == 0) {
+ pt = MOEA64_PVO_TO_PTE(mmu, pvo);
+ pvo->pvo_vaddr |= PVO_WIRED;
+ pvo->pvo_pte.lpte.pte_hi |= LPTE_WIRED;
+ pm->pm_stats.wired_count++;
+ } else if ((flags & PVO_WIRED) == 0 &&
+ (pvo->pvo_vaddr & PVO_WIRED) != 0) {
+ pt = MOEA64_PVO_TO_PTE(mmu, pvo);
+ pvo->pvo_vaddr &= ~PVO_WIRED;
+ pvo->pvo_pte.lpte.pte_hi &= ~LPTE_WIRED;
+ pm->pm_stats.wired_count--;
+ }
if (!(pvo->pvo_pte.lpte.pte_hi & LPTE_VALID)) {
+ KASSERT(pt == -1,
+ ("moea64_pvo_enter: valid pt"));
/* Re-insert if spilled */
i = MOEA64_PTE_INSERT(mmu, ptegidx,
&pvo->pvo_pte.lpte);
if (i >= 0)
PVO_PTEGIDX_SET(pvo, i);
moea64_pte_overflow--;
+ } else if (pt != -1) {
+ /*
+ * The PTE's wired attribute is not a
+ * hardware feature, so there is no
+ * need to invalidate any TLB entries.
+ */
+ MOEA64_PTE_CHANGE(mmu, pt,
+ &pvo->pvo_pte.lpte, pvo->pvo_vpn);
}
return (0);
}
OpenPOWER on IntegriCloud