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