1 use core::cell::RefCell; 2 use core::sync::atomic::{fence, Ordering}; 3 4 use crate::arch::driver::tsc::TSCManager; 5 use crate::arch::interrupt::TrapFrame; 6 use crate::driver::base::device::DeviceId; 7 use crate::exception::irqdata::{IrqHandlerData, IrqLineStatus}; 8 use crate::exception::irqdesc::{ 9 irq_desc_manager, IrqDesc, IrqFlowHandler, IrqHandleFlags, IrqHandler, IrqReturn, 10 }; 11 use crate::exception::manage::irq_manager; 12 use crate::exception::IrqNumber; 13 14 use crate::mm::percpu::PerCpu; 15 use crate::smp::core::smp_get_processor_id; 16 use crate::smp::cpu::ProcessorId; 17 use crate::time::clocksource::HZ; 18 use crate::time::tick_common::tick_handle_periodic; 19 use alloc::string::ToString; 20 use alloc::sync::Arc; 21 pub use drop; 22 use log::debug; 23 use system_error::SystemError; 24 use x86::cpuid::cpuid; 25 use x86::msr::{wrmsr, IA32_X2APIC_DIV_CONF, IA32_X2APIC_INIT_COUNT}; 26 27 use super::lapic_vector::local_apic_chip; 28 use super::xapic::XApicOffset; 29 use super::{CurrentApic, LVTRegister, LocalAPIC, LVT}; 30 31 pub const APIC_TIMER_IRQ_NUM: IrqNumber = IrqNumber::new(151); 32 33 static mut LOCAL_APIC_TIMERS: [RefCell<LocalApicTimer>; PerCpu::MAX_CPU_NUM as usize] = 34 [const { RefCell::new(LocalApicTimer::new()) }; PerCpu::MAX_CPU_NUM as usize]; 35 36 #[allow(dead_code)] 37 #[inline(always)] 38 pub(super) fn local_apic_timer_instance( 39 cpu_id: ProcessorId, 40 ) -> core::cell::Ref<'static, LocalApicTimer> { 41 unsafe { LOCAL_APIC_TIMERS[cpu_id.data() as usize].borrow() } 42 } 43 44 #[inline(always)] 45 pub(super) fn local_apic_timer_instance_mut( 46 cpu_id: ProcessorId, 47 ) -> core::cell::RefMut<'static, LocalApicTimer> { 48 unsafe { LOCAL_APIC_TIMERS[cpu_id.data() as usize].borrow_mut() } 49 } 50 51 #[derive(Debug)] 52 struct LocalApicTimerHandler; 53 54 impl IrqHandler for LocalApicTimerHandler { 55 fn handle( 56 &self, 57 _irq: IrqNumber, 58 _static_data: Option<&dyn IrqHandlerData>, 59 _dynamic_data: Option<Arc<dyn IrqHandlerData>>, 60 ) -> Result<IrqReturn, SystemError> { 61 // empty (只是为了让编译通过,不会被调用到。真正的处理函数在LocalApicTimerIrqFlowHandler中) 62 Ok(IrqReturn::NotHandled) 63 } 64 } 65 66 #[derive(Debug)] 67 struct LocalApicTimerIrqFlowHandler; 68 69 impl IrqFlowHandler for LocalApicTimerIrqFlowHandler { 70 fn handle(&self, _irq_desc: &Arc<IrqDesc>, trap_frame: &mut TrapFrame) { 71 LocalApicTimer::handle_irq(trap_frame).ok(); 72 CurrentApic.send_eoi(); 73 fence(Ordering::SeqCst) 74 } 75 } 76 77 pub fn apic_timer_init() { 78 irq_manager() 79 .request_irq( 80 APIC_TIMER_IRQ_NUM, 81 "LocalApic".to_string(), 82 &LocalApicTimerHandler, 83 IrqHandleFlags::IRQF_SHARED | IrqHandleFlags::IRQF_PERCPU, 84 Some(DeviceId::new(Some("lapic timer"), None).unwrap()), 85 ) 86 .expect("Apic timer init failed"); 87 88 LocalApicTimerIntrController.install(); 89 LocalApicTimerIntrController.enable(); 90 } 91 92 /// 初始化本地APIC定时器的中断描述符 93 #[inline(never)] 94 pub(super) fn local_apic_timer_irq_desc_init() { 95 let desc = irq_desc_manager().lookup(APIC_TIMER_IRQ_NUM).unwrap(); 96 let irq_data: Arc<crate::exception::irqdata::IrqData> = desc.irq_data(); 97 let mut chip_info_guard = irq_data.chip_info_write_irqsave(); 98 chip_info_guard.set_chip(Some(local_apic_chip().clone())); 99 100 desc.modify_status(IrqLineStatus::IRQ_LEVEL, IrqLineStatus::empty()); 101 drop(chip_info_guard); 102 desc.set_handler(&LocalApicTimerIrqFlowHandler); 103 } 104 105 /// 初始化BSP的APIC定时器 106 /// 107 fn init_bsp_apic_timer() { 108 debug!("init_bsp_apic_timer"); 109 assert!(smp_get_processor_id().data() == 0); 110 let mut local_apic_timer = local_apic_timer_instance_mut(ProcessorId::new(0)); 111 local_apic_timer.init( 112 LocalApicTimerMode::Periodic, 113 LocalApicTimer::periodic_default_initial_count(), 114 LocalApicTimer::DIVISOR as u32, 115 ); 116 debug!("init_bsp_apic_timer done"); 117 } 118 119 fn init_ap_apic_timer() { 120 debug!("init_ap_apic_timer"); 121 let cpu_id = smp_get_processor_id(); 122 assert!(cpu_id.data() != 0); 123 124 let mut local_apic_timer = local_apic_timer_instance_mut(cpu_id); 125 local_apic_timer.init( 126 LocalApicTimerMode::Periodic, 127 LocalApicTimer::periodic_default_initial_count(), 128 LocalApicTimer::DIVISOR as u32, 129 ); 130 debug!("init_ap_apic_timer done"); 131 } 132 133 pub(super) struct LocalApicTimerIntrController; 134 135 impl LocalApicTimerIntrController { 136 pub(super) fn install(&self) { 137 debug!("LocalApicTimerIntrController::install"); 138 if smp_get_processor_id().data() == 0 { 139 init_bsp_apic_timer(); 140 } else { 141 init_ap_apic_timer(); 142 } 143 } 144 145 #[allow(dead_code)] 146 pub(super) fn uninstall(&self) { 147 let cpu_id = smp_get_processor_id(); 148 let local_apic_timer = local_apic_timer_instance(cpu_id); 149 local_apic_timer.stop_current(); 150 } 151 152 pub(super) fn enable(&self) { 153 debug!("LocalApicTimerIntrController::enable"); 154 let cpu_id = smp_get_processor_id(); 155 let mut local_apic_timer = local_apic_timer_instance_mut(cpu_id); 156 local_apic_timer.start_current(); 157 } 158 159 pub(super) fn disable(&self) { 160 let cpu_id = smp_get_processor_id(); 161 let local_apic_timer = local_apic_timer_instance_mut(cpu_id); 162 local_apic_timer.stop_current(); 163 } 164 } 165 166 #[derive(Debug, Copy, Clone)] 167 pub struct LocalApicTimer { 168 mode: LocalApicTimerMode, 169 /// IntialCount 170 initial_count: u64, 171 divisor: u32, 172 /// 是否已经触发(oneshot模式) 173 triggered: bool, 174 } 175 176 #[derive(Debug, Copy, Clone)] 177 #[repr(u32)] 178 pub enum LocalApicTimerMode { 179 Oneshot = 0, 180 Periodic = 1, 181 Deadline = 2, 182 } 183 184 impl LocalApicTimer { 185 /// 定时器中断的间隔 186 pub const INTERVAL_MS: u64 = 1000 / HZ; 187 pub const DIVISOR: u64 = 4; 188 189 /// IoApicManager 初值为0或false 190 pub const fn new() -> Self { 191 LocalApicTimer { 192 mode: LocalApicTimerMode::Periodic, 193 initial_count: 0, 194 divisor: 0, 195 triggered: false, 196 } 197 } 198 199 /// 周期模式下的默认初始值 200 pub fn periodic_default_initial_count() -> u64 { 201 let cpu_khz = TSCManager::cpu_khz(); 202 203 // 疑惑:这里使用khz吗? 204 // 我觉得应该是hz,但是由于旧的代码是测量出initcnt的,而不是计算的 205 // 然后我发现使用hz会导致计算出来的initcnt太大,导致系统卡顿,而khz的却能跑 206 let count = cpu_khz * Self::INTERVAL_MS / (Self::DIVISOR); 207 return count; 208 } 209 210 /// Init this manager. 211 /// 212 /// At this time, it does nothing. 213 fn init(&mut self, mode: LocalApicTimerMode, initial_count: u64, divisor: u32) { 214 self.stop_current(); 215 self.triggered = false; 216 match mode { 217 LocalApicTimerMode::Periodic => self.install_periodic_mode(initial_count, divisor), 218 LocalApicTimerMode::Oneshot => todo!(), 219 LocalApicTimerMode::Deadline => todo!(), 220 } 221 } 222 223 fn install_periodic_mode(&mut self, initial_count: u64, divisor: u32) { 224 debug!( 225 "install_periodic_mode: initial_count = {}, divisor = {}", 226 initial_count, divisor 227 ); 228 self.mode = LocalApicTimerMode::Periodic; 229 self.set_divisor(divisor); 230 self.setup_lvt( 231 APIC_TIMER_IRQ_NUM.data() as u8, 232 true, 233 LocalApicTimerMode::Periodic, 234 ); 235 self.set_initial_cnt(initial_count); 236 } 237 238 fn setup_lvt(&mut self, vector: u8, mask: bool, mode: LocalApicTimerMode) { 239 let mode: u32 = mode as u32; 240 let data = (mode << 17) | (vector as u32) | (if mask { 1 << 16 } else { 0 }); 241 let lvt = LVT::new(LVTRegister::Timer, data).unwrap(); 242 243 CurrentApic.set_lvt(lvt); 244 } 245 246 fn set_divisor(&mut self, divisor: u32) { 247 self.divisor = divisor; 248 CurrentApic.set_timer_divisor(divisor); 249 } 250 251 fn set_initial_cnt(&mut self, initial_count: u64) { 252 self.initial_count = initial_count; 253 CurrentApic.set_timer_initial_count(initial_count); 254 } 255 256 fn start_current(&mut self) { 257 let mut lvt = CurrentApic.read_lvt(LVTRegister::Timer); 258 lvt.set_mask(false); 259 CurrentApic.set_lvt(lvt); 260 } 261 262 fn stop_current(&self) { 263 let mut lvt = CurrentApic.read_lvt(LVTRegister::Timer); 264 lvt.set_mask(true); 265 CurrentApic.set_lvt(lvt); 266 } 267 268 /// 检查是否支持TSC-Deadline 269 /// 270 /// 此函数调用cpuid,请避免多次调用此函数。 271 /// 如果支持TSC-Deadline模式,则除非TSC为常数,否则不会启用该模式。 272 #[allow(dead_code)] 273 pub fn is_deadline_mode_supported(&self) -> bool { 274 let res = cpuid!(1); 275 return (res.ecx & (1 << 24)) != 0; 276 } 277 278 pub(super) fn handle_irq(trap_frame: &TrapFrame) -> Result<IrqReturn, SystemError> { 279 // sched_update_jiffies(); 280 tick_handle_periodic(trap_frame); 281 return Ok(IrqReturn::Handled); 282 } 283 } 284 285 impl TryFrom<u8> for LocalApicTimerMode { 286 type Error = SystemError; 287 288 fn try_from(value: u8) -> Result<Self, Self::Error> { 289 match value { 290 0b00 => { 291 return Ok(LocalApicTimerMode::Oneshot); 292 } 293 0b01 => { 294 return Ok(LocalApicTimerMode::Periodic); 295 } 296 0b10 => { 297 return Ok(LocalApicTimerMode::Deadline); 298 } 299 _ => { 300 return Err(SystemError::EINVAL); 301 } 302 } 303 } 304 } 305 306 impl CurrentApic { 307 fn set_timer_divisor(&self, divisor: u32) { 308 if self.x2apic_enabled() { 309 unsafe { wrmsr(IA32_X2APIC_DIV_CONF, divisor.into()) }; 310 } else { 311 unsafe { 312 self.write_xapic_register(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_CLKDIV, divisor) 313 }; 314 } 315 } 316 317 fn set_timer_initial_count(&self, initial_count: u64) { 318 if self.x2apic_enabled() { 319 unsafe { 320 wrmsr(IA32_X2APIC_INIT_COUNT, initial_count); 321 } 322 } else { 323 unsafe { 324 self.write_xapic_register( 325 XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_INITIAL_COUNT_REG, 326 initial_count as u32, 327 ) 328 }; 329 } 330 } 331 } 332