xref: /DragonOS/kernel/src/arch/x86_64/driver/apic/apic_timer.rs (revision e28411791f090c421fe4b6fa5956fb1bd362a8d9)
170a4e555SLoGin use core::cell::RefCell;
270a4e555SLoGin 
370a4e555SLoGin use crate::arch::driver::tsc::TSCManager;
4*e2841179SLoGin use crate::arch::interrupt::TrapFrame;
5*e2841179SLoGin use crate::driver::base::device::DeviceId;
6*e2841179SLoGin use crate::exception::irqdata::{IrqHandlerData, IrqLineStatus};
7*e2841179SLoGin use crate::exception::irqdesc::{
8*e2841179SLoGin     irq_desc_manager, IrqDesc, IrqFlowHandler, IrqHandleFlags, IrqHandler, IrqReturn,
9*e2841179SLoGin };
10*e2841179SLoGin use crate::exception::manage::irq_manager;
11*e2841179SLoGin use crate::exception::IrqNumber;
1270a4e555SLoGin 
1370a4e555SLoGin use crate::kdebug;
1470a4e555SLoGin use crate::mm::percpu::PerCpu;
1570a4e555SLoGin use crate::sched::core::sched_update_jiffies;
1670a4e555SLoGin use crate::smp::core::smp_get_processor_id;
17*e2841179SLoGin use crate::smp::cpu::ProcessorId;
18be8cdf4bSLoGin use crate::time::clocksource::HZ;
19*e2841179SLoGin use alloc::string::ToString;
20*e2841179SLoGin use alloc::sync::Arc;
2170a4e555SLoGin pub use drop;
2291e9d4abSLoGin use system_error::SystemError;
2370a4e555SLoGin use x86::cpuid::cpuid;
2470a4e555SLoGin use x86::msr::{wrmsr, IA32_X2APIC_DIV_CONF, IA32_X2APIC_INIT_COUNT};
2570a4e555SLoGin 
26*e2841179SLoGin use super::lapic_vector::local_apic_chip;
2770a4e555SLoGin use super::xapic::XApicOffset;
2870a4e555SLoGin use super::{CurrentApic, LVTRegister, LocalAPIC, LVT};
2970a4e555SLoGin 
30*e2841179SLoGin pub const APIC_TIMER_IRQ_NUM: IrqNumber = IrqNumber::new(151);
3170a4e555SLoGin 
32*e2841179SLoGin static mut LOCAL_APIC_TIMERS: [RefCell<LocalApicTimer>; PerCpu::MAX_CPU_NUM as usize] =
33*e2841179SLoGin     [const { RefCell::new(LocalApicTimer::new()) }; PerCpu::MAX_CPU_NUM as usize];
34*e2841179SLoGin 
35*e2841179SLoGin #[allow(dead_code)]
3670a4e555SLoGin #[inline(always)]
37*e2841179SLoGin pub(super) fn local_apic_timer_instance(
38*e2841179SLoGin     cpu_id: ProcessorId,
39*e2841179SLoGin ) -> core::cell::Ref<'static, LocalApicTimer> {
40*e2841179SLoGin     unsafe { LOCAL_APIC_TIMERS[cpu_id.data() as usize].borrow() }
4170a4e555SLoGin }
4270a4e555SLoGin 
4370a4e555SLoGin #[inline(always)]
4470a4e555SLoGin pub(super) fn local_apic_timer_instance_mut(
45*e2841179SLoGin     cpu_id: ProcessorId,
4670a4e555SLoGin ) -> core::cell::RefMut<'static, LocalApicTimer> {
47*e2841179SLoGin     unsafe { LOCAL_APIC_TIMERS[cpu_id.data() as usize].borrow_mut() }
48*e2841179SLoGin }
49*e2841179SLoGin 
50*e2841179SLoGin #[derive(Debug)]
51*e2841179SLoGin struct LocalApicTimerHandler;
52*e2841179SLoGin 
53*e2841179SLoGin impl IrqHandler for LocalApicTimerHandler {
54*e2841179SLoGin     fn handle(
55*e2841179SLoGin         &self,
56*e2841179SLoGin         _irq: IrqNumber,
57*e2841179SLoGin         _static_data: Option<&dyn IrqHandlerData>,
58*e2841179SLoGin         _dynamic_data: Option<Arc<dyn IrqHandlerData>>,
59*e2841179SLoGin     ) -> Result<IrqReturn, SystemError> {
60*e2841179SLoGin         // empty (只是为了让编译通过,不会被调用到。真正的处理函数在LocalApicTimerIrqFlowHandler中)
61*e2841179SLoGin         Ok(IrqReturn::NotHandled)
62*e2841179SLoGin     }
63*e2841179SLoGin }
64*e2841179SLoGin 
65*e2841179SLoGin #[derive(Debug)]
66*e2841179SLoGin struct LocalApicTimerIrqFlowHandler;
67*e2841179SLoGin 
68*e2841179SLoGin impl IrqFlowHandler for LocalApicTimerIrqFlowHandler {
69*e2841179SLoGin     fn handle(&self, _irq_desc: &Arc<IrqDesc>, _trap_frame: &mut TrapFrame) {
70*e2841179SLoGin         LocalApicTimer::handle_irq().ok();
71*e2841179SLoGin         CurrentApic.send_eoi();
72*e2841179SLoGin     }
73*e2841179SLoGin }
74*e2841179SLoGin 
75*e2841179SLoGin pub fn apic_timer_init() {
76*e2841179SLoGin     irq_manager()
77*e2841179SLoGin         .request_irq(
78*e2841179SLoGin             APIC_TIMER_IRQ_NUM,
79*e2841179SLoGin             "LocalApic".to_string(),
80*e2841179SLoGin             &LocalApicTimerHandler,
81*e2841179SLoGin             IrqHandleFlags::IRQF_SHARED | IrqHandleFlags::IRQF_PERCPU,
82*e2841179SLoGin             Some(DeviceId::new(Some("lapic timer"), None).unwrap()),
83*e2841179SLoGin         )
84*e2841179SLoGin         .expect("Apic timer init failed");
85*e2841179SLoGin 
86*e2841179SLoGin     LocalApicTimerIntrController.install();
87*e2841179SLoGin     LocalApicTimerIntrController.enable();
88*e2841179SLoGin }
89*e2841179SLoGin 
90*e2841179SLoGin /// 初始化本地APIC定时器的中断描述符
91*e2841179SLoGin #[inline(never)]
92*e2841179SLoGin pub(super) fn local_apic_timer_irq_desc_init() {
93*e2841179SLoGin     let desc = irq_desc_manager().lookup(APIC_TIMER_IRQ_NUM).unwrap();
94*e2841179SLoGin     let irq_data: Arc<crate::exception::irqdata::IrqData> = desc.irq_data();
95*e2841179SLoGin     let mut chip_info_guard = irq_data.chip_info_write_irqsave();
96*e2841179SLoGin     chip_info_guard.set_chip(Some(local_apic_chip().clone()));
97*e2841179SLoGin 
98*e2841179SLoGin     desc.modify_status(IrqLineStatus::IRQ_LEVEL, IrqLineStatus::empty());
99*e2841179SLoGin     drop(chip_info_guard);
100*e2841179SLoGin     desc.set_handler(&LocalApicTimerIrqFlowHandler);
10170a4e555SLoGin }
10270a4e555SLoGin 
10370a4e555SLoGin /// 初始化BSP的APIC定时器
10470a4e555SLoGin ///
10570a4e555SLoGin fn init_bsp_apic_timer() {
10670a4e555SLoGin     kdebug!("init_bsp_apic_timer");
107*e2841179SLoGin     assert!(smp_get_processor_id().data() == 0);
108*e2841179SLoGin     let mut local_apic_timer = local_apic_timer_instance_mut(ProcessorId::new(0));
10970a4e555SLoGin     local_apic_timer.init(
11070a4e555SLoGin         LocalApicTimerMode::Periodic,
11170a4e555SLoGin         LocalApicTimer::periodic_default_initial_count(),
11270a4e555SLoGin         LocalApicTimer::DIVISOR as u32,
11370a4e555SLoGin     );
11470a4e555SLoGin     kdebug!("init_bsp_apic_timer done");
11570a4e555SLoGin }
11670a4e555SLoGin 
11770a4e555SLoGin fn init_ap_apic_timer() {
11870a4e555SLoGin     kdebug!("init_ap_apic_timer");
11970a4e555SLoGin     let cpu_id = smp_get_processor_id();
120*e2841179SLoGin     assert!(cpu_id.data() != 0);
12170a4e555SLoGin 
12270a4e555SLoGin     let mut local_apic_timer = local_apic_timer_instance_mut(cpu_id);
12370a4e555SLoGin     local_apic_timer.init(
12470a4e555SLoGin         LocalApicTimerMode::Periodic,
12570a4e555SLoGin         LocalApicTimer::periodic_default_initial_count(),
12670a4e555SLoGin         LocalApicTimer::DIVISOR as u32,
12770a4e555SLoGin     );
12870a4e555SLoGin     kdebug!("init_ap_apic_timer done");
12970a4e555SLoGin }
13070a4e555SLoGin 
13170a4e555SLoGin pub(super) struct LocalApicTimerIntrController;
13270a4e555SLoGin 
13370a4e555SLoGin impl LocalApicTimerIntrController {
134*e2841179SLoGin     pub(super) fn install(&self) {
13570a4e555SLoGin         kdebug!("LocalApicTimerIntrController::install");
136*e2841179SLoGin         if smp_get_processor_id().data() == 0 {
13770a4e555SLoGin             init_bsp_apic_timer();
13870a4e555SLoGin         } else {
13970a4e555SLoGin             init_ap_apic_timer();
14070a4e555SLoGin         }
14170a4e555SLoGin     }
14270a4e555SLoGin 
143*e2841179SLoGin     #[allow(dead_code)]
14470a4e555SLoGin     pub(super) fn uninstall(&self) {
14570a4e555SLoGin         let cpu_id = smp_get_processor_id();
14670a4e555SLoGin         let local_apic_timer = local_apic_timer_instance(cpu_id);
14770a4e555SLoGin         local_apic_timer.stop_current();
14870a4e555SLoGin     }
14970a4e555SLoGin 
15070a4e555SLoGin     pub(super) fn enable(&self) {
15170a4e555SLoGin         kdebug!("LocalApicTimerIntrController::enable");
15270a4e555SLoGin         let cpu_id = smp_get_processor_id();
15370a4e555SLoGin         let mut local_apic_timer = local_apic_timer_instance_mut(cpu_id);
15470a4e555SLoGin         local_apic_timer.start_current();
15570a4e555SLoGin     }
15670a4e555SLoGin 
15770a4e555SLoGin     pub(super) fn disable(&self) {
15870a4e555SLoGin         let cpu_id = smp_get_processor_id();
15970a4e555SLoGin         let local_apic_timer = local_apic_timer_instance_mut(cpu_id);
16070a4e555SLoGin         local_apic_timer.stop_current();
16170a4e555SLoGin     }
16270a4e555SLoGin }
16370a4e555SLoGin 
16470a4e555SLoGin #[derive(Debug, Copy, Clone)]
16570a4e555SLoGin pub struct LocalApicTimer {
16670a4e555SLoGin     mode: LocalApicTimerMode,
16770a4e555SLoGin     /// IntialCount
16870a4e555SLoGin     initial_count: u64,
16970a4e555SLoGin     divisor: u32,
17070a4e555SLoGin     /// 是否已经触发(oneshot模式)
17170a4e555SLoGin     triggered: bool,
17270a4e555SLoGin }
17370a4e555SLoGin 
17470a4e555SLoGin #[derive(Debug, Copy, Clone)]
17570a4e555SLoGin #[repr(u32)]
17670a4e555SLoGin pub enum LocalApicTimerMode {
17770a4e555SLoGin     Oneshot = 0,
17870a4e555SLoGin     Periodic = 1,
17970a4e555SLoGin     Deadline = 2,
18070a4e555SLoGin }
18170a4e555SLoGin 
18270a4e555SLoGin impl LocalApicTimer {
18370a4e555SLoGin     /// 定时器中断的间隔
184be8cdf4bSLoGin     pub const INTERVAL_MS: u64 = 1000 / HZ as u64;
1850d6cf65aSLoGin     pub const DIVISOR: u64 = 4;
18670a4e555SLoGin 
18770a4e555SLoGin     /// IoApicManager 初值为0或false
18870a4e555SLoGin     pub const fn new() -> Self {
18970a4e555SLoGin         LocalApicTimer {
19070a4e555SLoGin             mode: LocalApicTimerMode::Periodic,
19170a4e555SLoGin             initial_count: 0,
19270a4e555SLoGin             divisor: 0,
19370a4e555SLoGin             triggered: false,
19470a4e555SLoGin         }
19570a4e555SLoGin     }
19670a4e555SLoGin 
19770a4e555SLoGin     /// 周期模式下的默认初始值
19870a4e555SLoGin     pub fn periodic_default_initial_count() -> u64 {
19970a4e555SLoGin         let cpu_khz = TSCManager::cpu_khz();
20070a4e555SLoGin 
20170a4e555SLoGin         // 疑惑:这里使用khz吗?
20270a4e555SLoGin         // 我觉得应该是hz,但是由于旧的代码是测量出initcnt的,而不是计算的
20370a4e555SLoGin         // 然后我发现使用hz会导致计算出来的initcnt太大,导致系统卡顿,而khz的却能跑
2040d6cf65aSLoGin         let count = cpu_khz * Self::INTERVAL_MS / (Self::DIVISOR);
20570a4e555SLoGin         return count;
20670a4e555SLoGin     }
20770a4e555SLoGin 
20870a4e555SLoGin     /// Init this manager.
20970a4e555SLoGin     ///
21070a4e555SLoGin     /// At this time, it does nothing.
21170a4e555SLoGin     fn init(&mut self, mode: LocalApicTimerMode, initial_count: u64, divisor: u32) {
21270a4e555SLoGin         self.stop_current();
21370a4e555SLoGin         self.triggered = false;
21470a4e555SLoGin         match mode {
21570a4e555SLoGin             LocalApicTimerMode::Periodic => self.install_periodic_mode(initial_count, divisor),
21670a4e555SLoGin             LocalApicTimerMode::Oneshot => todo!(),
21770a4e555SLoGin             LocalApicTimerMode::Deadline => todo!(),
21870a4e555SLoGin         }
21970a4e555SLoGin     }
22070a4e555SLoGin 
22170a4e555SLoGin     fn install_periodic_mode(&mut self, initial_count: u64, divisor: u32) {
22270a4e555SLoGin         kdebug!(
22370a4e555SLoGin             "install_periodic_mode: initial_count = {}, divisor = {}",
22470a4e555SLoGin             initial_count,
22570a4e555SLoGin             divisor
22670a4e555SLoGin         );
22770a4e555SLoGin         self.mode = LocalApicTimerMode::Periodic;
22870a4e555SLoGin         self.set_divisor(divisor);
22970a4e555SLoGin         self.set_initial_cnt(initial_count);
230*e2841179SLoGin         self.setup_lvt(
231*e2841179SLoGin             APIC_TIMER_IRQ_NUM.data() as u8,
232*e2841179SLoGin             true,
233*e2841179SLoGin             LocalApicTimerMode::Periodic,
234*e2841179SLoGin         );
23570a4e555SLoGin     }
23670a4e555SLoGin 
23770a4e555SLoGin     fn setup_lvt(&mut self, vector: u8, mask: bool, mode: LocalApicTimerMode) {
23870a4e555SLoGin         let mode: u32 = mode as u32;
23970a4e555SLoGin         let data = (mode << 17) | (vector as u32) | (if mask { 1 << 16 } else { 0 });
24070a4e555SLoGin         let lvt = LVT::new(LVTRegister::Timer, data).unwrap();
24170a4e555SLoGin 
24270a4e555SLoGin         CurrentApic.set_lvt(lvt);
24370a4e555SLoGin     }
24470a4e555SLoGin 
24570a4e555SLoGin     fn set_divisor(&mut self, divisor: u32) {
24670a4e555SLoGin         self.divisor = divisor;
24770a4e555SLoGin         CurrentApic.set_timer_divisor(divisor as u32);
24870a4e555SLoGin     }
24970a4e555SLoGin 
25070a4e555SLoGin     fn set_initial_cnt(&mut self, initial_count: u64) {
25170a4e555SLoGin         self.initial_count = initial_count;
25270a4e555SLoGin         CurrentApic.set_timer_initial_count(initial_count);
25370a4e555SLoGin     }
25470a4e555SLoGin 
25570a4e555SLoGin     fn start_current(&mut self) {
25670a4e555SLoGin         let mut lvt = CurrentApic.read_lvt(LVTRegister::Timer);
25770a4e555SLoGin         lvt.set_mask(false);
25870a4e555SLoGin         CurrentApic.set_lvt(lvt);
25970a4e555SLoGin     }
26070a4e555SLoGin 
26170a4e555SLoGin     fn stop_current(&self) {
26270a4e555SLoGin         let mut lvt = CurrentApic.read_lvt(LVTRegister::Timer);
26370a4e555SLoGin         lvt.set_mask(true);
26470a4e555SLoGin         CurrentApic.set_lvt(lvt);
26570a4e555SLoGin     }
26670a4e555SLoGin 
26770a4e555SLoGin     /// 检查是否支持TSC-Deadline
26870a4e555SLoGin     ///
26970a4e555SLoGin     /// 此函数调用cpuid,请避免多次调用此函数。
27070a4e555SLoGin     /// 如果支持TSC-Deadline模式,则除非TSC为常数,否则不会启用该模式。
27170a4e555SLoGin     #[allow(dead_code)]
27270a4e555SLoGin     pub fn is_deadline_mode_supported(&self) -> bool {
27370a4e555SLoGin         let res = cpuid!(1);
27470a4e555SLoGin         return (res.ecx & (1 << 24)) != 0;
27570a4e555SLoGin     }
27670a4e555SLoGin 
277*e2841179SLoGin     pub(super) fn handle_irq() -> Result<IrqReturn, SystemError> {
27870a4e555SLoGin         sched_update_jiffies();
279*e2841179SLoGin         return Ok(IrqReturn::Handled);
28070a4e555SLoGin     }
28170a4e555SLoGin }
28270a4e555SLoGin 
28370a4e555SLoGin impl TryFrom<u8> for LocalApicTimerMode {
28470a4e555SLoGin     type Error = SystemError;
28570a4e555SLoGin 
28670a4e555SLoGin     fn try_from(value: u8) -> Result<Self, Self::Error> {
28770a4e555SLoGin         match value {
28870a4e555SLoGin             0b00 => {
28970a4e555SLoGin                 return Ok(LocalApicTimerMode::Oneshot);
29070a4e555SLoGin             }
29170a4e555SLoGin             0b01 => {
29270a4e555SLoGin                 return Ok(LocalApicTimerMode::Periodic);
29370a4e555SLoGin             }
29470a4e555SLoGin             0b10 => {
29570a4e555SLoGin                 return Ok(LocalApicTimerMode::Deadline);
29670a4e555SLoGin             }
29770a4e555SLoGin             _ => {
29870a4e555SLoGin                 return Err(SystemError::EINVAL);
29970a4e555SLoGin             }
30070a4e555SLoGin         }
30170a4e555SLoGin     }
30270a4e555SLoGin }
30370a4e555SLoGin 
30470a4e555SLoGin impl CurrentApic {
30570a4e555SLoGin     fn set_timer_divisor(&self, divisor: u32) {
30670a4e555SLoGin         if self.x2apic_enabled() {
30770a4e555SLoGin             unsafe { wrmsr(IA32_X2APIC_DIV_CONF, divisor.into()) };
30870a4e555SLoGin         } else {
30970a4e555SLoGin             unsafe {
31070a4e555SLoGin                 self.write_xapic_register(
31170a4e555SLoGin                     XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_CLKDIV,
31270a4e555SLoGin                     divisor.into(),
31370a4e555SLoGin                 )
31470a4e555SLoGin             };
31570a4e555SLoGin         }
31670a4e555SLoGin     }
31770a4e555SLoGin 
31870a4e555SLoGin     fn set_timer_initial_count(&self, initial_count: u64) {
31970a4e555SLoGin         if self.x2apic_enabled() {
32070a4e555SLoGin             unsafe {
32170a4e555SLoGin                 wrmsr(IA32_X2APIC_INIT_COUNT.into(), initial_count);
32270a4e555SLoGin             }
32370a4e555SLoGin         } else {
32470a4e555SLoGin             unsafe {
32570a4e555SLoGin                 self.write_xapic_register(
32670a4e555SLoGin                     XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_INITIAL_COUNT_REG,
32770a4e555SLoGin                     initial_count as u32,
32870a4e555SLoGin                 )
32970a4e555SLoGin             };
33070a4e555SLoGin         }
33170a4e555SLoGin     }
33270a4e555SLoGin }
333