162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci#ifndef __ASM_CSKY_PGTABLE_H
462306a36Sopenharmony_ci#define __ASM_CSKY_PGTABLE_H
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <asm/fixmap.h>
762306a36Sopenharmony_ci#include <asm/memory.h>
862306a36Sopenharmony_ci#include <asm/addrspace.h>
962306a36Sopenharmony_ci#include <abi/pgtable-bits.h>
1062306a36Sopenharmony_ci#include <asm-generic/pgtable-nopmd.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#define PGDIR_SHIFT		22
1362306a36Sopenharmony_ci#define PGDIR_SIZE		(1UL << PGDIR_SHIFT)
1462306a36Sopenharmony_ci#define PGDIR_MASK		(~(PGDIR_SIZE-1))
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define USER_PTRS_PER_PGD	(PAGE_OFFSET/PGDIR_SIZE)
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci/*
1962306a36Sopenharmony_ci * C-SKY is two-level paging structure:
2062306a36Sopenharmony_ci */
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#define PTRS_PER_PGD	(PAGE_SIZE / sizeof(pgd_t))
2362306a36Sopenharmony_ci#define PTRS_PER_PMD	1
2462306a36Sopenharmony_ci#define PTRS_PER_PTE	(PAGE_SIZE / sizeof(pte_t))
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define pte_ERROR(e) \
2762306a36Sopenharmony_ci	pr_err("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, (e).pte_low)
2862306a36Sopenharmony_ci#define pgd_ERROR(e) \
2962306a36Sopenharmony_ci	pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#define PFN_PTE_SHIFT	PAGE_SHIFT
3262306a36Sopenharmony_ci#define pmd_pfn(pmd)	(pmd_phys(pmd) >> PAGE_SHIFT)
3362306a36Sopenharmony_ci#define pmd_page(pmd)	(pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
3462306a36Sopenharmony_ci#define pte_clear(mm, addr, ptep)	set_pte((ptep), \
3562306a36Sopenharmony_ci	(((unsigned int) addr >= PAGE_OFFSET) ? __pte(_PAGE_GLOBAL) : __pte(0)))
3662306a36Sopenharmony_ci#define pte_none(pte)		(!(pte_val(pte) & ~_PAGE_GLOBAL))
3762306a36Sopenharmony_ci#define pte_present(pte)	(pte_val(pte) & _PAGE_PRESENT)
3862306a36Sopenharmony_ci#define pte_pfn(x)	((unsigned long)((x).pte_low >> PAGE_SHIFT))
3962306a36Sopenharmony_ci#define pfn_pte(pfn, prot) __pte(((unsigned long long)(pfn) << PAGE_SHIFT) \
4062306a36Sopenharmony_ci				| pgprot_val(prot))
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
4362306a36Sopenharmony_ci#define __swp_entry_to_pte(x)		((pte_t) { (x).val })
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci#define pte_page(x)			pfn_to_page(pte_pfn(x))
4662306a36Sopenharmony_ci#define __mk_pte(page_nr, pgprot)	__pte(((page_nr) << PAGE_SHIFT) | \
4762306a36Sopenharmony_ci					pgprot_val(pgprot))
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci/*
5062306a36Sopenharmony_ci * C-SKY only has VALID and DIRTY bit in hardware. So we need to use the
5162306a36Sopenharmony_ci * two bits emulate PRESENT, READ, WRITE, EXEC, MODIFIED, ACCESSED.
5262306a36Sopenharmony_ci */
5362306a36Sopenharmony_ci#define _PAGE_BASE	(_PAGE_PRESENT | _PAGE_ACCESSED)
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci#define PAGE_NONE	__pgprot(_PAGE_PROT_NONE)
5662306a36Sopenharmony_ci#define PAGE_READ	__pgprot(_PAGE_BASE | _PAGE_READ | \
5762306a36Sopenharmony_ci				_CACHE_CACHED)
5862306a36Sopenharmony_ci#define PAGE_WRITE	__pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_WRITE | \
5962306a36Sopenharmony_ci				_CACHE_CACHED)
6062306a36Sopenharmony_ci#define PAGE_SHARED PAGE_WRITE
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci#define PAGE_KERNEL	__pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_VALID | \
6362306a36Sopenharmony_ci				_PAGE_WRITE | _PAGE_DIRTY | _PAGE_MODIFIED | \
6462306a36Sopenharmony_ci				_PAGE_GLOBAL | \
6562306a36Sopenharmony_ci				_CACHE_CACHED)
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci#define _PAGE_IOREMAP		(_PAGE_BASE | _PAGE_READ | _PAGE_VALID | \
6862306a36Sopenharmony_ci				_PAGE_WRITE | _PAGE_DIRTY | _PAGE_MODIFIED | \
6962306a36Sopenharmony_ci				_PAGE_GLOBAL | \
7062306a36Sopenharmony_ci				_CACHE_UNCACHED | _PAGE_SO)
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci#define _PAGE_CHG_MASK	(~(unsigned long) \
7362306a36Sopenharmony_ci				(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
7462306a36Sopenharmony_ci				_CACHE_MASK | _PAGE_GLOBAL))
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci#define MAX_SWAPFILES_CHECK() \
7762306a36Sopenharmony_ci		BUILD_BUG_ON(MAX_SWAPFILES_SHIFT != 5)
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ciextern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
8062306a36Sopenharmony_ci#define ZERO_PAGE(vaddr)	(virt_to_page(empty_zero_page))
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ciextern void load_pgd(unsigned long pg_dir);
8362306a36Sopenharmony_ciextern pte_t invalid_pte_table[PTRS_PER_PTE];
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_cistatic inline void set_pte(pte_t *p, pte_t pte)
8662306a36Sopenharmony_ci{
8762306a36Sopenharmony_ci	*p = pte;
8862306a36Sopenharmony_ci#if defined(CONFIG_CPU_NEED_TLBSYNC)
8962306a36Sopenharmony_ci	dcache_wb_line((u32)p);
9062306a36Sopenharmony_ci#endif
9162306a36Sopenharmony_ci	/* prevent out of order excution */
9262306a36Sopenharmony_ci	smp_mb();
9362306a36Sopenharmony_ci}
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_cistatic inline pte_t *pmd_page_vaddr(pmd_t pmd)
9662306a36Sopenharmony_ci{
9762306a36Sopenharmony_ci	unsigned long ptr;
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	ptr = pmd_val(pmd);
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	return __va(ptr);
10262306a36Sopenharmony_ci}
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci#define pmd_phys(pmd) pmd_val(pmd)
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_cistatic inline void set_pmd(pmd_t *p, pmd_t pmd)
10762306a36Sopenharmony_ci{
10862306a36Sopenharmony_ci	*p = pmd;
10962306a36Sopenharmony_ci#if defined(CONFIG_CPU_NEED_TLBSYNC)
11062306a36Sopenharmony_ci	dcache_wb_line((u32)p);
11162306a36Sopenharmony_ci#endif
11262306a36Sopenharmony_ci	/* prevent specul excute */
11362306a36Sopenharmony_ci	smp_mb();
11462306a36Sopenharmony_ci}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistatic inline int pmd_none(pmd_t pmd)
11862306a36Sopenharmony_ci{
11962306a36Sopenharmony_ci	return pmd_val(pmd) == __pa(invalid_pte_table);
12062306a36Sopenharmony_ci}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci#define pmd_bad(pmd)	(pmd_val(pmd) & ~PAGE_MASK)
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_cistatic inline int pmd_present(pmd_t pmd)
12562306a36Sopenharmony_ci{
12662306a36Sopenharmony_ci	return (pmd_val(pmd) != __pa(invalid_pte_table));
12762306a36Sopenharmony_ci}
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_cistatic inline void pmd_clear(pmd_t *p)
13062306a36Sopenharmony_ci{
13162306a36Sopenharmony_ci	pmd_val(*p) = (__pa(invalid_pte_table));
13262306a36Sopenharmony_ci#if defined(CONFIG_CPU_NEED_TLBSYNC)
13362306a36Sopenharmony_ci	dcache_wb_line((u32)p);
13462306a36Sopenharmony_ci#endif
13562306a36Sopenharmony_ci}
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci/*
13862306a36Sopenharmony_ci * The following only work if pte_present() is true.
13962306a36Sopenharmony_ci * Undefined behaviour if not..
14062306a36Sopenharmony_ci */
14162306a36Sopenharmony_cistatic inline int pte_read(pte_t pte)
14262306a36Sopenharmony_ci{
14362306a36Sopenharmony_ci	return pte.pte_low & _PAGE_READ;
14462306a36Sopenharmony_ci}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_cistatic inline int pte_write(pte_t pte)
14762306a36Sopenharmony_ci{
14862306a36Sopenharmony_ci	return (pte).pte_low & _PAGE_WRITE;
14962306a36Sopenharmony_ci}
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_cistatic inline int pte_dirty(pte_t pte)
15262306a36Sopenharmony_ci{
15362306a36Sopenharmony_ci	return (pte).pte_low & _PAGE_MODIFIED;
15462306a36Sopenharmony_ci}
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_cistatic inline int pte_young(pte_t pte)
15762306a36Sopenharmony_ci{
15862306a36Sopenharmony_ci	return (pte).pte_low & _PAGE_ACCESSED;
15962306a36Sopenharmony_ci}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cistatic inline pte_t pte_wrprotect(pte_t pte)
16262306a36Sopenharmony_ci{
16362306a36Sopenharmony_ci	pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_DIRTY);
16462306a36Sopenharmony_ci	return pte;
16562306a36Sopenharmony_ci}
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_cistatic inline pte_t pte_mkclean(pte_t pte)
16862306a36Sopenharmony_ci{
16962306a36Sopenharmony_ci	pte_val(pte) &= ~(_PAGE_MODIFIED|_PAGE_DIRTY);
17062306a36Sopenharmony_ci	return pte;
17162306a36Sopenharmony_ci}
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_cistatic inline pte_t pte_mkold(pte_t pte)
17462306a36Sopenharmony_ci{
17562306a36Sopenharmony_ci	pte_val(pte) &= ~(_PAGE_ACCESSED|_PAGE_VALID);
17662306a36Sopenharmony_ci	return pte;
17762306a36Sopenharmony_ci}
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_cistatic inline pte_t pte_mkwrite_novma(pte_t pte)
18062306a36Sopenharmony_ci{
18162306a36Sopenharmony_ci	pte_val(pte) |= _PAGE_WRITE;
18262306a36Sopenharmony_ci	if (pte_val(pte) & _PAGE_MODIFIED)
18362306a36Sopenharmony_ci		pte_val(pte) |= _PAGE_DIRTY;
18462306a36Sopenharmony_ci	return pte;
18562306a36Sopenharmony_ci}
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_cistatic inline pte_t pte_mkdirty(pte_t pte)
18862306a36Sopenharmony_ci{
18962306a36Sopenharmony_ci	pte_val(pte) |= _PAGE_MODIFIED;
19062306a36Sopenharmony_ci	if (pte_val(pte) & _PAGE_WRITE)
19162306a36Sopenharmony_ci		pte_val(pte) |= _PAGE_DIRTY;
19262306a36Sopenharmony_ci	return pte;
19362306a36Sopenharmony_ci}
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_cistatic inline pte_t pte_mkyoung(pte_t pte)
19662306a36Sopenharmony_ci{
19762306a36Sopenharmony_ci	pte_val(pte) |= _PAGE_ACCESSED;
19862306a36Sopenharmony_ci	if (pte_val(pte) & _PAGE_READ)
19962306a36Sopenharmony_ci		pte_val(pte) |= _PAGE_VALID;
20062306a36Sopenharmony_ci	return pte;
20162306a36Sopenharmony_ci}
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_cistatic inline int pte_swp_exclusive(pte_t pte)
20462306a36Sopenharmony_ci{
20562306a36Sopenharmony_ci	return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
20662306a36Sopenharmony_ci}
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_cistatic inline pte_t pte_swp_mkexclusive(pte_t pte)
20962306a36Sopenharmony_ci{
21062306a36Sopenharmony_ci	pte_val(pte) |= _PAGE_SWP_EXCLUSIVE;
21162306a36Sopenharmony_ci	return pte;
21262306a36Sopenharmony_ci}
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_cistatic inline pte_t pte_swp_clear_exclusive(pte_t pte)
21562306a36Sopenharmony_ci{
21662306a36Sopenharmony_ci	pte_val(pte) &= ~_PAGE_SWP_EXCLUSIVE;
21762306a36Sopenharmony_ci	return pte;
21862306a36Sopenharmony_ci}
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci#define __HAVE_PHYS_MEM_ACCESS_PROT
22162306a36Sopenharmony_cistruct file;
22262306a36Sopenharmony_ciextern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
22362306a36Sopenharmony_ci				     unsigned long size, pgprot_t vma_prot);
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci/*
22662306a36Sopenharmony_ci * Macro to make mark a page protection value as "uncacheable".  Note
22762306a36Sopenharmony_ci * that "protection" is really a misnomer here as the protection value
22862306a36Sopenharmony_ci * contains the memory attribute bits, dirty bits, and various other
22962306a36Sopenharmony_ci * bits as well.
23062306a36Sopenharmony_ci */
23162306a36Sopenharmony_ci#define pgprot_noncached pgprot_noncached
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_cistatic inline pgprot_t pgprot_noncached(pgprot_t _prot)
23462306a36Sopenharmony_ci{
23562306a36Sopenharmony_ci	unsigned long prot = pgprot_val(_prot);
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED | _PAGE_SO;
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	return __pgprot(prot);
24062306a36Sopenharmony_ci}
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci#define pgprot_writecombine pgprot_writecombine
24362306a36Sopenharmony_cistatic inline pgprot_t pgprot_writecombine(pgprot_t _prot)
24462306a36Sopenharmony_ci{
24562306a36Sopenharmony_ci	unsigned long prot = pgprot_val(_prot);
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED;
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	return __pgprot(prot);
25062306a36Sopenharmony_ci}
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci/*
25362306a36Sopenharmony_ci * Conversion functions: convert a page and protection to a page entry,
25462306a36Sopenharmony_ci * and a page entry and page directory to the page they refer to.
25562306a36Sopenharmony_ci */
25662306a36Sopenharmony_ci#define mk_pte(page, pgprot)    pfn_pte(page_to_pfn(page), (pgprot))
25762306a36Sopenharmony_cistatic inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
25862306a36Sopenharmony_ci{
25962306a36Sopenharmony_ci	return __pte((pte_val(pte) & _PAGE_CHG_MASK) |
26062306a36Sopenharmony_ci		     (pgprot_val(newprot)));
26162306a36Sopenharmony_ci}
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ciextern pgd_t swapper_pg_dir[PTRS_PER_PGD];
26462306a36Sopenharmony_ciextern void paging_init(void);
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_civoid update_mmu_cache_range(struct vm_fault *vmf, struct vm_area_struct *vma,
26762306a36Sopenharmony_ci		unsigned long address, pte_t *pte, unsigned int nr);
26862306a36Sopenharmony_ci#define update_mmu_cache(vma, addr, ptep) \
26962306a36Sopenharmony_ci	update_mmu_cache_range(NULL, vma, addr, ptep, 1)
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
27262306a36Sopenharmony_ci	remap_pfn_range(vma, vaddr, pfn, size, prot)
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci#endif /* __ASM_CSKY_PGTABLE_H */
275