xref: /DragonOS/kernel/src/arch/x86_64/driver/apic/apic_timer.rs (revision 70a4e5550a9fb49b537092287c3ddc36448c5b78)
1*70a4e555SLoGin use core::cell::RefCell;
2*70a4e555SLoGin 
3*70a4e555SLoGin use crate::arch::driver::tsc::TSCManager;
4*70a4e555SLoGin use crate::include::bindings::bindings::APIC_TIMER_IRQ_NUM;
5*70a4e555SLoGin 
6*70a4e555SLoGin use crate::kdebug;
7*70a4e555SLoGin use crate::mm::percpu::PerCpu;
8*70a4e555SLoGin use crate::sched::core::sched_update_jiffies;
9*70a4e555SLoGin use crate::smp::core::smp_get_processor_id;
10*70a4e555SLoGin use crate::syscall::SystemError;
11*70a4e555SLoGin pub use drop;
12*70a4e555SLoGin use x86::cpuid::cpuid;
13*70a4e555SLoGin use x86::msr::{wrmsr, IA32_X2APIC_DIV_CONF, IA32_X2APIC_INIT_COUNT};
14*70a4e555SLoGin 
15*70a4e555SLoGin use super::xapic::XApicOffset;
16*70a4e555SLoGin use super::{CurrentApic, LVTRegister, LocalAPIC, LVT};
17*70a4e555SLoGin 
18*70a4e555SLoGin static mut LOCAL_APIC_TIMERS: [RefCell<LocalApicTimer>; PerCpu::MAX_CPU_NUM] =
19*70a4e555SLoGin     [const { RefCell::new(LocalApicTimer::new()) }; PerCpu::MAX_CPU_NUM];
20*70a4e555SLoGin 
21*70a4e555SLoGin #[inline(always)]
22*70a4e555SLoGin pub(super) fn local_apic_timer_instance(cpu_id: u32) -> core::cell::Ref<'static, LocalApicTimer> {
23*70a4e555SLoGin     unsafe { LOCAL_APIC_TIMERS[cpu_id as usize].borrow() }
24*70a4e555SLoGin }
25*70a4e555SLoGin 
26*70a4e555SLoGin #[inline(always)]
27*70a4e555SLoGin pub(super) fn local_apic_timer_instance_mut(
28*70a4e555SLoGin     cpu_id: u32,
29*70a4e555SLoGin ) -> core::cell::RefMut<'static, LocalApicTimer> {
30*70a4e555SLoGin     unsafe { LOCAL_APIC_TIMERS[cpu_id as usize].borrow_mut() }
31*70a4e555SLoGin }
32*70a4e555SLoGin 
33*70a4e555SLoGin /// 初始化BSP的APIC定时器
34*70a4e555SLoGin ///
35*70a4e555SLoGin fn init_bsp_apic_timer() {
36*70a4e555SLoGin     kdebug!("init_bsp_apic_timer");
37*70a4e555SLoGin     assert!(smp_get_processor_id() == 0);
38*70a4e555SLoGin     let mut local_apic_timer = local_apic_timer_instance_mut(0);
39*70a4e555SLoGin     local_apic_timer.init(
40*70a4e555SLoGin         LocalApicTimerMode::Periodic,
41*70a4e555SLoGin         LocalApicTimer::periodic_default_initial_count(),
42*70a4e555SLoGin         LocalApicTimer::DIVISOR as u32,
43*70a4e555SLoGin     );
44*70a4e555SLoGin     kdebug!("init_bsp_apic_timer done");
45*70a4e555SLoGin }
46*70a4e555SLoGin 
47*70a4e555SLoGin fn init_ap_apic_timer() {
48*70a4e555SLoGin     kdebug!("init_ap_apic_timer");
49*70a4e555SLoGin     let cpu_id = smp_get_processor_id();
50*70a4e555SLoGin     assert!(cpu_id != 0);
51*70a4e555SLoGin 
52*70a4e555SLoGin     let mut local_apic_timer = local_apic_timer_instance_mut(cpu_id);
53*70a4e555SLoGin     local_apic_timer.init(
54*70a4e555SLoGin         LocalApicTimerMode::Periodic,
55*70a4e555SLoGin         LocalApicTimer::periodic_default_initial_count(),
56*70a4e555SLoGin         LocalApicTimer::DIVISOR as u32,
57*70a4e555SLoGin     );
58*70a4e555SLoGin     kdebug!("init_ap_apic_timer done");
59*70a4e555SLoGin }
60*70a4e555SLoGin 
61*70a4e555SLoGin pub(super) struct LocalApicTimerIntrController;
62*70a4e555SLoGin 
63*70a4e555SLoGin impl LocalApicTimerIntrController {
64*70a4e555SLoGin     pub(super) fn install(&self, _irq_num: u8) {
65*70a4e555SLoGin         kdebug!("LocalApicTimerIntrController::install");
66*70a4e555SLoGin         if smp_get_processor_id() == 0 {
67*70a4e555SLoGin             init_bsp_apic_timer();
68*70a4e555SLoGin         } else {
69*70a4e555SLoGin             init_ap_apic_timer();
70*70a4e555SLoGin         }
71*70a4e555SLoGin     }
72*70a4e555SLoGin 
73*70a4e555SLoGin     pub(super) fn uninstall(&self) {
74*70a4e555SLoGin         let cpu_id = smp_get_processor_id();
75*70a4e555SLoGin         let local_apic_timer = local_apic_timer_instance(cpu_id);
76*70a4e555SLoGin         local_apic_timer.stop_current();
77*70a4e555SLoGin     }
78*70a4e555SLoGin 
79*70a4e555SLoGin     pub(super) fn enable(&self) {
80*70a4e555SLoGin         kdebug!("LocalApicTimerIntrController::enable");
81*70a4e555SLoGin         let cpu_id = smp_get_processor_id();
82*70a4e555SLoGin         let mut local_apic_timer = local_apic_timer_instance_mut(cpu_id);
83*70a4e555SLoGin         local_apic_timer.start_current();
84*70a4e555SLoGin     }
85*70a4e555SLoGin 
86*70a4e555SLoGin     pub(super) fn disable(&self) {
87*70a4e555SLoGin         let cpu_id = smp_get_processor_id();
88*70a4e555SLoGin         let local_apic_timer = local_apic_timer_instance_mut(cpu_id);
89*70a4e555SLoGin         local_apic_timer.stop_current();
90*70a4e555SLoGin     }
91*70a4e555SLoGin }
92*70a4e555SLoGin 
93*70a4e555SLoGin #[derive(Debug, Copy, Clone)]
94*70a4e555SLoGin pub struct LocalApicTimer {
95*70a4e555SLoGin     mode: LocalApicTimerMode,
96*70a4e555SLoGin     /// IntialCount
97*70a4e555SLoGin     initial_count: u64,
98*70a4e555SLoGin     divisor: u32,
99*70a4e555SLoGin     /// 是否已经触发(oneshot模式)
100*70a4e555SLoGin     triggered: bool,
101*70a4e555SLoGin }
102*70a4e555SLoGin 
103*70a4e555SLoGin #[derive(Debug, Copy, Clone)]
104*70a4e555SLoGin #[repr(u32)]
105*70a4e555SLoGin pub enum LocalApicTimerMode {
106*70a4e555SLoGin     Oneshot = 0,
107*70a4e555SLoGin     Periodic = 1,
108*70a4e555SLoGin     Deadline = 2,
109*70a4e555SLoGin }
110*70a4e555SLoGin 
111*70a4e555SLoGin impl LocalApicTimer {
112*70a4e555SLoGin     /// 定时器中断的间隔
113*70a4e555SLoGin     pub const INTERVAL_MS: u64 = 5;
114*70a4e555SLoGin     pub const DIVISOR: u64 = 3;
115*70a4e555SLoGin 
116*70a4e555SLoGin     /// IoApicManager 初值为0或false
117*70a4e555SLoGin     pub const fn new() -> Self {
118*70a4e555SLoGin         LocalApicTimer {
119*70a4e555SLoGin             mode: LocalApicTimerMode::Periodic,
120*70a4e555SLoGin             initial_count: 0,
121*70a4e555SLoGin             divisor: 0,
122*70a4e555SLoGin             triggered: false,
123*70a4e555SLoGin         }
124*70a4e555SLoGin     }
125*70a4e555SLoGin 
126*70a4e555SLoGin     /// 周期模式下的默认初始值
127*70a4e555SLoGin     pub fn periodic_default_initial_count() -> u64 {
128*70a4e555SLoGin         let cpu_khz = TSCManager::cpu_khz();
129*70a4e555SLoGin 
130*70a4e555SLoGin         // 疑惑:这里使用khz吗?
131*70a4e555SLoGin         // 我觉得应该是hz,但是由于旧的代码是测量出initcnt的,而不是计算的
132*70a4e555SLoGin         // 然后我发现使用hz会导致计算出来的initcnt太大,导致系统卡顿,而khz的却能跑
133*70a4e555SLoGin         let count = cpu_khz * Self::INTERVAL_MS / (1000 * Self::DIVISOR);
134*70a4e555SLoGin         return count;
135*70a4e555SLoGin     }
136*70a4e555SLoGin 
137*70a4e555SLoGin     /// Init this manager.
138*70a4e555SLoGin     ///
139*70a4e555SLoGin     /// At this time, it does nothing.
140*70a4e555SLoGin     fn init(&mut self, mode: LocalApicTimerMode, initial_count: u64, divisor: u32) {
141*70a4e555SLoGin         self.stop_current();
142*70a4e555SLoGin         self.triggered = false;
143*70a4e555SLoGin         match mode {
144*70a4e555SLoGin             LocalApicTimerMode::Periodic => self.install_periodic_mode(initial_count, divisor),
145*70a4e555SLoGin             LocalApicTimerMode::Oneshot => todo!(),
146*70a4e555SLoGin             LocalApicTimerMode::Deadline => todo!(),
147*70a4e555SLoGin         }
148*70a4e555SLoGin     }
149*70a4e555SLoGin 
150*70a4e555SLoGin     fn install_periodic_mode(&mut self, initial_count: u64, divisor: u32) {
151*70a4e555SLoGin         kdebug!(
152*70a4e555SLoGin             "install_periodic_mode: initial_count = {}, divisor = {}",
153*70a4e555SLoGin             initial_count,
154*70a4e555SLoGin             divisor
155*70a4e555SLoGin         );
156*70a4e555SLoGin         self.mode = LocalApicTimerMode::Periodic;
157*70a4e555SLoGin         self.set_divisor(divisor);
158*70a4e555SLoGin         self.set_initial_cnt(initial_count);
159*70a4e555SLoGin         self.setup_lvt(APIC_TIMER_IRQ_NUM as u8, true, LocalApicTimerMode::Periodic);
160*70a4e555SLoGin     }
161*70a4e555SLoGin 
162*70a4e555SLoGin     fn setup_lvt(&mut self, vector: u8, mask: bool, mode: LocalApicTimerMode) {
163*70a4e555SLoGin         let mode: u32 = mode as u32;
164*70a4e555SLoGin         let data = (mode << 17) | (vector as u32) | (if mask { 1 << 16 } else { 0 });
165*70a4e555SLoGin         let lvt = LVT::new(LVTRegister::Timer, data).unwrap();
166*70a4e555SLoGin 
167*70a4e555SLoGin         CurrentApic.set_lvt(lvt);
168*70a4e555SLoGin     }
169*70a4e555SLoGin 
170*70a4e555SLoGin     fn set_divisor(&mut self, divisor: u32) {
171*70a4e555SLoGin         self.divisor = divisor;
172*70a4e555SLoGin         CurrentApic.set_timer_divisor(divisor as u32);
173*70a4e555SLoGin     }
174*70a4e555SLoGin 
175*70a4e555SLoGin     fn set_initial_cnt(&mut self, initial_count: u64) {
176*70a4e555SLoGin         self.initial_count = initial_count;
177*70a4e555SLoGin         CurrentApic.set_timer_initial_count(initial_count);
178*70a4e555SLoGin     }
179*70a4e555SLoGin 
180*70a4e555SLoGin     fn start_current(&mut self) {
181*70a4e555SLoGin         let mut lvt = CurrentApic.read_lvt(LVTRegister::Timer);
182*70a4e555SLoGin         lvt.set_mask(false);
183*70a4e555SLoGin         CurrentApic.set_lvt(lvt);
184*70a4e555SLoGin     }
185*70a4e555SLoGin 
186*70a4e555SLoGin     fn stop_current(&self) {
187*70a4e555SLoGin         let mut lvt = CurrentApic.read_lvt(LVTRegister::Timer);
188*70a4e555SLoGin         lvt.set_mask(true);
189*70a4e555SLoGin         CurrentApic.set_lvt(lvt);
190*70a4e555SLoGin     }
191*70a4e555SLoGin 
192*70a4e555SLoGin     /// 检查是否支持TSC-Deadline
193*70a4e555SLoGin     ///
194*70a4e555SLoGin     /// 此函数调用cpuid,请避免多次调用此函数。
195*70a4e555SLoGin     /// 如果支持TSC-Deadline模式,则除非TSC为常数,否则不会启用该模式。
196*70a4e555SLoGin     #[allow(dead_code)]
197*70a4e555SLoGin     pub fn is_deadline_mode_supported(&self) -> bool {
198*70a4e555SLoGin         let res = cpuid!(1);
199*70a4e555SLoGin         return (res.ecx & (1 << 24)) != 0;
200*70a4e555SLoGin     }
201*70a4e555SLoGin 
202*70a4e555SLoGin     pub(super) fn handle_irq() -> Result<(), SystemError> {
203*70a4e555SLoGin         sched_update_jiffies();
204*70a4e555SLoGin         return Ok(());
205*70a4e555SLoGin     }
206*70a4e555SLoGin }
207*70a4e555SLoGin 
208*70a4e555SLoGin impl TryFrom<u8> for LocalApicTimerMode {
209*70a4e555SLoGin     type Error = SystemError;
210*70a4e555SLoGin 
211*70a4e555SLoGin     fn try_from(value: u8) -> Result<Self, Self::Error> {
212*70a4e555SLoGin         match value {
213*70a4e555SLoGin             0b00 => {
214*70a4e555SLoGin                 return Ok(LocalApicTimerMode::Oneshot);
215*70a4e555SLoGin             }
216*70a4e555SLoGin             0b01 => {
217*70a4e555SLoGin                 return Ok(LocalApicTimerMode::Periodic);
218*70a4e555SLoGin             }
219*70a4e555SLoGin             0b10 => {
220*70a4e555SLoGin                 return Ok(LocalApicTimerMode::Deadline);
221*70a4e555SLoGin             }
222*70a4e555SLoGin             _ => {
223*70a4e555SLoGin                 return Err(SystemError::EINVAL);
224*70a4e555SLoGin             }
225*70a4e555SLoGin         }
226*70a4e555SLoGin     }
227*70a4e555SLoGin }
228*70a4e555SLoGin 
229*70a4e555SLoGin impl CurrentApic {
230*70a4e555SLoGin     fn set_timer_divisor(&self, divisor: u32) {
231*70a4e555SLoGin         if self.x2apic_enabled() {
232*70a4e555SLoGin             unsafe { wrmsr(IA32_X2APIC_DIV_CONF, divisor.into()) };
233*70a4e555SLoGin         } else {
234*70a4e555SLoGin             unsafe {
235*70a4e555SLoGin                 self.write_xapic_register(
236*70a4e555SLoGin                     XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_CLKDIV,
237*70a4e555SLoGin                     divisor.into(),
238*70a4e555SLoGin                 )
239*70a4e555SLoGin             };
240*70a4e555SLoGin         }
241*70a4e555SLoGin     }
242*70a4e555SLoGin 
243*70a4e555SLoGin     fn set_timer_initial_count(&self, initial_count: u64) {
244*70a4e555SLoGin         if self.x2apic_enabled() {
245*70a4e555SLoGin             unsafe {
246*70a4e555SLoGin                 wrmsr(IA32_X2APIC_INIT_COUNT.into(), initial_count);
247*70a4e555SLoGin             }
248*70a4e555SLoGin         } else {
249*70a4e555SLoGin             unsafe {
250*70a4e555SLoGin                 self.write_xapic_register(
251*70a4e555SLoGin                     XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_INITIAL_COUNT_REG,
252*70a4e555SLoGin                     initial_count as u32,
253*70a4e555SLoGin                 )
254*70a4e555SLoGin             };
255*70a4e555SLoGin         }
256*70a4e555SLoGin     }
257*70a4e555SLoGin }
258