fsl_booke_entry_mapping.S 5.6 KB

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