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 the pte 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) \ 18 do { \ 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) \ 24 do { \ 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) \ 39 do { \ 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) \ 115 do { \ 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 131 struct mm_struct; 132 static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long address, pte_t *ptep) 133 { 134 pte_t old_pte = *ptep; 135 set_pte_at(mm, address, ptep, pte_wrprotect(old_pte)); 136 } 137 #endif 138 139 #ifndef __HAVE_ARCH_PTE_SAME 140 #define pte_same(A,B) (pte_val(A) == pte_val(B)) 141 #endif 142 143 #ifndef __HAVE_ARCH_PAGE_TEST_AND_CLEAR_DIRTY 144 #define page_test_and_clear_dirty(page) (0) 145 #define pte_maybe_dirty(pte) pte_dirty(pte) 146 #else 147 #define pte_maybe_dirty(pte) (1) 148 #endif 149 150 #ifndef __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG 151 #define page_test_and_clear_young(page) (0) 152 #endif 153 154 #ifndef __HAVE_ARCH_PGD_OFFSET_GATE 155 #define pgd_offset_gate(mm, addr) pgd_offset(mm, addr) 156 #endif 157 158 #ifndef __HAVE_ARCH_LAZY_MMU_PROT_UPDATE 159 #define lazy_mmu_prot_update(pte) do { } while (0) 160 #endif 161 162 #ifndef __HAVE_ARCH_MOVE_PTE 163 #define move_pte(pte, prot, old_addr, new_addr) (pte) 164 #endif 165 166 /* 167 * When walking page tables, get the address of the next boundary, 168 * or the end address of the range if that comes earlier. Although no 169 * vma end wraps to 0, rounded up __boundary may wrap to 0 throughout. 170 */ 171 172 #define pgd_addr_end(addr, end) \ 173 ({ unsigned long __boundary = ((addr) + PGDIR_SIZE) & PGDIR_MASK; \ 174 (__boundary - 1 < (end) - 1)? __boundary: (end); \ 175 }) 176 177 #ifndef pud_addr_end 178 #define pud_addr_end(addr, end) \ 179 ({ unsigned long __boundary = ((addr) + PUD_SIZE) & PUD_MASK; \ 180 (__boundary - 1 < (end) - 1)? __boundary: (end); \ 181 }) 182 #endif 183 184 #ifndef pmd_addr_end 185 #define pmd_addr_end(addr, end) \ 186 ({ unsigned long __boundary = ((addr) + PMD_SIZE) & PMD_MASK; \ 187 (__boundary - 1 < (end) - 1)? __boundary: (end); \ 188 }) 189 #endif 190 191 #ifndef __ASSEMBLY__ 192 /* 193 * When walking page tables, we usually want to skip any p?d_none entries; 194 * and any p?d_bad entries - reporting the error before resetting to none. 195 * Do the tests inline, but report and clear the bad entry in mm/memory.c. 196 */ 197 void pgd_clear_bad(pgd_t *); 198 void pud_clear_bad(pud_t *); 199 void pmd_clear_bad(pmd_t *); 200 201 static inline int pgd_none_or_clear_bad(pgd_t *pgd) 202 { 203 if (pgd_none(*pgd)) 204 return 1; 205 if (unlikely(pgd_bad(*pgd))) { 206 pgd_clear_bad(pgd); 207 return 1; 208 } 209 return 0; 210 } 211 212 static inline int pud_none_or_clear_bad(pud_t *pud) 213 { 214 if (pud_none(*pud)) 215 return 1; 216 if (unlikely(pud_bad(*pud))) { 217 pud_clear_bad(pud); 218 return 1; 219 } 220 return 0; 221 } 222 223 static inline int pmd_none_or_clear_bad(pmd_t *pmd) 224 { 225 if (pmd_none(*pmd)) 226 return 1; 227 if (unlikely(pmd_bad(*pmd))) { 228 pmd_clear_bad(pmd); 229 return 1; 230 } 231 return 0; 232 } 233 #endif /* !__ASSEMBLY__ */ 234 235 #endif /* _ASM_GENERIC_PGTABLE_H */ 236