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::kdebug; 15 use crate::mm::percpu::PerCpu; 16 use crate::process::ProcessManager; 17 use crate::smp::core::smp_get_processor_id; 18 use crate::smp::cpu::ProcessorId; 19 use crate::time::clocksource::HZ; 20 use alloc::string::ToString; 21 use alloc::sync::Arc; 22 pub use drop; 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 kdebug!("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 kdebug!("init_bsp_apic_timer done"); 117 } 118 119 fn init_ap_apic_timer() { 120 kdebug!("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 kdebug!("init_ap_apic_timer done"); 131 } 132 133 pub(super) struct LocalApicTimerIntrController; 134 135 impl LocalApicTimerIntrController { 136 pub(super) fn install(&self) { 137 kdebug!("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 kdebug!("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 kdebug!( 225 "install_periodic_mode: initial_count = {}, divisor = {}", 226 initial_count, 227 divisor 228 ); 229 self.mode = LocalApicTimerMode::Periodic; 230 self.set_divisor(divisor); 231 self.set_initial_cnt(initial_count); 232 self.setup_lvt( 233 APIC_TIMER_IRQ_NUM.data() as u8, 234 true, 235 LocalApicTimerMode::Periodic, 236 ); 237 } 238 239 fn setup_lvt(&mut self, vector: u8, mask: bool, mode: LocalApicTimerMode) { 240 let mode: u32 = mode as u32; 241 let data = (mode << 17) | (vector as u32) | (if mask { 1 << 16 } else { 0 }); 242 let lvt = LVT::new(LVTRegister::Timer, data).unwrap(); 243 244 CurrentApic.set_lvt(lvt); 245 } 246 247 fn set_divisor(&mut self, divisor: u32) { 248 self.divisor = divisor; 249 CurrentApic.set_timer_divisor(divisor); 250 } 251 252 fn set_initial_cnt(&mut self, initial_count: u64) { 253 self.initial_count = initial_count; 254 CurrentApic.set_timer_initial_count(initial_count); 255 } 256 257 fn start_current(&mut self) { 258 let mut lvt = CurrentApic.read_lvt(LVTRegister::Timer); 259 lvt.set_mask(false); 260 CurrentApic.set_lvt(lvt); 261 } 262 263 fn stop_current(&self) { 264 let mut lvt = CurrentApic.read_lvt(LVTRegister::Timer); 265 lvt.set_mask(true); 266 CurrentApic.set_lvt(lvt); 267 } 268 269 /// 检查是否支持TSC-Deadline 270 /// 271 /// 此函数调用cpuid,请避免多次调用此函数。 272 /// 如果支持TSC-Deadline模式,则除非TSC为常数,否则不会启用该模式。 273 #[allow(dead_code)] 274 pub fn is_deadline_mode_supported(&self) -> bool { 275 let res = cpuid!(1); 276 return (res.ecx & (1 << 24)) != 0; 277 } 278 279 pub(super) fn handle_irq(trap_frame: &TrapFrame) -> Result<IrqReturn, SystemError> { 280 // sched_update_jiffies(); 281 ProcessManager::update_process_times(trap_frame.is_from_user()); 282 return Ok(IrqReturn::Handled); 283 } 284 } 285 286 impl TryFrom<u8> for LocalApicTimerMode { 287 type Error = SystemError; 288 289 fn try_from(value: u8) -> Result<Self, Self::Error> { 290 match value { 291 0b00 => { 292 return Ok(LocalApicTimerMode::Oneshot); 293 } 294 0b01 => { 295 return Ok(LocalApicTimerMode::Periodic); 296 } 297 0b10 => { 298 return Ok(LocalApicTimerMode::Deadline); 299 } 300 _ => { 301 return Err(SystemError::EINVAL); 302 } 303 } 304 } 305 } 306 307 impl CurrentApic { 308 fn set_timer_divisor(&self, divisor: u32) { 309 if self.x2apic_enabled() { 310 unsafe { wrmsr(IA32_X2APIC_DIV_CONF, divisor.into()) }; 311 } else { 312 unsafe { 313 self.write_xapic_register(XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_CLKDIV, divisor) 314 }; 315 } 316 } 317 318 fn set_timer_initial_count(&self, initial_count: u64) { 319 if self.x2apic_enabled() { 320 unsafe { 321 wrmsr(IA32_X2APIC_INIT_COUNT, initial_count); 322 } 323 } else { 324 unsafe { 325 self.write_xapic_register( 326 XApicOffset::LOCAL_APIC_OFFSET_Local_APIC_INITIAL_COUNT_REG, 327 initial_count as u32, 328 ) 329 }; 330 } 331 } 332 } 333