18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2009 Chen Liqin <liqin.chen@sunplusct.com>
48c2ecf20Sopenharmony_ci * Copyright (C) 2012 Regents of the University of California
58c2ecf20Sopenharmony_ci * Copyright (C) 2017 SiFive
68c2ecf20Sopenharmony_ci * Copyright (C) 2017 XiaojingZhu <zhuxiaoj@ict.ac.cn>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#ifndef _ASM_RISCV_PAGE_H
108c2ecf20Sopenharmony_ci#define _ASM_RISCV_PAGE_H
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/pfn.h>
138c2ecf20Sopenharmony_ci#include <linux/const.h>
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#define PAGE_SHIFT	(12)
168c2ecf20Sopenharmony_ci#define PAGE_SIZE	(_AC(1, UL) << PAGE_SHIFT)
178c2ecf20Sopenharmony_ci#define PAGE_MASK	(~(PAGE_SIZE - 1))
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#ifdef CONFIG_64BIT
208c2ecf20Sopenharmony_ci#define HUGE_MAX_HSTATE		2
218c2ecf20Sopenharmony_ci#else
228c2ecf20Sopenharmony_ci#define HUGE_MAX_HSTATE		1
238c2ecf20Sopenharmony_ci#endif
248c2ecf20Sopenharmony_ci#define HPAGE_SHIFT		PMD_SHIFT
258c2ecf20Sopenharmony_ci#define HPAGE_SIZE		(_AC(1, UL) << HPAGE_SHIFT)
268c2ecf20Sopenharmony_ci#define HPAGE_MASK              (~(HPAGE_SIZE - 1))
278c2ecf20Sopenharmony_ci#define HUGETLB_PAGE_ORDER      (HPAGE_SHIFT - PAGE_SHIFT)
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci/*
308c2ecf20Sopenharmony_ci * PAGE_OFFSET -- the first address of the first page of memory.
318c2ecf20Sopenharmony_ci * When not using MMU this corresponds to the first free page in
328c2ecf20Sopenharmony_ci * physical memory (aligned on a page boundary).
338c2ecf20Sopenharmony_ci */
348c2ecf20Sopenharmony_ci#define PAGE_OFFSET		_AC(CONFIG_PAGE_OFFSET, UL)
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#define KERN_VIRT_SIZE (-PAGE_OFFSET)
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci#define PAGE_UP(addr)	(((addr)+((PAGE_SIZE)-1))&(~((PAGE_SIZE)-1)))
418c2ecf20Sopenharmony_ci#define PAGE_DOWN(addr)	((addr)&(~((PAGE_SIZE)-1)))
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci/* align addr on a size boundary - adjust address up/down if needed */
448c2ecf20Sopenharmony_ci#define _ALIGN_UP(addr, size)	(((addr)+((size)-1))&(~((size)-1)))
458c2ecf20Sopenharmony_ci#define _ALIGN_DOWN(addr, size)	((addr)&(~((size)-1)))
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci/* align addr on a size boundary - adjust address up if needed */
488c2ecf20Sopenharmony_ci#define _ALIGN(addr, size)	_ALIGN_UP(addr, size)
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci#define clear_page(pgaddr)			memset((pgaddr), 0, PAGE_SIZE)
518c2ecf20Sopenharmony_ci#define copy_page(to, from)			memcpy((to), (from), PAGE_SIZE)
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci#define clear_user_page(pgaddr, vaddr, page)	memset((pgaddr), 0, PAGE_SIZE)
548c2ecf20Sopenharmony_ci#define copy_user_page(vto, vfrom, vaddr, topg) \
558c2ecf20Sopenharmony_ci			memcpy((vto), (vfrom), PAGE_SIZE)
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci/*
588c2ecf20Sopenharmony_ci * Use struct definitions to apply C type checking
598c2ecf20Sopenharmony_ci */
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci/* Page Global Directory entry */
628c2ecf20Sopenharmony_citypedef struct {
638c2ecf20Sopenharmony_ci	unsigned long pgd;
648c2ecf20Sopenharmony_ci} pgd_t;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci/* Page Table entry */
678c2ecf20Sopenharmony_citypedef struct {
688c2ecf20Sopenharmony_ci	unsigned long pte;
698c2ecf20Sopenharmony_ci} pte_t;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_citypedef struct {
728c2ecf20Sopenharmony_ci	unsigned long pgprot;
738c2ecf20Sopenharmony_ci} pgprot_t;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_citypedef struct page *pgtable_t;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci#define pte_val(x)	((x).pte)
788c2ecf20Sopenharmony_ci#define pgd_val(x)	((x).pgd)
798c2ecf20Sopenharmony_ci#define pgprot_val(x)	((x).pgprot)
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci#define __pte(x)	((pte_t) { (x) })
828c2ecf20Sopenharmony_ci#define __pgd(x)	((pgd_t) { (x) })
838c2ecf20Sopenharmony_ci#define __pgprot(x)	((pgprot_t) { (x) })
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci#ifdef CONFIG_64BIT
868c2ecf20Sopenharmony_ci#define PTE_FMT "%016lx"
878c2ecf20Sopenharmony_ci#else
888c2ecf20Sopenharmony_ci#define PTE_FMT "%08lx"
898c2ecf20Sopenharmony_ci#endif
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci#ifdef CONFIG_MMU
928c2ecf20Sopenharmony_ciextern unsigned long va_pa_offset;
938c2ecf20Sopenharmony_ci#ifdef CONFIG_64BIT
948c2ecf20Sopenharmony_ciextern unsigned long va_kernel_pa_offset;
958c2ecf20Sopenharmony_ci#endif
968c2ecf20Sopenharmony_ciextern unsigned long pfn_base;
978c2ecf20Sopenharmony_ci#define ARCH_PFN_OFFSET		(pfn_base)
988c2ecf20Sopenharmony_ci#else
998c2ecf20Sopenharmony_ci#define va_pa_offset		0
1008c2ecf20Sopenharmony_ci#ifdef CONFIG_64BIT
1018c2ecf20Sopenharmony_ci#define va_kernel_pa_offset	0
1028c2ecf20Sopenharmony_ci#endif
1038c2ecf20Sopenharmony_ci#define ARCH_PFN_OFFSET		(PAGE_OFFSET >> PAGE_SHIFT)
1048c2ecf20Sopenharmony_ci#endif /* CONFIG_MMU */
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ciextern unsigned long max_low_pfn;
1078c2ecf20Sopenharmony_ciextern unsigned long min_low_pfn;
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ciextern unsigned long kernel_virt_addr;
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci#ifdef CONFIG_64BIT
1128c2ecf20Sopenharmony_ci#define linear_mapping_pa_to_va(x)	((void *)((unsigned long)(x) + va_pa_offset))
1138c2ecf20Sopenharmony_ci#define kernel_mapping_pa_to_va(x)	((void *)((unsigned long)(x) + va_kernel_pa_offset))
1148c2ecf20Sopenharmony_ci#define __pa_to_va_nodebug(x)		linear_mapping_pa_to_va(x)
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci#define linear_mapping_va_to_pa(x)	((unsigned long)(x) - va_pa_offset)
1178c2ecf20Sopenharmony_ci#define kernel_mapping_va_to_pa(x)	((unsigned long)(x) - va_kernel_pa_offset)
1188c2ecf20Sopenharmony_ci#define __va_to_pa_nodebug(x)	({						\
1198c2ecf20Sopenharmony_ci	unsigned long _x = x;							\
1208c2ecf20Sopenharmony_ci	(_x < kernel_virt_addr) ?						\
1218c2ecf20Sopenharmony_ci		linear_mapping_va_to_pa(_x) : kernel_mapping_va_to_pa(_x);	\
1228c2ecf20Sopenharmony_ci	})
1238c2ecf20Sopenharmony_ci#else
1248c2ecf20Sopenharmony_ci#define __pa_to_va_nodebug(x)  ((void *)((unsigned long) (x) + va_pa_offset))
1258c2ecf20Sopenharmony_ci#define __va_to_pa_nodebug(x)  ((unsigned long)(x) - va_pa_offset)
1268c2ecf20Sopenharmony_ci#endif
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_VIRTUAL
1298c2ecf20Sopenharmony_ciextern phys_addr_t __virt_to_phys(unsigned long x);
1308c2ecf20Sopenharmony_ciextern phys_addr_t __phys_addr_symbol(unsigned long x);
1318c2ecf20Sopenharmony_ci#else
1328c2ecf20Sopenharmony_ci#define __virt_to_phys(x)	__va_to_pa_nodebug(x)
1338c2ecf20Sopenharmony_ci#define __phys_addr_symbol(x)	__va_to_pa_nodebug(x)
1348c2ecf20Sopenharmony_ci#endif /* CONFIG_DEBUG_VIRTUAL */
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci#define __pa_symbol(x)	__phys_addr_symbol(RELOC_HIDE((unsigned long)(x), 0))
1378c2ecf20Sopenharmony_ci#define __pa(x)		__virt_to_phys((unsigned long)(x))
1388c2ecf20Sopenharmony_ci#define __va(x)		((void *)__pa_to_va_nodebug((phys_addr_t)(x)))
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci#define phys_to_pfn(phys)	(PFN_DOWN(phys))
1418c2ecf20Sopenharmony_ci#define pfn_to_phys(pfn)	(PFN_PHYS(pfn))
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci#define virt_to_pfn(vaddr)	(phys_to_pfn(__pa(vaddr)))
1448c2ecf20Sopenharmony_ci#define pfn_to_virt(pfn)	(__va(pfn_to_phys(pfn)))
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci#define virt_to_page(vaddr)	(pfn_to_page(virt_to_pfn(vaddr)))
1478c2ecf20Sopenharmony_ci#define page_to_virt(page)	(pfn_to_virt(page_to_pfn(page)))
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci#define page_to_phys(page)	(pfn_to_phys(page_to_pfn(page)))
1508c2ecf20Sopenharmony_ci#define page_to_bus(page)	(page_to_phys(page))
1518c2ecf20Sopenharmony_ci#define phys_to_page(paddr)	(pfn_to_page(phys_to_pfn(paddr)))
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci#ifdef CONFIG_FLATMEM
1548c2ecf20Sopenharmony_ci#define pfn_valid(pfn) \
1558c2ecf20Sopenharmony_ci	(((pfn) >= ARCH_PFN_OFFSET) && (((pfn) - ARCH_PFN_OFFSET) < max_mapnr))
1568c2ecf20Sopenharmony_ci#endif
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci#endif /* __ASSEMBLY__ */
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci#define virt_addr_valid(vaddr)	({						\
1618c2ecf20Sopenharmony_ci	unsigned long _addr = (unsigned long)vaddr;				\
1628c2ecf20Sopenharmony_ci	(unsigned long)(_addr) >= PAGE_OFFSET && pfn_valid(virt_to_pfn(_addr));	\
1638c2ecf20Sopenharmony_ci})
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci#define VM_DATA_DEFAULT_FLAGS	VM_DATA_FLAGS_NON_EXEC
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci#include <asm-generic/memory_model.h>
1688c2ecf20Sopenharmony_ci#include <asm-generic/getorder.h>
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci#endif /* _ASM_RISCV_PAGE_H */
171