realmode_switch.S 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /*
  2. * (C) Copyright 2002
  3. * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. * MA 02111-1307 USA
  22. */
  23. /* 32bit -> 16bit -> 32bit mode switch code */
  24. /*
  25. * Stack frame at 0xe00
  26. * e00 ebx;
  27. * e04 ecx;
  28. * e08 edx;
  29. * e0c esi;
  30. * e10 edi;
  31. * e14 ebp;
  32. * e18 eax;
  33. * e1c ds;
  34. * e20 es;
  35. * e24 fs;
  36. * e28 gs;
  37. * e2c orig_eax;
  38. * e30 eip;
  39. * e34 cs;
  40. * e38 eflags;
  41. * e3c esp;
  42. * e40 ss;
  43. */
  44. #define a32 .byte 0x67; /* address size prefix 32 */
  45. #define o32 .byte 0x66; /* operand size prefix 32 */
  46. .section .realmode, "ax"
  47. .code16
  48. /* 16bit protected mode code here */
  49. .globl realmode_enter
  50. realmode_enter:
  51. o32 pusha
  52. o32 pushf
  53. cli
  54. sidt saved_idt
  55. sgdt saved_gdt
  56. movl %esp, %eax
  57. movl %eax, saved_protected_mode_esp
  58. movl $0x10, %eax
  59. movl %eax, %esp
  60. movw $0x28, %ax
  61. movw %ax, %ds
  62. movw %ax, %es
  63. movw %ax, %fs
  64. movw %ax, %gs
  65. lidt realmode_idt_ptr
  66. movl %cr0, %eax /* Go back into real mode by */
  67. andl $0x7ffffffe, %eax /* clearing PE to 0 */
  68. movl %eax, %cr0
  69. ljmp $0x0,$do_realmode /* switch to real mode */
  70. do_realmode: /* realmode code from here */
  71. movw %cs,%ax
  72. movw %ax,%ds
  73. movw %ax,%es
  74. movw %ax,%fs
  75. movw %ax,%gs
  76. /* create a temporary stack */
  77. movw $0xc0, %ax
  78. movw %ax, %ss
  79. movw $0x200, %ax
  80. movw %ax, %sp
  81. popl %ebx
  82. popl %ecx
  83. popl %edx
  84. popl %esi
  85. popl %edi
  86. popl %ebp
  87. popl %eax
  88. movl %eax, temp_eax
  89. popl %eax
  90. movw %ax, %ds
  91. popl %eax
  92. movw %ax, %es
  93. popl %eax
  94. movw %ax, %fs
  95. popl %eax
  96. movw %ax, %gs
  97. popl %eax /* orig_eax */
  98. popl %eax
  99. cs movw %ax, temp_ip
  100. popl %eax
  101. cs movw %ax, temp_cs
  102. o32 popf
  103. popl %eax
  104. popw %ss
  105. movl %eax, %esp
  106. cs movl temp_eax, %eax
  107. wbinvd /* self-modifying code,
  108. * better flush the cache */
  109. .byte 0x9a /* lcall */
  110. temp_ip:
  111. .word 0 /* new ip */
  112. temp_cs:
  113. .word 0 /* new cs */
  114. realmode_ret:
  115. /* save eax, esp and ss */
  116. cs movl %eax, saved_eax
  117. movl %esp, %eax
  118. cs movl %eax, saved_esp
  119. movw %ss, %ax
  120. cs movw %ax, saved_ss
  121. /* restore the stack, note that we set sp to 0x244;
  122. * pt_regs is 0x44 bytes long and we push the structure
  123. * backwards on to the stack, bottom first */
  124. movw $0xc0, %ax
  125. movw %ax, %ss
  126. movw $0x244, %ax
  127. movw %ax, %sp
  128. xorl %eax,%eax
  129. cs movw saved_ss, %ax
  130. pushl %eax
  131. cs movl saved_esp, %eax
  132. pushl %eax
  133. o32 pushf
  134. xorl %eax,%eax
  135. cs movw temp_cs, %ax
  136. pushl %eax
  137. cs movw temp_ip, %ax
  138. pushl %eax
  139. pushl $0
  140. movw %gs, %ax
  141. pushl %eax
  142. movw %fs, %ax
  143. pushl %eax
  144. movw %es, %ax
  145. pushl %eax
  146. movw %ds, %ax
  147. pushl %eax
  148. movl saved_eax, %eax
  149. pushl %eax
  150. pushl %ebp
  151. pushl %edi
  152. pushl %esi
  153. pushl %edx
  154. pushl %ecx
  155. pushl %ebx
  156. o32 cs lidt saved_idt
  157. o32 cs lgdt saved_gdt /* Set GDTR */
  158. movl %cr0, %eax /* Go back into protected mode */
  159. orl $1,%eax /* reset PE to 1 */
  160. movl %eax, %cr0
  161. jmp next_line /* flush prefetch queue */
  162. next_line:
  163. movw $return_ptr, %ax
  164. movw %ax,%bp
  165. o32 cs ljmp *(%bp)
  166. .code32
  167. protected_mode:
  168. movl $0x18,%eax /* reload GDT[3] */
  169. movw %ax,%fs /* reset FS */
  170. movw %ax,%ds /* reset DS */
  171. movw %ax,%gs /* reset GS */
  172. movw %ax,%es /* reset ES */
  173. movw %ax,%ss /* reset SS */
  174. movl saved_protected_mode_esp, %eax
  175. movl %eax, %esp
  176. popf
  177. popa
  178. ret
  179. temp_eax:
  180. .long 0
  181. saved_ss:
  182. .word 0
  183. saved_esp:
  184. .long 0
  185. saved_eax:
  186. .long 0
  187. realmode_idt_ptr:
  188. .word 0x400
  189. .word 0x0, 0x0
  190. saved_gdt:
  191. .word 0, 0, 0, 0
  192. saved_idt:
  193. .word 0, 0, 0, 0
  194. saved_protected_mode_esp:
  195. .long 0
  196. return_ptr:
  197. .long protected_mode
  198. .word 0x10