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