relocate_kernel.S 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  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. /*
  10. * Must be relocatable PIC code callable as a C function, that once
  11. * it starts can not use the previous processes stack.
  12. */
  13. .globl relocate_new_kernel
  14. relocate_new_kernel:
  15. /* read the arguments and say goodbye to the stack */
  16. movl 4(%esp), %ebx /* page_list */
  17. movl 8(%esp), %ebp /* reboot_code_buffer */
  18. movl 12(%esp), %edx /* start address */
  19. movl 16(%esp), %ecx /* cpu_has_pae */
  20. /* zero out flags, and disable interrupts */
  21. pushl $0
  22. popfl
  23. /* set a new stack at the bottom of our page... */
  24. lea 4096(%ebp), %esp
  25. /* store the parameters back on the stack */
  26. pushl %edx /* store the start address */
  27. /* Set cr0 to a known state:
  28. * 31 0 == Paging disabled
  29. * 18 0 == Alignment check disabled
  30. * 16 0 == Write protect disabled
  31. * 3 0 == No task switch
  32. * 2 0 == Don't do FP software emulation.
  33. * 0 1 == Proctected mode enabled
  34. */
  35. movl %cr0, %eax
  36. andl $~((1<<31)|(1<<18)|(1<<16)|(1<<3)|(1<<2)), %eax
  37. orl $(1<<0), %eax
  38. movl %eax, %cr0
  39. /* clear cr4 if applicable */
  40. testl %ecx, %ecx
  41. jz 1f
  42. /* Set cr4 to a known state:
  43. * Setting everything to zero seems safe.
  44. */
  45. movl %cr4, %eax
  46. andl $0, %eax
  47. movl %eax, %cr4
  48. jmp 1f
  49. 1:
  50. /* Flush the TLB (needed?) */
  51. xorl %eax, %eax
  52. movl %eax, %cr3
  53. /* Do the copies */
  54. movl %ebx, %ecx
  55. jmp 1f
  56. 0: /* top, read another word from the indirection page */
  57. movl (%ebx), %ecx
  58. addl $4, %ebx
  59. 1:
  60. testl $0x1, %ecx /* is it a destination page */
  61. jz 2f
  62. movl %ecx, %edi
  63. andl $0xfffff000, %edi
  64. jmp 0b
  65. 2:
  66. testl $0x2, %ecx /* is it an indirection page */
  67. jz 2f
  68. movl %ecx, %ebx
  69. andl $0xfffff000, %ebx
  70. jmp 0b
  71. 2:
  72. testl $0x4, %ecx /* is it the done indicator */
  73. jz 2f
  74. jmp 3f
  75. 2:
  76. testl $0x8, %ecx /* is it the source indicator */
  77. jz 0b /* Ignore it otherwise */
  78. movl %ecx, %esi /* For every source page do a copy */
  79. andl $0xfffff000, %esi
  80. movl $1024, %ecx
  81. rep ; movsl
  82. jmp 0b
  83. 3:
  84. /* To be certain of avoiding problems with self-modifying code
  85. * I need to execute a serializing instruction here.
  86. * So I flush the TLB, it's handy, and not processor dependent.
  87. */
  88. xorl %eax, %eax
  89. movl %eax, %cr3
  90. /* set all of the registers to known values */
  91. /* leave %esp alone */
  92. xorl %eax, %eax
  93. xorl %ebx, %ebx
  94. xorl %ecx, %ecx
  95. xorl %edx, %edx
  96. xorl %esi, %esi
  97. xorl %edi, %edi
  98. xorl %ebp, %ebp
  99. ret
  100. relocate_new_kernel_end:
  101. .globl relocate_new_kernel_size
  102. relocate_new_kernel_size:
  103. .long relocate_new_kernel_end - relocate_new_kernel