diff options
author | Andy Whitcroft <apw@shadowen.org> | 2008-06-26 05:55:58 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2008-06-30 21:28:56 -0400 |
commit | 016b33c4958681c24056abed8ec95844a0da80a3 (patch) | |
tree | 67ba81cb6bc980119fab4eee15f09488e5777012 /include/asm-powerpc/pgtable-ppc64.h | |
parent | 03d70617b8a789c3721afaafde06fcbba7c7ebf1 (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/asm-powerpc/pgtable-ppc64.h')
-rw-r--r-- | include/asm-powerpc/pgtable-ppc64.h | 9 |
1 files changed, 9 insertions, 0 deletions
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 | } |
315 | static 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 |