xref: /linux/arch/arm64/include/asm/pgtable.h (revision af07484863e0c20796081e57093886c22dc16705)
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)
2859911ca4SSteve Capper #define PTE_PROT_NONE		(_AT(pteval_t, 1) << 2)	/* only when !PTE_VALID */
2959911ca4SSteve Capper #define PTE_FILE		(_AT(pteval_t, 1) << 3)	/* only when !pte_present() */
304f04d8f0SCatalin Marinas #define PTE_DIRTY		(_AT(pteval_t, 1) << 55)
314f04d8f0SCatalin Marinas #define PTE_SPECIAL		(_AT(pteval_t, 1) << 56)
324f04d8f0SCatalin Marinas 
334f04d8f0SCatalin Marinas /*
344f04d8f0SCatalin Marinas  * VMALLOC and SPARSEMEM_VMEMMAP ranges.
354f04d8f0SCatalin Marinas  */
364f04d8f0SCatalin Marinas #define VMALLOC_START		UL(0xffffff8000000000)
374f04d8f0SCatalin Marinas #define VMALLOC_END		(PAGE_OFFSET - UL(0x400000000) - SZ_64K)
384f04d8f0SCatalin Marinas 
394f04d8f0SCatalin Marinas #define vmemmap			((struct page *)(VMALLOC_END + SZ_64K))
404f04d8f0SCatalin Marinas 
414f04d8f0SCatalin Marinas #define FIRST_USER_ADDRESS	0
424f04d8f0SCatalin Marinas 
434f04d8f0SCatalin Marinas #ifndef __ASSEMBLY__
444f04d8f0SCatalin Marinas extern void __pte_error(const char *file, int line, unsigned long val);
454f04d8f0SCatalin Marinas extern void __pmd_error(const char *file, int line, unsigned long val);
464f04d8f0SCatalin Marinas extern void __pgd_error(const char *file, int line, unsigned long val);
474f04d8f0SCatalin Marinas 
484f04d8f0SCatalin Marinas #define pte_ERROR(pte)		__pte_error(__FILE__, __LINE__, pte_val(pte))
494f04d8f0SCatalin Marinas #ifndef CONFIG_ARM64_64K_PAGES
504f04d8f0SCatalin Marinas #define pmd_ERROR(pmd)		__pmd_error(__FILE__, __LINE__, pmd_val(pmd))
514f04d8f0SCatalin Marinas #endif
524f04d8f0SCatalin Marinas #define pgd_ERROR(pgd)		__pgd_error(__FILE__, __LINE__, pgd_val(pgd))
534f04d8f0SCatalin Marinas 
544f04d8f0SCatalin Marinas /*
554f04d8f0SCatalin Marinas  * The pgprot_* and protection_map entries will be fixed up at runtime to
564f04d8f0SCatalin Marinas  * include the cachable and bufferable bits based on memory policy, as well as
574f04d8f0SCatalin Marinas  * any architecture dependent bits like global/ASID and SMP shared mapping
584f04d8f0SCatalin Marinas  * bits.
594f04d8f0SCatalin Marinas  */
604f04d8f0SCatalin Marinas #define _PAGE_DEFAULT		PTE_TYPE_PAGE | PTE_AF
614f04d8f0SCatalin Marinas 
624f04d8f0SCatalin Marinas extern pgprot_t pgprot_default;
634f04d8f0SCatalin Marinas 
64a6fadf7eSWill Deacon #define __pgprot_modify(prot,mask,bits) \
65a6fadf7eSWill Deacon 	__pgprot((pgprot_val(prot) & ~(mask)) | (bits))
664f04d8f0SCatalin Marinas 
67a6fadf7eSWill Deacon #define _MOD_PROT(p, b)		__pgprot_modify(p, 0, b)
68a6fadf7eSWill Deacon 
69072b1b62SSteve Capper #define PAGE_NONE		__pgprot_modify(pgprot_default, PTE_TYPE_MASK, PTE_PROT_NONE | PTE_RDONLY | PTE_PXN | PTE_UXN)
708e620b04SCatalin Marinas #define PAGE_SHARED		_MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
718e620b04SCatalin Marinas #define PAGE_SHARED_EXEC	_MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN)
728e620b04SCatalin Marinas #define PAGE_COPY		_MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
738e620b04SCatalin Marinas #define PAGE_COPY_EXEC		_MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
748e620b04SCatalin Marinas #define PAGE_READONLY		_MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
758e620b04SCatalin Marinas #define PAGE_READONLY_EXEC	_MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
768e620b04SCatalin Marinas #define PAGE_KERNEL		_MOD_PROT(pgprot_default, PTE_PXN | PTE_UXN | PTE_DIRTY)
778e620b04SCatalin Marinas #define PAGE_KERNEL_EXEC	_MOD_PROT(pgprot_default, PTE_UXN | PTE_DIRTY)
784f04d8f0SCatalin Marinas 
79072b1b62SSteve Capper #define __PAGE_NONE		__pgprot(((_PAGE_DEFAULT) & ~PTE_TYPE_MASK) | PTE_PROT_NONE | PTE_RDONLY | PTE_PXN | PTE_UXN)
808e620b04SCatalin Marinas #define __PAGE_SHARED		__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
818e620b04SCatalin Marinas #define __PAGE_SHARED_EXEC	__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN)
828e620b04SCatalin Marinas #define __PAGE_COPY		__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
838e620b04SCatalin Marinas #define __PAGE_COPY_EXEC	__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
848e620b04SCatalin Marinas #define __PAGE_READONLY		__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
858e620b04SCatalin Marinas #define __PAGE_READONLY_EXEC	__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
864f04d8f0SCatalin Marinas 
874f04d8f0SCatalin Marinas #endif /* __ASSEMBLY__ */
884f04d8f0SCatalin Marinas 
894f04d8f0SCatalin Marinas #define __P000  __PAGE_NONE
904f04d8f0SCatalin Marinas #define __P001  __PAGE_READONLY
914f04d8f0SCatalin Marinas #define __P010  __PAGE_COPY
924f04d8f0SCatalin Marinas #define __P011  __PAGE_COPY
934f04d8f0SCatalin Marinas #define __P100  __PAGE_READONLY_EXEC
944f04d8f0SCatalin Marinas #define __P101  __PAGE_READONLY_EXEC
954f04d8f0SCatalin Marinas #define __P110  __PAGE_COPY_EXEC
964f04d8f0SCatalin Marinas #define __P111  __PAGE_COPY_EXEC
974f04d8f0SCatalin Marinas 
984f04d8f0SCatalin Marinas #define __S000  __PAGE_NONE
994f04d8f0SCatalin Marinas #define __S001  __PAGE_READONLY
1004f04d8f0SCatalin Marinas #define __S010  __PAGE_SHARED
1014f04d8f0SCatalin Marinas #define __S011  __PAGE_SHARED
1024f04d8f0SCatalin Marinas #define __S100  __PAGE_READONLY_EXEC
1034f04d8f0SCatalin Marinas #define __S101  __PAGE_READONLY_EXEC
1044f04d8f0SCatalin Marinas #define __S110  __PAGE_SHARED_EXEC
1054f04d8f0SCatalin Marinas #define __S111  __PAGE_SHARED_EXEC
1064f04d8f0SCatalin Marinas 
1074f04d8f0SCatalin Marinas #ifndef __ASSEMBLY__
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)))
1224f04d8f0SCatalin Marinas #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  */
132a6fadf7eSWill Deacon #define pte_present(pte)	(pte_val(pte) & (PTE_VALID | PTE_PROT_NONE))
1334f04d8f0SCatalin Marinas #define pte_dirty(pte)		(pte_val(pte) & PTE_DIRTY)
1344f04d8f0SCatalin Marinas #define pte_young(pte)		(pte_val(pte) & PTE_AF)
1354f04d8f0SCatalin Marinas #define pte_special(pte)	(pte_val(pte) & PTE_SPECIAL)
1364f04d8f0SCatalin Marinas #define pte_write(pte)		(!(pte_val(pte) & PTE_RDONLY))
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 
1424f04d8f0SCatalin Marinas #define PTE_BIT_FUNC(fn,op) \
1434f04d8f0SCatalin Marinas static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
1444f04d8f0SCatalin Marinas 
1454f04d8f0SCatalin Marinas PTE_BIT_FUNC(wrprotect, |= PTE_RDONLY);
1464f04d8f0SCatalin Marinas PTE_BIT_FUNC(mkwrite,   &= ~PTE_RDONLY);
1474f04d8f0SCatalin Marinas PTE_BIT_FUNC(mkclean,   &= ~PTE_DIRTY);
1484f04d8f0SCatalin Marinas PTE_BIT_FUNC(mkdirty,   |= PTE_DIRTY);
1494f04d8f0SCatalin Marinas PTE_BIT_FUNC(mkold,     &= ~PTE_AF);
1504f04d8f0SCatalin Marinas PTE_BIT_FUNC(mkyoung,   |= PTE_AF);
1514f04d8f0SCatalin Marinas PTE_BIT_FUNC(mkspecial, |= PTE_SPECIAL);
1524f04d8f0SCatalin Marinas 
1534f04d8f0SCatalin Marinas static inline void set_pte(pte_t *ptep, pte_t pte)
1544f04d8f0SCatalin Marinas {
1554f04d8f0SCatalin Marinas 	*ptep = pte;
1564f04d8f0SCatalin Marinas }
1574f04d8f0SCatalin Marinas 
1584f04d8f0SCatalin Marinas extern void __sync_icache_dcache(pte_t pteval, unsigned long addr);
1594f04d8f0SCatalin Marinas 
1604f04d8f0SCatalin Marinas static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
1614f04d8f0SCatalin Marinas 			      pte_t *ptep, pte_t pte)
1624f04d8f0SCatalin Marinas {
163a6fadf7eSWill Deacon 	if (pte_valid_user(pte)) {
16402522463SWill Deacon 		if (pte_exec(pte))
1654f04d8f0SCatalin Marinas 			__sync_icache_dcache(pte, addr);
16633eaa58fSCatalin Marinas 		if (!pte_dirty(pte))
16733eaa58fSCatalin Marinas 			pte = pte_wrprotect(pte);
16802522463SWill Deacon 	}
16902522463SWill Deacon 
1704f04d8f0SCatalin Marinas 	set_pte(ptep, pte);
1714f04d8f0SCatalin Marinas }
1724f04d8f0SCatalin Marinas 
1734f04d8f0SCatalin Marinas /*
1744f04d8f0SCatalin Marinas  * Huge pte definitions.
1754f04d8f0SCatalin Marinas  */
176084bd298SSteve Capper #define pte_huge(pte)		(!(pte_val(pte) & PTE_TABLE_BIT))
177084bd298SSteve Capper #define pte_mkhuge(pte)		(__pte(pte_val(pte) & ~PTE_TABLE_BIT))
178084bd298SSteve Capper 
179084bd298SSteve Capper /*
180084bd298SSteve Capper  * Hugetlb definitions.
181084bd298SSteve Capper  */
182084bd298SSteve Capper #define HUGE_MAX_HSTATE		2
183084bd298SSteve Capper #define HPAGE_SHIFT		PMD_SHIFT
184084bd298SSteve Capper #define HPAGE_SIZE		(_AC(1, UL) << HPAGE_SHIFT)
185084bd298SSteve Capper #define HPAGE_MASK		(~(HPAGE_SIZE - 1))
186084bd298SSteve Capper #define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
1874f04d8f0SCatalin Marinas 
1884f04d8f0SCatalin Marinas #define __HAVE_ARCH_PTE_SPECIAL
1894f04d8f0SCatalin Marinas 
1904f04d8f0SCatalin Marinas /*
191*af074848SSteve Capper  * Software PMD bits for THP
192*af074848SSteve Capper  */
193*af074848SSteve Capper 
194*af074848SSteve Capper #define PMD_SECT_DIRTY		(_AT(pmdval_t, 1) << 55)
195*af074848SSteve Capper #define PMD_SECT_SPLITTING	(_AT(pmdval_t, 1) << 57)
196*af074848SSteve Capper 
197*af074848SSteve Capper /*
198*af074848SSteve Capper  * THP definitions.
199*af074848SSteve Capper  */
200*af074848SSteve Capper #define pmd_young(pmd)		(pmd_val(pmd) & PMD_SECT_AF)
201*af074848SSteve Capper 
202*af074848SSteve Capper #define __HAVE_ARCH_PMD_WRITE
203*af074848SSteve Capper #define pmd_write(pmd)		(!(pmd_val(pmd) & PMD_SECT_RDONLY))
204*af074848SSteve Capper 
205*af074848SSteve Capper #ifdef CONFIG_TRANSPARENT_HUGEPAGE
206*af074848SSteve Capper #define pmd_trans_huge(pmd)	(pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT))
207*af074848SSteve Capper #define pmd_trans_splitting(pmd) (pmd_val(pmd) & PMD_SECT_SPLITTING)
208*af074848SSteve Capper #endif
209*af074848SSteve Capper 
210*af074848SSteve Capper #define PMD_BIT_FUNC(fn,op) \
211*af074848SSteve Capper static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; }
212*af074848SSteve Capper 
213*af074848SSteve Capper PMD_BIT_FUNC(wrprotect,	|= PMD_SECT_RDONLY);
214*af074848SSteve Capper PMD_BIT_FUNC(mkold,	&= ~PMD_SECT_AF);
215*af074848SSteve Capper PMD_BIT_FUNC(mksplitting, |= PMD_SECT_SPLITTING);
216*af074848SSteve Capper PMD_BIT_FUNC(mkwrite,   &= ~PMD_SECT_RDONLY);
217*af074848SSteve Capper PMD_BIT_FUNC(mkdirty,   |= PMD_SECT_DIRTY);
218*af074848SSteve Capper PMD_BIT_FUNC(mkyoung,   |= PMD_SECT_AF);
219*af074848SSteve Capper PMD_BIT_FUNC(mknotpresent, &= ~PMD_TYPE_MASK);
220*af074848SSteve Capper 
221*af074848SSteve Capper #define pmd_mkhuge(pmd)		(__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT))
222*af074848SSteve Capper 
223*af074848SSteve Capper #define pmd_pfn(pmd)		(((pmd_val(pmd) & PMD_MASK) & PHYS_MASK) >> PAGE_SHIFT)
224*af074848SSteve Capper #define pfn_pmd(pfn,prot)	(__pmd(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)))
225*af074848SSteve Capper #define mk_pmd(page,prot)	pfn_pmd(page_to_pfn(page),prot)
226*af074848SSteve Capper 
227*af074848SSteve Capper #define pmd_page(pmd)           pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))
228*af074848SSteve Capper 
229*af074848SSteve Capper static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
230*af074848SSteve Capper {
231*af074848SSteve Capper 	const pmdval_t mask = PMD_SECT_USER | PMD_SECT_PXN | PMD_SECT_UXN |
232*af074848SSteve Capper 			      PMD_SECT_RDONLY | PMD_SECT_PROT_NONE |
233*af074848SSteve Capper 			      PMD_SECT_VALID;
234*af074848SSteve Capper 	pmd_val(pmd) = (pmd_val(pmd) & ~mask) | (pgprot_val(newprot) & mask);
235*af074848SSteve Capper 	return pmd;
236*af074848SSteve Capper }
237*af074848SSteve Capper 
238*af074848SSteve Capper #define set_pmd_at(mm, addr, pmdp, pmd)	set_pmd(pmdp, pmd)
239*af074848SSteve Capper 
240*af074848SSteve Capper static inline int has_transparent_hugepage(void)
241*af074848SSteve Capper {
242*af074848SSteve Capper 	return 1;
243*af074848SSteve Capper }
244*af074848SSteve Capper 
245*af074848SSteve Capper /*
2464f04d8f0SCatalin Marinas  * Mark the prot value as uncacheable and unbufferable.
2474f04d8f0SCatalin Marinas  */
2484f04d8f0SCatalin Marinas #define pgprot_noncached(prot) \
2494f04d8f0SCatalin Marinas 	__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE))
2504f04d8f0SCatalin Marinas #define pgprot_writecombine(prot) \
2514f04d8f0SCatalin Marinas 	__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_GRE))
2524f04d8f0SCatalin Marinas #define pgprot_dmacoherent(prot) \
2534f04d8f0SCatalin Marinas 	__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC))
2544f04d8f0SCatalin Marinas #define __HAVE_PHYS_MEM_ACCESS_PROT
2554f04d8f0SCatalin Marinas struct file;
2564f04d8f0SCatalin Marinas extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
2574f04d8f0SCatalin Marinas 				     unsigned long size, pgprot_t vma_prot);
2584f04d8f0SCatalin Marinas 
2594f04d8f0SCatalin Marinas #define pmd_none(pmd)		(!pmd_val(pmd))
2604f04d8f0SCatalin Marinas #define pmd_present(pmd)	(pmd_val(pmd))
2614f04d8f0SCatalin Marinas 
2624f04d8f0SCatalin Marinas #define pmd_bad(pmd)		(!(pmd_val(pmd) & 2))
2634f04d8f0SCatalin Marinas 
2644f04d8f0SCatalin Marinas static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
2654f04d8f0SCatalin Marinas {
2664f04d8f0SCatalin Marinas 	*pmdp = pmd;
2674f04d8f0SCatalin Marinas 	dsb();
2684f04d8f0SCatalin Marinas }
2694f04d8f0SCatalin Marinas 
2704f04d8f0SCatalin Marinas static inline void pmd_clear(pmd_t *pmdp)
2714f04d8f0SCatalin Marinas {
2724f04d8f0SCatalin Marinas 	set_pmd(pmdp, __pmd(0));
2734f04d8f0SCatalin Marinas }
2744f04d8f0SCatalin Marinas 
2754f04d8f0SCatalin Marinas static inline pte_t *pmd_page_vaddr(pmd_t pmd)
2764f04d8f0SCatalin Marinas {
2774f04d8f0SCatalin Marinas 	return __va(pmd_val(pmd) & PHYS_MASK & (s32)PAGE_MASK);
2784f04d8f0SCatalin Marinas }
2794f04d8f0SCatalin Marinas 
2804f04d8f0SCatalin Marinas #define pmd_page(pmd)		pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))
2814f04d8f0SCatalin Marinas 
2824f04d8f0SCatalin Marinas /*
2834f04d8f0SCatalin Marinas  * Conversion functions: convert a page and protection to a page entry,
2844f04d8f0SCatalin Marinas  * and a page entry and page directory to the page they refer to.
2854f04d8f0SCatalin Marinas  */
2864f04d8f0SCatalin Marinas #define mk_pte(page,prot)	pfn_pte(page_to_pfn(page),prot)
2874f04d8f0SCatalin Marinas 
2884f04d8f0SCatalin Marinas #ifndef CONFIG_ARM64_64K_PAGES
2894f04d8f0SCatalin Marinas 
2904f04d8f0SCatalin Marinas #define pud_none(pud)		(!pud_val(pud))
2914f04d8f0SCatalin Marinas #define pud_bad(pud)		(!(pud_val(pud) & 2))
2924f04d8f0SCatalin Marinas #define pud_present(pud)	(pud_val(pud))
2934f04d8f0SCatalin Marinas 
2944f04d8f0SCatalin Marinas static inline void set_pud(pud_t *pudp, pud_t pud)
2954f04d8f0SCatalin Marinas {
2964f04d8f0SCatalin Marinas 	*pudp = pud;
2974f04d8f0SCatalin Marinas 	dsb();
2984f04d8f0SCatalin Marinas }
2994f04d8f0SCatalin Marinas 
3004f04d8f0SCatalin Marinas static inline void pud_clear(pud_t *pudp)
3014f04d8f0SCatalin Marinas {
3024f04d8f0SCatalin Marinas 	set_pud(pudp, __pud(0));
3034f04d8f0SCatalin Marinas }
3044f04d8f0SCatalin Marinas 
3054f04d8f0SCatalin Marinas static inline pmd_t *pud_page_vaddr(pud_t pud)
3064f04d8f0SCatalin Marinas {
3074f04d8f0SCatalin Marinas 	return __va(pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK);
3084f04d8f0SCatalin Marinas }
3094f04d8f0SCatalin Marinas 
3104f04d8f0SCatalin Marinas #endif	/* CONFIG_ARM64_64K_PAGES */
3114f04d8f0SCatalin Marinas 
3124f04d8f0SCatalin Marinas /* to find an entry in a page-table-directory */
3134f04d8f0SCatalin Marinas #define pgd_index(addr)		(((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
3144f04d8f0SCatalin Marinas 
3154f04d8f0SCatalin Marinas #define pgd_offset(mm, addr)	((mm)->pgd+pgd_index(addr))
3164f04d8f0SCatalin Marinas 
3174f04d8f0SCatalin Marinas /* to find an entry in a kernel page-table-directory */
3184f04d8f0SCatalin Marinas #define pgd_offset_k(addr)	pgd_offset(&init_mm, addr)
3194f04d8f0SCatalin Marinas 
3204f04d8f0SCatalin Marinas /* Find an entry in the second-level page table.. */
3214f04d8f0SCatalin Marinas #ifndef CONFIG_ARM64_64K_PAGES
3224f04d8f0SCatalin Marinas #define pmd_index(addr)		(((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
3234f04d8f0SCatalin Marinas static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
3244f04d8f0SCatalin Marinas {
3254f04d8f0SCatalin Marinas 	return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr);
3264f04d8f0SCatalin Marinas }
3274f04d8f0SCatalin Marinas #endif
3284f04d8f0SCatalin Marinas 
3294f04d8f0SCatalin Marinas /* Find an entry in the third-level page table.. */
3304f04d8f0SCatalin Marinas #define __pte_index(addr)	(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
3314f04d8f0SCatalin Marinas 
3324f04d8f0SCatalin Marinas static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
3334f04d8f0SCatalin Marinas {
334a6fadf7eSWill Deacon 	const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY |
335a6fadf7eSWill Deacon 			      PTE_PROT_NONE | PTE_VALID;
3364f04d8f0SCatalin Marinas 	pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
3374f04d8f0SCatalin Marinas 	return pte;
3384f04d8f0SCatalin Marinas }
3394f04d8f0SCatalin Marinas 
3404f04d8f0SCatalin Marinas extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
3414f04d8f0SCatalin Marinas extern pgd_t idmap_pg_dir[PTRS_PER_PGD];
3424f04d8f0SCatalin Marinas 
3434f04d8f0SCatalin Marinas #define SWAPPER_DIR_SIZE	(3 * PAGE_SIZE)
3444f04d8f0SCatalin Marinas #define IDMAP_DIR_SIZE		(2 * PAGE_SIZE)
3454f04d8f0SCatalin Marinas 
3464f04d8f0SCatalin Marinas /*
3474f04d8f0SCatalin Marinas  * Encode and decode a swap entry:
34859911ca4SSteve Capper  *	bits 0, 2:	present (must both be zero)
34959911ca4SSteve Capper  *	bit  3:		PTE_FILE
35059911ca4SSteve Capper  *	bits 4-8:	swap type
3514f04d8f0SCatalin Marinas  *	bits 9-63:	swap offset
3524f04d8f0SCatalin Marinas  */
35359911ca4SSteve Capper #define __SWP_TYPE_SHIFT	4
3544f04d8f0SCatalin Marinas #define __SWP_TYPE_BITS		6
3554f04d8f0SCatalin Marinas #define __SWP_TYPE_MASK		((1 << __SWP_TYPE_BITS) - 1)
3564f04d8f0SCatalin Marinas #define __SWP_OFFSET_SHIFT	(__SWP_TYPE_BITS + __SWP_TYPE_SHIFT)
3574f04d8f0SCatalin Marinas 
3584f04d8f0SCatalin Marinas #define __swp_type(x)		(((x).val >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK)
3594f04d8f0SCatalin Marinas #define __swp_offset(x)		((x).val >> __SWP_OFFSET_SHIFT)
3604f04d8f0SCatalin Marinas #define __swp_entry(type,offset) ((swp_entry_t) { ((type) << __SWP_TYPE_SHIFT) | ((offset) << __SWP_OFFSET_SHIFT) })
3614f04d8f0SCatalin Marinas 
3624f04d8f0SCatalin Marinas #define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
3634f04d8f0SCatalin Marinas #define __swp_entry_to_pte(swp)	((pte_t) { (swp).val })
3644f04d8f0SCatalin Marinas 
3654f04d8f0SCatalin Marinas /*
3664f04d8f0SCatalin Marinas  * Ensure that there are not more swap files than can be encoded in the kernel
3674f04d8f0SCatalin Marinas  * the PTEs.
3684f04d8f0SCatalin Marinas  */
3694f04d8f0SCatalin Marinas #define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > __SWP_TYPE_BITS)
3704f04d8f0SCatalin Marinas 
3714f04d8f0SCatalin Marinas /*
3724f04d8f0SCatalin Marinas  * Encode and decode a file entry:
37359911ca4SSteve Capper  *	bits 0, 2:	present (must both be zero)
37459911ca4SSteve Capper  *	bit  3:		PTE_FILE
37559911ca4SSteve Capper  *	bits 4-63:	file offset / PAGE_SIZE
3764f04d8f0SCatalin Marinas  */
3774f04d8f0SCatalin Marinas #define pte_file(pte)		(pte_val(pte) & PTE_FILE)
37859911ca4SSteve Capper #define pte_to_pgoff(x)		(pte_val(x) >> 4)
37959911ca4SSteve Capper #define pgoff_to_pte(x)		__pte(((x) << 4) | PTE_FILE)
3804f04d8f0SCatalin Marinas 
38159911ca4SSteve Capper #define PTE_FILE_MAX_BITS	60
3824f04d8f0SCatalin Marinas 
3834f04d8f0SCatalin Marinas extern int kern_addr_valid(unsigned long addr);
3844f04d8f0SCatalin Marinas 
3854f04d8f0SCatalin Marinas #include <asm-generic/pgtable.h>
3864f04d8f0SCatalin Marinas 
3874f04d8f0SCatalin Marinas /*
3884f04d8f0SCatalin Marinas  * remap a physical page `pfn' of size `size' with page protection `prot'
3894f04d8f0SCatalin Marinas  * into virtual address `from'
3904f04d8f0SCatalin Marinas  */
3914f04d8f0SCatalin Marinas #define io_remap_pfn_range(vma,from,pfn,size,prot) \
3924f04d8f0SCatalin Marinas 		remap_pfn_range(vma, from, pfn, size, prot)
3934f04d8f0SCatalin Marinas 
3944f04d8f0SCatalin Marinas #define pgtable_cache_init() do { } while (0)
3954f04d8f0SCatalin Marinas 
3964f04d8f0SCatalin Marinas #endif /* !__ASSEMBLY__ */
3974f04d8f0SCatalin Marinas 
3984f04d8f0SCatalin Marinas #endif /* __ASM_PGTABLE_H */
399