1#ifndef _ASM_M32R_PGTABLE_H 2#define _ASM_M32R_PGTABLE_H 3 4#include <asm-generic/4level-fixup.h> 5 6#ifdef __KERNEL__ 7/* 8 * The Linux memory management assumes a three-level page table setup. On 9 * the M32R, we use that, but "fold" the mid level into the top-level page 10 * table, so that we physically have the same two-level page table as the 11 * M32R mmu expects. 12 * 13 * This file contains the functions and defines necessary to modify and use 14 * the M32R page table tree. 15 */ 16 17/* CAUTION!: If you change macro definitions in this file, you might have to 18 * change arch/m32r/mmu.S manually. 19 */ 20 21#ifndef __ASSEMBLY__ 22 23#include <linux/threads.h> 24#include <linux/bitops.h> 25#include <asm/processor.h> 26#include <asm/addrspace.h> 27#include <asm/page.h> 28 29struct mm_struct; 30struct vm_area_struct; 31 32extern pgd_t swapper_pg_dir[1024]; 33extern void paging_init(void); 34 35/* 36 * ZERO_PAGE is a global shared page that is always zero: used 37 * for zero-mapped memory areas etc.. 38 */ 39extern unsigned long empty_zero_page[1024]; 40#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) 41 42#endif /* !__ASSEMBLY__ */ 43 44#ifndef __ASSEMBLY__ 45#include <asm/pgtable-2level.h> 46#endif 47 48#define pgtable_cache_init() do { } while (0) 49 50#define PMD_SIZE (1UL << PMD_SHIFT) 51#define PMD_MASK (~(PMD_SIZE - 1)) 52#define PGDIR_SIZE (1UL << PGDIR_SHIFT) 53#define PGDIR_MASK (~(PGDIR_SIZE - 1)) 54 55#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) 56#define FIRST_USER_ADDRESS 0UL 57 58#ifndef __ASSEMBLY__ 59/* Just any arbitrary offset to the start of the vmalloc VM area: the 60 * current 8MB value just means that there will be a 8MB "hole" after the 61 * physical memory until the kernel virtual memory starts. That means that 62 * any out-of-bounds memory accesses will hopefully be caught. 63 * The vmalloc() routines leaves a hole of 4kB between each vmalloced 64 * area for the same reason. ;) 65 */ 66#define VMALLOC_START KSEG2 67#define VMALLOC_END KSEG3 68 69/* 70 * M32R TLB format 71 * 72 * [0] [1:19] [20:23] [24:31] 73 * +-----------------------+----+-------------+ 74 * | VPN |0000| ASID | 75 * +-----------------------+----+-------------+ 76 * +-+---------------------+----+-+---+-+-+-+-+ 77 * |0 PPN |0000|N|AC |L|G|V| | 78 * +-+---------------------+----+-+---+-+-+-+-+ 79 * RWX 80 */ 81 82#define _PAGE_BIT_DIRTY 0 /* software: page changed */ 83#define _PAGE_BIT_PRESENT 1 /* Valid: page is valid */ 84#define _PAGE_BIT_GLOBAL 2 /* Global */ 85#define _PAGE_BIT_LARGE 3 /* Large */ 86#define _PAGE_BIT_EXEC 4 /* Execute */ 87#define _PAGE_BIT_WRITE 5 /* Write */ 88#define _PAGE_BIT_READ 6 /* Read */ 89#define _PAGE_BIT_NONCACHABLE 7 /* Non cachable */ 90#define _PAGE_BIT_ACCESSED 8 /* software: page referenced */ 91#define _PAGE_BIT_PROTNONE 9 /* software: if not present */ 92 93#define _PAGE_DIRTY (1UL << _PAGE_BIT_DIRTY) 94#define _PAGE_PRESENT (1UL << _PAGE_BIT_PRESENT) 95#define _PAGE_GLOBAL (1UL << _PAGE_BIT_GLOBAL) 96#define _PAGE_LARGE (1UL << _PAGE_BIT_LARGE) 97#define _PAGE_EXEC (1UL << _PAGE_BIT_EXEC) 98#define _PAGE_WRITE (1UL << _PAGE_BIT_WRITE) 99#define _PAGE_READ (1UL << _PAGE_BIT_READ) 100#define _PAGE_NONCACHABLE (1UL << _PAGE_BIT_NONCACHABLE) 101#define _PAGE_ACCESSED (1UL << _PAGE_BIT_ACCESSED) 102#define _PAGE_PROTNONE (1UL << _PAGE_BIT_PROTNONE) 103 104#define _PAGE_TABLE \ 105 ( _PAGE_PRESENT | _PAGE_WRITE | _PAGE_READ | _PAGE_ACCESSED \ 106 | _PAGE_DIRTY ) 107#define _KERNPG_TABLE \ 108 ( _PAGE_PRESENT | _PAGE_WRITE | _PAGE_READ | _PAGE_ACCESSED \ 109 | _PAGE_DIRTY ) 110#define _PAGE_CHG_MASK \ 111 ( PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY ) 112 113#ifdef CONFIG_MMU 114#define PAGE_NONE \ 115 __pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED) 116#define PAGE_SHARED \ 117 __pgprot(_PAGE_PRESENT | _PAGE_WRITE | _PAGE_READ | _PAGE_ACCESSED) 118#define PAGE_SHARED_EXEC \ 119 __pgprot(_PAGE_PRESENT | _PAGE_EXEC | _PAGE_WRITE | _PAGE_READ \ 120 | _PAGE_ACCESSED) 121#define PAGE_COPY \ 122 __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_ACCESSED) 123#define PAGE_COPY_EXEC \ 124 __pgprot(_PAGE_PRESENT | _PAGE_EXEC | _PAGE_READ | _PAGE_ACCESSED) 125#define PAGE_READONLY \ 126 __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_ACCESSED) 127#define PAGE_READONLY_EXEC \ 128 __pgprot(_PAGE_PRESENT | _PAGE_EXEC | _PAGE_READ | _PAGE_ACCESSED) 129 130#define __PAGE_KERNEL \ 131 ( _PAGE_PRESENT | _PAGE_EXEC | _PAGE_WRITE | _PAGE_READ | _PAGE_DIRTY \ 132 | _PAGE_ACCESSED ) 133#define __PAGE_KERNEL_RO ( __PAGE_KERNEL & ~_PAGE_WRITE ) 134#define __PAGE_KERNEL_NOCACHE ( __PAGE_KERNEL | _PAGE_NONCACHABLE) 135 136#define MAKE_GLOBAL(x) __pgprot((x) | _PAGE_GLOBAL) 137 138#define PAGE_KERNEL MAKE_GLOBAL(__PAGE_KERNEL) 139#define PAGE_KERNEL_RO MAKE_GLOBAL(__PAGE_KERNEL_RO) 140#define PAGE_KERNEL_NOCACHE MAKE_GLOBAL(__PAGE_KERNEL_NOCACHE) 141 142#else 143#define PAGE_NONE __pgprot(0) 144#define PAGE_SHARED __pgprot(0) 145#define PAGE_SHARED_EXEC __pgprot(0) 146#define PAGE_COPY __pgprot(0) 147#define PAGE_COPY_EXEC __pgprot(0) 148#define PAGE_READONLY __pgprot(0) 149#define PAGE_READONLY_EXEC __pgprot(0) 150 151#define PAGE_KERNEL __pgprot(0) 152#define PAGE_KERNEL_RO __pgprot(0) 153#define PAGE_KERNEL_NOCACHE __pgprot(0) 154#endif /* CONFIG_MMU */ 155 156 /* xwr */ 157#define __P000 PAGE_NONE 158#define __P001 PAGE_READONLY 159#define __P010 PAGE_COPY 160#define __P011 PAGE_COPY 161#define __P100 PAGE_READONLY_EXEC 162#define __P101 PAGE_READONLY_EXEC 163#define __P110 PAGE_COPY_EXEC 164#define __P111 PAGE_COPY_EXEC 165 166#define __S000 PAGE_NONE 167#define __S001 PAGE_READONLY 168#define __S010 PAGE_SHARED 169#define __S011 PAGE_SHARED 170#define __S100 PAGE_READONLY_EXEC 171#define __S101 PAGE_READONLY_EXEC 172#define __S110 PAGE_SHARED_EXEC 173#define __S111 PAGE_SHARED_EXEC 174 175/* page table for 0-4MB for everybody */ 176 177#define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE)) 178#define pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0) 179 180#define pmd_none(x) (!pmd_val(x)) 181#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT) 182#define pmd_clear(xp) do { set_pmd(xp, __pmd(0)); } while (0) 183#define pmd_bad(x) ((pmd_val(x) & ~PAGE_MASK) != _KERNPG_TABLE) 184 185#define pages_to_mb(x) ((x) >> (20 - PAGE_SHIFT)) 186 187/* 188 * The following only work if pte_present() is true. 189 * Undefined behaviour if not.. 190 */ 191static inline int pte_dirty(pte_t pte) 192{ 193 return pte_val(pte) & _PAGE_DIRTY; 194} 195 196static inline int pte_young(pte_t pte) 197{ 198 return pte_val(pte) & _PAGE_ACCESSED; 199} 200 201static inline int pte_write(pte_t pte) 202{ 203 return pte_val(pte) & _PAGE_WRITE; 204} 205 206static inline int pte_special(pte_t pte) 207{ 208 return 0; 209} 210 211static inline pte_t pte_mkclean(pte_t pte) 212{ 213 pte_val(pte) &= ~_PAGE_DIRTY; 214 return pte; 215} 216 217static inline pte_t pte_mkold(pte_t pte) 218{ 219 pte_val(pte) &= ~_PAGE_ACCESSED; 220 return pte; 221} 222 223static inline pte_t pte_wrprotect(pte_t pte) 224{ 225 pte_val(pte) &= ~_PAGE_WRITE; 226 return pte; 227} 228 229static inline pte_t pte_mkdirty(pte_t pte) 230{ 231 pte_val(pte) |= _PAGE_DIRTY; 232 return pte; 233} 234 235static inline pte_t pte_mkyoung(pte_t pte) 236{ 237 pte_val(pte) |= _PAGE_ACCESSED; 238 return pte; 239} 240 241static inline pte_t pte_mkwrite(pte_t pte) 242{ 243 pte_val(pte) |= _PAGE_WRITE; 244 return pte; 245} 246 247static inline pte_t pte_mkspecial(pte_t pte) 248{ 249 return pte; 250} 251 252static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) 253{ 254 return test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep); 255} 256 257static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) 258{ 259 clear_bit(_PAGE_BIT_WRITE, ptep); 260} 261 262/* 263 * Macro and implementation to make a page protection as uncachable. 264 */ 265static inline pgprot_t pgprot_noncached(pgprot_t _prot) 266{ 267 unsigned long prot = pgprot_val(_prot); 268 269 prot |= _PAGE_NONCACHABLE; 270 return __pgprot(prot); 271} 272 273#define pgprot_writecombine(prot) pgprot_noncached(prot) 274 275/* 276 * Conversion functions: convert a page and protection to a page entry, 277 * and a page entry and page directory to the page they refer to. 278 */ 279#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), pgprot) 280 281static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) 282{ 283 set_pte(&pte, __pte((pte_val(pte) & _PAGE_CHG_MASK) \ 284 | pgprot_val(newprot))); 285 286 return pte; 287} 288 289/* 290 * Conversion functions: convert a page and protection to a page entry, 291 * and a page entry and page directory to the page they refer to. 292 */ 293 294static inline void pmd_set(pmd_t * pmdp, pte_t * ptep) 295{ 296 pmd_val(*pmdp) = (((unsigned long) ptep) & PAGE_MASK); 297} 298 299#define pmd_page_vaddr(pmd) \ 300 ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK)) 301 302#ifndef CONFIG_DISCONTIGMEM 303#define pmd_page(pmd) (mem_map + ((pmd_val(pmd) >> PAGE_SHIFT) - PFN_BASE)) 304#endif /* !CONFIG_DISCONTIGMEM */ 305 306/* to find an entry in a page-table-directory. */ 307#define pgd_index(address) \ 308 (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) 309 310#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address)) 311 312/* to find an entry in a kernel page-table-directory */ 313#define pgd_offset_k(address) pgd_offset(&init_mm, address) 314 315#define pmd_index(address) \ 316 (((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) 317 318#define pte_index(address) \ 319 (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) 320#define pte_offset_kernel(dir, address) \ 321 ((pte_t *)pmd_page_vaddr(*(dir)) + pte_index(address)) 322#define pte_offset_map(dir, address) \ 323 ((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address)) 324#define pte_unmap(pte) do { } while (0) 325 326/* Encode and de-code a swap entry */ 327#define __swp_type(x) (((x).val >> 2) & 0x1f) 328#define __swp_offset(x) ((x).val >> 10) 329#define __swp_entry(type, offset) \ 330 ((swp_entry_t) { ((type) << 2) | ((offset) << 10) }) 331#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) 332#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) 333 334#endif /* !__ASSEMBLY__ */ 335 336/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ 337#define kern_addr_valid(addr) (1) 338 339#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG 340#define __HAVE_ARCH_PTEP_GET_AND_CLEAR 341#define __HAVE_ARCH_PTEP_SET_WRPROTECT 342#define __HAVE_ARCH_PTE_SAME 343#include <asm-generic/pgtable.h> 344 345#endif /* __KERNEL__ */ 346 347#endif /* _ASM_M32R_PGTABLE_H */ 348