xref: /linux/arch/arm64/include/asm/pgtable.h (revision f3b766a26dd490026b9eb91a9136ade9f49fc674)
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.
364f04d8f0SCatalin Marinas  */
37847264fbSCatalin Marinas #define VMALLOC_START		(UL(0xffffffffffffffff) << VA_BITS)
384f04d8f0SCatalin Marinas #define VMALLOC_END		(PAGE_OFFSET - UL(0x400000000) - SZ_64K)
394f04d8f0SCatalin Marinas 
404f04d8f0SCatalin Marinas #define vmemmap			((struct page *)(VMALLOC_END + SZ_64K))
414f04d8f0SCatalin Marinas 
424f04d8f0SCatalin Marinas #define FIRST_USER_ADDRESS	0
434f04d8f0SCatalin Marinas 
444f04d8f0SCatalin Marinas #ifndef __ASSEMBLY__
454f04d8f0SCatalin Marinas extern void __pte_error(const char *file, int line, unsigned long val);
464f04d8f0SCatalin Marinas extern void __pmd_error(const char *file, int line, unsigned long val);
474f04d8f0SCatalin Marinas extern void __pgd_error(const char *file, int line, unsigned long val);
484f04d8f0SCatalin Marinas 
494f04d8f0SCatalin Marinas #define pte_ERROR(pte)		__pte_error(__FILE__, __LINE__, pte_val(pte))
504f04d8f0SCatalin Marinas #ifndef CONFIG_ARM64_64K_PAGES
514f04d8f0SCatalin Marinas #define pmd_ERROR(pmd)		__pmd_error(__FILE__, __LINE__, pmd_val(pmd))
524f04d8f0SCatalin Marinas #endif
534f04d8f0SCatalin Marinas #define pgd_ERROR(pgd)		__pgd_error(__FILE__, __LINE__, pgd_val(pgd))
544f04d8f0SCatalin Marinas 
55a501e324SCatalin Marinas #ifdef CONFIG_SMP
56a501e324SCatalin Marinas #define PROT_DEFAULT		(PTE_TYPE_PAGE | PTE_AF | PTE_SHARED)
57a501e324SCatalin Marinas #define PROT_SECT_DEFAULT	(PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S)
58a501e324SCatalin Marinas #else
59a501e324SCatalin Marinas #define PROT_DEFAULT		(PTE_TYPE_PAGE | PTE_AF)
60a501e324SCatalin Marinas #define PROT_SECT_DEFAULT	(PMD_TYPE_SECT | PMD_SECT_AF)
61a501e324SCatalin Marinas #endif
624f04d8f0SCatalin Marinas 
63a501e324SCatalin Marinas #define PROT_DEVICE_nGnRE	(PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE))
64a501e324SCatalin Marinas #define PROT_NORMAL_NC		(PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_NORMAL_NC))
65a501e324SCatalin Marinas #define PROT_NORMAL		(PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_NORMAL))
664f04d8f0SCatalin Marinas 
67a501e324SCatalin Marinas #define PROT_SECT_DEVICE_nGnRE	(PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_DEVICE_nGnRE))
68a501e324SCatalin Marinas #define PROT_SECT_NORMAL	(PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL))
69a501e324SCatalin Marinas #define PROT_SECT_NORMAL_EXEC	(PROT_SECT_DEFAULT | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL))
704f04d8f0SCatalin Marinas 
71a501e324SCatalin Marinas #define _PAGE_DEFAULT		(PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL))
72a6fadf7eSWill Deacon 
73a501e324SCatalin Marinas #define PAGE_KERNEL		__pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE)
74a501e324SCatalin Marinas #define PAGE_KERNEL_EXEC	__pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE)
754f04d8f0SCatalin Marinas 
76a501e324SCatalin Marinas #define PAGE_HYP		__pgprot(_PAGE_DEFAULT | PTE_HYP)
7736311607SMarc Zyngier #define PAGE_HYP_DEVICE		__pgprot(PROT_DEVICE_nGnRE | PTE_HYP)
7836311607SMarc Zyngier 
79a501e324SCatalin Marinas #define PAGE_S2			__pgprot(PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_NORMAL) | PTE_S2_RDONLY)
8036311607SMarc Zyngier #define PAGE_S2_DEVICE		__pgprot(PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_DEVICE_nGnRE) | PTE_S2_RDWR | PTE_UXN)
8136311607SMarc Zyngier 
82a501e324SCatalin Marinas #define PAGE_NONE		__pgprot(((_PAGE_DEFAULT) & ~PTE_TYPE_MASK) | PTE_PROT_NONE | PTE_PXN | PTE_UXN)
83a501e324SCatalin Marinas #define PAGE_SHARED		__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE)
84a501e324SCatalin Marinas #define PAGE_SHARED_EXEC	__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_WRITE)
85a501e324SCatalin Marinas #define PAGE_COPY		__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
86a501e324SCatalin Marinas #define PAGE_COPY_EXEC		__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN)
87a501e324SCatalin Marinas #define PAGE_READONLY		__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
88a501e324SCatalin Marinas #define PAGE_READONLY_EXEC	__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN)
894f04d8f0SCatalin Marinas 
90a501e324SCatalin Marinas #define __P000  PAGE_NONE
91a501e324SCatalin Marinas #define __P001  PAGE_READONLY
92a501e324SCatalin Marinas #define __P010  PAGE_COPY
93a501e324SCatalin Marinas #define __P011  PAGE_COPY
945a0fdfadSCatalin Marinas #define __P100  PAGE_READONLY_EXEC
95a501e324SCatalin Marinas #define __P101  PAGE_READONLY_EXEC
96a501e324SCatalin Marinas #define __P110  PAGE_COPY_EXEC
97a501e324SCatalin Marinas #define __P111  PAGE_COPY_EXEC
984f04d8f0SCatalin Marinas 
99a501e324SCatalin Marinas #define __S000  PAGE_NONE
100a501e324SCatalin Marinas #define __S001  PAGE_READONLY
101a501e324SCatalin Marinas #define __S010  PAGE_SHARED
102a501e324SCatalin Marinas #define __S011  PAGE_SHARED
1035a0fdfadSCatalin Marinas #define __S100  PAGE_READONLY_EXEC
104a501e324SCatalin Marinas #define __S101  PAGE_READONLY_EXEC
105a501e324SCatalin Marinas #define __S110  PAGE_SHARED_EXEC
106a501e324SCatalin Marinas #define __S111  PAGE_SHARED_EXEC
1074f04d8f0SCatalin Marinas 
1084f04d8f0SCatalin Marinas /*
1094f04d8f0SCatalin Marinas  * ZERO_PAGE is a global shared page that is always zero: used
1104f04d8f0SCatalin Marinas  * for zero-mapped memory areas etc..
1114f04d8f0SCatalin Marinas  */
1124f04d8f0SCatalin Marinas extern struct page *empty_zero_page;
1134f04d8f0SCatalin Marinas #define ZERO_PAGE(vaddr)	(empty_zero_page)
1144f04d8f0SCatalin Marinas 
1154f04d8f0SCatalin Marinas #define pte_pfn(pte)		((pte_val(pte) & PHYS_MASK) >> PAGE_SHIFT)
1164f04d8f0SCatalin Marinas 
1174f04d8f0SCatalin Marinas #define pfn_pte(pfn,prot)	(__pte(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)))
1184f04d8f0SCatalin Marinas 
1194f04d8f0SCatalin Marinas #define pte_none(pte)		(!pte_val(pte))
1204f04d8f0SCatalin Marinas #define pte_clear(mm,addr,ptep)	set_pte(ptep, __pte(0))
1214f04d8f0SCatalin Marinas #define pte_page(pte)		(pfn_to_page(pte_pfn(pte)))
1229ab6d02fSWill Deacon #define pte_offset_kernel(dir,addr)	(pmd_page_vaddr(*(dir)) + pte_index(addr))
1234f04d8f0SCatalin Marinas 
1244f04d8f0SCatalin Marinas #define pte_offset_map(dir,addr)	pte_offset_kernel((dir), (addr))
1254f04d8f0SCatalin Marinas #define pte_offset_map_nested(dir,addr)	pte_offset_kernel((dir), (addr))
1264f04d8f0SCatalin Marinas #define pte_unmap(pte)			do { } while (0)
1274f04d8f0SCatalin Marinas #define pte_unmap_nested(pte)		do { } while (0)
1284f04d8f0SCatalin Marinas 
1294f04d8f0SCatalin Marinas /*
1304f04d8f0SCatalin Marinas  * The following only work if pte_present(). Undefined behaviour otherwise.
1314f04d8f0SCatalin Marinas  */
13284fe6826SSteve Capper #define pte_present(pte)	(!!(pte_val(pte) & (PTE_VALID | PTE_PROT_NONE)))
13384fe6826SSteve Capper #define pte_dirty(pte)		(!!(pte_val(pte) & PTE_DIRTY))
13484fe6826SSteve Capper #define pte_young(pte)		(!!(pte_val(pte) & PTE_AF))
13584fe6826SSteve Capper #define pte_special(pte)	(!!(pte_val(pte) & PTE_SPECIAL))
13684fe6826SSteve Capper #define pte_write(pte)		(!!(pte_val(pte) & PTE_WRITE))
1378e620b04SCatalin Marinas #define pte_exec(pte)		(!(pte_val(pte) & PTE_UXN))
1384f04d8f0SCatalin Marinas 
139a6fadf7eSWill Deacon #define pte_valid_user(pte) \
14002522463SWill Deacon 	((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER))
1414f04d8f0SCatalin Marinas 
14244b6dfc5SSteve Capper static inline pte_t pte_wrprotect(pte_t pte)
14344b6dfc5SSteve Capper {
144c2c93e5bSSteve Capper 	pte_val(pte) &= ~PTE_WRITE;
14544b6dfc5SSteve Capper 	return pte;
14644b6dfc5SSteve Capper }
1474f04d8f0SCatalin Marinas 
14844b6dfc5SSteve Capper static inline pte_t pte_mkwrite(pte_t pte)
14944b6dfc5SSteve Capper {
150c2c93e5bSSteve Capper 	pte_val(pte) |= PTE_WRITE;
15144b6dfc5SSteve Capper 	return pte;
15244b6dfc5SSteve Capper }
15344b6dfc5SSteve Capper 
15444b6dfc5SSteve Capper static inline pte_t pte_mkclean(pte_t pte)
15544b6dfc5SSteve Capper {
15644b6dfc5SSteve Capper 	pte_val(pte) &= ~PTE_DIRTY;
15744b6dfc5SSteve Capper 	return pte;
15844b6dfc5SSteve Capper }
15944b6dfc5SSteve Capper 
16044b6dfc5SSteve Capper static inline pte_t pte_mkdirty(pte_t pte)
16144b6dfc5SSteve Capper {
16244b6dfc5SSteve Capper 	pte_val(pte) |= PTE_DIRTY;
16344b6dfc5SSteve Capper 	return pte;
16444b6dfc5SSteve Capper }
16544b6dfc5SSteve Capper 
16644b6dfc5SSteve Capper static inline pte_t pte_mkold(pte_t pte)
16744b6dfc5SSteve Capper {
16844b6dfc5SSteve Capper 	pte_val(pte) &= ~PTE_AF;
16944b6dfc5SSteve Capper 	return pte;
17044b6dfc5SSteve Capper }
17144b6dfc5SSteve Capper 
17244b6dfc5SSteve Capper static inline pte_t pte_mkyoung(pte_t pte)
17344b6dfc5SSteve Capper {
17444b6dfc5SSteve Capper 	pte_val(pte) |= PTE_AF;
17544b6dfc5SSteve Capper 	return pte;
17644b6dfc5SSteve Capper }
17744b6dfc5SSteve Capper 
17844b6dfc5SSteve Capper static inline pte_t pte_mkspecial(pte_t pte)
17944b6dfc5SSteve Capper {
18044b6dfc5SSteve Capper 	pte_val(pte) |= PTE_SPECIAL;
18144b6dfc5SSteve Capper 	return pte;
18244b6dfc5SSteve Capper }
1834f04d8f0SCatalin Marinas 
1844f04d8f0SCatalin Marinas static inline void set_pte(pte_t *ptep, pte_t pte)
1854f04d8f0SCatalin Marinas {
1864f04d8f0SCatalin Marinas 	*ptep = pte;
1874f04d8f0SCatalin Marinas }
1884f04d8f0SCatalin Marinas 
1894f04d8f0SCatalin Marinas extern void __sync_icache_dcache(pte_t pteval, unsigned long addr);
1904f04d8f0SCatalin Marinas 
1914f04d8f0SCatalin Marinas static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
1924f04d8f0SCatalin Marinas 			      pte_t *ptep, pte_t pte)
1934f04d8f0SCatalin Marinas {
194a6fadf7eSWill Deacon 	if (pte_valid_user(pte)) {
19571fdb6bfSCatalin Marinas 		if (!pte_special(pte) && pte_exec(pte))
1964f04d8f0SCatalin Marinas 			__sync_icache_dcache(pte, addr);
197c2c93e5bSSteve Capper 		if (pte_dirty(pte) && pte_write(pte))
198c2c93e5bSSteve Capper 			pte_val(pte) &= ~PTE_RDONLY;
199c2c93e5bSSteve Capper 		else
200c2c93e5bSSteve Capper 			pte_val(pte) |= PTE_RDONLY;
20102522463SWill Deacon 	}
20202522463SWill Deacon 
2034f04d8f0SCatalin Marinas 	set_pte(ptep, pte);
2044f04d8f0SCatalin Marinas }
2054f04d8f0SCatalin Marinas 
2064f04d8f0SCatalin Marinas /*
2074f04d8f0SCatalin Marinas  * Huge pte definitions.
2084f04d8f0SCatalin Marinas  */
209084bd298SSteve Capper #define pte_huge(pte)		(!(pte_val(pte) & PTE_TABLE_BIT))
210084bd298SSteve Capper #define pte_mkhuge(pte)		(__pte(pte_val(pte) & ~PTE_TABLE_BIT))
211084bd298SSteve Capper 
212084bd298SSteve Capper /*
213084bd298SSteve Capper  * Hugetlb definitions.
214084bd298SSteve Capper  */
215084bd298SSteve Capper #define HUGE_MAX_HSTATE		2
216084bd298SSteve Capper #define HPAGE_SHIFT		PMD_SHIFT
217084bd298SSteve Capper #define HPAGE_SIZE		(_AC(1, UL) << HPAGE_SHIFT)
218084bd298SSteve Capper #define HPAGE_MASK		(~(HPAGE_SIZE - 1))
219084bd298SSteve Capper #define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
2204f04d8f0SCatalin Marinas 
2214f04d8f0SCatalin Marinas #define __HAVE_ARCH_PTE_SPECIAL
2224f04d8f0SCatalin Marinas 
2239c7e535fSSteve Capper static inline pte_t pmd_pte(pmd_t pmd)
2249c7e535fSSteve Capper {
2259c7e535fSSteve Capper 	return __pte(pmd_val(pmd));
2269c7e535fSSteve Capper }
227af074848SSteve Capper 
2289c7e535fSSteve Capper static inline pmd_t pte_pmd(pte_t pte)
2299c7e535fSSteve Capper {
2309c7e535fSSteve Capper 	return __pmd(pte_val(pte));
2319c7e535fSSteve Capper }
232af074848SSteve Capper 
233af074848SSteve Capper /*
234af074848SSteve Capper  * THP definitions.
235af074848SSteve Capper  */
236af074848SSteve Capper 
237af074848SSteve Capper #ifdef CONFIG_TRANSPARENT_HUGEPAGE
238af074848SSteve Capper #define pmd_trans_huge(pmd)	(pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT))
2399c7e535fSSteve Capper #define pmd_trans_splitting(pmd)	pte_special(pmd_pte(pmd))
240af074848SSteve Capper #endif
241af074848SSteve Capper 
2429c7e535fSSteve Capper #define pmd_young(pmd)		pte_young(pmd_pte(pmd))
2439c7e535fSSteve Capper #define pmd_wrprotect(pmd)	pte_pmd(pte_wrprotect(pmd_pte(pmd)))
2449c7e535fSSteve Capper #define pmd_mksplitting(pmd)	pte_pmd(pte_mkspecial(pmd_pte(pmd)))
2459c7e535fSSteve Capper #define pmd_mkold(pmd)		pte_pmd(pte_mkold(pmd_pte(pmd)))
2469c7e535fSSteve Capper #define pmd_mkwrite(pmd)	pte_pmd(pte_mkwrite(pmd_pte(pmd)))
2479c7e535fSSteve Capper #define pmd_mkdirty(pmd)	pte_pmd(pte_mkdirty(pmd_pte(pmd)))
2489c7e535fSSteve Capper #define pmd_mkyoung(pmd)	pte_pmd(pte_mkyoung(pmd_pte(pmd)))
249e3a920afSWill Deacon #define pmd_mknotpresent(pmd)	(__pmd(pmd_val(pmd) & ~PMD_TYPE_MASK))
250af074848SSteve Capper 
2519c7e535fSSteve Capper #define __HAVE_ARCH_PMD_WRITE
2529c7e535fSSteve Capper #define pmd_write(pmd)		pte_write(pmd_pte(pmd))
253af074848SSteve Capper 
254af074848SSteve Capper #define pmd_mkhuge(pmd)		(__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT))
255af074848SSteve Capper 
256af074848SSteve Capper #define pmd_pfn(pmd)		(((pmd_val(pmd) & PMD_MASK) & PHYS_MASK) >> PAGE_SHIFT)
257af074848SSteve Capper #define pfn_pmd(pfn,prot)	(__pmd(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)))
258af074848SSteve Capper #define mk_pmd(page,prot)	pfn_pmd(page_to_pfn(page),prot)
259af074848SSteve Capper 
260af074848SSteve Capper #define pmd_page(pmd)           pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))
261206a2a73SSteve Capper #define pud_pfn(pud)		(((pud_val(pud) & PUD_MASK) & PHYS_MASK) >> PAGE_SHIFT)
262af074848SSteve Capper 
263ceb21835SWill Deacon #define set_pmd_at(mm, addr, pmdp, pmd)	set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd))
264af074848SSteve Capper 
265af074848SSteve Capper static inline int has_transparent_hugepage(void)
266af074848SSteve Capper {
267af074848SSteve Capper 	return 1;
268af074848SSteve Capper }
269af074848SSteve Capper 
270a501e324SCatalin Marinas #define __pgprot_modify(prot,mask,bits) \
271a501e324SCatalin Marinas 	__pgprot((pgprot_val(prot) & ~(mask)) | (bits))
272a501e324SCatalin Marinas 
273af074848SSteve Capper /*
2744f04d8f0SCatalin Marinas  * Mark the prot value as uncacheable and unbufferable.
2754f04d8f0SCatalin Marinas  */
2764f04d8f0SCatalin Marinas #define pgprot_noncached(prot) \
277de2db743SCatalin Marinas 	__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE) | PTE_PXN | PTE_UXN)
2784f04d8f0SCatalin Marinas #define pgprot_writecombine(prot) \
279de2db743SCatalin Marinas 	__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC) | PTE_PXN | PTE_UXN)
2804f04d8f0SCatalin Marinas #define __HAVE_PHYS_MEM_ACCESS_PROT
2814f04d8f0SCatalin Marinas struct file;
2824f04d8f0SCatalin Marinas extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
2834f04d8f0SCatalin Marinas 				     unsigned long size, pgprot_t vma_prot);
2844f04d8f0SCatalin Marinas 
2854f04d8f0SCatalin Marinas #define pmd_none(pmd)		(!pmd_val(pmd))
2864f04d8f0SCatalin Marinas #define pmd_present(pmd)	(pmd_val(pmd))
2874f04d8f0SCatalin Marinas 
2884f04d8f0SCatalin Marinas #define pmd_bad(pmd)		(!(pmd_val(pmd) & 2))
2894f04d8f0SCatalin Marinas 
29036311607SMarc Zyngier #define pmd_table(pmd)		((pmd_val(pmd) & PMD_TYPE_MASK) == \
29136311607SMarc Zyngier 				 PMD_TYPE_TABLE)
29236311607SMarc Zyngier #define pmd_sect(pmd)		((pmd_val(pmd) & PMD_TYPE_MASK) == \
29336311607SMarc Zyngier 				 PMD_TYPE_SECT)
29436311607SMarc Zyngier 
295*f3b766a2SSteve Capper #ifdef CONFIG_ARM64_64K_PAGES
296206a2a73SSteve Capper #define pud_sect(pud)		(0)
297206a2a73SSteve Capper #else
298206a2a73SSteve Capper #define pud_sect(pud)		((pud_val(pud) & PUD_TYPE_MASK) == \
299206a2a73SSteve Capper 				 PUD_TYPE_SECT)
300206a2a73SSteve Capper #endif
30136311607SMarc Zyngier 
3024f04d8f0SCatalin Marinas static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
3034f04d8f0SCatalin Marinas {
3044f04d8f0SCatalin Marinas 	*pmdp = pmd;
30598f7685eSWill Deacon 	dsb(ishst);
3064f04d8f0SCatalin Marinas }
3074f04d8f0SCatalin Marinas 
3084f04d8f0SCatalin Marinas static inline void pmd_clear(pmd_t *pmdp)
3094f04d8f0SCatalin Marinas {
3104f04d8f0SCatalin Marinas 	set_pmd(pmdp, __pmd(0));
3114f04d8f0SCatalin Marinas }
3124f04d8f0SCatalin Marinas 
3134f04d8f0SCatalin Marinas static inline pte_t *pmd_page_vaddr(pmd_t pmd)
3144f04d8f0SCatalin Marinas {
3154f04d8f0SCatalin Marinas 	return __va(pmd_val(pmd) & PHYS_MASK & (s32)PAGE_MASK);
3164f04d8f0SCatalin Marinas }
3174f04d8f0SCatalin Marinas 
3184f04d8f0SCatalin Marinas #define pmd_page(pmd)		pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))
3194f04d8f0SCatalin Marinas 
3204f04d8f0SCatalin Marinas /*
3214f04d8f0SCatalin Marinas  * Conversion functions: convert a page and protection to a page entry,
3224f04d8f0SCatalin Marinas  * and a page entry and page directory to the page they refer to.
3234f04d8f0SCatalin Marinas  */
3244f04d8f0SCatalin Marinas #define mk_pte(page,prot)	pfn_pte(page_to_pfn(page),prot)
3254f04d8f0SCatalin Marinas 
3264f04d8f0SCatalin Marinas #ifndef CONFIG_ARM64_64K_PAGES
3274f04d8f0SCatalin Marinas 
3284f04d8f0SCatalin Marinas #define pud_none(pud)		(!pud_val(pud))
3294f04d8f0SCatalin Marinas #define pud_bad(pud)		(!(pud_val(pud) & 2))
3304f04d8f0SCatalin Marinas #define pud_present(pud)	(pud_val(pud))
3314f04d8f0SCatalin Marinas 
3324f04d8f0SCatalin Marinas static inline void set_pud(pud_t *pudp, pud_t pud)
3334f04d8f0SCatalin Marinas {
3344f04d8f0SCatalin Marinas 	*pudp = pud;
33598f7685eSWill Deacon 	dsb(ishst);
3364f04d8f0SCatalin Marinas }
3374f04d8f0SCatalin Marinas 
3384f04d8f0SCatalin Marinas static inline void pud_clear(pud_t *pudp)
3394f04d8f0SCatalin Marinas {
3404f04d8f0SCatalin Marinas 	set_pud(pudp, __pud(0));
3414f04d8f0SCatalin Marinas }
3424f04d8f0SCatalin Marinas 
3434f04d8f0SCatalin Marinas static inline pmd_t *pud_page_vaddr(pud_t pud)
3444f04d8f0SCatalin Marinas {
3454f04d8f0SCatalin Marinas 	return __va(pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK);
3464f04d8f0SCatalin Marinas }
3474f04d8f0SCatalin Marinas 
3484f04d8f0SCatalin Marinas #endif	/* CONFIG_ARM64_64K_PAGES */
3494f04d8f0SCatalin Marinas 
3504f04d8f0SCatalin Marinas /* to find an entry in a page-table-directory */
3514f04d8f0SCatalin Marinas #define pgd_index(addr)		(((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
3524f04d8f0SCatalin Marinas 
3534f04d8f0SCatalin Marinas #define pgd_offset(mm, addr)	((mm)->pgd+pgd_index(addr))
3544f04d8f0SCatalin Marinas 
3554f04d8f0SCatalin Marinas /* to find an entry in a kernel page-table-directory */
3564f04d8f0SCatalin Marinas #define pgd_offset_k(addr)	pgd_offset(&init_mm, addr)
3574f04d8f0SCatalin Marinas 
3584f04d8f0SCatalin Marinas /* Find an entry in the second-level page table.. */
3594f04d8f0SCatalin Marinas #ifndef CONFIG_ARM64_64K_PAGES
3604f04d8f0SCatalin Marinas #define pmd_index(addr)		(((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
3614f04d8f0SCatalin Marinas static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
3624f04d8f0SCatalin Marinas {
3634f04d8f0SCatalin Marinas 	return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr);
3644f04d8f0SCatalin Marinas }
3654f04d8f0SCatalin Marinas #endif
3664f04d8f0SCatalin Marinas 
3674f04d8f0SCatalin Marinas /* Find an entry in the third-level page table.. */
3689ab6d02fSWill Deacon #define pte_index(addr)		(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
3694f04d8f0SCatalin Marinas 
3704f04d8f0SCatalin Marinas static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
3714f04d8f0SCatalin Marinas {
372a6fadf7eSWill Deacon 	const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY |
373c2c93e5bSSteve Capper 			      PTE_PROT_NONE | PTE_VALID | PTE_WRITE;
3744f04d8f0SCatalin Marinas 	pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
3754f04d8f0SCatalin Marinas 	return pte;
3764f04d8f0SCatalin Marinas }
3774f04d8f0SCatalin Marinas 
3789c7e535fSSteve Capper static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
3799c7e535fSSteve Capper {
3809c7e535fSSteve Capper 	return pte_pmd(pte_modify(pmd_pte(pmd), newprot));
3819c7e535fSSteve Capper }
3829c7e535fSSteve Capper 
3834f04d8f0SCatalin Marinas extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
3844f04d8f0SCatalin Marinas extern pgd_t idmap_pg_dir[PTRS_PER_PGD];
3854f04d8f0SCatalin Marinas 
3864f04d8f0SCatalin Marinas #define SWAPPER_DIR_SIZE	(3 * PAGE_SIZE)
3874f04d8f0SCatalin Marinas #define IDMAP_DIR_SIZE		(2 * PAGE_SIZE)
3884f04d8f0SCatalin Marinas 
3894f04d8f0SCatalin Marinas /*
3904f04d8f0SCatalin Marinas  * Encode and decode a swap entry:
3913676f9efSCatalin Marinas  *	bits 0-1:	present (must be zero)
3923676f9efSCatalin Marinas  *	bit  2:		PTE_FILE
3933676f9efSCatalin Marinas  *	bits 3-8:	swap type
3943676f9efSCatalin Marinas  *	bits 9-57:	swap offset
3954f04d8f0SCatalin Marinas  */
3963676f9efSCatalin Marinas #define __SWP_TYPE_SHIFT	3
3974f04d8f0SCatalin Marinas #define __SWP_TYPE_BITS		6
3983676f9efSCatalin Marinas #define __SWP_OFFSET_BITS	49
3994f04d8f0SCatalin Marinas #define __SWP_TYPE_MASK		((1 << __SWP_TYPE_BITS) - 1)
4004f04d8f0SCatalin Marinas #define __SWP_OFFSET_SHIFT	(__SWP_TYPE_BITS + __SWP_TYPE_SHIFT)
4013676f9efSCatalin Marinas #define __SWP_OFFSET_MASK	((1UL << __SWP_OFFSET_BITS) - 1)
4024f04d8f0SCatalin Marinas 
4034f04d8f0SCatalin Marinas #define __swp_type(x)		(((x).val >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK)
4043676f9efSCatalin Marinas #define __swp_offset(x)		(((x).val >> __SWP_OFFSET_SHIFT) & __SWP_OFFSET_MASK)
4054f04d8f0SCatalin Marinas #define __swp_entry(type,offset) ((swp_entry_t) { ((type) << __SWP_TYPE_SHIFT) | ((offset) << __SWP_OFFSET_SHIFT) })
4064f04d8f0SCatalin Marinas 
4074f04d8f0SCatalin Marinas #define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
4084f04d8f0SCatalin Marinas #define __swp_entry_to_pte(swp)	((pte_t) { (swp).val })
4094f04d8f0SCatalin Marinas 
4104f04d8f0SCatalin Marinas /*
4114f04d8f0SCatalin Marinas  * Ensure that there are not more swap files than can be encoded in the kernel
412aad9061bSGeert Uytterhoeven  * PTEs.
4134f04d8f0SCatalin Marinas  */
4144f04d8f0SCatalin Marinas #define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > __SWP_TYPE_BITS)
4154f04d8f0SCatalin Marinas 
4164f04d8f0SCatalin Marinas /*
4174f04d8f0SCatalin Marinas  * Encode and decode a file entry:
4183676f9efSCatalin Marinas  *	bits 0-1:	present (must be zero)
4193676f9efSCatalin Marinas  *	bit  2:		PTE_FILE
4203676f9efSCatalin Marinas  *	bits 3-57:	file offset / PAGE_SIZE
4214f04d8f0SCatalin Marinas  */
4224f04d8f0SCatalin Marinas #define pte_file(pte)		(pte_val(pte) & PTE_FILE)
4233676f9efSCatalin Marinas #define pte_to_pgoff(x)		(pte_val(x) >> 3)
4243676f9efSCatalin Marinas #define pgoff_to_pte(x)		__pte(((x) << 3) | PTE_FILE)
4254f04d8f0SCatalin Marinas 
4263676f9efSCatalin Marinas #define PTE_FILE_MAX_BITS	55
4274f04d8f0SCatalin Marinas 
4284f04d8f0SCatalin Marinas extern int kern_addr_valid(unsigned long addr);
4294f04d8f0SCatalin Marinas 
4304f04d8f0SCatalin Marinas #include <asm-generic/pgtable.h>
4314f04d8f0SCatalin Marinas 
4324f04d8f0SCatalin Marinas #define pgtable_cache_init() do { } while (0)
4334f04d8f0SCatalin Marinas 
4344f04d8f0SCatalin Marinas #endif /* !__ASSEMBLY__ */
4354f04d8f0SCatalin Marinas 
4364f04d8f0SCatalin Marinas #endif /* __ASM_PGTABLE_H */
437