diff options
| -rw-r--r-- | include/asm-x86/pgtable.h | 16 | ||||
| -rw-r--r-- | mm/mprotect.c | 11 |
2 files changed, 23 insertions, 4 deletions
diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h index 801b31f71452..55c3a0e3a8ce 100644 --- a/include/asm-x86/pgtable.h +++ b/include/asm-x86/pgtable.h | |||
| @@ -57,7 +57,8 @@ | |||
| 57 | #define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | \ | 57 | #define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | \ |
| 58 | _PAGE_DIRTY) | 58 | _PAGE_DIRTY) |
| 59 | 59 | ||
| 60 | #define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) | 60 | #define _PAGE_CHG_MASK (PTE_MASK | _PAGE_PCD | _PAGE_PWT | \ |
| 61 | _PAGE_ACCESSED | _PAGE_DIRTY) | ||
| 61 | 62 | ||
| 62 | #define _PAGE_CACHE_MASK (_PAGE_PCD | _PAGE_PWT) | 63 | #define _PAGE_CACHE_MASK (_PAGE_PCD | _PAGE_PWT) |
| 63 | #define _PAGE_CACHE_WB (0) | 64 | #define _PAGE_CACHE_WB (0) |
| @@ -288,12 +289,21 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | |||
| 288 | * Chop off the NX bit (if present), and add the NX portion of | 289 | * Chop off the NX bit (if present), and add the NX portion of |
| 289 | * the newprot (if present): | 290 | * the newprot (if present): |
| 290 | */ | 291 | */ |
| 291 | val &= _PAGE_CHG_MASK & ~_PAGE_NX; | 292 | val &= _PAGE_CHG_MASK; |
| 292 | val |= pgprot_val(newprot) & __supported_pte_mask; | 293 | val |= pgprot_val(newprot) & (~_PAGE_CHG_MASK) & __supported_pte_mask; |
| 293 | 294 | ||
| 294 | return __pte(val); | 295 | return __pte(val); |
| 295 | } | 296 | } |
| 296 | 297 | ||
| 298 | /* mprotect needs to preserve PAT bits when updating vm_page_prot */ | ||
| 299 | #define pgprot_modify pgprot_modify | ||
| 300 | static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot) | ||
| 301 | { | ||
| 302 | pgprotval_t preservebits = pgprot_val(oldprot) & _PAGE_CHG_MASK; | ||
| 303 | pgprotval_t addbits = pgprot_val(newprot); | ||
| 304 | return __pgprot(preservebits | addbits); | ||
| 305 | } | ||
| 306 | |||
| 297 | #define pte_pgprot(x) __pgprot(pte_val(x) & (0xfff | _PAGE_NX)) | 307 | #define pte_pgprot(x) __pgprot(pte_val(x) & (0xfff | _PAGE_NX)) |
| 298 | 308 | ||
| 299 | #define canon_pgprot(p) __pgprot(pgprot_val(p) & __supported_pte_mask) | 309 | #define canon_pgprot(p) __pgprot(pgprot_val(p) & __supported_pte_mask) |
diff --git a/mm/mprotect.c b/mm/mprotect.c index 4de546899dc1..a5bf31c27375 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c | |||
| @@ -26,6 +26,13 @@ | |||
| 26 | #include <asm/cacheflush.h> | 26 | #include <asm/cacheflush.h> |
| 27 | #include <asm/tlbflush.h> | 27 | #include <asm/tlbflush.h> |
| 28 | 28 | ||
| 29 | #ifndef pgprot_modify | ||
| 30 | static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot) | ||
| 31 | { | ||
| 32 | return newprot; | ||
| 33 | } | ||
| 34 | #endif | ||
| 35 | |||
| 29 | static void change_pte_range(struct mm_struct *mm, pmd_t *pmd, | 36 | static void change_pte_range(struct mm_struct *mm, pmd_t *pmd, |
| 30 | unsigned long addr, unsigned long end, pgprot_t newprot, | 37 | unsigned long addr, unsigned long end, pgprot_t newprot, |
| 31 | int dirty_accountable) | 38 | int dirty_accountable) |
| @@ -192,7 +199,9 @@ success: | |||
| 192 | * held in write mode. | 199 | * held in write mode. |
| 193 | */ | 200 | */ |
| 194 | vma->vm_flags = newflags; | 201 | vma->vm_flags = newflags; |
| 195 | vma->vm_page_prot = vm_get_page_prot(newflags); | 202 | vma->vm_page_prot = pgprot_modify(vma->vm_page_prot, |
| 203 | vm_get_page_prot(newflags)); | ||
| 204 | |||
| 196 | if (vma_wants_writenotify(vma)) { | 205 | if (vma_wants_writenotify(vma)) { |
| 197 | vma->vm_page_prot = vm_get_page_prot(newflags & ~VM_SHARED); | 206 | vma->vm_page_prot = vm_get_page_prot(newflags & ~VM_SHARED); |
| 198 | dirty_accountable = 1; | 207 | dirty_accountable = 1; |
