diff options
author | Zhang, Yanmin <yanmin_zhang@linux.intel.com> | 2006-03-22 03:08:50 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-22 10:54:03 -0500 |
commit | 8f860591ffb29738cf5539b6fbf27f50dcdeb380 (patch) | |
tree | 4265e45c4a79d86a16cd5175a836e8c531be8117 /include/asm-i386 | |
parent | aed75ff3caafce404d9be7f0c088716375be5279 (diff) |
[PATCH] Enable mprotect on huge pages
2.6.16-rc3 uses hugetlb on-demand paging, but it doesn_t support hugetlb
mprotect.
From: David Gibson <david@gibson.dropbear.id.au>
Remove a test from the mprotect() path which checks that the mprotect()ed
range on a hugepage VMA is hugepage aligned (yes, really, the sense of
is_aligned_hugepage_range() is the opposite of what you'd guess :-/).
In fact, we don't need this test. If the given addresses match the
beginning/end of a hugepage VMA they must already be suitably aligned. If
they don't, then mprotect_fixup() will attempt to split the VMA. The very
first test in split_vma() will check for a badly aligned address on a
hugepage VMA and return -EINVAL if necessary.
From: "Chen, Kenneth W" <kenneth.w.chen@intel.com>
On i386 and x86-64, pte flag _PAGE_PSE collides with _PAGE_PROTNONE. The
identify of hugetlb pte is lost when changing page protection via mprotect.
A page fault occurs later will trigger a bug check in huge_pte_alloc().
The fix is to always make new pte a hugetlb pte and also to clean up
legacy code where _PAGE_PRESENT is forced on in the pre-faulting day.
Signed-off-by: Zhang Yanmin <yanmin.zhang@intel.com>
Cc: David Gibson <david@gibson.dropbear.id.au>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: William Lee Irwin III <wli@holomorphy.com>
Signed-off-by: Ken Chen <kenneth.w.chen@intel.com>
Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
Cc: Andi Kleen <ak@muc.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'include/asm-i386')
-rw-r--r-- | include/asm-i386/pgtable.h | 5 |
1 files changed, 2 insertions, 3 deletions
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h index 088a945bf26..ee056c41a9f 100644 --- a/include/asm-i386/pgtable.h +++ b/include/asm-i386/pgtable.h | |||
@@ -219,13 +219,12 @@ extern unsigned long pg0[]; | |||
219 | * The following only work if pte_present() is true. | 219 | * The following only work if pte_present() is true. |
220 | * Undefined behaviour if not.. | 220 | * Undefined behaviour if not.. |
221 | */ | 221 | */ |
222 | #define __LARGE_PTE (_PAGE_PSE | _PAGE_PRESENT) | ||
223 | static inline int pte_user(pte_t pte) { return (pte).pte_low & _PAGE_USER; } | 222 | static inline int pte_user(pte_t pte) { return (pte).pte_low & _PAGE_USER; } |
224 | static inline int pte_read(pte_t pte) { return (pte).pte_low & _PAGE_USER; } | 223 | static inline int pte_read(pte_t pte) { return (pte).pte_low & _PAGE_USER; } |
225 | static inline int pte_dirty(pte_t pte) { return (pte).pte_low & _PAGE_DIRTY; } | 224 | static inline int pte_dirty(pte_t pte) { return (pte).pte_low & _PAGE_DIRTY; } |
226 | static inline int pte_young(pte_t pte) { return (pte).pte_low & _PAGE_ACCESSED; } | 225 | static inline int pte_young(pte_t pte) { return (pte).pte_low & _PAGE_ACCESSED; } |
227 | static inline int pte_write(pte_t pte) { return (pte).pte_low & _PAGE_RW; } | 226 | static inline int pte_write(pte_t pte) { return (pte).pte_low & _PAGE_RW; } |
228 | static inline int pte_huge(pte_t pte) { return ((pte).pte_low & __LARGE_PTE) == __LARGE_PTE; } | 227 | static inline int pte_huge(pte_t pte) { return (pte).pte_low & _PAGE_PSE; } |
229 | 228 | ||
230 | /* | 229 | /* |
231 | * The following only works if pte_present() is not true. | 230 | * The following only works if pte_present() is not true. |
@@ -242,7 +241,7 @@ static inline pte_t pte_mkexec(pte_t pte) { (pte).pte_low |= _PAGE_USER; return | |||
242 | static inline pte_t pte_mkdirty(pte_t pte) { (pte).pte_low |= _PAGE_DIRTY; return pte; } | 241 | static inline pte_t pte_mkdirty(pte_t pte) { (pte).pte_low |= _PAGE_DIRTY; return pte; } |
243 | static inline pte_t pte_mkyoung(pte_t pte) { (pte).pte_low |= _PAGE_ACCESSED; return pte; } | 242 | static inline pte_t pte_mkyoung(pte_t pte) { (pte).pte_low |= _PAGE_ACCESSED; return pte; } |
244 | static inline pte_t pte_mkwrite(pte_t pte) { (pte).pte_low |= _PAGE_RW; return pte; } | 243 | static inline pte_t pte_mkwrite(pte_t pte) { (pte).pte_low |= _PAGE_RW; return pte; } |
245 | static inline pte_t pte_mkhuge(pte_t pte) { (pte).pte_low |= __LARGE_PTE; return pte; } | 244 | static inline pte_t pte_mkhuge(pte_t pte) { (pte).pte_low |= _PAGE_PSE; return pte; } |
246 | 245 | ||
247 | #ifdef CONFIG_X86_PAE | 246 | #ifdef CONFIG_X86_PAE |
248 | # include <asm/pgtable-3level.h> | 247 | # include <asm/pgtable-3level.h> |