From f74710a0bfb50dedac27e544faf8b7b418ff9008 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 6 Feb 2004 14:00:29 +1100 Subject: [PATCH] ppc32: Flush the Hash PTE in ptep_test_and_clear_young() Without this, page aging is broken on ppc32 --- arch/ppc/mm/tlb.c | 20 ++++++++++++++++++++ include/asm-ppc/pgtable.h | 14 +++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/arch/ppc/mm/tlb.c b/arch/ppc/mm/tlb.c index 832d2d2bd0c2d..3bf70f65f6554 100644 --- a/arch/ppc/mm/tlb.c +++ b/arch/ppc/mm/tlb.c @@ -46,6 +46,26 @@ void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, unsigned long addr) } } +/* + * Called by ptep_test_and_clear_young() + */ +void flush_hash_one_pte(pte_t *ptep) +{ + struct page *ptepage; + struct mm_struct *mm; + unsigned long ptephys; + unsigned long addr; + + if (Hash == 0) + return; + + ptepage = virt_to_page(ptep); + mm = (struct mm_struct *) ptepage->mapping; + ptephys = __pa(ptep) & PAGE_MASK; + addr = ptepage->index + (((unsigned long)ptep & ~PAGE_MASK) << 9); + flush_hash_pages(mm->context, addr, ptephys, 1); +} + /* * Called at the end of a mmu_gather operation to make sure the * TLB flush is completely done. diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h index 0cf6aab40dfbd..8ac2de22eaddd 100644 --- a/include/asm-ppc/pgtable.h +++ b/include/asm-ppc/pgtable.h @@ -511,9 +511,21 @@ static inline void set_pte(pte_t *ptep, pte_t pte) #endif } +extern void flush_hash_one_pte(pte_t *ptep); + +/* + * 2.6 calles this without flushing the TLB entry, this is wrong + * for our hash-based implementation, we fix that up here + */ static inline int ptep_test_and_clear_young(pte_t *ptep) { - return (pte_update(ptep, _PAGE_ACCESSED, 0) & _PAGE_ACCESSED) != 0; + unsigned long old; + old = (pte_update(ptep, _PAGE_ACCESSED, 0) & _PAGE_ACCESSED); +#if _PAGE_HASHPTE != 0 + if (old & _PAGE_HASHPTE) + flush_hash_one_pte(ptep); +#endif + return old != 0; } static inline int ptep_test_and_clear_dirty(pte_t *ptep) -- 2.53.0