1 /* 2 * arch/arm/include/asm/pgtable-3level.h 3 * 4 * Copyright (C) 2011 ARM Ltd. 5 * Author: Catalin Marinas <catalin.marinas@arm.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 #ifndef _ASM_PGTABLE_3LEVEL_H 21 #define _ASM_PGTABLE_3LEVEL_H 22 23 /* 24 * With LPAE, there are 3 levels of page tables. Each level has 512 entries of 25 * 8 bytes each, occupying a 4K page. The first level table covers a range of 26 * 512GB, each entry representing 1GB. Since we are limited to 4GB input 27 * address range, only 4 entries in the PGD are used. 28 * 29 * There are enough spare bits in a page table entry for the kernel specific 30 * state. 31 */ 32 #define PTRS_PER_PTE 512 33 #define PTRS_PER_PMD 512 34 #define PTRS_PER_PGD 4 35 36 #define PTE_HWTABLE_PTRS (PTRS_PER_PTE) 37 #define PTE_HWTABLE_OFF (0) 38 #define PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(u64)) 39 40 /* 41 * PGDIR_SHIFT determines the size a top-level page table entry can map. 42 */ 43 #define PGDIR_SHIFT 30 44 45 /* 46 * PMD_SHIFT determines the size a middle-level page table entry can map. 47 */ 48 #define PMD_SHIFT 21 49 50 #define PMD_SIZE (1UL << PMD_SHIFT) 51 #define PMD_MASK (~(PMD_SIZE-1)) 52 #define PGDIR_SIZE (1UL << PGDIR_SHIFT) 53 #define PGDIR_MASK (~(PGDIR_SIZE-1)) 54 55 /* 56 * section address mask and size definitions. 57 */ 58 #define SECTION_SHIFT 21 59 #define SECTION_SIZE (1UL << SECTION_SHIFT) 60 #define SECTION_MASK (~(SECTION_SIZE-1)) 61 62 #define USER_PTRS_PER_PGD (PAGE_OFFSET / PGDIR_SIZE) 63 64 /* 65 * "Linux" PTE definitions for LPAE. 66 * 67 * These bits overlap with the hardware bits but the naming is preserved for 68 * consistency with the classic page table format. 69 */ 70 #define L_PTE_VALID (_AT(pteval_t, 1) << 0) /* Valid */ 71 #define L_PTE_PRESENT (_AT(pteval_t, 3) << 0) /* Present */ 72 #define L_PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !PRESENT */ 73 #define L_PTE_USER (_AT(pteval_t, 1) << 6) /* AP[1] */ 74 #define L_PTE_RDONLY (_AT(pteval_t, 1) << 7) /* AP[2] */ 75 #define L_PTE_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ 76 #define L_PTE_YOUNG (_AT(pteval_t, 1) << 10) /* AF */ 77 #define L_PTE_XN (_AT(pteval_t, 1) << 54) /* XN */ 78 #define L_PTE_DIRTY (_AT(pteval_t, 1) << 55) /* unused */ 79 #define L_PTE_SPECIAL (_AT(pteval_t, 1) << 56) /* unused */ 80 #define L_PTE_NONE (_AT(pteval_t, 1) << 57) /* PROT_NONE */ 81 82 /* 83 * To be used in assembly code with the upper page attributes. 84 */ 85 #define L_PTE_XN_HIGH (1 << (54 - 32)) 86 #define L_PTE_DIRTY_HIGH (1 << (55 - 32)) 87 88 /* 89 * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers). 90 */ 91 #define L_PTE_MT_UNCACHED (_AT(pteval_t, 0) << 2) /* strongly ordered */ 92 #define L_PTE_MT_BUFFERABLE (_AT(pteval_t, 1) << 2) /* normal non-cacheable */ 93 #define L_PTE_MT_WRITETHROUGH (_AT(pteval_t, 2) << 2) /* normal inner write-through */ 94 #define L_PTE_MT_WRITEBACK (_AT(pteval_t, 3) << 2) /* normal inner write-back */ 95 #define L_PTE_MT_WRITEALLOC (_AT(pteval_t, 7) << 2) /* normal inner write-alloc */ 96 #define L_PTE_MT_DEV_SHARED (_AT(pteval_t, 4) << 2) /* device */ 97 #define L_PTE_MT_DEV_NONSHARED (_AT(pteval_t, 4) << 2) /* device */ 98 #define L_PTE_MT_DEV_WC (_AT(pteval_t, 1) << 2) /* normal non-cacheable */ 99 #define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 3) << 2) /* normal inner write-back */ 100 #define L_PTE_MT_MASK (_AT(pteval_t, 7) << 2) 101 102 /* 103 * Software PGD flags. 104 */ 105 #define L_PGD_SWAPPER (_AT(pgdval_t, 1) << 55) /* swapper_pg_dir entry */ 106 107 #ifndef __ASSEMBLY__ 108 109 #define pud_none(pud) (!pud_val(pud)) 110 #define pud_bad(pud) (!(pud_val(pud) & 2)) 111 #define pud_present(pud) (pud_val(pud)) 112 113 #define pud_clear(pudp) \ 114 do { \ 115 *pudp = __pud(0); \ 116 clean_pmd_entry(pudp); \ 117 } while (0) 118 119 #define set_pud(pudp, pud) \ 120 do { \ 121 *pudp = pud; \ 122 flush_pmd_entry(pudp); \ 123 } while (0) 124 125 static inline pmd_t *pud_page_vaddr(pud_t pud) 126 { 127 return __va(pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK); 128 } 129 130 /* Find an entry in the second-level page table.. */ 131 #define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) 132 static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr) 133 { 134 return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr); 135 } 136 137 #define pmd_bad(pmd) (!(pmd_val(pmd) & 2)) 138 139 #define copy_pmd(pmdpd,pmdps) \ 140 do { \ 141 *pmdpd = *pmdps; \ 142 flush_pmd_entry(pmdpd); \ 143 } while (0) 144 145 #define pmd_clear(pmdp) \ 146 do { \ 147 *pmdp = __pmd(0); \ 148 clean_pmd_entry(pmdp); \ 149 } while (0) 150 151 #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,__pte(pte_val(pte)|(ext))) 152 153 #endif /* __ASSEMBLY__ */ 154 155 #endif /* _ASM_PGTABLE_3LEVEL_H */ 156