gate.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /**
  2. * @file gate.h
  3. * @author longjin
  4. * @brief 门定义
  5. * @date 2022-01-24
  6. *
  7. */
  8. #ifndef __GATE_H__
  9. #define __GATE_H__
  10. #include <common/kprint.h>
  11. #include <mm/mm.h>
  12. #pragma GCC push_options
  13. #pragma GCC optimize("O0")
  14. //描述符表的结构体
  15. struct desc_struct
  16. {
  17. unsigned char x[8];
  18. };
  19. //门的结构体
  20. struct gate_struct
  21. {
  22. unsigned char x[16];
  23. };
  24. extern struct desc_struct GDT_Table[]; // GDT_Table是head.S中的GDT_Table
  25. extern struct gate_struct IDT_Table[]; // IDT_Table是head.S中的IDT_Table
  26. //extern unsigned int TSS64_Table[26];
  27. struct gdtr
  28. {
  29. uint16_t size;
  30. uint64_t gdt_vaddr;
  31. }__attribute__((packed));
  32. struct idtr
  33. {
  34. uint16_t size;
  35. uint64_t idt_vaddr;
  36. }__attribute__((packed));
  37. /**
  38. * @brief 初始化中段描述符表内的门描述符(每个16B)
  39. * @param gate_selector_addr IDT表项的地址
  40. * @param attr P、DPL、TYPE的属性
  41. * @param ist 中断栈表号
  42. * @param code_addr 指向中断服务程序的指针的地址
  43. */
  44. void set_gate(ul *gate_selector_addr, ul attr, unsigned char ist, ul *code_addr)
  45. {
  46. ul __d0 = 0, __d1 = 0;
  47. ul tmp_code_addr = *code_addr;
  48. __d0 = attr << 40; //设置P、DPL、Type
  49. __d0 |= ((ul)(ist) << 32); // 设置ist
  50. __d0 |= 8 << 16; //设置段选择子为0x1000
  51. __d0 |= (0xffff & tmp_code_addr); //设置段内偏移的[15:00]
  52. tmp_code_addr >>= 16;
  53. __d0 |= (0xffff & tmp_code_addr) << 48; // 设置段内偏移[31:16]
  54. tmp_code_addr >>= 16;
  55. __d1 = (0xffffffff & tmp_code_addr); //设置段内偏移[63:32]
  56. *gate_selector_addr = __d0;
  57. *(gate_selector_addr + 1) = __d1;
  58. }
  59. #define _set_gate(gate_selector_addr, attr, ist, code_addr) \
  60. do \
  61. { \
  62. unsigned long __d0, __d1; \
  63. __asm__ __volatile__("movw %%dx, %%ax \n\t" \
  64. "andq $0x7, %%rcx \n\t" \
  65. "addq %4, %%rcx \n\t" \
  66. "shlq $32, %%rcx \n\t" \
  67. "addq %%rcx, %%rax \n\t" \
  68. "xorq %%rcx, %%rcx \n\t" \
  69. "movl %%edx, %%ecx \n\t" \
  70. "shrq $16, %%rcx \n\t" \
  71. "shlq $48, %%rcx \n\t" \
  72. "addq %%rcx, %%rax \n\t" \
  73. "movq %%rax, %0 \n\t" \
  74. "shrq $32, %%rdx \n\t" \
  75. "movq %%rdx, %1 \n\t" \
  76. : "=m"(*((unsigned long *)(gate_selector_addr))), \
  77. "=m"(*(1 + (unsigned long *)(gate_selector_addr))), "=&a"(__d0), "=&d"(__d1) \
  78. : "i"(attr << 8), \
  79. "3"((unsigned long *)(code_addr)), "2"(0x8 << 16), "c"(ist) \
  80. : "memory"); \
  81. } while (0)
  82. void set_tss_descriptor(unsigned int n, void *addr)
  83. {
  84. unsigned long limit = 103;
  85. *(unsigned long *)(phys_2_virt(GDT_Table + n)) = (limit & 0xffff) | (((unsigned long)addr & 0xffff) << 16) | ((((unsigned long)addr >> 16) & 0xff) << 32) | ((unsigned long)0x89 << 40) | ((limit >> 16 & 0xf) << 48) | (((unsigned long)addr >> 24 & 0xff) << 56); /////89 is attribute
  86. *(unsigned long *)(phys_2_virt(GDT_Table + n + 1)) = (((unsigned long)addr >> 32) & 0xffffffff) | 0;
  87. }
  88. /**
  89. * @brief 加载任务状态段寄存器
  90. * @param n TSS基地址在GDT中的第几项
  91. * 左移3位的原因是GDT每项占8字节
  92. */
  93. #define load_TR(n) \
  94. do \
  95. { \
  96. __asm__ __volatile__("ltr %%ax" ::"a"((n) << 3)); \
  97. } while (0)
  98. /**
  99. * @brief 设置中断门
  100. *
  101. * @param n 中断号
  102. * @param ist ist
  103. * @param addr 服务程序的地址
  104. */
  105. void set_intr_gate(unsigned int n, unsigned char ist, void *addr)
  106. {
  107. _set_gate(phys_2_virt(IDT_Table + n), 0x8E, ist, addr); // p=1,DPL=0, type=E
  108. //set_gate((ul *)phys_2_virt(IDT_Table + n), 0x8E, ist, (ul *)(addr)); // p=1,DPL=0, type=E
  109. }
  110. /**
  111. * @brief 设置64位,DPL=0的陷阱门
  112. *
  113. * @param n 中断号
  114. * @param ist ist
  115. * @param addr 服务程序的地址
  116. */
  117. void set_trap_gate(unsigned int n, unsigned char ist, void *addr)
  118. {
  119. // kdebug("addr=%#018lx", (ul)(addr));
  120. //set_gate((ul *)phys_2_virt(IDT_Table + n), 0x8F, ist, (ul *)(addr)); // p=1,DPL=0, type=F
  121. _set_gate(phys_2_virt(IDT_Table + n), 0x8F, ist, addr); // p=1,DPL=0, type=F
  122. }
  123. /**
  124. * @brief 设置64位,DPL=3的陷阱门
  125. *
  126. * @param n 中断号
  127. * @param ist ist
  128. * @param addr 服务程序的地址
  129. */
  130. void set_system_trap_gate(unsigned int n, unsigned char ist, void *addr)
  131. {
  132. // kdebug("addr=%#018lx", (ul)(addr));
  133. //set_gate((ul *)phys_2_virt(IDT_Table + n), 0xEF, ist, (ul *)(addr)); // p=1,DPL=3, type=F
  134. _set_gate(phys_2_virt(IDT_Table + n), 0xEF, ist, addr); // p=1,DPL=3, type=F
  135. }
  136. static inline void set_system_intr_gate(unsigned int n,unsigned char ist,void * addr) //int3
  137. {
  138. _set_gate(phys_2_virt(IDT_Table + n) , 0xEE , ist , addr); //P,DPL=3,TYPE=E
  139. }
  140. /**
  141. * @brief 初始化TSS表的内容
  142. *
  143. */
  144. void set_tss64(unsigned int *Table, unsigned long rsp0, unsigned long rsp1, unsigned long rsp2, unsigned long ist1, unsigned long ist2, unsigned long ist3,
  145. unsigned long ist4, unsigned long ist5, unsigned long ist6, unsigned long ist7)
  146. {
  147. *(unsigned long *)(Table + 1) = rsp0;
  148. *(unsigned long *)(Table + 3) = rsp1;
  149. *(unsigned long *)(Table + 5) = rsp2;
  150. *(unsigned long *)(Table + 9) = ist1;
  151. *(unsigned long *)(Table + 11) = ist2;
  152. *(unsigned long *)(Table + 13) = ist3;
  153. *(unsigned long *)(Table + 15) = ist4;
  154. *(unsigned long *)(Table + 17) = ist5;
  155. *(unsigned long *)(Table + 19) = ist6;
  156. *(unsigned long *)(Table + 21) = ist7;
  157. }
  158. #endif
  159. #pragma GCC pop_options