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