xref: /linux/arch/arm64/include/asm/pgtable.h (revision 5d96e0cba26323c3daeb9f7cdfd4efe70985e2c6)
14f04d8f0SCatalin Marinas /*
24f04d8f0SCatalin Marinas  * Copyright (C) 2012 ARM Ltd.
34f04d8f0SCatalin Marinas  *
44f04d8f0SCatalin Marinas  * This program is free software; you can redistribute it and/or modify
54f04d8f0SCatalin Marinas  * it under the terms of the GNU General Public License version 2 as
64f04d8f0SCatalin Marinas  * published by the Free Software Foundation.
74f04d8f0SCatalin Marinas  *
84f04d8f0SCatalin Marinas  * This program is distributed in the hope that it will be useful,
94f04d8f0SCatalin Marinas  * but WITHOUT ANY WARRANTY; without even the implied warranty of
104f04d8f0SCatalin Marinas  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
114f04d8f0SCatalin Marinas  * GNU General Public License for more details.
124f04d8f0SCatalin Marinas  *
134f04d8f0SCatalin Marinas  * You should have received a copy of the GNU General Public License
144f04d8f0SCatalin Marinas  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
154f04d8f0SCatalin Marinas  */
164f04d8f0SCatalin Marinas #ifndef __ASM_PGTABLE_H
174f04d8f0SCatalin Marinas #define __ASM_PGTABLE_H
184f04d8f0SCatalin Marinas 
194f04d8f0SCatalin Marinas #include <asm/proc-fns.h>
204f04d8f0SCatalin Marinas 
214f04d8f0SCatalin Marinas #include <asm/memory.h>
224f04d8f0SCatalin Marinas #include <asm/pgtable-hwdef.h>
234f04d8f0SCatalin Marinas 
244f04d8f0SCatalin Marinas /*
254f04d8f0SCatalin Marinas  * Software defined PTE bits definition.
264f04d8f0SCatalin Marinas  */
27a6fadf7eSWill Deacon #define PTE_VALID		(_AT(pteval_t, 1) << 0)
283676f9efSCatalin Marinas #define PTE_FILE		(_AT(pteval_t, 1) << 2)	/* only when !pte_present() */
294f04d8f0SCatalin Marinas #define PTE_DIRTY		(_AT(pteval_t, 1) << 55)
304f04d8f0SCatalin Marinas #define PTE_SPECIAL		(_AT(pteval_t, 1) << 56)
31c2c93e5bSSteve Capper #define PTE_WRITE		(_AT(pteval_t, 1) << 57)
323676f9efSCatalin Marinas #define PTE_PROT_NONE		(_AT(pteval_t, 1) << 58) /* only when !PTE_VALID */
334f04d8f0SCatalin Marinas 
344f04d8f0SCatalin Marinas /*
354f04d8f0SCatalin Marinas  * VMALLOC and SPARSEMEM_VMEMMAP ranges.
3608375198SCatalin Marinas  *
3708375198SCatalin Marinas  * VMEMAP_SIZE: allows the whole VA space to be covered by a struct page array
3808375198SCatalin Marinas  *	(rounded up to PUD_SIZE).
3908375198SCatalin Marinas  * VMALLOC_START: beginning of the kernel VA space
4008375198SCatalin Marinas  * VMALLOC_END: extends to the available space below vmmemmap, PCI I/O space,
4108375198SCatalin Marinas  *	fixed mappings and modules
424f04d8f0SCatalin Marinas  */
4308375198SCatalin Marinas #define VMEMMAP_SIZE		ALIGN((1UL << (VA_BITS - PAGE_SHIFT)) * sizeof(struct page), PUD_SIZE)
44847264fbSCatalin Marinas #define VMALLOC_START		(UL(0xffffffffffffffff) << VA_BITS)
4508375198SCatalin Marinas #define VMALLOC_END		(PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - SZ_64K)
464f04d8f0SCatalin Marinas 
474f04d8f0SCatalin Marinas #define vmemmap			((struct page *)(VMALLOC_END + SZ_64K))
484f04d8f0SCatalin Marinas 
494f04d8f0SCatalin Marinas #define FIRST_USER_ADDRESS	0
504f04d8f0SCatalin Marinas 
514f04d8f0SCatalin Marinas #ifndef __ASSEMBLY__
524f04d8f0SCatalin Marinas extern void __pte_error(const char *file, int line, unsigned long val);
534f04d8f0SCatalin Marinas extern void __pmd_error(const char *file, int line, unsigned long val);
54c79b954bSJungseok Lee extern void __pud_error(const char *file, int line, unsigned long val);
554f04d8f0SCatalin Marinas extern void __pgd_error(const char *file, int line, unsigned long val);
564f04d8f0SCatalin Marinas 
57a501e324SCatalin Marinas #ifdef CONFIG_SMP
58a501e324SCatalin Marinas #define PROT_DEFAULT		(PTE_TYPE_PAGE | PTE_AF | PTE_SHARED)
59a501e324SCatalin Marinas #define PROT_SECT_DEFAULT	(PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S)
60a501e324SCatalin Marinas #else
61a501e324SCatalin Marinas #define PROT_DEFAULT		(PTE_TYPE_PAGE | PTE_AF)
62a501e324SCatalin Marinas #define PROT_SECT_DEFAULT	(PMD_TYPE_SECT | PMD_SECT_AF)
63a501e324SCatalin Marinas #endif
644f04d8f0SCatalin Marinas 
65a501e324SCatalin Marinas #define PROT_DEVICE_nGnRE	(PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE))
66a501e324SCatalin Marinas #define PROT_NORMAL_NC		(PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_NORMAL_NC))
67a501e324SCatalin Marinas #define PROT_NORMAL		(PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_NORMAL))
684f04d8f0SCatalin Marinas 
69a501e324SCatalin Marinas #define PROT_SECT_DEVICE_nGnRE	(PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_DEVICE_nGnRE))
70a501e324SCatalin Marinas #define PROT_SECT_NORMAL	(PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL))
71a501e324SCatalin Marinas #define PROT_SECT_NORMAL_EXEC	(PROT_SECT_DEFAULT | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL))
724f04d8f0SCatalin Marinas 
73a501e324SCatalin Marinas #define _PAGE_DEFAULT		(PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL))
74a6fadf7eSWill Deacon 
75a501e324SCatalin Marinas #define PAGE_KERNEL		__pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE)
76a501e324SCatalin Marinas #define PAGE_KERNEL_EXEC	__pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE)
774f04d8f0SCatalin Marinas 
78a501e324SCatalin Marinas #define PAGE_HYP		__pgprot(_PAGE_DEFAULT | PTE_HYP)
7936311607SMarc Zyngier #define PAGE_HYP_DEVICE		__pgprot(PROT_DEVICE_nGnRE | PTE_HYP)
8036311607SMarc Zyngier 
81a501e324SCatalin Marinas #define PAGE_S2			__pgprot(PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_NORMAL) | PTE_S2_RDONLY)
824a513fb0SArd Biesheuvel #define PAGE_S2_DEVICE		__pgprot(PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_DEVICE_nGnRE) | PTE_S2_RDONLY | PTE_UXN)
8336311607SMarc Zyngier 
84a501e324SCatalin Marinas #define PAGE_NONE		__pgprot(((_PAGE_DEFAULT) & ~PTE_TYPE_MASK) | PTE_PROT_NONE | PTE_PXN | PTE_UXN)
85a501e324SCatalin Marinas #define PAGE_SHARED		__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE)
86a501e324SCatalin Marinas #define PAGE_SHARED_EXEC	__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_WRITE)
87a501e324SCatalin Marinas #define PAGE_COPY		__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
88a501e324SCatalin Marinas #define PAGE_COPY_EXEC		__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN)
89a501e324SCatalin Marinas #define PAGE_READONLY		__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
90a501e324SCatalin Marinas #define PAGE_READONLY_EXEC	__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN)
914f04d8f0SCatalin Marinas 
92a501e324SCatalin Marinas #define __P000  PAGE_NONE
93a501e324SCatalin Marinas #define __P001  PAGE_READONLY
94a501e324SCatalin Marinas #define __P010  PAGE_COPY
95a501e324SCatalin Marinas #define __P011  PAGE_COPY
965a0fdfadSCatalin Marinas #define __P100  PAGE_READONLY_EXEC
97a501e324SCatalin Marinas #define __P101  PAGE_READONLY_EXEC
98a501e324SCatalin Marinas #define __P110  PAGE_COPY_EXEC
99a501e324SCatalin Marinas #define __P111  PAGE_COPY_EXEC
1004f04d8f0SCatalin Marinas 
101a501e324SCatalin Marinas #define __S000  PAGE_NONE
102a501e324SCatalin Marinas #define __S001  PAGE_READONLY
103a501e324SCatalin Marinas #define __S010  PAGE_SHARED
104a501e324SCatalin Marinas #define __S011  PAGE_SHARED
1055a0fdfadSCatalin Marinas #define __S100  PAGE_READONLY_EXEC
106a501e324SCatalin Marinas #define __S101  PAGE_READONLY_EXEC
107a501e324SCatalin Marinas #define __S110  PAGE_SHARED_EXEC
108a501e324SCatalin Marinas #define __S111  PAGE_SHARED_EXEC
1094f04d8f0SCatalin Marinas 
1104f04d8f0SCatalin Marinas /*
1114f04d8f0SCatalin Marinas  * ZERO_PAGE is a global shared page that is always zero: used
1124f04d8f0SCatalin Marinas  * for zero-mapped memory areas etc..
1134f04d8f0SCatalin Marinas  */
1144f04d8f0SCatalin Marinas extern struct page *empty_zero_page;
1154f04d8f0SCatalin Marinas #define ZERO_PAGE(vaddr)	(empty_zero_page)
1164f04d8f0SCatalin Marinas 
1177078db46SCatalin Marinas #define pte_ERROR(pte)		__pte_error(__FILE__, __LINE__, pte_val(pte))
1187078db46SCatalin Marinas 
1194f04d8f0SCatalin Marinas #define pte_pfn(pte)		((pte_val(pte) & PHYS_MASK) >> PAGE_SHIFT)
1204f04d8f0SCatalin Marinas 
1214f04d8f0SCatalin Marinas #define pfn_pte(pfn,prot)	(__pte(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)))
1224f04d8f0SCatalin Marinas 
1234f04d8f0SCatalin Marinas #define pte_none(pte)		(!pte_val(pte))
1244f04d8f0SCatalin Marinas #define pte_clear(mm,addr,ptep)	set_pte(ptep, __pte(0))
1254f04d8f0SCatalin Marinas #define pte_page(pte)		(pfn_to_page(pte_pfn(pte)))
1267078db46SCatalin Marinas 
1277078db46SCatalin Marinas /* Find an entry in the third-level page table. */
1287078db46SCatalin Marinas #define pte_index(addr)		(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
1297078db46SCatalin Marinas 
1309ab6d02fSWill Deacon #define pte_offset_kernel(dir,addr)	(pmd_page_vaddr(*(dir)) + pte_index(addr))
1314f04d8f0SCatalin Marinas 
1324f04d8f0SCatalin Marinas #define pte_offset_map(dir,addr)	pte_offset_kernel((dir), (addr))
1334f04d8f0SCatalin Marinas #define pte_offset_map_nested(dir,addr)	pte_offset_kernel((dir), (addr))
1344f04d8f0SCatalin Marinas #define pte_unmap(pte)			do { } while (0)
1354f04d8f0SCatalin Marinas #define pte_unmap_nested(pte)		do { } while (0)
1364f04d8f0SCatalin Marinas 
1374f04d8f0SCatalin Marinas /*
1384f04d8f0SCatalin Marinas  * The following only work if pte_present(). Undefined behaviour otherwise.
1394f04d8f0SCatalin Marinas  */
14084fe6826SSteve Capper #define pte_present(pte)	(!!(pte_val(pte) & (PTE_VALID | PTE_PROT_NONE)))
14184fe6826SSteve Capper #define pte_dirty(pte)		(!!(pte_val(pte) & PTE_DIRTY))
14284fe6826SSteve Capper #define pte_young(pte)		(!!(pte_val(pte) & PTE_AF))
14384fe6826SSteve Capper #define pte_special(pte)	(!!(pte_val(pte) & PTE_SPECIAL))
14484fe6826SSteve Capper #define pte_write(pte)		(!!(pte_val(pte) & PTE_WRITE))
1458e620b04SCatalin Marinas #define pte_exec(pte)		(!(pte_val(pte) & PTE_UXN))
1464f04d8f0SCatalin Marinas 
147a6fadf7eSWill Deacon #define pte_valid_user(pte) \
14802522463SWill Deacon 	((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER))
1497f0b1bf0SCatalin Marinas #define pte_valid_not_user(pte) \
1507f0b1bf0SCatalin Marinas 	((pte_val(pte) & (PTE_VALID | PTE_USER)) == PTE_VALID)
1514f04d8f0SCatalin Marinas 
152b6d4f280SLaura Abbott static inline pte_t clear_pte_bit(pte_t pte, pgprot_t prot)
153b6d4f280SLaura Abbott {
154b6d4f280SLaura Abbott 	pte_val(pte) &= ~pgprot_val(prot);
155b6d4f280SLaura Abbott 	return pte;
156b6d4f280SLaura Abbott }
157b6d4f280SLaura Abbott 
158b6d4f280SLaura Abbott static inline pte_t set_pte_bit(pte_t pte, pgprot_t prot)
159b6d4f280SLaura Abbott {
160b6d4f280SLaura Abbott 	pte_val(pte) |= pgprot_val(prot);
161b6d4f280SLaura Abbott 	return pte;
162b6d4f280SLaura Abbott }
163b6d4f280SLaura Abbott 
16444b6dfc5SSteve Capper static inline pte_t pte_wrprotect(pte_t pte)
16544b6dfc5SSteve Capper {
166b6d4f280SLaura Abbott 	return clear_pte_bit(pte, __pgprot(PTE_WRITE));
16744b6dfc5SSteve Capper }
1684f04d8f0SCatalin Marinas 
16944b6dfc5SSteve Capper static inline pte_t pte_mkwrite(pte_t pte)
17044b6dfc5SSteve Capper {
171b6d4f280SLaura Abbott 	return set_pte_bit(pte, __pgprot(PTE_WRITE));
17244b6dfc5SSteve Capper }
17344b6dfc5SSteve Capper 
17444b6dfc5SSteve Capper static inline pte_t pte_mkclean(pte_t pte)
17544b6dfc5SSteve Capper {
176b6d4f280SLaura Abbott 	return clear_pte_bit(pte, __pgprot(PTE_DIRTY));
17744b6dfc5SSteve Capper }
17844b6dfc5SSteve Capper 
17944b6dfc5SSteve Capper static inline pte_t pte_mkdirty(pte_t pte)
18044b6dfc5SSteve Capper {
181b6d4f280SLaura Abbott 	return set_pte_bit(pte, __pgprot(PTE_DIRTY));
18244b6dfc5SSteve Capper }
18344b6dfc5SSteve Capper 
18444b6dfc5SSteve Capper static inline pte_t pte_mkold(pte_t pte)
18544b6dfc5SSteve Capper {
186b6d4f280SLaura Abbott 	return clear_pte_bit(pte, __pgprot(PTE_AF));
18744b6dfc5SSteve Capper }
18844b6dfc5SSteve Capper 
18944b6dfc5SSteve Capper static inline pte_t pte_mkyoung(pte_t pte)
19044b6dfc5SSteve Capper {
191b6d4f280SLaura Abbott 	return set_pte_bit(pte, __pgprot(PTE_AF));
19244b6dfc5SSteve Capper }
19344b6dfc5SSteve Capper 
19444b6dfc5SSteve Capper static inline pte_t pte_mkspecial(pte_t pte)
19544b6dfc5SSteve Capper {
196b6d4f280SLaura Abbott 	return set_pte_bit(pte, __pgprot(PTE_SPECIAL));
19744b6dfc5SSteve Capper }
1984f04d8f0SCatalin Marinas 
1994f04d8f0SCatalin Marinas static inline void set_pte(pte_t *ptep, pte_t pte)
2004f04d8f0SCatalin Marinas {
2014f04d8f0SCatalin Marinas 	*ptep = pte;
2027f0b1bf0SCatalin Marinas 
2037f0b1bf0SCatalin Marinas 	/*
2047f0b1bf0SCatalin Marinas 	 * Only if the new pte is valid and kernel, otherwise TLB maintenance
2057f0b1bf0SCatalin Marinas 	 * or update_mmu_cache() have the necessary barriers.
2067f0b1bf0SCatalin Marinas 	 */
2077f0b1bf0SCatalin Marinas 	if (pte_valid_not_user(pte)) {
2087f0b1bf0SCatalin Marinas 		dsb(ishst);
2097f0b1bf0SCatalin Marinas 		isb();
2107f0b1bf0SCatalin Marinas 	}
2114f04d8f0SCatalin Marinas }
2124f04d8f0SCatalin Marinas 
2134f04d8f0SCatalin Marinas extern void __sync_icache_dcache(pte_t pteval, unsigned long addr);
2144f04d8f0SCatalin Marinas 
2154f04d8f0SCatalin Marinas static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
2164f04d8f0SCatalin Marinas 			      pte_t *ptep, pte_t pte)
2174f04d8f0SCatalin Marinas {
218a6fadf7eSWill Deacon 	if (pte_valid_user(pte)) {
21971fdb6bfSCatalin Marinas 		if (!pte_special(pte) && pte_exec(pte))
2204f04d8f0SCatalin Marinas 			__sync_icache_dcache(pte, addr);
221c2c93e5bSSteve Capper 		if (pte_dirty(pte) && pte_write(pte))
222c2c93e5bSSteve Capper 			pte_val(pte) &= ~PTE_RDONLY;
223c2c93e5bSSteve Capper 		else
224c2c93e5bSSteve Capper 			pte_val(pte) |= PTE_RDONLY;
22502522463SWill Deacon 	}
22602522463SWill Deacon 
2274f04d8f0SCatalin Marinas 	set_pte(ptep, pte);
2284f04d8f0SCatalin Marinas }
2294f04d8f0SCatalin Marinas 
2304f04d8f0SCatalin Marinas /*
2314f04d8f0SCatalin Marinas  * Huge pte definitions.
2324f04d8f0SCatalin Marinas  */
233084bd298SSteve Capper #define pte_huge(pte)		(!(pte_val(pte) & PTE_TABLE_BIT))
234084bd298SSteve Capper #define pte_mkhuge(pte)		(__pte(pte_val(pte) & ~PTE_TABLE_BIT))
235084bd298SSteve Capper 
236084bd298SSteve Capper /*
237084bd298SSteve Capper  * Hugetlb definitions.
238084bd298SSteve Capper  */
239084bd298SSteve Capper #define HUGE_MAX_HSTATE		2
240084bd298SSteve Capper #define HPAGE_SHIFT		PMD_SHIFT
241084bd298SSteve Capper #define HPAGE_SIZE		(_AC(1, UL) << HPAGE_SHIFT)
242084bd298SSteve Capper #define HPAGE_MASK		(~(HPAGE_SIZE - 1))
243084bd298SSteve Capper #define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
2444f04d8f0SCatalin Marinas 
2454f04d8f0SCatalin Marinas #define __HAVE_ARCH_PTE_SPECIAL
2464f04d8f0SCatalin Marinas 
24729e56940SSteve Capper static inline pte_t pud_pte(pud_t pud)
24829e56940SSteve Capper {
24929e56940SSteve Capper 	return __pte(pud_val(pud));
25029e56940SSteve Capper }
25129e56940SSteve Capper 
25229e56940SSteve Capper static inline pmd_t pud_pmd(pud_t pud)
25329e56940SSteve Capper {
25429e56940SSteve Capper 	return __pmd(pud_val(pud));
25529e56940SSteve Capper }
25629e56940SSteve Capper 
2579c7e535fSSteve Capper static inline pte_t pmd_pte(pmd_t pmd)
2589c7e535fSSteve Capper {
2599c7e535fSSteve Capper 	return __pte(pmd_val(pmd));
2609c7e535fSSteve Capper }
261af074848SSteve Capper 
2629c7e535fSSteve Capper static inline pmd_t pte_pmd(pte_t pte)
2639c7e535fSSteve Capper {
2649c7e535fSSteve Capper 	return __pmd(pte_val(pte));
2659c7e535fSSteve Capper }
266af074848SSteve Capper 
267af074848SSteve Capper /*
268af074848SSteve Capper  * THP definitions.
269af074848SSteve Capper  */
270af074848SSteve Capper 
271af074848SSteve Capper #ifdef CONFIG_TRANSPARENT_HUGEPAGE
272af074848SSteve Capper #define pmd_trans_huge(pmd)	(pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT))
2739c7e535fSSteve Capper #define pmd_trans_splitting(pmd)	pte_special(pmd_pte(pmd))
27429e56940SSteve Capper #ifdef CONFIG_HAVE_RCU_TABLE_FREE
27529e56940SSteve Capper #define __HAVE_ARCH_PMDP_SPLITTING_FLUSH
27629e56940SSteve Capper struct vm_area_struct;
27729e56940SSteve Capper void pmdp_splitting_flush(struct vm_area_struct *vma, unsigned long address,
27829e56940SSteve Capper 			  pmd_t *pmdp);
27929e56940SSteve Capper #endif /* CONFIG_HAVE_RCU_TABLE_FREE */
28029e56940SSteve Capper #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
281af074848SSteve Capper 
282c164e038SKirill A. Shutemov #define pmd_dirty(pmd)		pte_dirty(pmd_pte(pmd))
2839c7e535fSSteve Capper #define pmd_young(pmd)		pte_young(pmd_pte(pmd))
2849c7e535fSSteve Capper #define pmd_wrprotect(pmd)	pte_pmd(pte_wrprotect(pmd_pte(pmd)))
2859c7e535fSSteve Capper #define pmd_mksplitting(pmd)	pte_pmd(pte_mkspecial(pmd_pte(pmd)))
2869c7e535fSSteve Capper #define pmd_mkold(pmd)		pte_pmd(pte_mkold(pmd_pte(pmd)))
2879c7e535fSSteve Capper #define pmd_mkwrite(pmd)	pte_pmd(pte_mkwrite(pmd_pte(pmd)))
2889c7e535fSSteve Capper #define pmd_mkdirty(pmd)	pte_pmd(pte_mkdirty(pmd_pte(pmd)))
2899c7e535fSSteve Capper #define pmd_mkyoung(pmd)	pte_pmd(pte_mkyoung(pmd_pte(pmd)))
290e3a920afSWill Deacon #define pmd_mknotpresent(pmd)	(__pmd(pmd_val(pmd) & ~PMD_TYPE_MASK))
291af074848SSteve Capper 
2929c7e535fSSteve Capper #define __HAVE_ARCH_PMD_WRITE
2939c7e535fSSteve Capper #define pmd_write(pmd)		pte_write(pmd_pte(pmd))
294af074848SSteve Capper 
295af074848SSteve Capper #define pmd_mkhuge(pmd)		(__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT))
296af074848SSteve Capper 
297af074848SSteve Capper #define pmd_pfn(pmd)		(((pmd_val(pmd) & PMD_MASK) & PHYS_MASK) >> PAGE_SHIFT)
298af074848SSteve Capper #define pfn_pmd(pfn,prot)	(__pmd(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)))
299af074848SSteve Capper #define mk_pmd(page,prot)	pfn_pmd(page_to_pfn(page),prot)
300af074848SSteve Capper 
30129e56940SSteve Capper #define pud_write(pud)		pte_write(pud_pte(pud))
302206a2a73SSteve Capper #define pud_pfn(pud)		(((pud_val(pud) & PUD_MASK) & PHYS_MASK) >> PAGE_SHIFT)
303af074848SSteve Capper 
304ceb21835SWill Deacon #define set_pmd_at(mm, addr, pmdp, pmd)	set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd))
305af074848SSteve Capper 
306af074848SSteve Capper static inline int has_transparent_hugepage(void)
307af074848SSteve Capper {
308af074848SSteve Capper 	return 1;
309af074848SSteve Capper }
310af074848SSteve Capper 
311a501e324SCatalin Marinas #define __pgprot_modify(prot,mask,bits) \
312a501e324SCatalin Marinas 	__pgprot((pgprot_val(prot) & ~(mask)) | (bits))
313a501e324SCatalin Marinas 
314af074848SSteve Capper /*
3154f04d8f0SCatalin Marinas  * Mark the prot value as uncacheable and unbufferable.
3164f04d8f0SCatalin Marinas  */
3174f04d8f0SCatalin Marinas #define pgprot_noncached(prot) \
318de2db743SCatalin Marinas 	__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE) | PTE_PXN | PTE_UXN)
3194f04d8f0SCatalin Marinas #define pgprot_writecombine(prot) \
320de2db743SCatalin Marinas 	__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC) | PTE_PXN | PTE_UXN)
321d1e6dc91SLiviu Dudau #define pgprot_device(prot) \
322d1e6dc91SLiviu Dudau 	__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRE) | PTE_PXN | PTE_UXN)
3234f04d8f0SCatalin Marinas #define __HAVE_PHYS_MEM_ACCESS_PROT
3244f04d8f0SCatalin Marinas struct file;
3254f04d8f0SCatalin Marinas extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
3264f04d8f0SCatalin Marinas 				     unsigned long size, pgprot_t vma_prot);
3274f04d8f0SCatalin Marinas 
3284f04d8f0SCatalin Marinas #define pmd_none(pmd)		(!pmd_val(pmd))
3294f04d8f0SCatalin Marinas #define pmd_present(pmd)	(pmd_val(pmd))
3304f04d8f0SCatalin Marinas 
3314f04d8f0SCatalin Marinas #define pmd_bad(pmd)		(!(pmd_val(pmd) & 2))
3324f04d8f0SCatalin Marinas 
33336311607SMarc Zyngier #define pmd_table(pmd)		((pmd_val(pmd) & PMD_TYPE_MASK) == \
33436311607SMarc Zyngier 				 PMD_TYPE_TABLE)
33536311607SMarc Zyngier #define pmd_sect(pmd)		((pmd_val(pmd) & PMD_TYPE_MASK) == \
33636311607SMarc Zyngier 				 PMD_TYPE_SECT)
33736311607SMarc Zyngier 
338f3b766a2SSteve Capper #ifdef CONFIG_ARM64_64K_PAGES
339206a2a73SSteve Capper #define pud_sect(pud)		(0)
340206a2a73SSteve Capper #else
341206a2a73SSteve Capper #define pud_sect(pud)		((pud_val(pud) & PUD_TYPE_MASK) == \
342206a2a73SSteve Capper 				 PUD_TYPE_SECT)
343206a2a73SSteve Capper #endif
34436311607SMarc Zyngier 
3454f04d8f0SCatalin Marinas static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
3464f04d8f0SCatalin Marinas {
3474f04d8f0SCatalin Marinas 	*pmdp = pmd;
34898f7685eSWill Deacon 	dsb(ishst);
3497f0b1bf0SCatalin Marinas 	isb();
3504f04d8f0SCatalin Marinas }
3514f04d8f0SCatalin Marinas 
3524f04d8f0SCatalin Marinas static inline void pmd_clear(pmd_t *pmdp)
3534f04d8f0SCatalin Marinas {
3544f04d8f0SCatalin Marinas 	set_pmd(pmdp, __pmd(0));
3554f04d8f0SCatalin Marinas }
3564f04d8f0SCatalin Marinas 
3574f04d8f0SCatalin Marinas static inline pte_t *pmd_page_vaddr(pmd_t pmd)
3584f04d8f0SCatalin Marinas {
3594f04d8f0SCatalin Marinas 	return __va(pmd_val(pmd) & PHYS_MASK & (s32)PAGE_MASK);
3604f04d8f0SCatalin Marinas }
3614f04d8f0SCatalin Marinas 
3624f04d8f0SCatalin Marinas #define pmd_page(pmd)		pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))
3634f04d8f0SCatalin Marinas 
3644f04d8f0SCatalin Marinas /*
3654f04d8f0SCatalin Marinas  * Conversion functions: convert a page and protection to a page entry,
3664f04d8f0SCatalin Marinas  * and a page entry and page directory to the page they refer to.
3674f04d8f0SCatalin Marinas  */
3684f04d8f0SCatalin Marinas #define mk_pte(page,prot)	pfn_pte(page_to_pfn(page),prot)
3694f04d8f0SCatalin Marinas 
370abe669d7SCatalin Marinas #if CONFIG_ARM64_PGTABLE_LEVELS > 2
3714f04d8f0SCatalin Marinas 
3727078db46SCatalin Marinas #define pmd_ERROR(pmd)		__pmd_error(__FILE__, __LINE__, pmd_val(pmd))
3737078db46SCatalin Marinas 
3744f04d8f0SCatalin Marinas #define pud_none(pud)		(!pud_val(pud))
3754f04d8f0SCatalin Marinas #define pud_bad(pud)		(!(pud_val(pud) & 2))
3764f04d8f0SCatalin Marinas #define pud_present(pud)	(pud_val(pud))
3774f04d8f0SCatalin Marinas 
3784f04d8f0SCatalin Marinas static inline void set_pud(pud_t *pudp, pud_t pud)
3794f04d8f0SCatalin Marinas {
3804f04d8f0SCatalin Marinas 	*pudp = pud;
38198f7685eSWill Deacon 	dsb(ishst);
3827f0b1bf0SCatalin Marinas 	isb();
3834f04d8f0SCatalin Marinas }
3844f04d8f0SCatalin Marinas 
3854f04d8f0SCatalin Marinas static inline void pud_clear(pud_t *pudp)
3864f04d8f0SCatalin Marinas {
3874f04d8f0SCatalin Marinas 	set_pud(pudp, __pud(0));
3884f04d8f0SCatalin Marinas }
3894f04d8f0SCatalin Marinas 
3904f04d8f0SCatalin Marinas static inline pmd_t *pud_page_vaddr(pud_t pud)
3914f04d8f0SCatalin Marinas {
3924f04d8f0SCatalin Marinas 	return __va(pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK);
3934f04d8f0SCatalin Marinas }
3944f04d8f0SCatalin Marinas 
3957078db46SCatalin Marinas /* Find an entry in the second-level page table. */
3967078db46SCatalin Marinas #define pmd_index(addr)		(((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
3977078db46SCatalin Marinas 
3987078db46SCatalin Marinas static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
3997078db46SCatalin Marinas {
4007078db46SCatalin Marinas 	return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr);
4017078db46SCatalin Marinas }
4027078db46SCatalin Marinas 
403*5d96e0cbSJungseok Lee #define pud_page(pud)		pfn_to_page(__phys_to_pfn(pud_val(pud) & PHYS_MASK))
40429e56940SSteve Capper 
405abe669d7SCatalin Marinas #endif	/* CONFIG_ARM64_PGTABLE_LEVELS > 2 */
4064f04d8f0SCatalin Marinas 
407abe669d7SCatalin Marinas #if CONFIG_ARM64_PGTABLE_LEVELS > 3
408c79b954bSJungseok Lee 
4097078db46SCatalin Marinas #define pud_ERROR(pud)		__pud_error(__FILE__, __LINE__, pud_val(pud))
4107078db46SCatalin Marinas 
411c79b954bSJungseok Lee #define pgd_none(pgd)		(!pgd_val(pgd))
412c79b954bSJungseok Lee #define pgd_bad(pgd)		(!(pgd_val(pgd) & 2))
413c79b954bSJungseok Lee #define pgd_present(pgd)	(pgd_val(pgd))
414c79b954bSJungseok Lee 
415c79b954bSJungseok Lee static inline void set_pgd(pgd_t *pgdp, pgd_t pgd)
416c79b954bSJungseok Lee {
417c79b954bSJungseok Lee 	*pgdp = pgd;
418c79b954bSJungseok Lee 	dsb(ishst);
419c79b954bSJungseok Lee }
420c79b954bSJungseok Lee 
421c79b954bSJungseok Lee static inline void pgd_clear(pgd_t *pgdp)
422c79b954bSJungseok Lee {
423c79b954bSJungseok Lee 	set_pgd(pgdp, __pgd(0));
424c79b954bSJungseok Lee }
425c79b954bSJungseok Lee 
426c79b954bSJungseok Lee static inline pud_t *pgd_page_vaddr(pgd_t pgd)
427c79b954bSJungseok Lee {
428c79b954bSJungseok Lee 	return __va(pgd_val(pgd) & PHYS_MASK & (s32)PAGE_MASK);
429c79b954bSJungseok Lee }
430c79b954bSJungseok Lee 
4317078db46SCatalin Marinas /* Find an entry in the frst-level page table. */
4327078db46SCatalin Marinas #define pud_index(addr)		(((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))
4337078db46SCatalin Marinas 
4347078db46SCatalin Marinas static inline pud_t *pud_offset(pgd_t *pgd, unsigned long addr)
4357078db46SCatalin Marinas {
4367078db46SCatalin Marinas 	return (pud_t *)pgd_page_vaddr(*pgd) + pud_index(addr);
4377078db46SCatalin Marinas }
4387078db46SCatalin Marinas 
439*5d96e0cbSJungseok Lee #define pgd_page(pgd)		pfn_to_page(__phys_to_pfn(pgd_val(pgd) & PHYS_MASK))
440*5d96e0cbSJungseok Lee 
441abe669d7SCatalin Marinas #endif  /* CONFIG_ARM64_PGTABLE_LEVELS > 3 */
442c79b954bSJungseok Lee 
4437078db46SCatalin Marinas #define pgd_ERROR(pgd)		__pgd_error(__FILE__, __LINE__, pgd_val(pgd))
4447078db46SCatalin Marinas 
4454f04d8f0SCatalin Marinas /* to find an entry in a page-table-directory */
4464f04d8f0SCatalin Marinas #define pgd_index(addr)		(((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
4474f04d8f0SCatalin Marinas 
4484f04d8f0SCatalin Marinas #define pgd_offset(mm, addr)	((mm)->pgd+pgd_index(addr))
4494f04d8f0SCatalin Marinas 
4504f04d8f0SCatalin Marinas /* to find an entry in a kernel page-table-directory */
4514f04d8f0SCatalin Marinas #define pgd_offset_k(addr)	pgd_offset(&init_mm, addr)
4524f04d8f0SCatalin Marinas 
4534f04d8f0SCatalin Marinas static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
4544f04d8f0SCatalin Marinas {
455a6fadf7eSWill Deacon 	const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY |
456c2c93e5bSSteve Capper 			      PTE_PROT_NONE | PTE_VALID | PTE_WRITE;
4574f04d8f0SCatalin Marinas 	pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
4584f04d8f0SCatalin Marinas 	return pte;
4594f04d8f0SCatalin Marinas }
4604f04d8f0SCatalin Marinas 
4619c7e535fSSteve Capper static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
4629c7e535fSSteve Capper {
4639c7e535fSSteve Capper 	return pte_pmd(pte_modify(pmd_pte(pmd), newprot));
4649c7e535fSSteve Capper }
4659c7e535fSSteve Capper 
4664f04d8f0SCatalin Marinas extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
4674f04d8f0SCatalin Marinas extern pgd_t idmap_pg_dir[PTRS_PER_PGD];
4684f04d8f0SCatalin Marinas 
4694f04d8f0SCatalin Marinas /*
4704f04d8f0SCatalin Marinas  * Encode and decode a swap entry:
4713676f9efSCatalin Marinas  *	bits 0-1:	present (must be zero)
4723676f9efSCatalin Marinas  *	bit  2:		PTE_FILE
4733676f9efSCatalin Marinas  *	bits 3-8:	swap type
4743676f9efSCatalin Marinas  *	bits 9-57:	swap offset
4754f04d8f0SCatalin Marinas  */
4763676f9efSCatalin Marinas #define __SWP_TYPE_SHIFT	3
4774f04d8f0SCatalin Marinas #define __SWP_TYPE_BITS		6
4783676f9efSCatalin Marinas #define __SWP_OFFSET_BITS	49
4794f04d8f0SCatalin Marinas #define __SWP_TYPE_MASK		((1 << __SWP_TYPE_BITS) - 1)
4804f04d8f0SCatalin Marinas #define __SWP_OFFSET_SHIFT	(__SWP_TYPE_BITS + __SWP_TYPE_SHIFT)
4813676f9efSCatalin Marinas #define __SWP_OFFSET_MASK	((1UL << __SWP_OFFSET_BITS) - 1)
4824f04d8f0SCatalin Marinas 
4834f04d8f0SCatalin Marinas #define __swp_type(x)		(((x).val >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK)
4843676f9efSCatalin Marinas #define __swp_offset(x)		(((x).val >> __SWP_OFFSET_SHIFT) & __SWP_OFFSET_MASK)
4854f04d8f0SCatalin Marinas #define __swp_entry(type,offset) ((swp_entry_t) { ((type) << __SWP_TYPE_SHIFT) | ((offset) << __SWP_OFFSET_SHIFT) })
4864f04d8f0SCatalin Marinas 
4874f04d8f0SCatalin Marinas #define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
4884f04d8f0SCatalin Marinas #define __swp_entry_to_pte(swp)	((pte_t) { (swp).val })
4894f04d8f0SCatalin Marinas 
4904f04d8f0SCatalin Marinas /*
4914f04d8f0SCatalin Marinas  * Ensure that there are not more swap files than can be encoded in the kernel
492aad9061bSGeert Uytterhoeven  * PTEs.
4934f04d8f0SCatalin Marinas  */
4944f04d8f0SCatalin Marinas #define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > __SWP_TYPE_BITS)
4954f04d8f0SCatalin Marinas 
4964f04d8f0SCatalin Marinas /*
4974f04d8f0SCatalin Marinas  * Encode and decode a file entry:
4983676f9efSCatalin Marinas  *	bits 0-1:	present (must be zero)
4993676f9efSCatalin Marinas  *	bit  2:		PTE_FILE
5003676f9efSCatalin Marinas  *	bits 3-57:	file offset / PAGE_SIZE
5014f04d8f0SCatalin Marinas  */
5024f04d8f0SCatalin Marinas #define pte_file(pte)		(pte_val(pte) & PTE_FILE)
5033676f9efSCatalin Marinas #define pte_to_pgoff(x)		(pte_val(x) >> 3)
5043676f9efSCatalin Marinas #define pgoff_to_pte(x)		__pte(((x) << 3) | PTE_FILE)
5054f04d8f0SCatalin Marinas 
5063676f9efSCatalin Marinas #define PTE_FILE_MAX_BITS	55
5074f04d8f0SCatalin Marinas 
5084f04d8f0SCatalin Marinas extern int kern_addr_valid(unsigned long addr);
5094f04d8f0SCatalin Marinas 
5104f04d8f0SCatalin Marinas #include <asm-generic/pgtable.h>
5114f04d8f0SCatalin Marinas 
5124f04d8f0SCatalin Marinas #define pgtable_cache_init() do { } while (0)
5134f04d8f0SCatalin Marinas 
5144f04d8f0SCatalin Marinas #endif /* !__ASSEMBLY__ */
5154f04d8f0SCatalin Marinas 
5164f04d8f0SCatalin Marinas #endif /* __ASM_PGTABLE_H */
517