gate.h 6.7 KB

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