Skip to content

Commit a8e654f

Browse files
Nitin Guptatorvalds
authored andcommitted
sparc64: update pmdp_invalidate() to return old pmd value
It's required to avoid losing dirty and accessed bits. [[email protected]: add a `do' to the do-while loop] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Nitin Gupta <[email protected]> Signed-off-by: Kirill A. Shutemov <[email protected]> Cc: David Miller <[email protected]> Cc: Vlastimil Babka <[email protected]> Cc: Andrea Arcangeli <[email protected]> Cc: Michal Hocko <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 9c4563f commit a8e654f

File tree

2 files changed

+19
-6
lines changed

2 files changed

+19
-6
lines changed

arch/sparc/include/asm/pgtable_64.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1010,7 +1010,7 @@ void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
10101010
pmd_t *pmd);
10111011

10121012
#define __HAVE_ARCH_PMDP_INVALIDATE
1013-
extern void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
1013+
extern pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
10141014
pmd_t *pmdp);
10151015

10161016
#define __HAVE_ARCH_PGTABLE_DEPOSIT

arch/sparc/mm/tlb.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -219,17 +219,28 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr,
219219
}
220220
}
221221

222+
static inline pmd_t pmdp_establish(struct vm_area_struct *vma,
223+
unsigned long address, pmd_t *pmdp, pmd_t pmd)
224+
{
225+
pmd_t old;
226+
227+
do {
228+
old = *pmdp;
229+
} while (cmpxchg64(&pmdp->pmd, old.pmd, pmd.pmd) != old.pmd);
230+
231+
return old;
232+
}
233+
222234
/*
223235
* This routine is only called when splitting a THP
224236
*/
225-
void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
237+
pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
226238
pmd_t *pmdp)
227239
{
228-
pmd_t entry = *pmdp;
229-
230-
pmd_val(entry) &= ~_PAGE_VALID;
240+
pmd_t old, entry;
231241

232-
set_pmd_at(vma->vm_mm, address, pmdp, entry);
242+
entry = __pmd(pmd_val(*pmdp) & ~_PAGE_VALID);
243+
old = pmdp_establish(vma, address, pmdp, entry);
233244
flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
234245

235246
/*
@@ -240,6 +251,8 @@ void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
240251
if ((pmd_val(entry) & _PAGE_PMD_HUGE) &&
241252
!is_huge_zero_page(pmd_page(entry)))
242253
(vma->vm_mm)->context.thp_pte_count--;
254+
255+
return old;
243256
}
244257

245258
void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,

0 commit comments

Comments
 (0)