xref: /OK3568_Linux_fs/kernel/arch/sparc/include/asm/tsb.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun #ifndef _SPARC64_TSB_H
3*4882a593Smuzhiyun #define _SPARC64_TSB_H
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun /* The sparc64 TSB is similar to the powerpc hashtables.  It's a
6*4882a593Smuzhiyun  * power-of-2 sized table of TAG/PTE pairs.  The cpu precomputes
7*4882a593Smuzhiyun  * pointers into this table for 8K and 64K page sizes, and also a
8*4882a593Smuzhiyun  * comparison TAG based upon the virtual address and context which
9*4882a593Smuzhiyun  * faults.
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * TLB miss trap handler software does the actual lookup via something
12*4882a593Smuzhiyun  * of the form:
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * 	ldxa		[%g0] ASI_{D,I}MMU_TSB_8KB_PTR, %g1
15*4882a593Smuzhiyun  * 	ldxa		[%g0] ASI_{D,I}MMU, %g6
16*4882a593Smuzhiyun  *	sllx		%g6, 22, %g6
17*4882a593Smuzhiyun  *	srlx		%g6, 22, %g6
18*4882a593Smuzhiyun  * 	ldda		[%g1] ASI_NUCLEUS_QUAD_LDD, %g4
19*4882a593Smuzhiyun  * 	cmp		%g4, %g6
20*4882a593Smuzhiyun  * 	bne,pn	%xcc, tsb_miss_{d,i}tlb
21*4882a593Smuzhiyun  * 	 mov		FAULT_CODE_{D,I}TLB, %g3
22*4882a593Smuzhiyun  * 	stxa		%g5, [%g0] ASI_{D,I}TLB_DATA_IN
23*4882a593Smuzhiyun  * 	retry
24*4882a593Smuzhiyun  *
25*4882a593Smuzhiyun  *
26*4882a593Smuzhiyun  * Each 16-byte slot of the TSB is the 8-byte tag and then the 8-byte
27*4882a593Smuzhiyun  * PTE.  The TAG is of the same layout as the TLB TAG TARGET mmu
28*4882a593Smuzhiyun  * register which is:
29*4882a593Smuzhiyun  *
30*4882a593Smuzhiyun  * -------------------------------------------------
31*4882a593Smuzhiyun  * |  -  |  CONTEXT |  -  |    VADDR bits 63:22    |
32*4882a593Smuzhiyun  * -------------------------------------------------
33*4882a593Smuzhiyun  *  63 61 60      48 47 42 41                     0
34*4882a593Smuzhiyun  *
35*4882a593Smuzhiyun  * But actually, since we use per-mm TSB's, we zero out the CONTEXT
36*4882a593Smuzhiyun  * field.
37*4882a593Smuzhiyun  *
38*4882a593Smuzhiyun  * Like the powerpc hashtables we need to use locking in order to
39*4882a593Smuzhiyun  * synchronize while we update the entries.  PTE updates need locking
40*4882a593Smuzhiyun  * as well.
41*4882a593Smuzhiyun  *
42*4882a593Smuzhiyun  * We need to carefully choose a lock bits for the TSB entry.  We
43*4882a593Smuzhiyun  * choose to use bit 47 in the tag.  Also, since we never map anything
44*4882a593Smuzhiyun  * at page zero in context zero, we use zero as an invalid tag entry.
45*4882a593Smuzhiyun  * When the lock bit is set, this forces a tag comparison failure.
46*4882a593Smuzhiyun  */
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun #define TSB_TAG_LOCK_BIT	47
49*4882a593Smuzhiyun #define TSB_TAG_LOCK_HIGH	(1 << (TSB_TAG_LOCK_BIT - 32))
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun #define TSB_TAG_INVALID_BIT	46
52*4882a593Smuzhiyun #define TSB_TAG_INVALID_HIGH	(1 << (TSB_TAG_INVALID_BIT - 32))
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun /* Some cpus support physical address quad loads.  We want to use
55*4882a593Smuzhiyun  * those if possible so we don't need to hard-lock the TSB mapping
56*4882a593Smuzhiyun  * into the TLB.  We encode some instruction patching in order to
57*4882a593Smuzhiyun  * support this.
58*4882a593Smuzhiyun  *
59*4882a593Smuzhiyun  * The kernel TSB is locked into the TLB by virtue of being in the
60*4882a593Smuzhiyun  * kernel image, so we don't play these games for swapper_tsb access.
61*4882a593Smuzhiyun  */
62*4882a593Smuzhiyun #ifndef __ASSEMBLY__
63*4882a593Smuzhiyun struct tsb_ldquad_phys_patch_entry {
64*4882a593Smuzhiyun 	unsigned int	addr;
65*4882a593Smuzhiyun 	unsigned int	sun4u_insn;
66*4882a593Smuzhiyun 	unsigned int	sun4v_insn;
67*4882a593Smuzhiyun };
68*4882a593Smuzhiyun extern struct tsb_ldquad_phys_patch_entry __tsb_ldquad_phys_patch,
69*4882a593Smuzhiyun 	__tsb_ldquad_phys_patch_end;
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun struct tsb_phys_patch_entry {
72*4882a593Smuzhiyun 	unsigned int	addr;
73*4882a593Smuzhiyun 	unsigned int	insn;
74*4882a593Smuzhiyun };
75*4882a593Smuzhiyun extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
76*4882a593Smuzhiyun #endif
77*4882a593Smuzhiyun #define TSB_LOAD_QUAD(TSB, REG)	\
78*4882a593Smuzhiyun 661:	ldda		[TSB] ASI_NUCLEUS_QUAD_LDD, REG; \
79*4882a593Smuzhiyun 	.section	.tsb_ldquad_phys_patch, "ax"; \
80*4882a593Smuzhiyun 	.word		661b; \
81*4882a593Smuzhiyun 	ldda		[TSB] ASI_QUAD_LDD_PHYS, REG; \
82*4882a593Smuzhiyun 	ldda		[TSB] ASI_QUAD_LDD_PHYS_4V, REG; \
83*4882a593Smuzhiyun 	.previous
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun #define TSB_LOAD_TAG_HIGH(TSB, REG) \
86*4882a593Smuzhiyun 661:	lduwa		[TSB] ASI_N, REG; \
87*4882a593Smuzhiyun 	.section	.tsb_phys_patch, "ax"; \
88*4882a593Smuzhiyun 	.word		661b; \
89*4882a593Smuzhiyun 	lduwa		[TSB] ASI_PHYS_USE_EC, REG; \
90*4882a593Smuzhiyun 	.previous
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun #define TSB_LOAD_TAG(TSB, REG) \
93*4882a593Smuzhiyun 661:	ldxa		[TSB] ASI_N, REG; \
94*4882a593Smuzhiyun 	.section	.tsb_phys_patch, "ax"; \
95*4882a593Smuzhiyun 	.word		661b; \
96*4882a593Smuzhiyun 	ldxa		[TSB] ASI_PHYS_USE_EC, REG; \
97*4882a593Smuzhiyun 	.previous
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun #define TSB_CAS_TAG_HIGH(TSB, REG1, REG2) \
100*4882a593Smuzhiyun 661:	casa		[TSB] ASI_N, REG1, REG2; \
101*4882a593Smuzhiyun 	.section	.tsb_phys_patch, "ax"; \
102*4882a593Smuzhiyun 	.word		661b; \
103*4882a593Smuzhiyun 	casa		[TSB] ASI_PHYS_USE_EC, REG1, REG2; \
104*4882a593Smuzhiyun 	.previous
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun #define TSB_CAS_TAG(TSB, REG1, REG2) \
107*4882a593Smuzhiyun 661:	casxa		[TSB] ASI_N, REG1, REG2; \
108*4882a593Smuzhiyun 	.section	.tsb_phys_patch, "ax"; \
109*4882a593Smuzhiyun 	.word		661b; \
110*4882a593Smuzhiyun 	casxa		[TSB] ASI_PHYS_USE_EC, REG1, REG2; \
111*4882a593Smuzhiyun 	.previous
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun #define TSB_STORE(ADDR, VAL) \
114*4882a593Smuzhiyun 661:	stxa		VAL, [ADDR] ASI_N; \
115*4882a593Smuzhiyun 	.section	.tsb_phys_patch, "ax"; \
116*4882a593Smuzhiyun 	.word		661b; \
117*4882a593Smuzhiyun 	stxa		VAL, [ADDR] ASI_PHYS_USE_EC; \
118*4882a593Smuzhiyun 	.previous
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun #define TSB_LOCK_TAG(TSB, REG1, REG2)	\
121*4882a593Smuzhiyun 99:	TSB_LOAD_TAG_HIGH(TSB, REG1);	\
122*4882a593Smuzhiyun 	sethi	%hi(TSB_TAG_LOCK_HIGH), REG2;\
123*4882a593Smuzhiyun 	andcc	REG1, REG2, %g0;	\
124*4882a593Smuzhiyun 	bne,pn	%icc, 99b;		\
125*4882a593Smuzhiyun 	 nop;				\
126*4882a593Smuzhiyun 	TSB_CAS_TAG_HIGH(TSB, REG1, REG2);	\
127*4882a593Smuzhiyun 	cmp	REG1, REG2;		\
128*4882a593Smuzhiyun 	bne,pn	%icc, 99b;		\
129*4882a593Smuzhiyun 	 nop;				\
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun #define TSB_WRITE(TSB, TTE, TAG) \
132*4882a593Smuzhiyun 	add	TSB, 0x8, TSB;   \
133*4882a593Smuzhiyun 	TSB_STORE(TSB, TTE);     \
134*4882a593Smuzhiyun 	sub	TSB, 0x8, TSB;   \
135*4882a593Smuzhiyun 	TSB_STORE(TSB, TAG);
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	/* Do a kernel page table walk.  Leaves valid PTE value in
138*4882a593Smuzhiyun 	 * REG1.  Jumps to FAIL_LABEL on early page table walk
139*4882a593Smuzhiyun 	 * termination.  VADDR will not be clobbered, but REG2 will.
140*4882a593Smuzhiyun 	 *
141*4882a593Smuzhiyun 	 * There are two masks we must apply to propagate bits from
142*4882a593Smuzhiyun 	 * the virtual address into the PTE physical address field
143*4882a593Smuzhiyun 	 * when dealing with huge pages.  This is because the page
144*4882a593Smuzhiyun 	 * table boundaries do not match the huge page size(s) the
145*4882a593Smuzhiyun 	 * hardware supports.
146*4882a593Smuzhiyun 	 *
147*4882a593Smuzhiyun 	 * In these cases we propagate the bits that are below the
148*4882a593Smuzhiyun 	 * page table level where we saw the huge page mapping, but
149*4882a593Smuzhiyun 	 * are still within the relevant physical bits for the huge
150*4882a593Smuzhiyun 	 * page size in question.  So for PMD mappings (which fall on
151*4882a593Smuzhiyun 	 * bit 23, for 8MB per PMD) we must propagate bit 22 for a
152*4882a593Smuzhiyun 	 * 4MB huge page.  For huge PUDs (which fall on bit 33, for
153*4882a593Smuzhiyun 	 * 8GB per PUD), we have to accommodate 256MB and 2GB huge
154*4882a593Smuzhiyun 	 * pages.  So for those we propagate bits 32 to 28.
155*4882a593Smuzhiyun 	 */
156*4882a593Smuzhiyun #define KERN_PGTABLE_WALK(VADDR, REG1, REG2, FAIL_LABEL)	\
157*4882a593Smuzhiyun 	sethi		%hi(swapper_pg_dir), REG1; \
158*4882a593Smuzhiyun 	or		REG1, %lo(swapper_pg_dir), REG1; \
159*4882a593Smuzhiyun 	sllx		VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \
160*4882a593Smuzhiyun 	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
161*4882a593Smuzhiyun 	andn		REG2, 0x7, REG2; \
162*4882a593Smuzhiyun 	ldx		[REG1 + REG2], REG1; \
163*4882a593Smuzhiyun 	brz,pn		REG1, FAIL_LABEL; \
164*4882a593Smuzhiyun 	 sllx		VADDR, 64 - (PUD_SHIFT + PUD_BITS), REG2; \
165*4882a593Smuzhiyun 	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
166*4882a593Smuzhiyun 	andn		REG2, 0x7, REG2; \
167*4882a593Smuzhiyun 	ldxa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
168*4882a593Smuzhiyun 	brz,pn		REG1, FAIL_LABEL; \
169*4882a593Smuzhiyun 	sethi		%uhi(_PAGE_PUD_HUGE), REG2; \
170*4882a593Smuzhiyun 	brz,pn		REG1, FAIL_LABEL; \
171*4882a593Smuzhiyun 	 sllx		REG2, 32, REG2; \
172*4882a593Smuzhiyun 	andcc		REG1, REG2, %g0; \
173*4882a593Smuzhiyun 	sethi		%hi(0xf8000000), REG2; \
174*4882a593Smuzhiyun 	bne,pt		%xcc, 697f; \
175*4882a593Smuzhiyun 	 sllx		REG2, 1, REG2; \
176*4882a593Smuzhiyun 	sllx		VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \
177*4882a593Smuzhiyun 	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
178*4882a593Smuzhiyun 	andn		REG2, 0x7, REG2; \
179*4882a593Smuzhiyun 	ldxa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
180*4882a593Smuzhiyun 	sethi		%uhi(_PAGE_PMD_HUGE), REG2; \
181*4882a593Smuzhiyun 	brz,pn		REG1, FAIL_LABEL; \
182*4882a593Smuzhiyun 	 sllx		REG2, 32, REG2; \
183*4882a593Smuzhiyun 	andcc		REG1, REG2, %g0; \
184*4882a593Smuzhiyun 	be,pn		%xcc, 698f; \
185*4882a593Smuzhiyun 	 sethi		%hi(0x400000), REG2; \
186*4882a593Smuzhiyun 697:	brgez,pn	REG1, FAIL_LABEL; \
187*4882a593Smuzhiyun 	 andn		REG1, REG2, REG1; \
188*4882a593Smuzhiyun 	and		VADDR, REG2, REG2; \
189*4882a593Smuzhiyun 	ba,pt		%xcc, 699f; \
190*4882a593Smuzhiyun 	 or		REG1, REG2, REG1; \
191*4882a593Smuzhiyun 698:	sllx		VADDR, 64 - PMD_SHIFT, REG2; \
192*4882a593Smuzhiyun 	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
193*4882a593Smuzhiyun 	andn		REG2, 0x7, REG2; \
194*4882a593Smuzhiyun 	ldxa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
195*4882a593Smuzhiyun 	brgez,pn	REG1, FAIL_LABEL; \
196*4882a593Smuzhiyun 	 nop; \
197*4882a593Smuzhiyun 699:
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	/* PUD has been loaded into REG1, interpret the value, seeing
200*4882a593Smuzhiyun 	 * if it is a HUGE PUD or a normal one.  If it is not valid
201*4882a593Smuzhiyun 	 * then jump to FAIL_LABEL.  If it is a HUGE PUD, and it
202*4882a593Smuzhiyun 	 * translates to a valid PTE, branch to PTE_LABEL.
203*4882a593Smuzhiyun 	 *
204*4882a593Smuzhiyun 	 * We have to propagate bits [32:22] from the virtual address
205*4882a593Smuzhiyun 	 * to resolve at 4M granularity.
206*4882a593Smuzhiyun 	 */
207*4882a593Smuzhiyun #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
208*4882a593Smuzhiyun #define USER_PGTABLE_CHECK_PUD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, PTE_LABEL) \
209*4882a593Smuzhiyun 700:	ba 700f;					\
210*4882a593Smuzhiyun 	 nop;						\
211*4882a593Smuzhiyun 	.section	.pud_huge_patch, "ax";		\
212*4882a593Smuzhiyun 	.word		700b;				\
213*4882a593Smuzhiyun 	nop;						\
214*4882a593Smuzhiyun 	.previous;					\
215*4882a593Smuzhiyun 	brz,pn		REG1, FAIL_LABEL;		\
216*4882a593Smuzhiyun 	 sethi		%uhi(_PAGE_PUD_HUGE), REG2;	\
217*4882a593Smuzhiyun 	sllx		REG2, 32, REG2;			\
218*4882a593Smuzhiyun 	andcc		REG1, REG2, %g0;		\
219*4882a593Smuzhiyun 	be,pt		%xcc, 700f;			\
220*4882a593Smuzhiyun 	 sethi		%hi(0xffe00000), REG2;		\
221*4882a593Smuzhiyun 	sllx		REG2, 1, REG2;			\
222*4882a593Smuzhiyun 	brgez,pn	REG1, FAIL_LABEL;		\
223*4882a593Smuzhiyun 	 andn		REG1, REG2, REG1;		\
224*4882a593Smuzhiyun 	and		VADDR, REG2, REG2;		\
225*4882a593Smuzhiyun 	brlz,pt		REG1, PTE_LABEL;		\
226*4882a593Smuzhiyun 	 or		REG1, REG2, REG1;		\
227*4882a593Smuzhiyun 700:
228*4882a593Smuzhiyun #else
229*4882a593Smuzhiyun #define USER_PGTABLE_CHECK_PUD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, PTE_LABEL) \
230*4882a593Smuzhiyun 	brz,pn		REG1, FAIL_LABEL; \
231*4882a593Smuzhiyun 	 nop;
232*4882a593Smuzhiyun #endif
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	/* PMD has been loaded into REG1, interpret the value, seeing
235*4882a593Smuzhiyun 	 * if it is a HUGE PMD or a normal one.  If it is not valid
236*4882a593Smuzhiyun 	 * then jump to FAIL_LABEL.  If it is a HUGE PMD, and it
237*4882a593Smuzhiyun 	 * translates to a valid PTE, branch to PTE_LABEL.
238*4882a593Smuzhiyun 	 *
239*4882a593Smuzhiyun 	 * We have to propagate the 4MB bit of the virtual address
240*4882a593Smuzhiyun 	 * because we are fabricating 8MB pages using 4MB hw pages.
241*4882a593Smuzhiyun 	 */
242*4882a593Smuzhiyun #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
243*4882a593Smuzhiyun #define USER_PGTABLE_CHECK_PMD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, PTE_LABEL) \
244*4882a593Smuzhiyun 	brz,pn		REG1, FAIL_LABEL;		\
245*4882a593Smuzhiyun 	 sethi		%uhi(_PAGE_PMD_HUGE), REG2;	\
246*4882a593Smuzhiyun 	sllx		REG2, 32, REG2;			\
247*4882a593Smuzhiyun 	andcc		REG1, REG2, %g0;		\
248*4882a593Smuzhiyun 	be,pt		%xcc, 700f;			\
249*4882a593Smuzhiyun 	 sethi		%hi(4 * 1024 * 1024), REG2;	\
250*4882a593Smuzhiyun 	brgez,pn	REG1, FAIL_LABEL;		\
251*4882a593Smuzhiyun 	 andn		REG1, REG2, REG1;		\
252*4882a593Smuzhiyun 	and		VADDR, REG2, REG2;		\
253*4882a593Smuzhiyun 	brlz,pt		REG1, PTE_LABEL;		\
254*4882a593Smuzhiyun 	 or		REG1, REG2, REG1;		\
255*4882a593Smuzhiyun 700:
256*4882a593Smuzhiyun #else
257*4882a593Smuzhiyun #define USER_PGTABLE_CHECK_PMD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, PTE_LABEL) \
258*4882a593Smuzhiyun 	brz,pn		REG1, FAIL_LABEL; \
259*4882a593Smuzhiyun 	 nop;
260*4882a593Smuzhiyun #endif
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	/* Do a user page table walk in MMU globals.  Leaves final,
263*4882a593Smuzhiyun 	 * valid, PTE value in REG1.  Jumps to FAIL_LABEL on early
264*4882a593Smuzhiyun 	 * page table walk termination or if the PTE is not valid.
265*4882a593Smuzhiyun 	 *
266*4882a593Smuzhiyun 	 * Physical base of page tables is in PHYS_PGD which will not
267*4882a593Smuzhiyun 	 * be modified.
268*4882a593Smuzhiyun 	 *
269*4882a593Smuzhiyun 	 * VADDR will not be clobbered, but REG1 and REG2 will.
270*4882a593Smuzhiyun 	 */
271*4882a593Smuzhiyun #define USER_PGTABLE_WALK_TL1(VADDR, PHYS_PGD, REG1, REG2, FAIL_LABEL)	\
272*4882a593Smuzhiyun 	sllx		VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \
273*4882a593Smuzhiyun 	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
274*4882a593Smuzhiyun 	andn		REG2, 0x7, REG2; \
275*4882a593Smuzhiyun 	ldxa		[PHYS_PGD + REG2] ASI_PHYS_USE_EC, REG1; \
276*4882a593Smuzhiyun 	brz,pn		REG1, FAIL_LABEL; \
277*4882a593Smuzhiyun 	 sllx		VADDR, 64 - (PUD_SHIFT + PUD_BITS), REG2; \
278*4882a593Smuzhiyun 	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
279*4882a593Smuzhiyun 	andn		REG2, 0x7, REG2; \
280*4882a593Smuzhiyun 	ldxa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
281*4882a593Smuzhiyun 	USER_PGTABLE_CHECK_PUD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, 800f) \
282*4882a593Smuzhiyun 	brz,pn		REG1, FAIL_LABEL; \
283*4882a593Smuzhiyun 	 sllx		VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \
284*4882a593Smuzhiyun 	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
285*4882a593Smuzhiyun 	andn		REG2, 0x7, REG2; \
286*4882a593Smuzhiyun 	ldxa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
287*4882a593Smuzhiyun 	USER_PGTABLE_CHECK_PMD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, 800f) \
288*4882a593Smuzhiyun 	sllx		VADDR, 64 - PMD_SHIFT, REG2; \
289*4882a593Smuzhiyun 	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
290*4882a593Smuzhiyun 	andn		REG2, 0x7, REG2; \
291*4882a593Smuzhiyun 	add		REG1, REG2, REG1; \
292*4882a593Smuzhiyun 	ldxa		[REG1] ASI_PHYS_USE_EC, REG1; \
293*4882a593Smuzhiyun 	brgez,pn	REG1, FAIL_LABEL; \
294*4882a593Smuzhiyun 	 nop; \
295*4882a593Smuzhiyun 800:
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun /* Lookup a OBP mapping on VADDR in the prom_trans[] table at TL>0.
298*4882a593Smuzhiyun  * If no entry is found, FAIL_LABEL will be branched to.  On success
299*4882a593Smuzhiyun  * the resulting PTE value will be left in REG1.  VADDR is preserved
300*4882a593Smuzhiyun  * by this routine.
301*4882a593Smuzhiyun  */
302*4882a593Smuzhiyun #define OBP_TRANS_LOOKUP(VADDR, REG1, REG2, REG3, FAIL_LABEL) \
303*4882a593Smuzhiyun 	sethi		%hi(prom_trans), REG1; \
304*4882a593Smuzhiyun 	or		REG1, %lo(prom_trans), REG1; \
305*4882a593Smuzhiyun 97:	ldx		[REG1 + 0x00], REG2; \
306*4882a593Smuzhiyun 	brz,pn		REG2, FAIL_LABEL; \
307*4882a593Smuzhiyun 	 nop; \
308*4882a593Smuzhiyun 	ldx		[REG1 + 0x08], REG3; \
309*4882a593Smuzhiyun 	add		REG2, REG3, REG3; \
310*4882a593Smuzhiyun 	cmp		REG2, VADDR; \
311*4882a593Smuzhiyun 	bgu,pt		%xcc, 98f; \
312*4882a593Smuzhiyun 	 cmp		VADDR, REG3; \
313*4882a593Smuzhiyun 	bgeu,pt		%xcc, 98f; \
314*4882a593Smuzhiyun 	 ldx		[REG1 + 0x10], REG3; \
315*4882a593Smuzhiyun 	sub		VADDR, REG2, REG2; \
316*4882a593Smuzhiyun 	ba,pt		%xcc, 99f; \
317*4882a593Smuzhiyun 	 add		REG3, REG2, REG1; \
318*4882a593Smuzhiyun 98:	ba,pt		%xcc, 97b; \
319*4882a593Smuzhiyun 	 add		REG1, (3 * 8), REG1; \
320*4882a593Smuzhiyun 99:
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	/* We use a 32K TSB for the whole kernel, this allows to
323*4882a593Smuzhiyun 	 * handle about 16MB of modules and vmalloc mappings without
324*4882a593Smuzhiyun 	 * incurring many hash conflicts.
325*4882a593Smuzhiyun 	 */
326*4882a593Smuzhiyun #define KERNEL_TSB_SIZE_BYTES	(32 * 1024)
327*4882a593Smuzhiyun #define KERNEL_TSB_NENTRIES	\
328*4882a593Smuzhiyun 	(KERNEL_TSB_SIZE_BYTES / 16)
329*4882a593Smuzhiyun #define KERNEL_TSB4M_NENTRIES	4096
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	/* Do a kernel TSB lookup at tl>0 on VADDR+TAG, branch to OK_LABEL
332*4882a593Smuzhiyun 	 * on TSB hit.  REG1, REG2, REG3, and REG4 are used as temporaries
333*4882a593Smuzhiyun 	 * and the found TTE will be left in REG1.  REG3 and REG4 must
334*4882a593Smuzhiyun 	 * be an even/odd pair of registers.
335*4882a593Smuzhiyun 	 *
336*4882a593Smuzhiyun 	 * VADDR and TAG will be preserved and not clobbered by this macro.
337*4882a593Smuzhiyun 	 */
338*4882a593Smuzhiyun #define KERN_TSB_LOOKUP_TL1(VADDR, TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
339*4882a593Smuzhiyun 661:	sethi		%uhi(swapper_tsb), REG1; \
340*4882a593Smuzhiyun 	sethi		%hi(swapper_tsb), REG2; \
341*4882a593Smuzhiyun 	or		REG1, %ulo(swapper_tsb), REG1; \
342*4882a593Smuzhiyun 	or		REG2, %lo(swapper_tsb), REG2; \
343*4882a593Smuzhiyun 	.section	.swapper_tsb_phys_patch, "ax"; \
344*4882a593Smuzhiyun 	.word		661b; \
345*4882a593Smuzhiyun 	.previous; \
346*4882a593Smuzhiyun 	sllx		REG1, 32, REG1; \
347*4882a593Smuzhiyun 	or		REG1, REG2, REG1; \
348*4882a593Smuzhiyun 	srlx		VADDR, PAGE_SHIFT, REG2; \
349*4882a593Smuzhiyun 	and		REG2, (KERNEL_TSB_NENTRIES - 1), REG2; \
350*4882a593Smuzhiyun 	sllx		REG2, 4, REG2; \
351*4882a593Smuzhiyun 	add		REG1, REG2, REG2; \
352*4882a593Smuzhiyun 	TSB_LOAD_QUAD(REG2, REG3); \
353*4882a593Smuzhiyun 	cmp		REG3, TAG; \
354*4882a593Smuzhiyun 	be,a,pt		%xcc, OK_LABEL; \
355*4882a593Smuzhiyun 	 mov		REG4, REG1;
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun #ifndef CONFIG_DEBUG_PAGEALLOC
358*4882a593Smuzhiyun 	/* This version uses a trick, the TAG is already (VADDR >> 22) so
359*4882a593Smuzhiyun 	 * we can make use of that for the index computation.
360*4882a593Smuzhiyun 	 */
361*4882a593Smuzhiyun #define KERN_TSB4M_LOOKUP_TL1(TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
362*4882a593Smuzhiyun 661:	sethi		%uhi(swapper_4m_tsb), REG1; \
363*4882a593Smuzhiyun 	sethi		%hi(swapper_4m_tsb), REG2; \
364*4882a593Smuzhiyun 	or		REG1, %ulo(swapper_4m_tsb), REG1; \
365*4882a593Smuzhiyun 	or		REG2, %lo(swapper_4m_tsb), REG2; \
366*4882a593Smuzhiyun 	.section	.swapper_4m_tsb_phys_patch, "ax"; \
367*4882a593Smuzhiyun 	.word		661b; \
368*4882a593Smuzhiyun 	.previous; \
369*4882a593Smuzhiyun 	sllx		REG1, 32, REG1; \
370*4882a593Smuzhiyun 	or		REG1, REG2, REG1; \
371*4882a593Smuzhiyun 	and		TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \
372*4882a593Smuzhiyun 	sllx		REG2, 4, REG2; \
373*4882a593Smuzhiyun 	add		REG1, REG2, REG2; \
374*4882a593Smuzhiyun 	TSB_LOAD_QUAD(REG2, REG3); \
375*4882a593Smuzhiyun 	cmp		REG3, TAG; \
376*4882a593Smuzhiyun 	be,a,pt		%xcc, OK_LABEL; \
377*4882a593Smuzhiyun 	 mov		REG4, REG1;
378*4882a593Smuzhiyun #endif
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun #endif /* !(_SPARC64_TSB_H) */
381