swsusp_32.S 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #include <linux/threads.h>
  3. #include <linux/linkage.h>
  4. #include <asm/processor.h>
  5. #include <asm/page.h>
  6. #include <asm/cputable.h>
  7. #include <asm/thread_info.h>
  8. #include <asm/ppc_asm.h>
  9. #include <asm/asm-offsets.h>
  10. #include <asm/mmu.h>
  11. #include <asm/feature-fixups.h>
  12. /*
  13. * Structure for storing CPU registers on the save area.
  14. */
  15. #define SL_SP 0
  16. #define SL_PC 4
  17. #define SL_MSR 8
  18. #define SL_SDR1 0xc
  19. #define SL_SPRG0 0x10 /* 4 sprg's */
  20. #define SL_DBAT0 0x20
  21. #define SL_IBAT0 0x28
  22. #define SL_DBAT1 0x30
  23. #define SL_IBAT1 0x38
  24. #define SL_DBAT2 0x40
  25. #define SL_IBAT2 0x48
  26. #define SL_DBAT3 0x50
  27. #define SL_IBAT3 0x58
  28. #define SL_DBAT4 0x60
  29. #define SL_IBAT4 0x68
  30. #define SL_DBAT5 0x70
  31. #define SL_IBAT5 0x78
  32. #define SL_DBAT6 0x80
  33. #define SL_IBAT6 0x88
  34. #define SL_DBAT7 0x90
  35. #define SL_IBAT7 0x98
  36. #define SL_TB 0xa0
  37. #define SL_R2 0xa8
  38. #define SL_CR 0xac
  39. #define SL_LR 0xb0
  40. #define SL_R12 0xb4 /* r12 to r31 */
  41. #define SL_SIZE (SL_R12 + 80)
  42. .section .data
  43. .align 5
  44. _GLOBAL(swsusp_save_area)
  45. .space SL_SIZE
  46. .section .text
  47. .align 5
  48. _GLOBAL(swsusp_arch_suspend)
  49. lis r11,swsusp_save_area@h
  50. ori r11,r11,swsusp_save_area@l
  51. mflr r0
  52. stw r0,SL_LR(r11)
  53. mfcr r0
  54. stw r0,SL_CR(r11)
  55. stw r1,SL_SP(r11)
  56. stw r2,SL_R2(r11)
  57. stmw r12,SL_R12(r11)
  58. /* Save MSR & SDR1 */
  59. mfmsr r4
  60. stw r4,SL_MSR(r11)
  61. mfsdr1 r4
  62. stw r4,SL_SDR1(r11)
  63. /* Get a stable timebase and save it */
  64. 1: mftbu r4
  65. stw r4,SL_TB(r11)
  66. mftb r5
  67. stw r5,SL_TB+4(r11)
  68. mftbu r3
  69. cmpw r3,r4
  70. bne 1b
  71. /* Save SPRGs */
  72. mfsprg r4,0
  73. stw r4,SL_SPRG0(r11)
  74. mfsprg r4,1
  75. stw r4,SL_SPRG0+4(r11)
  76. mfsprg r4,2
  77. stw r4,SL_SPRG0+8(r11)
  78. mfsprg r4,3
  79. stw r4,SL_SPRG0+12(r11)
  80. /* Save BATs */
  81. mfdbatu r4,0
  82. stw r4,SL_DBAT0(r11)
  83. mfdbatl r4,0
  84. stw r4,SL_DBAT0+4(r11)
  85. mfdbatu r4,1
  86. stw r4,SL_DBAT1(r11)
  87. mfdbatl r4,1
  88. stw r4,SL_DBAT1+4(r11)
  89. mfdbatu r4,2
  90. stw r4,SL_DBAT2(r11)
  91. mfdbatl r4,2
  92. stw r4,SL_DBAT2+4(r11)
  93. mfdbatu r4,3
  94. stw r4,SL_DBAT3(r11)
  95. mfdbatl r4,3
  96. stw r4,SL_DBAT3+4(r11)
  97. mfibatu r4,0
  98. stw r4,SL_IBAT0(r11)
  99. mfibatl r4,0
  100. stw r4,SL_IBAT0+4(r11)
  101. mfibatu r4,1
  102. stw r4,SL_IBAT1(r11)
  103. mfibatl r4,1
  104. stw r4,SL_IBAT1+4(r11)
  105. mfibatu r4,2
  106. stw r4,SL_IBAT2(r11)
  107. mfibatl r4,2
  108. stw r4,SL_IBAT2+4(r11)
  109. mfibatu r4,3
  110. stw r4,SL_IBAT3(r11)
  111. mfibatl r4,3
  112. stw r4,SL_IBAT3+4(r11)
  113. BEGIN_MMU_FTR_SECTION
  114. mfspr r4,SPRN_DBAT4U
  115. stw r4,SL_DBAT4(r11)
  116. mfspr r4,SPRN_DBAT4L
  117. stw r4,SL_DBAT4+4(r11)
  118. mfspr r4,SPRN_DBAT5U
  119. stw r4,SL_DBAT5(r11)
  120. mfspr r4,SPRN_DBAT5L
  121. stw r4,SL_DBAT5+4(r11)
  122. mfspr r4,SPRN_DBAT6U
  123. stw r4,SL_DBAT6(r11)
  124. mfspr r4,SPRN_DBAT6L
  125. stw r4,SL_DBAT6+4(r11)
  126. mfspr r4,SPRN_DBAT7U
  127. stw r4,SL_DBAT7(r11)
  128. mfspr r4,SPRN_DBAT7L
  129. stw r4,SL_DBAT7+4(r11)
  130. mfspr r4,SPRN_IBAT4U
  131. stw r4,SL_IBAT4(r11)
  132. mfspr r4,SPRN_IBAT4L
  133. stw r4,SL_IBAT4+4(r11)
  134. mfspr r4,SPRN_IBAT5U
  135. stw r4,SL_IBAT5(r11)
  136. mfspr r4,SPRN_IBAT5L
  137. stw r4,SL_IBAT5+4(r11)
  138. mfspr r4,SPRN_IBAT6U
  139. stw r4,SL_IBAT6(r11)
  140. mfspr r4,SPRN_IBAT6L
  141. stw r4,SL_IBAT6+4(r11)
  142. mfspr r4,SPRN_IBAT7U
  143. stw r4,SL_IBAT7(r11)
  144. mfspr r4,SPRN_IBAT7L
  145. stw r4,SL_IBAT7+4(r11)
  146. END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
  147. #if 0
  148. /* Backup various CPU config stuffs */
  149. bl __save_cpu_setup
  150. #endif
  151. /* Call the low level suspend stuff (we should probably have made
  152. * a stackframe...
  153. */
  154. bl swsusp_save
  155. /* Restore LR from the save area */
  156. lis r11,swsusp_save_area@h
  157. ori r11,r11,swsusp_save_area@l
  158. lwz r0,SL_LR(r11)
  159. mtlr r0
  160. blr
  161. /* Resume code */
  162. _GLOBAL(swsusp_arch_resume)
  163. #ifdef CONFIG_ALTIVEC
  164. /* Stop pending alitvec streams and memory accesses */
  165. BEGIN_FTR_SECTION
  166. PPC_DSSALL
  167. END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
  168. #endif
  169. sync
  170. /* Disable MSR:DR to make sure we don't take a TLB or
  171. * hash miss during the copy, as our hash table will
  172. * for a while be unusable. For .text, we assume we are
  173. * covered by a BAT. This works only for non-G5 at this
  174. * point. G5 will need a better approach, possibly using
  175. * a small temporary hash table filled with large mappings,
  176. * disabling the MMU completely isn't a good option for
  177. * performance reasons.
  178. * (Note that 750's may have the same performance issue as
  179. * the G5 in this case, we should investigate using moving
  180. * BATs for these CPUs)
  181. */
  182. mfmsr r0
  183. sync
  184. rlwinm r0,r0,0,28,26 /* clear MSR_DR */
  185. mtmsr r0
  186. sync
  187. isync
  188. /* Load ptr the list of pages to copy in r3 */
  189. lis r11,(restore_pblist - KERNELBASE)@h
  190. ori r11,r11,restore_pblist@l
  191. lwz r10,0(r11)
  192. /* Copy the pages. This is a very basic implementation, to
  193. * be replaced by something more cache efficient */
  194. 1:
  195. tophys(r3,r10)
  196. li r0,256
  197. mtctr r0
  198. lwz r11,pbe_address(r3) /* source */
  199. tophys(r5,r11)
  200. lwz r10,pbe_orig_address(r3) /* destination */
  201. tophys(r6,r10)
  202. 2:
  203. lwz r8,0(r5)
  204. lwz r9,4(r5)
  205. lwz r10,8(r5)
  206. lwz r11,12(r5)
  207. addi r5,r5,16
  208. stw r8,0(r6)
  209. stw r9,4(r6)
  210. stw r10,8(r6)
  211. stw r11,12(r6)
  212. addi r6,r6,16
  213. bdnz 2b
  214. lwz r10,pbe_next(r3)
  215. cmpwi 0,r10,0
  216. bne 1b
  217. /* Do a very simple cache flush/inval of the L1 to ensure
  218. * coherency of the icache
  219. */
  220. lis r3,0x0002
  221. mtctr r3
  222. li r3, 0
  223. 1:
  224. lwz r0,0(r3)
  225. addi r3,r3,0x0020
  226. bdnz 1b
  227. isync
  228. sync
  229. /* Now flush those cache lines */
  230. lis r3,0x0002
  231. mtctr r3
  232. li r3, 0
  233. 1:
  234. dcbf 0,r3
  235. addi r3,r3,0x0020
  236. bdnz 1b
  237. sync
  238. /* Ok, we are now running with the kernel data of the old
  239. * kernel fully restored. We can get to the save area
  240. * easily now. As for the rest of the code, it assumes the
  241. * loader kernel and the booted one are exactly identical
  242. */
  243. lis r11,swsusp_save_area@h
  244. ori r11,r11,swsusp_save_area@l
  245. tophys(r11,r11)
  246. #if 0
  247. /* Restore various CPU config stuffs */
  248. bl __restore_cpu_setup
  249. #endif
  250. /* Restore the BATs, and SDR1. Then we can turn on the MMU.
  251. * This is a bit hairy as we are running out of those BATs,
  252. * but first, our code is probably in the icache, and we are
  253. * writing the same value to the BAT, so that should be fine,
  254. * though a better solution will have to be found long-term
  255. */
  256. lwz r4,SL_SDR1(r11)
  257. mtsdr1 r4
  258. lwz r4,SL_SPRG0(r11)
  259. mtsprg 0,r4
  260. lwz r4,SL_SPRG0+4(r11)
  261. mtsprg 1,r4
  262. lwz r4,SL_SPRG0+8(r11)
  263. mtsprg 2,r4
  264. lwz r4,SL_SPRG0+12(r11)
  265. mtsprg 3,r4
  266. #if 0
  267. lwz r4,SL_DBAT0(r11)
  268. mtdbatu 0,r4
  269. lwz r4,SL_DBAT0+4(r11)
  270. mtdbatl 0,r4
  271. lwz r4,SL_DBAT1(r11)
  272. mtdbatu 1,r4
  273. lwz r4,SL_DBAT1+4(r11)
  274. mtdbatl 1,r4
  275. lwz r4,SL_DBAT2(r11)
  276. mtdbatu 2,r4
  277. lwz r4,SL_DBAT2+4(r11)
  278. mtdbatl 2,r4
  279. lwz r4,SL_DBAT3(r11)
  280. mtdbatu 3,r4
  281. lwz r4,SL_DBAT3+4(r11)
  282. mtdbatl 3,r4
  283. lwz r4,SL_IBAT0(r11)
  284. mtibatu 0,r4
  285. lwz r4,SL_IBAT0+4(r11)
  286. mtibatl 0,r4
  287. lwz r4,SL_IBAT1(r11)
  288. mtibatu 1,r4
  289. lwz r4,SL_IBAT1+4(r11)
  290. mtibatl 1,r4
  291. lwz r4,SL_IBAT2(r11)
  292. mtibatu 2,r4
  293. lwz r4,SL_IBAT2+4(r11)
  294. mtibatl 2,r4
  295. lwz r4,SL_IBAT3(r11)
  296. mtibatu 3,r4
  297. lwz r4,SL_IBAT3+4(r11)
  298. mtibatl 3,r4
  299. BEGIN_MMU_FTR_SECTION
  300. lwz r4,SL_DBAT4(r11)
  301. mtspr SPRN_DBAT4U,r4
  302. lwz r4,SL_DBAT4+4(r11)
  303. mtspr SPRN_DBAT4L,r4
  304. lwz r4,SL_DBAT5(r11)
  305. mtspr SPRN_DBAT5U,r4
  306. lwz r4,SL_DBAT5+4(r11)
  307. mtspr SPRN_DBAT5L,r4
  308. lwz r4,SL_DBAT6(r11)
  309. mtspr SPRN_DBAT6U,r4
  310. lwz r4,SL_DBAT6+4(r11)
  311. mtspr SPRN_DBAT6L,r4
  312. lwz r4,SL_DBAT7(r11)
  313. mtspr SPRN_DBAT7U,r4
  314. lwz r4,SL_DBAT7+4(r11)
  315. mtspr SPRN_DBAT7L,r4
  316. lwz r4,SL_IBAT4(r11)
  317. mtspr SPRN_IBAT4U,r4
  318. lwz r4,SL_IBAT4+4(r11)
  319. mtspr SPRN_IBAT4L,r4
  320. lwz r4,SL_IBAT5(r11)
  321. mtspr SPRN_IBAT5U,r4
  322. lwz r4,SL_IBAT5+4(r11)
  323. mtspr SPRN_IBAT5L,r4
  324. lwz r4,SL_IBAT6(r11)
  325. mtspr SPRN_IBAT6U,r4
  326. lwz r4,SL_IBAT6+4(r11)
  327. mtspr SPRN_IBAT6L,r4
  328. lwz r4,SL_IBAT7(r11)
  329. mtspr SPRN_IBAT7U,r4
  330. lwz r4,SL_IBAT7+4(r11)
  331. mtspr SPRN_IBAT7L,r4
  332. END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
  333. #endif
  334. /* Flush all TLBs */
  335. lis r4,0x1000
  336. 1: addic. r4,r4,-0x1000
  337. tlbie r4
  338. bgt 1b
  339. sync
  340. /* restore the MSR and turn on the MMU */
  341. lwz r3,SL_MSR(r11)
  342. bl turn_on_mmu
  343. tovirt(r11,r11)
  344. /* Restore TB */
  345. li r3,0
  346. mttbl r3
  347. lwz r3,SL_TB(r11)
  348. lwz r4,SL_TB+4(r11)
  349. mttbu r3
  350. mttbl r4
  351. /* Kick decrementer */
  352. li r0,1
  353. mtdec r0
  354. /* Restore the callee-saved registers and return */
  355. lwz r0,SL_CR(r11)
  356. mtcr r0
  357. lwz r2,SL_R2(r11)
  358. lmw r12,SL_R12(r11)
  359. lwz r1,SL_SP(r11)
  360. lwz r0,SL_LR(r11)
  361. mtlr r0
  362. // XXX Note: we don't really need to call swsusp_resume
  363. li r3,0
  364. blr
  365. _ASM_NOKPROBE_SYMBOL(swsusp_arch_resume)
  366. /* FIXME:This construct is actually not useful since we don't shut
  367. * down the instruction MMU, we could just flip back MSR-DR on.
  368. */
  369. SYM_FUNC_START_LOCAL(turn_on_mmu)
  370. mflr r4
  371. mtsrr0 r4
  372. mtsrr1 r3
  373. sync
  374. isync
  375. rfi
  376. _ASM_NOKPROBE_SYMBOL(turn_on_mmu)
  377. SYM_FUNC_END(turn_on_mmu)