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.h119
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) \
217static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; }
218
219PMD_BIT_FUNC(wrprotect, |= PMD_SECT_RDONLY);
220PMD_BIT_FUNC(mkold, &= ~PMD_SECT_AF);
221PMD_BIT_FUNC(mksplitting, |= PMD_SECT_SPLITTING);
222PMD_BIT_FUNC(mkwrite, &= ~PMD_SECT_RDONLY);
223PMD_BIT_FUNC(mkdirty, |= PMD_SECT_DIRTY);
224PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF);
225PMD_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
235static 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
246static 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
200static inline void set_pmd(pmd_t *pmdp, pmd_t pmd) 276static 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
268static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) 344static 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
319extern int kern_addr_valid(unsigned long addr); 395extern 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__ */