interrupt.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. #define _INTERRUPT_C_
  2. #include <asm/port_io.h>
  3. #include <kernel/hw/keyboard.h>
  4. #include <kernel/hw/timer.h>
  5. #include <kernel/interrupt.h>
  6. #include <kernel/mem.h>
  7. #include <kernel/mm.hpp>
  8. #include <kernel/stdio.h>
  9. #include <kernel/tty.h>
  10. #include <kernel/vga.h>
  11. #include <kernel_main.h>
  12. static struct IDT_entry IDT[256];
  13. void init_idt()
  14. {
  15. asm_cli();
  16. memset(IDT, 0x00, sizeof(IDT));
  17. // invalid opcode
  18. SET_IDT_ENTRY_FN(6, int6, 0x08);
  19. // double fault
  20. SET_IDT_ENTRY_FN(8, int8, 0x08);
  21. // general protection
  22. SET_IDT_ENTRY_FN(13, int13, 0x08);
  23. // page fault
  24. SET_IDT_ENTRY_FN(14, int14, 0x08);
  25. uint16_t idt_descriptor[3];
  26. idt_descriptor[0] = sizeof(struct IDT_entry) * 256;
  27. *((uint32_t*)(idt_descriptor + 1)) = (ptr_t)IDT;
  28. asm_load_idt(idt_descriptor, 0);
  29. }
  30. void init_pic(void)
  31. {
  32. asm_cli();
  33. asm_outb(PORT_PIC1_COMMAND, 0x11); // edge trigger mode
  34. asm_outb(PORT_PIC1_DATA, 0x20); // start from int 0x20
  35. asm_outb(PORT_PIC1_DATA, 0x04); // PIC1 is connected to IRQ2 (1 << 2)
  36. asm_outb(PORT_PIC1_DATA, 0x01); // no buffer mode
  37. asm_outb(PORT_PIC2_COMMAND, 0x11); // edge trigger mode
  38. asm_outb(PORT_PIC2_DATA, 0x28); // start from int 0x28
  39. asm_outb(PORT_PIC2_DATA, 0x02); // connected to IRQ2
  40. asm_outb(PORT_PIC2_DATA, 0x01); // no buffer mode
  41. // allow all the interrupts
  42. asm_outb(PORT_PIC1_DATA, 0x00);
  43. asm_outb(PORT_PIC2_DATA, 0x00);
  44. // 0x08 stands for kernel code segment
  45. SET_UP_IRQ(0, 0x08);
  46. SET_UP_IRQ(1, 0x08);
  47. SET_UP_IRQ(2, 0x08);
  48. SET_UP_IRQ(3, 0x08);
  49. SET_UP_IRQ(4, 0x08);
  50. SET_UP_IRQ(5, 0x08);
  51. SET_UP_IRQ(6, 0x08);
  52. SET_UP_IRQ(7, 0x08);
  53. SET_UP_IRQ(8, 0x08);
  54. SET_UP_IRQ(9, 0x08);
  55. SET_UP_IRQ(10, 0x08);
  56. SET_UP_IRQ(11, 0x08);
  57. SET_UP_IRQ(12, 0x08);
  58. SET_UP_IRQ(13, 0x08);
  59. SET_UP_IRQ(14, 0x08);
  60. SET_UP_IRQ(15, 0x08);
  61. asm_sti();
  62. }
  63. extern "C" void int6_handler(
  64. struct regs_32 s_regs,
  65. uint32_t error_code,
  66. ptr_t eip,
  67. uint16_t cs)
  68. {
  69. char buf[512];
  70. tty_print(console, "---- INVALID OPCODE ----\n");
  71. snprintf(
  72. buf, 512,
  73. "eax: %x, ebx: %x, ecx: %x, edx: %x\n"
  74. "esp: %x, ebp: %x, esi: %x, edi: %x\n"
  75. "eip: %x, cs: %x, error_code: %x \n",
  76. s_regs.eax, s_regs.ebx, s_regs.ecx,
  77. s_regs.edx, s_regs.esp, s_regs.ebp,
  78. s_regs.esi, s_regs.edi, eip,
  79. cs, error_code);
  80. tty_print(console, buf);
  81. tty_print(console, "---- HALTING SYSTEM ----");
  82. asm_cli();
  83. asm_hlt();
  84. }
  85. // general protection
  86. extern "C" void int13_handler(
  87. struct regs_32 s_regs,
  88. uint32_t error_code,
  89. ptr_t eip,
  90. uint16_t cs,
  91. uint32_t eflags)
  92. {
  93. char buf[512];
  94. tty_print(console, "---- SEGMENTATION FAULT ----\n");
  95. snprintf(
  96. buf, 512,
  97. "eax: %x, ebx: %x, ecx: %x, edx: %x\n"
  98. "esp: %x, ebp: %x, esi: %x, edi: %x\n"
  99. "eip: %x, cs: %x, error_code: %x \n"
  100. "eflags: %x \n",
  101. s_regs.eax, s_regs.ebx, s_regs.ecx,
  102. s_regs.edx, s_regs.esp, s_regs.ebp,
  103. s_regs.esi, s_regs.edi, eip,
  104. cs, error_code, eflags);
  105. tty_print(console, buf);
  106. tty_print(console, "---- HALTING SYSTEM ----");
  107. asm_cli();
  108. asm_hlt();
  109. }
  110. // TODO: remove debug variable
  111. static size_t page_fault_times;
  112. struct PACKED int14_data {
  113. linr_ptr_t l_addr;
  114. struct regs_32 s_regs;
  115. struct page_fault_error_code error_code;
  116. void* v_eip;
  117. uint16_t cs;
  118. uint32_t eflags;
  119. };
  120. // page fault
  121. extern "C" void int14_handler(struct int14_data* d)
  122. {
  123. char buf[512];
  124. // TODO: remove debug variable
  125. ++page_fault_times;
  126. // not present page, possibly mapped but not loaded
  127. // or invalid address or just invalid address
  128. // TODO: mmapping and swapping
  129. if (d->error_code.present == 0) {
  130. goto kill;
  131. }
  132. // kernel code
  133. if (d->cs == KERNEL_CODE_SEGMENT) {
  134. if (is_l_ptr_valid(kernel_mms, d->l_addr) != GB_OK) {
  135. goto kill;
  136. }
  137. struct page* page = find_page_by_l_ptr(kernel_mms, d->l_addr);
  138. // copy on write
  139. if (d->error_code.write == 1 && page->attr.cow == 1) {
  140. page_directory_entry* pde = mms_get_pd(kernel_mms) + linr_addr_to_pd_i(d->l_addr);
  141. page_table_entry* pte = (page_table_entry*)p_ptr_to_v_ptr(page_to_phys_addr(pde->in.pt_page));
  142. pte += linr_addr_to_pt_i(d->l_addr);
  143. // if it is a dying page
  144. if (*page->ref_count == 1) {
  145. page->attr.cow = 0;
  146. pte->in.a = 0;
  147. pte->in.rw = 1;
  148. return;
  149. }
  150. // duplicate the page
  151. page_t new_page = alloc_raw_page();
  152. void* new_page_data = p_ptr_to_v_ptr(page_to_phys_addr(new_page));
  153. memcpy(new_page_data, p_ptr_to_v_ptr(page_to_phys_addr(page->phys_page_id)), PAGE_SIZE);
  154. pte->in.page = new_page;
  155. pte->in.rw = 1;
  156. pte->in.a = 0;
  157. --*page->ref_count;
  158. page->ref_count = (size_t*)k_malloc(sizeof(size_t));
  159. *page->ref_count = 1;
  160. page->attr.cow = 0;
  161. page->phys_page_id = new_page;
  162. return;
  163. }
  164. }
  165. kill:
  166. snprintf(
  167. buf, 512,
  168. "killed: segmentation fault (eip: %x, cr2: %x, error_code: %x)", d->v_eip, d->l_addr, d->error_code);
  169. tty_print(console, buf);
  170. MAKE_BREAK_POINT();
  171. asm_cli();
  172. asm_hlt();
  173. }
  174. struct PACKED irq0_data {
  175. struct regs_32 s_regs;
  176. void* v_eip;
  177. uint16_t cs;
  178. uint32_t eflags;
  179. uint32_t esp;
  180. uint16_t ss;
  181. };
  182. extern "C" void irq0_handler(struct irq0_data* d)
  183. {
  184. inc_tick();
  185. asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
  186. }
  187. // keyboard interrupt
  188. extern "C" void irq1_handler(void)
  189. {
  190. asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
  191. handle_keyboard_interrupt();
  192. }
  193. extern "C" void irq2_handler(void)
  194. {
  195. asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
  196. }
  197. extern "C" void irq3_handler(void)
  198. {
  199. asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
  200. }
  201. extern "C" void irq4_handler(void)
  202. {
  203. asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
  204. }
  205. extern "C" void irq5_handler(void)
  206. {
  207. asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
  208. }
  209. extern "C" void irq6_handler(void)
  210. {
  211. asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
  212. }
  213. extern "C" void irq7_handler(void)
  214. {
  215. asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
  216. }
  217. extern "C" void irq8_handler(void)
  218. {
  219. asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
  220. asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
  221. }
  222. extern "C" void irq9_handler(void)
  223. {
  224. asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
  225. asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
  226. }
  227. extern "C" void irq10_handler(void)
  228. {
  229. asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
  230. asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
  231. }
  232. extern "C" void irq11_handler(void)
  233. {
  234. asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
  235. asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
  236. }
  237. extern "C" void irq12_handler(void)
  238. {
  239. asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
  240. asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
  241. }
  242. extern "C" void irq13_handler(void)
  243. {
  244. asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
  245. asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
  246. }
  247. extern "C" void irq14_handler(void)
  248. {
  249. asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
  250. asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
  251. }
  252. extern "C" void irq15_handler(void)
  253. {
  254. asm_outb(PORT_PIC2_COMMAND, PIC_EOI);
  255. asm_outb(PORT_PIC1_COMMAND, PIC_EOI);
  256. }