Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

sparc64: Fix regression in pmdp_invalidate().

pmdp_invalidate() was changed to update the pmd atomically
(to not lose dirty/access bits) and return the original pmd
value.

However, in doing so, we lost a lot of the essential work that
set_pmd_at() does, namely to update hugepage mapping counts and
queuing up the batched TLB flush entry.

Thus we were not flushing entries out of the TLB when making
such PMD changes.

Fix this by abstracting the accounting work of set_pmd_at() out into a
separate function, and call it from pmdp_establish().

Fixes: a8e654f01cb7 ("sparc64: update pmdp_invalidate() to return old pmd value")
Signed-off-by: David S. Miller <davem@davemloft.net>

+13 -6
+13 -6
arch/sparc/mm/tlb.c
··· 163 163 pte_unmap(pte); 164 164 } 165 165 166 - void set_pmd_at(struct mm_struct *mm, unsigned long addr, 167 - pmd_t *pmdp, pmd_t pmd) 166 + 167 + static void __set_pmd_acct(struct mm_struct *mm, unsigned long addr, 168 + pmd_t orig, pmd_t pmd) 168 169 { 169 - pmd_t orig = *pmdp; 170 - 171 - *pmdp = pmd; 172 - 173 170 if (mm == &init_mm) 174 171 return; 175 172 ··· 216 219 } 217 220 } 218 221 222 + void set_pmd_at(struct mm_struct *mm, unsigned long addr, 223 + pmd_t *pmdp, pmd_t pmd) 224 + { 225 + pmd_t orig = *pmdp; 226 + 227 + *pmdp = pmd; 228 + __set_pmd_acct(mm, addr, orig, pmd); 229 + } 230 + 219 231 static inline pmd_t pmdp_establish(struct vm_area_struct *vma, 220 232 unsigned long address, pmd_t *pmdp, pmd_t pmd) 221 233 { ··· 233 227 do { 234 228 old = *pmdp; 235 229 } while (cmpxchg64(&pmdp->pmd, old.pmd, pmd.pmd) != old.pmd); 230 + __set_pmd_acct(vma->vm_mm, address, old, pmd); 236 231 237 232 return old; 238 233 }