xref: /linux/arch/arm64/include/asm/pgtable.h (revision d1e6dc91b532d3d3dbbd0fa356b775ca320dc2c2)
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)
8236311607SMarc Zyngier #define PAGE_S2_DEVICE		__pgprot(PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_DEVICE_nGnRE) | PTE_S2_RDWR | 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 
15244b6dfc5SSteve Capper static inline pte_t pte_wrprotect(pte_t pte)
15344b6dfc5SSteve Capper {
154c2c93e5bSSteve Capper 	pte_val(pte) &= ~PTE_WRITE;
15544b6dfc5SSteve Capper 	return pte;
15644b6dfc5SSteve Capper }
1574f04d8f0SCatalin Marinas 
15844b6dfc5SSteve Capper static inline pte_t pte_mkwrite(pte_t pte)
15944b6dfc5SSteve Capper {
160c2c93e5bSSteve Capper 	pte_val(pte) |= PTE_WRITE;
16144b6dfc5SSteve Capper 	return pte;
16244b6dfc5SSteve Capper }
16344b6dfc5SSteve Capper 
16444b6dfc5SSteve Capper static inline pte_t pte_mkclean(pte_t pte)
16544b6dfc5SSteve Capper {
16644b6dfc5SSteve Capper 	pte_val(pte) &= ~PTE_DIRTY;
16744b6dfc5SSteve Capper 	return pte;
16844b6dfc5SSteve Capper }
16944b6dfc5SSteve Capper 
17044b6dfc5SSteve Capper static inline pte_t pte_mkdirty(pte_t pte)
17144b6dfc5SSteve Capper {
17244b6dfc5SSteve Capper 	pte_val(pte) |= PTE_DIRTY;
17344b6dfc5SSteve Capper 	return pte;
17444b6dfc5SSteve Capper }
17544b6dfc5SSteve Capper 
17644b6dfc5SSteve Capper static inline pte_t pte_mkold(pte_t pte)
17744b6dfc5SSteve Capper {
17844b6dfc5SSteve Capper 	pte_val(pte) &= ~PTE_AF;
17944b6dfc5SSteve Capper 	return pte;
18044b6dfc5SSteve Capper }
18144b6dfc5SSteve Capper 
18244b6dfc5SSteve Capper static inline pte_t pte_mkyoung(pte_t pte)
18344b6dfc5SSteve Capper {
18444b6dfc5SSteve Capper 	pte_val(pte) |= PTE_AF;
18544b6dfc5SSteve Capper 	return pte;
18644b6dfc5SSteve Capper }
18744b6dfc5SSteve Capper 
18844b6dfc5SSteve Capper static inline pte_t pte_mkspecial(pte_t pte)
18944b6dfc5SSteve Capper {
19044b6dfc5SSteve Capper 	pte_val(pte) |= PTE_SPECIAL;
19144b6dfc5SSteve Capper 	return pte;
19244b6dfc5SSteve Capper }
1934f04d8f0SCatalin Marinas 
1944f04d8f0SCatalin Marinas static inline void set_pte(pte_t *ptep, pte_t pte)
1954f04d8f0SCatalin Marinas {
1964f04d8f0SCatalin Marinas 	*ptep = pte;
1977f0b1bf0SCatalin Marinas 
1987f0b1bf0SCatalin Marinas 	/*
1997f0b1bf0SCatalin Marinas 	 * Only if the new pte is valid and kernel, otherwise TLB maintenance
2007f0b1bf0SCatalin Marinas 	 * or update_mmu_cache() have the necessary barriers.
2017f0b1bf0SCatalin Marinas 	 */
2027f0b1bf0SCatalin Marinas 	if (pte_valid_not_user(pte)) {
2037f0b1bf0SCatalin Marinas 		dsb(ishst);
2047f0b1bf0SCatalin Marinas 		isb();
2057f0b1bf0SCatalin Marinas 	}
2064f04d8f0SCatalin Marinas }
2074f04d8f0SCatalin Marinas 
2084f04d8f0SCatalin Marinas extern void __sync_icache_dcache(pte_t pteval, unsigned long addr);
2094f04d8f0SCatalin Marinas 
2104f04d8f0SCatalin Marinas static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
2114f04d8f0SCatalin Marinas 			      pte_t *ptep, pte_t pte)
2124f04d8f0SCatalin Marinas {
213a6fadf7eSWill Deacon 	if (pte_valid_user(pte)) {
21471fdb6bfSCatalin Marinas 		if (!pte_special(pte) && pte_exec(pte))
2154f04d8f0SCatalin Marinas 			__sync_icache_dcache(pte, addr);
216c2c93e5bSSteve Capper 		if (pte_dirty(pte) && pte_write(pte))
217c2c93e5bSSteve Capper 			pte_val(pte) &= ~PTE_RDONLY;
218c2c93e5bSSteve Capper 		else
219c2c93e5bSSteve Capper 			pte_val(pte) |= PTE_RDONLY;
22002522463SWill Deacon 	}
22102522463SWill Deacon 
2224f04d8f0SCatalin Marinas 	set_pte(ptep, pte);
2234f04d8f0SCatalin Marinas }
2244f04d8f0SCatalin Marinas 
2254f04d8f0SCatalin Marinas /*
2264f04d8f0SCatalin Marinas  * Huge pte definitions.
2274f04d8f0SCatalin Marinas  */
228084bd298SSteve Capper #define pte_huge(pte)		(!(pte_val(pte) & PTE_TABLE_BIT))
229084bd298SSteve Capper #define pte_mkhuge(pte)		(__pte(pte_val(pte) & ~PTE_TABLE_BIT))
230084bd298SSteve Capper 
231084bd298SSteve Capper /*
232084bd298SSteve Capper  * Hugetlb definitions.
233084bd298SSteve Capper  */
234084bd298SSteve Capper #define HUGE_MAX_HSTATE		2
235084bd298SSteve Capper #define HPAGE_SHIFT		PMD_SHIFT
236084bd298SSteve Capper #define HPAGE_SIZE		(_AC(1, UL) << HPAGE_SHIFT)
237084bd298SSteve Capper #define HPAGE_MASK		(~(HPAGE_SIZE - 1))
238084bd298SSteve Capper #define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
2394f04d8f0SCatalin Marinas 
2404f04d8f0SCatalin Marinas #define __HAVE_ARCH_PTE_SPECIAL
2414f04d8f0SCatalin Marinas 
2429c7e535fSSteve Capper static inline pte_t pmd_pte(pmd_t pmd)
2439c7e535fSSteve Capper {
2449c7e535fSSteve Capper 	return __pte(pmd_val(pmd));
2459c7e535fSSteve Capper }
246af074848SSteve Capper 
2479c7e535fSSteve Capper static inline pmd_t pte_pmd(pte_t pte)
2489c7e535fSSteve Capper {
2499c7e535fSSteve Capper 	return __pmd(pte_val(pte));
2509c7e535fSSteve Capper }
251af074848SSteve Capper 
252af074848SSteve Capper /*
253af074848SSteve Capper  * THP definitions.
254af074848SSteve Capper  */
255af074848SSteve Capper 
256af074848SSteve Capper #ifdef CONFIG_TRANSPARENT_HUGEPAGE
257af074848SSteve Capper #define pmd_trans_huge(pmd)	(pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT))
2589c7e535fSSteve Capper #define pmd_trans_splitting(pmd)	pte_special(pmd_pte(pmd))
259af074848SSteve Capper #endif
260af074848SSteve Capper 
2619c7e535fSSteve Capper #define pmd_young(pmd)		pte_young(pmd_pte(pmd))
2629c7e535fSSteve Capper #define pmd_wrprotect(pmd)	pte_pmd(pte_wrprotect(pmd_pte(pmd)))
2639c7e535fSSteve Capper #define pmd_mksplitting(pmd)	pte_pmd(pte_mkspecial(pmd_pte(pmd)))
2649c7e535fSSteve Capper #define pmd_mkold(pmd)		pte_pmd(pte_mkold(pmd_pte(pmd)))
2659c7e535fSSteve Capper #define pmd_mkwrite(pmd)	pte_pmd(pte_mkwrite(pmd_pte(pmd)))
2669c7e535fSSteve Capper #define pmd_mkdirty(pmd)	pte_pmd(pte_mkdirty(pmd_pte(pmd)))
2679c7e535fSSteve Capper #define pmd_mkyoung(pmd)	pte_pmd(pte_mkyoung(pmd_pte(pmd)))
268e3a920afSWill Deacon #define pmd_mknotpresent(pmd)	(__pmd(pmd_val(pmd) & ~PMD_TYPE_MASK))
269af074848SSteve Capper 
2709c7e535fSSteve Capper #define __HAVE_ARCH_PMD_WRITE
2719c7e535fSSteve Capper #define pmd_write(pmd)		pte_write(pmd_pte(pmd))
272af074848SSteve Capper 
273af074848SSteve Capper #define pmd_mkhuge(pmd)		(__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT))
274af074848SSteve Capper 
275af074848SSteve Capper #define pmd_pfn(pmd)		(((pmd_val(pmd) & PMD_MASK) & PHYS_MASK) >> PAGE_SHIFT)
276af074848SSteve Capper #define pfn_pmd(pfn,prot)	(__pmd(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)))
277af074848SSteve Capper #define mk_pmd(page,prot)	pfn_pmd(page_to_pfn(page),prot)
278af074848SSteve Capper 
279af074848SSteve Capper #define pmd_page(pmd)           pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))
280206a2a73SSteve Capper #define pud_pfn(pud)		(((pud_val(pud) & PUD_MASK) & PHYS_MASK) >> PAGE_SHIFT)
281af074848SSteve Capper 
282ceb21835SWill Deacon #define set_pmd_at(mm, addr, pmdp, pmd)	set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd))
283af074848SSteve Capper 
284af074848SSteve Capper static inline int has_transparent_hugepage(void)
285af074848SSteve Capper {
286af074848SSteve Capper 	return 1;
287af074848SSteve Capper }
288af074848SSteve Capper 
289a501e324SCatalin Marinas #define __pgprot_modify(prot,mask,bits) \
290a501e324SCatalin Marinas 	__pgprot((pgprot_val(prot) & ~(mask)) | (bits))
291a501e324SCatalin Marinas 
292af074848SSteve Capper /*
2934f04d8f0SCatalin Marinas  * Mark the prot value as uncacheable and unbufferable.
2944f04d8f0SCatalin Marinas  */
2954f04d8f0SCatalin Marinas #define pgprot_noncached(prot) \
296de2db743SCatalin Marinas 	__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE) | PTE_PXN | PTE_UXN)
2974f04d8f0SCatalin Marinas #define pgprot_writecombine(prot) \
298de2db743SCatalin Marinas 	__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC) | PTE_PXN | PTE_UXN)
299*d1e6dc91SLiviu Dudau #define pgprot_device(prot) \
300*d1e6dc91SLiviu Dudau 	__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRE) | PTE_PXN | PTE_UXN)
3014f04d8f0SCatalin Marinas #define __HAVE_PHYS_MEM_ACCESS_PROT
3024f04d8f0SCatalin Marinas struct file;
3034f04d8f0SCatalin Marinas extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
3044f04d8f0SCatalin Marinas 				     unsigned long size, pgprot_t vma_prot);
3054f04d8f0SCatalin Marinas 
3064f04d8f0SCatalin Marinas #define pmd_none(pmd)		(!pmd_val(pmd))
3074f04d8f0SCatalin Marinas #define pmd_present(pmd)	(pmd_val(pmd))
3084f04d8f0SCatalin Marinas 
3094f04d8f0SCatalin Marinas #define pmd_bad(pmd)		(!(pmd_val(pmd) & 2))
3104f04d8f0SCatalin Marinas 
31136311607SMarc Zyngier #define pmd_table(pmd)		((pmd_val(pmd) & PMD_TYPE_MASK) == \
31236311607SMarc Zyngier 				 PMD_TYPE_TABLE)
31336311607SMarc Zyngier #define pmd_sect(pmd)		((pmd_val(pmd) & PMD_TYPE_MASK) == \
31436311607SMarc Zyngier 				 PMD_TYPE_SECT)
31536311607SMarc Zyngier 
316f3b766a2SSteve Capper #ifdef CONFIG_ARM64_64K_PAGES
317206a2a73SSteve Capper #define pud_sect(pud)		(0)
318206a2a73SSteve Capper #else
319206a2a73SSteve Capper #define pud_sect(pud)		((pud_val(pud) & PUD_TYPE_MASK) == \
320206a2a73SSteve Capper 				 PUD_TYPE_SECT)
321206a2a73SSteve Capper #endif
32236311607SMarc Zyngier 
3234f04d8f0SCatalin Marinas static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
3244f04d8f0SCatalin Marinas {
3254f04d8f0SCatalin Marinas 	*pmdp = pmd;
32698f7685eSWill Deacon 	dsb(ishst);
3277f0b1bf0SCatalin Marinas 	isb();
3284f04d8f0SCatalin Marinas }
3294f04d8f0SCatalin Marinas 
3304f04d8f0SCatalin Marinas static inline void pmd_clear(pmd_t *pmdp)
3314f04d8f0SCatalin Marinas {
3324f04d8f0SCatalin Marinas 	set_pmd(pmdp, __pmd(0));
3334f04d8f0SCatalin Marinas }
3344f04d8f0SCatalin Marinas 
3354f04d8f0SCatalin Marinas static inline pte_t *pmd_page_vaddr(pmd_t pmd)
3364f04d8f0SCatalin Marinas {
3374f04d8f0SCatalin Marinas 	return __va(pmd_val(pmd) & PHYS_MASK & (s32)PAGE_MASK);
3384f04d8f0SCatalin Marinas }
3394f04d8f0SCatalin Marinas 
3404f04d8f0SCatalin Marinas #define pmd_page(pmd)		pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))
3414f04d8f0SCatalin Marinas 
3424f04d8f0SCatalin Marinas /*
3434f04d8f0SCatalin Marinas  * Conversion functions: convert a page and protection to a page entry,
3444f04d8f0SCatalin Marinas  * and a page entry and page directory to the page they refer to.
3454f04d8f0SCatalin Marinas  */
3464f04d8f0SCatalin Marinas #define mk_pte(page,prot)	pfn_pte(page_to_pfn(page),prot)
3474f04d8f0SCatalin Marinas 
348abe669d7SCatalin Marinas #if CONFIG_ARM64_PGTABLE_LEVELS > 2
3494f04d8f0SCatalin Marinas 
3507078db46SCatalin Marinas #define pmd_ERROR(pmd)		__pmd_error(__FILE__, __LINE__, pmd_val(pmd))
3517078db46SCatalin Marinas 
3524f04d8f0SCatalin Marinas #define pud_none(pud)		(!pud_val(pud))
3534f04d8f0SCatalin Marinas #define pud_bad(pud)		(!(pud_val(pud) & 2))
3544f04d8f0SCatalin Marinas #define pud_present(pud)	(pud_val(pud))
3554f04d8f0SCatalin Marinas 
3564f04d8f0SCatalin Marinas static inline void set_pud(pud_t *pudp, pud_t pud)
3574f04d8f0SCatalin Marinas {
3584f04d8f0SCatalin Marinas 	*pudp = pud;
35998f7685eSWill Deacon 	dsb(ishst);
3607f0b1bf0SCatalin Marinas 	isb();
3614f04d8f0SCatalin Marinas }
3624f04d8f0SCatalin Marinas 
3634f04d8f0SCatalin Marinas static inline void pud_clear(pud_t *pudp)
3644f04d8f0SCatalin Marinas {
3654f04d8f0SCatalin Marinas 	set_pud(pudp, __pud(0));
3664f04d8f0SCatalin Marinas }
3674f04d8f0SCatalin Marinas 
3684f04d8f0SCatalin Marinas static inline pmd_t *pud_page_vaddr(pud_t pud)
3694f04d8f0SCatalin Marinas {
3704f04d8f0SCatalin Marinas 	return __va(pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK);
3714f04d8f0SCatalin Marinas }
3724f04d8f0SCatalin Marinas 
3737078db46SCatalin Marinas /* Find an entry in the second-level page table. */
3747078db46SCatalin Marinas #define pmd_index(addr)		(((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
3757078db46SCatalin Marinas 
3767078db46SCatalin Marinas static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
3777078db46SCatalin Marinas {
3787078db46SCatalin Marinas 	return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr);
3797078db46SCatalin Marinas }
3807078db46SCatalin Marinas 
381abe669d7SCatalin Marinas #endif	/* CONFIG_ARM64_PGTABLE_LEVELS > 2 */
3824f04d8f0SCatalin Marinas 
383abe669d7SCatalin Marinas #if CONFIG_ARM64_PGTABLE_LEVELS > 3
384c79b954bSJungseok Lee 
3857078db46SCatalin Marinas #define pud_ERROR(pud)		__pud_error(__FILE__, __LINE__, pud_val(pud))
3867078db46SCatalin Marinas 
387c79b954bSJungseok Lee #define pgd_none(pgd)		(!pgd_val(pgd))
388c79b954bSJungseok Lee #define pgd_bad(pgd)		(!(pgd_val(pgd) & 2))
389c79b954bSJungseok Lee #define pgd_present(pgd)	(pgd_val(pgd))
390c79b954bSJungseok Lee 
391c79b954bSJungseok Lee static inline void set_pgd(pgd_t *pgdp, pgd_t pgd)
392c79b954bSJungseok Lee {
393c79b954bSJungseok Lee 	*pgdp = pgd;
394c79b954bSJungseok Lee 	dsb(ishst);
395c79b954bSJungseok Lee }
396c79b954bSJungseok Lee 
397c79b954bSJungseok Lee static inline void pgd_clear(pgd_t *pgdp)
398c79b954bSJungseok Lee {
399c79b954bSJungseok Lee 	set_pgd(pgdp, __pgd(0));
400c79b954bSJungseok Lee }
401c79b954bSJungseok Lee 
402c79b954bSJungseok Lee static inline pud_t *pgd_page_vaddr(pgd_t pgd)
403c79b954bSJungseok Lee {
404c79b954bSJungseok Lee 	return __va(pgd_val(pgd) & PHYS_MASK & (s32)PAGE_MASK);
405c79b954bSJungseok Lee }
406c79b954bSJungseok Lee 
4077078db46SCatalin Marinas /* Find an entry in the frst-level page table. */
4087078db46SCatalin Marinas #define pud_index(addr)		(((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))
4097078db46SCatalin Marinas 
4107078db46SCatalin Marinas static inline pud_t *pud_offset(pgd_t *pgd, unsigned long addr)
4117078db46SCatalin Marinas {
4127078db46SCatalin Marinas 	return (pud_t *)pgd_page_vaddr(*pgd) + pud_index(addr);
4137078db46SCatalin Marinas }
4147078db46SCatalin Marinas 
415abe669d7SCatalin Marinas #endif  /* CONFIG_ARM64_PGTABLE_LEVELS > 3 */
416c79b954bSJungseok Lee 
4177078db46SCatalin Marinas #define pgd_ERROR(pgd)		__pgd_error(__FILE__, __LINE__, pgd_val(pgd))
4187078db46SCatalin Marinas 
4194f04d8f0SCatalin Marinas /* to find an entry in a page-table-directory */
4204f04d8f0SCatalin Marinas #define pgd_index(addr)		(((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
4214f04d8f0SCatalin Marinas 
4224f04d8f0SCatalin Marinas #define pgd_offset(mm, addr)	((mm)->pgd+pgd_index(addr))
4234f04d8f0SCatalin Marinas 
4244f04d8f0SCatalin Marinas /* to find an entry in a kernel page-table-directory */
4254f04d8f0SCatalin Marinas #define pgd_offset_k(addr)	pgd_offset(&init_mm, addr)
4264f04d8f0SCatalin Marinas 
4274f04d8f0SCatalin Marinas static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
4284f04d8f0SCatalin Marinas {
429a6fadf7eSWill Deacon 	const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY |
430c2c93e5bSSteve Capper 			      PTE_PROT_NONE | PTE_VALID | PTE_WRITE;
4314f04d8f0SCatalin Marinas 	pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
4324f04d8f0SCatalin Marinas 	return pte;
4334f04d8f0SCatalin Marinas }
4344f04d8f0SCatalin Marinas 
4359c7e535fSSteve Capper static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
4369c7e535fSSteve Capper {
4379c7e535fSSteve Capper 	return pte_pmd(pte_modify(pmd_pte(pmd), newprot));
4389c7e535fSSteve Capper }
4399c7e535fSSteve Capper 
4404f04d8f0SCatalin Marinas extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
4414f04d8f0SCatalin Marinas extern pgd_t idmap_pg_dir[PTRS_PER_PGD];
4424f04d8f0SCatalin Marinas 
4434f04d8f0SCatalin Marinas /*
4444f04d8f0SCatalin Marinas  * Encode and decode a swap entry:
4453676f9efSCatalin Marinas  *	bits 0-1:	present (must be zero)
4463676f9efSCatalin Marinas  *	bit  2:		PTE_FILE
4473676f9efSCatalin Marinas  *	bits 3-8:	swap type
4483676f9efSCatalin Marinas  *	bits 9-57:	swap offset
4494f04d8f0SCatalin Marinas  */
4503676f9efSCatalin Marinas #define __SWP_TYPE_SHIFT	3
4514f04d8f0SCatalin Marinas #define __SWP_TYPE_BITS		6
4523676f9efSCatalin Marinas #define __SWP_OFFSET_BITS	49
4534f04d8f0SCatalin Marinas #define __SWP_TYPE_MASK		((1 << __SWP_TYPE_BITS) - 1)
4544f04d8f0SCatalin Marinas #define __SWP_OFFSET_SHIFT	(__SWP_TYPE_BITS + __SWP_TYPE_SHIFT)
4553676f9efSCatalin Marinas #define __SWP_OFFSET_MASK	((1UL << __SWP_OFFSET_BITS) - 1)
4564f04d8f0SCatalin Marinas 
4574f04d8f0SCatalin Marinas #define __swp_type(x)		(((x).val >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK)
4583676f9efSCatalin Marinas #define __swp_offset(x)		(((x).val >> __SWP_OFFSET_SHIFT) & __SWP_OFFSET_MASK)
4594f04d8f0SCatalin Marinas #define __swp_entry(type,offset) ((swp_entry_t) { ((type) << __SWP_TYPE_SHIFT) | ((offset) << __SWP_OFFSET_SHIFT) })
4604f04d8f0SCatalin Marinas 
4614f04d8f0SCatalin Marinas #define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
4624f04d8f0SCatalin Marinas #define __swp_entry_to_pte(swp)	((pte_t) { (swp).val })
4634f04d8f0SCatalin Marinas 
4644f04d8f0SCatalin Marinas /*
4654f04d8f0SCatalin Marinas  * Ensure that there are not more swap files than can be encoded in the kernel
466aad9061bSGeert Uytterhoeven  * PTEs.
4674f04d8f0SCatalin Marinas  */
4684f04d8f0SCatalin Marinas #define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > __SWP_TYPE_BITS)
4694f04d8f0SCatalin Marinas 
4704f04d8f0SCatalin Marinas /*
4714f04d8f0SCatalin Marinas  * Encode and decode a file entry:
4723676f9efSCatalin Marinas  *	bits 0-1:	present (must be zero)
4733676f9efSCatalin Marinas  *	bit  2:		PTE_FILE
4743676f9efSCatalin Marinas  *	bits 3-57:	file offset / PAGE_SIZE
4754f04d8f0SCatalin Marinas  */
4764f04d8f0SCatalin Marinas #define pte_file(pte)		(pte_val(pte) & PTE_FILE)
4773676f9efSCatalin Marinas #define pte_to_pgoff(x)		(pte_val(x) >> 3)
4783676f9efSCatalin Marinas #define pgoff_to_pte(x)		__pte(((x) << 3) | PTE_FILE)
4794f04d8f0SCatalin Marinas 
4803676f9efSCatalin Marinas #define PTE_FILE_MAX_BITS	55
4814f04d8f0SCatalin Marinas 
4824f04d8f0SCatalin Marinas extern int kern_addr_valid(unsigned long addr);
4834f04d8f0SCatalin Marinas 
4844f04d8f0SCatalin Marinas #include <asm-generic/pgtable.h>
4854f04d8f0SCatalin Marinas 
4864f04d8f0SCatalin Marinas #define pgtable_cache_init() do { } while (0)
4874f04d8f0SCatalin Marinas 
4884f04d8f0SCatalin Marinas #endif /* !__ASSEMBLY__ */
4894f04d8f0SCatalin Marinas 
4904f04d8f0SCatalin Marinas #endif /* __ASM_PGTABLE_H */
491