gate.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-07-16 JasonHu first version
  9. */
  10. #include "gate.h"
  11. #include "segment.h"
  12. #include "interrupt.h"
  13. #include <rtdef.h>
  14. struct rt_hw_gate
  15. {
  16. rt_uint16_t offset_low, selector;
  17. rt_uint8_t datacount;
  18. rt_uint8_t attributes; /* P(1) DPL(2) DT(1) TYPE(4) */
  19. rt_uint16_t offset_high;
  20. };
  21. typedef struct rt_hw_gate rt_hw_gate_t;
  22. typedef void (*rt_hw_intr_entry_t)(void);
  23. extern void rt_hw_intr_entry0x00(void);
  24. extern void rt_hw_intr_entry0x01(void);
  25. extern void rt_hw_intr_entry0x02(void);
  26. extern void rt_hw_intr_entry0x03(void);
  27. extern void rt_hw_intr_entry0x04(void);
  28. extern void rt_hw_intr_entry0x05(void);
  29. extern void rt_hw_intr_entry0x06(void);
  30. extern void rt_hw_intr_entry0x07(void);
  31. extern void rt_hw_intr_entry0x08(void);
  32. extern void rt_hw_intr_entry0x09(void);
  33. extern void rt_hw_intr_entry0x0a(void);
  34. extern void rt_hw_intr_entry0x0b(void);
  35. extern void rt_hw_intr_entry0x0c(void);
  36. extern void rt_hw_intr_entry0x0d(void);
  37. extern void rt_hw_intr_entry0x0e(void);
  38. extern void rt_hw_intr_entry0x0f(void);
  39. extern void rt_hw_intr_entry0x10(void);
  40. extern void rt_hw_intr_entry0x11(void);
  41. extern void rt_hw_intr_entry0x12(void);
  42. extern void rt_hw_intr_entry0x13(void);
  43. extern void rt_hw_intr_entry0x14(void);
  44. extern void rt_hw_intr_entry0x15(void);
  45. extern void rt_hw_intr_entry0x16(void);
  46. extern void rt_hw_intr_entry0x17(void);
  47. extern void rt_hw_intr_entry0x18(void);
  48. extern void rt_hw_intr_entry0x19(void);
  49. extern void rt_hw_intr_entry0x1a(void);
  50. extern void rt_hw_intr_entry0x1b(void);
  51. extern void rt_hw_intr_entry0x1c(void);
  52. extern void rt_hw_intr_entry0x1d(void);
  53. extern void rt_hw_intr_entry0x1e(void);
  54. extern void rt_hw_intr_entry0x1f(void);
  55. extern void rt_hw_intr_entry0x20(void);
  56. extern void rt_hw_intr_entry0x21(void);
  57. extern void rt_hw_intr_entry0x22(void);
  58. extern void rt_hw_intr_entry0x23(void);
  59. extern void rt_hw_intr_entry0x24(void);
  60. extern void rt_hw_intr_entry0x25(void);
  61. extern void rt_hw_intr_entry0x26(void);
  62. extern void rt_hw_intr_entry0x27(void);
  63. extern void rt_hw_intr_entry0x28(void);
  64. extern void rt_hw_intr_entry0x29(void);
  65. extern void rt_hw_intr_entry0x2a(void);
  66. extern void rt_hw_intr_entry0x2b(void);
  67. extern void rt_hw_intr_entry0x2c(void);
  68. extern void rt_hw_intr_entry0x2d(void);
  69. extern void rt_hw_intr_entry0x2e(void);
  70. extern void rt_hw_intr_entry0x2f(void);
  71. static void gate_set(rt_hw_gate_t *gate, rt_hw_intr_entry_t handler,
  72. rt_uint32_t selector, rt_uint32_t attributes, rt_uint8_t privilege)
  73. {
  74. rt_ubase_t offset = (rt_ubase_t) handler;
  75. gate->offset_low = offset & 0xffff;
  76. gate->selector = selector;
  77. gate->attributes = attributes | (privilege << 5);
  78. gate->datacount = 0;
  79. gate->offset_high = (offset >> 16) & 0xffff;
  80. }
  81. void rt_hw_gate_init(void)
  82. {
  83. rt_hw_gate_t *idt = (rt_hw_gate_t *) (IDT_VADDR);
  84. /*
  85. 将中断描述符表的内容设置成内核下的中断门
  86. 并把汇编部分的中断处理函数传入进去
  87. */
  88. int i;
  89. for (i = 0; i < MAX_IDT_NR; i++) {
  90. gate_set(IDT_OFF2PTR(idt, i), 0, 0, 0, 0);
  91. }
  92. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE), rt_hw_intr_entry0x00, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  93. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+1), rt_hw_intr_entry0x01, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  94. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+2), rt_hw_intr_entry0x02, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  95. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+3), rt_hw_intr_entry0x03, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  96. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+4), rt_hw_intr_entry0x04, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  97. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+5), rt_hw_intr_entry0x05, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  98. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+6), rt_hw_intr_entry0x06, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  99. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+7), rt_hw_intr_entry0x07, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  100. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+8), rt_hw_intr_entry0x08, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  101. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+9), rt_hw_intr_entry0x09, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  102. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+10), rt_hw_intr_entry0x0a, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  103. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+11), rt_hw_intr_entry0x0b, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  104. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+12), rt_hw_intr_entry0x0c, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  105. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+13), rt_hw_intr_entry0x0d, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  106. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+14), rt_hw_intr_entry0x0e, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  107. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+15), rt_hw_intr_entry0x0f, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  108. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+16), rt_hw_intr_entry0x10, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  109. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+17), rt_hw_intr_entry0x11, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  110. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+18), rt_hw_intr_entry0x12, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  111. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+19), rt_hw_intr_entry0x13, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  112. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+20), rt_hw_intr_entry0x14, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  113. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+21), rt_hw_intr_entry0x15, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  114. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+22), rt_hw_intr_entry0x16, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  115. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+23), rt_hw_intr_entry0x17, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  116. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+24), rt_hw_intr_entry0x18, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  117. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+25), rt_hw_intr_entry0x19, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  118. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+26), rt_hw_intr_entry0x1a, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  119. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+27), rt_hw_intr_entry0x1b, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  120. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+28), rt_hw_intr_entry0x1c, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  121. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+29), rt_hw_intr_entry0x1d, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  122. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+30), rt_hw_intr_entry0x1e, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  123. gate_set(IDT_OFF2PTR(idt, EXCEPTION_INTR_BASE+31), rt_hw_intr_entry0x1f, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  124. gate_set(IDT_OFF2PTR(idt, IRQ_INTR_BASE), rt_hw_intr_entry0x20, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  125. gate_set(IDT_OFF2PTR(idt, IRQ_INTR_BASE+1), rt_hw_intr_entry0x21, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  126. gate_set(IDT_OFF2PTR(idt, IRQ_INTR_BASE+2), rt_hw_intr_entry0x22, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  127. gate_set(IDT_OFF2PTR(idt, IRQ_INTR_BASE+3), rt_hw_intr_entry0x23, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  128. gate_set(IDT_OFF2PTR(idt, IRQ_INTR_BASE+4), rt_hw_intr_entry0x24, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  129. gate_set(IDT_OFF2PTR(idt, IRQ_INTR_BASE+5), rt_hw_intr_entry0x25, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  130. gate_set(IDT_OFF2PTR(idt, IRQ_INTR_BASE+6), rt_hw_intr_entry0x26, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  131. gate_set(IDT_OFF2PTR(idt, IRQ_INTR_BASE+7), rt_hw_intr_entry0x27, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  132. gate_set(IDT_OFF2PTR(idt, IRQ_INTR_BASE+8), rt_hw_intr_entry0x28, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  133. gate_set(IDT_OFF2PTR(idt, IRQ_INTR_BASE+9), rt_hw_intr_entry0x29, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  134. gate_set(IDT_OFF2PTR(idt, IRQ_INTR_BASE+10), rt_hw_intr_entry0x2a, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  135. gate_set(IDT_OFF2PTR(idt, IRQ_INTR_BASE+11), rt_hw_intr_entry0x2b, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  136. gate_set(IDT_OFF2PTR(idt, IRQ_INTR_BASE+12), rt_hw_intr_entry0x2c, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  137. gate_set(IDT_OFF2PTR(idt, IRQ_INTR_BASE+13), rt_hw_intr_entry0x2d, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  138. gate_set(IDT_OFF2PTR(idt, IRQ_INTR_BASE+14), rt_hw_intr_entry0x2e, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  139. gate_set(IDT_OFF2PTR(idt, IRQ_INTR_BASE+15), rt_hw_intr_entry0x2f, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL0);
  140. /* 系统调用处理中断 */
  141. #ifdef RT_USING_USERSPACE
  142. extern void hw_syscall_entry(void);
  143. gate_set(IDT_OFF2PTR(idt, SYSCALL_INTR_BASE), hw_syscall_entry, KERNEL_CODE_SEL, DA_386_INTR_GATE, DA_GATE_DPL3);
  144. #endif /* RT_USING_USERSPACE */
  145. extern void load_new_idt(rt_ubase_t size, rt_ubase_t idtr);
  146. load_new_idt(IDT_LIMIT, IDT_VADDR);
  147. }