feat(driver/acpi_pm): Implement ACPI PM Timer (#772)

* feat: Implement ACPI PM Timer
This commit is contained in:
Mingtao Huang 2024-04-28 13:25:12 +08:00 committed by GitHub
parent f75cb0f8ed
commit dd8e74ef0d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 464 additions and 28 deletions

View File

@ -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

View File

@ -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 {

View File

@ -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<u64, SystemError> {
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 {

View File

@ -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(());

View File

@ -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;
}

View File

@ -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<Arc<Acpipm>> = None;
pub fn clocksource_acpi_pm() -> Arc<Acpipm> {
return unsafe { CLOCKSOURCE_ACPI_PM.as_ref().unwrap().clone() };
}
#[derive(Debug)]
pub struct Acpipm(SpinLock<InnerAcpipm>);
#[derive(Debug)]
struct InnerAcpipm {
data: ClocksourceData,
self_reaf: Weak<Acpipm>,
}
impl Acpipm {
pub fn new() -> Arc<Self> {
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<dyn Clocksource> {
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::<Fadt>()
.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<dyn Clocksource>;
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);
}
};
}

View File

@ -1,2 +1,4 @@
#[cfg(target_arch = "riscv64")]
pub mod timer_riscv;
pub mod acpi_pm;

View File

@ -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!(

View File

@ -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),
}
}

View File

@ -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<i32, SystemError> {
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;
}

View File

@ -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<ClocksourceJiffies> {
pub fn jiffies_init() {
//注册jiffies
let jiffies = clocksource_default_clock() as Arc<dyn Clocksource>;
match jiffies.register() {
match jiffies.register(1, 0) {
Ok(_) => {
kinfo!("jiffies_init sccessfully");
}

View File

@ -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)]