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)]
local_apic_timer_instance( cpu_id: ProcessorId, ) -> core::cell::Ref<'static, LocalApicTimer>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)]
local_apic_timer_instance_mut( cpu_id: ProcessorId, ) -> core::cell::RefMut<'static, LocalApicTimer>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 {
handle( &self, _irq: IrqNumber, _static_data: Option<&dyn IrqHandlerData>, _dynamic_data: Option<Arc<dyn IrqHandlerData>>, ) -> Result<IrqReturn, SystemError>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 {
handle(&self, _irq_desc: &Arc<IrqDesc>, trap_frame: &mut TrapFrame)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
apic_timer_init()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)]
local_apic_timer_irq_desc_init()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 ///
init_bsp_apic_timer()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
init_ap_apic_timer()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 {
install(&self)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)]
uninstall(&self)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
enable(&self)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 #[allow(dead_code)]
disable(&self)160 pub(super) fn disable(&self) {
161 let cpu_id = smp_get_processor_id();
162 let local_apic_timer = local_apic_timer_instance_mut(cpu_id);
163 local_apic_timer.stop_current();
164 }
165 }
166
167 #[derive(Debug, Copy, Clone)]
168 pub struct LocalApicTimer {
169 mode: LocalApicTimerMode,
170 /// IntialCount
171 initial_count: u64,
172 divisor: u32,
173 /// 是否已经触发(oneshot模式)
174 triggered: bool,
175 }
176
177 #[derive(Debug, Copy, Clone)]
178 #[repr(u32)]
179 pub enum LocalApicTimerMode {
180 Oneshot = 0,
181 Periodic = 1,
182 Deadline = 2,
183 }
184
185 impl LocalApicTimer {
186 /// 定时器中断的间隔
187 pub const INTERVAL_MS: u64 = 1000 / HZ;
188 pub const DIVISOR: u64 = 4;
189
190 /// IoApicManager 初值为0或false
new() -> Self191 pub const fn new() -> Self {
192 LocalApicTimer {
193 mode: LocalApicTimerMode::Periodic,
194 initial_count: 0,
195 divisor: 0,
196 triggered: false,
197 }
198 }
199
200 /// 周期模式下的默认初始值
periodic_default_initial_count() -> u64201 pub fn periodic_default_initial_count() -> u64 {
202 let cpu_khz = TSCManager::cpu_khz();
203
204 // 疑惑:这里使用khz吗?
205 // 我觉得应该是hz,但是由于旧的代码是测量出initcnt的,而不是计算的
206 // 然后我发现使用hz会导致计算出来的initcnt太大,导致系统卡顿,而khz的却能跑
207 let count = cpu_khz * Self::INTERVAL_MS / (Self::DIVISOR);
208 return count;
209 }
210
211 /// Init this manager.
212 ///
213 /// At this time, it does nothing.
init(&mut self, mode: LocalApicTimerMode, initial_count: u64, divisor: u32)214 fn init(&mut self, mode: LocalApicTimerMode, initial_count: u64, divisor: u32) {
215 self.stop_current();
216 self.triggered = false;
217 match mode {
218 LocalApicTimerMode::Periodic => self.install_periodic_mode(initial_count, divisor),
219 LocalApicTimerMode::Oneshot => todo!(),
220 LocalApicTimerMode::Deadline => todo!(),
221 }
222 }
223
install_periodic_mode(&mut self, initial_count: u64, divisor: u32)224 fn install_periodic_mode(&mut self, initial_count: u64, divisor: u32) {
225 debug!(
226 "install_periodic_mode: initial_count = {}, divisor = {}",
227 initial_count, divisor
228 );
229 self.mode = LocalApicTimerMode::Periodic;
230 self.set_divisor(divisor);
231 self.setup_lvt(
232 APIC_TIMER_IRQ_NUM.data() as u8,
233 true,
234 LocalApicTimerMode::Periodic,
235 );
236 self.set_initial_cnt(initial_count);
237 }
238
setup_lvt(&mut self, vector: u8, mask: bool, mode: LocalApicTimerMode)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
set_divisor(&mut self, divisor: u32)247 fn set_divisor(&mut self, divisor: u32) {
248 self.divisor = divisor;
249 CurrentApic.set_timer_divisor(divisor);
250 }
251
set_initial_cnt(&mut self, initial_count: u64)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
start_current(&mut self)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
stop_current(&self)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)]
is_deadline_mode_supported(&self) -> bool274 pub fn is_deadline_mode_supported(&self) -> bool {
275 let res = cpuid!(1);
276 return (res.ecx & (1 << 24)) != 0;
277 }
278
handle_irq(trap_frame: &TrapFrame) -> Result<IrqReturn, SystemError>279 pub(super) fn handle_irq(trap_frame: &TrapFrame) -> Result<IrqReturn, SystemError> {
280 // sched_update_jiffies();
281 tick_handle_periodic(trap_frame);
282 return Ok(IrqReturn::Handled);
283 }
284 }
285
286 impl TryFrom<u8> for LocalApicTimerMode {
287 type Error = SystemError;
288
try_from(value: u8) -> Result<Self, Self::Error>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 {
set_timer_divisor(&self, divisor: u32)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
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, 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