You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

gdbidt.S 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * Interrupt Descriptor Table (IDT) setup and interrupt handlers for GDB stub.
  3. */
  4. #include <librm.h>
  5. #define SIZEOF_I386_REGS 32
  6. #define SIZEOF_I386_FLAGS 4
  7. /****************************************************************************
  8. * Interrupt Descriptor Table
  9. ****************************************************************************
  10. */
  11. .section ".data16", "aw", @progbits
  12. .globl idtr
  13. idtr:
  14. idt_limit:
  15. .word idt_length - 1
  16. idt_base:
  17. .long 0
  18. /* IDT entries have the following format:
  19. * offset_lo, segment selector, flags, offset_hi
  20. *
  21. * Since it is not possible to specify relocations in arbitrary
  22. * expressions like (int_overflow & 0xffff), we initialise the
  23. * IDT with entries in an incorrect format.
  24. *
  25. * The entries are shuffled into the correct format in init_librm().
  26. */
  27. #define IDT_ENTRY_EMPTY(name) .word 0, 0, 0, 0
  28. #define IDT_ENTRY_PRESENT(name) \
  29. .long int_##name; \
  30. .word 0x8e00, VIRTUAL_CS
  31. .align 16
  32. idt:
  33. IDT_ENTRY_PRESENT(divide_error)
  34. IDT_ENTRY_PRESENT(debug_trap)
  35. IDT_ENTRY_EMPTY(non_maskable_interrupt)
  36. IDT_ENTRY_PRESENT(breakpoint)
  37. IDT_ENTRY_PRESENT(overflow)
  38. IDT_ENTRY_PRESENT(bound_range_exceeded)
  39. IDT_ENTRY_PRESENT(invalid_opcode)
  40. IDT_ENTRY_EMPTY(device_not_available)
  41. IDT_ENTRY_PRESENT(double_fault)
  42. IDT_ENTRY_EMPTY(coprocessor_segment_overrun)
  43. IDT_ENTRY_PRESENT(invalid_tss)
  44. IDT_ENTRY_PRESENT(segment_not_present)
  45. IDT_ENTRY_PRESENT(stack_segment_fault)
  46. IDT_ENTRY_PRESENT(general_protection)
  47. IDT_ENTRY_PRESENT(page_fault)
  48. idt_end:
  49. .equ idt_length, idt_end - idt
  50. /* The IDT entries are fixed up (once) in init_librm() */
  51. idt_fixed:
  52. .byte 0
  53. /****************************************************************************
  54. * idt_init (real-mode near call, 16-bit real-mode near return address)
  55. *
  56. * Initialise the IDT, called from init_librm.
  57. *
  58. * Parameters:
  59. * %eax : IDT base address
  60. *
  61. * Destroys %ax, %bx, and %di.
  62. ****************************************************************************
  63. */
  64. .section ".text16", "ax", @progbits
  65. .code16
  66. .globl idt_init
  67. idt_init:
  68. movl %eax, idt_base
  69. addl $idt, idt_base
  70. /* IDT entries are only fixed up once */
  71. movb idt_fixed, %al
  72. orb %al, %al
  73. jnz 2f
  74. movb $1, idt_fixed
  75. /* Shuffle IDT entries into the correct format */
  76. movb $(idt_length / 8), %al
  77. movw $idt, %bx
  78. or %al, %al
  79. jz 2f
  80. 1:
  81. movw 2(%bx), %di
  82. xchg %di, 6(%bx)
  83. movw %di, 2(%bx)
  84. addw $8, %bx
  85. dec %al
  86. jnz 1b
  87. 2:
  88. ret
  89. /****************************************************************************
  90. * Interrupt handlers
  91. ****************************************************************************
  92. */
  93. .section ".text", "ax", @progbits
  94. .code32
  95. /* POSIX signal numbers for reporting traps to GDB */
  96. #define SIGILL 4
  97. #define SIGTRAP 5
  98. #define SIGBUS 7
  99. #define SIGFPE 8
  100. #define SIGSEGV 11
  101. #define SIGSTKFLT 16
  102. int_divide_error:
  103. pushl $SIGFPE
  104. jmp do_interrupt
  105. int_debug_trap:
  106. int_breakpoint:
  107. pushl $SIGTRAP
  108. jmp do_interrupt
  109. int_overflow:
  110. int_bound_range_exceeded:
  111. pushl $SIGSTKFLT
  112. jmp do_interrupt
  113. int_invalid_opcode:
  114. pushl $SIGILL
  115. jmp do_interrupt
  116. int_double_fault:
  117. movl $SIGBUS, (%esp)
  118. jmp do_interrupt
  119. int_invalid_tss:
  120. int_segment_not_present:
  121. int_stack_segment_fault:
  122. int_general_protection:
  123. int_page_fault:
  124. movl $SIGSEGV, (%esp)
  125. jmp do_interrupt
  126. /* When invoked, the stack contains: eflags, cs, eip, signo. */
  127. #define IH_OFFSET_GDB_REGS ( 0 )
  128. #define IH_OFFSET_GDB_EIP ( IH_OFFSET_GDB_REGS + SIZEOF_I386_REGS )
  129. #define IH_OFFSET_GDB_EFLAGS ( IH_OFFSET_GDB_EIP + 4 )
  130. #define IH_OFFSET_GDB_SEG_REGS ( IH_OFFSET_GDB_EFLAGS + SIZEOF_I386_FLAGS )
  131. #define IH_OFFSET_GDB_END ( IH_OFFSET_GDB_SEG_REGS + 6 * 4 )
  132. #define IH_OFFSET_SIGNO ( IH_OFFSET_GDB_END )
  133. #define IH_OFFSET_OLD_EIP ( IH_OFFSET_SIGNO + 4 )
  134. #define IH_OFFSET_OLD_CS ( IH_OFFSET_OLD_EIP + 4 )
  135. #define IH_OFFSET_OLD_EFLAGS ( IH_OFFSET_OLD_CS + 4 )
  136. #define IH_OFFSET_END ( IH_OFFSET_OLD_EFLAGS + 4 )
  137. /* We also access the stack whilst still storing or restoring
  138. * the register snapshot. Since ESP is in flux, we need
  139. * special offsets.
  140. */
  141. #define IH_OFFSET_FLUX_OLD_CS ( IH_OFFSET_OLD_CS - 44 )
  142. #define IH_OFFSET_FLUX_OLD_EFLAGS ( IH_OFFSET_OLD_EFLAGS - 40 )
  143. #define IH_OFFSET_FLUX_OLD_EIP ( IH_OFFSET_OLD_EIP - 36 )
  144. #define IH_OFFSET_FLUX_END ( IH_OFFSET_END - 20 )
  145. do_interrupt:
  146. /* Store CPU state in GDB register snapshot */
  147. pushw $0
  148. pushw %gs
  149. pushw $0
  150. pushw %fs
  151. pushw $0
  152. pushw %es
  153. pushw $0
  154. pushw %ds
  155. pushw $0
  156. pushw %ss
  157. pushw $0
  158. pushw IH_OFFSET_FLUX_OLD_CS + 2(%esp)
  159. pushl IH_OFFSET_FLUX_OLD_EFLAGS(%esp)
  160. pushl IH_OFFSET_FLUX_OLD_EIP(%esp)
  161. pushl %edi
  162. pushl %esi
  163. pushl %ebp
  164. leal IH_OFFSET_FLUX_END(%esp), %edi
  165. pushl %edi /* old ESP */
  166. pushl %ebx
  167. pushl %edx
  168. pushl %ecx
  169. pushl %eax
  170. /* Call GDB stub exception handler */
  171. pushl %esp
  172. pushl (IH_OFFSET_SIGNO + 4)(%esp)
  173. call gdbmach_handler
  174. addl $8, %esp
  175. /* Restore CPU state from GDB register snapshot */
  176. popl %eax
  177. popl %ecx
  178. popl %edx
  179. popl %ebx
  180. addl $4, %esp /* Changing ESP currently not supported */
  181. popl %ebp
  182. popl %esi
  183. popl %edi
  184. popl IH_OFFSET_FLUX_OLD_EIP(%esp)
  185. popl IH_OFFSET_FLUX_OLD_EFLAGS(%esp)
  186. popl IH_OFFSET_FLUX_OLD_CS(%esp)
  187. popl %ss
  188. popl %ds
  189. popl %es
  190. popl %fs
  191. popl %gs
  192. addl $4, %esp /* drop signo */
  193. iret