1/* SPDX-License-Identifier: GPL-2.0 */ 2 3/* 1. Find the index of the entry we're executing in */ 4 bl invstr /* Find our address */ 5invstr: 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 36match_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 */ 491: 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 60skpinv: 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 */ 891: 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 */ 1211: 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 1272: 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 */ 1422: 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 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 162#else 163#define M_IF_NEEDED 0 164#endif 165 166#if defined(ENTRY_MAPPING_BOOT_SETUP) 167 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 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 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 183 rlwinm r7,r25,0,0x03ffffff 184 add r6,r7,r6 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 199next_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 */ 214 mr r6, r25 215#else 216 #error You need to specify the mapping or not use this at all. 217#endif 218 219 lis r7,MSR_KERNEL@h 220 ori r7,r7,MSR_KERNEL@l 221 bl 1f /* Find our address */ 2221: mflr r9 223 rlwimi r6,r9,0,20,31 224 addi r6,r6,(2f - 1b) 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 */ 2302: 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 242