diff options
-rw-r--r-- | include/asm-generic/pgtable.h | 16 | ||||
-rw-r--r-- | include/asm-i386/pgtable.h | 13 | ||||
-rw-r--r-- | mm/memory.c | 5 |
3 files changed, 32 insertions, 2 deletions
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index f40593565173..f86c1e549466 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h | |||
@@ -101,6 +101,22 @@ do { \ | |||
101 | }) | 101 | }) |
102 | #endif | 102 | #endif |
103 | 103 | ||
104 | #ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL | ||
105 | #define ptep_get_and_clear_full(__mm, __address, __ptep, __full) \ | ||
106 | ({ \ | ||
107 | pte_t __pte; \ | ||
108 | __pte = ptep_get_and_clear((__mm), (__address), (__ptep)); \ | ||
109 | __pte; \ | ||
110 | }) | ||
111 | #endif | ||
112 | |||
113 | #ifndef __HAVE_ARCH_PTE_CLEAR_FULL | ||
114 | #define pte_clear_full(__mm, __address, __ptep, __full) \ | ||
115 | do { \ | ||
116 | pte_clear((__mm), (__address), (__ptep)); \ | ||
117 | } while (0) | ||
118 | #endif | ||
119 | |||
104 | #ifndef __HAVE_ARCH_PTEP_CLEAR_FLUSH | 120 | #ifndef __HAVE_ARCH_PTEP_CLEAR_FLUSH |
105 | #define ptep_clear_flush(__vma, __address, __ptep) \ | 121 | #define ptep_clear_flush(__vma, __address, __ptep) \ |
106 | ({ \ | 122 | ({ \ |
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h index f51fd2c956bb..d74185aee15b 100644 --- a/include/asm-i386/pgtable.h +++ b/include/asm-i386/pgtable.h | |||
@@ -260,6 +260,18 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned | |||
260 | return test_and_clear_bit(_PAGE_BIT_ACCESSED, &ptep->pte_low); | 260 | return test_and_clear_bit(_PAGE_BIT_ACCESSED, &ptep->pte_low); |
261 | } | 261 | } |
262 | 262 | ||
263 | static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int full) | ||
264 | { | ||
265 | pte_t pte; | ||
266 | if (full) { | ||
267 | pte = *ptep; | ||
268 | *ptep = __pte(0); | ||
269 | } else { | ||
270 | pte = ptep_get_and_clear(mm, addr, ptep); | ||
271 | } | ||
272 | return pte; | ||
273 | } | ||
274 | |||
263 | static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) | 275 | static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) |
264 | { | 276 | { |
265 | clear_bit(_PAGE_BIT_RW, &ptep->pte_low); | 277 | clear_bit(_PAGE_BIT_RW, &ptep->pte_low); |
@@ -417,6 +429,7 @@ extern void noexec_setup(const char *str); | |||
417 | #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG | 429 | #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG |
418 | #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY | 430 | #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY |
419 | #define __HAVE_ARCH_PTEP_GET_AND_CLEAR | 431 | #define __HAVE_ARCH_PTEP_GET_AND_CLEAR |
432 | #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL | ||
420 | #define __HAVE_ARCH_PTEP_SET_WRPROTECT | 433 | #define __HAVE_ARCH_PTEP_SET_WRPROTECT |
421 | #define __HAVE_ARCH_PTE_SAME | 434 | #define __HAVE_ARCH_PTE_SAME |
422 | #include <asm-generic/pgtable.h> | 435 | #include <asm-generic/pgtable.h> |
diff --git a/mm/memory.c b/mm/memory.c index b25f5e58a14c..788a62810340 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -562,7 +562,8 @@ static void zap_pte_range(struct mmu_gather *tlb, pmd_t *pmd, | |||
562 | page->index > details->last_index)) | 562 | page->index > details->last_index)) |
563 | continue; | 563 | continue; |
564 | } | 564 | } |
565 | ptent = ptep_get_and_clear(tlb->mm, addr, pte); | 565 | ptent = ptep_get_and_clear_full(tlb->mm, addr, pte, |
566 | tlb->fullmm); | ||
566 | tlb_remove_tlb_entry(tlb, pte, addr); | 567 | tlb_remove_tlb_entry(tlb, pte, addr); |
567 | if (unlikely(!page)) | 568 | if (unlikely(!page)) |
568 | continue; | 569 | continue; |
@@ -590,7 +591,7 @@ static void zap_pte_range(struct mmu_gather *tlb, pmd_t *pmd, | |||
590 | continue; | 591 | continue; |
591 | if (!pte_file(ptent)) | 592 | if (!pte_file(ptent)) |
592 | free_swap_and_cache(pte_to_swp_entry(ptent)); | 593 | free_swap_and_cache(pte_to_swp_entry(ptent)); |
593 | pte_clear(tlb->mm, addr, pte); | 594 | pte_clear_full(tlb->mm, addr, pte, tlb->fullmm); |
594 | } while (pte++, addr += PAGE_SIZE, addr != end); | 595 | } while (pte++, addr += PAGE_SIZE, addr != end); |
595 | pte_unmap(pte - 1); | 596 | pte_unmap(pte - 1); |
596 | } | 597 | } |