relocate_kernel_32.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. #include <asm/processor-flags.h>
  12. #include <asm/pgtable.h>
  13. /*
  14. * Must be relocatable PIC code callable as a C function
  15. */
  16. #define PTR(x) (x << 2)
  17. #define PAGE_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
  18. #define PAE_PGD_ATTR (_PAGE_PRESENT)
  19. .text
  20. .align PAGE_SIZE
  21. .globl relocate_kernel
  22. relocate_kernel:
  23. movl 8(%esp), %ebp /* list of pages */
  24. #ifdef CONFIG_X86_PAE
  25. /* map the control page at its virtual address */
  26. movl PTR(VA_PGD)(%ebp), %edi
  27. movl PTR(VA_CONTROL_PAGE)(%ebp), %eax
  28. andl $0xc0000000, %eax
  29. shrl $27, %eax
  30. addl %edi, %eax
  31. movl PTR(PA_PMD_0)(%ebp), %edx
  32. orl $PAE_PGD_ATTR, %edx
  33. movl %edx, (%eax)
  34. movl PTR(VA_PMD_0)(%ebp), %edi
  35. movl PTR(VA_CONTROL_PAGE)(%ebp), %eax
  36. andl $0x3fe00000, %eax
  37. shrl $18, %eax
  38. addl %edi, %eax
  39. movl PTR(PA_PTE_0)(%ebp), %edx
  40. orl $PAGE_ATTR, %edx
  41. movl %edx, (%eax)
  42. movl PTR(VA_PTE_0)(%ebp), %edi
  43. movl PTR(VA_CONTROL_PAGE)(%ebp), %eax
  44. andl $0x001ff000, %eax
  45. shrl $9, %eax
  46. addl %edi, %eax
  47. movl PTR(PA_CONTROL_PAGE)(%ebp), %edx
  48. orl $PAGE_ATTR, %edx
  49. movl %edx, (%eax)
  50. /* identity map the control page at its physical address */
  51. movl PTR(VA_PGD)(%ebp), %edi
  52. movl PTR(PA_CONTROL_PAGE)(%ebp), %eax
  53. andl $0xc0000000, %eax
  54. shrl $27, %eax
  55. addl %edi, %eax
  56. movl PTR(PA_PMD_1)(%ebp), %edx
  57. orl $PAE_PGD_ATTR, %edx
  58. movl %edx, (%eax)
  59. movl PTR(VA_PMD_1)(%ebp), %edi
  60. movl PTR(PA_CONTROL_PAGE)(%ebp), %eax
  61. andl $0x3fe00000, %eax
  62. shrl $18, %eax
  63. addl %edi, %eax
  64. movl PTR(PA_PTE_1)(%ebp), %edx
  65. orl $PAGE_ATTR, %edx
  66. movl %edx, (%eax)
  67. movl PTR(VA_PTE_1)(%ebp), %edi
  68. movl PTR(PA_CONTROL_PAGE)(%ebp), %eax
  69. andl $0x001ff000, %eax
  70. shrl $9, %eax
  71. addl %edi, %eax
  72. movl PTR(PA_CONTROL_PAGE)(%ebp), %edx
  73. orl $PAGE_ATTR, %edx
  74. movl %edx, (%eax)
  75. #else
  76. /* map the control page at its virtual address */
  77. movl PTR(VA_PGD)(%ebp), %edi
  78. movl PTR(VA_CONTROL_PAGE)(%ebp), %eax
  79. andl $0xffc00000, %eax
  80. shrl $20, %eax
  81. addl %edi, %eax
  82. movl PTR(PA_PTE_0)(%ebp), %edx
  83. orl $PAGE_ATTR, %edx
  84. movl %edx, (%eax)
  85. movl PTR(VA_PTE_0)(%ebp), %edi
  86. movl PTR(VA_CONTROL_PAGE)(%ebp), %eax
  87. andl $0x003ff000, %eax
  88. shrl $10, %eax
  89. addl %edi, %eax
  90. movl PTR(PA_CONTROL_PAGE)(%ebp), %edx
  91. orl $PAGE_ATTR, %edx
  92. movl %edx, (%eax)
  93. /* identity map the control page at its physical address */
  94. movl PTR(VA_PGD)(%ebp), %edi
  95. movl PTR(PA_CONTROL_PAGE)(%ebp), %eax
  96. andl $0xffc00000, %eax
  97. shrl $20, %eax
  98. addl %edi, %eax
  99. movl PTR(PA_PTE_1)(%ebp), %edx
  100. orl $PAGE_ATTR, %edx
  101. movl %edx, (%eax)
  102. movl PTR(VA_PTE_1)(%ebp), %edi
  103. movl PTR(PA_CONTROL_PAGE)(%ebp), %eax
  104. andl $0x003ff000, %eax
  105. shrl $10, %eax
  106. addl %edi, %eax
  107. movl PTR(PA_CONTROL_PAGE)(%ebp), %edx
  108. orl $PAGE_ATTR, %edx
  109. movl %edx, (%eax)
  110. #endif
  111. relocate_new_kernel:
  112. /* read the arguments and say goodbye to the stack */
  113. movl 4(%esp), %ebx /* page_list */
  114. movl 8(%esp), %ebp /* list of pages */
  115. movl 12(%esp), %edx /* start address */
  116. movl 16(%esp), %ecx /* cpu_has_pae */
  117. /* zero out flags, and disable interrupts */
  118. pushl $0
  119. popfl
  120. /* get physical address of control page now */
  121. /* this is impossible after page table switch */
  122. movl PTR(PA_CONTROL_PAGE)(%ebp), %edi
  123. /* switch to new set of page tables */
  124. movl PTR(PA_PGD)(%ebp), %eax
  125. movl %eax, %cr3
  126. /* setup a new stack at the end of the physical control page */
  127. lea PAGE_SIZE(%edi), %esp
  128. /* jump to identity mapped page */
  129. movl %edi, %eax
  130. addl $(identity_mapped - relocate_kernel), %eax
  131. pushl %eax
  132. ret
  133. identity_mapped:
  134. /* store the start address on the stack */
  135. pushl %edx
  136. /* Set cr0 to a known state:
  137. * - Paging disabled
  138. * - Alignment check disabled
  139. * - Write protect disabled
  140. * - No task switch
  141. * - Don't do FP software emulation.
  142. * - Proctected mode enabled
  143. */
  144. movl %cr0, %eax
  145. andl $~(X86_CR0_PG | X86_CR0_AM | X86_CR0_WP | X86_CR0_TS | X86_CR0_EM), %eax
  146. orl $(X86_CR0_PE), %eax
  147. movl %eax, %cr0
  148. /* clear cr4 if applicable */
  149. testl %ecx, %ecx
  150. jz 1f
  151. /* Set cr4 to a known state:
  152. * Setting everything to zero seems safe.
  153. */
  154. xorl %eax, %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