1 use crate::{
2 alloc::string::ToString,
3 arch::{io::PortIOArch, CurrentPortIOArch},
4 driver::acpi::{
5 acpi_manager,
6 pmtmr::{ACPI_PM_MASK, PMTMR_TICKS_PER_SEC},
7 },
8 libs::spinlock::SpinLock,
9 time::{
10 clocksource::{Clocksource, ClocksourceData, ClocksourceFlags, ClocksourceMask, CycleNum},
11 PIT_TICK_RATE,
12 },
13 };
14 use acpi::fadt::Fadt;
15 use alloc::sync::{Arc, Weak};
16 use core::intrinsics::unlikely;
17 use core::sync::atomic::{AtomicU32, Ordering};
18 use log::info;
19 use system_error::SystemError;
20
21 // 参考:https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/clocksource/acpi_pm.c
22
23 /// acpi_pmtmr所在的I/O端口
24 pub static PMTMR_IO_PORT: AtomicU32 = AtomicU32::new(0);
25
26 /// # 读取acpi_pmtmr当前值,并对齐进行掩码操作
27 #[inline(always)]
read_pmtmr() -> u3228 fn read_pmtmr() -> u32 {
29 return unsafe { CurrentPortIOArch::in32(PMTMR_IO_PORT.load(Ordering::SeqCst) as u16) }
30 & ACPI_PM_MASK as u32;
31 }
32
33 //参考: https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/clocksource/acpi_pm.c#41
34 /// # 读取acpi_pmtmr的值,并进行多次读取以保证获取正确的值
35 ///
36 /// ## 返回值
37 /// - u32: 读取到的acpi_pmtmr值
38 #[allow(dead_code)]
acpi_pm_read_verified() -> u3239 pub fn acpi_pm_read_verified() -> u32 {
40 let mut v2: u32;
41
42 // 因为某些损坏芯片组(如ICH4、PIIX4和PIIX4E)可能导致APCI PM时钟源未锁存
43 // 因此需要多次读取以保证获取正确的值
44 loop {
45 let v1 = read_pmtmr();
46 v2 = read_pmtmr();
47 let v3 = read_pmtmr();
48
49 if !(unlikely((v2 > v3 || v1 < v3) && v1 > v2 || v1 < v3 && v2 > v3)) {
50 break;
51 }
52 }
53
54 return v2;
55 }
56
57 /// # 作为时钟源的读取函数
58 ///
59 /// ## 返回值
60 /// - u64: acpi_pmtmr的当前值
acpi_pm_read() -> u6461 fn acpi_pm_read() -> u64 {
62 return read_pmtmr() as u64;
63 }
64
65 pub static mut CLOCKSOURCE_ACPI_PM: Option<Arc<Acpipm>> = None;
66
clocksource_acpi_pm() -> Arc<Acpipm>67 pub fn clocksource_acpi_pm() -> Arc<Acpipm> {
68 return unsafe { CLOCKSOURCE_ACPI_PM.as_ref().unwrap().clone() };
69 }
70
71 #[derive(Debug)]
72 pub struct Acpipm(SpinLock<InnerAcpipm>);
73
74 #[derive(Debug)]
75 struct InnerAcpipm {
76 data: ClocksourceData,
77 self_reaf: Weak<Acpipm>,
78 }
79
80 impl Acpipm {
new() -> Arc<Self>81 pub fn new() -> Arc<Self> {
82 let data = ClocksourceData {
83 name: "acpi_pm".to_string(),
84 rating: 200,
85 mask: ClocksourceMask::new(ACPI_PM_MASK),
86 mult: 0,
87 shift: 0,
88 max_idle_ns: Default::default(),
89 flags: ClocksourceFlags::CLOCK_SOURCE_IS_CONTINUOUS,
90 watchdog_last: CycleNum::new(0),
91 cs_last: CycleNum::new(0),
92 uncertainty_margin: 0,
93 maxadj: 0,
94 cycle_last: CycleNum::new(0),
95 };
96 let acpi_pm = Arc::new(Acpipm(SpinLock::new(InnerAcpipm {
97 data,
98 self_reaf: Default::default(),
99 })));
100 acpi_pm.0.lock().self_reaf = Arc::downgrade(&acpi_pm);
101
102 return acpi_pm;
103 }
104 }
105
106 impl Clocksource for Acpipm {
read(&self) -> CycleNum107 fn read(&self) -> CycleNum {
108 return CycleNum::new(acpi_pm_read());
109 }
110
clocksource_data(&self) -> ClocksourceData111 fn clocksource_data(&self) -> ClocksourceData {
112 let inner = self.0.lock_irqsave();
113 return inner.data.clone();
114 }
115
clocksource(&self) -> Arc<dyn Clocksource>116 fn clocksource(&self) -> Arc<dyn Clocksource> {
117 return self.0.lock_irqsave().self_reaf.upgrade().unwrap();
118 }
119
update_clocksource_data(&self, data: ClocksourceData) -> Result<(), SystemError>120 fn update_clocksource_data(&self, data: ClocksourceData) -> Result<(), SystemError> {
121 let d = &mut self.0.lock_irqsave().data;
122 d.set_name(data.name);
123 d.set_rating(data.rating);
124 d.set_mask(data.mask);
125 d.set_mult(data.mult);
126 d.set_shift(data.shift);
127 d.set_max_idle_ns(data.max_idle_ns);
128 d.set_flags(data.flags);
129 d.watchdog_last = data.watchdog_last;
130 d.cs_last = data.cs_last;
131 d.set_uncertainty_margin(data.uncertainty_margin);
132 d.set_maxadj(data.maxadj);
133 d.cycle_last = data.cycle_last;
134 return Ok(());
135 }
136 }
137
138 // 参考:https://code.dragonos.org.cn/xref/linux-6.6.21/arch/x86/include/asm/mach_timer.h?fi=mach_prepare_counter
139 #[allow(dead_code)]
140 pub const CALIBRATE_TIME_MSEC: u64 = 30;
141 pub const CALIBRATE_LATCH: u64 = (PIT_TICK_RATE * CALIBRATE_TIME_MSEC + 1000 / 2) / 1000;
142
143 #[inline(always)]
144 #[allow(dead_code)]
mach_prepare_counter()145 pub fn mach_prepare_counter() {
146 unsafe {
147 // 将Gate位设置为高电平,从而禁用扬声器
148 CurrentPortIOArch::out8(0x61, (CurrentPortIOArch::in8(0x61) & !0x02) | 0x01);
149
150 // 针对计数器/定时器控制器的通道2进行配置,设置为模式0,二进制计数
151 CurrentPortIOArch::out8(0x43, 0xb0);
152 CurrentPortIOArch::out8(0x42, (CALIBRATE_LATCH & 0xff) as u8);
153 CurrentPortIOArch::out8(0x42, (CALIBRATE_LATCH >> 8) as u8);
154 }
155 }
156
157 #[allow(dead_code)]
mach_countup(count: &mut u32)158 pub fn mach_countup(count: &mut u32) {
159 let mut tmp: u32 = 0;
160 loop {
161 tmp += 1;
162 if (unsafe { CurrentPortIOArch::in8(0x61) } & 0x20) != 0 {
163 break;
164 }
165 }
166 *count = tmp;
167 }
168
169 #[allow(dead_code)]
170 const PMTMR_EXPECTED_RATE: u64 =
171 (CALIBRATE_LATCH * (PMTMR_TICKS_PER_SEC >> 10)) / (PIT_TICK_RATE >> 10);
172
173 /// # 验证ACPI PM Timer的运行速率是否在预期范围内(在x86_64架构以外的情况下验证)
174 ///
175 /// ## 返回值
176 /// - i32:如果为0则表示在预期范围内,否则不在
177 #[cfg(not(target_arch = "x86_64"))]
178 #[allow(dead_code)]
verify_pmtmr_rate() -> bool179 fn verify_pmtmr_rate() -> bool {
180 use log::info;
181
182 let mut count: u32 = 0;
183
184 mach_prepare_counter();
185 let value1 = clocksource_acpi_pm().read().data();
186 mach_countup(&mut count);
187 let value2 = clocksource_acpi_pm().read().data();
188 let delta = (value2 - value1) & ACPI_PM_MASK;
189
190 if (delta < (PMTMR_EXPECTED_RATE * 19) / 20) || (delta > (PMTMR_EXPECTED_RATE * 21) / 20) {
191 info!(
192 "PM Timer running at invalid rate: {}",
193 100 * delta / PMTMR_EXPECTED_RATE
194 );
195 return false;
196 }
197
198 return true;
199 }
200 #[cfg(target_arch = "x86_64")]
verify_pmtmr_rate() -> bool201 fn verify_pmtmr_rate() -> bool {
202 return true;
203 }
204
205 const ACPI_PM_MONOTONIC_CHECKS: u32 = 10;
206 const ACPI_PM_READ_CHECKS: u32 = 10000;
207
208 /// # 解析fadt
find_acpi_pm_clock() -> Result<(), SystemError>209 fn find_acpi_pm_clock() -> Result<(), SystemError> {
210 let fadt = acpi_manager()
211 .tables()
212 .unwrap()
213 .find_table::<Fadt>()
214 .expect("failed to find FADT table");
215 let pm_timer_block = fadt.pm_timer_block().map_err(|_| SystemError::ENODEV)?;
216 let pm_timer_block = pm_timer_block.ok_or(SystemError::ENODEV)?;
217 let pmtmr_addr = pm_timer_block.address;
218
219 PMTMR_IO_PORT.store(pmtmr_addr as u32, Ordering::SeqCst);
220
221 info!(
222 "apic_pmtmr I/O port: {}",
223 PMTMR_IO_PORT.load(Ordering::SeqCst)
224 );
225
226 return Ok(());
227 }
228
229 /// # 初始化ACPI PM Timer作为系统时钟源
230 // #[unified_init(INITCALL_FS)]
231 #[inline(never)]
232 #[allow(dead_code)]
init_acpi_pm_clocksource() -> Result<(), SystemError>233 pub fn init_acpi_pm_clocksource() -> Result<(), SystemError> {
234 let acpi_pm = Acpipm::new();
235
236 // 解析fadt
237 find_acpi_pm_clock()?;
238
239 // 检查pmtmr_io_port是否被设置
240 if PMTMR_IO_PORT.load(Ordering::SeqCst) == 0 {
241 return Err(SystemError::ENODEV);
242 }
243
244 unsafe {
245 CLOCKSOURCE_ACPI_PM = Some(acpi_pm);
246 }
247
248 // 验证ACPI PM Timer作为时钟源的稳定性和一致性
249 for j in 0..ACPI_PM_MONOTONIC_CHECKS {
250 let mut cnt = 100 * j;
251 while cnt > 0 {
252 cnt -= 1;
253 }
254
255 let value1 = clocksource_acpi_pm().read().data();
256 let mut i = 0;
257 for _ in 0..ACPI_PM_READ_CHECKS {
258 let value2 = clocksource_acpi_pm().read().data();
259 if value2 == value1 {
260 i += 1;
261 continue;
262 }
263 if value2 > value1 {
264 break;
265 }
266 if (value2 < value1) && (value2 < 0xfff) {
267 break;
268 }
269 info!("PM Timer had inconsistens results: {} {}", value1, value2);
270
271 PMTMR_IO_PORT.store(0, Ordering::SeqCst);
272
273 return Err(SystemError::EINVAL);
274 }
275 if i == ACPI_PM_READ_CHECKS {
276 info!("PM Timer failed consistency check: {}", value1);
277
278 PMTMR_IO_PORT.store(0, Ordering::SeqCst);
279
280 return Err(SystemError::EINVAL);
281 }
282 }
283
284 // 检查ACPI PM Timer的频率是否正确
285 if !verify_pmtmr_rate() {
286 PMTMR_IO_PORT.store(0, Ordering::SeqCst);
287 }
288
289 // 检查TSC时钟源的监视器是否被禁用,如果被禁用则将时钟源的标志设置为CLOCK_SOURCE_MUST_VERIFY
290 // 是因为jiffies精度小于acpi pm,所以不需要被jiffies监视
291 let tsc_clocksource_watchdog_disabled = false;
292 if tsc_clocksource_watchdog_disabled {
293 clocksource_acpi_pm().0.lock_irqsave().data.flags |=
294 ClocksourceFlags::CLOCK_SOURCE_MUST_VERIFY;
295 }
296
297 // 注册ACPI PM Timer
298 let acpi_pmtmr = clocksource_acpi_pm() as Arc<dyn Clocksource>;
299 match acpi_pmtmr.register(1, PMTMR_TICKS_PER_SEC as u32) {
300 Ok(_) => {
301 info!("ACPI PM Timer registered as clocksource sccessfully");
302 return Ok(());
303 }
304 Err(_) => {
305 info!("ACPI PM Timer init registered failed");
306 return Err(SystemError::ENOSYS);
307 }
308 };
309 }
310