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