xref: /openbmc/linux/arch/riscv/include/asm/page.h (revision d32fd6bb9f2bc8178cdd65ebec1ad670a8bfa241)
150acfb2bSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
207037db5SPalmer Dabbelt /*
307037db5SPalmer Dabbelt  * Copyright (C) 2009 Chen Liqin <liqin.chen@sunplusct.com>
407037db5SPalmer Dabbelt  * Copyright (C) 2012 Regents of the University of California
507037db5SPalmer Dabbelt  * Copyright (C) 2017 SiFive
607037db5SPalmer Dabbelt  * Copyright (C) 2017 XiaojingZhu <zhuxiaoj@ict.ac.cn>
707037db5SPalmer Dabbelt  */
807037db5SPalmer Dabbelt 
907037db5SPalmer Dabbelt #ifndef _ASM_RISCV_PAGE_H
1007037db5SPalmer Dabbelt #define _ASM_RISCV_PAGE_H
1107037db5SPalmer Dabbelt 
1207037db5SPalmer Dabbelt #include <linux/pfn.h>
1307037db5SPalmer Dabbelt #include <linux/const.h>
1407037db5SPalmer Dabbelt 
1507037db5SPalmer Dabbelt #define PAGE_SHIFT	(12)
1607037db5SPalmer Dabbelt #define PAGE_SIZE	(_AC(1, UL) << PAGE_SHIFT)
1707037db5SPalmer Dabbelt #define PAGE_MASK	(~(PAGE_SIZE - 1))
1807037db5SPalmer Dabbelt 
199e953cdaSAlexandre Ghiti #define HPAGE_SHIFT		PMD_SHIFT
209e953cdaSAlexandre Ghiti #define HPAGE_SIZE		(_AC(1, UL) << HPAGE_SHIFT)
219e953cdaSAlexandre Ghiti #define HPAGE_MASK              (~(HPAGE_SIZE - 1))
229e953cdaSAlexandre Ghiti #define HUGETLB_PAGE_ORDER      (HPAGE_SHIFT - PAGE_SHIFT)
239e953cdaSAlexandre Ghiti 
2407037db5SPalmer Dabbelt /*
2507037db5SPalmer Dabbelt  * PAGE_OFFSET -- the first address of the first page of memory.
2607037db5SPalmer Dabbelt  * When not using MMU this corresponds to the first free page in
2707037db5SPalmer Dabbelt  * physical memory (aligned on a page boundary).
2807037db5SPalmer Dabbelt  */
29e8a62cc2SAlexandre Ghiti #ifdef CONFIG_64BIT
30e8a62cc2SAlexandre Ghiti #ifdef CONFIG_MMU
31e8a62cc2SAlexandre Ghiti #define PAGE_OFFSET		kernel_map.page_offset
32e8a62cc2SAlexandre Ghiti #else
3307037db5SPalmer Dabbelt #define PAGE_OFFSET		_AC(CONFIG_PAGE_OFFSET, UL)
34e8a62cc2SAlexandre Ghiti #endif
35e8a62cc2SAlexandre Ghiti /*
36bf564cf9SSong Shuai  * By default, CONFIG_PAGE_OFFSET value corresponds to SV57 address space so
37bf564cf9SSong Shuai  * define the PAGE_OFFSET value for SV48 and SV39.
38e8a62cc2SAlexandre Ghiti  */
39011f09d1SQinglin Pan #define PAGE_OFFSET_L4		_AC(0xffffaf8000000000, UL)
40e8a62cc2SAlexandre Ghiti #define PAGE_OFFSET_L3		_AC(0xffffffd800000000, UL)
41e8a62cc2SAlexandre Ghiti #else
42e8a62cc2SAlexandre Ghiti #define PAGE_OFFSET		_AC(CONFIG_PAGE_OFFSET, UL)
43e8a62cc2SAlexandre Ghiti #endif /* CONFIG_64BIT */
4407037db5SPalmer Dabbelt 
4507037db5SPalmer Dabbelt #ifndef __ASSEMBLY__
4607037db5SPalmer Dabbelt 
47ab0f7746SAndrew Jones #ifdef CONFIG_RISCV_ISA_ZICBOZ
48ab0f7746SAndrew Jones void clear_page(void *page);
49ab0f7746SAndrew Jones #else
5007037db5SPalmer Dabbelt #define clear_page(pgaddr)			memset((pgaddr), 0, PAGE_SIZE)
51ab0f7746SAndrew Jones #endif
5207037db5SPalmer Dabbelt #define copy_page(to, from)			memcpy((to), (from), PAGE_SIZE)
5307037db5SPalmer Dabbelt 
54ab0f7746SAndrew Jones #define clear_user_page(pgaddr, vaddr, page)	clear_page(pgaddr)
5507037db5SPalmer Dabbelt #define copy_user_page(vto, vfrom, vaddr, topg) \
5607037db5SPalmer Dabbelt 			memcpy((vto), (vfrom), PAGE_SIZE)
5707037db5SPalmer Dabbelt 
5807037db5SPalmer Dabbelt /*
5907037db5SPalmer Dabbelt  * Use struct definitions to apply C type checking
6007037db5SPalmer Dabbelt  */
6107037db5SPalmer Dabbelt 
6207037db5SPalmer Dabbelt /* Page Global Directory entry */
6307037db5SPalmer Dabbelt typedef struct {
6407037db5SPalmer Dabbelt 	unsigned long pgd;
6507037db5SPalmer Dabbelt } pgd_t;
6607037db5SPalmer Dabbelt 
6707037db5SPalmer Dabbelt /* Page Table entry */
6807037db5SPalmer Dabbelt typedef struct {
6907037db5SPalmer Dabbelt 	unsigned long pte;
7007037db5SPalmer Dabbelt } pte_t;
7107037db5SPalmer Dabbelt 
7207037db5SPalmer Dabbelt typedef struct {
7307037db5SPalmer Dabbelt 	unsigned long pgprot;
7407037db5SPalmer Dabbelt } pgprot_t;
7507037db5SPalmer Dabbelt 
7607037db5SPalmer Dabbelt typedef struct page *pgtable_t;
7707037db5SPalmer Dabbelt 
7807037db5SPalmer Dabbelt #define pte_val(x)	((x).pte)
7907037db5SPalmer Dabbelt #define pgd_val(x)	((x).pgd)
8007037db5SPalmer Dabbelt #define pgprot_val(x)	((x).pgprot)
8107037db5SPalmer Dabbelt 
8207037db5SPalmer Dabbelt #define __pte(x)	((pte_t) { (x) })
8307037db5SPalmer Dabbelt #define __pgd(x)	((pgd_t) { (x) })
8407037db5SPalmer Dabbelt #define __pgprot(x)	((pgprot_t) { (x) })
8507037db5SPalmer Dabbelt 
868581f387SAntony Pavlov #ifdef CONFIG_64BIT
8707037db5SPalmer Dabbelt #define PTE_FMT "%016lx"
8807037db5SPalmer Dabbelt #else
8907037db5SPalmer Dabbelt #define PTE_FMT "%08lx"
9007037db5SPalmer Dabbelt #endif
9107037db5SPalmer Dabbelt 
92b008e327SSamuel Holland #if defined(CONFIG_64BIT) && defined(CONFIG_MMU)
933335068fSAlexandre Ghiti /*
943335068fSAlexandre Ghiti  * We override this value as its generic definition uses __pa too early in
953335068fSAlexandre Ghiti  * the boot process (before kernel_map.va_pa_offset is set).
963335068fSAlexandre Ghiti  */
973335068fSAlexandre Ghiti #define MIN_MEMBLOCK_ADDR      0
983335068fSAlexandre Ghiti #endif
993335068fSAlexandre Ghiti 
1006bd33e1eSChristoph Hellwig #ifdef CONFIG_MMU
101a7407a13SAlexandre Ghiti #define ARCH_PFN_OFFSET		(PFN_DOWN((unsigned long)phys_ram_base))
1026bd33e1eSChristoph Hellwig #else
1036bd33e1eSChristoph Hellwig #define ARCH_PFN_OFFSET		(PAGE_OFFSET >> PAGE_SHIFT)
1046bd33e1eSChristoph Hellwig #endif /* CONFIG_MMU */
10507037db5SPalmer Dabbelt 
106658e2c51SAlexandre Ghiti struct kernel_mapping {
107e8a62cc2SAlexandre Ghiti 	unsigned long page_offset;
108658e2c51SAlexandre Ghiti 	unsigned long virt_addr;
10984fe419dSAlexandre Ghiti 	unsigned long virt_offset;
110658e2c51SAlexandre Ghiti 	uintptr_t phys_addr;
111658e2c51SAlexandre Ghiti 	uintptr_t size;
112658e2c51SAlexandre Ghiti 	/* Offset between linear mapping virtual address and kernel load address */
113658e2c51SAlexandre Ghiti 	unsigned long va_pa_offset;
114658e2c51SAlexandre Ghiti 	/* Offset between kernel mapping virtual address and kernel load address */
115658e2c51SAlexandre Ghiti 	unsigned long va_kernel_pa_offset;
116658e2c51SAlexandre Ghiti 	unsigned long va_kernel_xip_pa_offset;
117658e2c51SAlexandre Ghiti #ifdef CONFIG_XIP_KERNEL
118658e2c51SAlexandre Ghiti 	uintptr_t xiprom;
119658e2c51SAlexandre Ghiti 	uintptr_t xiprom_sz;
120658e2c51SAlexandre Ghiti #endif
121658e2c51SAlexandre Ghiti };
122658e2c51SAlexandre Ghiti 
123658e2c51SAlexandre Ghiti extern struct kernel_mapping kernel_map;
1246d7f91d9SAlexandre Ghiti extern phys_addr_t phys_ram_base;
125*a4a7ac3dSXu Lu extern unsigned long vmemmap_start_pfn;
1262bfc6cd8SAlexandre Ghiti 
127e5c35fa0SAlexandre Ghiti #define is_kernel_mapping(x)	\
128658e2c51SAlexandre Ghiti 	((x) >= kernel_map.virt_addr && (x) < (kernel_map.virt_addr + kernel_map.size))
1290aba691aSAlexandre Ghiti 
130e5c35fa0SAlexandre Ghiti #define is_linear_mapping(x)	\
1318b274f22SAlexandre Ghiti 	((x) >= PAGE_OFFSET && (!IS_ENABLED(CONFIG_64BIT) || (x) < PAGE_OFFSET + KERN_VIRT_SIZE))
132e5c35fa0SAlexandre Ghiti 
1333335068fSAlexandre Ghiti #ifndef CONFIG_DEBUG_VIRTUAL
134658e2c51SAlexandre Ghiti #define linear_mapping_pa_to_va(x)	((void *)((unsigned long)(x) + kernel_map.va_pa_offset))
1353335068fSAlexandre Ghiti #else
1363335068fSAlexandre Ghiti void *linear_mapping_pa_to_va(unsigned long x);
1373335068fSAlexandre Ghiti #endif
13844c92257SVitaly Wool #define kernel_mapping_pa_to_va(y)	({					\
139583286e2SSamuel Holland 	unsigned long _y = (unsigned long)(y);					\
1406d7f91d9SAlexandre Ghiti 	(IS_ENABLED(CONFIG_XIP_KERNEL) && _y < phys_ram_base) ?			\
141583286e2SSamuel Holland 		(void *)(_y + kernel_map.va_kernel_xip_pa_offset) :		\
142583286e2SSamuel Holland 		(void *)(_y + kernel_map.va_kernel_pa_offset + XIP_OFFSET);	\
14344c92257SVitaly Wool 	})
1442bfc6cd8SAlexandre Ghiti #define __pa_to_va_nodebug(x)		linear_mapping_pa_to_va(x)
1452bfc6cd8SAlexandre Ghiti 
1463335068fSAlexandre Ghiti #ifndef CONFIG_DEBUG_VIRTUAL
147658e2c51SAlexandre Ghiti #define linear_mapping_va_to_pa(x)	((unsigned long)(x) - kernel_map.va_pa_offset)
1483335068fSAlexandre Ghiti #else
1493335068fSAlexandre Ghiti phys_addr_t linear_mapping_va_to_pa(unsigned long x);
1503335068fSAlexandre Ghiti #endif
15144c92257SVitaly Wool #define kernel_mapping_va_to_pa(y) ({						\
152583286e2SSamuel Holland 	unsigned long _y = (unsigned long)(y);					\
15359a27e11SAlexandre Ghiti 	(IS_ENABLED(CONFIG_XIP_KERNEL) && _y < kernel_map.virt_addr + XIP_OFFSET) ? \
154583286e2SSamuel Holland 		(_y - kernel_map.va_kernel_xip_pa_offset) :			\
155583286e2SSamuel Holland 		(_y - kernel_map.va_kernel_pa_offset - XIP_OFFSET);		\
15644c92257SVitaly Wool 	})
1577094e6acSAlexandre Ghiti 
1582bfc6cd8SAlexandre Ghiti #define __va_to_pa_nodebug(x)	({						\
1592bfc6cd8SAlexandre Ghiti 	unsigned long _x = x;							\
160e5c35fa0SAlexandre Ghiti 	is_linear_mapping(_x) ?							\
1612bfc6cd8SAlexandre Ghiti 		linear_mapping_va_to_pa(_x) : kernel_mapping_va_to_pa(_x);	\
1622bfc6cd8SAlexandre Ghiti 	})
1636435f773SZong Li 
1646435f773SZong Li #ifdef CONFIG_DEBUG_VIRTUAL
1656435f773SZong Li extern phys_addr_t __virt_to_phys(unsigned long x);
1666435f773SZong Li extern phys_addr_t __phys_addr_symbol(unsigned long x);
1676435f773SZong Li #else
1686435f773SZong Li #define __virt_to_phys(x)	__va_to_pa_nodebug(x)
1696435f773SZong Li #define __phys_addr_symbol(x)	__va_to_pa_nodebug(x)
1706435f773SZong Li #endif /* CONFIG_DEBUG_VIRTUAL */
1716435f773SZong Li 
1726435f773SZong Li #define __pa_symbol(x)	__phys_addr_symbol(RELOC_HIDE((unsigned long)(x), 0))
1736435f773SZong Li #define __pa(x)		__virt_to_phys((unsigned long)(x))
1746435f773SZong Li #define __va(x)		((void *)__pa_to_va_nodebug((phys_addr_t)(x)))
17507037db5SPalmer Dabbelt 
17607037db5SPalmer Dabbelt #define phys_to_pfn(phys)	(PFN_DOWN(phys))
17707037db5SPalmer Dabbelt #define pfn_to_phys(pfn)	(PFN_PHYS(pfn))
17807037db5SPalmer Dabbelt 
17907037db5SPalmer Dabbelt #define virt_to_pfn(vaddr)	(phys_to_pfn(__pa(vaddr)))
18007037db5SPalmer Dabbelt #define pfn_to_virt(pfn)	(__va(pfn_to_phys(pfn)))
18107037db5SPalmer Dabbelt 
18207037db5SPalmer Dabbelt #define virt_to_page(vaddr)	(pfn_to_page(virt_to_pfn(vaddr)))
18307037db5SPalmer Dabbelt #define page_to_virt(page)	(pfn_to_virt(page_to_pfn(page)))
18407037db5SPalmer Dabbelt 
18507037db5SPalmer Dabbelt #define page_to_phys(page)	(pfn_to_phys(page_to_pfn(page)))
18607037db5SPalmer Dabbelt #define phys_to_page(paddr)	(pfn_to_page(phys_to_pfn(paddr)))
18707037db5SPalmer Dabbelt 
188dffe11e2STong Tiangen #define sym_to_pfn(x)           __phys_to_pfn(__pa_symbol(x))
189dffe11e2STong Tiangen 
19084fe419dSAlexandre Ghiti unsigned long kaslr_offset(void);
19184fe419dSAlexandre Ghiti 
19207037db5SPalmer Dabbelt #endif /* __ASSEMBLY__ */
19307037db5SPalmer Dabbelt 
1942ab54382SAlexandre Ghiti #define virt_addr_valid(vaddr)	({						\
1952ab54382SAlexandre Ghiti 	unsigned long _addr = (unsigned long)vaddr;				\
1962ab54382SAlexandre Ghiti 	(unsigned long)(_addr) >= PAGE_OFFSET && pfn_valid(virt_to_pfn(_addr));	\
1972ab54382SAlexandre Ghiti })
19807037db5SPalmer Dabbelt 
199c62da0c3SAnshuman Khandual #define VM_DATA_DEFAULT_FLAGS	VM_DATA_FLAGS_NON_EXEC
20007037db5SPalmer Dabbelt 
20107037db5SPalmer Dabbelt #include <asm-generic/memory_model.h>
20207037db5SPalmer Dabbelt #include <asm-generic/getorder.h>
20307037db5SPalmer Dabbelt 
20407037db5SPalmer Dabbelt #endif /* _ASM_RISCV_PAGE_H */
205