aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorAndy Whitcroft <apw@shadowen.org>2008-06-26 05:55:58 -0400
committerPaul Mackerras <paulus@samba.org>2008-06-30 21:28:56 -0400
commit016b33c4958681c24056abed8ec95844a0da80a3 (patch)
tree67ba81cb6bc980119fab4eee15f09488e5777012 /include
parent03d70617b8a789c3721afaafde06fcbba7c7ebf1 (diff)
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 <apw@shadowen.org> Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'include')
-rw-r--r--include/asm-powerpc/hugetlb.h6
-rw-r--r--include/asm-powerpc/pgtable-ppc32.h6
-rw-r--r--include/asm-powerpc/pgtable-ppc64.h9
3 files changed, 15 insertions, 6 deletions
diff --git a/include/asm-powerpc/hugetlb.h b/include/asm-powerpc/hugetlb.h
index 649c6c3b87b3..be32ff02f4a0 100644
--- a/include/asm-powerpc/hugetlb.h
+++ b/include/asm-powerpc/hugetlb.h
@@ -49,12 +49,6 @@ static inline pte_t huge_pte_wrprotect(pte_t pte)
49 return pte_wrprotect(pte); 49 return pte_wrprotect(pte);
50} 50}
51 51
52static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
53 unsigned long addr, pte_t *ptep)
54{
55 ptep_set_wrprotect(mm, addr, ptep);
56}
57
58static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma, 52static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
59 unsigned long addr, pte_t *ptep, 53 unsigned long addr, pte_t *ptep,
60 pte_t pte, int dirty) 54 pte_t pte, int dirty)
diff --git a/include/asm-powerpc/pgtable-ppc32.h b/include/asm-powerpc/pgtable-ppc32.h
index dde466bd2cea..e1d2bb57f1d5 100644
--- a/include/asm-powerpc/pgtable-ppc32.h
+++ b/include/asm-powerpc/pgtable-ppc32.h
@@ -652,6 +652,12 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
652{ 652{
653 pte_update(ptep, (_PAGE_RW | _PAGE_HWWRITE), 0); 653 pte_update(ptep, (_PAGE_RW | _PAGE_HWWRITE), 0);
654} 654}
655static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
656 unsigned long addr, pte_t *ptep)
657{
658 ptep_set_wrprotect(mm, addr, ptep);
659}
660
655 661
656#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS 662#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
657static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty) 663static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty)
diff --git a/include/asm-powerpc/pgtable-ppc64.h b/include/asm-powerpc/pgtable-ppc64.h
index 2e48be841cc9..b2754d46be44 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,
312 return; 312 return;
313 old = pte_update(mm, addr, ptep, _PAGE_RW, 0); 313 old = pte_update(mm, addr, ptep, _PAGE_RW, 0);
314} 314}
315static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
316 unsigned long addr, pte_t *ptep)
317{
318 unsigned long old;
319
320 if ((pte_val(*ptep) & _PAGE_RW) == 0)
321 return;
322 old = pte_update(mm, addr, ptep, _PAGE_RW, 1);
323}
315 324
316/* 325/*
317 * We currently remove entries from the hashtable regardless of whether 326 * We currently remove entries from the hashtable regardless of whether