162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef _ASM_POWERPC_MMU_8XX_H_ 362306a36Sopenharmony_ci#define _ASM_POWERPC_MMU_8XX_H_ 462306a36Sopenharmony_ci/* 562306a36Sopenharmony_ci * PPC8xx support 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci/* Control/status registers for the MPC8xx. 962306a36Sopenharmony_ci * A write operation to these registers causes serialized access. 1062306a36Sopenharmony_ci * During software tablewalk, the registers used perform mask/shift-add 1162306a36Sopenharmony_ci * operations when written/read. A TLB entry is created when the Mx_RPN 1262306a36Sopenharmony_ci * is written, and the contents of several registers are used to 1362306a36Sopenharmony_ci * create the entry. 1462306a36Sopenharmony_ci */ 1562306a36Sopenharmony_ci#define SPRN_MI_CTR 784 /* Instruction TLB control register */ 1662306a36Sopenharmony_ci#define MI_GPM 0x80000000 /* Set domain manager mode */ 1762306a36Sopenharmony_ci#define MI_PPM 0x40000000 /* Set subpage protection */ 1862306a36Sopenharmony_ci#define MI_CIDEF 0x20000000 /* Set cache inhibit when MMU dis */ 1962306a36Sopenharmony_ci#define MI_RSV4I 0x08000000 /* Reserve 4 TLB entries */ 2062306a36Sopenharmony_ci#define MI_PPCS 0x02000000 /* Use MI_RPN prob/priv state */ 2162306a36Sopenharmony_ci#define MI_IDXMASK 0x00001f00 /* TLB index to be loaded */ 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/* These are the Ks and Kp from the PowerPC books. For proper operation, 2462306a36Sopenharmony_ci * Ks = 0, Kp = 1. 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_ci#define SPRN_MI_AP 786 2762306a36Sopenharmony_ci#define MI_Ks 0x80000000 /* Should not be set */ 2862306a36Sopenharmony_ci#define MI_Kp 0x40000000 /* Should always be set */ 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci/* 3162306a36Sopenharmony_ci * All pages' PP data bits are set to either 001 or 011 by copying _PAGE_EXEC 3262306a36Sopenharmony_ci * into bit 21 in the ITLBmiss handler (bit 21 is the middle bit), which means 3362306a36Sopenharmony_ci * respectively NA for All or X for Supervisor and no access for User. 3462306a36Sopenharmony_ci * Then we use the APG to say whether accesses are according to Page rules or 3562306a36Sopenharmony_ci * "all Supervisor" rules (Access to all) 3662306a36Sopenharmony_ci * _PAGE_ACCESSED is also managed via APG. When _PAGE_ACCESSED is not set, say 3762306a36Sopenharmony_ci * "all User" rules, that will lead to NA for all. 3862306a36Sopenharmony_ci * Therefore, we define 4 APG groups. lsb is _PAGE_ACCESSED 3962306a36Sopenharmony_ci * 0 => Kernel => 11 (all accesses performed according as user iaw page definition) 4062306a36Sopenharmony_ci * 1 => Kernel+Accessed => 01 (all accesses performed according to page definition) 4162306a36Sopenharmony_ci * 2 => User => 11 (all accesses performed according as user iaw page definition) 4262306a36Sopenharmony_ci * 3 => User+Accessed => 10 (all accesses performed according to swaped page definition) for KUEP 4362306a36Sopenharmony_ci * 4-15 => Not Used 4462306a36Sopenharmony_ci */ 4562306a36Sopenharmony_ci#define MI_APG_INIT 0xde000000 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci/* The effective page number register. When read, contains the information 4862306a36Sopenharmony_ci * about the last instruction TLB miss. When MI_RPN is written, bits in 4962306a36Sopenharmony_ci * this register are used to create the TLB entry. 5062306a36Sopenharmony_ci */ 5162306a36Sopenharmony_ci#define SPRN_MI_EPN 787 5262306a36Sopenharmony_ci#define MI_EPNMASK 0xfffff000 /* Effective page number for entry */ 5362306a36Sopenharmony_ci#define MI_EVALID 0x00000200 /* Entry is valid */ 5462306a36Sopenharmony_ci#define MI_ASIDMASK 0x0000000f /* ASID match value */ 5562306a36Sopenharmony_ci /* Reset value is undefined */ 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci/* A "level 1" or "segment" or whatever you want to call it register. 5862306a36Sopenharmony_ci * For the instruction TLB, it contains bits that get loaded into the 5962306a36Sopenharmony_ci * TLB entry when the MI_RPN is written. 6062306a36Sopenharmony_ci */ 6162306a36Sopenharmony_ci#define SPRN_MI_TWC 789 6262306a36Sopenharmony_ci#define MI_APG 0x000001e0 /* Access protection group (0) */ 6362306a36Sopenharmony_ci#define MI_GUARDED 0x00000010 /* Guarded storage */ 6462306a36Sopenharmony_ci#define MI_PSMASK 0x0000000c /* Mask of page size bits */ 6562306a36Sopenharmony_ci#define MI_PS8MEG 0x0000000c /* 8M page size */ 6662306a36Sopenharmony_ci#define MI_PS512K 0x00000004 /* 512K page size */ 6762306a36Sopenharmony_ci#define MI_PS4K_16K 0x00000000 /* 4K or 16K page size */ 6862306a36Sopenharmony_ci#define MI_SVALID 0x00000001 /* Segment entry is valid */ 6962306a36Sopenharmony_ci /* Reset value is undefined */ 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci/* Real page number. Defined by the pte. Writing this register 7262306a36Sopenharmony_ci * causes a TLB entry to be created for the instruction TLB, using 7362306a36Sopenharmony_ci * additional information from the MI_EPN, and MI_TWC registers. 7462306a36Sopenharmony_ci */ 7562306a36Sopenharmony_ci#define SPRN_MI_RPN 790 7662306a36Sopenharmony_ci#define MI_SPS16K 0x00000008 /* Small page size (0 = 4k, 1 = 16k) */ 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci/* Define an RPN value for mapping kernel memory to large virtual 7962306a36Sopenharmony_ci * pages for boot initialization. This has real page number of 0, 8062306a36Sopenharmony_ci * large page size, shared page, cache enabled, and valid. 8162306a36Sopenharmony_ci * Also mark all subpages valid and write access. 8262306a36Sopenharmony_ci */ 8362306a36Sopenharmony_ci#define MI_BOOTINIT 0x000001fd 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci#define SPRN_MD_CTR 792 /* Data TLB control register */ 8662306a36Sopenharmony_ci#define MD_GPM 0x80000000 /* Set domain manager mode */ 8762306a36Sopenharmony_ci#define MD_PPM 0x40000000 /* Set subpage protection */ 8862306a36Sopenharmony_ci#define MD_CIDEF 0x20000000 /* Set cache inhibit when MMU dis */ 8962306a36Sopenharmony_ci#define MD_WTDEF 0x10000000 /* Set writethrough when MMU dis */ 9062306a36Sopenharmony_ci#define MD_RSV4I 0x08000000 /* Reserve 4 TLB entries */ 9162306a36Sopenharmony_ci#define MD_TWAM 0x04000000 /* Use 4K page hardware assist */ 9262306a36Sopenharmony_ci#define MD_PPCS 0x02000000 /* Use MI_RPN prob/priv state */ 9362306a36Sopenharmony_ci#define MD_IDXMASK 0x00001f00 /* TLB index to be loaded */ 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci#define SPRN_M_CASID 793 /* Address space ID (context) to match */ 9662306a36Sopenharmony_ci#define MC_ASIDMASK 0x0000000f /* Bits used for ASID value */ 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci/* These are the Ks and Kp from the PowerPC books. For proper operation, 10062306a36Sopenharmony_ci * Ks = 0, Kp = 1. 10162306a36Sopenharmony_ci */ 10262306a36Sopenharmony_ci#define SPRN_MD_AP 794 10362306a36Sopenharmony_ci#define MD_Ks 0x80000000 /* Should not be set */ 10462306a36Sopenharmony_ci#define MD_Kp 0x40000000 /* Should always be set */ 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci/* See explanation above at the definition of MI_APG_INIT */ 10762306a36Sopenharmony_ci#define MD_APG_INIT 0xdc000000 10862306a36Sopenharmony_ci#define MD_APG_KUAP 0xde000000 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci/* The effective page number register. When read, contains the information 11162306a36Sopenharmony_ci * about the last instruction TLB miss. When MD_RPN is written, bits in 11262306a36Sopenharmony_ci * this register are used to create the TLB entry. 11362306a36Sopenharmony_ci */ 11462306a36Sopenharmony_ci#define SPRN_MD_EPN 795 11562306a36Sopenharmony_ci#define MD_EPNMASK 0xfffff000 /* Effective page number for entry */ 11662306a36Sopenharmony_ci#define MD_EVALID 0x00000200 /* Entry is valid */ 11762306a36Sopenharmony_ci#define MD_ASIDMASK 0x0000000f /* ASID match value */ 11862306a36Sopenharmony_ci /* Reset value is undefined */ 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci/* The pointer to the base address of the first level page table. 12162306a36Sopenharmony_ci * During a software tablewalk, reading this register provides the address 12262306a36Sopenharmony_ci * of the entry associated with MD_EPN. 12362306a36Sopenharmony_ci */ 12462306a36Sopenharmony_ci#define SPRN_M_TWB 796 12562306a36Sopenharmony_ci#define M_L1TB 0xfffff000 /* Level 1 table base address */ 12662306a36Sopenharmony_ci#define M_L1INDX 0x00000ffc /* Level 1 index, when read */ 12762306a36Sopenharmony_ci /* Reset value is undefined */ 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci/* A "level 1" or "segment" or whatever you want to call it register. 13062306a36Sopenharmony_ci * For the data TLB, it contains bits that get loaded into the TLB entry 13162306a36Sopenharmony_ci * when the MD_RPN is written. It is also provides the hardware assist 13262306a36Sopenharmony_ci * for finding the PTE address during software tablewalk. 13362306a36Sopenharmony_ci */ 13462306a36Sopenharmony_ci#define SPRN_MD_TWC 797 13562306a36Sopenharmony_ci#define MD_L2TB 0xfffff000 /* Level 2 table base address */ 13662306a36Sopenharmony_ci#define MD_L2INDX 0xfffffe00 /* Level 2 index (*pte), when read */ 13762306a36Sopenharmony_ci#define MD_APG 0x000001e0 /* Access protection group (0) */ 13862306a36Sopenharmony_ci#define MD_GUARDED 0x00000010 /* Guarded storage */ 13962306a36Sopenharmony_ci#define MD_PSMASK 0x0000000c /* Mask of page size bits */ 14062306a36Sopenharmony_ci#define MD_PS8MEG 0x0000000c /* 8M page size */ 14162306a36Sopenharmony_ci#define MD_PS512K 0x00000004 /* 512K page size */ 14262306a36Sopenharmony_ci#define MD_PS4K_16K 0x00000000 /* 4K or 16K page size */ 14362306a36Sopenharmony_ci#define MD_WT 0x00000002 /* Use writethrough page attribute */ 14462306a36Sopenharmony_ci#define MD_SVALID 0x00000001 /* Segment entry is valid */ 14562306a36Sopenharmony_ci /* Reset value is undefined */ 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci/* Real page number. Defined by the pte. Writing this register 14962306a36Sopenharmony_ci * causes a TLB entry to be created for the data TLB, using 15062306a36Sopenharmony_ci * additional information from the MD_EPN, and MD_TWC registers. 15162306a36Sopenharmony_ci */ 15262306a36Sopenharmony_ci#define SPRN_MD_RPN 798 15362306a36Sopenharmony_ci#define MD_SPS16K 0x00000008 /* Small page size (0 = 4k, 1 = 16k) */ 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci/* This is a temporary storage register that could be used to save 15662306a36Sopenharmony_ci * a processor working register during a tablewalk. 15762306a36Sopenharmony_ci */ 15862306a36Sopenharmony_ci#define SPRN_M_TW 799 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci#if defined(CONFIG_PPC_4K_PAGES) 16162306a36Sopenharmony_ci#define mmu_virtual_psize MMU_PAGE_4K 16262306a36Sopenharmony_ci#elif defined(CONFIG_PPC_16K_PAGES) 16362306a36Sopenharmony_ci#define mmu_virtual_psize MMU_PAGE_16K 16462306a36Sopenharmony_ci#define PTE_FRAG_NR 4 16562306a36Sopenharmony_ci#define PTE_FRAG_SIZE_SHIFT 12 16662306a36Sopenharmony_ci#define PTE_FRAG_SIZE (1UL << 12) 16762306a36Sopenharmony_ci#else 16862306a36Sopenharmony_ci#error "Unsupported PAGE_SIZE" 16962306a36Sopenharmony_ci#endif 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci#define mmu_linear_psize MMU_PAGE_8M 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci#define MODULES_VADDR (PAGE_OFFSET - SZ_256M) 17462306a36Sopenharmony_ci#define MODULES_END PAGE_OFFSET 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci#ifndef __ASSEMBLY__ 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci#include <linux/mmdebug.h> 17962306a36Sopenharmony_ci#include <linux/sizes.h> 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_civoid mmu_pin_tlb(unsigned long top, bool readonly); 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_citypedef struct { 18462306a36Sopenharmony_ci unsigned int id; 18562306a36Sopenharmony_ci unsigned int active; 18662306a36Sopenharmony_ci void __user *vdso; 18762306a36Sopenharmony_ci void *pte_frag; 18862306a36Sopenharmony_ci} mm_context_t; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci#define PHYS_IMMR_BASE (mfspr(SPRN_IMMR) & 0xfff80000) 19162306a36Sopenharmony_ci#define VIRT_IMMR_BASE (__fix_to_virt(FIX_IMMR_BASE)) 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci/* Page size definitions, common between 32 and 64-bit 19462306a36Sopenharmony_ci * 19562306a36Sopenharmony_ci * shift : is the "PAGE_SHIFT" value for that page size 19662306a36Sopenharmony_ci * penc : is the pte encoding mask 19762306a36Sopenharmony_ci * 19862306a36Sopenharmony_ci */ 19962306a36Sopenharmony_cistruct mmu_psize_def { 20062306a36Sopenharmony_ci unsigned int shift; /* number of bits */ 20162306a36Sopenharmony_ci unsigned int enc; /* PTE encoding */ 20262306a36Sopenharmony_ci unsigned int ind; /* Corresponding indirect page size shift */ 20362306a36Sopenharmony_ci unsigned int flags; 20462306a36Sopenharmony_ci#define MMU_PAGE_SIZE_DIRECT 0x1 /* Supported as a direct size */ 20562306a36Sopenharmony_ci#define MMU_PAGE_SIZE_INDIRECT 0x2 /* Supported as an indirect size */ 20662306a36Sopenharmony_ci}; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ciextern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_cistatic inline int shift_to_mmu_psize(unsigned int shift) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci int psize; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) 21562306a36Sopenharmony_ci if (mmu_psize_defs[psize].shift == shift) 21662306a36Sopenharmony_ci return psize; 21762306a36Sopenharmony_ci return -1; 21862306a36Sopenharmony_ci} 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_cistatic inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize) 22162306a36Sopenharmony_ci{ 22262306a36Sopenharmony_ci if (mmu_psize_defs[mmu_psize].shift) 22362306a36Sopenharmony_ci return mmu_psize_defs[mmu_psize].shift; 22462306a36Sopenharmony_ci BUG(); 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cistatic inline bool arch_vmap_try_size(unsigned long addr, unsigned long end, u64 pfn, 22862306a36Sopenharmony_ci unsigned int max_page_shift, unsigned long size) 22962306a36Sopenharmony_ci{ 23062306a36Sopenharmony_ci if (end - addr < size) 23162306a36Sopenharmony_ci return false; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci if ((1UL << max_page_shift) < size) 23462306a36Sopenharmony_ci return false; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci if (!IS_ALIGNED(addr, size)) 23762306a36Sopenharmony_ci return false; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci if (!IS_ALIGNED(PFN_PHYS(pfn), size)) 24062306a36Sopenharmony_ci return false; 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci return true; 24362306a36Sopenharmony_ci} 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_cistatic inline unsigned long arch_vmap_pte_range_map_size(unsigned long addr, unsigned long end, 24662306a36Sopenharmony_ci u64 pfn, unsigned int max_page_shift) 24762306a36Sopenharmony_ci{ 24862306a36Sopenharmony_ci if (arch_vmap_try_size(addr, end, pfn, max_page_shift, SZ_512K)) 24962306a36Sopenharmony_ci return SZ_512K; 25062306a36Sopenharmony_ci if (PAGE_SIZE == SZ_16K) 25162306a36Sopenharmony_ci return SZ_16K; 25262306a36Sopenharmony_ci if (arch_vmap_try_size(addr, end, pfn, max_page_shift, SZ_16K)) 25362306a36Sopenharmony_ci return SZ_16K; 25462306a36Sopenharmony_ci return PAGE_SIZE; 25562306a36Sopenharmony_ci} 25662306a36Sopenharmony_ci#define arch_vmap_pte_range_map_size arch_vmap_pte_range_map_size 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_cistatic inline int arch_vmap_pte_supported_shift(unsigned long size) 25962306a36Sopenharmony_ci{ 26062306a36Sopenharmony_ci if (size >= SZ_512K) 26162306a36Sopenharmony_ci return 19; 26262306a36Sopenharmony_ci else if (size >= SZ_16K) 26362306a36Sopenharmony_ci return 14; 26462306a36Sopenharmony_ci else 26562306a36Sopenharmony_ci return PAGE_SHIFT; 26662306a36Sopenharmony_ci} 26762306a36Sopenharmony_ci#define arch_vmap_pte_supported_shift arch_vmap_pte_supported_shift 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci/* patch sites */ 27062306a36Sopenharmony_ciextern s32 patch__itlbmiss_exit_1, patch__dtlbmiss_exit_1; 27162306a36Sopenharmony_ciextern s32 patch__itlbmiss_perf, patch__dtlbmiss_perf; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci#endif /* !__ASSEMBLY__ */ 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci#endif /* _ASM_POWERPC_MMU_8XX_H_ */ 276