18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef _ASM_POWERPC_MMU_8XX_H_
38c2ecf20Sopenharmony_ci#define _ASM_POWERPC_MMU_8XX_H_
48c2ecf20Sopenharmony_ci/*
58c2ecf20Sopenharmony_ci * PPC8xx support
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci/* Control/status registers for the MPC8xx.
98c2ecf20Sopenharmony_ci * A write operation to these registers causes serialized access.
108c2ecf20Sopenharmony_ci * During software tablewalk, the registers used perform mask/shift-add
118c2ecf20Sopenharmony_ci * operations when written/read.  A TLB entry is created when the Mx_RPN
128c2ecf20Sopenharmony_ci * is written, and the contents of several registers are used to
138c2ecf20Sopenharmony_ci * create the entry.
148c2ecf20Sopenharmony_ci */
158c2ecf20Sopenharmony_ci#define SPRN_MI_CTR	784	/* Instruction TLB control register */
168c2ecf20Sopenharmony_ci#define MI_GPM		0x80000000	/* Set domain manager mode */
178c2ecf20Sopenharmony_ci#define MI_PPM		0x40000000	/* Set subpage protection */
188c2ecf20Sopenharmony_ci#define MI_CIDEF	0x20000000	/* Set cache inhibit when MMU dis */
198c2ecf20Sopenharmony_ci#define MI_RSV4I	0x08000000	/* Reserve 4 TLB entries */
208c2ecf20Sopenharmony_ci#define MI_PPCS		0x02000000	/* Use MI_RPN prob/priv state */
218c2ecf20Sopenharmony_ci#define MI_IDXMASK	0x00001f00	/* TLB index to be loaded */
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci/* These are the Ks and Kp from the PowerPC books.  For proper operation,
248c2ecf20Sopenharmony_ci * Ks = 0, Kp = 1.
258c2ecf20Sopenharmony_ci */
268c2ecf20Sopenharmony_ci#define SPRN_MI_AP	786
278c2ecf20Sopenharmony_ci#define MI_Ks		0x80000000	/* Should not be set */
288c2ecf20Sopenharmony_ci#define MI_Kp		0x40000000	/* Should always be set */
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci/*
318c2ecf20Sopenharmony_ci * All pages' PP data bits are set to either 001 or 011 by copying _PAGE_EXEC
328c2ecf20Sopenharmony_ci * into bit 21 in the ITLBmiss handler (bit 21 is the middle bit), which means
338c2ecf20Sopenharmony_ci * respectively NA for All or X for Supervisor and no access for User.
348c2ecf20Sopenharmony_ci * Then we use the APG to say whether accesses are according to Page rules or
358c2ecf20Sopenharmony_ci * "all Supervisor" rules (Access to all)
368c2ecf20Sopenharmony_ci * _PAGE_ACCESSED is also managed via APG. When _PAGE_ACCESSED is not set, say
378c2ecf20Sopenharmony_ci * "all User" rules, that will lead to NA for all.
388c2ecf20Sopenharmony_ci * Therefore, we define 4 APG groups. lsb is _PAGE_ACCESSED
398c2ecf20Sopenharmony_ci * 0 => Kernel => 11 (all accesses performed according as user iaw page definition)
408c2ecf20Sopenharmony_ci * 1 => Kernel+Accessed => 01 (all accesses performed according to page definition)
418c2ecf20Sopenharmony_ci * 2 => User => 11 (all accesses performed according as user iaw page definition)
428c2ecf20Sopenharmony_ci * 3 => User+Accessed => 00 (all accesses performed as supervisor iaw page definition) for INIT
438c2ecf20Sopenharmony_ci *                    => 10 (all accesses performed according to swaped page definition) for KUEP
448c2ecf20Sopenharmony_ci * 4-15 => Not Used
458c2ecf20Sopenharmony_ci */
468c2ecf20Sopenharmony_ci#define MI_APG_INIT	0xdc000000
478c2ecf20Sopenharmony_ci#define MI_APG_KUEP	0xde000000
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci/* The effective page number register.  When read, contains the information
508c2ecf20Sopenharmony_ci * about the last instruction TLB miss.  When MI_RPN is written, bits in
518c2ecf20Sopenharmony_ci * this register are used to create the TLB entry.
528c2ecf20Sopenharmony_ci */
538c2ecf20Sopenharmony_ci#define SPRN_MI_EPN	787
548c2ecf20Sopenharmony_ci#define MI_EPNMASK	0xfffff000	/* Effective page number for entry */
558c2ecf20Sopenharmony_ci#define MI_EVALID	0x00000200	/* Entry is valid */
568c2ecf20Sopenharmony_ci#define MI_ASIDMASK	0x0000000f	/* ASID match value */
578c2ecf20Sopenharmony_ci					/* Reset value is undefined */
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci/* A "level 1" or "segment" or whatever you want to call it register.
608c2ecf20Sopenharmony_ci * For the instruction TLB, it contains bits that get loaded into the
618c2ecf20Sopenharmony_ci * TLB entry when the MI_RPN is written.
628c2ecf20Sopenharmony_ci */
638c2ecf20Sopenharmony_ci#define SPRN_MI_TWC	789
648c2ecf20Sopenharmony_ci#define MI_APG		0x000001e0	/* Access protection group (0) */
658c2ecf20Sopenharmony_ci#define MI_GUARDED	0x00000010	/* Guarded storage */
668c2ecf20Sopenharmony_ci#define MI_PSMASK	0x0000000c	/* Mask of page size bits */
678c2ecf20Sopenharmony_ci#define MI_PS8MEG	0x0000000c	/* 8M page size */
688c2ecf20Sopenharmony_ci#define MI_PS512K	0x00000004	/* 512K page size */
698c2ecf20Sopenharmony_ci#define MI_PS4K_16K	0x00000000	/* 4K or 16K page size */
708c2ecf20Sopenharmony_ci#define MI_SVALID	0x00000001	/* Segment entry is valid */
718c2ecf20Sopenharmony_ci					/* Reset value is undefined */
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci/* Real page number.  Defined by the pte.  Writing this register
748c2ecf20Sopenharmony_ci * causes a TLB entry to be created for the instruction TLB, using
758c2ecf20Sopenharmony_ci * additional information from the MI_EPN, and MI_TWC registers.
768c2ecf20Sopenharmony_ci */
778c2ecf20Sopenharmony_ci#define SPRN_MI_RPN	790
788c2ecf20Sopenharmony_ci#define MI_SPS16K	0x00000008	/* Small page size (0 = 4k, 1 = 16k) */
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci/* Define an RPN value for mapping kernel memory to large virtual
818c2ecf20Sopenharmony_ci * pages for boot initialization.  This has real page number of 0,
828c2ecf20Sopenharmony_ci * large page size, shared page, cache enabled, and valid.
838c2ecf20Sopenharmony_ci * Also mark all subpages valid and write access.
848c2ecf20Sopenharmony_ci */
858c2ecf20Sopenharmony_ci#define MI_BOOTINIT	0x000001fd
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci#define SPRN_MD_CTR	792	/* Data TLB control register */
888c2ecf20Sopenharmony_ci#define MD_GPM		0x80000000	/* Set domain manager mode */
898c2ecf20Sopenharmony_ci#define MD_PPM		0x40000000	/* Set subpage protection */
908c2ecf20Sopenharmony_ci#define MD_CIDEF	0x20000000	/* Set cache inhibit when MMU dis */
918c2ecf20Sopenharmony_ci#define MD_WTDEF	0x10000000	/* Set writethrough when MMU dis */
928c2ecf20Sopenharmony_ci#define MD_RSV4I	0x08000000	/* Reserve 4 TLB entries */
938c2ecf20Sopenharmony_ci#define MD_TWAM		0x04000000	/* Use 4K page hardware assist */
948c2ecf20Sopenharmony_ci#define MD_PPCS		0x02000000	/* Use MI_RPN prob/priv state */
958c2ecf20Sopenharmony_ci#define MD_IDXMASK	0x00001f00	/* TLB index to be loaded */
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci#define SPRN_M_CASID	793	/* Address space ID (context) to match */
988c2ecf20Sopenharmony_ci#define MC_ASIDMASK	0x0000000f	/* Bits used for ASID value */
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci/* These are the Ks and Kp from the PowerPC books.  For proper operation,
1028c2ecf20Sopenharmony_ci * Ks = 0, Kp = 1.
1038c2ecf20Sopenharmony_ci */
1048c2ecf20Sopenharmony_ci#define SPRN_MD_AP	794
1058c2ecf20Sopenharmony_ci#define MD_Ks		0x80000000	/* Should not be set */
1068c2ecf20Sopenharmony_ci#define MD_Kp		0x40000000	/* Should always be set */
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci/* See explanation above at the definition of MI_APG_INIT */
1098c2ecf20Sopenharmony_ci#define MD_APG_INIT	0xdc000000
1108c2ecf20Sopenharmony_ci#define MD_APG_KUAP	0xde000000
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci/* The effective page number register.  When read, contains the information
1138c2ecf20Sopenharmony_ci * about the last instruction TLB miss.  When MD_RPN is written, bits in
1148c2ecf20Sopenharmony_ci * this register are used to create the TLB entry.
1158c2ecf20Sopenharmony_ci */
1168c2ecf20Sopenharmony_ci#define SPRN_MD_EPN	795
1178c2ecf20Sopenharmony_ci#define MD_EPNMASK	0xfffff000	/* Effective page number for entry */
1188c2ecf20Sopenharmony_ci#define MD_EVALID	0x00000200	/* Entry is valid */
1198c2ecf20Sopenharmony_ci#define MD_ASIDMASK	0x0000000f	/* ASID match value */
1208c2ecf20Sopenharmony_ci					/* Reset value is undefined */
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci/* The pointer to the base address of the first level page table.
1238c2ecf20Sopenharmony_ci * During a software tablewalk, reading this register provides the address
1248c2ecf20Sopenharmony_ci * of the entry associated with MD_EPN.
1258c2ecf20Sopenharmony_ci */
1268c2ecf20Sopenharmony_ci#define SPRN_M_TWB	796
1278c2ecf20Sopenharmony_ci#define	M_L1TB		0xfffff000	/* Level 1 table base address */
1288c2ecf20Sopenharmony_ci#define M_L1INDX	0x00000ffc	/* Level 1 index, when read */
1298c2ecf20Sopenharmony_ci					/* Reset value is undefined */
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci/* A "level 1" or "segment" or whatever you want to call it register.
1328c2ecf20Sopenharmony_ci * For the data TLB, it contains bits that get loaded into the TLB entry
1338c2ecf20Sopenharmony_ci * when the MD_RPN is written.  It is also provides the hardware assist
1348c2ecf20Sopenharmony_ci * for finding the PTE address during software tablewalk.
1358c2ecf20Sopenharmony_ci */
1368c2ecf20Sopenharmony_ci#define SPRN_MD_TWC	797
1378c2ecf20Sopenharmony_ci#define MD_L2TB		0xfffff000	/* Level 2 table base address */
1388c2ecf20Sopenharmony_ci#define MD_L2INDX	0xfffffe00	/* Level 2 index (*pte), when read */
1398c2ecf20Sopenharmony_ci#define MD_APG		0x000001e0	/* Access protection group (0) */
1408c2ecf20Sopenharmony_ci#define MD_GUARDED	0x00000010	/* Guarded storage */
1418c2ecf20Sopenharmony_ci#define MD_PSMASK	0x0000000c	/* Mask of page size bits */
1428c2ecf20Sopenharmony_ci#define MD_PS8MEG	0x0000000c	/* 8M page size */
1438c2ecf20Sopenharmony_ci#define MD_PS512K	0x00000004	/* 512K page size */
1448c2ecf20Sopenharmony_ci#define MD_PS4K_16K	0x00000000	/* 4K or 16K page size */
1458c2ecf20Sopenharmony_ci#define MD_WT		0x00000002	/* Use writethrough page attribute */
1468c2ecf20Sopenharmony_ci#define MD_SVALID	0x00000001	/* Segment entry is valid */
1478c2ecf20Sopenharmony_ci					/* Reset value is undefined */
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci/* Real page number.  Defined by the pte.  Writing this register
1518c2ecf20Sopenharmony_ci * causes a TLB entry to be created for the data TLB, using
1528c2ecf20Sopenharmony_ci * additional information from the MD_EPN, and MD_TWC registers.
1538c2ecf20Sopenharmony_ci */
1548c2ecf20Sopenharmony_ci#define SPRN_MD_RPN	798
1558c2ecf20Sopenharmony_ci#define MD_SPS16K	0x00000008	/* Small page size (0 = 4k, 1 = 16k) */
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci/* This is a temporary storage register that could be used to save
1588c2ecf20Sopenharmony_ci * a processor working register during a tablewalk.
1598c2ecf20Sopenharmony_ci */
1608c2ecf20Sopenharmony_ci#define SPRN_M_TW	799
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci#if defined(CONFIG_PPC_4K_PAGES)
1638c2ecf20Sopenharmony_ci#define mmu_virtual_psize	MMU_PAGE_4K
1648c2ecf20Sopenharmony_ci#elif defined(CONFIG_PPC_16K_PAGES)
1658c2ecf20Sopenharmony_ci#define mmu_virtual_psize	MMU_PAGE_16K
1668c2ecf20Sopenharmony_ci#define PTE_FRAG_NR		4
1678c2ecf20Sopenharmony_ci#define PTE_FRAG_SIZE_SHIFT	12
1688c2ecf20Sopenharmony_ci#define PTE_FRAG_SIZE		(1UL << 12)
1698c2ecf20Sopenharmony_ci#else
1708c2ecf20Sopenharmony_ci#error "Unsupported PAGE_SIZE"
1718c2ecf20Sopenharmony_ci#endif
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci#define mmu_linear_psize	MMU_PAGE_8M
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci#include <linux/mmdebug.h>
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_civoid mmu_pin_tlb(unsigned long top, bool readonly);
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_citypedef struct {
1828c2ecf20Sopenharmony_ci	unsigned int id;
1838c2ecf20Sopenharmony_ci	unsigned int active;
1848c2ecf20Sopenharmony_ci	unsigned long vdso_base;
1858c2ecf20Sopenharmony_ci	void *pte_frag;
1868c2ecf20Sopenharmony_ci} mm_context_t;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci#define PHYS_IMMR_BASE (mfspr(SPRN_IMMR) & 0xfff80000)
1898c2ecf20Sopenharmony_ci#define VIRT_IMMR_BASE (__fix_to_virt(FIX_IMMR_BASE))
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci/* Page size definitions, common between 32 and 64-bit
1928c2ecf20Sopenharmony_ci *
1938c2ecf20Sopenharmony_ci *    shift : is the "PAGE_SHIFT" value for that page size
1948c2ecf20Sopenharmony_ci *    penc  : is the pte encoding mask
1958c2ecf20Sopenharmony_ci *
1968c2ecf20Sopenharmony_ci */
1978c2ecf20Sopenharmony_cistruct mmu_psize_def {
1988c2ecf20Sopenharmony_ci	unsigned int	shift;	/* number of bits */
1998c2ecf20Sopenharmony_ci	unsigned int	enc;	/* PTE encoding */
2008c2ecf20Sopenharmony_ci	unsigned int    ind;    /* Corresponding indirect page size shift */
2018c2ecf20Sopenharmony_ci	unsigned int	flags;
2028c2ecf20Sopenharmony_ci#define MMU_PAGE_SIZE_DIRECT	0x1	/* Supported as a direct size */
2038c2ecf20Sopenharmony_ci#define MMU_PAGE_SIZE_INDIRECT	0x2	/* Supported as an indirect size */
2048c2ecf20Sopenharmony_ci};
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ciextern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_cistatic inline int shift_to_mmu_psize(unsigned int shift)
2098c2ecf20Sopenharmony_ci{
2108c2ecf20Sopenharmony_ci	int psize;
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	for (psize = 0; psize < MMU_PAGE_COUNT; ++psize)
2138c2ecf20Sopenharmony_ci		if (mmu_psize_defs[psize].shift == shift)
2148c2ecf20Sopenharmony_ci			return psize;
2158c2ecf20Sopenharmony_ci	return -1;
2168c2ecf20Sopenharmony_ci}
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_cistatic inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize)
2198c2ecf20Sopenharmony_ci{
2208c2ecf20Sopenharmony_ci	if (mmu_psize_defs[mmu_psize].shift)
2218c2ecf20Sopenharmony_ci		return mmu_psize_defs[mmu_psize].shift;
2228c2ecf20Sopenharmony_ci	BUG();
2238c2ecf20Sopenharmony_ci}
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci/* patch sites */
2268c2ecf20Sopenharmony_ciextern s32 patch__itlbmiss_exit_1, patch__dtlbmiss_exit_1;
2278c2ecf20Sopenharmony_ciextern s32 patch__itlbmiss_perf, patch__dtlbmiss_perf;
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci#endif /* !__ASSEMBLY__ */
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci#endif /* _ASM_POWERPC_MMU_8XX_H_ */
232