diff options
author | alc <alc@FreeBSD.org> | 2014-08-01 01:48:41 +0000 |
---|---|---|
committer | alc <alc@FreeBSD.org> | 2014-08-01 01:48:41 +0000 |
commit | 2672e2483d20f935efb79ece09f8f9d347372198 (patch) | |
tree | fbb0131a21c6eb56d9769a19e48e894068620cc0 /sys/powerpc/aim | |
parent | a2ddf5904ecb2ad1817d80799104e33536032d6b (diff) | |
download | FreeBSD-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.c | 14 | ||||
-rw-r--r-- | sys/powerpc/aim/mmu_oea64.c | 30 |
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); } |