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