at v2.6.21 7.8 kB view raw
1#ifndef _ASM_GENERIC_PGTABLE_H 2#define _ASM_GENERIC_PGTABLE_H 3 4#ifndef __ASSEMBLY__ 5 6#ifndef __HAVE_ARCH_PTEP_ESTABLISH 7/* 8 * Establish a new mapping: 9 * - flush the old one 10 * - update the page tables 11 * - inform the TLB about the new one 12 * 13 * We hold the mm semaphore for reading, and the pte lock. 14 * 15 * Note: the old pte is known to not be writable, so we don't need to 16 * worry about dirty bits etc getting lost. 17 */ 18#define ptep_establish(__vma, __address, __ptep, __entry) \ 19do { \ 20 set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \ 21 flush_tlb_page(__vma, __address); \ 22} while (0) 23#endif 24 25#ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS 26/* 27 * Largely same as above, but only sets the access flags (dirty, 28 * accessed, and writable). Furthermore, we know it always gets set 29 * to a "more permissive" setting, which allows most architectures 30 * to optimize this. 31 */ 32#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \ 33do { \ 34 set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \ 35 flush_tlb_page(__vma, __address); \ 36} while (0) 37#endif 38 39#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG 40#define ptep_test_and_clear_young(__vma, __address, __ptep) \ 41({ \ 42 pte_t __pte = *(__ptep); \ 43 int r = 1; \ 44 if (!pte_young(__pte)) \ 45 r = 0; \ 46 else \ 47 set_pte_at((__vma)->vm_mm, (__address), \ 48 (__ptep), pte_mkold(__pte)); \ 49 r; \ 50}) 51#endif 52 53#ifndef __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH 54#define ptep_clear_flush_young(__vma, __address, __ptep) \ 55({ \ 56 int __young; \ 57 __young = ptep_test_and_clear_young(__vma, __address, __ptep); \ 58 if (__young) \ 59 flush_tlb_page(__vma, __address); \ 60 __young; \ 61}) 62#endif 63 64#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY 65#define ptep_test_and_clear_dirty(__vma, __address, __ptep) \ 66({ \ 67 pte_t __pte = *__ptep; \ 68 int r = 1; \ 69 if (!pte_dirty(__pte)) \ 70 r = 0; \ 71 else \ 72 set_pte_at((__vma)->vm_mm, (__address), (__ptep), \ 73 pte_mkclean(__pte)); \ 74 r; \ 75}) 76#endif 77 78#ifndef __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH 79#define ptep_clear_flush_dirty(__vma, __address, __ptep) \ 80({ \ 81 int __dirty; \ 82 __dirty = ptep_test_and_clear_dirty(__vma, __address, __ptep); \ 83 if (__dirty) \ 84 flush_tlb_page(__vma, __address); \ 85 __dirty; \ 86}) 87#endif 88 89#ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR 90#define ptep_get_and_clear(__mm, __address, __ptep) \ 91({ \ 92 pte_t __pte = *(__ptep); \ 93 pte_clear((__mm), (__address), (__ptep)); \ 94 __pte; \ 95}) 96#endif 97 98#ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL 99#define ptep_get_and_clear_full(__mm, __address, __ptep, __full) \ 100({ \ 101 pte_t __pte; \ 102 __pte = ptep_get_and_clear((__mm), (__address), (__ptep)); \ 103 __pte; \ 104}) 105#endif 106 107/* 108 * Some architectures may be able to avoid expensive synchronization 109 * primitives when modifications are made to PTE's which are already 110 * not present, or in the process of an address space destruction. 111 */ 112#ifndef __HAVE_ARCH_PTE_CLEAR_NOT_PRESENT_FULL 113#define pte_clear_not_present_full(__mm, __address, __ptep, __full) \ 114do { \ 115 pte_clear((__mm), (__address), (__ptep)); \ 116} while (0) 117#endif 118 119#ifndef __HAVE_ARCH_PTEP_CLEAR_FLUSH 120#define ptep_clear_flush(__vma, __address, __ptep) \ 121({ \ 122 pte_t __pte; \ 123 __pte = ptep_get_and_clear((__vma)->vm_mm, __address, __ptep); \ 124 flush_tlb_page(__vma, __address); \ 125 __pte; \ 126}) 127#endif 128 129#ifndef __HAVE_ARCH_PTEP_SET_WRPROTECT 130struct mm_struct; 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#ifndef __HAVE_ARCH_MOVE_PTE 162#define move_pte(pte, prot, old_addr, new_addr) (pte) 163#endif 164 165/* 166 * A facility to provide lazy MMU batching. This allows PTE updates and 167 * page invalidations to be delayed until a call to leave lazy MMU mode 168 * is issued. Some architectures may benefit from doing this, and it is 169 * beneficial for both shadow and direct mode hypervisors, which may batch 170 * the PTE updates which happen during this window. Note that using this 171 * interface requires that read hazards be removed from the code. A read 172 * hazard could result in the direct mode hypervisor case, since the actual 173 * write to the page tables may not yet have taken place, so reads though 174 * a raw PTE pointer after it has been modified are not guaranteed to be 175 * up to date. This mode can only be entered and left under the protection of 176 * the page table locks for all page tables which may be modified. In the UP 177 * case, this is required so that preemption is disabled, and in the SMP case, 178 * it must synchronize the delayed page table writes properly on other CPUs. 179 */ 180#ifndef __HAVE_ARCH_ENTER_LAZY_MMU_MODE 181#define arch_enter_lazy_mmu_mode() do {} while (0) 182#define arch_leave_lazy_mmu_mode() do {} while (0) 183#define arch_flush_lazy_mmu_mode() do {} while (0) 184#endif 185 186/* 187 * A facility to provide batching of the reload of page tables with the 188 * actual context switch code for paravirtualized guests. By convention, 189 * only one of the lazy modes (CPU, MMU) should be active at any given 190 * time, entry should never be nested, and entry and exits should always 191 * be paired. This is for sanity of maintaining and reasoning about the 192 * kernel code. 193 */ 194#ifndef __HAVE_ARCH_ENTER_LAZY_CPU_MODE 195#define arch_enter_lazy_cpu_mode() do {} while (0) 196#define arch_leave_lazy_cpu_mode() do {} while (0) 197#define arch_flush_lazy_cpu_mode() do {} while (0) 198#endif 199 200/* 201 * When walking page tables, get the address of the next boundary, 202 * or the end address of the range if that comes earlier. Although no 203 * vma end wraps to 0, rounded up __boundary may wrap to 0 throughout. 204 */ 205 206#define pgd_addr_end(addr, end) \ 207({ unsigned long __boundary = ((addr) + PGDIR_SIZE) & PGDIR_MASK; \ 208 (__boundary - 1 < (end) - 1)? __boundary: (end); \ 209}) 210 211#ifndef pud_addr_end 212#define pud_addr_end(addr, end) \ 213({ unsigned long __boundary = ((addr) + PUD_SIZE) & PUD_MASK; \ 214 (__boundary - 1 < (end) - 1)? __boundary: (end); \ 215}) 216#endif 217 218#ifndef pmd_addr_end 219#define pmd_addr_end(addr, end) \ 220({ unsigned long __boundary = ((addr) + PMD_SIZE) & PMD_MASK; \ 221 (__boundary - 1 < (end) - 1)? __boundary: (end); \ 222}) 223#endif 224 225/* 226 * When walking page tables, we usually want to skip any p?d_none entries; 227 * and any p?d_bad entries - reporting the error before resetting to none. 228 * Do the tests inline, but report and clear the bad entry in mm/memory.c. 229 */ 230void pgd_clear_bad(pgd_t *); 231void pud_clear_bad(pud_t *); 232void pmd_clear_bad(pmd_t *); 233 234static inline int pgd_none_or_clear_bad(pgd_t *pgd) 235{ 236 if (pgd_none(*pgd)) 237 return 1; 238 if (unlikely(pgd_bad(*pgd))) { 239 pgd_clear_bad(pgd); 240 return 1; 241 } 242 return 0; 243} 244 245static inline int pud_none_or_clear_bad(pud_t *pud) 246{ 247 if (pud_none(*pud)) 248 return 1; 249 if (unlikely(pud_bad(*pud))) { 250 pud_clear_bad(pud); 251 return 1; 252 } 253 return 0; 254} 255 256static inline int pmd_none_or_clear_bad(pmd_t *pmd) 257{ 258 if (pmd_none(*pmd)) 259 return 1; 260 if (unlikely(pmd_bad(*pmd))) { 261 pmd_clear_bad(pmd); 262 return 1; 263 } 264 return 0; 265} 266#endif /* !__ASSEMBLY__ */ 267 268#endif /* _ASM_GENERIC_PGTABLE_H */