133323Sphk/* SPDX-License-Identifier: GPL-2.0 */ 233323Sphk 333323Sphk#ifndef __ASM_CSKY_PGTABLE_H 433323Sphk#define __ASM_CSKY_PGTABLE_H 533323Sphk 633323Sphk#include <asm/fixmap.h> 733323Sphk#include <asm/memory.h> 833323Sphk#include <asm/addrspace.h> 950477Speter#include <abi/pgtable-bits.h> 1033323Sphk#include <asm-generic/pgtable-nopmd.h> 1136938Sphk 1236938Sphk#define PGDIR_SHIFT 22 1336938Sphk#define PGDIR_SIZE (1UL << PGDIR_SHIFT) 1436938Sphk#define PGDIR_MASK (~(PGDIR_SIZE-1)) 1536938Sphk 1633323Sphk#define USER_PTRS_PER_PGD (PAGE_OFFSET/PGDIR_SIZE) 1733323Sphk 1833323Sphk/* 1933323Sphk * C-SKY is two-level paging structure: 2033323Sphk */ 2133323Sphk 2236739Sphk#define PTRS_PER_PGD (PAGE_SIZE / sizeof(pgd_t)) 2333323Sphk#define PTRS_PER_PMD 1 2433323Sphk#define PTRS_PER_PTE (PAGE_SIZE / sizeof(pte_t)) 2533323Sphk 2633326Sphk#define pte_ERROR(e) \ 2733323Sphk pr_err("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, (e).pte_low) 2849550Sphk#define pgd_ERROR(e) \ 2933323Sphk pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) 3049550Sphk 3146053Sphk#define PFN_PTE_SHIFT PAGE_SHIFT 3233396Sphk#define pmd_pfn(pmd) (pmd_phys(pmd) >> PAGE_SHIFT) 3344666Sphk#define pmd_page(pmd) (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT)) 3449550Sphk#define pte_clear(mm, addr, ptep) set_pte((ptep), \ 3533323Sphk (((unsigned int) addr >= PAGE_OFFSET) ? __pte(_PAGE_GLOBAL) : __pte(0))) 3633396Sphk#define pte_none(pte) (!(pte_val(pte) & ~_PAGE_GLOBAL)) 3733323Sphk#define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT) 3833323Sphk#define pte_pfn(x) ((unsigned long)((x).pte_low >> PAGE_SHIFT)) 3933323Sphk#define pfn_pte(pfn, prot) __pte(((unsigned long long)(pfn) << PAGE_SHIFT) \ 4033323Sphk | pgprot_val(prot)) 4133323Sphk 4233396Sphk#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) 4333396Sphk#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) 4449550Sphk 4533323Sphk#define pte_page(x) pfn_to_page(pte_pfn(x)) 4633396Sphk#define __mk_pte(page_nr, pgprot) __pte(((page_nr) << PAGE_SHIFT) | \ 4733396Sphk pgprot_val(pgprot)) 4833323Sphk 4933323Sphk/* 5033396Sphk * C-SKY only has VALID and DIRTY bit in hardware. So we need to use the 5133323Sphk * two bits emulate PRESENT, READ, WRITE, EXEC, MODIFIED, ACCESSED. 5233396Sphk */ 5333396Sphk#define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED) 5436739Sphk 5533323Sphk#define PAGE_NONE __pgprot(_PAGE_PROT_NONE) 5633323Sphk#define PAGE_READ __pgprot(_PAGE_BASE | _PAGE_READ | \ 5747625Sphk _CACHE_CACHED) 5847625Sphk#define PAGE_WRITE __pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_WRITE | \ 5947625Sphk _CACHE_CACHED) 6047625Sphk#define PAGE_SHARED PAGE_WRITE 6147625Sphk 6247625Sphk#define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_VALID | \ 6347625Sphk _PAGE_WRITE | _PAGE_DIRTY | _PAGE_MODIFIED | \ 6447625Sphk _PAGE_GLOBAL | \ 6547625Sphk _CACHE_CACHED) 6647625Sphk 6747625Sphk#define _PAGE_IOREMAP (_PAGE_BASE | _PAGE_READ | _PAGE_VALID | \ 6847625Sphk _PAGE_WRITE | _PAGE_DIRTY | _PAGE_MODIFIED | \ 6947625Sphk _PAGE_GLOBAL | \ 7047625Sphk _CACHE_UNCACHED | _PAGE_SO) 7147625Sphk 7247625Sphk#define _PAGE_CHG_MASK (~(unsigned long) \ 7347625Sphk (_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ 7447625Sphk _CACHE_MASK | _PAGE_GLOBAL)) 7547625Sphk 7647625Sphk#define MAX_SWAPFILES_CHECK() \ 7747625Sphk BUILD_BUG_ON(MAX_SWAPFILES_SHIFT != 5) 7833323Sphk 7944666Sphkextern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; 8033323Sphk#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) 8133396Sphk 8233323Sphkextern void load_pgd(unsigned long pg_dir); 8333396Sphkextern pte_t invalid_pte_table[PTRS_PER_PTE]; 8447640Sphk 8549550Sphkstatic inline void set_pte(pte_t *p, pte_t pte) 8633323Sphk{ 8747640Sphk *p = pte; 8847640Sphk#if defined(CONFIG_CPU_NEED_TLBSYNC) 8947640Sphk dcache_wb_line((u32)p); 9033396Sphk#endif 9133323Sphk /* prevent out of order excution */ 9233323Sphk smp_mb(); 9333326Sphk} 9433323Sphk 9533323Sphkstatic inline pte_t *pmd_page_vaddr(pmd_t pmd) 9633396Sphk{ 9733323Sphk unsigned long ptr; 9849550Sphk 9949550Sphk ptr = pmd_val(pmd); 10033323Sphk 10149550Sphk return __va(ptr); 10233323Sphk} 10349550Sphk 10433396Sphk#define pmd_phys(pmd) pmd_val(pmd) 10538061Smsmith 10649550Sphkstatic inline void set_pmd(pmd_t *p, pmd_t pmd) 10749550Sphk{ 10833323Sphk *p = pmd; 10944666Sphk#if defined(CONFIG_CPU_NEED_TLBSYNC) 11044666Sphk dcache_wb_line((u32)p); 11133396Sphk#endif 11233323Sphk /* prevent specul excute */ 11333323Sphk smp_mb(); 11433323Sphk} 11533396Sphk 11633323Sphk 11744666Sphkstatic inline int pmd_none(pmd_t pmd) 11833323Sphk{ 11933323Sphk return pmd_val(pmd) == __pa(invalid_pte_table); 12033323Sphk} 12133326Sphk 12233323Sphk#define pmd_bad(pmd) (pmd_val(pmd) & ~PAGE_MASK) 12333323Sphk 12433323Sphkstatic inline int pmd_present(pmd_t pmd) 12533323Sphk{ 12633323Sphk return (pmd_val(pmd) != __pa(invalid_pte_table)); 12733323Sphk} 12833396Sphk 12933323Sphkstatic inline void pmd_clear(pmd_t *p) 13033396Sphk{ 13133323Sphk pmd_val(*p) = (__pa(invalid_pte_table)); 13233323Sphk#if defined(CONFIG_CPU_NEED_TLBSYNC) 13333396Sphk dcache_wb_line((u32)p); 13433323Sphk#endif 13533323Sphk} 13649550Sphk 13733323Sphk/* 13846053Sphk * The following only work if pte_present() is true. 13946053Sphk * Undefined behaviour if not.. 14046053Sphk */ 14133323Sphkstatic inline int pte_read(pte_t pte) 14246053Sphk{ 14346053Sphk return pte.pte_low & _PAGE_READ; 14446053Sphk} 14546053Sphk 14633323Sphkstatic inline int pte_write(pte_t pte) 14733323Sphk{ 14833323Sphk return (pte).pte_low & _PAGE_WRITE; 14933323Sphk} 15033323Sphk 15133396Sphkstatic inline int pte_dirty(pte_t pte) 15233323Sphk{ 15349550Sphk return (pte).pte_low & _PAGE_MODIFIED; 15433323Sphk} 15544666Sphk 15643433Snsouchstatic inline int pte_young(pte_t pte) 15743433Snsouch{ 15843433Snsouch return (pte).pte_low & _PAGE_ACCESSED; 15943433Snsouch} 16033396Sphk 16146053Sphkstatic inline pte_t pte_wrprotect(pte_t pte) 16233323Sphk{ 16333323Sphk pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_DIRTY); 16433323Sphk return pte; 16533323Sphk} 16649550Sphk 16733323Sphkstatic inline pte_t pte_mkclean(pte_t pte) 16849550Sphk{ 16944666Sphk pte_val(pte) &= ~(_PAGE_MODIFIED|_PAGE_DIRTY); 17044666Sphk return pte; 17133323Sphk} 17244666Sphk 17344666Sphkstatic inline pte_t pte_mkold(pte_t pte) 17433396Sphk{ 17533323Sphk pte_val(pte) &= ~(_PAGE_ACCESSED|_PAGE_VALID); 17644666Sphk return pte; 17736739Sphk} 17844666Sphk 17944666Sphkstatic inline pte_t pte_mkwrite_novma(pte_t pte) 18036739Sphk{ 18133323Sphk pte_val(pte) |= _PAGE_WRITE; 18233323Sphk if (pte_val(pte) & _PAGE_MODIFIED) 18336739Sphk pte_val(pte) |= _PAGE_DIRTY; 18436748Sbde return pte; 18533323Sphk} 18649550Sphk 18733323Sphkstatic inline pte_t pte_mkdirty(pte_t pte) 18844666Sphk{ 18933323Sphk pte_val(pte) |= _PAGE_MODIFIED; 19033323Sphk if (pte_val(pte) & _PAGE_WRITE) 191 pte_val(pte) |= _PAGE_DIRTY; 192 return pte; 193} 194 195static inline pte_t pte_mkyoung(pte_t pte) 196{ 197 pte_val(pte) |= _PAGE_ACCESSED; 198 if (pte_val(pte) & _PAGE_READ) 199 pte_val(pte) |= _PAGE_VALID; 200 return pte; 201} 202 203static inline int pte_swp_exclusive(pte_t pte) 204{ 205 return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; 206} 207 208static inline pte_t pte_swp_mkexclusive(pte_t pte) 209{ 210 pte_val(pte) |= _PAGE_SWP_EXCLUSIVE; 211 return pte; 212} 213 214static inline pte_t pte_swp_clear_exclusive(pte_t pte) 215{ 216 pte_val(pte) &= ~_PAGE_SWP_EXCLUSIVE; 217 return pte; 218} 219 220#define __HAVE_PHYS_MEM_ACCESS_PROT 221struct file; 222extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, 223 unsigned long size, pgprot_t vma_prot); 224 225/* 226 * Macro to make mark a page protection value as "uncacheable". Note 227 * that "protection" is really a misnomer here as the protection value 228 * contains the memory attribute bits, dirty bits, and various other 229 * bits as well. 230 */ 231#define pgprot_noncached pgprot_noncached 232 233static inline pgprot_t pgprot_noncached(pgprot_t _prot) 234{ 235 unsigned long prot = pgprot_val(_prot); 236 237 prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED | _PAGE_SO; 238 239 return __pgprot(prot); 240} 241 242#define pgprot_writecombine pgprot_writecombine 243static inline pgprot_t pgprot_writecombine(pgprot_t _prot) 244{ 245 unsigned long prot = pgprot_val(_prot); 246 247 prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED; 248 249 return __pgprot(prot); 250} 251 252/* 253 * Conversion functions: convert a page and protection to a page entry, 254 * and a page entry and page directory to the page they refer to. 255 */ 256#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) 257static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) 258{ 259 return __pte((pte_val(pte) & _PAGE_CHG_MASK) | 260 (pgprot_val(newprot))); 261} 262 263extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; 264extern void paging_init(void); 265 266void update_mmu_cache_range(struct vm_fault *vmf, struct vm_area_struct *vma, 267 unsigned long address, pte_t *pte, unsigned int nr); 268#define update_mmu_cache(vma, addr, ptep) \ 269 update_mmu_cache_range(NULL, vma, addr, ptep, 1) 270 271#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ 272 remap_pfn_range(vma, vaddr, pfn, size, prot) 273 274#endif /* __ASM_CSKY_PGTABLE_H */ 275