diff --git a/kernel/src/arch/x86_64/acpi.rs b/kernel/src/arch/x86_64/acpi.rs index 842f1b58..d29b3bcd 100644 --- a/kernel/src/arch/x86_64/acpi.rs +++ b/kernel/src/arch/x86_64/acpi.rs @@ -1,8 +1,6 @@ -use system_error::SystemError; - -use crate::{driver::acpi::acpi_manager, kinfo, mm::percpu::PerCpu, smp::cpu::ProcessorId}; - use super::smp::SMP_BOOT_DATA; +use crate::{driver::acpi::acpi_manager, kinfo, mm::percpu::PerCpu, smp::cpu::ProcessorId}; +use system_error::SystemError; pub(super) fn early_acpi_boot_init() -> Result<(), SystemError> { // 在这里解析madt,初始化smp boot data diff --git a/kernel/src/arch/x86_64/driver/hpet.rs b/kernel/src/arch/x86_64/driver/hpet.rs index a4e2d120..f19f50fa 100644 --- a/kernel/src/arch/x86_64/driver/hpet.rs +++ b/kernel/src/arch/x86_64/driver/hpet.rs @@ -44,6 +44,14 @@ pub fn hpet_instance() -> &'static Hpet { unsafe { HPET_INSTANCE.as_ref().unwrap() } } +#[inline(always)] +pub fn is_hpet_enabled() -> bool { + if unsafe { HPET_INSTANCE.as_ref().is_some() } { + return unsafe { HPET_INSTANCE.as_ref().unwrap().enabled() }; + } + return false; +} + pub struct Hpet { info: HpetInfo, _mmio_guard: MMIOSpaceGuard, @@ -254,10 +262,8 @@ impl Hpet { } pub fn hpet_init() -> Result<(), SystemError> { - let hpet_info = HpetInfo::new(acpi_manager().tables().unwrap()).map_err(|e| { - kerror!("Failed to get HPET info: {:?}", e); - SystemError::ENODEV - })?; + let hpet_info = + HpetInfo::new(acpi_manager().tables().unwrap()).map_err(|_| SystemError::ENODEV)?; let hpet_instance = Hpet::new(hpet_info)?; unsafe { diff --git a/kernel/src/arch/x86_64/driver/tsc.rs b/kernel/src/arch/x86_64/driver/tsc.rs index 358c6e85..f1aab65d 100644 --- a/kernel/src/arch/x86_64/driver/tsc.rs +++ b/kernel/src/arch/x86_64/driver/tsc.rs @@ -1,9 +1,9 @@ use crate::{ arch::{io::PortIOArch, CurrentIrqArch, CurrentPortIOArch, CurrentTimeArch}, - driver::acpi::pmtmr::{ACPI_PM_OVERRUN, PMTMR_TICKS_PER_SEC}, + driver::acpi::pmtmr::{acpi_pm_read_early, ACPI_PM_OVERRUN, PMTMR_TICKS_PER_SEC}, exception::InterruptArch, kdebug, kerror, kinfo, kwarn, - time::TimeArch, + time::{TimeArch, PIT_TICK_RATE}, }; use core::{ cmp::{max, min}, @@ -11,10 +11,7 @@ use core::{ }; use system_error::SystemError; -use super::hpet::hpet_instance; - -/// The clock frequency of the i8253/i8254 PIT -const PIT_TICK_RATE: u64 = 1193182; +use super::hpet::{hpet_instance, is_hpet_enabled}; #[derive(Debug)] pub struct TSCManager; @@ -104,7 +101,7 @@ impl TSCManager { /// /// 使用pit、hpet、ptimer来测量CPU总线的频率 fn calibrate_cpu_by_pit_hpet_ptimer() -> Result { - let hpet = hpet_instance().enabled(); + let hpet = is_hpet_enabled(); kdebug!( "Calibrating TSC with {}", if hpet { "HPET" } else { "PMTIMER" } @@ -321,7 +318,7 @@ impl TSCManager { if hpet_enabled { ref_ret = hpet_instance().main_counter_value(); } else { - todo!("read pmtimer") + ref_ret = acpi_pm_read_early() as u64; } let t2 = CurrentTimeArch::get_cycles() as u64; if (t2 - t1) < thresh { diff --git a/kernel/src/arch/x86_64/init/mod.rs b/kernel/src/arch/x86_64/init/mod.rs index fb6250a5..6f392d3a 100644 --- a/kernel/src/arch/x86_64/init/mod.rs +++ b/kernel/src/arch/x86_64/init/mod.rs @@ -5,6 +5,7 @@ use x86::dtables::DescriptorTablePointer; use crate::{ arch::{interrupt::trap::arch_trap_init, process::table::TSSManager}, + driver::clocksource::acpi_pm::init_acpi_pm_clocksource, init::init::start_kernel, kdebug, mm::{MemoryManagementArch, PhysAddr}, @@ -93,8 +94,12 @@ pub fn setup_arch() -> Result<(), SystemError> { /// 架构相关的初始化(在IDLE的最后一个阶段) #[inline(never)] pub fn setup_arch_post() -> Result<(), SystemError> { - hpet_init().expect("hpet init failed"); - hpet_instance().hpet_enable().expect("hpet enable failed"); + let ret = hpet_init(); + if ret.is_ok() { + hpet_instance().hpet_enable().expect("hpet enable failed"); + } else { + init_acpi_pm_clocksource().expect("acpi_pm_timer inits failed"); + } TSCManager::init().expect("tsc init failed"); return Ok(()); diff --git a/kernel/src/driver/acpi/pmtmr.rs b/kernel/src/driver/acpi/pmtmr.rs index 92f14840..390f50da 100644 --- a/kernel/src/driver/acpi/pmtmr.rs +++ b/kernel/src/driver/acpi/pmtmr.rs @@ -1,4 +1,30 @@ +use crate::driver::clocksource::acpi_pm::{acpi_pm_read_verified, PMTMR_IO_PORT}; +use core::sync::atomic::Ordering; + pub const ACPI_PM_OVERRUN: u64 = 1 << 24; /// Number of PMTMR ticks expected during calibration run pub const PMTMR_TICKS_PER_SEC: u64 = 3579545; + +/// 用于掩码ACPI_PM_READ_ERALY返回值的前24位 +pub const ACPI_PM_MASK: u64 = 0xffffff; + +#[inline(always)] +#[cfg(target_arch = "x86_64")] +pub fn acpi_pm_read_early() -> u32 { + let port = unsafe { PMTMR_IO_PORT.load(Ordering::SeqCst) }; + + // 如果端口为零直接返回 + if port == 0 { + return 0; + } + + // 对读取的pmtmr值进行验证并进行掩码处理 + return acpi_pm_read_verified() & ACPI_PM_MASK as u32; +} + +#[inline(always)] +#[cfg(not(target_arch = "x86_64"))] +pub fn acpi_pm_read_early() -> u32 { + return 0; +} diff --git a/kernel/src/driver/clocksource/acpi_pm.rs b/kernel/src/driver/clocksource/acpi_pm.rs new file mode 100644 index 00000000..9167d234 --- /dev/null +++ b/kernel/src/driver/clocksource/acpi_pm.rs @@ -0,0 +1,296 @@ +use crate::{ + alloc::string::ToString, + arch::{io::PortIOArch, CurrentPortIOArch}, + driver::acpi::{ + acpi_manager, + pmtmr::{ACPI_PM_MASK, PMTMR_TICKS_PER_SEC}, + }, + libs::spinlock::SpinLock, + time::{ + clocksource::{Clocksource, ClocksourceData, ClocksourceFlags, ClocksourceMask, CycleNum}, + PIT_TICK_RATE, + }, +}; +use acpi::fadt::Fadt; +use alloc::sync::{Arc, Weak}; +use core::intrinsics::unlikely; +use core::sync::atomic::{AtomicU32, Ordering}; +use system_error::SystemError; + +// 参考:https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/clocksource/acpi_pm.c + +/// acpi_pmtmr所在的I/O端口 +pub static mut PMTMR_IO_PORT: AtomicU32 = AtomicU32::new(0); + +/// # 读取acpi_pmtmr当前值,并对齐进行掩码操作 +#[inline(always)] +fn read_pmtmr() -> u32 { + return unsafe { CurrentPortIOArch::in32(PMTMR_IO_PORT.load(Ordering::SeqCst) as u16) } + & ACPI_PM_MASK as u32; +} + +//参考: https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/clocksource/acpi_pm.c#41 +/// # 读取acpi_pmtmr的值,并进行多次读取以保证获取正确的值 +/// +/// ## 返回值 +/// - u32: 读取到的acpi_pmtmr值 +pub fn acpi_pm_read_verified() -> u32 { + let mut v2: u32; + + // 因为某些损坏芯片组(如ICH4、PIIX4和PIIX4E)可能导致APCI PM时钟源未锁存 + // 因此需要多次读取以保证获取正确的值 + loop { + let v1 = read_pmtmr(); + v2 = read_pmtmr(); + let v3 = read_pmtmr(); + + if !(unlikely((v2 > v3 || v1 < v3) && v1 > v2 || v1 < v3 && v2 > v3)) { + break; + } + } + + return v2; +} + +/// # 作为时钟源的读取函数 +/// +/// ## 返回值 +/// - u64: acpi_pmtmr的当前值 +fn acpi_pm_read() -> u64 { + return read_pmtmr() as u64; +} + +pub static mut CLOCKSOURCE_ACPI_PM: Option> = None; + +pub fn clocksource_acpi_pm() -> Arc { + return unsafe { CLOCKSOURCE_ACPI_PM.as_ref().unwrap().clone() }; +} + +#[derive(Debug)] +pub struct Acpipm(SpinLock); + +#[derive(Debug)] +struct InnerAcpipm { + data: ClocksourceData, + self_reaf: Weak, +} + +impl Acpipm { + pub fn new() -> Arc { + let data = ClocksourceData { + name: "acpi_pm".to_string(), + rating: 200, + mask: ClocksourceMask::new(ACPI_PM_MASK), + mult: 0, + shift: 0, + max_idle_ns: Default::default(), + flags: ClocksourceFlags::CLOCK_SOURCE_IS_CONTINUOUS, + watchdog_last: CycleNum::new(0), + uncertainty_margin: 0, + maxadj: 0, + }; + let acpi_pm = Arc::new(Acpipm(SpinLock::new(InnerAcpipm { + data, + self_reaf: Default::default(), + }))); + acpi_pm.0.lock().self_reaf = Arc::downgrade(&acpi_pm); + + return acpi_pm; + } +} + +impl Clocksource for Acpipm { + fn read(&self) -> CycleNum { + return CycleNum::new(acpi_pm_read()); + } + + fn clocksource_data(&self) -> ClocksourceData { + let inner = self.0.lock_irqsave(); + return inner.data.clone(); + } + + fn clocksource(&self) -> Arc { + return self.0.lock_irqsave().self_reaf.upgrade().unwrap(); + } + + fn update_clocksource_data(&self, data: ClocksourceData) -> Result<(), SystemError> { + let d = &mut self.0.lock_irqsave().data; + d.set_flags(data.flags); + d.set_mask(data.mask); + d.set_max_idle_ns(data.max_idle_ns); + d.set_mult(data.mult); + d.set_name(data.name); + d.set_rating(data.rating); + d.set_shift(data.shift); + d.watchdog_last = data.watchdog_last; + return Ok(()); + } +} + +// 参考:https://code.dragonos.org.cn/xref/linux-6.6.21/arch/x86/include/asm/mach_timer.h?fi=mach_prepare_counter +#[allow(dead_code)] +pub const CALIBRATE_TIME_MSEC: u64 = 30; +pub const CALIBRATE_LATCH: u64 = (PIT_TICK_RATE * CALIBRATE_TIME_MSEC + 1000 / 2) / 1000; + +#[inline(always)] +#[allow(dead_code)] +pub fn mach_prepare_counter() { + unsafe { + // 将Gate位设置为高电平,从而禁用扬声器 + CurrentPortIOArch::out8(0x61, (CurrentPortIOArch::in8(0x61) & !0x02) | 0x01); + + // 针对计数器/定时器控制器的通道2进行配置,设置为模式0,二进制计数 + CurrentPortIOArch::out8(0x43, 0xb0); + CurrentPortIOArch::out8(0x42, (CALIBRATE_LATCH & 0xff) as u8); + CurrentPortIOArch::out8(0x42, (CALIBRATE_LATCH >> 8) as u8); + } +} + +#[allow(dead_code)] +pub fn mach_countup(count: &mut u32) { + let mut tmp: u32 = 0; + loop { + tmp += 1; + if (unsafe { CurrentPortIOArch::in8(0x61) } & 0x20) != 0 { + break; + } + } + *count = tmp; +} + +#[allow(dead_code)] +const PMTMR_EXPECTED_RATE: u64 = + (CALIBRATE_LATCH * (PMTMR_TICKS_PER_SEC >> 10)) / (PIT_TICK_RATE >> 10); + +/// # 验证ACPI PM Timer的运行速率是否在预期范围内(在x86_64架构以外的情况下验证) +/// +/// ## 返回值 +/// - i32:如果为0则表示在预期范围内,否则不在 +#[cfg(not(target_arch = "x86_64"))] +fn verify_pmtmr_rate() -> bool { + let mut count: u32 = 0; + + mach_prepare_counter(); + let value1 = clocksource_acpi_pm().read().data(); + mach_countup(&mut count); + let value2 = clocksource_acpi_pm().read().data(); + let delta = (value2 - value1) & ACPI_PM_MASK; + + if (delta < (PMTMR_EXPECTED_RATE * 19) / 20) || (delta > (PMTMR_EXPECTED_RATE * 21) / 20) { + kinfo!( + "PM Timer running at invalid rate: {}", + 100 * delta / PMTMR_EXPECTED_RATE + ); + return false; + } + + return true; +} +#[cfg(target_arch = "x86_64")] +fn verify_pmtmr_rate() -> bool { + return true; +} + +const ACPI_PM_MONOTONIC_CHECKS: u32 = 10; +const ACPI_PM_READ_CHECKS: u32 = 10000; + +/// # 解析fadt +fn find_acpi_pm_clock() -> Result<(), SystemError> { + let fadt = acpi_manager() + .tables() + .unwrap() + .find_table::() + .expect("failed to find FADT table"); + let pm_timer_block = fadt.pm_timer_block().map_err(|_| SystemError::ENODEV)?; + let pm_timer_block = pm_timer_block.ok_or(SystemError::ENODEV)?; + let pmtmr_addr = pm_timer_block.address; + unsafe { + PMTMR_IO_PORT.store(pmtmr_addr as u32, Ordering::SeqCst); + } + kinfo!("apic_pmtmr I/O port: {}", unsafe { + PMTMR_IO_PORT.load(Ordering::SeqCst) + }); + + return Ok(()); +} + +/// # 初始化ACPI PM Timer作为系统时钟源 +// #[unified_init(INITCALL_FS)] +pub fn init_acpi_pm_clocksource() -> Result<(), SystemError> { + let acpi_pm = Acpipm::new(); + unsafe { + CLOCKSOURCE_ACPI_PM = Some(acpi_pm); + } + + // 解析fadt + find_acpi_pm_clock()?; + + // 检查pmtmr_io_port是否被设置 + if unsafe { PMTMR_IO_PORT.load(Ordering::SeqCst) } == 0 { + return Err(SystemError::ENODEV); + } + + // 验证ACPI PM Timer作为时钟源的稳定性和一致性 + for j in 0..ACPI_PM_MONOTONIC_CHECKS { + let mut cnt = 100 * j; + while cnt > 0 { + cnt -= 1; + } + + let value1 = clocksource_acpi_pm().read().data(); + let mut i = 0; + for _ in 0..ACPI_PM_READ_CHECKS { + let value2 = clocksource_acpi_pm().read().data(); + if value2 == value1 { + i += 1; + continue; + } + if value2 > value1 { + break; + } + if (value2 < value1) && (value2 < 0xfff) { + break; + } + kinfo!("PM Timer had inconsistens results: {} {}", value1, value2); + unsafe { + PMTMR_IO_PORT.store(0, Ordering::SeqCst); + } + return Err(SystemError::EINVAL); + } + if i == ACPI_PM_READ_CHECKS { + kinfo!("PM Timer failed consistency check: {}", value1); + unsafe { + PMTMR_IO_PORT.store(0, Ordering::SeqCst); + } + return Err(SystemError::EINVAL); + } + } + + // 检查ACPI PM Timer的频率是否正确 + if !verify_pmtmr_rate() { + unsafe { + PMTMR_IO_PORT.store(0, Ordering::SeqCst); + } + } + + // 检查TSC时钟源的监视器是否被禁用,如果被禁用则将时钟源的标志设置为CLOCK_SOURCE_MUST_VERIFY + // 没有实现clocksource_selecet_watchdog函数,所以这里设置为false + let tsc_clocksource_watchdog_disabled = false; + if tsc_clocksource_watchdog_disabled { + clocksource_acpi_pm().0.lock_irqsave().data.flags |= + ClocksourceFlags::CLOCK_SOURCE_MUST_VERIFY; + } + + // 注册ACPI PM Timer + let acpi_pmtmr = clocksource_acpi_pm() as Arc; + match acpi_pmtmr.register(100, PMTMR_TICKS_PER_SEC as u32) { + Ok(_) => { + kinfo!("ACPI PM Timer registered as clocksource sccessfully"); + return Ok(()); + } + Err(_) => { + kinfo!("ACPI PM Timer init registered failed"); + return Err(SystemError::ENOSYS); + } + }; +} diff --git a/kernel/src/driver/clocksource/mod.rs b/kernel/src/driver/clocksource/mod.rs index 393f405d..fda0b086 100644 --- a/kernel/src/driver/clocksource/mod.rs +++ b/kernel/src/driver/clocksource/mod.rs @@ -1,2 +1,4 @@ #[cfg(target_arch = "riscv64")] pub mod timer_riscv; + +pub mod acpi_pm; diff --git a/kernel/src/driver/pci/pci.rs b/kernel/src/driver/pci/pci.rs index 6e1cdef1..0f37e59e 100644 --- a/kernel/src/driver/pci/pci.rs +++ b/kernel/src/driver/pci/pci.rs @@ -1069,7 +1069,7 @@ pub fn pci_init() { ); } HeaderType::PciPciBridge if common_header.status & 0x10 != 0 => { - kinfo!("Found pci-to-pci bridge device with class code ={} subclass={} status={:#x} cap_pointer={:#x}", common_header.class_code, common_header.subclass, common_header.status, box_pci_device.as_standard_device().unwrap().capabilities_pointer); + kinfo!("Found pci-to-pci bridge device with class code ={} subclass={} status={:#x} cap_pointer={:#x}", common_header.class_code, common_header.subclass, common_header.status, box_pci_device.as_pci_to_pci_bridge_device().unwrap().capability_pointer); } HeaderType::PciPciBridge => { kinfo!( diff --git a/kernel/src/sched/mod.rs b/kernel/src/sched/mod.rs index 7d2fb3f8..c50782e8 100644 --- a/kernel/src/sched/mod.rs +++ b/kernel/src/sched/mod.rs @@ -433,7 +433,7 @@ impl CpuRunQueue { SchedPolicy::CFS => CompletelyFairScheduler::dequeue(self, pcb, flags), SchedPolicy::FIFO => todo!(), SchedPolicy::RT => todo!(), - SchedPolicy::IDLE => todo!(), + SchedPolicy::IDLE => IdleScheduler::dequeue(self, pcb, flags), } } diff --git a/kernel/src/time/clocksource.rs b/kernel/src/time/clocksource.rs index d67d81c9..df0ed81a 100644 --- a/kernel/src/time/clocksource.rs +++ b/kernel/src/time/clocksource.rs @@ -30,7 +30,7 @@ use crate::{ use super::{ jiffies::clocksource_default_clock, timer::{clock, Timer, TimerFunction}, - NSEC_PER_SEC, + NSEC_PER_SEC, NSEC_PER_USEC, }; lazy_static! { @@ -58,11 +58,16 @@ pub static mut FINISHED_BOOTING: AtomicBool = AtomicBool::new(false); /// Interval: 0.5sec Threshold: 0.0625s /// 系统节拍率 pub const HZ: u64 = 250; +// 参考:https://code.dragonos.org.cn/xref/linux-6.6.21/kernel/time/clocksource.c#101 /// watchdog检查间隔 pub const WATCHDOG_INTERVAL: u64 = HZ >> 1; +// 参考:https://code.dragonos.org.cn/xref/linux-6.6.21/kernel/time/clocksource.c#108 /// 最大能接受的误差大小 pub const WATCHDOG_THRESHOLD: u32 = NSEC_PER_SEC >> 4; +pub const MAX_SKEW_USEC: u64 = 125 * WATCHDOG_INTERVAL / HZ; +pub const WATCHDOG_MAX_SKEW: u32 = MAX_SKEW_USEC as u32 * NSEC_PER_USEC; + // 时钟周期数 #[derive(Debug, Clone, Copy)] pub struct CycleNum(u64); @@ -266,6 +271,7 @@ impl dyn Clocksource { let cs_data_guard = self.clocksource_data(); let mut max_cycles: u64; + // 这里我有问题,不知道要不要修改,暂时不修改它 max_cycles = (1 << (63 - (log2(cs_data_guard.mult) + 1))) as u64; max_cycles = max_cycles.min(cs_data_guard.mask.bits); let max_nsecs = clocksource_cyc2ns( @@ -276,17 +282,95 @@ impl dyn Clocksource { return max_nsecs - (max_nsecs >> 5); } + /// # 计算时钟源的mult和shift,以便将一个时钟源的频率转换为另一个时钟源的频率 + fn clocks_calc_mult_shift(&self, from: u32, to: u32, maxsec: u32) -> (u32, u32) { + let mut sftacc: u32 = 32; + let mut sft = 1; + + // 计算限制转换范围的shift + let mut mult = (maxsec as u64 * from as u64) >> 32; + while mult != 0 { + mult >>= 1; + sftacc -= 1; + } + + // 找到最佳的mult和shift + for i in (1..=32).rev() { + sft = i; + mult = (to as u64) << sft; + mult += from as u64 / 2; + mult /= from as u64; + if (mult >> sftacc) == 0 { + break; + } + } + + return (mult as u32, sft); + } + + /// # 计算时钟源可以进行的最大调整量 + fn clocksource_max_adjustment(&self) -> u32 { + let cs_data = self.clocksource_data(); + let ret = cs_data.mult as u64 * 11 / 100; + + return ret as u32; + } + + /// # 更新时钟源频率,初始化mult/shift 和 max_idle_ns + fn clocksource_update_freq_scale(&self, scale: u32, freq: u32) -> Result<(), SystemError> { + let mut cs_data = self.clocksource_data(); + + if freq != 0 { + let mut sec: u64 = cs_data.mask.bits(); + + sec /= freq as u64; + sec /= scale as u64; + if sec == 0 { + sec = 1; + } else if sec > 600 && cs_data.mask.bits() > u32::MAX as u64 { + sec = 600; + } + + let (mult, shift) = + self.clocks_calc_mult_shift(freq, NSEC_PER_SEC / scale, sec as u32 * scale); + cs_data.set_mult(mult); + cs_data.set_shift(shift); + } + + if scale != 0 && freq != 0 && cs_data.uncertainty_margin == 0 { + cs_data.set_uncertainty_margin(NSEC_PER_SEC / (scale * freq)); + if cs_data.uncertainty_margin < 2 * WATCHDOG_MAX_SKEW { + cs_data.set_uncertainty_margin(2 * WATCHDOG_MAX_SKEW); + } + } else if cs_data.uncertainty_margin == 0 { + cs_data.set_uncertainty_margin(WATCHDOG_THRESHOLD); + } + + // 确保时钟源没有太大的mult值造成溢出 + cs_data.set_maxadj(self.clocksource_max_adjustment()); + + let ns = self.clocksource_max_deferment(); + cs_data.set_max_idle_ns(ns as u32); + + self.update_clocksource_data(cs_data)?; + + return Ok(()); + } + /// # 注册时钟源 /// + /// ## 参数 + /// + /// - scale: 如果freq单位为0或hz,此值为1,如果为khz,此值为1000 + /// - freq: 时钟源的频率,jiffies注册时此值为0 + /// /// ## 返回值 /// /// * `Ok(0)` - 时钟源注册成功。 /// * `Err(SystemError)` - 时钟源注册失败。 - pub fn register(&self) -> Result { - let ns = self.clocksource_max_deferment(); - let mut cs_data = self.clocksource_data(); - cs_data.max_idle_ns = ns as u32; - self.update_clocksource_data(cs_data)?; + pub fn register(&self, scale: u32, freq: u32) -> Result<(), SystemError> { + self.clocksource_update_freq_scale(scale, freq)?; + // 将时钟源加入到时钟源队列中 self.clocksource_enqueue(); // 将时钟源加入到监视队列中 @@ -295,7 +379,7 @@ impl dyn Clocksource { // 选择一个最好的时钟源 clocksource_select(); kdebug!("clocksource_register successfully"); - return Ok(0); + return Ok(()); } /// # 将时钟源插入时钟源队列 @@ -569,10 +653,15 @@ pub struct ClocksourceData { pub max_idle_ns: u32, pub flags: ClocksourceFlags, pub watchdog_last: CycleNum, + // 用于描述时钟源的不确定性边界,时钟源读取的时间可能存在的不确定性和误差范围 + pub uncertainty_margin: u32, + // 最大的时间调整量 + pub maxadj: u32, } impl ClocksourceData { #[allow(dead_code)] + #[allow(clippy::too_many_arguments)] pub fn new( name: String, rating: i32, @@ -581,6 +670,8 @@ impl ClocksourceData { shift: u32, max_idle_ns: u32, flags: ClocksourceFlags, + uncertainty_margin: u32, + maxadj: u32, ) -> Self { let csd = ClocksourceData { name, @@ -591,6 +682,8 @@ impl ClocksourceData { max_idle_ns, flags, watchdog_last: CycleNum(0), + uncertainty_margin, + maxadj, }; return csd; } @@ -624,6 +717,12 @@ impl ClocksourceData { pub fn insert_flags(&mut self, flags: ClocksourceFlags) { self.flags.insert(flags) } + pub fn set_uncertainty_margin(&mut self, uncertainty_margin: u32) { + self.uncertainty_margin = uncertainty_margin; + } + pub fn set_maxadj(&mut self, maxadj: u32) { + self.maxadj = maxadj; + } } /// converts clocksource cycles to nanoseconds @@ -733,6 +832,8 @@ pub fn clocksource_watchdog() -> Result<(), SystemError> { if cs_dev_nsec.abs_diff(wd_dev_nsec) > WATCHDOG_THRESHOLD.into() { // kdebug!("set_unstable"); // 误差过大,标记为unstable + kinfo!("cs_dev_nsec = {}", cs_dev_nsec); + kinfo!("wd_dev_nsec = {}", wd_dev_nsec); cs.set_unstable((cs_dev_nsec - wd_dev_nsec).try_into().unwrap())?; continue; } diff --git a/kernel/src/time/jiffies.rs b/kernel/src/time/jiffies.rs index aa1f9dc1..e01451fa 100644 --- a/kernel/src/time/jiffies.rs +++ b/kernel/src/time/jiffies.rs @@ -75,6 +75,8 @@ impl ClocksourceJiffies { max_idle_ns: Default::default(), flags: ClocksourceFlags::new(0), watchdog_last: CycleNum::new(0), + uncertainty_margin: 0, + maxadj: 0, }; let jiffies = Arc::new(ClocksourceJiffies(SpinLock::new(InnerJiffies { data, @@ -92,7 +94,7 @@ pub fn clocksource_default_clock() -> Arc { pub fn jiffies_init() { //注册jiffies let jiffies = clocksource_default_clock() as Arc; - match jiffies.register() { + match jiffies.register(1, 0) { Ok(_) => { kinfo!("jiffies_init sccessfully"); } diff --git a/kernel/src/time/mod.rs b/kernel/src/time/mod.rs index ca9ae138..d42a6d4a 100644 --- a/kernel/src/time/mod.rs +++ b/kernel/src/time/mod.rs @@ -43,6 +43,9 @@ pub const NSEC_PER_SEC: u32 = 1000000000; #[allow(dead_code)] pub const FSEC_PER_SEC: u64 = 1000000000000000; +/// The clock frequency of the i8253/i8254 PIT +pub const PIT_TICK_RATE: u64 = 1193182; + /// 表示时间的结构体,符合POSIX标准。 #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] #[repr(C)]