apic_timer.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #include "apic_timer.h"
  2. #include <exception/irq.h>
  3. #include <process/process.h>
  4. #include <common/kprint.h>
  5. #include <sched/sched.h>
  6. // #pragma GCC push_options
  7. // #pragma GCC optimize("O0")
  8. uint64_t apic_timer_ticks_result = 0;
  9. void apic_timer_enable(uint64_t irq_num)
  10. {
  11. // 启动apic定时器
  12. io_mfence();
  13. uint64_t val = apic_timer_get_LVT();
  14. io_mfence();
  15. val &= (~APIC_LVT_INT_MASKED);
  16. io_mfence();
  17. apic_timer_write_LVT(val);
  18. io_mfence();
  19. }
  20. void apic_timer_disable(uint64_t irq_num)
  21. {
  22. apic_timer_stop();
  23. }
  24. /**
  25. * @brief 安装local apic定时器中断
  26. *
  27. * @param irq_num 中断向量号
  28. * @param arg 初始计数值
  29. * @return uint64_t
  30. */
  31. uint64_t apic_timer_install(ul irq_num, void *arg)
  32. {
  33. // 设置div16
  34. io_mfence();
  35. apic_timer_stop();
  36. io_mfence();
  37. apic_timer_set_div(APIC_TIMER_DIVISOR);
  38. io_mfence();
  39. // 设置初始计数
  40. apic_timer_set_init_cnt(*(uint64_t *)arg);
  41. io_mfence();
  42. // 填写LVT
  43. apic_timer_set_LVT(APIC_TIMER_IRQ_NUM, 1, APIC_LVT_Timer_Periodic);
  44. io_mfence();
  45. }
  46. void apic_timer_uninstall(ul irq_num)
  47. {
  48. apic_timer_write_LVT(APIC_LVT_INT_MASKED);
  49. io_mfence();
  50. }
  51. hardware_intr_controller apic_timer_intr_controller =
  52. {
  53. .enable = apic_timer_enable,
  54. .disable = apic_timer_disable,
  55. .install = apic_timer_install,
  56. .uninstall = apic_timer_uninstall,
  57. .ack = apic_local_apic_edge_ack,
  58. };
  59. /**
  60. * @brief local apic定时器的中断处理函数
  61. *
  62. * @param number 中断向量号
  63. * @param param 参数
  64. * @param regs 寄存器值
  65. */
  66. void apic_timer_handler(uint64_t number, uint64_t param, struct pt_regs *regs)
  67. {
  68. sched_update_jiffies();
  69. io_mfence();
  70. }
  71. /**
  72. * @brief 初始化local APIC定时器
  73. *
  74. */
  75. void apic_timer_init()
  76. {
  77. if (apic_timer_ticks_result == 0)
  78. {
  79. kBUG("APIC timer ticks in 5ms is equal to ZERO!");
  80. while (1)
  81. hlt();
  82. }
  83. kinfo("Initializing apic timer for cpu %d", proc_current_cpu_id);
  84. irq_register(APIC_TIMER_IRQ_NUM, &apic_timer_ticks_result, &apic_timer_handler, 0, &apic_timer_intr_controller, "apic timer");
  85. kinfo("Successfully initialized apic timer for cpu %d", proc_current_cpu_id);
  86. }