1
0

isr.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. #include "libcflat.h"
  2. #include "isr.h"
  3. #include "vm.h"
  4. #include "desc.h"
  5. extern char isr_entry_point[];
  6. asm (
  7. "isr_entry_point: \n"
  8. #ifdef __x86_64__
  9. "push %r15 \n\t"
  10. "push %r14 \n\t"
  11. "push %r13 \n\t"
  12. "push %r12 \n\t"
  13. "push %r11 \n\t"
  14. "push %r10 \n\t"
  15. "push %r9 \n\t"
  16. "push %r8 \n\t"
  17. #endif
  18. "push %"R "di \n\t"
  19. "push %"R "si \n\t"
  20. "push %"R "bp \n\t"
  21. "push %"R "sp \n\t"
  22. "push %"R "bx \n\t"
  23. "push %"R "dx \n\t"
  24. "push %"R "cx \n\t"
  25. "push %"R "ax \n\t"
  26. #ifdef __x86_64__
  27. "mov %rsp, %rdi \n\t"
  28. "callq *8*16(%rsp) \n\t"
  29. #else
  30. "push %esp \n\t"
  31. "calll *4+4*8(%esp) \n\t"
  32. "add $4, %esp \n\t"
  33. #endif
  34. "pop %"R "ax \n\t"
  35. "pop %"R "cx \n\t"
  36. "pop %"R "dx \n\t"
  37. "pop %"R "bx \n\t"
  38. "pop %"R "bp \n\t"
  39. "pop %"R "bp \n\t"
  40. "pop %"R "si \n\t"
  41. "pop %"R "di \n\t"
  42. #ifdef __x86_64__
  43. "pop %r8 \n\t"
  44. "pop %r9 \n\t"
  45. "pop %r10 \n\t"
  46. "pop %r11 \n\t"
  47. "pop %r12 \n\t"
  48. "pop %r13 \n\t"
  49. "pop %r14 \n\t"
  50. "pop %r15 \n\t"
  51. #endif
  52. ".globl isr_iret_ip\n\t"
  53. #ifdef __x86_64__
  54. "add $8, %rsp \n\t"
  55. "isr_iret_ip: \n\t"
  56. "iretq \n\t"
  57. #else
  58. "add $4, %esp \n\t"
  59. "isr_iret_ip: \n\t"
  60. "iretl \n\t"
  61. #endif
  62. );
  63. void handle_irq(unsigned vec, void (*func)(isr_regs_t *regs))
  64. {
  65. u8 *thunk = vmalloc(50);
  66. set_idt_entry(vec, thunk, 0);
  67. #ifdef __x86_64__
  68. /* sub $8, %rsp */
  69. *thunk++ = 0x48; *thunk++ = 0x83; *thunk++ = 0xec; *thunk++ = 0x08;
  70. /* mov $func_low, %(rsp) */
  71. *thunk++ = 0xc7; *thunk++ = 0x04; *thunk++ = 0x24;
  72. *(u32 *)thunk = (ulong)func; thunk += 4;
  73. /* mov $func_high, %(rsp+4) */
  74. *thunk++ = 0xc7; *thunk++ = 0x44; *thunk++ = 0x24; *thunk++ = 0x04;
  75. *(u32 *)thunk = (ulong)func >> 32; thunk += 4;
  76. /* jmp isr_entry_point */
  77. *thunk ++ = 0xe9;
  78. *(u32 *)thunk = (ulong)isr_entry_point - (ulong)(thunk + 4);
  79. #else
  80. /* push $func */
  81. *thunk++ = 0x68;
  82. *(u32 *)thunk = (ulong)func; thunk += 4;
  83. /* jmp isr_entry_point */
  84. *thunk++ = 0xe9;
  85. *(u32 *)thunk = (ulong)isr_entry_point - (ulong)(thunk + 4);
  86. #endif
  87. }
  88. void handle_external_interrupt(int vector)
  89. {
  90. idt_entry_t *idt = &boot_idt[vector];
  91. unsigned long entry =
  92. idt->offset0 | ((unsigned long)idt->offset1 << 16);
  93. #ifdef __x86_64__
  94. unsigned long tmp;
  95. entry |= ((unsigned long)idt->offset2 << 32);
  96. #endif
  97. asm volatile(
  98. #ifdef __x86_64__
  99. "mov %%rsp, %[sp]\n\t"
  100. "and $0xfffffffffffffff0, %%rsp\n\t"
  101. "push $%c[ss]\n\t"
  102. "push %[sp]\n\t"
  103. #endif
  104. "pushf\n\t"
  105. "orl $0x200, (%%"R "sp)\n\t"
  106. "push $%c[cs]\n\t"
  107. "call *%[entry]\n\t"
  108. :
  109. #ifdef __x86_64__
  110. [sp]"=&r"(tmp)
  111. #endif
  112. :
  113. [entry]"r"(entry),
  114. [ss]"i"(KERNEL_DS),
  115. [cs]"i"(KERNEL_CS)
  116. );
  117. }