ppc32: Flush the Hash PTE in ptep_test_and_clear_young()

Without this, page aging is broken on ppc32
parent c380a048
...@@ -46,6 +46,26 @@ void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, unsigned long addr) ...@@ -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 * Called at the end of a mmu_gather operation to make sure the
* TLB flush is completely done. * TLB flush is completely done.
......
...@@ -511,9 +511,21 @@ static inline void set_pte(pte_t *ptep, pte_t pte) ...@@ -511,9 +511,21 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
#endif #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) 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) static inline int ptep_test_and_clear_dirty(pte_t *ptep)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment