Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 
0003 /* 1. Find the index of the entry we're executing in */
0004     bcl 20,31,$+4               /* Find our address */
0005 invstr: mflr    r6              /* Make it accessible */
0006     mfmsr   r7
0007     rlwinm  r4,r7,27,31,31          /* extract MSR[IS] */
0008     mfspr   r7, SPRN_PID0
0009     slwi    r7,r7,16
0010     or  r7,r7,r4
0011     mtspr   SPRN_MAS6,r7
0012     tlbsx   0,r6                /* search MSR[IS], SPID=PID0 */
0013     mfspr   r7,SPRN_MAS1
0014     andis.  r7,r7,MAS1_VALID@h
0015     bne match_TLB
0016 
0017     mfspr   r7,SPRN_MMUCFG
0018     rlwinm  r7,r7,21,28,31          /* extract MMUCFG[NPIDS] */
0019     cmpwi   r7,3
0020     bne match_TLB           /* skip if NPIDS != 3 */
0021 
0022     mfspr   r7,SPRN_PID1
0023     slwi    r7,r7,16
0024     or  r7,r7,r4
0025     mtspr   SPRN_MAS6,r7
0026     tlbsx   0,r6                /* search MSR[IS], SPID=PID1 */
0027     mfspr   r7,SPRN_MAS1
0028     andis.  r7,r7,MAS1_VALID@h
0029     bne match_TLB
0030     mfspr   r7, SPRN_PID2
0031     slwi    r7,r7,16
0032     or  r7,r7,r4
0033     mtspr   SPRN_MAS6,r7
0034     tlbsx   0,r6                /* Fall through, we had to match */
0035 
0036 match_TLB:
0037     mfspr   r7,SPRN_MAS0
0038     rlwinm  r3,r7,16,20,31          /* Extract MAS0(Entry) */
0039 
0040     mfspr   r7,SPRN_MAS1            /* Insure IPROT set */
0041     oris    r7,r7,MAS1_IPROT@h
0042     mtspr   SPRN_MAS1,r7
0043     tlbwe
0044 
0045 /* 2. Invalidate all entries except the entry we're executing in */
0046     mfspr   r9,SPRN_TLB1CFG
0047     andi.   r9,r9,0xfff
0048     li  r6,0                /* Set Entry counter to 0 */
0049 1:  lis r7,0x1000           /* Set MAS0(TLBSEL) = 1 */
0050     rlwimi  r7,r6,16,4,15           /* Setup MAS0 = TLBSEL | ESEL(r6) */
0051     mtspr   SPRN_MAS0,r7
0052     tlbre
0053     mfspr   r7,SPRN_MAS1
0054     rlwinm  r7,r7,0,2,31            /* Clear MAS1 Valid and IPROT */
0055     cmpw    r3,r6
0056     beq skpinv              /* Dont update the current execution TLB */
0057     mtspr   SPRN_MAS1,r7
0058     tlbwe
0059     isync
0060 skpinv: addi    r6,r6,1             /* Increment */
0061     cmpw    r6,r9               /* Are we done? */
0062     bne 1b              /* If not, repeat */
0063 
0064     /* Invalidate TLB0 */
0065     li  r6,0x04
0066     tlbivax 0,r6
0067     TLBSYNC
0068     /* Invalidate TLB1 */
0069     li  r6,0x0c
0070     tlbivax 0,r6
0071     TLBSYNC
0072 
0073 /* 3. Setup a temp mapping and jump to it */
0074     andi.   r5, r3, 0x1 /* Find an entry not used and is non-zero */
0075     addi    r5, r5, 0x1
0076     lis r7,0x1000   /* Set MAS0(TLBSEL) = 1 */
0077     rlwimi  r7,r3,16,4,15   /* Setup MAS0 = TLBSEL | ESEL(r3) */
0078     mtspr   SPRN_MAS0,r7
0079     tlbre
0080 
0081     /* grab and fixup the RPN */
0082     mfspr   r6,SPRN_MAS1    /* extract MAS1[SIZE] */
0083     rlwinm  r6,r6,25,27,31
0084     li  r8,-1
0085     addi    r6,r6,10
0086     slw r6,r8,r6    /* convert to mask */
0087 
0088     bcl 20,31,$+4   /* Find our address */
0089 1:  mflr    r7
0090 
0091     mfspr   r8,SPRN_MAS3
0092 #ifdef CONFIG_PHYS_64BIT
0093     mfspr   r23,SPRN_MAS7
0094 #endif
0095     and r8,r6,r8
0096     subfic  r9,r6,-4096
0097     and r9,r9,r7
0098 
0099     or  r25,r8,r9
0100     ori r8,r25,(MAS3_SX|MAS3_SW|MAS3_SR)
0101 
0102     /* Just modify the entry ID and EPN for the temp mapping */
0103     lis r7,0x1000   /* Set MAS0(TLBSEL) = 1 */
0104     rlwimi  r7,r5,16,4,15   /* Setup MAS0 = TLBSEL | ESEL(r5) */
0105     mtspr   SPRN_MAS0,r7
0106     xori    r6,r4,1     /* Setup TMP mapping in the other Address space */
0107     slwi    r6,r6,12
0108     oris    r6,r6,(MAS1_VALID|MAS1_IPROT)@h
0109     ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_4K))@l
0110     mtspr   SPRN_MAS1,r6
0111     mfspr   r6,SPRN_MAS2
0112     li  r7,0        /* temp EPN = 0 */
0113     rlwimi  r7,r6,0,20,31
0114     mtspr   SPRN_MAS2,r7
0115     mtspr   SPRN_MAS3,r8
0116     tlbwe
0117 
0118     xori    r6,r4,1
0119     slwi    r6,r6,5     /* setup new context with other address space */
0120     bcl 20,31,$+4   /* Find our address */
0121 1:  mflr    r9
0122     rlwimi  r7,r9,0,20,31
0123     addi    r7,r7,(2f - 1b)
0124     mtspr   SPRN_SRR0,r7
0125     mtspr   SPRN_SRR1,r6
0126     rfi
0127 2:
0128 /* 4. Clear out PIDs & Search info */
0129     li  r6,0
0130     mtspr   SPRN_MAS6,r6
0131     mtspr   SPRN_PID0,r6
0132 
0133     mfspr   r7,SPRN_MMUCFG
0134     rlwinm  r7,r7,21,28,31          /* extract MMUCFG[NPIDS] */
0135     cmpwi   r7,3
0136     bne 2f              /* skip if NPIDS != 3 */
0137 
0138     mtspr   SPRN_PID1,r6
0139     mtspr   SPRN_PID2,r6
0140 
0141 /* 5. Invalidate mapping we started in */
0142 2:
0143     lis r7,0x1000   /* Set MAS0(TLBSEL) = 1 */
0144     rlwimi  r7,r3,16,4,15   /* Setup MAS0 = TLBSEL | ESEL(r3) */
0145     mtspr   SPRN_MAS0,r7
0146     tlbre
0147     mfspr   r6,SPRN_MAS1
0148     rlwinm  r6,r6,0,2,0 /* clear IPROT */
0149     mtspr   SPRN_MAS1,r6
0150     tlbwe
0151     /* Invalidate TLB1 */
0152     li  r9,0x0c
0153     tlbivax 0,r9
0154     TLBSYNC
0155 
0156 #if defined(ENTRY_MAPPING_BOOT_SETUP)
0157 
0158 /* 6. Setup kernstart_virt_addr mapping in TLB1[0] */
0159     lis r6,0x1000       /* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */
0160     mtspr   SPRN_MAS0,r6
0161     lis r6,(MAS1_VALID|MAS1_IPROT)@h
0162     ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_64M))@l
0163     mtspr   SPRN_MAS1,r6
0164     lis r6,MAS2_EPN_MASK(BOOK3E_PAGESZ_64M)@h
0165     ori r6,r6,MAS2_EPN_MASK(BOOK3E_PAGESZ_64M)@l
0166     and r6,r6,r20
0167     ori r6,r6,MAS2_M_IF_NEEDED@l
0168     mtspr   SPRN_MAS2,r6
0169     mtspr   SPRN_MAS3,r8
0170     tlbwe
0171 
0172 /* 7. Jump to kernstart_virt_addr mapping */
0173     mr  r6,r20
0174 
0175 #elif defined(ENTRY_MAPPING_KEXEC_SETUP)
0176 /*
0177  * 6. Setup a 1:1 mapping in TLB1. Esel 0 is unsued, 1 or 2 contains the tmp
0178  * mapping so we start at 3. We setup 8 mappings, each 256MiB in size. This
0179  * will cover the first 2GiB of memory.
0180  */
0181 
0182     lis r10, (MAS1_VALID|MAS1_IPROT)@h
0183     ori r10,r10, (MAS1_TSIZE(BOOK3E_PAGESZ_256M))@l
0184     li  r11, 0
0185     li  r0, 8
0186     mtctr   r0
0187 
0188 next_tlb_setup:
0189     addi    r0, r11, 3
0190     rlwinm  r0, r0, 16, 4, 15  // Compute esel
0191     rlwinm  r9, r11, 28, 0, 3   // Compute [ER]PN
0192     oris    r0, r0, (MAS0_TLBSEL(1))@h
0193     mtspr   SPRN_MAS0,r0
0194     mtspr   SPRN_MAS1,r10
0195     mtspr   SPRN_MAS2,r9
0196     ori r9, r9, (MAS3_SX|MAS3_SW|MAS3_SR)
0197     mtspr   SPRN_MAS3,r9
0198     tlbwe
0199     addi    r11, r11, 1
0200     bdnz+   next_tlb_setup
0201 
0202 /* 7. Jump to our 1:1 mapping */
0203     mr  r6, r25
0204 #else
0205     #error You need to specify the mapping or not use this at all.
0206 #endif
0207 
0208     lis r7,MSR_KERNEL@h
0209     ori r7,r7,MSR_KERNEL@l
0210     bcl 20,31,$+4       /* Find our address */
0211 1:  mflr    r9
0212     rlwimi  r6,r9,0,20,31
0213     addi    r6,r6,(2f - 1b)
0214     mtspr   SPRN_SRR0,r6
0215     mtspr   SPRN_SRR1,r7
0216     rfi             /* start execution out of TLB1[0] entry */
0217 
0218 /* 8. Clear out the temp mapping */
0219 2:  lis r7,0x1000   /* Set MAS0(TLBSEL) = 1 */
0220     rlwimi  r7,r5,16,4,15   /* Setup MAS0 = TLBSEL | ESEL(r5) */
0221     mtspr   SPRN_MAS0,r7
0222     tlbre
0223     mfspr   r8,SPRN_MAS1
0224     rlwinm  r8,r8,0,2,0 /* clear IPROT */
0225     mtspr   SPRN_MAS1,r8
0226     tlbwe
0227     /* Invalidate TLB1 */
0228     li  r9,0x0c
0229     tlbivax 0,r9
0230     TLBSYNC