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
This commit is contained in:
Alan Cox 2014-08-01 01:48:41 +00:00
parent 88998d7afc
commit add0359068
2 changed files with 44 additions and 0 deletions

View File

@ -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);

View File

@ -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);
}