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