apic.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. #include "apic.h"
  2. #include "../../../common/kprint.h"
  3. #include "../../../common/printk.h"
  4. #include "../../../common/cpu.h"
  5. #include "../../../common/glib.h"
  6. #include "../../../exception/gate.h"
  7. #include "../../acpi/acpi.h"
  8. // 导出定义在irq.c中的中段门表
  9. extern void (*interrupt_table[24])(void);
  10. bool flag_support_apic = false;
  11. bool flag_support_x2apic = false;
  12. uint local_apic_version;
  13. uint local_apic_max_LVT_entries;
  14. static struct acpi_Multiple_APIC_Description_Table_t *madt;
  15. /**
  16. * @brief 初始化io_apic
  17. *
  18. */
  19. void apic_io_apic_init()
  20. {
  21. // 初始化中断门, 中断使用第二个ist
  22. for (int i = 32; i <= 55; ++i)
  23. set_intr_gate(i, 2, interrupt_table[i - 32]);
  24. // 屏蔽类8259A芯片
  25. io_out8(0x21, 0xff);
  26. io_out8(0xa1, 0xff);
  27. kdebug("8259A Masked.");
  28. ul madt_addr;
  29. kdebug("madt_addr = %#018lx", (ul)madt_addr);
  30. acpi_iter_SDT(acpi_get_MADT, &madt_addr);
  31. madt = (struct acpi_Multiple_APIC_Description_Table_t *)madt_addr;
  32. kdebug("MADT->local intr controller addr=%#018lx", madt->Local_Interrupt_Controller_Address);
  33. kdebug("MADT->length= %d bytes", madt->header.Length);
  34. void *ent = (void *)(madt_addr) + sizeof(struct acpi_Multiple_APIC_Description_Table_t);
  35. struct apic_Interrupt_Controller_Structure_header_t *header;
  36. for (int i = 0; i < 17; ++i)
  37. {
  38. header = (struct apic_Interrupt_Controller_Structure_header_t *)ent;
  39. kdebug("[ %d ] type=%d, length=%d", i, header->type, header->length);
  40. if (header->type == 1)
  41. {
  42. struct acpi_IO_APIC_Structure_t *t = (struct acpi_IO_APIC_Structure_t *)ent;
  43. kdebug("IO apic addr = %#018lx", t->IO_APIC_Address);
  44. }
  45. ent += header->length;
  46. }
  47. apic_local_apic_init();
  48. sti();
  49. }
  50. /**
  51. * @brief 初始化local apic
  52. *
  53. */
  54. void apic_local_apic_init()
  55. {
  56. uint a, b, c, d;
  57. cpu_cpuid(1, 0, &a, &b, &c, &d);
  58. kdebug("CPUID 0x01, eax:%#010lx, ebx:%#010lx, ecx:%#010lx, edx:%#010lx", a, b, c, d);
  59. // 判断是否支持APIC和xAPIC
  60. if ((1 << 9) & d)
  61. {
  62. flag_support_apic = true;
  63. kdebug("This computer support APIC&xAPIC");
  64. }
  65. else
  66. {
  67. flag_support_apic = false;
  68. kerror("This computer does not support APIC&xAPIC");
  69. while (1)
  70. ;
  71. }
  72. // 判断是否支持x2APIC
  73. if ((1 << 21) & c)
  74. {
  75. flag_support_x2apic = true;
  76. kdebug("This computer support x2APIC");
  77. }
  78. else
  79. {
  80. kerror("This computer does not support x2APIC");
  81. }
  82. uint eax, edx;
  83. // 启用xAPIC 和x2APIC
  84. __asm__ __volatile__("movq $0x1b, %%rcx \n\t" // 读取IA32_APIC_BASE寄存器
  85. "rdmsr \n\t"
  86. "bts $10, %%rax \n\t"
  87. "bts $11, %%rax \n\t"
  88. "wrmsr \n\t"
  89. "movq $0x1b, %%rcx \n\t"
  90. "rdmsr \n\t"
  91. : "=a"(eax), "=d"(edx)::"memory");
  92. kdebug("After enable xAPIC and x2APIC: edx=%#010x, eax=%#010x", edx, eax);
  93. // 检测是否成功启用xAPIC和x2APIC
  94. if (eax & 0xc00)
  95. kinfo("xAPIC & x2APIC enabled!");
  96. // 设置SVR寄存器,开启local APIC、禁止EOI广播
  97. __asm__ __volatile__("movq 0x80f, %%rcx \n\t"
  98. "rdmsr \n\t"
  99. "bts $8, %%rax \n\t"
  100. "bts $12, %%rax \n\t"
  101. "movq 0x80f, %%rcx \n\t"
  102. "wrmsr \n\t"
  103. "movq $0x80f , %%rcx \n\t"
  104. "rdmsr \n\t"
  105. : "=a"(eax), "=d"(edx)::"memory", "rcx");
  106. /*
  107. //enable SVR[8]
  108. __asm__ __volatile__( "movq $0x80f, %%rcx \n\t"
  109. "rdmsr \n\t"
  110. "bts $8, %%rax \n\t"
  111. "bts $12,%%rax\n\t"
  112. "wrmsr \n\t"
  113. "movq $0x80f, %%rcx \n\t"
  114. "rdmsr \n\t"
  115. :"=a"(eax),"=d"(edx)
  116. :
  117. :"memory");
  118. */
  119. kdebug("After setting SVR: edx=%#010x, eax=%#010x", edx, eax);
  120. if (eax & 0x100)
  121. kinfo("APIC Software Enabled.");
  122. if (eax & 0x1000)
  123. kinfo("EOI-Broadcast Suppression Enabled.");
  124. // 获取Local APIC的基础信息 (参见英特尔开发手册Vol3A 10-39)
  125. // Table 10-6. Local APIC Register Address Map Supported by x2APIC
  126. // 获取 Local APIC ID
  127. // 0x802处是x2APIC ID 位宽32bits 的 Local APIC ID register
  128. __asm__ __volatile__("movq $0x802, %%rcx \n\t"
  129. "rdmsr \n\t"
  130. : "=a"(eax), "=d"(edx)::"memory");
  131. kdebug("get Local APIC ID: edx=%#010x, eax=%#010x", edx, eax);
  132. // 获取Local APIC Version
  133. // 0x803处是 Local APIC Version register
  134. __asm__ __volatile__("movq $0x803, %%rcx \n\t"
  135. "rdmsr \n\t"
  136. : "=a"(eax), "=d"(edx)::"memory");
  137. local_apic_max_LVT_entries = ((eax >> 16) & 0xff) + 1;
  138. local_apic_version = eax & 0xff;
  139. kdebug("local APIC Version:%#010x,Max LVT Entry:%#010x,SVR(Suppress EOI Broadcast):%#04x\t", local_apic_version, local_apic_max_LVT_entries, (eax >> 24) & 0x1);
  140. if ((eax & 0xff) < 0x10)
  141. {
  142. kdebug("82489DX discrete APIC");
  143. }
  144. else if (((eax & 0xff) >= 0x10) && ((eax & 0xff) <= 0x15))
  145. kdebug("Integrated APIC.");
  146. // 由于尚未配置LVT对应的处理程序,因此先屏蔽所有的LVT
  147. __asm__ __volatile__(
  148. "movq $0x82f, %%rcx \n\t" // CMCI
  149. "wrmsr \n\t"
  150. "movq $0x832, %%rcx \n\t" // Timer
  151. "wrmsr \n\t"
  152. "movq $0x833, %%rcx \n\t" // Thermal Monitor
  153. "wrmsr \n\t"
  154. "movq $0x834, %%rcx \n\t" // Performance Counter
  155. "wrmsr \n\t"
  156. "movq $0x835, %%rcx \n\t" // LINT0
  157. "wrmsr \n\t"
  158. "movq $0x836, %%rcx \n\t" // LINT1
  159. "wrmsr \n\t"
  160. "movq $0x837, %%rcx \n\t" // Error
  161. "wrmsr \n\t"
  162. :
  163. : "a"(0x10000), "d"(0x00)
  164. : "memory");
  165. kdebug("All LVT Masked");
  166. // 获取TPR寄存器的值
  167. __asm__ __volatile__("movq $0x808, %%rcx \n\t"
  168. "rdmsr \n\t"
  169. : "=a"(eax), "=d"(edx)::"memory");
  170. kdebug("LVT_TPR=%#010x", eax);
  171. // 获取PPR寄存器的值
  172. __asm__ __volatile__("movq $0x80a, %%rcx \n\t"
  173. "rdmsr \n\t"
  174. : "=a"(eax), "=d"(edx)::"memory");
  175. kdebug("LVT_PPR=%#010x", eax);
  176. }
  177. /**
  178. * @brief 初始化apic控制器
  179. *
  180. */
  181. void apic_init()
  182. {
  183. apic_io_apic_init();
  184. }
  185. /**
  186. * @brief 中断服务程序
  187. *
  188. * @param rsp 中断栈指针
  189. * @param number 中断号
  190. */
  191. void do_IRQ(struct pt_regs *rsp, ul number)
  192. {
  193. }