162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef _MOTOROLA_PGTABLE_H 362306a36Sopenharmony_ci#define _MOTOROLA_PGTABLE_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci/* 762306a36Sopenharmony_ci * Definitions for MMU descriptors 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci#define _PAGE_PRESENT 0x001 1062306a36Sopenharmony_ci#define _PAGE_SHORT 0x002 1162306a36Sopenharmony_ci#define _PAGE_RONLY 0x004 1262306a36Sopenharmony_ci#define _PAGE_READWRITE 0x000 1362306a36Sopenharmony_ci#define _PAGE_ACCESSED 0x008 1462306a36Sopenharmony_ci#define _PAGE_DIRTY 0x010 1562306a36Sopenharmony_ci#define _PAGE_SUPER 0x080 /* 68040 supervisor only */ 1662306a36Sopenharmony_ci#define _PAGE_GLOBAL040 0x400 /* 68040 global bit, used for kva descs */ 1762306a36Sopenharmony_ci#define _PAGE_NOCACHE030 0x040 /* 68030 no-cache mode */ 1862306a36Sopenharmony_ci#define _PAGE_NOCACHE 0x060 /* 68040 cache mode, non-serialized */ 1962306a36Sopenharmony_ci#define _PAGE_NOCACHE_S 0x040 /* 68040 no-cache mode, serialized */ 2062306a36Sopenharmony_ci#define _PAGE_CACHE040 0x020 /* 68040 cache mode, cachable, copyback */ 2162306a36Sopenharmony_ci#define _PAGE_CACHE040W 0x000 /* 68040 cache mode, cachable, write-through */ 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define _DESCTYPE_MASK 0x003 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#define _CACHEMASK040 (~0x060) 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci/* 2862306a36Sopenharmony_ci * Currently set to the minimum alignment of table pointers (256 bytes). 2962306a36Sopenharmony_ci * The hardware only uses the low 4 bits for state: 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci * 3 - Used 3262306a36Sopenharmony_ci * 2 - Write Protected 3362306a36Sopenharmony_ci * 0,1 - Descriptor Type 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci * and has the rest of the bits reserved. 3662306a36Sopenharmony_ci */ 3762306a36Sopenharmony_ci#define _TABLE_MASK (0xffffff00) 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#define _PAGE_TABLE (_PAGE_SHORT) 4062306a36Sopenharmony_ci#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_NOCACHE) 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#define _PAGE_PROTNONE 0x004 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci/* We borrow bit 11 to store the exclusive marker in swap PTEs. */ 4562306a36Sopenharmony_ci#define _PAGE_SWP_EXCLUSIVE 0x800 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#ifndef __ASSEMBLY__ 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/* This is the cache mode to be used for pages containing page descriptors for 5062306a36Sopenharmony_ci * processors >= '040. It is in pte_mknocache(), and the variable is defined 5162306a36Sopenharmony_ci * and initialized in head.S */ 5262306a36Sopenharmony_ciextern int m68k_pgtable_cachemode; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci/* This is the cache mode for normal pages, for supervisor access on 5562306a36Sopenharmony_ci * processors >= '040. It is used in pte_mkcache(), and the variable is 5662306a36Sopenharmony_ci * defined and initialized in head.S */ 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci#if defined(CPU_M68060_ONLY) && defined(CONFIG_060_WRITETHROUGH) 5962306a36Sopenharmony_ci#define m68k_supervisor_cachemode _PAGE_CACHE040W 6062306a36Sopenharmony_ci#elif defined(CPU_M68040_OR_M68060_ONLY) 6162306a36Sopenharmony_ci#define m68k_supervisor_cachemode _PAGE_CACHE040 6262306a36Sopenharmony_ci#elif defined(CPU_M68020_OR_M68030_ONLY) 6362306a36Sopenharmony_ci#define m68k_supervisor_cachemode 0 6462306a36Sopenharmony_ci#else 6562306a36Sopenharmony_ciextern int m68k_supervisor_cachemode; 6662306a36Sopenharmony_ci#endif 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci#if defined(CPU_M68040_OR_M68060_ONLY) 6962306a36Sopenharmony_ci#define mm_cachebits _PAGE_CACHE040 7062306a36Sopenharmony_ci#elif defined(CPU_M68020_OR_M68030_ONLY) 7162306a36Sopenharmony_ci#define mm_cachebits 0 7262306a36Sopenharmony_ci#else 7362306a36Sopenharmony_ciextern unsigned long mm_cachebits; 7462306a36Sopenharmony_ci#endif 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED | mm_cachebits) 7762306a36Sopenharmony_ci#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | mm_cachebits) 7862306a36Sopenharmony_ci#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_RONLY | _PAGE_ACCESSED | mm_cachebits) 7962306a36Sopenharmony_ci#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_RONLY | _PAGE_ACCESSED | mm_cachebits) 8062306a36Sopenharmony_ci#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_DIRTY | _PAGE_ACCESSED | mm_cachebits) 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci#define pmd_pgtable(pmd) ((pgtable_t)pmd_page_vaddr(pmd)) 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci/* 8562306a36Sopenharmony_ci * Conversion functions: convert a page and protection to a page entry, 8662306a36Sopenharmony_ci * and a page entry and page directory to the page they refer to. 8762306a36Sopenharmony_ci */ 8862306a36Sopenharmony_ci#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_cistatic inline pte_t pte_modify(pte_t pte, pgprot_t newprot) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); 9362306a36Sopenharmony_ci return pte; 9462306a36Sopenharmony_ci} 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_cistatic inline void pmd_set(pmd_t *pmdp, pte_t *ptep) 9762306a36Sopenharmony_ci{ 9862306a36Sopenharmony_ci pmd_val(*pmdp) = virt_to_phys(ptep) | _PAGE_TABLE | _PAGE_ACCESSED; 9962306a36Sopenharmony_ci} 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_cistatic inline void pud_set(pud_t *pudp, pmd_t *pmdp) 10262306a36Sopenharmony_ci{ 10362306a36Sopenharmony_ci pud_val(*pudp) = _PAGE_TABLE | _PAGE_ACCESSED | __pa(pmdp); 10462306a36Sopenharmony_ci} 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci#define __pte_page(pte) ((unsigned long)__va(pte_val(pte) & PAGE_MASK)) 10762306a36Sopenharmony_ci#define pmd_page_vaddr(pmd) ((unsigned long)__va(pmd_val(pmd) & _TABLE_MASK)) 10862306a36Sopenharmony_ci#define pud_pgtable(pud) ((pmd_t *)__va(pud_val(pud) & _TABLE_MASK)) 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci#define pte_none(pte) (!pte_val(pte)) 11262306a36Sopenharmony_ci#define pte_present(pte) (pte_val(pte) & (_PAGE_PRESENT | _PAGE_PROTNONE)) 11362306a36Sopenharmony_ci#define pte_clear(mm,addr,ptep) ({ pte_val(*(ptep)) = 0; }) 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci#define PFN_PTE_SHIFT PAGE_SHIFT 11662306a36Sopenharmony_ci#define pte_page(pte) virt_to_page(__va(pte_val(pte))) 11762306a36Sopenharmony_ci#define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT) 11862306a36Sopenharmony_ci#define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci#define pmd_none(pmd) (!pmd_val(pmd)) 12162306a36Sopenharmony_ci#define pmd_bad(pmd) ((pmd_val(pmd) & _DESCTYPE_MASK) != _PAGE_TABLE) 12262306a36Sopenharmony_ci#define pmd_present(pmd) (pmd_val(pmd) & _PAGE_TABLE) 12362306a36Sopenharmony_ci#define pmd_clear(pmdp) ({ pmd_val(*pmdp) = 0; }) 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci#define pmd_pfn(pmd) ((pmd_val(pmd) & _TABLE_MASK) >> PAGE_SHIFT) 12662306a36Sopenharmony_ci/* 12762306a36Sopenharmony_ci * m68k does not have huge pages (020/030 actually could), but generic code 12862306a36Sopenharmony_ci * expects pmd_page() to exists, only to then DCE it all. Provide a dummy to 12962306a36Sopenharmony_ci * make the compiler happy. 13062306a36Sopenharmony_ci */ 13162306a36Sopenharmony_ci#define pmd_page(pmd) ((struct page *)NULL) 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci#define pud_none(pud) (!pud_val(pud)) 13562306a36Sopenharmony_ci#define pud_bad(pud) ((pud_val(pud) & _DESCTYPE_MASK) != _PAGE_TABLE) 13662306a36Sopenharmony_ci#define pud_present(pud) (pud_val(pud) & _PAGE_TABLE) 13762306a36Sopenharmony_ci#define pud_clear(pudp) ({ pud_val(*pudp) = 0; }) 13862306a36Sopenharmony_ci#define pud_page(pud) (mem_map + ((unsigned long)(__va(pud_val(pud)) - PAGE_OFFSET) >> PAGE_SHIFT)) 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci#define pte_ERROR(e) \ 14162306a36Sopenharmony_ci printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) 14262306a36Sopenharmony_ci#define pmd_ERROR(e) \ 14362306a36Sopenharmony_ci printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e)) 14462306a36Sopenharmony_ci#define pgd_ERROR(e) \ 14562306a36Sopenharmony_ci printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci/* 14962306a36Sopenharmony_ci * The following only work if pte_present() is true. 15062306a36Sopenharmony_ci * Undefined behaviour if not.. 15162306a36Sopenharmony_ci */ 15262306a36Sopenharmony_cistatic inline int pte_write(pte_t pte) { return !(pte_val(pte) & _PAGE_RONLY); } 15362306a36Sopenharmony_cistatic inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } 15462306a36Sopenharmony_cistatic inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_cistatic inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) |= _PAGE_RONLY; return pte; } 15762306a36Sopenharmony_cistatic inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; } 15862306a36Sopenharmony_cistatic inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; } 15962306a36Sopenharmony_cistatic inline pte_t pte_mkwrite_novma(pte_t pte){ pte_val(pte) &= ~_PAGE_RONLY; return pte; } 16062306a36Sopenharmony_cistatic inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; } 16162306a36Sopenharmony_cistatic inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; } 16262306a36Sopenharmony_cistatic inline pte_t pte_mknocache(pte_t pte) 16362306a36Sopenharmony_ci{ 16462306a36Sopenharmony_ci pte_val(pte) = (pte_val(pte) & _CACHEMASK040) | m68k_pgtable_cachemode; 16562306a36Sopenharmony_ci return pte; 16662306a36Sopenharmony_ci} 16762306a36Sopenharmony_cistatic inline pte_t pte_mkcache(pte_t pte) 16862306a36Sopenharmony_ci{ 16962306a36Sopenharmony_ci pte_val(pte) = (pte_val(pte) & _CACHEMASK040) | m68k_supervisor_cachemode; 17062306a36Sopenharmony_ci return pte; 17162306a36Sopenharmony_ci} 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci#define swapper_pg_dir kernel_pg_dir 17462306a36Sopenharmony_ciextern pgd_t kernel_pg_dir[128]; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci/* 17762306a36Sopenharmony_ci * Encode/decode swap entries and swap PTEs. Swap PTEs are all PTEs that 17862306a36Sopenharmony_ci * are !pte_none() && !pte_present(). 17962306a36Sopenharmony_ci * 18062306a36Sopenharmony_ci * Format of swap PTEs: 18162306a36Sopenharmony_ci * 18262306a36Sopenharmony_ci * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 18362306a36Sopenharmony_ci * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 18462306a36Sopenharmony_ci * <----------------- offset ------------> E <-- type ---> 0 0 0 0 18562306a36Sopenharmony_ci * 18662306a36Sopenharmony_ci * E is the exclusive marker that is not stored in swap entries. 18762306a36Sopenharmony_ci */ 18862306a36Sopenharmony_ci#define __swp_type(x) (((x).val >> 4) & 0x7f) 18962306a36Sopenharmony_ci#define __swp_offset(x) ((x).val >> 12) 19062306a36Sopenharmony_ci#define __swp_entry(type, offset) ((swp_entry_t) { (((type) & 0x7f) << 4) | ((offset) << 12) }) 19162306a36Sopenharmony_ci#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) 19262306a36Sopenharmony_ci#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_cistatic inline int pte_swp_exclusive(pte_t pte) 19562306a36Sopenharmony_ci{ 19662306a36Sopenharmony_ci return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; 19762306a36Sopenharmony_ci} 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_cistatic inline pte_t pte_swp_mkexclusive(pte_t pte) 20062306a36Sopenharmony_ci{ 20162306a36Sopenharmony_ci pte_val(pte) |= _PAGE_SWP_EXCLUSIVE; 20262306a36Sopenharmony_ci return pte; 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_cistatic inline pte_t pte_swp_clear_exclusive(pte_t pte) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci pte_val(pte) &= ~_PAGE_SWP_EXCLUSIVE; 20862306a36Sopenharmony_ci return pte; 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci#endif /* !__ASSEMBLY__ */ 21262306a36Sopenharmony_ci#endif /* _MOTOROLA_PGTABLE_H */ 213