18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#ifndef __ASM_CSKY_PGTABLE_H
58c2ecf20Sopenharmony_ci#define __ASM_CSKY_PGTABLE_H
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <asm/fixmap.h>
88c2ecf20Sopenharmony_ci#include <asm/memory.h>
98c2ecf20Sopenharmony_ci#include <asm/addrspace.h>
108c2ecf20Sopenharmony_ci#include <abi/pgtable-bits.h>
118c2ecf20Sopenharmony_ci#include <asm-generic/pgtable-nopmd.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#define PGDIR_SHIFT		22
148c2ecf20Sopenharmony_ci#define PGDIR_SIZE		(1UL << PGDIR_SHIFT)
158c2ecf20Sopenharmony_ci#define PGDIR_MASK		(~(PGDIR_SIZE-1))
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#define USER_PTRS_PER_PGD	(0x80000000UL/PGDIR_SIZE)
188c2ecf20Sopenharmony_ci#define FIRST_USER_ADDRESS	0UL
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci/*
218c2ecf20Sopenharmony_ci * C-SKY is two-level paging structure:
228c2ecf20Sopenharmony_ci */
238c2ecf20Sopenharmony_ci#define PGD_ORDER	0
248c2ecf20Sopenharmony_ci#define PTE_ORDER	0
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#define PTRS_PER_PGD	((PAGE_SIZE << PGD_ORDER) / sizeof(pgd_t))
278c2ecf20Sopenharmony_ci#define PTRS_PER_PMD	1
288c2ecf20Sopenharmony_ci#define PTRS_PER_PTE	((PAGE_SIZE << PTE_ORDER) / sizeof(pte_t))
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#define pte_ERROR(e) \
318c2ecf20Sopenharmony_ci	pr_err("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, (e).pte_low)
328c2ecf20Sopenharmony_ci#define pgd_ERROR(e) \
338c2ecf20Sopenharmony_ci	pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#define pmd_page(pmd)	(pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
368c2ecf20Sopenharmony_ci#define pte_clear(mm, addr, ptep)	set_pte((ptep), \
378c2ecf20Sopenharmony_ci	(((unsigned int) addr & PAGE_OFFSET) ? __pte(_PAGE_GLOBAL) : __pte(0)))
388c2ecf20Sopenharmony_ci#define pte_none(pte)		(!(pte_val(pte) & ~_PAGE_GLOBAL))
398c2ecf20Sopenharmony_ci#define pte_present(pte)	(pte_val(pte) & _PAGE_PRESENT)
408c2ecf20Sopenharmony_ci#define pte_pfn(x)	((unsigned long)((x).pte_low >> PAGE_SHIFT))
418c2ecf20Sopenharmony_ci#define pfn_pte(pfn, prot) __pte(((unsigned long long)(pfn) << PAGE_SHIFT) \
428c2ecf20Sopenharmony_ci				| pgprot_val(prot))
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci#define __READABLE	(_PAGE_READ | _PAGE_VALID | _PAGE_ACCESSED)
458c2ecf20Sopenharmony_ci#define __WRITEABLE	(_PAGE_WRITE | _PAGE_DIRTY | _PAGE_MODIFIED)
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci#define _PAGE_CHG_MASK	(PAGE_MASK | _PAGE_ACCESSED | _PAGE_MODIFIED | \
488c2ecf20Sopenharmony_ci			 _CACHE_MASK)
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci#define __swp_type(x)			(((x).val >> 4) & 0xff)
518c2ecf20Sopenharmony_ci#define __swp_offset(x)			((x).val >> 12)
528c2ecf20Sopenharmony_ci#define __swp_entry(type, offset)	((swp_entry_t) {((type) << 4) | \
538c2ecf20Sopenharmony_ci					((offset) << 12) })
548c2ecf20Sopenharmony_ci#define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
558c2ecf20Sopenharmony_ci#define __swp_entry_to_pte(x)		((pte_t) { (x).val })
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci#define pte_page(x)			pfn_to_page(pte_pfn(x))
588c2ecf20Sopenharmony_ci#define __mk_pte(page_nr, pgprot)	__pte(((page_nr) << PAGE_SHIFT) | \
598c2ecf20Sopenharmony_ci					pgprot_val(pgprot))
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci/*
628c2ecf20Sopenharmony_ci * CSKY can't do page protection for execute, and considers that the same like
638c2ecf20Sopenharmony_ci * read. Also, write permissions imply read permissions. This is the closest
648c2ecf20Sopenharmony_ci * we can get by reasonable means..
658c2ecf20Sopenharmony_ci */
668c2ecf20Sopenharmony_ci#define PAGE_NONE	__pgprot(_PAGE_PRESENT | _CACHE_CACHED)
678c2ecf20Sopenharmony_ci#define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
688c2ecf20Sopenharmony_ci				_CACHE_CACHED)
698c2ecf20Sopenharmony_ci#define PAGE_COPY	__pgprot(_PAGE_PRESENT | _PAGE_READ | _CACHE_CACHED)
708c2ecf20Sopenharmony_ci#define PAGE_READONLY	__pgprot(_PAGE_PRESENT | _PAGE_READ | _CACHE_CACHED)
718c2ecf20Sopenharmony_ci#define PAGE_KERNEL	__pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
728c2ecf20Sopenharmony_ci				_PAGE_GLOBAL | _CACHE_CACHED)
738c2ecf20Sopenharmony_ci#define PAGE_USERIO	__pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
748c2ecf20Sopenharmony_ci				_CACHE_CACHED)
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci#define _PAGE_IOREMAP \
778c2ecf20Sopenharmony_ci	(_PAGE_PRESENT | __READABLE | __WRITEABLE | _PAGE_GLOBAL | \
788c2ecf20Sopenharmony_ci	 _CACHE_UNCACHED | _PAGE_SO)
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci#define __P000	PAGE_NONE
818c2ecf20Sopenharmony_ci#define __P001	PAGE_READONLY
828c2ecf20Sopenharmony_ci#define __P010	PAGE_COPY
838c2ecf20Sopenharmony_ci#define __P011	PAGE_COPY
848c2ecf20Sopenharmony_ci#define __P100	PAGE_READONLY
858c2ecf20Sopenharmony_ci#define __P101	PAGE_READONLY
868c2ecf20Sopenharmony_ci#define __P110	PAGE_COPY
878c2ecf20Sopenharmony_ci#define __P111	PAGE_COPY
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci#define __S000	PAGE_NONE
908c2ecf20Sopenharmony_ci#define __S001	PAGE_READONLY
918c2ecf20Sopenharmony_ci#define __S010	PAGE_SHARED
928c2ecf20Sopenharmony_ci#define __S011	PAGE_SHARED
938c2ecf20Sopenharmony_ci#define __S100	PAGE_READONLY
948c2ecf20Sopenharmony_ci#define __S101	PAGE_READONLY
958c2ecf20Sopenharmony_ci#define __S110	PAGE_SHARED
968c2ecf20Sopenharmony_ci#define __S111	PAGE_SHARED
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ciextern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
998c2ecf20Sopenharmony_ci#define ZERO_PAGE(vaddr)	(virt_to_page(empty_zero_page))
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ciextern void load_pgd(unsigned long pg_dir);
1028c2ecf20Sopenharmony_ciextern pte_t invalid_pte_table[PTRS_PER_PTE];
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistatic inline void set_pte(pte_t *p, pte_t pte)
1058c2ecf20Sopenharmony_ci{
1068c2ecf20Sopenharmony_ci	*p = pte;
1078c2ecf20Sopenharmony_ci#if defined(CONFIG_CPU_NEED_TLBSYNC)
1088c2ecf20Sopenharmony_ci	dcache_wb_line((u32)p);
1098c2ecf20Sopenharmony_ci#endif
1108c2ecf20Sopenharmony_ci	/* prevent out of order excution */
1118c2ecf20Sopenharmony_ci	smp_mb();
1128c2ecf20Sopenharmony_ci}
1138c2ecf20Sopenharmony_ci#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval)
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_cistatic inline pte_t *pmd_page_vaddr(pmd_t pmd)
1168c2ecf20Sopenharmony_ci{
1178c2ecf20Sopenharmony_ci	unsigned long ptr;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	ptr = pmd_val(pmd);
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	return __va(ptr);
1228c2ecf20Sopenharmony_ci}
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci#define pmd_phys(pmd) pmd_val(pmd)
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_cistatic inline void set_pmd(pmd_t *p, pmd_t pmd)
1278c2ecf20Sopenharmony_ci{
1288c2ecf20Sopenharmony_ci	*p = pmd;
1298c2ecf20Sopenharmony_ci#if defined(CONFIG_CPU_NEED_TLBSYNC)
1308c2ecf20Sopenharmony_ci	dcache_wb_line((u32)p);
1318c2ecf20Sopenharmony_ci#endif
1328c2ecf20Sopenharmony_ci	/* prevent specul excute */
1338c2ecf20Sopenharmony_ci	smp_mb();
1348c2ecf20Sopenharmony_ci}
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_cistatic inline int pmd_none(pmd_t pmd)
1388c2ecf20Sopenharmony_ci{
1398c2ecf20Sopenharmony_ci	return pmd_val(pmd) == __pa(invalid_pte_table);
1408c2ecf20Sopenharmony_ci}
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci#define pmd_bad(pmd)	(pmd_val(pmd) & ~PAGE_MASK)
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_cistatic inline int pmd_present(pmd_t pmd)
1458c2ecf20Sopenharmony_ci{
1468c2ecf20Sopenharmony_ci	return (pmd_val(pmd) != __pa(invalid_pte_table));
1478c2ecf20Sopenharmony_ci}
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_cistatic inline void pmd_clear(pmd_t *p)
1508c2ecf20Sopenharmony_ci{
1518c2ecf20Sopenharmony_ci	pmd_val(*p) = (__pa(invalid_pte_table));
1528c2ecf20Sopenharmony_ci#if defined(CONFIG_CPU_NEED_TLBSYNC)
1538c2ecf20Sopenharmony_ci	dcache_wb_line((u32)p);
1548c2ecf20Sopenharmony_ci#endif
1558c2ecf20Sopenharmony_ci}
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci/*
1588c2ecf20Sopenharmony_ci * The following only work if pte_present() is true.
1598c2ecf20Sopenharmony_ci * Undefined behaviour if not..
1608c2ecf20Sopenharmony_ci */
1618c2ecf20Sopenharmony_cistatic inline int pte_read(pte_t pte)
1628c2ecf20Sopenharmony_ci{
1638c2ecf20Sopenharmony_ci	return pte.pte_low & _PAGE_READ;
1648c2ecf20Sopenharmony_ci}
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_cistatic inline int pte_write(pte_t pte)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	return (pte).pte_low & _PAGE_WRITE;
1698c2ecf20Sopenharmony_ci}
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_cistatic inline int pte_dirty(pte_t pte)
1728c2ecf20Sopenharmony_ci{
1738c2ecf20Sopenharmony_ci	return (pte).pte_low & _PAGE_MODIFIED;
1748c2ecf20Sopenharmony_ci}
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_cistatic inline int pte_young(pte_t pte)
1778c2ecf20Sopenharmony_ci{
1788c2ecf20Sopenharmony_ci	return (pte).pte_low & _PAGE_ACCESSED;
1798c2ecf20Sopenharmony_ci}
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_cistatic inline pte_t pte_wrprotect(pte_t pte)
1828c2ecf20Sopenharmony_ci{
1838c2ecf20Sopenharmony_ci	pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_DIRTY);
1848c2ecf20Sopenharmony_ci	return pte;
1858c2ecf20Sopenharmony_ci}
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_cistatic inline pte_t pte_mkclean(pte_t pte)
1888c2ecf20Sopenharmony_ci{
1898c2ecf20Sopenharmony_ci	pte_val(pte) &= ~(_PAGE_MODIFIED|_PAGE_DIRTY);
1908c2ecf20Sopenharmony_ci	return pte;
1918c2ecf20Sopenharmony_ci}
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_cistatic inline pte_t pte_mkold(pte_t pte)
1948c2ecf20Sopenharmony_ci{
1958c2ecf20Sopenharmony_ci	pte_val(pte) &= ~(_PAGE_ACCESSED|_PAGE_VALID);
1968c2ecf20Sopenharmony_ci	return pte;
1978c2ecf20Sopenharmony_ci}
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_cistatic inline pte_t pte_mkwrite(pte_t pte)
2008c2ecf20Sopenharmony_ci{
2018c2ecf20Sopenharmony_ci	pte_val(pte) |= _PAGE_WRITE;
2028c2ecf20Sopenharmony_ci	if (pte_val(pte) & _PAGE_MODIFIED)
2038c2ecf20Sopenharmony_ci		pte_val(pte) |= _PAGE_DIRTY;
2048c2ecf20Sopenharmony_ci	return pte;
2058c2ecf20Sopenharmony_ci}
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_cistatic inline pte_t pte_mkdirty(pte_t pte)
2088c2ecf20Sopenharmony_ci{
2098c2ecf20Sopenharmony_ci	pte_val(pte) |= _PAGE_MODIFIED;
2108c2ecf20Sopenharmony_ci	if (pte_val(pte) & _PAGE_WRITE)
2118c2ecf20Sopenharmony_ci		pte_val(pte) |= _PAGE_DIRTY;
2128c2ecf20Sopenharmony_ci	return pte;
2138c2ecf20Sopenharmony_ci}
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_cistatic inline pte_t pte_mkyoung(pte_t pte)
2168c2ecf20Sopenharmony_ci{
2178c2ecf20Sopenharmony_ci	pte_val(pte) |= _PAGE_ACCESSED;
2188c2ecf20Sopenharmony_ci	if (pte_val(pte) & _PAGE_READ)
2198c2ecf20Sopenharmony_ci		pte_val(pte) |= _PAGE_VALID;
2208c2ecf20Sopenharmony_ci	return pte;
2218c2ecf20Sopenharmony_ci}
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci#define __HAVE_PHYS_MEM_ACCESS_PROT
2248c2ecf20Sopenharmony_cistruct file;
2258c2ecf20Sopenharmony_ciextern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
2268c2ecf20Sopenharmony_ci				     unsigned long size, pgprot_t vma_prot);
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci/*
2298c2ecf20Sopenharmony_ci * Macro to make mark a page protection value as "uncacheable".  Note
2308c2ecf20Sopenharmony_ci * that "protection" is really a misnomer here as the protection value
2318c2ecf20Sopenharmony_ci * contains the memory attribute bits, dirty bits, and various other
2328c2ecf20Sopenharmony_ci * bits as well.
2338c2ecf20Sopenharmony_ci */
2348c2ecf20Sopenharmony_ci#define pgprot_noncached pgprot_noncached
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_cistatic inline pgprot_t pgprot_noncached(pgprot_t _prot)
2378c2ecf20Sopenharmony_ci{
2388c2ecf20Sopenharmony_ci	unsigned long prot = pgprot_val(_prot);
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED | _PAGE_SO;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	return __pgprot(prot);
2438c2ecf20Sopenharmony_ci}
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci#define pgprot_writecombine pgprot_writecombine
2468c2ecf20Sopenharmony_cistatic inline pgprot_t pgprot_writecombine(pgprot_t _prot)
2478c2ecf20Sopenharmony_ci{
2488c2ecf20Sopenharmony_ci	unsigned long prot = pgprot_val(_prot);
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED;
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	return __pgprot(prot);
2538c2ecf20Sopenharmony_ci}
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci/*
2568c2ecf20Sopenharmony_ci * Conversion functions: convert a page and protection to a page entry,
2578c2ecf20Sopenharmony_ci * and a page entry and page directory to the page they refer to.
2588c2ecf20Sopenharmony_ci */
2598c2ecf20Sopenharmony_ci#define mk_pte(page, pgprot)    pfn_pte(page_to_pfn(page), (pgprot))
2608c2ecf20Sopenharmony_cistatic inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
2618c2ecf20Sopenharmony_ci{
2628c2ecf20Sopenharmony_ci	return __pte((pte_val(pte) & _PAGE_CHG_MASK) |
2638c2ecf20Sopenharmony_ci		     (pgprot_val(newprot)));
2648c2ecf20Sopenharmony_ci}
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ciextern pgd_t swapper_pg_dir[PTRS_PER_PGD];
2678c2ecf20Sopenharmony_ciextern void paging_init(void);
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_civoid update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
2708c2ecf20Sopenharmony_ci		      pte_t *pte);
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
2738c2ecf20Sopenharmony_ci#define kern_addr_valid(addr)	(1)
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
2768c2ecf20Sopenharmony_ci	remap_pfn_range(vma, vaddr, pfn, size, prot)
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci#endif /* __ASM_CSKY_PGTABLE_H */
279