1*dfc3095cSChristophe Leroy/* SPDX-License-Identifier: GPL-2.0 */
2*dfc3095cSChristophe Leroy
3*dfc3095cSChristophe Leroy/* 1. Find the index of the entry we're executing in */
4*dfc3095cSChristophe Leroy	bcl	20,31,$+4				/* Find our address */
5*dfc3095cSChristophe Leroyinvstr:	mflr	r6				/* Make it accessible */
6*dfc3095cSChristophe Leroy	mfmsr	r7
7*dfc3095cSChristophe Leroy	rlwinm	r4,r7,27,31,31			/* extract MSR[IS] */
8*dfc3095cSChristophe Leroy	mfspr	r7, SPRN_PID0
9*dfc3095cSChristophe Leroy	slwi	r7,r7,16
10*dfc3095cSChristophe Leroy	or	r7,r7,r4
11*dfc3095cSChristophe Leroy	mtspr	SPRN_MAS6,r7
12*dfc3095cSChristophe Leroy	tlbsx	0,r6				/* search MSR[IS], SPID=PID0 */
13*dfc3095cSChristophe Leroy	mfspr	r7,SPRN_MAS1
14*dfc3095cSChristophe Leroy	andis.	r7,r7,MAS1_VALID@h
15*dfc3095cSChristophe Leroy	bne	match_TLB
16*dfc3095cSChristophe Leroy
17*dfc3095cSChristophe Leroy	mfspr	r7,SPRN_MMUCFG
18*dfc3095cSChristophe Leroy	rlwinm	r7,r7,21,28,31			/* extract MMUCFG[NPIDS] */
19*dfc3095cSChristophe Leroy	cmpwi	r7,3
20*dfc3095cSChristophe Leroy	bne	match_TLB			/* skip if NPIDS != 3 */
21*dfc3095cSChristophe Leroy
22*dfc3095cSChristophe Leroy	mfspr	r7,SPRN_PID1
23*dfc3095cSChristophe Leroy	slwi	r7,r7,16
24*dfc3095cSChristophe Leroy	or	r7,r7,r4
25*dfc3095cSChristophe Leroy	mtspr	SPRN_MAS6,r7
26*dfc3095cSChristophe Leroy	tlbsx	0,r6				/* search MSR[IS], SPID=PID1 */
27*dfc3095cSChristophe Leroy	mfspr	r7,SPRN_MAS1
28*dfc3095cSChristophe Leroy	andis.	r7,r7,MAS1_VALID@h
29*dfc3095cSChristophe Leroy	bne	match_TLB
30*dfc3095cSChristophe Leroy	mfspr	r7, SPRN_PID2
31*dfc3095cSChristophe Leroy	slwi	r7,r7,16
32*dfc3095cSChristophe Leroy	or	r7,r7,r4
33*dfc3095cSChristophe Leroy	mtspr	SPRN_MAS6,r7
34*dfc3095cSChristophe Leroy	tlbsx	0,r6				/* Fall through, we had to match */
35*dfc3095cSChristophe Leroy
36*dfc3095cSChristophe Leroymatch_TLB:
37*dfc3095cSChristophe Leroy	mfspr	r7,SPRN_MAS0
38*dfc3095cSChristophe Leroy	rlwinm	r3,r7,16,20,31			/* Extract MAS0(Entry) */
39*dfc3095cSChristophe Leroy
40*dfc3095cSChristophe Leroy	mfspr	r7,SPRN_MAS1			/* Insure IPROT set */
41*dfc3095cSChristophe Leroy	oris	r7,r7,MAS1_IPROT@h
42*dfc3095cSChristophe Leroy	mtspr	SPRN_MAS1,r7
43*dfc3095cSChristophe Leroy	tlbwe
44*dfc3095cSChristophe Leroy
45*dfc3095cSChristophe Leroy/* 2. Invalidate all entries except the entry we're executing in */
46*dfc3095cSChristophe Leroy	mfspr	r9,SPRN_TLB1CFG
47*dfc3095cSChristophe Leroy	andi.	r9,r9,0xfff
48*dfc3095cSChristophe Leroy	li	r6,0				/* Set Entry counter to 0 */
49*dfc3095cSChristophe Leroy1:	lis	r7,0x1000			/* Set MAS0(TLBSEL) = 1 */
50*dfc3095cSChristophe Leroy	rlwimi	r7,r6,16,4,15			/* Setup MAS0 = TLBSEL | ESEL(r6) */
51*dfc3095cSChristophe Leroy	mtspr	SPRN_MAS0,r7
52*dfc3095cSChristophe Leroy	tlbre
53*dfc3095cSChristophe Leroy	mfspr	r7,SPRN_MAS1
54*dfc3095cSChristophe Leroy	rlwinm	r7,r7,0,2,31			/* Clear MAS1 Valid and IPROT */
55*dfc3095cSChristophe Leroy	cmpw	r3,r6
56*dfc3095cSChristophe Leroy	beq	skpinv				/* Dont update the current execution TLB */
57*dfc3095cSChristophe Leroy	mtspr	SPRN_MAS1,r7
58*dfc3095cSChristophe Leroy	tlbwe
59*dfc3095cSChristophe Leroy	isync
60*dfc3095cSChristophe Leroyskpinv:	addi	r6,r6,1				/* Increment */
61*dfc3095cSChristophe Leroy	cmpw	r6,r9				/* Are we done? */
62*dfc3095cSChristophe Leroy	bne	1b				/* If not, repeat */
63*dfc3095cSChristophe Leroy
64*dfc3095cSChristophe Leroy	/* Invalidate TLB0 */
65*dfc3095cSChristophe Leroy	li	r6,0x04
66*dfc3095cSChristophe Leroy	tlbivax 0,r6
67*dfc3095cSChristophe Leroy	TLBSYNC
68*dfc3095cSChristophe Leroy	/* Invalidate TLB1 */
69*dfc3095cSChristophe Leroy	li	r6,0x0c
70*dfc3095cSChristophe Leroy	tlbivax 0,r6
71*dfc3095cSChristophe Leroy	TLBSYNC
72*dfc3095cSChristophe Leroy
73*dfc3095cSChristophe Leroy/* 3. Setup a temp mapping and jump to it */
74*dfc3095cSChristophe Leroy	andi.	r5, r3, 0x1	/* Find an entry not used and is non-zero */
75*dfc3095cSChristophe Leroy	addi	r5, r5, 0x1
76*dfc3095cSChristophe Leroy	lis	r7,0x1000	/* Set MAS0(TLBSEL) = 1 */
77*dfc3095cSChristophe Leroy	rlwimi	r7,r3,16,4,15	/* Setup MAS0 = TLBSEL | ESEL(r3) */
78*dfc3095cSChristophe Leroy	mtspr	SPRN_MAS0,r7
79*dfc3095cSChristophe Leroy	tlbre
80*dfc3095cSChristophe Leroy
81*dfc3095cSChristophe Leroy	/* grab and fixup the RPN */
82*dfc3095cSChristophe Leroy	mfspr	r6,SPRN_MAS1	/* extract MAS1[SIZE] */
83*dfc3095cSChristophe Leroy	rlwinm	r6,r6,25,27,31
84*dfc3095cSChristophe Leroy	li	r8,-1
85*dfc3095cSChristophe Leroy	addi	r6,r6,10
86*dfc3095cSChristophe Leroy	slw	r6,r8,r6	/* convert to mask */
87*dfc3095cSChristophe Leroy
88*dfc3095cSChristophe Leroy	bcl	20,31,$+4	/* Find our address */
89*dfc3095cSChristophe Leroy1:	mflr	r7
90*dfc3095cSChristophe Leroy
91*dfc3095cSChristophe Leroy	mfspr	r8,SPRN_MAS3
92*dfc3095cSChristophe Leroy#ifdef CONFIG_PHYS_64BIT
93*dfc3095cSChristophe Leroy	mfspr	r23,SPRN_MAS7
94*dfc3095cSChristophe Leroy#endif
95*dfc3095cSChristophe Leroy	and	r8,r6,r8
96*dfc3095cSChristophe Leroy	subfic	r9,r6,-4096
97*dfc3095cSChristophe Leroy	and	r9,r9,r7
98*dfc3095cSChristophe Leroy
99*dfc3095cSChristophe Leroy	or	r25,r8,r9
100*dfc3095cSChristophe Leroy	ori	r8,r25,(MAS3_SX|MAS3_SW|MAS3_SR)
101*dfc3095cSChristophe Leroy
102*dfc3095cSChristophe Leroy	/* Just modify the entry ID and EPN for the temp mapping */
103*dfc3095cSChristophe Leroy	lis	r7,0x1000	/* Set MAS0(TLBSEL) = 1 */
104*dfc3095cSChristophe Leroy	rlwimi	r7,r5,16,4,15	/* Setup MAS0 = TLBSEL | ESEL(r5) */
105*dfc3095cSChristophe Leroy	mtspr	SPRN_MAS0,r7
106*dfc3095cSChristophe Leroy	xori	r6,r4,1		/* Setup TMP mapping in the other Address space */
107*dfc3095cSChristophe Leroy	slwi	r6,r6,12
108*dfc3095cSChristophe Leroy	oris	r6,r6,(MAS1_VALID|MAS1_IPROT)@h
109*dfc3095cSChristophe Leroy	ori	r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_4K))@l
110*dfc3095cSChristophe Leroy	mtspr	SPRN_MAS1,r6
111*dfc3095cSChristophe Leroy	mfspr	r6,SPRN_MAS2
112*dfc3095cSChristophe Leroy	li	r7,0		/* temp EPN = 0 */
113*dfc3095cSChristophe Leroy	rlwimi	r7,r6,0,20,31
114*dfc3095cSChristophe Leroy	mtspr	SPRN_MAS2,r7
115*dfc3095cSChristophe Leroy	mtspr	SPRN_MAS3,r8
116*dfc3095cSChristophe Leroy	tlbwe
117*dfc3095cSChristophe Leroy
118*dfc3095cSChristophe Leroy	xori	r6,r4,1
119*dfc3095cSChristophe Leroy	slwi	r6,r6,5		/* setup new context with other address space */
120*dfc3095cSChristophe Leroy	bcl	20,31,$+4	/* Find our address */
121*dfc3095cSChristophe Leroy1:	mflr	r9
122*dfc3095cSChristophe Leroy	rlwimi	r7,r9,0,20,31
123*dfc3095cSChristophe Leroy	addi	r7,r7,(2f - 1b)
124*dfc3095cSChristophe Leroy	mtspr	SPRN_SRR0,r7
125*dfc3095cSChristophe Leroy	mtspr	SPRN_SRR1,r6
126*dfc3095cSChristophe Leroy	rfi
127*dfc3095cSChristophe Leroy2:
128*dfc3095cSChristophe Leroy/* 4. Clear out PIDs & Search info */
129*dfc3095cSChristophe Leroy	li	r6,0
130*dfc3095cSChristophe Leroy	mtspr   SPRN_MAS6,r6
131*dfc3095cSChristophe Leroy	mtspr	SPRN_PID0,r6
132*dfc3095cSChristophe Leroy
133*dfc3095cSChristophe Leroy	mfspr	r7,SPRN_MMUCFG
134*dfc3095cSChristophe Leroy	rlwinm	r7,r7,21,28,31			/* extract MMUCFG[NPIDS] */
135*dfc3095cSChristophe Leroy	cmpwi	r7,3
136*dfc3095cSChristophe Leroy	bne	2f				/* skip if NPIDS != 3 */
137*dfc3095cSChristophe Leroy
138*dfc3095cSChristophe Leroy	mtspr	SPRN_PID1,r6
139*dfc3095cSChristophe Leroy	mtspr	SPRN_PID2,r6
140*dfc3095cSChristophe Leroy
141*dfc3095cSChristophe Leroy/* 5. Invalidate mapping we started in */
142*dfc3095cSChristophe Leroy2:
143*dfc3095cSChristophe Leroy	lis	r7,0x1000	/* Set MAS0(TLBSEL) = 1 */
144*dfc3095cSChristophe Leroy	rlwimi	r7,r3,16,4,15	/* Setup MAS0 = TLBSEL | ESEL(r3) */
145*dfc3095cSChristophe Leroy	mtspr	SPRN_MAS0,r7
146*dfc3095cSChristophe Leroy	tlbre
147*dfc3095cSChristophe Leroy	mfspr	r6,SPRN_MAS1
148*dfc3095cSChristophe Leroy	rlwinm	r6,r6,0,2,0	/* clear IPROT */
149*dfc3095cSChristophe Leroy	mtspr	SPRN_MAS1,r6
150*dfc3095cSChristophe Leroy	tlbwe
151*dfc3095cSChristophe Leroy	/* Invalidate TLB1 */
152*dfc3095cSChristophe Leroy	li	r9,0x0c
153*dfc3095cSChristophe Leroy	tlbivax 0,r9
154*dfc3095cSChristophe Leroy	TLBSYNC
155*dfc3095cSChristophe Leroy
156*dfc3095cSChristophe Leroy#if defined(ENTRY_MAPPING_BOOT_SETUP)
157*dfc3095cSChristophe Leroy
158*dfc3095cSChristophe Leroy/* 6. Setup kernstart_virt_addr mapping in TLB1[0] */
159*dfc3095cSChristophe Leroy	lis	r6,0x1000		/* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */
160*dfc3095cSChristophe Leroy	mtspr	SPRN_MAS0,r6
161*dfc3095cSChristophe Leroy	lis	r6,(MAS1_VALID|MAS1_IPROT)@h
162*dfc3095cSChristophe Leroy	ori	r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_64M))@l
163*dfc3095cSChristophe Leroy	mtspr	SPRN_MAS1,r6
164*dfc3095cSChristophe Leroy	lis	r6,MAS2_EPN_MASK(BOOK3E_PAGESZ_64M)@h
165*dfc3095cSChristophe Leroy	ori	r6,r6,MAS2_EPN_MASK(BOOK3E_PAGESZ_64M)@l
166*dfc3095cSChristophe Leroy	and	r6,r6,r20
167*dfc3095cSChristophe Leroy	ori	r6,r6,MAS2_M_IF_NEEDED@l
168*dfc3095cSChristophe Leroy	mtspr	SPRN_MAS2,r6
169*dfc3095cSChristophe Leroy	mtspr	SPRN_MAS3,r8
170*dfc3095cSChristophe Leroy	tlbwe
171*dfc3095cSChristophe Leroy
172*dfc3095cSChristophe Leroy/* 7. Jump to kernstart_virt_addr mapping */
173*dfc3095cSChristophe Leroy	mr	r6,r20
174*dfc3095cSChristophe Leroy
175*dfc3095cSChristophe Leroy#elif defined(ENTRY_MAPPING_KEXEC_SETUP)
176*dfc3095cSChristophe Leroy/*
177*dfc3095cSChristophe Leroy * 6. Setup a 1:1 mapping in TLB1. Esel 0 is unsued, 1 or 2 contains the tmp
178*dfc3095cSChristophe Leroy * mapping so we start at 3. We setup 8 mappings, each 256MiB in size. This
179*dfc3095cSChristophe Leroy * will cover the first 2GiB of memory.
180*dfc3095cSChristophe Leroy */
181*dfc3095cSChristophe Leroy
182*dfc3095cSChristophe Leroy	lis r10, (MAS1_VALID|MAS1_IPROT)@h
183*dfc3095cSChristophe Leroy	ori r10,r10, (MAS1_TSIZE(BOOK3E_PAGESZ_256M))@l
184*dfc3095cSChristophe Leroy	li  r11, 0
185*dfc3095cSChristophe Leroy	li  r0, 8
186*dfc3095cSChristophe Leroy	mtctr   r0
187*dfc3095cSChristophe Leroy
188*dfc3095cSChristophe Leroynext_tlb_setup:
189*dfc3095cSChristophe Leroy	addi	r0, r11, 3
190*dfc3095cSChristophe Leroy	rlwinm  r0, r0, 16, 4, 15  // Compute esel
191*dfc3095cSChristophe Leroy	rlwinm  r9, r11, 28, 0, 3   // Compute [ER]PN
192*dfc3095cSChristophe Leroy	oris    r0, r0, (MAS0_TLBSEL(1))@h
193*dfc3095cSChristophe Leroy	mtspr   SPRN_MAS0,r0
194*dfc3095cSChristophe Leroy	mtspr   SPRN_MAS1,r10
195*dfc3095cSChristophe Leroy	mtspr   SPRN_MAS2,r9
196*dfc3095cSChristophe Leroy	ori r9, r9, (MAS3_SX|MAS3_SW|MAS3_SR)
197*dfc3095cSChristophe Leroy	mtspr   SPRN_MAS3,r9
198*dfc3095cSChristophe Leroy	tlbwe
199*dfc3095cSChristophe Leroy	addi    r11, r11, 1
200*dfc3095cSChristophe Leroy	bdnz+   next_tlb_setup
201*dfc3095cSChristophe Leroy
202*dfc3095cSChristophe Leroy/* 7. Jump to our 1:1 mapping */
203*dfc3095cSChristophe Leroy	mr	r6, r25
204*dfc3095cSChristophe Leroy#else
205*dfc3095cSChristophe Leroy	#error You need to specify the mapping or not use this at all.
206*dfc3095cSChristophe Leroy#endif
207*dfc3095cSChristophe Leroy
208*dfc3095cSChristophe Leroy	lis	r7,MSR_KERNEL@h
209*dfc3095cSChristophe Leroy	ori	r7,r7,MSR_KERNEL@l
210*dfc3095cSChristophe Leroy	bcl	20,31,$+4		/* Find our address */
211*dfc3095cSChristophe Leroy1:	mflr	r9
212*dfc3095cSChristophe Leroy	rlwimi	r6,r9,0,20,31
213*dfc3095cSChristophe Leroy	addi	r6,r6,(2f - 1b)
214*dfc3095cSChristophe Leroy	mtspr	SPRN_SRR0,r6
215*dfc3095cSChristophe Leroy	mtspr	SPRN_SRR1,r7
216*dfc3095cSChristophe Leroy	rfi				/* start execution out of TLB1[0] entry */
217*dfc3095cSChristophe Leroy
218*dfc3095cSChristophe Leroy/* 8. Clear out the temp mapping */
219*dfc3095cSChristophe Leroy2:	lis	r7,0x1000	/* Set MAS0(TLBSEL) = 1 */
220*dfc3095cSChristophe Leroy	rlwimi	r7,r5,16,4,15	/* Setup MAS0 = TLBSEL | ESEL(r5) */
221*dfc3095cSChristophe Leroy	mtspr	SPRN_MAS0,r7
222*dfc3095cSChristophe Leroy	tlbre
223*dfc3095cSChristophe Leroy	mfspr	r8,SPRN_MAS1
224*dfc3095cSChristophe Leroy	rlwinm	r8,r8,0,2,0	/* clear IPROT */
225*dfc3095cSChristophe Leroy	mtspr	SPRN_MAS1,r8
226*dfc3095cSChristophe Leroy	tlbwe
227*dfc3095cSChristophe Leroy	/* Invalidate TLB1 */
228*dfc3095cSChristophe Leroy	li	r9,0x0c
229*dfc3095cSChristophe Leroy	tlbivax 0,r9
230*dfc3095cSChristophe Leroy	TLBSYNC
231