From 016b33c4958681c24056abed8ec95844a0da80a3 Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Thu, 26 Jun 2008 19:55:58 +1000 Subject: powerpc: Add 64 bit version of huge_ptep_set_wrprotect The implementation of huge_ptep_set_wrprotect() directly calls ptep_set_wrprotect() to mark a hugepte write protected. However this call is not appropriate on ppc64 kernels as this is a small page only implementation. This can lead to the hash not being flushed correctly when a mapping is being converted to COW, allowing processes to continue using the original copy. Currently huge_ptep_set_wrprotect() unconditionally calls ptep_set_wrprotect(). This is fine on ppc32 kernels as this call is generic. On 64 bit this is implemented as: pte_update(mm, addr, ptep, _PAGE_RW, 0); On ppc64 this last parameter is the page size and is passed directly on to hpte_need_flush(): hpte_need_flush(mm, addr, ptep, old, huge); And this directly affects the page size we pass to flush_hash_page(): flush_hash_page(vaddr, rpte, psize, ssize, 0); As this changes the way the hash is calculated we will flush the wrong pages, potentially leaving live hashes to the original page. Move the definition of huge_ptep_set_wrprotect() to the 32/64 bit specific headers. Signed-off-by: Andy Whitcroft Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- include/asm-powerpc/pgtable-ppc64.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'include/asm-powerpc/pgtable-ppc64.h') diff --git a/include/asm-powerpc/pgtable-ppc64.h b/include/asm-powerpc/pgtable-ppc64.h index 2e48be8..b2754d4 100644 --- a/include/asm-powerpc/pgtable-ppc64.h +++ b/include/asm-powerpc/pgtable-ppc64.h @@ -312,6 +312,15 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, return; old = pte_update(mm, addr, ptep, _PAGE_RW, 0); } +static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, + unsigned long addr, pte_t *ptep) +{ + unsigned long old; + + if ((pte_val(*ptep) & _PAGE_RW) == 0) + return; + old = pte_update(mm, addr, ptep, _PAGE_RW, 1); +} /* * We currently remove entries from the hashtable regardless of whether -- cgit v1.1