aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64/include/asm/pgtable.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm64/include/asm/pgtable.h')
-rw-r--r--arch/arm64/include/asm/pgtable.h100
1 files changed, 76 insertions, 24 deletions
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index e0ccceb317d9..ffe1ba0506d1 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -33,9 +33,16 @@
33 33
34/* 34/*
35 * VMALLOC and SPARSEMEM_VMEMMAP ranges. 35 * VMALLOC and SPARSEMEM_VMEMMAP ranges.
36 *
37 * VMEMAP_SIZE: allows the whole VA space to be covered by a struct page array
38 * (rounded up to PUD_SIZE).
39 * VMALLOC_START: beginning of the kernel VA space
40 * VMALLOC_END: extends to the available space below vmmemmap, PCI I/O space,
41 * fixed mappings and modules
36 */ 42 */
43#define VMEMMAP_SIZE ALIGN((1UL << (VA_BITS - PAGE_SHIFT)) * sizeof(struct page), PUD_SIZE)
37#define VMALLOC_START (UL(0xffffffffffffffff) << VA_BITS) 44#define VMALLOC_START (UL(0xffffffffffffffff) << VA_BITS)
38#define VMALLOC_END (PAGE_OFFSET - UL(0x400000000) - SZ_64K) 45#define VMALLOC_END (PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - SZ_64K)
39 46
40#define vmemmap ((struct page *)(VMALLOC_END + SZ_64K)) 47#define vmemmap ((struct page *)(VMALLOC_END + SZ_64K))
41 48
@@ -44,14 +51,9 @@
44#ifndef __ASSEMBLY__ 51#ifndef __ASSEMBLY__
45extern void __pte_error(const char *file, int line, unsigned long val); 52extern void __pte_error(const char *file, int line, unsigned long val);
46extern void __pmd_error(const char *file, int line, unsigned long val); 53extern void __pmd_error(const char *file, int line, unsigned long val);
54extern void __pud_error(const char *file, int line, unsigned long val);
47extern void __pgd_error(const char *file, int line, unsigned long val); 55extern void __pgd_error(const char *file, int line, unsigned long val);
48 56
49#define pte_ERROR(pte) __pte_error(__FILE__, __LINE__, pte_val(pte))
50#ifndef CONFIG_ARM64_64K_PAGES
51#define pmd_ERROR(pmd) __pmd_error(__FILE__, __LINE__, pmd_val(pmd))
52#endif
53#define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd_val(pgd))
54
55#ifdef CONFIG_SMP 57#ifdef CONFIG_SMP
56#define PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED) 58#define PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED)
57#define PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S) 59#define PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S)
@@ -112,6 +114,8 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
112extern struct page *empty_zero_page; 114extern struct page *empty_zero_page;
113#define ZERO_PAGE(vaddr) (empty_zero_page) 115#define ZERO_PAGE(vaddr) (empty_zero_page)
114 116
117#define pte_ERROR(pte) __pte_error(__FILE__, __LINE__, pte_val(pte))
118
115#define pte_pfn(pte) ((pte_val(pte) & PHYS_MASK) >> PAGE_SHIFT) 119#define pte_pfn(pte) ((pte_val(pte) & PHYS_MASK) >> PAGE_SHIFT)
116 120
117#define pfn_pte(pfn,prot) (__pte(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))) 121#define pfn_pte(pfn,prot) (__pte(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)))
@@ -119,6 +123,10 @@ extern struct page *empty_zero_page;
119#define pte_none(pte) (!pte_val(pte)) 123#define pte_none(pte) (!pte_val(pte))
120#define pte_clear(mm,addr,ptep) set_pte(ptep, __pte(0)) 124#define pte_clear(mm,addr,ptep) set_pte(ptep, __pte(0))
121#define pte_page(pte) (pfn_to_page(pte_pfn(pte))) 125#define pte_page(pte) (pfn_to_page(pte_pfn(pte)))
126
127/* Find an entry in the third-level page table. */
128#define pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
129
122#define pte_offset_kernel(dir,addr) (pmd_page_vaddr(*(dir)) + pte_index(addr)) 130#define pte_offset_kernel(dir,addr) (pmd_page_vaddr(*(dir)) + pte_index(addr))
123 131
124#define pte_offset_map(dir,addr) pte_offset_kernel((dir), (addr)) 132#define pte_offset_map(dir,addr) pte_offset_kernel((dir), (addr))
@@ -138,6 +146,8 @@ extern struct page *empty_zero_page;
138 146
139#define pte_valid_user(pte) \ 147#define pte_valid_user(pte) \
140 ((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER)) 148 ((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER))
149#define pte_valid_not_user(pte) \
150 ((pte_val(pte) & (PTE_VALID | PTE_USER)) == PTE_VALID)
141 151
142static inline pte_t pte_wrprotect(pte_t pte) 152static inline pte_t pte_wrprotect(pte_t pte)
143{ 153{
@@ -184,6 +194,15 @@ static inline pte_t pte_mkspecial(pte_t pte)
184static inline void set_pte(pte_t *ptep, pte_t pte) 194static inline void set_pte(pte_t *ptep, pte_t pte)
185{ 195{
186 *ptep = pte; 196 *ptep = pte;
197
198 /*
199 * Only if the new pte is valid and kernel, otherwise TLB maintenance
200 * or update_mmu_cache() have the necessary barriers.
201 */
202 if (pte_valid_not_user(pte)) {
203 dsb(ishst);
204 isb();
205 }
187} 206}
188 207
189extern void __sync_icache_dcache(pte_t pteval, unsigned long addr); 208extern void __sync_icache_dcache(pte_t pteval, unsigned long addr);
@@ -303,6 +322,7 @@ static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
303{ 322{
304 *pmdp = pmd; 323 *pmdp = pmd;
305 dsb(ishst); 324 dsb(ishst);
325 isb();
306} 326}
307 327
308static inline void pmd_clear(pmd_t *pmdp) 328static inline void pmd_clear(pmd_t *pmdp)
@@ -323,7 +343,9 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
323 */ 343 */
324#define mk_pte(page,prot) pfn_pte(page_to_pfn(page),prot) 344#define mk_pte(page,prot) pfn_pte(page_to_pfn(page),prot)
325 345
326#ifndef CONFIG_ARM64_64K_PAGES 346#if CONFIG_ARM64_PGTABLE_LEVELS > 2
347
348#define pmd_ERROR(pmd) __pmd_error(__FILE__, __LINE__, pmd_val(pmd))
327 349
328#define pud_none(pud) (!pud_val(pud)) 350#define pud_none(pud) (!pud_val(pud))
329#define pud_bad(pud) (!(pud_val(pud) & 2)) 351#define pud_bad(pud) (!(pud_val(pud) & 2))
@@ -333,6 +355,7 @@ static inline void set_pud(pud_t *pudp, pud_t pud)
333{ 355{
334 *pudp = pud; 356 *pudp = pud;
335 dsb(ishst); 357 dsb(ishst);
358 isb();
336} 359}
337 360
338static inline void pud_clear(pud_t *pudp) 361static inline void pud_clear(pud_t *pudp)
@@ -345,7 +368,51 @@ static inline pmd_t *pud_page_vaddr(pud_t pud)
345 return __va(pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK); 368 return __va(pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK);
346} 369}
347 370
348#endif /* CONFIG_ARM64_64K_PAGES */ 371/* Find an entry in the second-level page table. */
372#define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
373
374static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
375{
376 return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr);
377}
378
379#endif /* CONFIG_ARM64_PGTABLE_LEVELS > 2 */
380
381#if CONFIG_ARM64_PGTABLE_LEVELS > 3
382
383#define pud_ERROR(pud) __pud_error(__FILE__, __LINE__, pud_val(pud))
384
385#define pgd_none(pgd) (!pgd_val(pgd))
386#define pgd_bad(pgd) (!(pgd_val(pgd) & 2))
387#define pgd_present(pgd) (pgd_val(pgd))
388
389static inline void set_pgd(pgd_t *pgdp, pgd_t pgd)
390{
391 *pgdp = pgd;
392 dsb(ishst);
393}
394
395static inline void pgd_clear(pgd_t *pgdp)
396{
397 set_pgd(pgdp, __pgd(0));
398}
399
400static inline pud_t *pgd_page_vaddr(pgd_t pgd)
401{
402 return __va(pgd_val(pgd) & PHYS_MASK & (s32)PAGE_MASK);
403}
404
405/* Find an entry in the frst-level page table. */
406#define pud_index(addr) (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))
407
408static inline pud_t *pud_offset(pgd_t *pgd, unsigned long addr)
409{
410 return (pud_t *)pgd_page_vaddr(*pgd) + pud_index(addr);
411}
412
413#endif /* CONFIG_ARM64_PGTABLE_LEVELS > 3 */
414
415#define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd_val(pgd))
349 416
350/* to find an entry in a page-table-directory */ 417/* to find an entry in a page-table-directory */
351#define pgd_index(addr) (((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) 418#define pgd_index(addr) (((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
@@ -355,18 +422,6 @@ static inline pmd_t *pud_page_vaddr(pud_t pud)
355/* to find an entry in a kernel page-table-directory */ 422/* to find an entry in a kernel page-table-directory */
356#define pgd_offset_k(addr) pgd_offset(&init_mm, addr) 423#define pgd_offset_k(addr) pgd_offset(&init_mm, addr)
357 424
358/* Find an entry in the second-level page table.. */
359#ifndef CONFIG_ARM64_64K_PAGES
360#define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
361static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
362{
363 return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr);
364}
365#endif
366
367/* Find an entry in the third-level page table.. */
368#define pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
369
370static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) 425static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
371{ 426{
372 const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY | 427 const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY |
@@ -383,9 +438,6 @@ static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
383extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; 438extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
384extern pgd_t idmap_pg_dir[PTRS_PER_PGD]; 439extern pgd_t idmap_pg_dir[PTRS_PER_PGD];
385 440
386#define SWAPPER_DIR_SIZE (3 * PAGE_SIZE)
387#define IDMAP_DIR_SIZE (2 * PAGE_SIZE)
388
389/* 441/*
390 * Encode and decode a swap entry: 442 * Encode and decode a swap entry:
391 * bits 0-1: present (must be zero) 443 * bits 0-1: present (must be zero)