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