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