diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /arch/arm/include/asm/pgtable.h | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'arch/arm/include/asm/pgtable.h')
-rw-r--r-- | arch/arm/include/asm/pgtable.h | 309 |
1 files changed, 163 insertions, 146 deletions
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index e90b167ea848..5750704e0271 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h | |||
@@ -10,6 +10,7 @@ | |||
10 | #ifndef _ASMARM_PGTABLE_H | 10 | #ifndef _ASMARM_PGTABLE_H |
11 | #define _ASMARM_PGTABLE_H | 11 | #define _ASMARM_PGTABLE_H |
12 | 12 | ||
13 | #include <linux/const.h> | ||
13 | #include <asm-generic/4level-fixup.h> | 14 | #include <asm-generic/4level-fixup.h> |
14 | #include <asm/proc-fns.h> | 15 | #include <asm/proc-fns.h> |
15 | 16 | ||
@@ -54,7 +55,7 @@ | |||
54 | * Therefore, we tweak the implementation slightly - we tell Linux that we | 55 | * Therefore, we tweak the implementation slightly - we tell Linux that we |
55 | * have 2048 entries in the first level, each of which is 8 bytes (iow, two | 56 | * have 2048 entries in the first level, each of which is 8 bytes (iow, two |
56 | * hardware pointers to the second level.) The second level contains two | 57 | * hardware pointers to the second level.) The second level contains two |
57 | * hardware PTE tables arranged contiguously, followed by Linux versions | 58 | * hardware PTE tables arranged contiguously, preceded by Linux versions |
58 | * which contain the state information Linux needs. We, therefore, end up | 59 | * which contain the state information Linux needs. We, therefore, end up |
59 | * with 512 entries in the "PTE" level. | 60 | * with 512 entries in the "PTE" level. |
60 | * | 61 | * |
@@ -62,15 +63,15 @@ | |||
62 | * | 63 | * |
63 | * pgd pte | 64 | * pgd pte |
64 | * | | | 65 | * | | |
65 | * +--------+ +0 | 66 | * +--------+ |
66 | * | |-----> +------------+ +0 | 67 | * | | +------------+ +0 |
68 | * +- - - - + | Linux pt 0 | | ||
69 | * | | +------------+ +1024 | ||
70 | * +--------+ +0 | Linux pt 1 | | ||
71 | * | |-----> +------------+ +2048 | ||
67 | * +- - - - + +4 | h/w pt 0 | | 72 | * +- - - - + +4 | h/w pt 0 | |
68 | * | |-----> +------------+ +1024 | 73 | * | |-----> +------------+ +3072 |
69 | * +--------+ +8 | h/w pt 1 | | 74 | * +--------+ +8 | h/w pt 1 | |
70 | * | | +------------+ +2048 | ||
71 | * +- - - - + | Linux pt 0 | | ||
72 | * | | +------------+ +3072 | ||
73 | * +--------+ | Linux pt 1 | | ||
74 | * | | +------------+ +4096 | 75 | * | | +------------+ +4096 |
75 | * | 76 | * |
76 | * See L_PTE_xxx below for definitions of bits in the "Linux pt", and | 77 | * See L_PTE_xxx below for definitions of bits in the "Linux pt", and |
@@ -102,6 +103,10 @@ | |||
102 | #define PTRS_PER_PMD 1 | 103 | #define PTRS_PER_PMD 1 |
103 | #define PTRS_PER_PGD 2048 | 104 | #define PTRS_PER_PGD 2048 |
104 | 105 | ||
106 | #define PTE_HWTABLE_PTRS (PTRS_PER_PTE) | ||
107 | #define PTE_HWTABLE_OFF (PTE_HWTABLE_PTRS * sizeof(pte_t)) | ||
108 | #define PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(u32)) | ||
109 | |||
105 | /* | 110 | /* |
106 | * PMD_SHIFT determines the size of the area a second-level page table can map | 111 | * PMD_SHIFT determines the size of the area a second-level page table can map |
107 | * PGDIR_SHIFT determines what a third-level page table entry can map | 112 | * PGDIR_SHIFT determines what a third-level page table entry can map |
@@ -112,13 +117,13 @@ | |||
112 | #define LIBRARY_TEXT_START 0x0c000000 | 117 | #define LIBRARY_TEXT_START 0x0c000000 |
113 | 118 | ||
114 | #ifndef __ASSEMBLY__ | 119 | #ifndef __ASSEMBLY__ |
115 | extern void __pte_error(const char *file, int line, unsigned long val); | 120 | extern void __pte_error(const char *file, int line, pte_t); |
116 | extern void __pmd_error(const char *file, int line, unsigned long val); | 121 | extern void __pmd_error(const char *file, int line, pmd_t); |
117 | extern void __pgd_error(const char *file, int line, unsigned long val); | 122 | extern void __pgd_error(const char *file, int line, pgd_t); |
118 | 123 | ||
119 | #define pte_ERROR(pte) __pte_error(__FILE__, __LINE__, pte_val(pte)) | 124 | #define pte_ERROR(pte) __pte_error(__FILE__, __LINE__, pte) |
120 | #define pmd_ERROR(pmd) __pmd_error(__FILE__, __LINE__, pmd_val(pmd)) | 125 | #define pmd_ERROR(pmd) __pmd_error(__FILE__, __LINE__, pmd) |
121 | #define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd_val(pgd)) | 126 | #define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd) |
122 | #endif /* !__ASSEMBLY__ */ | 127 | #endif /* !__ASSEMBLY__ */ |
123 | 128 | ||
124 | #define PMD_SIZE (1UL << PMD_SHIFT) | 129 | #define PMD_SIZE (1UL << PMD_SHIFT) |
@@ -133,8 +138,7 @@ extern void __pgd_error(const char *file, int line, unsigned long val); | |||
133 | */ | 138 | */ |
134 | #define FIRST_USER_ADDRESS PAGE_SIZE | 139 | #define FIRST_USER_ADDRESS PAGE_SIZE |
135 | 140 | ||
136 | #define FIRST_USER_PGD_NR 1 | 141 | #define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) |
137 | #define USER_PTRS_PER_PGD ((TASK_SIZE/PGDIR_SIZE) - FIRST_USER_PGD_NR) | ||
138 | 142 | ||
139 | /* | 143 | /* |
140 | * section address mask and size definitions. | 144 | * section address mask and size definitions. |
@@ -161,30 +165,30 @@ extern void __pgd_error(const char *file, int line, unsigned long val); | |||
161 | * The PTE table pointer refers to the hardware entries; the "Linux" | 165 | * The PTE table pointer refers to the hardware entries; the "Linux" |
162 | * entries are stored 1024 bytes below. | 166 | * entries are stored 1024 bytes below. |
163 | */ | 167 | */ |
164 | #define L_PTE_PRESENT (1 << 0) | 168 | #define L_PTE_PRESENT (_AT(pteval_t, 1) << 0) |
165 | #define L_PTE_YOUNG (1 << 1) | 169 | #define L_PTE_YOUNG (_AT(pteval_t, 1) << 1) |
166 | #define L_PTE_FILE (1 << 2) /* only when !PRESENT */ | 170 | #define L_PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !PRESENT */ |
167 | #define L_PTE_DIRTY (1 << 6) | 171 | #define L_PTE_DIRTY (_AT(pteval_t, 1) << 6) |
168 | #define L_PTE_WRITE (1 << 7) | 172 | #define L_PTE_RDONLY (_AT(pteval_t, 1) << 7) |
169 | #define L_PTE_USER (1 << 8) | 173 | #define L_PTE_USER (_AT(pteval_t, 1) << 8) |
170 | #define L_PTE_EXEC (1 << 9) | 174 | #define L_PTE_XN (_AT(pteval_t, 1) << 9) |
171 | #define L_PTE_SHARED (1 << 10) /* shared(v6), coherent(xsc3) */ | 175 | #define L_PTE_SHARED (_AT(pteval_t, 1) << 10) /* shared(v6), coherent(xsc3) */ |
172 | 176 | ||
173 | /* | 177 | /* |
174 | * These are the memory types, defined to be compatible with | 178 | * These are the memory types, defined to be compatible with |
175 | * pre-ARMv6 CPUs cacheable and bufferable bits: XXCB | 179 | * pre-ARMv6 CPUs cacheable and bufferable bits: XXCB |
176 | */ | 180 | */ |
177 | #define L_PTE_MT_UNCACHED (0x00 << 2) /* 0000 */ | 181 | #define L_PTE_MT_UNCACHED (_AT(pteval_t, 0x00) << 2) /* 0000 */ |
178 | #define L_PTE_MT_BUFFERABLE (0x01 << 2) /* 0001 */ | 182 | #define L_PTE_MT_BUFFERABLE (_AT(pteval_t, 0x01) << 2) /* 0001 */ |
179 | #define L_PTE_MT_WRITETHROUGH (0x02 << 2) /* 0010 */ | 183 | #define L_PTE_MT_WRITETHROUGH (_AT(pteval_t, 0x02) << 2) /* 0010 */ |
180 | #define L_PTE_MT_WRITEBACK (0x03 << 2) /* 0011 */ | 184 | #define L_PTE_MT_WRITEBACK (_AT(pteval_t, 0x03) << 2) /* 0011 */ |
181 | #define L_PTE_MT_MINICACHE (0x06 << 2) /* 0110 (sa1100, xscale) */ | 185 | #define L_PTE_MT_MINICACHE (_AT(pteval_t, 0x06) << 2) /* 0110 (sa1100, xscale) */ |
182 | #define L_PTE_MT_WRITEALLOC (0x07 << 2) /* 0111 */ | 186 | #define L_PTE_MT_WRITEALLOC (_AT(pteval_t, 0x07) << 2) /* 0111 */ |
183 | #define L_PTE_MT_DEV_SHARED (0x04 << 2) /* 0100 */ | 187 | #define L_PTE_MT_DEV_SHARED (_AT(pteval_t, 0x04) << 2) /* 0100 */ |
184 | #define L_PTE_MT_DEV_NONSHARED (0x0c << 2) /* 1100 */ | 188 | #define L_PTE_MT_DEV_NONSHARED (_AT(pteval_t, 0x0c) << 2) /* 1100 */ |
185 | #define L_PTE_MT_DEV_WC (0x09 << 2) /* 1001 */ | 189 | #define L_PTE_MT_DEV_WC (_AT(pteval_t, 0x09) << 2) /* 1001 */ |
186 | #define L_PTE_MT_DEV_CACHED (0x0b << 2) /* 1011 */ | 190 | #define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 0x0b) << 2) /* 1011 */ |
187 | #define L_PTE_MT_MASK (0x0f << 2) | 191 | #define L_PTE_MT_MASK (_AT(pteval_t, 0x0f) << 2) |
188 | 192 | ||
189 | #ifndef __ASSEMBLY__ | 193 | #ifndef __ASSEMBLY__ |
190 | 194 | ||
@@ -201,23 +205,44 @@ extern pgprot_t pgprot_kernel; | |||
201 | 205 | ||
202 | #define _MOD_PROT(p, b) __pgprot(pgprot_val(p) | (b)) | 206 | #define _MOD_PROT(p, b) __pgprot(pgprot_val(p) | (b)) |
203 | 207 | ||
204 | #define PAGE_NONE pgprot_user | 208 | #define PAGE_NONE _MOD_PROT(pgprot_user, L_PTE_XN | L_PTE_RDONLY) |
205 | #define PAGE_SHARED _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_WRITE) | 209 | #define PAGE_SHARED _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_XN) |
206 | #define PAGE_SHARED_EXEC _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_WRITE | L_PTE_EXEC) | 210 | #define PAGE_SHARED_EXEC _MOD_PROT(pgprot_user, L_PTE_USER) |
207 | #define PAGE_COPY _MOD_PROT(pgprot_user, L_PTE_USER) | 211 | #define PAGE_COPY _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY | L_PTE_XN) |
208 | #define PAGE_COPY_EXEC _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_EXEC) | 212 | #define PAGE_COPY_EXEC _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY) |
209 | #define PAGE_READONLY _MOD_PROT(pgprot_user, L_PTE_USER) | 213 | #define PAGE_READONLY _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY | L_PTE_XN) |
210 | #define PAGE_READONLY_EXEC _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_EXEC) | 214 | #define PAGE_READONLY_EXEC _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY) |
211 | #define PAGE_KERNEL pgprot_kernel | 215 | #define PAGE_KERNEL _MOD_PROT(pgprot_kernel, L_PTE_XN) |
212 | #define PAGE_KERNEL_EXEC _MOD_PROT(pgprot_kernel, L_PTE_EXEC) | 216 | #define PAGE_KERNEL_EXEC pgprot_kernel |
213 | 217 | ||
214 | #define __PAGE_NONE __pgprot(_L_PTE_DEFAULT) | 218 | #define __PAGE_NONE __pgprot(_L_PTE_DEFAULT | L_PTE_RDONLY | L_PTE_XN) |
215 | #define __PAGE_SHARED __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_WRITE) | 219 | #define __PAGE_SHARED __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_XN) |
216 | #define __PAGE_SHARED_EXEC __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_WRITE | L_PTE_EXEC) | 220 | #define __PAGE_SHARED_EXEC __pgprot(_L_PTE_DEFAULT | L_PTE_USER) |
217 | #define __PAGE_COPY __pgprot(_L_PTE_DEFAULT | L_PTE_USER) | 221 | #define __PAGE_COPY __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_RDONLY | L_PTE_XN) |
218 | #define __PAGE_COPY_EXEC __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_EXEC) | 222 | #define __PAGE_COPY_EXEC __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_RDONLY) |
219 | #define __PAGE_READONLY __pgprot(_L_PTE_DEFAULT | L_PTE_USER) | 223 | #define __PAGE_READONLY __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_RDONLY | L_PTE_XN) |
220 | #define __PAGE_READONLY_EXEC __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_EXEC) | 224 | #define __PAGE_READONLY_EXEC __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_RDONLY) |
225 | |||
226 | #define __pgprot_modify(prot,mask,bits) \ | ||
227 | __pgprot((pgprot_val(prot) & ~(mask)) | (bits)) | ||
228 | |||
229 | #define pgprot_noncached(prot) \ | ||
230 | __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED) | ||
231 | |||
232 | #define pgprot_writecombine(prot) \ | ||
233 | __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE) | ||
234 | |||
235 | #ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE | ||
236 | #define pgprot_dmacoherent(prot) \ | ||
237 | __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE | L_PTE_XN) | ||
238 | #define __HAVE_PHYS_MEM_ACCESS_PROT | ||
239 | struct file; | ||
240 | extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | ||
241 | unsigned long size, pgprot_t vma_prot); | ||
242 | #else | ||
243 | #define pgprot_dmacoherent(prot) \ | ||
244 | __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED | L_PTE_XN) | ||
245 | #endif | ||
221 | 246 | ||
222 | #endif /* __ASSEMBLY__ */ | 247 | #endif /* __ASSEMBLY__ */ |
223 | 248 | ||
@@ -255,76 +280,32 @@ extern pgprot_t pgprot_kernel; | |||
255 | extern struct page *empty_zero_page; | 280 | extern struct page *empty_zero_page; |
256 | #define ZERO_PAGE(vaddr) (empty_zero_page) | 281 | #define ZERO_PAGE(vaddr) (empty_zero_page) |
257 | 282 | ||
258 | #define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT) | ||
259 | #define pfn_pte(pfn,prot) (__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))) | ||
260 | |||
261 | #define pte_none(pte) (!pte_val(pte)) | ||
262 | #define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0) | ||
263 | #define pte_page(pte) (pfn_to_page(pte_pfn(pte))) | ||
264 | #define pte_offset_kernel(dir,addr) (pmd_page_vaddr(*(dir)) + __pte_index(addr)) | ||
265 | 283 | ||
266 | #define pte_offset_map(dir,addr) (__pte_map(dir, KM_PTE0) + __pte_index(addr)) | 284 | extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; |
267 | #define pte_offset_map_nested(dir,addr) (__pte_map(dir, KM_PTE1) + __pte_index(addr)) | ||
268 | #define pte_unmap(pte) __pte_unmap(pte, KM_PTE0) | ||
269 | #define pte_unmap_nested(pte) __pte_unmap(pte, KM_PTE1) | ||
270 | 285 | ||
271 | #ifndef CONFIG_HIGHPTE | 286 | /* to find an entry in a page-table-directory */ |
272 | #define __pte_map(dir,km) pmd_page_vaddr(*(dir)) | 287 | #define pgd_index(addr) ((addr) >> PGDIR_SHIFT) |
273 | #define __pte_unmap(pte,km) do { } while (0) | ||
274 | #else | ||
275 | #define __pte_map(dir,km) ((pte_t *)kmap_atomic(pmd_page(*(dir)), km) + PTRS_PER_PTE) | ||
276 | #define __pte_unmap(pte,km) kunmap_atomic((pte - PTRS_PER_PTE), km) | ||
277 | #endif | ||
278 | 288 | ||
279 | #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext) | 289 | #define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr)) |
280 | 290 | ||
281 | #define set_pte_at(mm,addr,ptep,pteval) do { \ | 291 | /* to find an entry in a kernel page-table-directory */ |
282 | set_pte_ext(ptep, pteval, (addr) >= TASK_SIZE ? 0 : PTE_EXT_NG); \ | 292 | #define pgd_offset_k(addr) pgd_offset(&init_mm, addr) |
283 | } while (0) | ||
284 | 293 | ||
285 | /* | 294 | /* |
286 | * The following only work if pte_present() is true. | 295 | * The "pgd_xxx()" functions here are trivial for a folded two-level |
287 | * Undefined behaviour if not.. | 296 | * setup: the pgd is never bad, and a pmd always exists (as it's folded |
297 | * into the pgd entry) | ||
288 | */ | 298 | */ |
289 | #define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT) | 299 | #define pgd_none(pgd) (0) |
290 | #define pte_write(pte) (pte_val(pte) & L_PTE_WRITE) | 300 | #define pgd_bad(pgd) (0) |
291 | #define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY) | 301 | #define pgd_present(pgd) (1) |
292 | #define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG) | 302 | #define pgd_clear(pgdp) do { } while (0) |
293 | #define pte_special(pte) (0) | 303 | #define set_pgd(pgd,pgdp) do { } while (0) |
294 | 304 | #define set_pud(pud,pudp) do { } while (0) | |
295 | #define PTE_BIT_FUNC(fn,op) \ | ||
296 | static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } | ||
297 | |||
298 | PTE_BIT_FUNC(wrprotect, &= ~L_PTE_WRITE); | ||
299 | PTE_BIT_FUNC(mkwrite, |= L_PTE_WRITE); | ||
300 | PTE_BIT_FUNC(mkclean, &= ~L_PTE_DIRTY); | ||
301 | PTE_BIT_FUNC(mkdirty, |= L_PTE_DIRTY); | ||
302 | PTE_BIT_FUNC(mkold, &= ~L_PTE_YOUNG); | ||
303 | PTE_BIT_FUNC(mkyoung, |= L_PTE_YOUNG); | ||
304 | |||
305 | static inline pte_t pte_mkspecial(pte_t pte) { return pte; } | ||
306 | 305 | ||
307 | #define __pgprot_modify(prot,mask,bits) \ | ||
308 | __pgprot((pgprot_val(prot) & ~(mask)) | (bits)) | ||
309 | 306 | ||
310 | /* | 307 | /* Find an entry in the second-level page table.. */ |
311 | * Mark the prot value as uncacheable and unbufferable. | 308 | #define pmd_offset(dir, addr) ((pmd_t *)(dir)) |
312 | */ | ||
313 | #define pgprot_noncached(prot) \ | ||
314 | __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED) | ||
315 | #define pgprot_writecombine(prot) \ | ||
316 | __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE) | ||
317 | #ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE | ||
318 | #define pgprot_dmacoherent(prot) \ | ||
319 | __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_BUFFERABLE) | ||
320 | #define __HAVE_PHYS_MEM_ACCESS_PROT | ||
321 | struct file; | ||
322 | extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | ||
323 | unsigned long size, pgprot_t vma_prot); | ||
324 | #else | ||
325 | #define pgprot_dmacoherent(prot) \ | ||
326 | __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_UNCACHED) | ||
327 | #endif | ||
328 | 309 | ||
329 | #define pmd_none(pmd) (!pmd_val(pmd)) | 310 | #define pmd_none(pmd) (!pmd_val(pmd)) |
330 | #define pmd_present(pmd) (pmd_val(pmd)) | 311 | #define pmd_present(pmd) (pmd_val(pmd)) |
@@ -346,56 +327,89 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | |||
346 | 327 | ||
347 | static inline pte_t *pmd_page_vaddr(pmd_t pmd) | 328 | static inline pte_t *pmd_page_vaddr(pmd_t pmd) |
348 | { | 329 | { |
349 | unsigned long ptr; | 330 | return __va(pmd_val(pmd) & PAGE_MASK); |
350 | |||
351 | ptr = pmd_val(pmd) & ~(PTRS_PER_PTE * sizeof(void *) - 1); | ||
352 | ptr += PTRS_PER_PTE * sizeof(void *); | ||
353 | |||
354 | return __va(ptr); | ||
355 | } | 331 | } |
356 | 332 | ||
357 | #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd))) | 333 | #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd))) |
358 | 334 | ||
359 | /* | 335 | /* we don't need complex calculations here as the pmd is folded into the pgd */ |
360 | * Conversion functions: convert a page and protection to a page entry, | 336 | #define pmd_addr_end(addr,end) (end) |
361 | * and a page entry and page directory to the page they refer to. | ||
362 | */ | ||
363 | #define mk_pte(page,prot) pfn_pte(page_to_pfn(page),prot) | ||
364 | 337 | ||
365 | /* | ||
366 | * The "pgd_xxx()" functions here are trivial for a folded two-level | ||
367 | * setup: the pgd is never bad, and a pmd always exists (as it's folded | ||
368 | * into the pgd entry) | ||
369 | */ | ||
370 | #define pgd_none(pgd) (0) | ||
371 | #define pgd_bad(pgd) (0) | ||
372 | #define pgd_present(pgd) (1) | ||
373 | #define pgd_clear(pgdp) do { } while (0) | ||
374 | #define set_pgd(pgd,pgdp) do { } while (0) | ||
375 | 338 | ||
376 | /* to find an entry in a page-table-directory */ | 339 | #ifndef CONFIG_HIGHPTE |
377 | #define pgd_index(addr) ((addr) >> PGDIR_SHIFT) | 340 | #define __pte_map(pmd) pmd_page_vaddr(*(pmd)) |
341 | #define __pte_unmap(pte) do { } while (0) | ||
342 | #else | ||
343 | #define __pte_map(pmd) (pte_t *)kmap_atomic(pmd_page(*(pmd))) | ||
344 | #define __pte_unmap(pte) kunmap_atomic(pte) | ||
345 | #endif | ||
378 | 346 | ||
379 | #define pgd_offset(mm, addr) ((mm)->pgd+pgd_index(addr)) | 347 | #define pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) |
380 | 348 | ||
381 | /* to find an entry in a kernel page-table-directory */ | 349 | #define pte_offset_kernel(pmd,addr) (pmd_page_vaddr(*(pmd)) + pte_index(addr)) |
382 | #define pgd_offset_k(addr) pgd_offset(&init_mm, addr) | ||
383 | 350 | ||
384 | /* Find an entry in the second-level page table.. */ | 351 | #define pte_offset_map(pmd,addr) (__pte_map(pmd) + pte_index(addr)) |
385 | #define pmd_offset(dir, addr) ((pmd_t *)(dir)) | 352 | #define pte_unmap(pte) __pte_unmap(pte) |
386 | 353 | ||
387 | /* Find an entry in the third-level page table.. */ | 354 | #define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT) |
388 | #define __pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) | 355 | #define pfn_pte(pfn,prot) __pte(__pfn_to_phys(pfn) | pgprot_val(prot)) |
356 | |||
357 | #define pte_page(pte) pfn_to_page(pte_pfn(pte)) | ||
358 | #define mk_pte(page,prot) pfn_pte(page_to_pfn(page), prot) | ||
359 | |||
360 | #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext) | ||
361 | #define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0) | ||
362 | |||
363 | #if __LINUX_ARM_ARCH__ < 6 | ||
364 | static inline void __sync_icache_dcache(pte_t pteval) | ||
365 | { | ||
366 | } | ||
367 | #else | ||
368 | extern void __sync_icache_dcache(pte_t pteval); | ||
369 | #endif | ||
370 | |||
371 | static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | ||
372 | pte_t *ptep, pte_t pteval) | ||
373 | { | ||
374 | if (addr >= TASK_SIZE) | ||
375 | set_pte_ext(ptep, pteval, 0); | ||
376 | else { | ||
377 | __sync_icache_dcache(pteval); | ||
378 | set_pte_ext(ptep, pteval, PTE_EXT_NG); | ||
379 | } | ||
380 | } | ||
381 | |||
382 | #define pte_none(pte) (!pte_val(pte)) | ||
383 | #define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT) | ||
384 | #define pte_write(pte) (!(pte_val(pte) & L_PTE_RDONLY)) | ||
385 | #define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY) | ||
386 | #define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG) | ||
387 | #define pte_exec(pte) (!(pte_val(pte) & L_PTE_XN)) | ||
388 | #define pte_special(pte) (0) | ||
389 | |||
390 | #define pte_present_user(pte) \ | ||
391 | ((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \ | ||
392 | (L_PTE_PRESENT | L_PTE_USER)) | ||
393 | |||
394 | #define PTE_BIT_FUNC(fn,op) \ | ||
395 | static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } | ||
396 | |||
397 | PTE_BIT_FUNC(wrprotect, |= L_PTE_RDONLY); | ||
398 | PTE_BIT_FUNC(mkwrite, &= ~L_PTE_RDONLY); | ||
399 | PTE_BIT_FUNC(mkclean, &= ~L_PTE_DIRTY); | ||
400 | PTE_BIT_FUNC(mkdirty, |= L_PTE_DIRTY); | ||
401 | PTE_BIT_FUNC(mkold, &= ~L_PTE_YOUNG); | ||
402 | PTE_BIT_FUNC(mkyoung, |= L_PTE_YOUNG); | ||
403 | |||
404 | static inline pte_t pte_mkspecial(pte_t pte) { return pte; } | ||
389 | 405 | ||
390 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | 406 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) |
391 | { | 407 | { |
392 | const unsigned long mask = L_PTE_EXEC | L_PTE_WRITE | L_PTE_USER; | 408 | const pteval_t mask = L_PTE_XN | L_PTE_RDONLY | L_PTE_USER; |
393 | pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask); | 409 | pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask); |
394 | return pte; | 410 | return pte; |
395 | } | 411 | } |
396 | 412 | ||
397 | extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; | ||
398 | |||
399 | /* | 413 | /* |
400 | * Encode and decode a swap entry. Swap entries are stored in the Linux | 414 | * Encode and decode a swap entry. Swap entries are stored in the Linux |
401 | * page tables as follows: | 415 | * page tables as follows: |
@@ -460,6 +474,9 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; | |||
460 | 474 | ||
461 | #define pgtable_cache_init() do { } while (0) | 475 | #define pgtable_cache_init() do { } while (0) |
462 | 476 | ||
477 | void identity_mapping_add(pgd_t *, unsigned long, unsigned long); | ||
478 | void identity_mapping_del(pgd_t *, unsigned long, unsigned long); | ||
479 | |||
463 | #endif /* !__ASSEMBLY__ */ | 480 | #endif /* !__ASSEMBLY__ */ |
464 | 481 | ||
465 | #endif /* CONFIG_MMU */ | 482 | #endif /* CONFIG_MMU */ |