relocate_32.S 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. /* SPDX-License-Identifier: GPL-2.0-or-later */
  2. /*
  3. * This file contains kexec low-level functions.
  4. *
  5. * Copyright (C) 2002-2003 Eric Biederman <[email protected]>
  6. * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
  7. * PPC44x port. Copyright (C) 2011, IBM Corporation
  8. * Author: Suzuki Poulose <[email protected]>
  9. */
  10. #include <asm/reg.h>
  11. #include <asm/page.h>
  12. #include <asm/mmu.h>
  13. #include <asm/ppc_asm.h>
  14. #include <asm/kexec.h>
  15. .text
  16. /*
  17. * Must be relocatable PIC code callable as a C function.
  18. */
  19. .globl relocate_new_kernel
  20. relocate_new_kernel:
  21. /* r3 = page_list */
  22. /* r4 = reboot_code_buffer */
  23. /* r5 = start_address */
  24. #ifdef CONFIG_PPC_85xx
  25. mr r29, r3
  26. mr r30, r4
  27. mr r31, r5
  28. #define ENTRY_MAPPING_KEXEC_SETUP
  29. #include <kernel/85xx_entry_mapping.S>
  30. #undef ENTRY_MAPPING_KEXEC_SETUP
  31. mr r3, r29
  32. mr r4, r30
  33. mr r5, r31
  34. li r0, 0
  35. #elif defined(CONFIG_44x)
  36. /* Save our parameters */
  37. mr r29, r3
  38. mr r30, r4
  39. mr r31, r5
  40. #ifdef CONFIG_PPC_47x
  41. /* Check for 47x cores */
  42. mfspr r3,SPRN_PVR
  43. srwi r3,r3,16
  44. cmplwi cr0,r3,PVR_476FPE@h
  45. beq setup_map_47x
  46. cmplwi cr0,r3,PVR_476@h
  47. beq setup_map_47x
  48. cmplwi cr0,r3,PVR_476_ISS@h
  49. beq setup_map_47x
  50. #endif /* CONFIG_PPC_47x */
  51. /*
  52. * Code for setting up 1:1 mapping for PPC440x for KEXEC
  53. *
  54. * We cannot switch off the MMU on PPC44x.
  55. * So we:
  56. * 1) Invalidate all the mappings except the one we are running from.
  57. * 2) Create a tmp mapping for our code in the other address space(TS) and
  58. * jump to it. Invalidate the entry we started in.
  59. * 3) Create a 1:1 mapping for 0-2GiB in chunks of 256M in original TS.
  60. * 4) Jump to the 1:1 mapping in original TS.
  61. * 5) Invalidate the tmp mapping.
  62. *
  63. * - Based on the kexec support code for FSL BookE
  64. *
  65. */
  66. /*
  67. * Load the PID with kernel PID (0).
  68. * Also load our MSR_IS and TID to MMUCR for TLB search.
  69. */
  70. li r3, 0
  71. mtspr SPRN_PID, r3
  72. mfmsr r4
  73. andi. r4,r4,MSR_IS@l
  74. beq wmmucr
  75. oris r3,r3,PPC44x_MMUCR_STS@h
  76. wmmucr:
  77. mtspr SPRN_MMUCR,r3
  78. sync
  79. /*
  80. * Invalidate all the TLB entries except the current entry
  81. * where we are running from
  82. */
  83. bcl 20,31,$+4 /* Find our address */
  84. 0: mflr r5 /* Make it accessible */
  85. tlbsx r23,0,r5 /* Find entry we are in */
  86. li r4,0 /* Start at TLB entry 0 */
  87. li r3,0 /* Set PAGEID inval value */
  88. 1: cmpw r23,r4 /* Is this our entry? */
  89. beq skip /* If so, skip the inval */
  90. tlbwe r3,r4,PPC44x_TLB_PAGEID /* If not, inval the entry */
  91. skip:
  92. addi r4,r4,1 /* Increment */
  93. cmpwi r4,64 /* Are we done? */
  94. bne 1b /* If not, repeat */
  95. isync
  96. /* Create a temp mapping and jump to it */
  97. andi. r6, r23, 1 /* Find the index to use */
  98. addi r24, r6, 1 /* r24 will contain 1 or 2 */
  99. mfmsr r9 /* get the MSR */
  100. rlwinm r5, r9, 27, 31, 31 /* Extract the MSR[IS] */
  101. xori r7, r5, 1 /* Use the other address space */
  102. /* Read the current mapping entries */
  103. tlbre r3, r23, PPC44x_TLB_PAGEID
  104. tlbre r4, r23, PPC44x_TLB_XLAT
  105. tlbre r5, r23, PPC44x_TLB_ATTRIB
  106. /* Save our current XLAT entry */
  107. mr r25, r4
  108. /* Extract the TLB PageSize */
  109. li r10, 1 /* r10 will hold PageSize */
  110. rlwinm r11, r3, 0, 24, 27 /* bits 24-27 */
  111. /* XXX: As of now we use 256M, 4K pages */
  112. cmpwi r11, PPC44x_TLB_256M
  113. bne tlb_4k
  114. rotlwi r10, r10, 28 /* r10 = 256M */
  115. b write_out
  116. tlb_4k:
  117. cmpwi r11, PPC44x_TLB_4K
  118. bne default
  119. rotlwi r10, r10, 12 /* r10 = 4K */
  120. b write_out
  121. default:
  122. rotlwi r10, r10, 10 /* r10 = 1K */
  123. write_out:
  124. /*
  125. * Write out the tmp 1:1 mapping for this code in other address space
  126. * Fixup EPN = RPN , TS=other address space
  127. */
  128. insrwi r3, r7, 1, 23 /* Bit 23 is TS for PAGEID field */
  129. /* Write out the tmp mapping entries */
  130. tlbwe r3, r24, PPC44x_TLB_PAGEID
  131. tlbwe r4, r24, PPC44x_TLB_XLAT
  132. tlbwe r5, r24, PPC44x_TLB_ATTRIB
  133. subi r11, r10, 1 /* PageOffset Mask = PageSize - 1 */
  134. not r10, r11 /* Mask for PageNum */
  135. /* Switch to other address space in MSR */
  136. insrwi r9, r7, 1, 26 /* Set MSR[IS] = r7 */
  137. bcl 20,31,$+4
  138. 1: mflr r8
  139. addi r8, r8, (2f-1b) /* Find the target offset */
  140. /* Jump to the tmp mapping */
  141. mtspr SPRN_SRR0, r8
  142. mtspr SPRN_SRR1, r9
  143. rfi
  144. 2:
  145. /* Invalidate the entry we were executing from */
  146. li r3, 0
  147. tlbwe r3, r23, PPC44x_TLB_PAGEID
  148. /* attribute fields. rwx for SUPERVISOR mode */
  149. li r5, 0
  150. ori r5, r5, (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G)
  151. /* Create 1:1 mapping in 256M pages */
  152. xori r7, r7, 1 /* Revert back to Original TS */
  153. li r8, 0 /* PageNumber */
  154. li r6, 3 /* TLB Index, start at 3 */
  155. next_tlb:
  156. rotlwi r3, r8, 28 /* Create EPN (bits 0-3) */
  157. mr r4, r3 /* RPN = EPN */
  158. ori r3, r3, (PPC44x_TLB_VALID | PPC44x_TLB_256M) /* SIZE = 256M, Valid */
  159. insrwi r3, r7, 1, 23 /* Set TS from r7 */
  160. tlbwe r3, r6, PPC44x_TLB_PAGEID /* PageID field : EPN, V, SIZE */
  161. tlbwe r4, r6, PPC44x_TLB_XLAT /* Address translation : RPN */
  162. tlbwe r5, r6, PPC44x_TLB_ATTRIB /* Attributes */
  163. addi r8, r8, 1 /* Increment PN */
  164. addi r6, r6, 1 /* Increment TLB Index */
  165. cmpwi r8, 8 /* Are we done ? */
  166. bne next_tlb
  167. isync
  168. /* Jump to the new mapping 1:1 */
  169. li r9,0
  170. insrwi r9, r7, 1, 26 /* Set MSR[IS] = r7 */
  171. bcl 20,31,$+4
  172. 1: mflr r8
  173. and r8, r8, r11 /* Get our offset within page */
  174. addi r8, r8, (2f-1b)
  175. and r5, r25, r10 /* Get our target PageNum */
  176. or r8, r8, r5 /* Target jump address */
  177. mtspr SPRN_SRR0, r8
  178. mtspr SPRN_SRR1, r9
  179. rfi
  180. 2:
  181. /* Invalidate the tmp entry we used */
  182. li r3, 0
  183. tlbwe r3, r24, PPC44x_TLB_PAGEID
  184. sync
  185. b ppc44x_map_done
  186. #ifdef CONFIG_PPC_47x
  187. /* 1:1 mapping for 47x */
  188. setup_map_47x:
  189. /*
  190. * Load the kernel pid (0) to PID and also to MMUCR[TID].
  191. * Also set the MSR IS->MMUCR STS
  192. */
  193. li r3, 0
  194. mtspr SPRN_PID, r3 /* Set PID */
  195. mfmsr r4 /* Get MSR */
  196. andi. r4, r4, MSR_IS@l /* TS=1? */
  197. beq 1f /* If not, leave STS=0 */
  198. oris r3, r3, PPC47x_MMUCR_STS@h /* Set STS=1 */
  199. 1: mtspr SPRN_MMUCR, r3 /* Put MMUCR */
  200. sync
  201. /* Find the entry we are running from */
  202. bcl 20,31,$+4
  203. 2: mflr r23
  204. tlbsx r23, 0, r23
  205. tlbre r24, r23, 0 /* TLB Word 0 */
  206. tlbre r25, r23, 1 /* TLB Word 1 */
  207. tlbre r26, r23, 2 /* TLB Word 2 */
  208. /*
  209. * Invalidates all the tlb entries by writing to 256 RPNs(r4)
  210. * of 4k page size in all 4 ways (0-3 in r3).
  211. * This would invalidate the entire UTLB including the one we are
  212. * running from. However the shadow TLB entries would help us
  213. * to continue the execution, until we flush them (rfi/isync).
  214. */
  215. addis r3, 0, 0x8000 /* specify the way */
  216. addi r4, 0, 0 /* TLB Word0 = (EPN=0, VALID = 0) */
  217. addi r5, 0, 0
  218. b clear_utlb_entry
  219. /* Align the loop to speed things up. from head_44x.S */
  220. .align 6
  221. clear_utlb_entry:
  222. tlbwe r4, r3, 0
  223. tlbwe r5, r3, 1
  224. tlbwe r5, r3, 2
  225. addis r3, r3, 0x2000 /* Increment the way */
  226. cmpwi r3, 0
  227. bne clear_utlb_entry
  228. addis r3, 0, 0x8000
  229. addis r4, r4, 0x100 /* Increment the EPN */
  230. cmpwi r4, 0
  231. bne clear_utlb_entry
  232. /* Create the entries in the other address space */
  233. mfmsr r5
  234. rlwinm r7, r5, 27, 31, 31 /* Get the TS (Bit 26) from MSR */
  235. xori r7, r7, 1 /* r7 = !TS */
  236. insrwi r24, r7, 1, 21 /* Change the TS in the saved TLB word 0 */
  237. /*
  238. * write out the TLB entries for the tmp mapping
  239. * Use way '0' so that we could easily invalidate it later.
  240. */
  241. lis r3, 0x8000 /* Way '0' */
  242. tlbwe r24, r3, 0
  243. tlbwe r25, r3, 1
  244. tlbwe r26, r3, 2
  245. /* Update the msr to the new TS */
  246. insrwi r5, r7, 1, 26
  247. bcl 20,31,$+4
  248. 1: mflr r6
  249. addi r6, r6, (2f-1b)
  250. mtspr SPRN_SRR0, r6
  251. mtspr SPRN_SRR1, r5
  252. rfi
  253. /*
  254. * Now we are in the tmp address space.
  255. * Create a 1:1 mapping for 0-2GiB in the original TS.
  256. */
  257. 2:
  258. li r3, 0
  259. li r4, 0 /* TLB Word 0 */
  260. li r5, 0 /* TLB Word 1 */
  261. li r6, 0
  262. ori r6, r6, PPC47x_TLB2_S_RWX /* TLB word 2 */
  263. li r8, 0 /* PageIndex */
  264. xori r7, r7, 1 /* revert back to original TS */
  265. write_utlb:
  266. rotlwi r5, r8, 28 /* RPN = PageIndex * 256M */
  267. /* ERPN = 0 as we don't use memory above 2G */
  268. mr r4, r5 /* EPN = RPN */
  269. ori r4, r4, (PPC47x_TLB0_VALID | PPC47x_TLB0_256M)
  270. insrwi r4, r7, 1, 21 /* Insert the TS to Word 0 */
  271. tlbwe r4, r3, 0 /* Write out the entries */
  272. tlbwe r5, r3, 1
  273. tlbwe r6, r3, 2
  274. addi r8, r8, 1
  275. cmpwi r8, 8 /* Have we completed ? */
  276. bne write_utlb
  277. /* make sure we complete the TLB write up */
  278. isync
  279. /*
  280. * Prepare to jump to the 1:1 mapping.
  281. * 1) Extract page size of the tmp mapping
  282. * DSIZ = TLB_Word0[22:27]
  283. * 2) Calculate the physical address of the address
  284. * to jump to.
  285. */
  286. rlwinm r10, r24, 0, 22, 27
  287. cmpwi r10, PPC47x_TLB0_4K
  288. bne 0f
  289. li r10, 0x1000 /* r10 = 4k */
  290. bl 1f
  291. 0:
  292. /* Defaults to 256M */
  293. lis r10, 0x1000
  294. bcl 20,31,$+4
  295. 1: mflr r4
  296. addi r4, r4, (2f-1b) /* virtual address of 2f */
  297. subi r11, r10, 1 /* offsetmask = Pagesize - 1 */
  298. not r10, r11 /* Pagemask = ~(offsetmask) */
  299. and r5, r25, r10 /* Physical page */
  300. and r6, r4, r11 /* offset within the current page */
  301. or r5, r5, r6 /* Physical address for 2f */
  302. /* Switch the TS in MSR to the original one */
  303. mfmsr r8
  304. insrwi r8, r7, 1, 26
  305. mtspr SPRN_SRR1, r8
  306. mtspr SPRN_SRR0, r5
  307. rfi
  308. 2:
  309. /* Invalidate the tmp mapping */
  310. lis r3, 0x8000 /* Way '0' */
  311. clrrwi r24, r24, 12 /* Clear the valid bit */
  312. tlbwe r24, r3, 0
  313. tlbwe r25, r3, 1
  314. tlbwe r26, r3, 2
  315. /* Make sure we complete the TLB write and flush the shadow TLB */
  316. isync
  317. #endif
  318. ppc44x_map_done:
  319. /* Restore the parameters */
  320. mr r3, r29
  321. mr r4, r30
  322. mr r5, r31
  323. li r0, 0
  324. #else
  325. li r0, 0
  326. /*
  327. * Set Machine Status Register to a known status,
  328. * switch the MMU off and jump to 1: in a single step.
  329. */
  330. mr r8, r0
  331. ori r8, r8, MSR_RI|MSR_ME
  332. mtspr SPRN_SRR1, r8
  333. addi r8, r4, 1f - relocate_new_kernel
  334. mtspr SPRN_SRR0, r8
  335. sync
  336. rfi
  337. 1:
  338. #endif
  339. /* from this point address translation is turned off */
  340. /* and interrupts are disabled */
  341. /* set a new stack at the bottom of our page... */
  342. /* (not really needed now) */
  343. addi r1, r4, KEXEC_CONTROL_PAGE_SIZE - 8 /* for LR Save+Back Chain */
  344. stw r0, 0(r1)
  345. /* Do the copies */
  346. li r6, 0 /* checksum */
  347. mr r0, r3
  348. b 1f
  349. 0: /* top, read another word for the indirection page */
  350. lwzu r0, 4(r3)
  351. 1:
  352. /* is it a destination page? (r8) */
  353. rlwinm. r7, r0, 0, 31, 31 /* IND_DESTINATION (1<<0) */
  354. beq 2f
  355. rlwinm r8, r0, 0, 0, 19 /* clear kexec flags, page align */
  356. b 0b
  357. 2: /* is it an indirection page? (r3) */
  358. rlwinm. r7, r0, 0, 30, 30 /* IND_INDIRECTION (1<<1) */
  359. beq 2f
  360. rlwinm r3, r0, 0, 0, 19 /* clear kexec flags, page align */
  361. subi r3, r3, 4
  362. b 0b
  363. 2: /* are we done? */
  364. rlwinm. r7, r0, 0, 29, 29 /* IND_DONE (1<<2) */
  365. beq 2f
  366. b 3f
  367. 2: /* is it a source page? (r9) */
  368. rlwinm. r7, r0, 0, 28, 28 /* IND_SOURCE (1<<3) */
  369. beq 0b
  370. rlwinm r9, r0, 0, 0, 19 /* clear kexec flags, page align */
  371. li r7, PAGE_SIZE / 4
  372. mtctr r7
  373. subi r9, r9, 4
  374. subi r8, r8, 4
  375. 9:
  376. lwzu r0, 4(r9) /* do the copy */
  377. xor r6, r6, r0
  378. stwu r0, 4(r8)
  379. dcbst 0, r8
  380. sync
  381. icbi 0, r8
  382. bdnz 9b
  383. addi r9, r9, 4
  384. addi r8, r8, 4
  385. b 0b
  386. 3:
  387. /* To be certain of avoiding problems with self-modifying code
  388. * execute a serializing instruction here.
  389. */
  390. isync
  391. sync
  392. mfspr r3, SPRN_PIR /* current core we are running on */
  393. mr r4, r5 /* load physical address of chunk called */
  394. /* jump to the entry point, usually the setup routine */
  395. mtlr r5
  396. blrl
  397. 1: b 1b
  398. relocate_new_kernel_end:
  399. .globl relocate_new_kernel_size
  400. relocate_new_kernel_size:
  401. .long relocate_new_kernel_end - relocate_new_kernel