crt0.S 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. /*
  2. * Copyright (c) 2009 Corey Tabaka
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining
  5. * a copy of this software and associated documentation files
  6. * (the "Software"), to deal in the Software without restriction,
  7. * including without limitation the rights to use, copy, modify, merge,
  8. * publish, distribute, sublicense, and/or sell copies of the Software,
  9. * and to permit persons to whom the Software is furnished to do so,
  10. * subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be
  13. * included in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  18. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  19. * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  20. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  21. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. /* The magic number for the Multiboot header. */
  24. #define MULTIBOOT_HEADER_MAGIC 0x1BADB002
  25. /* The flags for the Multiboot header. */
  26. #if defined(__ELF__) && 0
  27. #define MULTIBOOT_HEADER_FLAGS 0x00000002
  28. #else
  29. #define MULTIBOOT_HEADER_FLAGS 0x00010002
  30. #endif
  31. /* The magic number passed by a Multiboot-compliant boot loader. */
  32. #define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
  33. #define NUM_INT 0x31
  34. #define NUM_EXC 0x14
  35. .text
  36. .global _start
  37. _start:
  38. jmp real_start
  39. .align 4
  40. multiboot_header:
  41. /* magic */
  42. .int MULTIBOOT_HEADER_MAGIC
  43. /* flags */
  44. .int MULTIBOOT_HEADER_FLAGS
  45. /* checksum */
  46. .int -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
  47. #if !defined(__ELF__) || 1
  48. /* header_addr */
  49. .int multiboot_header
  50. /* load_addr */
  51. .int _start
  52. /* load_end_addr */
  53. .int __bss_start
  54. /* bss_end_addr */
  55. .int __bss_end
  56. /* entry_addr */
  57. .int real_start
  58. #endif
  59. real_start:
  60. cmpl $MULTIBOOT_BOOTLOADER_MAGIC, %eax
  61. jne 0f
  62. movl %ebx, (_multiboot_info)
  63. 0:
  64. /* setup isr stub descriptors in the idt */
  65. movl $_isr, %esi
  66. movl $_idt, %edi
  67. movl $NUM_INT, %ecx
  68. .Lloop:
  69. movl %esi, %ebx
  70. movw %bx, (%edi) /* low word in IDT(n).low */
  71. shrl $16, %ebx
  72. movw %bx, 6(%edi) /* high word in IDT(n).high */
  73. addl $isr_stub_len, %esi/* index the next ISR stub */
  74. addl $8, %edi /* index the next IDT entry */
  75. loop .Lloop
  76. lidt _idtr
  77. xorl %eax, %eax
  78. movl %eax, %cr3
  79. lgdt _gdtr
  80. movw $datasel, %ax
  81. movw %ax, %ds
  82. movw %ax, %es
  83. movw %ax, %fs
  84. movw %ax, %ss
  85. movw %ax, %gs
  86. movw %ax, %ss
  87. movl $_kstack, %esp
  88. /* zero the bss section */
  89. movl $__bss_start, %edi /* starting address of the bss */
  90. movl $__bss_end, %ecx /* find the length of the bss in bytes */
  91. subl %edi, %ecx
  92. shrl $2, %ecx /* convert to 32 bit words, since the bss is aligned anyway */
  93. 2:
  94. movl $0, (%edi)
  95. addl $4, %edi
  96. loop 2b
  97. /* call the main module */
  98. call kmain
  99. 0: /* just sit around waiting for interrupts */
  100. hlt /* interrupts will unhalt the processor */
  101. pause
  102. jmp 0b /* so jump back to halt to conserve power */
  103. /* interrupt service routine stubs */
  104. _isr:
  105. .set i, 0
  106. .rept NUM_INT
  107. .set isr_stub_start, .
  108. .if i == 8 || (i >= 10 && i <= 14) || i == 17
  109. nop /* error code pushed by exception */
  110. nop /* 2 nops are the same length as push byte */
  111. pushl $i /* interrupt number */
  112. jmp interrupt_common
  113. .else
  114. pushl $0 /* fill in error code in iframe */
  115. pushl $i /* interrupt number */
  116. jmp interrupt_common
  117. .endif
  118. /* figure out the length of a single isr stub (usually 6 or 9 bytes) */
  119. .set isr_stub_len, . - isr_stub_start
  120. .set i, i + 1
  121. .endr
  122. /* annoying, but force AS to use the same (longer) encoding of jmp for all of the stubs */
  123. .fill 256
  124. interrupt_common:
  125. pushl %gs /* save segment registers */
  126. pushl %fs
  127. pushl %es
  128. pushl %ds
  129. pusha /* save general purpose registers */
  130. movl $datasel, %eax /* put known good value in segment registers */
  131. movl %eax, %gs
  132. movl %eax, %fs
  133. movl %eax, %es
  134. movl %eax, %ds
  135. movl %esp, %eax /* store stack switch pivot. push esp has errata on some cpus, so use mov/push */
  136. pushl %eax
  137. movl %esp, %eax /* store pointer to iframe, using same method */
  138. pushl %eax
  139. incl critical_section_count
  140. call platform_irq
  141. cmpl $0,%eax
  142. je 0f
  143. call thread_preempt
  144. 0:
  145. decl critical_section_count
  146. popl %eax /* drop pointer to iframe */
  147. popl %eax /* restore task_esp, stack switch can occur here if task_esp is modified */
  148. movl %eax, %esp
  149. popa /* restore general purpose registers */
  150. popl %ds /* restore segment registers */
  151. popl %es
  152. popl %fs
  153. popl %gs
  154. addl $8, %esp /* drop exception number and error code */
  155. iret
  156. .data
  157. .align 4
  158. /* define the heap end as read-write data containing the default end of the
  159. * heap. dynamic memory length discovery can update this value during init.
  160. * other archs can define this statically based on the memory layout of the
  161. * platform.
  162. */
  163. .global _heap_end
  164. _heap_end:
  165. .int 4096*1024 /* default to 4MB total */
  166. .global _multiboot_info
  167. _multiboot_info:
  168. .int 0
  169. .global _gdtr
  170. _gdtr:
  171. .short _gdt_end - _gdt - 1
  172. .int _gdt
  173. .global _gdt
  174. _gdt:
  175. .int 0
  176. .int 0
  177. /* ring 0 descriptors */
  178. .set codesel, . - _gdt
  179. _code_gde:
  180. .short 0xffff /* limit 15:00 */
  181. .short 0x0000 /* base 15:00 */
  182. .byte 0x00 /* base 23:16 */
  183. .byte 0b10011010 /* P(1) DPL(00) S(1) 1 C(0) R(1) A(0) */
  184. .byte 0b11001111 /* G(1) D(1) 0 0 limit 19:16 */
  185. .byte 0x0 /* base 31:24 */
  186. .set datasel, . - _gdt
  187. _data_gde:
  188. .short 0xffff /* limit 15:00 */
  189. .short 0x0000 /* base 15:00 */
  190. .byte 0x00 /* base 23:16 */
  191. .byte 0b10010010 /* P(1) DPL(00) S(1) 0 E(0) W(1) A(0) */
  192. .byte 0b11001111 /* G(1) B(1) 0 0 limit 19:16 */
  193. .byte 0x0 /* base 31:24 */
  194. .set videosel, . - _gdt
  195. _video_gde:
  196. .short 0xffff /* limit 15:00 */
  197. .short 0x8000 /* base 15:00 */
  198. .byte 0x0b /* base 23:16 */
  199. .byte 0b10010010 /* P(1) DPL(00) S(1) 0 E(0) W(1) A(0) */
  200. .byte 0b11001111 /* G(1) B(1) 0 0 limit 19:16 */
  201. .byte 0x0 /* base 31:24 */
  202. .if 1
  203. /* ring 3 descriptors */
  204. .set user_codesel, . - _gdt
  205. _user_code_gde:
  206. .short 0xffff /* limit 15:00 */
  207. .short 0x0000 /* base 15:00 */
  208. .byte 0x00 /* base 23:16 */
  209. .byte 0b11111010 /* P(1) DPL(11) S(1) 1 C(0) R(1) A(0) */
  210. .byte 0b11001111 /* G(1) D(1) 0 0 limit 19:16 */
  211. .byte 0x0 /* base 31:24 */
  212. .set user_datasel, . - _gdt
  213. _user_data_gde:
  214. .short 0xffff /* limit 15:00 */
  215. .short 0x0000 /* base 15:00 */
  216. .byte 0x00 /* base 23:16 */
  217. .byte 0b11110010 /* P(1) DPL(11) S(1) 0 E(0) W(1) A(0) */
  218. .byte 0b11001111 /* G(1) B(1) 0 0 limit 19:16 */
  219. .byte 0x0 /* base 31:24 */
  220. .endif
  221. /* TSS descriptor */
  222. .if 1
  223. .set tsssel, . - _gdt
  224. _tss_gde:
  225. .short 0 /* limit 15:00 */
  226. .short 0 /* base 15:00 */
  227. .byte 0 /* base 23:16 */
  228. .byte 0xe9 /* P(1) DPL(11) 0 10 B(0) 1 */
  229. .byte 0x00 /* G(0) 0 0 AVL(0) limit 19:16 */
  230. .short 0 /* base 31:24 */
  231. .endif
  232. .global _gdt_end
  233. _gdt_end:
  234. .global _idtr
  235. _idtr:
  236. .short _idt_end - _idt - 1 /* IDT limit */
  237. .int _idt
  238. /* interrupt descriptor table (IDT) */
  239. .global _idt
  240. _idt:
  241. .set i, 0
  242. .rept NUM_INT-1
  243. .short 0 /* low 16 bits of ISR offset (_isr#i & 0FFFFh) */
  244. .short codesel /* selector */
  245. .byte 0
  246. .byte 0x8e /* present, ring 0, 32-bit interrupt gate */
  247. .short 0 /* high 16 bits of ISR offset (_isr#i / 65536) */
  248. .set i, i + 1
  249. .endr
  250. /* syscall int (ring 3) */
  251. _idt30:
  252. .short 0 /* low 16 bits of ISR offset (_isr#i & 0FFFFh) */
  253. .short codesel /* selector */
  254. .byte 0
  255. .byte 0xee /* present, ring 3, 32-bit interrupt gate */
  256. .short 0 /* high 16 bits of ISR offset (_isr#i / 65536) */
  257. .global _idt_end
  258. _idt_end:
  259. .bss
  260. .align 4096
  261. .global _kstack
  262. .fill 4096
  263. _kstack: