linux/arch/powerpc/kernel/fsl_booke_entry_mapping.S
<<
>>
Prefs
   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