18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef _SPARC64_TSB_H
38c2ecf20Sopenharmony_ci#define _SPARC64_TSB_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci/* The sparc64 TSB is similar to the powerpc hashtables.  It's a
68c2ecf20Sopenharmony_ci * power-of-2 sized table of TAG/PTE pairs.  The cpu precomputes
78c2ecf20Sopenharmony_ci * pointers into this table for 8K and 64K page sizes, and also a
88c2ecf20Sopenharmony_ci * comparison TAG based upon the virtual address and context which
98c2ecf20Sopenharmony_ci * faults.
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * TLB miss trap handler software does the actual lookup via something
128c2ecf20Sopenharmony_ci * of the form:
138c2ecf20Sopenharmony_ci *
148c2ecf20Sopenharmony_ci * 	ldxa		[%g0] ASI_{D,I}MMU_TSB_8KB_PTR, %g1
158c2ecf20Sopenharmony_ci * 	ldxa		[%g0] ASI_{D,I}MMU, %g6
168c2ecf20Sopenharmony_ci *	sllx		%g6, 22, %g6
178c2ecf20Sopenharmony_ci *	srlx		%g6, 22, %g6
188c2ecf20Sopenharmony_ci * 	ldda		[%g1] ASI_NUCLEUS_QUAD_LDD, %g4
198c2ecf20Sopenharmony_ci * 	cmp		%g4, %g6
208c2ecf20Sopenharmony_ci * 	bne,pn	%xcc, tsb_miss_{d,i}tlb
218c2ecf20Sopenharmony_ci * 	 mov		FAULT_CODE_{D,I}TLB, %g3
228c2ecf20Sopenharmony_ci * 	stxa		%g5, [%g0] ASI_{D,I}TLB_DATA_IN
238c2ecf20Sopenharmony_ci * 	retry
248c2ecf20Sopenharmony_ci *
258c2ecf20Sopenharmony_ci *
268c2ecf20Sopenharmony_ci * Each 16-byte slot of the TSB is the 8-byte tag and then the 8-byte
278c2ecf20Sopenharmony_ci * PTE.  The TAG is of the same layout as the TLB TAG TARGET mmu
288c2ecf20Sopenharmony_ci * register which is:
298c2ecf20Sopenharmony_ci *
308c2ecf20Sopenharmony_ci * -------------------------------------------------
318c2ecf20Sopenharmony_ci * |  -  |  CONTEXT |  -  |    VADDR bits 63:22    |
328c2ecf20Sopenharmony_ci * -------------------------------------------------
338c2ecf20Sopenharmony_ci *  63 61 60      48 47 42 41                     0
348c2ecf20Sopenharmony_ci *
358c2ecf20Sopenharmony_ci * But actually, since we use per-mm TSB's, we zero out the CONTEXT
368c2ecf20Sopenharmony_ci * field.
378c2ecf20Sopenharmony_ci *
388c2ecf20Sopenharmony_ci * Like the powerpc hashtables we need to use locking in order to
398c2ecf20Sopenharmony_ci * synchronize while we update the entries.  PTE updates need locking
408c2ecf20Sopenharmony_ci * as well.
418c2ecf20Sopenharmony_ci *
428c2ecf20Sopenharmony_ci * We need to carefully choose a lock bits for the TSB entry.  We
438c2ecf20Sopenharmony_ci * choose to use bit 47 in the tag.  Also, since we never map anything
448c2ecf20Sopenharmony_ci * at page zero in context zero, we use zero as an invalid tag entry.
458c2ecf20Sopenharmony_ci * When the lock bit is set, this forces a tag comparison failure.
468c2ecf20Sopenharmony_ci */
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci#define TSB_TAG_LOCK_BIT	47
498c2ecf20Sopenharmony_ci#define TSB_TAG_LOCK_HIGH	(1 << (TSB_TAG_LOCK_BIT - 32))
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci#define TSB_TAG_INVALID_BIT	46
528c2ecf20Sopenharmony_ci#define TSB_TAG_INVALID_HIGH	(1 << (TSB_TAG_INVALID_BIT - 32))
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci/* Some cpus support physical address quad loads.  We want to use
558c2ecf20Sopenharmony_ci * those if possible so we don't need to hard-lock the TSB mapping
568c2ecf20Sopenharmony_ci * into the TLB.  We encode some instruction patching in order to
578c2ecf20Sopenharmony_ci * support this.
588c2ecf20Sopenharmony_ci *
598c2ecf20Sopenharmony_ci * The kernel TSB is locked into the TLB by virtue of being in the
608c2ecf20Sopenharmony_ci * kernel image, so we don't play these games for swapper_tsb access.
618c2ecf20Sopenharmony_ci */
628c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
638c2ecf20Sopenharmony_cistruct tsb_ldquad_phys_patch_entry {
648c2ecf20Sopenharmony_ci	unsigned int	addr;
658c2ecf20Sopenharmony_ci	unsigned int	sun4u_insn;
668c2ecf20Sopenharmony_ci	unsigned int	sun4v_insn;
678c2ecf20Sopenharmony_ci};
688c2ecf20Sopenharmony_ciextern struct tsb_ldquad_phys_patch_entry __tsb_ldquad_phys_patch,
698c2ecf20Sopenharmony_ci	__tsb_ldquad_phys_patch_end;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cistruct tsb_phys_patch_entry {
728c2ecf20Sopenharmony_ci	unsigned int	addr;
738c2ecf20Sopenharmony_ci	unsigned int	insn;
748c2ecf20Sopenharmony_ci};
758c2ecf20Sopenharmony_ciextern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
768c2ecf20Sopenharmony_ci#endif
778c2ecf20Sopenharmony_ci#define TSB_LOAD_QUAD(TSB, REG)	\
788c2ecf20Sopenharmony_ci661:	ldda		[TSB] ASI_NUCLEUS_QUAD_LDD, REG; \
798c2ecf20Sopenharmony_ci	.section	.tsb_ldquad_phys_patch, "ax"; \
808c2ecf20Sopenharmony_ci	.word		661b; \
818c2ecf20Sopenharmony_ci	ldda		[TSB] ASI_QUAD_LDD_PHYS, REG; \
828c2ecf20Sopenharmony_ci	ldda		[TSB] ASI_QUAD_LDD_PHYS_4V, REG; \
838c2ecf20Sopenharmony_ci	.previous
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci#define TSB_LOAD_TAG_HIGH(TSB, REG) \
868c2ecf20Sopenharmony_ci661:	lduwa		[TSB] ASI_N, REG; \
878c2ecf20Sopenharmony_ci	.section	.tsb_phys_patch, "ax"; \
888c2ecf20Sopenharmony_ci	.word		661b; \
898c2ecf20Sopenharmony_ci	lduwa		[TSB] ASI_PHYS_USE_EC, REG; \
908c2ecf20Sopenharmony_ci	.previous
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci#define TSB_LOAD_TAG(TSB, REG) \
938c2ecf20Sopenharmony_ci661:	ldxa		[TSB] ASI_N, REG; \
948c2ecf20Sopenharmony_ci	.section	.tsb_phys_patch, "ax"; \
958c2ecf20Sopenharmony_ci	.word		661b; \
968c2ecf20Sopenharmony_ci	ldxa		[TSB] ASI_PHYS_USE_EC, REG; \
978c2ecf20Sopenharmony_ci	.previous
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci#define TSB_CAS_TAG_HIGH(TSB, REG1, REG2) \
1008c2ecf20Sopenharmony_ci661:	casa		[TSB] ASI_N, REG1, REG2; \
1018c2ecf20Sopenharmony_ci	.section	.tsb_phys_patch, "ax"; \
1028c2ecf20Sopenharmony_ci	.word		661b; \
1038c2ecf20Sopenharmony_ci	casa		[TSB] ASI_PHYS_USE_EC, REG1, REG2; \
1048c2ecf20Sopenharmony_ci	.previous
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci#define TSB_CAS_TAG(TSB, REG1, REG2) \
1078c2ecf20Sopenharmony_ci661:	casxa		[TSB] ASI_N, REG1, REG2; \
1088c2ecf20Sopenharmony_ci	.section	.tsb_phys_patch, "ax"; \
1098c2ecf20Sopenharmony_ci	.word		661b; \
1108c2ecf20Sopenharmony_ci	casxa		[TSB] ASI_PHYS_USE_EC, REG1, REG2; \
1118c2ecf20Sopenharmony_ci	.previous
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci#define TSB_STORE(ADDR, VAL) \
1148c2ecf20Sopenharmony_ci661:	stxa		VAL, [ADDR] ASI_N; \
1158c2ecf20Sopenharmony_ci	.section	.tsb_phys_patch, "ax"; \
1168c2ecf20Sopenharmony_ci	.word		661b; \
1178c2ecf20Sopenharmony_ci	stxa		VAL, [ADDR] ASI_PHYS_USE_EC; \
1188c2ecf20Sopenharmony_ci	.previous
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci#define TSB_LOCK_TAG(TSB, REG1, REG2)	\
1218c2ecf20Sopenharmony_ci99:	TSB_LOAD_TAG_HIGH(TSB, REG1);	\
1228c2ecf20Sopenharmony_ci	sethi	%hi(TSB_TAG_LOCK_HIGH), REG2;\
1238c2ecf20Sopenharmony_ci	andcc	REG1, REG2, %g0;	\
1248c2ecf20Sopenharmony_ci	bne,pn	%icc, 99b;		\
1258c2ecf20Sopenharmony_ci	 nop;				\
1268c2ecf20Sopenharmony_ci	TSB_CAS_TAG_HIGH(TSB, REG1, REG2);	\
1278c2ecf20Sopenharmony_ci	cmp	REG1, REG2;		\
1288c2ecf20Sopenharmony_ci	bne,pn	%icc, 99b;		\
1298c2ecf20Sopenharmony_ci	 nop;				\
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci#define TSB_WRITE(TSB, TTE, TAG) \
1328c2ecf20Sopenharmony_ci	add	TSB, 0x8, TSB;   \
1338c2ecf20Sopenharmony_ci	TSB_STORE(TSB, TTE);     \
1348c2ecf20Sopenharmony_ci	sub	TSB, 0x8, TSB;   \
1358c2ecf20Sopenharmony_ci	TSB_STORE(TSB, TAG);
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	/* Do a kernel page table walk.  Leaves valid PTE value in
1388c2ecf20Sopenharmony_ci	 * REG1.  Jumps to FAIL_LABEL on early page table walk
1398c2ecf20Sopenharmony_ci	 * termination.  VADDR will not be clobbered, but REG2 will.
1408c2ecf20Sopenharmony_ci	 *
1418c2ecf20Sopenharmony_ci	 * There are two masks we must apply to propagate bits from
1428c2ecf20Sopenharmony_ci	 * the virtual address into the PTE physical address field
1438c2ecf20Sopenharmony_ci	 * when dealing with huge pages.  This is because the page
1448c2ecf20Sopenharmony_ci	 * table boundaries do not match the huge page size(s) the
1458c2ecf20Sopenharmony_ci	 * hardware supports.
1468c2ecf20Sopenharmony_ci	 *
1478c2ecf20Sopenharmony_ci	 * In these cases we propagate the bits that are below the
1488c2ecf20Sopenharmony_ci	 * page table level where we saw the huge page mapping, but
1498c2ecf20Sopenharmony_ci	 * are still within the relevant physical bits for the huge
1508c2ecf20Sopenharmony_ci	 * page size in question.  So for PMD mappings (which fall on
1518c2ecf20Sopenharmony_ci	 * bit 23, for 8MB per PMD) we must propagate bit 22 for a
1528c2ecf20Sopenharmony_ci	 * 4MB huge page.  For huge PUDs (which fall on bit 33, for
1538c2ecf20Sopenharmony_ci	 * 8GB per PUD), we have to accommodate 256MB and 2GB huge
1548c2ecf20Sopenharmony_ci	 * pages.  So for those we propagate bits 32 to 28.
1558c2ecf20Sopenharmony_ci	 */
1568c2ecf20Sopenharmony_ci#define KERN_PGTABLE_WALK(VADDR, REG1, REG2, FAIL_LABEL)	\
1578c2ecf20Sopenharmony_ci	sethi		%hi(swapper_pg_dir), REG1; \
1588c2ecf20Sopenharmony_ci	or		REG1, %lo(swapper_pg_dir), REG1; \
1598c2ecf20Sopenharmony_ci	sllx		VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \
1608c2ecf20Sopenharmony_ci	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
1618c2ecf20Sopenharmony_ci	andn		REG2, 0x7, REG2; \
1628c2ecf20Sopenharmony_ci	ldx		[REG1 + REG2], REG1; \
1638c2ecf20Sopenharmony_ci	brz,pn		REG1, FAIL_LABEL; \
1648c2ecf20Sopenharmony_ci	 sllx		VADDR, 64 - (PUD_SHIFT + PUD_BITS), REG2; \
1658c2ecf20Sopenharmony_ci	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
1668c2ecf20Sopenharmony_ci	andn		REG2, 0x7, REG2; \
1678c2ecf20Sopenharmony_ci	ldxa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
1688c2ecf20Sopenharmony_ci	brz,pn		REG1, FAIL_LABEL; \
1698c2ecf20Sopenharmony_ci	sethi		%uhi(_PAGE_PUD_HUGE), REG2; \
1708c2ecf20Sopenharmony_ci	brz,pn		REG1, FAIL_LABEL; \
1718c2ecf20Sopenharmony_ci	 sllx		REG2, 32, REG2; \
1728c2ecf20Sopenharmony_ci	andcc		REG1, REG2, %g0; \
1738c2ecf20Sopenharmony_ci	sethi		%hi(0xf8000000), REG2; \
1748c2ecf20Sopenharmony_ci	bne,pt		%xcc, 697f; \
1758c2ecf20Sopenharmony_ci	 sllx		REG2, 1, REG2; \
1768c2ecf20Sopenharmony_ci	sllx		VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \
1778c2ecf20Sopenharmony_ci	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
1788c2ecf20Sopenharmony_ci	andn		REG2, 0x7, REG2; \
1798c2ecf20Sopenharmony_ci	ldxa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
1808c2ecf20Sopenharmony_ci	sethi		%uhi(_PAGE_PMD_HUGE), REG2; \
1818c2ecf20Sopenharmony_ci	brz,pn		REG1, FAIL_LABEL; \
1828c2ecf20Sopenharmony_ci	 sllx		REG2, 32, REG2; \
1838c2ecf20Sopenharmony_ci	andcc		REG1, REG2, %g0; \
1848c2ecf20Sopenharmony_ci	be,pn		%xcc, 698f; \
1858c2ecf20Sopenharmony_ci	 sethi		%hi(0x400000), REG2; \
1868c2ecf20Sopenharmony_ci697:	brgez,pn	REG1, FAIL_LABEL; \
1878c2ecf20Sopenharmony_ci	 andn		REG1, REG2, REG1; \
1888c2ecf20Sopenharmony_ci	and		VADDR, REG2, REG2; \
1898c2ecf20Sopenharmony_ci	ba,pt		%xcc, 699f; \
1908c2ecf20Sopenharmony_ci	 or		REG1, REG2, REG1; \
1918c2ecf20Sopenharmony_ci698:	sllx		VADDR, 64 - PMD_SHIFT, REG2; \
1928c2ecf20Sopenharmony_ci	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
1938c2ecf20Sopenharmony_ci	andn		REG2, 0x7, REG2; \
1948c2ecf20Sopenharmony_ci	ldxa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
1958c2ecf20Sopenharmony_ci	brgez,pn	REG1, FAIL_LABEL; \
1968c2ecf20Sopenharmony_ci	 nop; \
1978c2ecf20Sopenharmony_ci699:
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	/* PUD has been loaded into REG1, interpret the value, seeing
2008c2ecf20Sopenharmony_ci	 * if it is a HUGE PUD or a normal one.  If it is not valid
2018c2ecf20Sopenharmony_ci	 * then jump to FAIL_LABEL.  If it is a HUGE PUD, and it
2028c2ecf20Sopenharmony_ci	 * translates to a valid PTE, branch to PTE_LABEL.
2038c2ecf20Sopenharmony_ci	 *
2048c2ecf20Sopenharmony_ci	 * We have to propagate bits [32:22] from the virtual address
2058c2ecf20Sopenharmony_ci	 * to resolve at 4M granularity.
2068c2ecf20Sopenharmony_ci	 */
2078c2ecf20Sopenharmony_ci#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
2088c2ecf20Sopenharmony_ci#define USER_PGTABLE_CHECK_PUD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, PTE_LABEL) \
2098c2ecf20Sopenharmony_ci700:	ba 700f;					\
2108c2ecf20Sopenharmony_ci	 nop;						\
2118c2ecf20Sopenharmony_ci	.section	.pud_huge_patch, "ax";		\
2128c2ecf20Sopenharmony_ci	.word		700b;				\
2138c2ecf20Sopenharmony_ci	nop;						\
2148c2ecf20Sopenharmony_ci	.previous;					\
2158c2ecf20Sopenharmony_ci	brz,pn		REG1, FAIL_LABEL;		\
2168c2ecf20Sopenharmony_ci	 sethi		%uhi(_PAGE_PUD_HUGE), REG2;	\
2178c2ecf20Sopenharmony_ci	sllx		REG2, 32, REG2;			\
2188c2ecf20Sopenharmony_ci	andcc		REG1, REG2, %g0;		\
2198c2ecf20Sopenharmony_ci	be,pt		%xcc, 700f;			\
2208c2ecf20Sopenharmony_ci	 sethi		%hi(0xffe00000), REG2;		\
2218c2ecf20Sopenharmony_ci	sllx		REG2, 1, REG2;			\
2228c2ecf20Sopenharmony_ci	brgez,pn	REG1, FAIL_LABEL;		\
2238c2ecf20Sopenharmony_ci	 andn		REG1, REG2, REG1;		\
2248c2ecf20Sopenharmony_ci	and		VADDR, REG2, REG2;		\
2258c2ecf20Sopenharmony_ci	brlz,pt		REG1, PTE_LABEL;		\
2268c2ecf20Sopenharmony_ci	 or		REG1, REG2, REG1;		\
2278c2ecf20Sopenharmony_ci700:
2288c2ecf20Sopenharmony_ci#else
2298c2ecf20Sopenharmony_ci#define USER_PGTABLE_CHECK_PUD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, PTE_LABEL) \
2308c2ecf20Sopenharmony_ci	brz,pn		REG1, FAIL_LABEL; \
2318c2ecf20Sopenharmony_ci	 nop;
2328c2ecf20Sopenharmony_ci#endif
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	/* PMD has been loaded into REG1, interpret the value, seeing
2358c2ecf20Sopenharmony_ci	 * if it is a HUGE PMD or a normal one.  If it is not valid
2368c2ecf20Sopenharmony_ci	 * then jump to FAIL_LABEL.  If it is a HUGE PMD, and it
2378c2ecf20Sopenharmony_ci	 * translates to a valid PTE, branch to PTE_LABEL.
2388c2ecf20Sopenharmony_ci	 *
2398c2ecf20Sopenharmony_ci	 * We have to propagate the 4MB bit of the virtual address
2408c2ecf20Sopenharmony_ci	 * because we are fabricating 8MB pages using 4MB hw pages.
2418c2ecf20Sopenharmony_ci	 */
2428c2ecf20Sopenharmony_ci#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
2438c2ecf20Sopenharmony_ci#define USER_PGTABLE_CHECK_PMD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, PTE_LABEL) \
2448c2ecf20Sopenharmony_ci	brz,pn		REG1, FAIL_LABEL;		\
2458c2ecf20Sopenharmony_ci	 sethi		%uhi(_PAGE_PMD_HUGE), REG2;	\
2468c2ecf20Sopenharmony_ci	sllx		REG2, 32, REG2;			\
2478c2ecf20Sopenharmony_ci	andcc		REG1, REG2, %g0;		\
2488c2ecf20Sopenharmony_ci	be,pt		%xcc, 700f;			\
2498c2ecf20Sopenharmony_ci	 sethi		%hi(4 * 1024 * 1024), REG2;	\
2508c2ecf20Sopenharmony_ci	brgez,pn	REG1, FAIL_LABEL;		\
2518c2ecf20Sopenharmony_ci	 andn		REG1, REG2, REG1;		\
2528c2ecf20Sopenharmony_ci	and		VADDR, REG2, REG2;		\
2538c2ecf20Sopenharmony_ci	brlz,pt		REG1, PTE_LABEL;		\
2548c2ecf20Sopenharmony_ci	 or		REG1, REG2, REG1;		\
2558c2ecf20Sopenharmony_ci700:
2568c2ecf20Sopenharmony_ci#else
2578c2ecf20Sopenharmony_ci#define USER_PGTABLE_CHECK_PMD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, PTE_LABEL) \
2588c2ecf20Sopenharmony_ci	brz,pn		REG1, FAIL_LABEL; \
2598c2ecf20Sopenharmony_ci	 nop;
2608c2ecf20Sopenharmony_ci#endif
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	/* Do a user page table walk in MMU globals.  Leaves final,
2638c2ecf20Sopenharmony_ci	 * valid, PTE value in REG1.  Jumps to FAIL_LABEL on early
2648c2ecf20Sopenharmony_ci	 * page table walk termination or if the PTE is not valid.
2658c2ecf20Sopenharmony_ci	 *
2668c2ecf20Sopenharmony_ci	 * Physical base of page tables is in PHYS_PGD which will not
2678c2ecf20Sopenharmony_ci	 * be modified.
2688c2ecf20Sopenharmony_ci	 *
2698c2ecf20Sopenharmony_ci	 * VADDR will not be clobbered, but REG1 and REG2 will.
2708c2ecf20Sopenharmony_ci	 */
2718c2ecf20Sopenharmony_ci#define USER_PGTABLE_WALK_TL1(VADDR, PHYS_PGD, REG1, REG2, FAIL_LABEL)	\
2728c2ecf20Sopenharmony_ci	sllx		VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \
2738c2ecf20Sopenharmony_ci	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
2748c2ecf20Sopenharmony_ci	andn		REG2, 0x7, REG2; \
2758c2ecf20Sopenharmony_ci	ldxa		[PHYS_PGD + REG2] ASI_PHYS_USE_EC, REG1; \
2768c2ecf20Sopenharmony_ci	brz,pn		REG1, FAIL_LABEL; \
2778c2ecf20Sopenharmony_ci	 sllx		VADDR, 64 - (PUD_SHIFT + PUD_BITS), REG2; \
2788c2ecf20Sopenharmony_ci	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
2798c2ecf20Sopenharmony_ci	andn		REG2, 0x7, REG2; \
2808c2ecf20Sopenharmony_ci	ldxa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
2818c2ecf20Sopenharmony_ci	USER_PGTABLE_CHECK_PUD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, 800f) \
2828c2ecf20Sopenharmony_ci	brz,pn		REG1, FAIL_LABEL; \
2838c2ecf20Sopenharmony_ci	 sllx		VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \
2848c2ecf20Sopenharmony_ci	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
2858c2ecf20Sopenharmony_ci	andn		REG2, 0x7, REG2; \
2868c2ecf20Sopenharmony_ci	ldxa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
2878c2ecf20Sopenharmony_ci	USER_PGTABLE_CHECK_PMD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, 800f) \
2888c2ecf20Sopenharmony_ci	sllx		VADDR, 64 - PMD_SHIFT, REG2; \
2898c2ecf20Sopenharmony_ci	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
2908c2ecf20Sopenharmony_ci	andn		REG2, 0x7, REG2; \
2918c2ecf20Sopenharmony_ci	add		REG1, REG2, REG1; \
2928c2ecf20Sopenharmony_ci	ldxa		[REG1] ASI_PHYS_USE_EC, REG1; \
2938c2ecf20Sopenharmony_ci	brgez,pn	REG1, FAIL_LABEL; \
2948c2ecf20Sopenharmony_ci	 nop; \
2958c2ecf20Sopenharmony_ci800:
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci/* Lookup a OBP mapping on VADDR in the prom_trans[] table at TL>0.
2988c2ecf20Sopenharmony_ci * If no entry is found, FAIL_LABEL will be branched to.  On success
2998c2ecf20Sopenharmony_ci * the resulting PTE value will be left in REG1.  VADDR is preserved
3008c2ecf20Sopenharmony_ci * by this routine.
3018c2ecf20Sopenharmony_ci */
3028c2ecf20Sopenharmony_ci#define OBP_TRANS_LOOKUP(VADDR, REG1, REG2, REG3, FAIL_LABEL) \
3038c2ecf20Sopenharmony_ci	sethi		%hi(prom_trans), REG1; \
3048c2ecf20Sopenharmony_ci	or		REG1, %lo(prom_trans), REG1; \
3058c2ecf20Sopenharmony_ci97:	ldx		[REG1 + 0x00], REG2; \
3068c2ecf20Sopenharmony_ci	brz,pn		REG2, FAIL_LABEL; \
3078c2ecf20Sopenharmony_ci	 nop; \
3088c2ecf20Sopenharmony_ci	ldx		[REG1 + 0x08], REG3; \
3098c2ecf20Sopenharmony_ci	add		REG2, REG3, REG3; \
3108c2ecf20Sopenharmony_ci	cmp		REG2, VADDR; \
3118c2ecf20Sopenharmony_ci	bgu,pt		%xcc, 98f; \
3128c2ecf20Sopenharmony_ci	 cmp		VADDR, REG3; \
3138c2ecf20Sopenharmony_ci	bgeu,pt		%xcc, 98f; \
3148c2ecf20Sopenharmony_ci	 ldx		[REG1 + 0x10], REG3; \
3158c2ecf20Sopenharmony_ci	sub		VADDR, REG2, REG2; \
3168c2ecf20Sopenharmony_ci	ba,pt		%xcc, 99f; \
3178c2ecf20Sopenharmony_ci	 add		REG3, REG2, REG1; \
3188c2ecf20Sopenharmony_ci98:	ba,pt		%xcc, 97b; \
3198c2ecf20Sopenharmony_ci	 add		REG1, (3 * 8), REG1; \
3208c2ecf20Sopenharmony_ci99:
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	/* We use a 32K TSB for the whole kernel, this allows to
3238c2ecf20Sopenharmony_ci	 * handle about 16MB of modules and vmalloc mappings without
3248c2ecf20Sopenharmony_ci	 * incurring many hash conflicts.
3258c2ecf20Sopenharmony_ci	 */
3268c2ecf20Sopenharmony_ci#define KERNEL_TSB_SIZE_BYTES	(32 * 1024)
3278c2ecf20Sopenharmony_ci#define KERNEL_TSB_NENTRIES	\
3288c2ecf20Sopenharmony_ci	(KERNEL_TSB_SIZE_BYTES / 16)
3298c2ecf20Sopenharmony_ci#define KERNEL_TSB4M_NENTRIES	4096
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	/* Do a kernel TSB lookup at tl>0 on VADDR+TAG, branch to OK_LABEL
3328c2ecf20Sopenharmony_ci	 * on TSB hit.  REG1, REG2, REG3, and REG4 are used as temporaries
3338c2ecf20Sopenharmony_ci	 * and the found TTE will be left in REG1.  REG3 and REG4 must
3348c2ecf20Sopenharmony_ci	 * be an even/odd pair of registers.
3358c2ecf20Sopenharmony_ci	 *
3368c2ecf20Sopenharmony_ci	 * VADDR and TAG will be preserved and not clobbered by this macro.
3378c2ecf20Sopenharmony_ci	 */
3388c2ecf20Sopenharmony_ci#define KERN_TSB_LOOKUP_TL1(VADDR, TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
3398c2ecf20Sopenharmony_ci661:	sethi		%uhi(swapper_tsb), REG1; \
3408c2ecf20Sopenharmony_ci	sethi		%hi(swapper_tsb), REG2; \
3418c2ecf20Sopenharmony_ci	or		REG1, %ulo(swapper_tsb), REG1; \
3428c2ecf20Sopenharmony_ci	or		REG2, %lo(swapper_tsb), REG2; \
3438c2ecf20Sopenharmony_ci	.section	.swapper_tsb_phys_patch, "ax"; \
3448c2ecf20Sopenharmony_ci	.word		661b; \
3458c2ecf20Sopenharmony_ci	.previous; \
3468c2ecf20Sopenharmony_ci	sllx		REG1, 32, REG1; \
3478c2ecf20Sopenharmony_ci	or		REG1, REG2, REG1; \
3488c2ecf20Sopenharmony_ci	srlx		VADDR, PAGE_SHIFT, REG2; \
3498c2ecf20Sopenharmony_ci	and		REG2, (KERNEL_TSB_NENTRIES - 1), REG2; \
3508c2ecf20Sopenharmony_ci	sllx		REG2, 4, REG2; \
3518c2ecf20Sopenharmony_ci	add		REG1, REG2, REG2; \
3528c2ecf20Sopenharmony_ci	TSB_LOAD_QUAD(REG2, REG3); \
3538c2ecf20Sopenharmony_ci	cmp		REG3, TAG; \
3548c2ecf20Sopenharmony_ci	be,a,pt		%xcc, OK_LABEL; \
3558c2ecf20Sopenharmony_ci	 mov		REG4, REG1;
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci#ifndef CONFIG_DEBUG_PAGEALLOC
3588c2ecf20Sopenharmony_ci	/* This version uses a trick, the TAG is already (VADDR >> 22) so
3598c2ecf20Sopenharmony_ci	 * we can make use of that for the index computation.
3608c2ecf20Sopenharmony_ci	 */
3618c2ecf20Sopenharmony_ci#define KERN_TSB4M_LOOKUP_TL1(TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
3628c2ecf20Sopenharmony_ci661:	sethi		%uhi(swapper_4m_tsb), REG1; \
3638c2ecf20Sopenharmony_ci	sethi		%hi(swapper_4m_tsb), REG2; \
3648c2ecf20Sopenharmony_ci	or		REG1, %ulo(swapper_4m_tsb), REG1; \
3658c2ecf20Sopenharmony_ci	or		REG2, %lo(swapper_4m_tsb), REG2; \
3668c2ecf20Sopenharmony_ci	.section	.swapper_4m_tsb_phys_patch, "ax"; \
3678c2ecf20Sopenharmony_ci	.word		661b; \
3688c2ecf20Sopenharmony_ci	.previous; \
3698c2ecf20Sopenharmony_ci	sllx		REG1, 32, REG1; \
3708c2ecf20Sopenharmony_ci	or		REG1, REG2, REG1; \
3718c2ecf20Sopenharmony_ci	and		TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \
3728c2ecf20Sopenharmony_ci	sllx		REG2, 4, REG2; \
3738c2ecf20Sopenharmony_ci	add		REG1, REG2, REG2; \
3748c2ecf20Sopenharmony_ci	TSB_LOAD_QUAD(REG2, REG3); \
3758c2ecf20Sopenharmony_ci	cmp		REG3, TAG; \
3768c2ecf20Sopenharmony_ci	be,a,pt		%xcc, OK_LABEL; \
3778c2ecf20Sopenharmony_ci	 mov		REG4, REG1;
3788c2ecf20Sopenharmony_ci#endif
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci#endif /* !(_SPARC64_TSB_H) */
381