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