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