relocate_kernel.S 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*
  2. * relocate_kernel.S - put the kernel image in place to boot
  3. * Copyright (C) 2002-2004 Eric Biederman <ebiederm@xmission.com>
  4. *
  5. * This source code is licensed under the GNU General Public License,
  6. * Version 2. See the file COPYING for more details.
  7. */
  8. #include <linux/linkage.h>
  9. #include <asm/page.h>
  10. #include <asm/kexec.h>
  11. /*
  12. * Must be relocatable PIC code callable as a C function
  13. */
  14. #define PTR(x) (x << 2)
  15. #define PAGE_ALIGNED (1 << PAGE_SHIFT)
  16. #define PAGE_ATTR 0x63 /* _PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY */
  17. #define PAE_PGD_ATTR 0x01 /* _PAGE_PRESENT */
  18. .text
  19. .align PAGE_ALIGNED
  20. .globl relocate_kernel
  21. relocate_kernel:
  22. movl 8(%esp), %ebp /* list of pages */
  23. #ifdef CONFIG_X86_PAE
  24. /* map the control page at its virtual address */
  25. movl PTR(VA_PGD)(%ebp), %edi
  26. movl PTR(VA_CONTROL_PAGE)(%ebp), %eax
  27. andl $0xc0000000, %eax
  28. shrl $27, %eax
  29. addl %edi, %eax
  30. movl PTR(PA_PMD_0)(%ebp), %edx
  31. orl $PAE_PGD_ATTR, %edx
  32. movl %edx, (%eax)
  33. movl PTR(VA_PMD_0)(%ebp), %edi
  34. movl PTR(VA_CONTROL_PAGE)(%ebp), %eax
  35. andl $0x3fe00000, %eax
  36. shrl $18, %eax
  37. addl %edi, %eax
  38. movl PTR(PA_PTE_0)(%ebp), %edx
  39. orl $PAGE_ATTR, %edx
  40. movl %edx, (%eax)
  41. movl PTR(VA_PTE_0)(%ebp), %edi
  42. movl PTR(VA_CONTROL_PAGE)(%ebp), %eax
  43. andl $0x001ff000, %eax
  44. shrl $9, %eax
  45. addl %edi, %eax
  46. movl PTR(PA_CONTROL_PAGE)(%ebp), %edx
  47. orl $PAGE_ATTR, %edx
  48. movl %edx, (%eax)
  49. /* identity map the control page at its physical address */
  50. movl PTR(VA_PGD)(%ebp), %edi
  51. movl PTR(PA_CONTROL_PAGE)(%ebp), %eax
  52. andl $0xc0000000, %eax
  53. shrl $27, %eax
  54. addl %edi, %eax
  55. movl PTR(PA_PMD_1)(%ebp), %edx
  56. orl $PAE_PGD_ATTR, %edx
  57. movl %edx, (%eax)
  58. movl PTR(VA_PMD_1)(%ebp), %edi
  59. movl PTR(PA_CONTROL_PAGE)(%ebp), %eax
  60. andl $0x3fe00000, %eax
  61. shrl $18, %eax
  62. addl %edi, %eax
  63. movl PTR(PA_PTE_1)(%ebp), %edx
  64. orl $PAGE_ATTR, %edx
  65. movl %edx, (%eax)
  66. movl PTR(VA_PTE_1)(%ebp), %edi
  67. movl PTR(PA_CONTROL_PAGE)(%ebp), %eax
  68. andl $0x001ff000, %eax
  69. shrl $9, %eax
  70. addl %edi, %eax
  71. movl PTR(PA_CONTROL_PAGE)(%ebp), %edx
  72. orl $PAGE_ATTR, %edx
  73. movl %edx, (%eax)
  74. #else
  75. /* map the control page at its virtual address */
  76. movl PTR(VA_PGD)(%ebp), %edi
  77. movl PTR(VA_CONTROL_PAGE)(%ebp), %eax
  78. andl $0xffc00000, %eax
  79. shrl $20, %eax
  80. addl %edi, %eax
  81. movl PTR(PA_PTE_0)(%ebp), %edx
  82. orl $PAGE_ATTR, %edx
  83. movl %edx, (%eax)
  84. movl PTR(VA_PTE_0)(%ebp), %edi
  85. movl PTR(VA_CONTROL_PAGE)(%ebp), %eax
  86. andl $0x003ff000, %eax
  87. shrl $10, %eax
  88. addl %edi, %eax
  89. movl PTR(PA_CONTROL_PAGE)(%ebp), %edx
  90. orl $PAGE_ATTR, %edx
  91. movl %edx, (%eax)
  92. /* identity map the control page at its physical address */
  93. movl PTR(VA_PGD)(%ebp), %edi
  94. movl PTR(PA_CONTROL_PAGE)(%ebp), %eax
  95. andl $0xffc00000, %eax
  96. shrl $20, %eax
  97. addl %edi, %eax
  98. movl PTR(PA_PTE_1)(%ebp), %edx
  99. orl $PAGE_ATTR, %edx
  100. movl %edx, (%eax)
  101. movl PTR(VA_PTE_1)(%ebp), %edi
  102. movl PTR(PA_CONTROL_PAGE)(%ebp), %eax
  103. andl $0x003ff000, %eax
  104. shrl $10, %eax
  105. addl %edi, %eax
  106. movl PTR(PA_CONTROL_PAGE)(%ebp), %edx
  107. orl $PAGE_ATTR, %edx
  108. movl %edx, (%eax)
  109. #endif
  110. relocate_new_kernel:
  111. /* read the arguments and say goodbye to the stack */
  112. movl 4(%esp), %ebx /* page_list */
  113. movl 8(%esp), %ebp /* list of pages */
  114. movl 12(%esp), %edx /* start address */
  115. movl 16(%esp), %ecx /* cpu_has_pae */
  116. /* zero out flags, and disable interrupts */
  117. pushl $0
  118. popfl
  119. /* get physical address of control page now */
  120. /* this is impossible after page table switch */
  121. movl PTR(PA_CONTROL_PAGE)(%ebp), %edi
  122. /* switch to new set of page tables */
  123. movl PTR(PA_PGD)(%ebp), %eax
  124. movl %eax, %cr3
  125. /* setup a new stack at the end of the physical control page */
  126. lea 4096(%edi), %esp
  127. /* jump to identity mapped page */
  128. movl %edi, %eax
  129. addl $(identity_mapped - relocate_kernel), %eax
  130. pushl %eax
  131. ret
  132. identity_mapped:
  133. /* store the start address on the stack */
  134. pushl %edx
  135. /* Set cr0 to a known state:
  136. * 31 0 == Paging disabled
  137. * 18 0 == Alignment check disabled
  138. * 16 0 == Write protect disabled
  139. * 3 0 == No task switch
  140. * 2 0 == Don't do FP software emulation.
  141. * 0 1 == Proctected mode enabled
  142. */
  143. movl %cr0, %eax
  144. andl $~((1<<31)|(1<<18)|(1<<16)|(1<<3)|(1<<2)), %eax
  145. orl $(1<<0), %eax
  146. movl %eax, %cr0
  147. /* clear cr4 if applicable */
  148. testl %ecx, %ecx
  149. jz 1f
  150. /* Set cr4 to a known state:
  151. * Setting everything to zero seems safe.
  152. */
  153. movl %cr4, %eax
  154. andl $0, %eax
  155. movl %eax, %cr4
  156. jmp 1f
  157. 1:
  158. /* Flush the TLB (needed?) */
  159. xorl %eax, %eax
  160. movl %eax, %cr3
  161. /* Do the copies */
  162. movl %ebx, %ecx
  163. jmp 1f
  164. 0: /* top, read another word from the indirection page */
  165. movl (%ebx), %ecx
  166. addl $4, %ebx
  167. 1:
  168. testl $0x1, %ecx /* is it a destination page */
  169. jz 2f
  170. movl %ecx, %edi
  171. andl $0xfffff000, %edi
  172. jmp 0b
  173. 2:
  174. testl $0x2, %ecx /* is it an indirection page */
  175. jz 2f
  176. movl %ecx, %ebx
  177. andl $0xfffff000, %ebx
  178. jmp 0b
  179. 2:
  180. testl $0x4, %ecx /* is it the done indicator */
  181. jz 2f
  182. jmp 3f
  183. 2:
  184. testl $0x8, %ecx /* is it the source indicator */
  185. jz 0b /* Ignore it otherwise */
  186. movl %ecx, %esi /* For every source page do a copy */
  187. andl $0xfffff000, %esi
  188. movl $1024, %ecx
  189. rep ; movsl
  190. jmp 0b
  191. 3:
  192. /* To be certain of avoiding problems with self-modifying code
  193. * I need to execute a serializing instruction here.
  194. * So I flush the TLB, it's handy, and not processor dependent.
  195. */
  196. xorl %eax, %eax
  197. movl %eax, %cr3
  198. /* set all of the registers to known values */
  199. /* leave %esp alone */
  200. xorl %eax, %eax
  201. xorl %ebx, %ebx
  202. xorl %ecx, %ecx
  203. xorl %edx, %edx
  204. xorl %esi, %esi
  205. xorl %edi, %edi
  206. xorl %ebp, %ebp
  207. ret