diff options
Diffstat (limited to 'arch/arm64/include/asm/pgtable.h')
-rw-r--r-- | arch/arm64/include/asm/pgtable.h | 119 |
1 files changed, 94 insertions, 25 deletions
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index e333a243bfcc..f0bebc5e22cd 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h | |||
@@ -25,8 +25,8 @@ | |||
25 | * Software defined PTE bits definition. | 25 | * Software defined PTE bits definition. |
26 | */ | 26 | */ |
27 | #define PTE_VALID (_AT(pteval_t, 1) << 0) | 27 | #define PTE_VALID (_AT(pteval_t, 1) << 0) |
28 | #define PTE_PROT_NONE (_AT(pteval_t, 1) << 1) /* only when !PTE_VALID */ | 28 | #define PTE_PROT_NONE (_AT(pteval_t, 1) << 2) /* only when !PTE_VALID */ |
29 | #define PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !pte_present() */ | 29 | #define PTE_FILE (_AT(pteval_t, 1) << 3) /* only when !pte_present() */ |
30 | #define PTE_DIRTY (_AT(pteval_t, 1) << 55) | 30 | #define PTE_DIRTY (_AT(pteval_t, 1) << 55) |
31 | #define PTE_SPECIAL (_AT(pteval_t, 1) << 56) | 31 | #define PTE_SPECIAL (_AT(pteval_t, 1) << 56) |
32 | 32 | ||
@@ -66,7 +66,7 @@ extern pgprot_t pgprot_default; | |||
66 | 66 | ||
67 | #define _MOD_PROT(p, b) __pgprot_modify(p, 0, b) | 67 | #define _MOD_PROT(p, b) __pgprot_modify(p, 0, b) |
68 | 68 | ||
69 | #define PAGE_NONE __pgprot_modify(pgprot_default, PTE_TYPE_MASK, PTE_PROT_NONE) | 69 | #define PAGE_NONE __pgprot_modify(pgprot_default, PTE_TYPE_MASK, PTE_PROT_NONE | PTE_RDONLY | PTE_PXN | PTE_UXN) |
70 | #define PAGE_SHARED _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) | 70 | #define PAGE_SHARED _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) |
71 | #define PAGE_SHARED_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN) | 71 | #define PAGE_SHARED_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN) |
72 | #define PAGE_COPY _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) | 72 | #define PAGE_COPY _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) |
@@ -76,7 +76,13 @@ extern pgprot_t pgprot_default; | |||
76 | #define PAGE_KERNEL _MOD_PROT(pgprot_default, PTE_PXN | PTE_UXN | PTE_DIRTY) | 76 | #define PAGE_KERNEL _MOD_PROT(pgprot_default, PTE_PXN | PTE_UXN | PTE_DIRTY) |
77 | #define PAGE_KERNEL_EXEC _MOD_PROT(pgprot_default, PTE_UXN | PTE_DIRTY) | 77 | #define PAGE_KERNEL_EXEC _MOD_PROT(pgprot_default, PTE_UXN | PTE_DIRTY) |
78 | 78 | ||
79 | #define __PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_TYPE_MASK) | PTE_PROT_NONE) | 79 | #define PAGE_HYP _MOD_PROT(pgprot_default, PTE_HYP) |
80 | #define PAGE_HYP_DEVICE __pgprot(PROT_DEVICE_nGnRE | PTE_HYP) | ||
81 | |||
82 | #define PAGE_S2 __pgprot_modify(pgprot_default, PTE_S2_MEMATTR_MASK, PTE_S2_MEMATTR(MT_S2_NORMAL) | PTE_S2_RDONLY) | ||
83 | #define PAGE_S2_DEVICE __pgprot(PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_DEVICE_nGnRE) | PTE_S2_RDWR | PTE_UXN) | ||
84 | |||
85 | #define __PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_TYPE_MASK) | PTE_PROT_NONE | PTE_RDONLY | PTE_PXN | PTE_UXN) | ||
80 | #define __PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) | 86 | #define __PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) |
81 | #define __PAGE_SHARED_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN) | 87 | #define __PAGE_SHARED_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN) |
82 | #define __PAGE_COPY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) | 88 | #define __PAGE_COPY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) |
@@ -119,7 +125,7 @@ extern struct page *empty_zero_page; | |||
119 | #define pte_none(pte) (!pte_val(pte)) | 125 | #define pte_none(pte) (!pte_val(pte)) |
120 | #define pte_clear(mm,addr,ptep) set_pte(ptep, __pte(0)) | 126 | #define pte_clear(mm,addr,ptep) set_pte(ptep, __pte(0)) |
121 | #define pte_page(pte) (pfn_to_page(pte_pfn(pte))) | 127 | #define pte_page(pte) (pfn_to_page(pte_pfn(pte))) |
122 | #define pte_offset_kernel(dir,addr) (pmd_page_vaddr(*(dir)) + __pte_index(addr)) | 128 | #define pte_offset_kernel(dir,addr) (pmd_page_vaddr(*(dir)) + pte_index(addr)) |
123 | 129 | ||
124 | #define pte_offset_map(dir,addr) pte_offset_kernel((dir), (addr)) | 130 | #define pte_offset_map(dir,addr) pte_offset_kernel((dir), (addr)) |
125 | #define pte_offset_map_nested(dir,addr) pte_offset_kernel((dir), (addr)) | 131 | #define pte_offset_map_nested(dir,addr) pte_offset_kernel((dir), (addr)) |
@@ -173,12 +179,76 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | |||
173 | /* | 179 | /* |
174 | * Huge pte definitions. | 180 | * Huge pte definitions. |
175 | */ | 181 | */ |
176 | #define pte_huge(pte) ((pte_val(pte) & PTE_TYPE_MASK) == PTE_TYPE_HUGEPAGE) | 182 | #define pte_huge(pte) (!(pte_val(pte) & PTE_TABLE_BIT)) |
177 | #define pte_mkhuge(pte) (__pte((pte_val(pte) & ~PTE_TYPE_MASK) | PTE_TYPE_HUGEPAGE)) | 183 | #define pte_mkhuge(pte) (__pte(pte_val(pte) & ~PTE_TABLE_BIT)) |
184 | |||
185 | /* | ||
186 | * Hugetlb definitions. | ||
187 | */ | ||
188 | #define HUGE_MAX_HSTATE 2 | ||
189 | #define HPAGE_SHIFT PMD_SHIFT | ||
190 | #define HPAGE_SIZE (_AC(1, UL) << HPAGE_SHIFT) | ||
191 | #define HPAGE_MASK (~(HPAGE_SIZE - 1)) | ||
192 | #define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) | ||
178 | 193 | ||
179 | #define __HAVE_ARCH_PTE_SPECIAL | 194 | #define __HAVE_ARCH_PTE_SPECIAL |
180 | 195 | ||
181 | /* | 196 | /* |
197 | * Software PMD bits for THP | ||
198 | */ | ||
199 | |||
200 | #define PMD_SECT_DIRTY (_AT(pmdval_t, 1) << 55) | ||
201 | #define PMD_SECT_SPLITTING (_AT(pmdval_t, 1) << 57) | ||
202 | |||
203 | /* | ||
204 | * THP definitions. | ||
205 | */ | ||
206 | #define pmd_young(pmd) (pmd_val(pmd) & PMD_SECT_AF) | ||
207 | |||
208 | #define __HAVE_ARCH_PMD_WRITE | ||
209 | #define pmd_write(pmd) (!(pmd_val(pmd) & PMD_SECT_RDONLY)) | ||
210 | |||
211 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
212 | #define pmd_trans_huge(pmd) (pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT)) | ||
213 | #define pmd_trans_splitting(pmd) (pmd_val(pmd) & PMD_SECT_SPLITTING) | ||
214 | #endif | ||
215 | |||
216 | #define PMD_BIT_FUNC(fn,op) \ | ||
217 | static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; } | ||
218 | |||
219 | PMD_BIT_FUNC(wrprotect, |= PMD_SECT_RDONLY); | ||
220 | PMD_BIT_FUNC(mkold, &= ~PMD_SECT_AF); | ||
221 | PMD_BIT_FUNC(mksplitting, |= PMD_SECT_SPLITTING); | ||
222 | PMD_BIT_FUNC(mkwrite, &= ~PMD_SECT_RDONLY); | ||
223 | PMD_BIT_FUNC(mkdirty, |= PMD_SECT_DIRTY); | ||
224 | PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF); | ||
225 | PMD_BIT_FUNC(mknotpresent, &= ~PMD_TYPE_MASK); | ||
226 | |||
227 | #define pmd_mkhuge(pmd) (__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT)) | ||
228 | |||
229 | #define pmd_pfn(pmd) (((pmd_val(pmd) & PMD_MASK) & PHYS_MASK) >> PAGE_SHIFT) | ||
230 | #define pfn_pmd(pfn,prot) (__pmd(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))) | ||
231 | #define mk_pmd(page,prot) pfn_pmd(page_to_pfn(page),prot) | ||
232 | |||
233 | #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK)) | ||
234 | |||
235 | static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) | ||
236 | { | ||
237 | const pmdval_t mask = PMD_SECT_USER | PMD_SECT_PXN | PMD_SECT_UXN | | ||
238 | PMD_SECT_RDONLY | PMD_SECT_PROT_NONE | | ||
239 | PMD_SECT_VALID; | ||
240 | pmd_val(pmd) = (pmd_val(pmd) & ~mask) | (pgprot_val(newprot) & mask); | ||
241 | return pmd; | ||
242 | } | ||
243 | |||
244 | #define set_pmd_at(mm, addr, pmdp, pmd) set_pmd(pmdp, pmd) | ||
245 | |||
246 | static inline int has_transparent_hugepage(void) | ||
247 | { | ||
248 | return 1; | ||
249 | } | ||
250 | |||
251 | /* | ||
182 | * Mark the prot value as uncacheable and unbufferable. | 252 | * Mark the prot value as uncacheable and unbufferable. |
183 | */ | 253 | */ |
184 | #define pgprot_noncached(prot) \ | 254 | #define pgprot_noncached(prot) \ |
@@ -197,6 +267,12 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | |||
197 | 267 | ||
198 | #define pmd_bad(pmd) (!(pmd_val(pmd) & 2)) | 268 | #define pmd_bad(pmd) (!(pmd_val(pmd) & 2)) |
199 | 269 | ||
270 | #define pmd_table(pmd) ((pmd_val(pmd) & PMD_TYPE_MASK) == \ | ||
271 | PMD_TYPE_TABLE) | ||
272 | #define pmd_sect(pmd) ((pmd_val(pmd) & PMD_TYPE_MASK) == \ | ||
273 | PMD_TYPE_SECT) | ||
274 | |||
275 | |||
200 | static inline void set_pmd(pmd_t *pmdp, pmd_t pmd) | 276 | static inline void set_pmd(pmd_t *pmdp, pmd_t pmd) |
201 | { | 277 | { |
202 | *pmdp = pmd; | 278 | *pmdp = pmd; |
@@ -263,7 +339,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr) | |||
263 | #endif | 339 | #endif |
264 | 340 | ||
265 | /* Find an entry in the third-level page table.. */ | 341 | /* Find an entry in the third-level page table.. */ |
266 | #define __pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) | 342 | #define pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) |
267 | 343 | ||
268 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | 344 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) |
269 | { | 345 | { |
@@ -281,12 +357,12 @@ extern pgd_t idmap_pg_dir[PTRS_PER_PGD]; | |||
281 | 357 | ||
282 | /* | 358 | /* |
283 | * Encode and decode a swap entry: | 359 | * Encode and decode a swap entry: |
284 | * bits 0-1: present (must be zero) | 360 | * bits 0, 2: present (must both be zero) |
285 | * bit 2: PTE_FILE | 361 | * bit 3: PTE_FILE |
286 | * bits 3-8: swap type | 362 | * bits 4-8: swap type |
287 | * bits 9-63: swap offset | 363 | * bits 9-63: swap offset |
288 | */ | 364 | */ |
289 | #define __SWP_TYPE_SHIFT 3 | 365 | #define __SWP_TYPE_SHIFT 4 |
290 | #define __SWP_TYPE_BITS 6 | 366 | #define __SWP_TYPE_BITS 6 |
291 | #define __SWP_TYPE_MASK ((1 << __SWP_TYPE_BITS) - 1) | 367 | #define __SWP_TYPE_MASK ((1 << __SWP_TYPE_BITS) - 1) |
292 | #define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT) | 368 | #define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT) |
@@ -306,27 +382,20 @@ extern pgd_t idmap_pg_dir[PTRS_PER_PGD]; | |||
306 | 382 | ||
307 | /* | 383 | /* |
308 | * Encode and decode a file entry: | 384 | * Encode and decode a file entry: |
309 | * bits 0-1: present (must be zero) | 385 | * bits 0, 2: present (must both be zero) |
310 | * bit 2: PTE_FILE | 386 | * bit 3: PTE_FILE |
311 | * bits 3-63: file offset / PAGE_SIZE | 387 | * bits 4-63: file offset / PAGE_SIZE |
312 | */ | 388 | */ |
313 | #define pte_file(pte) (pte_val(pte) & PTE_FILE) | 389 | #define pte_file(pte) (pte_val(pte) & PTE_FILE) |
314 | #define pte_to_pgoff(x) (pte_val(x) >> 3) | 390 | #define pte_to_pgoff(x) (pte_val(x) >> 4) |
315 | #define pgoff_to_pte(x) __pte(((x) << 3) | PTE_FILE) | 391 | #define pgoff_to_pte(x) __pte(((x) << 4) | PTE_FILE) |
316 | 392 | ||
317 | #define PTE_FILE_MAX_BITS 61 | 393 | #define PTE_FILE_MAX_BITS 60 |
318 | 394 | ||
319 | extern int kern_addr_valid(unsigned long addr); | 395 | extern int kern_addr_valid(unsigned long addr); |
320 | 396 | ||
321 | #include <asm-generic/pgtable.h> | 397 | #include <asm-generic/pgtable.h> |
322 | 398 | ||
323 | /* | ||
324 | * remap a physical page `pfn' of size `size' with page protection `prot' | ||
325 | * into virtual address `from' | ||
326 | */ | ||
327 | #define io_remap_pfn_range(vma,from,pfn,size,prot) \ | ||
328 | remap_pfn_range(vma, from, pfn, size, prot) | ||
329 | |||
330 | #define pgtable_cache_init() do { } while (0) | 399 | #define pgtable_cache_init() do { } while (0) |
331 | 400 | ||
332 | #endif /* !__ASSEMBLY__ */ | 401 | #endif /* !__ASSEMBLY__ */ |