at v2.6.14-rc2 6.0 kB view raw
1#ifndef _ASM_GENERIC_PGTABLE_H 2#define _ASM_GENERIC_PGTABLE_H 3 4#ifndef __HAVE_ARCH_PTEP_ESTABLISH 5/* 6 * Establish a new mapping: 7 * - flush the old one 8 * - update the page tables 9 * - inform the TLB about the new one 10 * 11 * We hold the mm semaphore for reading and vma->vm_mm->page_table_lock. 12 * 13 * Note: the old pte is known to not be writable, so we don't need to 14 * worry about dirty bits etc getting lost. 15 */ 16#ifndef __HAVE_ARCH_SET_PTE_ATOMIC 17#define ptep_establish(__vma, __address, __ptep, __entry) \ 18do { \ 19 set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \ 20 flush_tlb_page(__vma, __address); \ 21} while (0) 22#else /* __HAVE_ARCH_SET_PTE_ATOMIC */ 23#define ptep_establish(__vma, __address, __ptep, __entry) \ 24do { \ 25 set_pte_atomic(__ptep, __entry); \ 26 flush_tlb_page(__vma, __address); \ 27} while (0) 28#endif /* __HAVE_ARCH_SET_PTE_ATOMIC */ 29#endif 30 31#ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS 32/* 33 * Largely same as above, but only sets the access flags (dirty, 34 * accessed, and writable). Furthermore, we know it always gets set 35 * to a "more permissive" setting, which allows most architectures 36 * to optimize this. 37 */ 38#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \ 39do { \ 40 set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \ 41 flush_tlb_page(__vma, __address); \ 42} while (0) 43#endif 44 45#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG 46#define ptep_test_and_clear_young(__vma, __address, __ptep) \ 47({ \ 48 pte_t __pte = *(__ptep); \ 49 int r = 1; \ 50 if (!pte_young(__pte)) \ 51 r = 0; \ 52 else \ 53 set_pte_at((__vma)->vm_mm, (__address), \ 54 (__ptep), pte_mkold(__pte)); \ 55 r; \ 56}) 57#endif 58 59#ifndef __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH 60#define ptep_clear_flush_young(__vma, __address, __ptep) \ 61({ \ 62 int __young; \ 63 __young = ptep_test_and_clear_young(__vma, __address, __ptep); \ 64 if (__young) \ 65 flush_tlb_page(__vma, __address); \ 66 __young; \ 67}) 68#endif 69 70#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY 71#define ptep_test_and_clear_dirty(__vma, __address, __ptep) \ 72({ \ 73 pte_t __pte = *__ptep; \ 74 int r = 1; \ 75 if (!pte_dirty(__pte)) \ 76 r = 0; \ 77 else \ 78 set_pte_at((__vma)->vm_mm, (__address), (__ptep), \ 79 pte_mkclean(__pte)); \ 80 r; \ 81}) 82#endif 83 84#ifndef __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH 85#define ptep_clear_flush_dirty(__vma, __address, __ptep) \ 86({ \ 87 int __dirty; \ 88 __dirty = ptep_test_and_clear_dirty(__vma, __address, __ptep); \ 89 if (__dirty) \ 90 flush_tlb_page(__vma, __address); \ 91 __dirty; \ 92}) 93#endif 94 95#ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR 96#define ptep_get_and_clear(__mm, __address, __ptep) \ 97({ \ 98 pte_t __pte = *(__ptep); \ 99 pte_clear((__mm), (__address), (__ptep)); \ 100 __pte; \ 101}) 102#endif 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) \ 115do { \ 116 pte_clear((__mm), (__address), (__ptep)); \ 117} while (0) 118#endif 119 120#ifndef __HAVE_ARCH_PTEP_CLEAR_FLUSH 121#define ptep_clear_flush(__vma, __address, __ptep) \ 122({ \ 123 pte_t __pte; \ 124 __pte = ptep_get_and_clear((__vma)->vm_mm, __address, __ptep); \ 125 flush_tlb_page(__vma, __address); \ 126 __pte; \ 127}) 128#endif 129 130#ifndef __HAVE_ARCH_PTEP_SET_WRPROTECT 131static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long address, pte_t *ptep) 132{ 133 pte_t old_pte = *ptep; 134 set_pte_at(mm, address, ptep, pte_wrprotect(old_pte)); 135} 136#endif 137 138#ifndef __HAVE_ARCH_PTE_SAME 139#define pte_same(A,B) (pte_val(A) == pte_val(B)) 140#endif 141 142#ifndef __HAVE_ARCH_PAGE_TEST_AND_CLEAR_DIRTY 143#define page_test_and_clear_dirty(page) (0) 144#define pte_maybe_dirty(pte) pte_dirty(pte) 145#else 146#define pte_maybe_dirty(pte) (1) 147#endif 148 149#ifndef __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG 150#define page_test_and_clear_young(page) (0) 151#endif 152 153#ifndef __HAVE_ARCH_PGD_OFFSET_GATE 154#define pgd_offset_gate(mm, addr) pgd_offset(mm, addr) 155#endif 156 157#ifndef __HAVE_ARCH_LAZY_MMU_PROT_UPDATE 158#define lazy_mmu_prot_update(pte) do { } while (0) 159#endif 160 161/* 162 * When walking page tables, get the address of the next boundary, 163 * or the end address of the range if that comes earlier. Although no 164 * vma end wraps to 0, rounded up __boundary may wrap to 0 throughout. 165 */ 166 167#define pgd_addr_end(addr, end) \ 168({ unsigned long __boundary = ((addr) + PGDIR_SIZE) & PGDIR_MASK; \ 169 (__boundary - 1 < (end) - 1)? __boundary: (end); \ 170}) 171 172#ifndef pud_addr_end 173#define pud_addr_end(addr, end) \ 174({ unsigned long __boundary = ((addr) + PUD_SIZE) & PUD_MASK; \ 175 (__boundary - 1 < (end) - 1)? __boundary: (end); \ 176}) 177#endif 178 179#ifndef pmd_addr_end 180#define pmd_addr_end(addr, end) \ 181({ unsigned long __boundary = ((addr) + PMD_SIZE) & PMD_MASK; \ 182 (__boundary - 1 < (end) - 1)? __boundary: (end); \ 183}) 184#endif 185 186#ifndef __ASSEMBLY__ 187/* 188 * When walking page tables, we usually want to skip any p?d_none entries; 189 * and any p?d_bad entries - reporting the error before resetting to none. 190 * Do the tests inline, but report and clear the bad entry in mm/memory.c. 191 */ 192void pgd_clear_bad(pgd_t *); 193void pud_clear_bad(pud_t *); 194void pmd_clear_bad(pmd_t *); 195 196static inline int pgd_none_or_clear_bad(pgd_t *pgd) 197{ 198 if (pgd_none(*pgd)) 199 return 1; 200 if (unlikely(pgd_bad(*pgd))) { 201 pgd_clear_bad(pgd); 202 return 1; 203 } 204 return 0; 205} 206 207static inline int pud_none_or_clear_bad(pud_t *pud) 208{ 209 if (pud_none(*pud)) 210 return 1; 211 if (unlikely(pud_bad(*pud))) { 212 pud_clear_bad(pud); 213 return 1; 214 } 215 return 0; 216} 217 218static inline int pmd_none_or_clear_bad(pmd_t *pmd) 219{ 220 if (pmd_none(*pmd)) 221 return 1; 222 if (unlikely(pmd_bad(*pmd))) { 223 pmd_clear_bad(pmd); 224 return 1; 225 } 226 return 0; 227} 228#endif /* !__ASSEMBLY__ */ 229 230#endif /* _ASM_GENERIC_PGTABLE_H */